USBJoystick 0.21

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

USBJoystick 0.21

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?
  • Updated RTFM Joystick detection emulation based on some research and advice from Jon. Hopefully this fixes issues with JK Squash

Download

Version 0.21 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 - probably when a RISC OS git client is available. 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
USBJoystick021.zip
(207.65 KiB) Downloaded 833 times
richw
Posts: 159
Joined: Sat Sep 14, 2013 9:05 pm

Re: USBJoystick 0.21

Post by richw »

Ah, been doing a bit of playing about...

The RTFM change isn't good. I tried Mad Professor, and it makes the controls go bazerk. I think I need to double check how that game is testing for and reading the sticks.
JonAbbott
Posts: 2938
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: USBJoystick 0.21

Post by JonAbbott »

richw wrote: Thu Aug 18, 2022 9:54 pm I tried Mad Professor, and it makes the controls go berserk
So it does.

Odd thing is, it works correctly if you test with an XB360 controller. Not sure why that would make a difference?

EDIT: If you look at its code, I need to correct it as its relying on the SWI to fail:

Code: Select all

000181DC SWI     XJoy_Read0    
000181E0 MOVVS   R0,#0         
000181E4 ANDS    R0,R0,#&1F    
000181E8 BNE     &000181FC     
000181EC SWI     XJoy_Read1    
000181F0 MOVVS   R0,#0         
000181F4 ANDS    R0,R0,#&1F    
000181F8 BEQ     &0001822C     
000181FC MOV     R12,#0        
00018200 TST     R0,#&10       
00018204 ORRNE   R12,R12,#&10  
00018208 TST     R0,#8         
0001820C ORRNE   R12,R12,#4    
00018210 TST     R0,#4         
00018214 ORRNE   R12,R12,#8    
00018218 TST     R0,#2         
0001821C ORRNE   R12,R12,#1    
00018220 TST     R0,#1         
00018224 ORRNE   R12,R12,#2
So, I'd say USBJoystick is good. I just need to correct the game code to actually check if a Joystick is attached via Joy_Test. ADFFS 2.81 already has a few of the JoyMod games corrected to test for a Joystick, I'll go through and check them all before final release and correct their code where necessary.

Our problem is we're trying to cover several iterations of JoyMod and its changed over time. Earlier games rely on the SWI returning an error if there's no Joystick attached, later games make use of Joy_Test and expect Joy_Read to return 1F if not attached. I've taken the view that I'm going to patch all games to use the final iteration of Joy_Mod.

I suppose we could add a *Command to switch the behaviour to old or new responses and have the SWI return an error when emulating old JoyMod?

EDIT:2 I forgot to mention that if you get into a level, press CTRL-D and then press "I" it does actually tell you what it expects from Joy_Read0/1. Its using the very first iteration of JoyMod by the looks of it:
Mad Professor Mariarti JoyMod details.png
Mad Professor Mariarti JoyMod details.png (67.24 KiB) Viewed 3967 times
JonAbbott
Posts: 2938
Joined: Thu Apr 11, 2013 12:13 pm
Location: Essex
Contact:

Re: USBJoystick 0.21

Post by JonAbbott »

State of play with 0.21:

Working
Axis
Champions: Jahangir Khan World Championship Squash
Chuck Rock [SA version]
Fire & Ice
Heimdall
Jahangir Khan World Championship Squash
Jahangir Khan World Championship Squash [BUZZ version]
James Pond
James Pond [BUZZ version]
James Pond [SA version]
Krisalis Collection, The: Terramex
Lotus Turbo Challenge 2
Manchester United Europe
Nebulus
Pac-mania [Learning Curve version]
Sally and Wally
SpeedBall 2
Spheres of Chaos
Stunt Racer 2000

Joystick not being detected
Fervour
Krisalis Collection, The: Revelation! [BUZZ version]
Manchester United
Revelation! [BUZZ version]

Don't have a copy of the game
Mad Professor Mariarti [BUZZ version]
Revelation!

RTFM code needs correcting
Chuck Rock
Krisalis Collection, The: Mad Professor Mariarti [BUZZ version]
Mad Professor Mariarti
Nevryon
S.W.I.V.
S.W.I.V. [BUZZ version]

I've corrected the RTFM code in Chuck Rock, Mad Professor Mariarti and SWIV in ADFFS 2.81.

I'll need to take a more detailed look at Fervour, Manchester United and Revelation! as I couldn't get them to work with a Joystick. I don't recall ever testing them in the past, only noting that they called Joystick SWI's or had Joystick options.
richw
Posts: 159
Joined: Sat Sep 14, 2013 9:05 pm

Re: USBJoystick 0.21

Post by richw »

Funny thing about MadProf is that I was testing it with a (Chinese knock-off) XB360 controller, so that's interesting!

Its good news that you've boiled it down to a few games which are not right. I was thinking that either the new approach was totally wrong, or that I'd need to add in some sort of switch to the behaviour. I was pondering an alternative SWI (or tweaking to r0) which I could pick-up and return different behaviour. But I guess that if you have to patch the game to do that, then you might as well patch the game properly!

At least these games are not moving targets. It's all stuff from the past, so patching actually makes sense. Going forward, anyone coding Joystick support in a game should be using the Acorn Joystick SWIs, so there's no issue.

Oh, and there's a blast from the past. I think I last saw that page of info in MadProf when I was about 10, and had no idea what any of it meant. ;)
Post Reply