diff --git a/Machines/Amiga/Amiga.cpp b/Machines/Amiga/Amiga.cpp index dcaefae53..94617d592 100644 --- a/Machines/Amiga/Amiga.cpp +++ b/Machines/Amiga/Amiga.cpp @@ -40,6 +40,7 @@ namespace Amiga { class ConcreteMachine: public Activity::Source, public CPU::MC68000::BusHandler, + public MachineTypes::JoystickMachine, public MachineTypes::MappedKeyboardMachine, public MachineTypes::MediaTarget, public MachineTypes::MouseMachine, @@ -208,6 +209,12 @@ class ConcreteMachine: return chipset_.get_mouse();; } + // MARK: - MachineTypes::JoystickMachine. + + const std::vector> &get_joysticks() { + return chipset_.get_joysticks(); + } + // MARK: - Keyboard. Amiga::KeyboardMapper keyboard_mapper_; diff --git a/Machines/Amiga/Chipset.cpp b/Machines/Amiga/Chipset.cpp index 1b2216c86..6ef8b5d2e 100644 --- a/Machines/Amiga/Chipset.cpp +++ b/Machines/Amiga/Chipset.cpp @@ -86,6 +86,9 @@ Chipset::Chipset(MemoryMap &map, int input_clock_rate) : disk_controller_(Cycles(input_clock_rate), *this, disk_, cia_b), keyboard_(cia_a.serial_input) { disk_controller_.set_clocking_hint_observer(this); + + joysticks_.emplace_back(new Joystick()); + cia_a_handler_.set_joystick(&joystick(0)); } #undef DMA_CONSTRUCT @@ -698,7 +701,7 @@ void Chipset::perform(const CPU::MC68000::Microcycle &cycle) { cycle.set_value16(mouse_.get_position()); break; case Read(0x00c): // JOY1DAT - cycle.set_value16(0x0202); + cycle.set_value16(joystick(0).get_position()); break; case Write(0x034): // POTGO @@ -1203,9 +1206,11 @@ uint8_t Chipset::CIAAHandler::get_port_input(MOS::MOS6526::Port port) { if(port) { LOG("TODO: parallel input?"); } else { + // Use the mouse as FIR0, the joystick as FIR1. return controller_.get_rdy_trk0_wpro_chng() & - mouse_.get_cia_button(); + mouse_.get_cia_button() & + (1 | (joystick_->get_cia_button() << 1)); } return 0xff; } @@ -1321,6 +1326,17 @@ uint16_t Chipset::Mouse::get_position() { // MARK: - Joystick. +// TODO: add second fire button. + +Chipset::Joystick::Joystick() : + ConcreteJoystick({ + Input(Input::Up), + Input(Input::Down), + Input(Input::Left), + Input(Input::Right), + Input(Input::Fire, 0), + }) {} + void Chipset::Joystick::did_set_input(const Input &input, bool is_active) { // Accumulate state. inputs_[input.type] = is_active; diff --git a/Machines/Amiga/Chipset.hpp b/Machines/Amiga/Chipset.hpp index 558c66aa2..10bceef70 100644 --- a/Machines/Amiga/Chipset.hpp +++ b/Machines/Amiga/Chipset.hpp @@ -99,10 +99,16 @@ class Chipset: private ClockingHint::Observer { disk_controller_.set_activity_observer(observer); } + // Keyboard and mouse exposure. Keyboard &get_keyboard() { return keyboard_; } + const std::vector> &get_joysticks() { + return joysticks_; + } + + // Synchronisation. void flush(); private: @@ -369,6 +375,11 @@ class Chipset: private ClockingHint::Observer { uint16_t position_ = 0; }; + std::vector> joysticks_; + Joystick &joystick(size_t index) const { + return *static_cast(joysticks_[index].get()); + } + // MARK: - CIAs. private: class DiskController; @@ -380,10 +391,18 @@ class Chipset: private ClockingHint::Observer { uint8_t get_port_input(MOS::MOS6526::Port port); void set_activity_observer(Activity::Observer *observer); + // TEMPORARY. + // TODO: generalise mice and joysticks. + // This is a hack. A TEMPORARY HACK. + void set_joystick(Joystick *joystick) { + joystick_ = joystick; + } + private: MemoryMap &map_; DiskController &controller_; Mouse &mouse_; + Joystick *joystick_ = nullptr; Activity::Observer *observer_ = nullptr; inline static const std::string led_name = "Power"; } cia_a_handler_;