USBJoystick 0.20

USB Joystick driver for RISC OS 5
Post Reply
richw
Posts: 153
Joined: Sat Sep 14, 2013 9:05 pm

USBJoystick 0.20

Post by richw »

USBJoystick is a USB joystick driver for RISC OS 5. It supports USB HID-compliant joystick (or gamepad, or steering wheel etc.), including the XBOX 360 wired and wireless controllers. It provides the legacy Acorn, RTFM and SerialPort SWI interfaces, so existing games can be used with modern controllers.


What’s new?
  • I have improved the I/O podule ADC emulation so that ranges can be specified. This allows, for example, a single axis to be used as an accelerator and brake in Saloon Cars Deluxe. It may also allow for an effective deadzone to be specified, but I have not had a chance to try this.
  • The format of the ADC mapping *commands have changed. See the 'MapSCD' file in the src.utils directory for an example.
  • I have also had to re-introduce a couple of floats in the scaling. However, they are not in any SWI handlers, so there should be no regression to the abort situation.
  • The mouse pointer and buttons can be controlled with a joystick
  • Resolved a bug causing a crash when reading the manufacturer and product strings

Download

Version 0.20 is attached to this post.

A slightly earlier version is on GitHub for convenient browsing. I intend to sort this out properly at some point, so it can become the master repository. I will keep an eye out on how ROOL and others use Git. Link here: https://github.com/riscos-richard/USBJoystick


Requirements

You need a RISC OS 5 machine with USB hardware. I have only tried a Pi model B+. In theory, any USB HID-compliant joystick will work, but again, I have only tried what I have:
For any *commands, it is particularly useful if you have the LineEditor module installed. If you don’t have this, I would recommend you get it and stick it in your Boot PreDesk directory. You’ll wonder how you ever lived without it! You can grab the module from here:
https://github.com/philpem/LineEditor

Please make sure you don’t have any unsaved data before trying this module!

SparkFS (or similar) will be needed to open the attached zip file.


Starting

The zip file contains a single RISC OS module, USBJoystick. Just double-click it. The 'src' directory may interest you if you have the ROOL DDE.

Aso in the 'src' directory is a 'utils' directory, which contains a couple of BASIC test applications:
  • ADCTest: tests the I/O module ADC OSByte interface)
  • AcornTest: tests the Acorn 8-bit and 16-bit Joystick_Read SWI
  • RTFMTest: tests the RTFM interface - this is not currently usable
  • SerPortTest: tests the Serial Port (Vertical Twist) Joystick_Status SWI
You can use these from within a Task Window or by double-clicking from the Desktop. They will allow you to verify your joystick configuration without going to the trouble of loading a game.


Joystick discovery/enumeration

Open a Task Window (CTRL-F12) and type '*USBJoystick_List’. You should see some information on whatever joystick(s) you have plugged in. Each joystick is given an id number, starting from zero.

If you don’t see your joystick, then USBJoystick has not been able to detect it (can you see it if you use the OS command, '*USBDevices’?).


Enumeration

Joysticks will be discovered when the module starts. If you connect a joystick later on, it should be automatically detected (without restarting the module). Similarly, if you remove a joystick, the module will stop talking to it.


Mapping

The classic Acorn and Serial Port Joystick APIs refer to joysticks by a joystick number (0 or 1, for player 1 and 2 respectively). Note that the RTFM and Serial Port APIs only support one or two joysticks, but the Acorn API can support many more.

Each joystick number can offer two directional axes, typically up/down (Y) and left/right (X). A modern USB joystick will have multiple analogue axes (X, Y, Z, RX, RY, RZ) and separate digital inputs (DPAD or HAT switches). The desired USB axes need to be 'mapped' to the legacy number, X axis and Y axis.

As of version 0.07, you can map up to 8 buttons, but these will only work independently with the Acorn Joystick APIs. Games using the Serial Port or RTFM API will see a 'fire' when any of the buttons are pressed.

You can see the mapping with *USBJoystick_Mapped.


Automatic mapping

As of version 0.08, USBJoystick tries to automatically map the USB stick, axes and buttons across to the legacy items. The stick numbers will be assigned based on the order the USB devices are identified. If your joystick has a DPAD or HAT switch they will be mapped to the Serial Port, RTFM and Acorn 8-bit X and Y axes. If you have analogue X and Y axes, they will be mapped to the Acorn 16-bit X and Y axes. The buttons will be mapped in their order they the controller reports them - usually the first one reported is the primary.


Manual mapping

If the automatic mapping is not to your satisfaction, it can be adjusted with a number of *commands: *USBJoystick_MapStick, *USBJoystick_MapAxes8, *USBJoystick_MapAxes16 and *USBJoystick_MapButtons. Use the help to discover the exact syntax, e.g. *Help USBJoystick_MapStick will show you how to use the stick mapping feature.

You need to test your joystick to determine which axes and button you want to use. Type 'USBJoystick_Read 0' (or whatever joystick id you want). You should see some raw data showing the state of each axis and button. If you don’t touch the joystick, they will all be at their rest positions. Move the joystick up, and whilst holding that position, enter the read command again. Compare the two read outputs: you should be able to spot the value changing on one of the axes. This will be the Y-axis. Make a note of the axis number.

Repeat the above for identifying the X-axis, and each button. At the end of the process, you should know for each joystick id, the x and y axes numbers, and the primary button number. To map these up to the old Acorn/SerialPort API, you need to use the commands mentioned at the beginning of this section.

If any of your axes are working the wrong way around (e.g. up is down and down is up) then you can use the *USBJoystick_Flip command to invert the direction.

Please note that the mapping is not saved anywhere - it is just remembered in RAM. If you unplug the joystick, kill the USBJoystick module, or reboot your machine, the mapping will be lost. Once you have it figured out, you may wish to create an obey file which will set it up again for you.


Acorn I/O Podule Analogue to Digital converter

USBJoystick can emulate the ADC converter found on the I/O podule. It hooks into OSByte 128, so software using this SWI (including BASIC’s ADVAL function) will work. You can map an axis, or part of an axis, to an ADC channel, and a pair of buttons for fire. Please investigate the *command help: there is some mapping required.

The partial mapping is useful for configurations like a single Y axis (0 for middle, +32768 for top, and -32767 for bottom), where you want to map ADC Channel 0 to ‘up’ (so 0 to 32768 will be translated to 0 to 65520) and Channel 1 to ‘down’ (so 0 to -32767 will be translated to 0 to 65520).


Using the Joystick

Once you have mapped, you can use any software which supports the Acorn (SWI Joystick_Read) or Serial Port (SWI Joystick_Status). The USB Joystick driver module will transform the USB data into a format for those SWIs, and respond to their requests. With the help of ADFFS, games which use the RTFM API should also function.

I have tried some of the games from this web site: James Pond and SWIV work over the Serial Port SWI, and Zool works over the Acorn SWI.


Testing

Obviously, this thing is far from finished. It clearly needs more testing: one machine, two USB joysticks, and three games doesn’t really cut it! :)

All feedback is welcome.


Technical matters

If you have any problems with the module, it would be helpful if you could run Reporter before you run the module. If Reporter is active, some debugging guff will appear in Reporter’s log. This may help me! Reporter is available here: http://www.avisoft.f9.co.uk/Reporter.htm

The *command *USBJoystick_Debug 0 (replacing 0 for your joystick id, or removing it entirely to see all) may also provide useful information for me.

The output from Colin Granville's USBDescriptors output may be useful.


Acknowledgements

Jon’s efforts with JASPP itself was my inspiration for developing this (obviously, this is tiny effort in comparison!). Also, many thanks to the following people over on the ROOL forums who offered advice and put up with my silly questions: Jeffrey Lee, Rick Murray, Stuart Swales, Colin Granville, Simon Birtwhistle, and Chris Mahoney. Thanks to James Peacock for EtherUSB, and Colin Granville for USBDescriptors. The code uses components from NetBSD and XMAME. There are further notes in the source code.


