Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@gagern
Copy link
Contributor

@gagern gagern commented Nov 18, 2023

Having read about M.U.L.E., I wanted to give that a try with a group of 4 players. 3 controllers and 1 keyboard, or so I hoped. But it didn't work out. And it took considerable working with the code and some recorded inputs to figure out that both the keyboard and the first SDL device were controlling the emulated joystick 0, while nothing was controlling the emulated joystick 3. Pity.

So I wrote some code to change that. This pull request introduces a new command line flag -joy-distinct which places the physical SDL devices after the keyboard-emulated devices, based on which keyboard-emulated devices are enabled at the time the config file and command line flags have been processed. This doesn't achieve full control over freely mapping which combinations of physical devices should control which emulated joysticks at which point in time, but it's a start and good enough for my use case. Extended logging output will make the assignments clearer and hopefully help future users who might get surprised by the default behavior the way I was surprised.

Reading the existing code I found that a lot of places were making very non-trivial assumptions about which kinds of host devices could be associated with which emulated controller. Different arrays were linked by index in various places. The possibility of having LPT joysticks and an on-screen keyboard (OSK) thrown in didn't make things any simpler. So the first commit of this request is a fairly wide-ranging change to simplify the abstraction of an emulated device without introducing any actual changes in observed behavior. A later commit then performs the changes based on the setting of the flag. One commit is a drive-by improvement by means of bit field arithmetic which is not really related to this PR except that I happened to look at that code and see a potential for simplification. Readers may choose to look at the commits in isolation to separate these aspects. The commit descriptions have more details which I won't repeat here.

Prior to this change, a lot of code uses the number of an emulated joystick
device to correlate various arrays and perform other case distinctions.
This change here introduces a more object-oriented approach: A single struct
contains all the information about an emulated stick, and functions to get
state can use that struct without worrying about the index.

The change removes the js_state structure.  Since SDL will already have the
current state cached, adding a second caching layer just adds complexity and
data duplication.  The get_platform_PORT and get_platform_TRIG functions are
also removed: since PLATFORM_PORT and PLATFORM_TRIG request state for just
one or two devices at a time, computing state for all of them feels wasteful
and confusing.

This change fixes a minor bug related to a failed SDL_JoystickOpen call.  In
that case, the variables i and joysticks_found inside Init_SDL_Joysticks
might mismatch.  That can lead to an incorrect assignment of the number of
buttons.  Apart from this, there should be no user-observable changes
introduced by this commit.

The rest of this commit message will look at some finer nuances of how
the old functionality gets modeled in the new code.

* The variables kbd_joy_#_enabled and swap_joysticks now require a
  call to update_kbd_sticks to take effect, since it's the stick_dev.kbd
  pointer that really matters here.  That's the reason the ui must now use
  functions instead of variables to access these.  Note that swap_joysticks
  only applies to keybord-emulated sticks, both before and after this
  change.
* The arguments to Init_SDL_Joysticks were without effect so got dropped.
* The four separate kbhits checks were replaced by a loop. The index
  in the configuration array corresponds to the bit for that direction.
  Alternative would have been to use a struct instead of an array, and to
  keep four separate id conditions instead of the loop.
* The presence of an LPT joystick overrides the SDL joystick of the
  same index.  This used to be due to an if-else construct in
  get_platform_PORT and get_platform_TRIG but is now achieved by
  Init_SDL_Joysticks clearing the SDL pointer on those devices.
* For the OSK, joysticks_found != 0 translates to osk_stick != NULL.
* Instead of relying on locally cached state, the on-screen keyboard
  now queries buttons individually at the time they are needed.  The
  joystick direction (port) state is also kept local.
These functions are translating from one bit pattern to another.  By
combining the resulting patterns for the four main directions, there is no
need to explicitly handle the diagonal directions as well.  Those will
simply follow from a combination the main directions.
This new flag allows users to emulate a larger number of joysticks by not
combining multiple physical devices into a single emulated joystick.

For example this allows using keyboard to emulate one or two joysticks, and
to use these in conjunction with physical SDL joysticks / controllers in
order to play with more people than there are SDL joysticks.
The same logic gets applied to LPT joysticks, too: if the flag is present,
these come after joysticks from keyboard emulation.

Furthermore, the logic also gets applied to put SDL joysticks after LPT
joystics even when the command line flag isn't set.  Since LPT joysticks
take precedence over SDL joysticks on the same emulated device, this takes a
device that was completely ignored before and makes it useful now.

The assignments are fixed at program start-up, after config file and command
line flags have been taken into account.  If the UI is used to enable or
disable a keyboard-emulated joystick, this can cause an emulated joystick to
be controlled by multiple physical devices, or by none.
@mikrosk mikrosk merged commit 246d5ec into atari800:master Nov 23, 2023
@mikrosk
Copy link
Member

mikrosk commented Nov 23, 2023

Looks good, merged. Thanks for the attention to detail!

@gagern gagern deleted the joy branch November 23, 2023 21:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants