1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-02 05:29:32 +00:00

Merge pull request #472 from TomHarte/SDLJoystick

Connects SDL joystick input to joystick machines.
This commit is contained in:
Thomas Harte 2018-06-16 22:26:19 -04:00 committed by GitHub
commit 3da1d5700c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 5 deletions

View File

@ -188,11 +188,11 @@ class ConcreteJoystick: public Joystick {
default: did_set_input(input, value > 0.5f); break;
case Type::Horizontal:
did_set_input(Input(Type::Left, input.info.control.index), value <= 0.25f);
did_set_input(Input(Type::Right, input.info.control.index), value >= 0.25f);
did_set_input(Input(Type::Right, input.info.control.index), value >= 0.75f);
break;
case Type::Vertical:
did_set_input(Input(Type::Up, input.info.control.index), value <= 0.25f);
did_set_input(Input(Type::Down, input.info.control.index), value >= 0.25f);
did_set_input(Input(Type::Down, input.info.control.index), value >= 0.75f);
break;
}
}

View File

@ -584,7 +584,7 @@ class ConcreteMachine:
}
// Update analogue charge level.
analogue_charge_ = std::min(analogue_charge_ + 1.0f / 2820.0f, 1.0f);
analogue_charge_ = std::min(analogue_charge_ + 1.0f / 2820.0f, 1.1f);
return Cycles(1);
}

View File

@ -390,9 +390,9 @@ int main(int argc, char *argv[]) {
int window_width, window_height;
SDL_GetWindowSize(window, &window_width, &window_height);
// Establish user-friendly options by default.
Configurable::Device *configurable_device = machine->configurable_device();
Configurable::Device *const configurable_device = machine->configurable_device();
if(configurable_device) {
// Establish user-friendly options by default.
configurable_device->set_selections(configurable_device->get_user_friendly_selections());
// Consider transcoding any list selections that map to Boolean options.
@ -410,9 +410,58 @@ int main(int argc, char *argv[]) {
}
}
}
// Apply the user's actual selections to override the defaults.
configurable_device->set_selections(arguments.selections);
}
// If this is a joystick machine, check for and open attached joysticks.
/*!
Provides a wrapper for SDL_Joystick pointers that can keep track
of historic hat values.
*/
class SDLJoystick {
public:
SDLJoystick(SDL_Joystick *joystick) : joystick_(joystick) {
hat_values_.resize(SDL_JoystickNumHats(joystick));
}
~SDLJoystick() {
SDL_JoystickClose(joystick_);
}
/// @returns The underlying SDL_Joystick.
SDL_Joystick *get() {
return joystick_;
}
/// @returns A reference to the storage for the previous state of hat @c c.
Uint8 &last_hat_value(int c) {
return hat_values_[c];
}
/// @returns The logic OR of all stored hat states.
Uint8 hat_values() {
Uint8 value = 0;
for(const auto hat_value: hat_values_) {
value |= hat_value;
}
return value;
}
private:
SDL_Joystick *joystick_;
std::vector<Uint8> hat_values_;
};
std::vector<SDLJoystick> joysticks;
JoystickMachine::Machine *const joystick_machine = machine->joystick_machine();
if(joystick_machine) {
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
for(int c = 0; c < SDL_NumJoysticks(); ++c) {
joysticks.emplace_back(SDL_JoystickOpen(c));
}
}
// Run the main event loop until the OS tells us to quit.
bool should_quit = false;
Uint32 fullscreen_mode = 0;
@ -510,6 +559,54 @@ int main(int argc, char *argv[]) {
}
}
// Push new joystick state, if any.
JoystickMachine::Machine *const joystick_machine = machine->joystick_machine();
if(joystick_machine) {
std::vector<std::unique_ptr<Inputs::Joystick>> &machine_joysticks = joystick_machine->get_joysticks();
for(size_t c = 0; c < joysticks.size(); ++c) {
size_t target = c % machine_joysticks.size();
// Post the first two analogue axes presented by the controller as horizontal and vertical inputs,
// unless the user seems to be using a hat.
// SDL will return a value in the range [-32768, 32767], so map from that to [0, 1.0]
if(!joysticks[c].hat_values()) {
const float x_axis = static_cast<float>(SDL_JoystickGetAxis(joysticks[c].get(), 0) + 32768) / 65535.0f;
const float y_axis = static_cast<float>(SDL_JoystickGetAxis(joysticks[c].get(), 1) + 32768) / 65535.0f;
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Horizontal), x_axis);
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Vertical), y_axis);
}
// Forward hats as directions; hats always override analogue inputs.
const int number_of_hats = SDL_JoystickNumHats(joysticks[c].get());
for(int hat = 0; hat < number_of_hats; ++hat) {
const Uint8 hat_value = SDL_JoystickGetHat(joysticks[c].get(), hat);
const Uint8 changes = hat_value ^ joysticks[c].last_hat_value(hat);
joysticks[c].last_hat_value(hat) = hat_value;
if(changes & SDL_HAT_UP) {
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Up), !!(hat_value & SDL_HAT_UP));
}
if(changes & SDL_HAT_DOWN) {
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Down), !!(hat_value & SDL_HAT_DOWN));
}
if(changes & SDL_HAT_LEFT) {
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Left), !!(hat_value & SDL_HAT_LEFT));
}
if(changes & SDL_HAT_RIGHT) {
machine_joysticks[target]->set_input(Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Right), !!(hat_value & SDL_HAT_RIGHT));
}
}
// Forward all fire buttons, retaining their original indices.
const int number_of_buttons = SDL_JoystickNumButtons(joysticks[c].get());
for(int button = 0; button < number_of_buttons; ++button) {
machine_joysticks[target]->set_input(
Inputs::Joystick::Input(Inputs::Joystick::Input::Type::Fire, button),
SDL_JoystickGetButton(joysticks[c].get(), button) ? true : false);
}
}
}
// Display a new frame and wait for vsync.
updater.update();
machine->crt_machine()->get_crt()->draw_frame(static_cast<unsigned int>(window_width), static_cast<unsigned int>(window_height), false);
@ -517,6 +614,7 @@ int main(int argc, char *argv[]) {
}
// Clean up.
joysticks.clear();
SDL_DestroyWindow( window );
SDL_Quit();