Todo: Refactoring
  • Remove floats so we don’t need FPA DONE IN 0.12
  • Listen for service calls from USBDriver Starting/Dying
  • Do we really need joy_index to be a global?
  • Implement releasing of memory in clean_joystick_data_item() DONE IN 0.10
  • Determine correct error-handling strategy for module_finalise()

Todo: Features
  • Support multiple buttons in the mapping DONE IN 0.07
  • Support SerialPort 'stir', 'flag A' and 'flag B' - extra buttons/mappings?
  • Decide if we need ability to reverse an axis in the mapping DONE IN 0.08
  • Emulate 16-bit Acorn Joystick_Read response DONE IN 0.7
  • Emulate RTFM joystick API (based on Econet hardware peeks) DONE IN 0.06 (with ADFFS)
  • Emulate Acorn I/O podule API (ADVAL and associated OSBYTEs) DONE IN 0.12
  • Save settings into Choices$Write and read back on init
  • Load settings via USB alias system (used by !Printers). Would it be useful?
  • Consider auto-assigning legacy joystick numbers as devices are discovered DONE IN 0.07
  • Allow Joystick actions to be mapped to keypresses or mouse moves DONE IN 0.20
  • Formalise an SWI interface for device enumeration and configuration. This would allow a Configure plug-in to be developed.
Attachments
usbjoystick020.zip
(207.48 KiB) Downloaded 126 times

JonAbbott
Posts: 2460
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: USBJoystick 0.20

Post by JonAbbott »

Thanks for the update Richard, I'll roll this into the ADFFS beta and begin some testing on a wider range of games.

I'm busy adding Joystick support to games that don't support them, so can test the mouse emulation as a few need it mapping.

richw
Posts: 153
Joined: Sat Sep 14, 2013 9:05 pm

Re: USBJoystick 0.20

Post by richw »

Sounds good.

I was pondering keyboard emulation in USBJoystick, as it is the same code as for the mouse buttons. But I think it makes more sense in ADFFS, as it could be worked into the game boot scripts.

I think I need to add in a sensitivity setting for the mouse, perhaps even try to set it automatically based on the axes ranges.

The thing I keep putting off is a GUI in Boot/Configure. One day...

grannyg
Posts: 18
Joined: Fri Dec 13, 2013 3:47 pm

Re: USBJoystick 0.20

Post by grannyg »

I tried mapping the buttons on a PS4 controller to key presses but it doesn't seem to take effect.
If say the 'X' button is mapped to the 'a' key should 'a' then appear in a task window if the 'X' button is pressed.

JonAbbott
Posts: 2460
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: USBJoystick 0.20

Post by JonAbbott »

richw wrote:
Wed Jan 27, 2021 9:17 pm
I was pondering keyboard emulation in USBJoystick, as it is the same code as for the mouse buttons. But I think it makes more sense in ADFFS, as it could be worked into the game boot scripts.
If that does ever change, I can easily redirect the ADFFS * command to USBJoystick if it's available. I wonder if moving it to USBJoystick might resolve the issue I'm having with Alerion where inserting a keypress causes random aborts.

I suspect Alerion's IRQ handler can't handle re-entrancy, but haven't had time to look yet.
grannyg wrote:
Thu Jan 28, 2021 1:45 pm
I tried mapping the buttons on a PS4 controller to key presses but it doesn't seem to take effect.
Using ADFFS? It will only work in games that run under the JIT, as its handled in the VIDC emulator.

JonAbbott
Posts: 2460
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: USBJoystick 0.20

Post by JonAbbott »

Richard, how can we add support for multiple thumb sticks for use in games?

I'm attempting to add Joystick support for BloodLust and a few others that use keyboard for movement and Mouse for firing direction, but unless I'm missing something obvious I can't see how to read the 2nd thumb stick on the mapped Joystick.

Some other titles could do with multiple mappings as well, such as Pandora's Box, Carnage Inc. etc. where you need to navigate the menu separately to the movement control. For those, ideally we'd want the D-Pad and Thumbstick separate - I might possibly be able to do that now by using 16 bit for movement and 8 bit for the D-Pad?

richw
Posts: 153
Joined: Sat Sep 14, 2013 9:05 pm

Re: USBJoystick 0.20

