16static constexpr int THRESHOLD = 2;
17static constexpr int SCALE = 2;
18static constexpr int PHASE_XHIGH1 = 0;
19static constexpr int PHASE_XLOW1 = 1;
20static constexpr int PHASE_YHIGH1 = 2;
21static constexpr int PHASE_YLOW1 = 3;
22static constexpr int PHASE_XHIGH2 = 4;
23static constexpr int PHASE_XLOW2 = 5;
24static constexpr int PHASE_YHIGH2 = 6;
25static constexpr int PHASE_YLOW2 = 7;
26static constexpr int STROBE = 0x04;
33 MouseState(EmuTime::param time_,
int deltaX_,
int deltaY_,
34 uint8_t press_, uint8_t release_)
36 , deltaX(deltaX_), deltaY(deltaY_)
37 , press(press_), release(release_) {}
38 [[nodiscard]]
int getDeltaX()
const {
return deltaX; }
39 [[nodiscard]]
int getDeltaY()
const {
return deltaY; }
40 [[nodiscard]] uint8_t
getPress()
const {
return press; }
41 [[nodiscard]] uint8_t
getRelease()
const {
return release; }
42 template<
typename Archive>
void serialize(Archive& ar,
unsigned version)
44 ar.template serializeBase<StateChange>(*
this);
45 ar.serialize(
"deltaX", deltaX,
49 if (ar.versionBelow(version, 2)) {
50 assert(Archive::IS_LOADER);
63 deltaX = newMsxX - oldMsxX;
64 deltaY = newMsxY - oldMsxY;
69 uint8_t press, release;
79 : eventDistributor(eventDistributor_)
80 , stateChangeDistributor(stateChangeDistributor_)
88 Mouse::unplugHelper(EmuTime::dummy());
94std::string_view Mouse::getName()
const
99std::string_view Mouse::getDescription()
const
104void Mouse::plugHelper(Connector& , EmuTime::param time)
106 if (SDL_GetMouseState(
nullptr,
nullptr) & SDL_BUTTON(SDL_BUTTON_LEFT)) {
117void Mouse::plugHelper2()
123void Mouse::unplugHelper(EmuTime::param )
131uint8_t Mouse::read(EmuTime::param )
135 case PHASE_XHIGH1:
case PHASE_XHIGH2:
136 return ((xRel >> 4) & 0x0F) | status;
137 case PHASE_XLOW1:
case PHASE_XLOW2:
138 return (xRel & 0x0F) | status;
139 case PHASE_YHIGH1:
case PHASE_YHIGH2:
140 return ((yRel >> 4) & 0x0F) | status;
141 case PHASE_YLOW1:
case PHASE_YLOW2:
142 return (yRel & 0x0F) | status;
152void Mouse::emulateJoystick()
156 int deltaX = curXRel; curXRel = 0;
157 int deltaY = curYRel; curYRel = 0;
158 int absX = (deltaX > 0) ? deltaX : -deltaX;
159 int absY = (deltaY > 0) ? deltaY : -deltaY;
161 if ((absX < THRESHOLD) && (absY < THRESHOLD)) {
168 if ((12 * absX) > (5 * absY)) {
171 if ((12 * absY) > (5 * absX)) {
175 if ((12 * absX) > (5 * absY)) {
178 if ((12 * absY) > (5 * absX)) {
184 if ((12 * absX) > (5 * absY)) {
187 if ((12 * absY) > (5 * absX)) {
191 if ((12 * absX) > (5 * absY)) {
194 if ((12 * absY) > (5 * absX)) {
201void Mouse::write(uint8_t value, EmuTime::param time)
228 case PHASE_XHIGH1:
case PHASE_XHIGH2:
229 case PHASE_YHIGH1:
case PHASE_YHIGH2:
230 if ((value & STROBE) == 0) ++phase;
232 case PHASE_XLOW1:
case PHASE_XLOW2:
233 if ((value & STROBE) != 0) ++phase;
236 if ((value & STROBE) != 0) {
237 phase = PHASE_XHIGH2;
245 if ((value & STROBE) != 0) {
246 phase = PHASE_XHIGH1;
250 xrel = curxrel; yrel = curyrel;
251 curxrel = 0; curyrel = 0;
260 xRel = std::clamp(curXRel, -127, 127);
261 yRel = std::clamp(curYRel, -127, 127);
275void Mouse::signalMSXEvent(
const Event& event, EmuTime::param time)
noexcept
278 [&](
const MouseMotionEvent&
e) {
279 if (
e.getX() ||
e.getY()) {
286 fractionalX = qrX.remainder;
287 fractionalY = qrY.remainder;
290 createMouseStateChange(time, -qrX.quotient, -qrY.quotient, 0, 0);
293 [&](
const MouseButtonDownEvent&
e) {
294 switch (
e.getButton()) {
295 case SDL_BUTTON_LEFT:
296 createMouseStateChange(time, 0, 0, JOY_BUTTONA, 0);
298 case SDL_BUTTON_RIGHT:
299 createMouseStateChange(time, 0, 0, JOY_BUTTONB, 0);
306 [&](
const MouseButtonUpEvent&
e) {
307 switch (
e.getButton()) {
308 case SDL_BUTTON_LEFT:
309 createMouseStateChange(time, 0, 0, 0, JOY_BUTTONA);
311 case SDL_BUTTON_RIGHT:
312 createMouseStateChange(time, 0, 0, 0, JOY_BUTTONB);
319 [](
const EventBase&) { }
323void Mouse::createMouseStateChange(
324 EmuTime::param time,
int deltaX,
int deltaY, uint8_t press, uint8_t release)
327 time, deltaX, deltaY, press, release);
330void Mouse::signalStateChange(
const StateChange& event)
332 const auto* ms =
dynamic_cast<const MouseState*
>(&event);
337 curXRel += ms->getDeltaX();
338 curYRel += ms->getDeltaY();
339 status = (status & ~ms->getPress()) | ms->getRelease();
342void Mouse::stopReplay(EmuTime::param time)
noexcept
345 int dx = 0 - curXRel;
346 int dy = 0 - curYRel;
347 uint8_t release = (JOY_BUTTONA | JOY_BUTTONB) & ~status;
348 if ((dx != 0) || (dy != 0) || (release != 0)) {
349 createMouseStateChange(time, dx, dy, 0, release);
359template<
typename Archive>
365 if constexpr (Archive::IS_LOADER) {
374 if (ar.versionBelow(version, 4)) {
375 assert(Archive::IS_LOADER);
377 ar.serialize(
"lastTime", tmp);
380 ar.serialize(
"lastTime", lastTime);
382 ar.serialize(
"faze", phase,
386 "mouseMode", mouseMode);
387 if (ar.versionAtLeast(version, 2)) {
388 ar.serialize(
"curxrel", curXRel,
392 if (ar.versionBelow(version, 3)) {
Represents a clock with a fixed frequency.
constexpr EmuTime::param getTime() const
Gets the time at which the last clock tick occurred.
static constexpr EmuDuration usec(unsigned x)
static constexpr uint8_t JOY_RIGHT
static constexpr uint8_t JOY_LEFT
static constexpr uint8_t JOY_DOWN
static constexpr uint8_t JOY_UP
void registerEventListener(MSXEventListener &listener)
Registers a given object to receive certain events.
void unregisterEventListener(MSXEventListener &listener)
Unregisters a previously registered event listener.
uint8_t getRelease() const
void serialize(Archive &ar, unsigned version)
MouseState(EmuTime::param time_, int deltaX_, int deltaY_, uint8_t press_, uint8_t release_)
Mouse(MSXEventDistributor &eventDistributor, StateChangeDistributor &stateChangeDistributor)
void serialize(Archive &ar, unsigned version)
bool isPluggedIn() const
Returns true if this pluggable is currently plugged into a connector.
void registerListener(StateChangeListener &listener)
(Un)registers the given object to receive state change events.
void distributeNew(EmuTime::param time, Args &&...args)
Deliver the event to all registered listeners MSX input devices should call the distributeNew() versi...
void unregisterListener(StateChangeListener &listener)
Base class for all external MSX state changing events.
constexpr QuotientRemainder div_mod_floor(int dividend, int divisor)
This file implemented 3 utility functions:
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
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)