27 unsigned press_,
unsigned release_)
29 , press(press_), release(release_), id(id_) {}
31 [[nodiscard]]
auto getId()
const {
return id; }
32 [[nodiscard]]
auto getPress()
const {
return press; }
33 [[nodiscard]]
auto getRelease()
const {
return release; }
35 template<
typename Archive>
void serialize(Archive& ar,
unsigned )
37 ar.template serializeBase<StateChange>(*
this);
38 ar.serialize(
"id",
id,
43 unsigned press, release;
51 if (!buttons)
return {};
53 std::array<TclObject, 8> lists;
54 auto joy = joyId.
str();
55 for (
auto b :
xrange(*buttons)) {
56 lists[b % 8].addListElement(
tmpStrCat(joy,
" button", b));
78 : commandController(commandController_)
79 , eventDistributor(eventDistributor_)
80 , stateChangeDistributor(stateChangeDistributor_)
81 , joystickManager(joystickManager_)
82 , configSetting(commandController,
tmpStrCat(
"joymega", id_,
"_config"),
83 "joymega mapping configuration", getDefaultConfig(
JoystickId(id_ - 1), joystickManager).getString())
84 , description(
strCat(
"JoyMega based Mega Drive controller ", id_,
". Mapping is fully configurable."))
88 this->checkJoystickConfig(newValue); });
90 checkJoystickConfig(configSetting.
getValue());
96 JoyMega::unplugHelper(EmuTime::dummy());
100void JoyMega::checkJoystickConfig(
const TclObject& newValue)
102 std::array<std::vector<BooleanInput>, 12> newBindings;
109 for (
unsigned i = 0; i < n; i += 2) {
110 static constexpr std::array<std::string_view, 12> keys = {
112 "UP",
"DOWN",
"LEFT",
"RIGHT",
113 "A",
"B",
"C",
"START",
114 "X",
"Y",
"Z",
"SELECT",
118 if (it ==
keys.end()) {
119 throw CommandException(
120 "Invalid key: must be one of ",
join(keys,
", "));
122 auto idx = std::distance(
keys.begin(), it);
125 for (
auto j :
xrange(value.getListLength(interp))) {
129 throw CommandException(
"Invalid binding: ", val);
131 newBindings[idx].push_back(*bind);
140std::string_view JoyMega::getName()
const
143 case 1:
return "joymega1";
144 case 2:
return "joymega2";
149std::string_view JoyMega::getDescription()
const
154void JoyMega::plugHelper(Connector& , EmuTime::param )
161 cycleMask = (status & 0x800) ? 7 : 1;
164void JoyMega::plugHelper2()
170void JoyMega::unplugHelper(EmuTime::param )
178uint8_t JoyMega::read(EmuTime::param time)
185 case 0:
case 2:
case 4:
187 return (status & 0x00f) | ((status & 0x060) >> 1);
190 return (status & 0x013) | ((status & 0x080) >> 2);
193 return (status & 0x010) | ((status & 0x080) >> 2);
196 return ((status & 0x400) >> 10) |
197 ((status & 0xA00) >> 8) |
198 ((status & 0x100) >> 6) |
199 ((status & 0x060) >> 1);
202 return (status & 0x010) | ((status & 0x080) >> 2) | 0x0f;
208void JoyMega::write(uint8_t value, EmuTime::param time)
212 if (((value >> 2) & 1) != (cycle & 1)) {
213 cycle = (cycle + 1) & cycleMask;
215 assert(((value >> 2) & 1) == (cycle & 1));
218void JoyMega::checkTime(EmuTime::param time)
227void JoyMega::signalMSXEvent(
const Event& event, EmuTime::param time)
noexcept
230 unsigned release = 0;
232 auto getJoyDeadZone = [&](JoystickId joyId) {
233 const auto*
setting = joystickManager.getJoyDeadZoneSetting(joyId);
236 for (
int i :
xrange(12)) {
237 for (
const auto& binding : bindings[i]) {
238 if (
auto onOff =
match(binding, event, getJoyDeadZone)) {
239 (*onOff ? press : release) |= 1 << i;
244 if (((status & ~press) | release) != status) {
245 stateChangeDistributor.distributeNew<JoyMegaState>(
246 time,
id, press, release);
251void JoyMega::signalStateChange(
const StateChange& event)
253 const auto* js =
dynamic_cast<const JoyMegaState*
>(&event);
255 if (js->getId() != id)
return;
257 status = (status & ~js->getPress()) | js->getRelease();
260void JoyMega::stopReplay(EmuTime::param time)
noexcept
262 unsigned newStatus = 0xfff;
263 if (newStatus != status) {
264 auto release = newStatus & ~status;
265 stateChangeDistributor.distributeNew<JoyMegaState>(
266 time,
id, 0, release);
270template<
typename Archive>
273 ar.serialize(
"lastTime", lastTime,
276 "cycleMask", cycleMask);
277 if constexpr (Archive::IS_LOADER) {
virtual Interpreter & getInterpreter()=0
static constexpr EmuDuration usec(unsigned x)
JoyMegaState(EmuTime::param time_, uint8_t id_, unsigned press_, unsigned release_)
void serialize(Archive &ar, unsigned)
static TclObject getDefaultConfig(JoystickId joyId, const JoystickManager &joystickManager)
JoyMega(CommandController &commandController, MSXEventDistributor &eventDistributor, StateChangeDistributor &stateChangeDistributor, JoystickManager &joystickManager, uint8_t id)
void serialize(Archive &ar, unsigned version)
std::optional< unsigned > getNumButtons(JoystickId joyId) const
void registerEventListener(MSXEventListener &listener)
Registers a given object to receive certain events.
void unregisterEventListener(MSXEventListener &listener)
Unregisters a previously registered event listener.
bool isPluggedIn() const
Returns true if this pluggable is currently plugged into a connector.
void setChecker(std::function< void(TclObject &)> checkFunc_)
Set value-check-callback.
const TclObject & getValue() const final
Gets the current value of this setting as a TclObject.
void registerListener(StateChangeListener &listener)
(Un)registers the given object to receive state change events.
void unregisterListener(StateChangeListener &listener)
Base class for all external MSX state changing events.
unsigned getListLength(Interpreter &interp) const
TclObject getListIndex(Interpreter &interp, unsigned index) const
zstring_view getString() const
detail::Joiner< Collection, Separator > join(Collection &&col, Separator &&sep)
This file implemented 3 utility functions:
std::optional< bool > match(const BooleanInput &binding, const Event &event, function_ref< int(JoystickId)> getJoyDeadZone)
std::optional< BooleanInput > parseBooleanInput(std::string_view text)
std::variant< KeyUpEvent, KeyDownEvent, MouseMotionEvent, MouseButtonUpEvent, MouseButtonDownEvent, MouseWheelEvent, JoystickAxisMotionEvent, JoystickHatEvent, JoystickButtonUpEvent, JoystickButtonDownEvent, OsdControlReleaseEvent, OsdControlPressEvent, WindowEvent, TextEvent, FileDropEvent, QuitEvent, FinishFrameEvent, CliCommandEvent, GroupEvent, BootEvent, FrameDrawnEvent, BreakEvent, SwitchRendererEvent, TakeReverseSnapshotEvent, AfterTimedEvent, MachineLoadedEvent, MachineActivatedEvent, MachineDeactivatedEvent, MidiInReaderEvent, MidiInWindowsEvent, MidiInCoreMidiEvent, MidiInCoreMidiVirtualEvent, MidiInALSAEvent, Rs232TesterEvent, Rs232NetEvent, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
TclObject makeTclList(Args &&... args)
auto find(InputRange &&range, const T &value)
constexpr auto copy(InputRange &&range, OutputIter out)
constexpr auto keys(Map &&map)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
TemporaryString tmpStrCat(Ts &&... ts)
constexpr auto xrange(T e)