Post by richw »

Hi Jon,

It has been floating around in my head for a while... I think the Acorn Joystick SWIs need extending to cover more complex use-cases like multi-axes. We could also cover things like reporting the connected devices and even force feedback.

I keep meaning to draw up some proposals and post on the ROOL forum for feedback.

It would be good if it could ease in with libraries like SDL2 to assist porting, and there might even be some existing API extensions (it is possible that Paradise might have come up with something late on).

Ideas welcome!

Also, yes, combining 8 and 16 bit might help you out there...

JonAbbott
Posts: 2460
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: USBJoystick 0.20

Post by JonAbbott »

Some of the mappings I can't currently implement are:
  • Battle Tank needs the Thumb sticks mapped to a left/right tank tracks and the right trigger mapped to fire
  • BloodLust needs the left thumb stick mapped to movement and the right thumb stick mapped to the firing direction
  • Robotix needs the left thumb stick mapped to movement and the right thumb stick mapped to the firing direction
  • Chequered Flag needs the Accelerator/Brake mapped to the left/right triggers
  • Pandora's Box, Carnage Inc need the menu selection mapped to the D-Pad and direction mapped to a thumb stick
Currently we've got the D-Pad mapped to Joystick_Read 0 and the left thumb stick mapped to Joystick_Read 1. That's worked for games that already support Joysticks and needs to be kept. As a quick fix, we could add an SWI at the top of the Joystick SWI range until a formal standard can be worked out. Something along the lines of:

Joystick_ReadElement (name is academic)
SWI (&43F45)
  • R0=Joystick no
  • R1=Element to read (0 - Buttons, 1 - D-Pad, 2 - Left thumb stick, 3 - Right thumb stick, 4 - Left trigger, 5 - Right trigger, 6 - named element)
  • R2=named element if R1=6 (0 - Left trigger, 1 - Right trigger, 2 - LB, 3 - RB, 4 - Left thumb stick click, 5 - Right thumb stick click, 6 - Start, 7 - Back ...)
Exit R2/R3 values dependent on R1
  • 0 - R2=<1 bit per button> supporting 32 buttons
  • 1 - R2=0-8 (0-No position, 1-Up, 2-Up/Right, 3-Right ...)
  • 2/3 - R2=X value, R3=Y value (32-bit signed)
  • 4/5 - R2=value (32-bit signed)
  • 6 - R3=1 if pressed
ROOL thread to discuss this proposed change.

JonAbbott
Posts: 2460
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: USBJoystick 0.20

Post by JonAbbott »

I’ve tested Saloon Cars using ADC mapped to the three channels for steering, brake and accelerator. It works perfectly, except the steering is reversed with my XB360 steering wheel. I could have sworn you wrote a manual for USBJoystick, but I couldn’t find it in the source or on my HD - is there a way to inverse an axis mapping? Save me wading through the source code.

I tried the obvious of using =value on the axis, which clearly didn’t work.

The next problem I can foresee with using USBJoystick in ADFFS scripts is mapping to numbers for elements, instead of names. Eg RT, LT, Left=Thumb=X etc. I’ve got a similar knock on issue into ADFFS with mapping to buttons such as LB,RB, Start, Back etc and have assumed they’ll always be mapped to B6 thru B8.

I’m in the process of adding named mapping to the ADFFS commands, so am going to assume the mappings are consistent. They’re certainly consistent across my various XB360 controllers.

One final thing, is it possible to map LT, RT to buttons as that would be useful for some of the games I’m working on at the minute.

JonAbbott
Posts: 2460
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: USBJoystick 0.20

Post by JonAbbott »

Am I being a bit thick, how do I map to RISC OS Joystick 2? For example how can I map the right stick on Joystick 1 to RISC OS Joystick 2? I can map stick 1 on Joystick 1 to RISC OS Joystick 1 via:
*USBJoystick_MapStick 0 0 (ie USB joystick 1, stick 1)

I think there might also be a bug as the following does not appear to map stick 2 to Joystick 1:
*USBJoystick_MapStick 0 1 (ie USB joystick 1, stick 2)

Post Reply