1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-06-09 17:29:36 +00:00

Moves the joystick class towards accepting analogue inputs.

This commit is contained in:
Thomas Harte 2018-06-10 20:45:52 -04:00
parent a1c60152d4
commit 3ea2a4ccb8
7 changed files with 109 additions and 76 deletions

View File

@ -25,11 +25,11 @@ class MultiJoystick: public Inputs::Joystick {
}
}
std::vector<DigitalInput> get_inputs() override {
std::vector<DigitalInput> inputs;
std::vector<Input> get_inputs() override {
std::vector<Input> inputs;
for(const auto &joystick: joysticks_) {
std::vector<DigitalInput> joystick_inputs = joystick->get_inputs();
std::vector<Input> 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 {

View File

@ -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<DigitalInput> get_inputs() = 0;
virtual std::vector<Input> 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);
}
}
};

View File

@ -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<DigitalInput> get_inputs() override {
std::vector<Input> 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

View File

@ -34,28 +34,28 @@ namespace Vision {
class Joystick: public Inputs::Joystick {
public:
std::vector<DigitalInput> get_inputs() override {
std::vector<Input> 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;

View File

@ -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<DigitalInput> get_inputs() override {
std::vector<Input> 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);

View File

@ -252,19 +252,21 @@ struct SpeakerDelegate: public Outputs::Speaker::Speaker::Delegate, public LockP
@synchronized(self) {
std::vector<std::unique_ptr<Inputs::Joystick>> &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;
}

View File

@ -464,16 +464,16 @@ int main(int argc, char *argv[]) {
std::vector<std::unique_ptr<Inputs::Joystick>> &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;
}
}