mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-24 12:30:17 +00:00
Moves the joystick class towards accepting analogue inputs.
This commit is contained in:
parent
a1c60152d4
commit
3ea2a4ccb8
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user