As previously mentioned, here is an alpha test version of my USB Joystick driver module (scroll to bottom of post for download link). Quick instructions follow.
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:
- a USB-Atari interface, with an old Atari joystick, and a Chinese knock-off MegaDrive pad
- a wireless XBOX360-style controller
Please make sure you don’t have any unsaved data before trying this module!
SparkFS (or similar) will be needed to open the attached file.
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 appliations. They test the SerialPort and Acorn interfaces (just as games would) so you can use them to check your joystick is detected and mapped correctly without running a game.
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. Note the ‘mapped to’ lines, which should be empty (-).
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.
The classic Acorn and Serial Port Joystick APIs refer to joysticks by a joystick number (0 or 1, for player 1 and 2 respectively) and they support two directional axis, typically up/down (Y) and left/right (X). This needs to be 'mapped' to the capabilities of your USB joystick.
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 ‘*USBJoystick_Map'. Help is available, so ‘*Help USBJoystick_Map’ will tell you the formal definition of the command.
For my Atari joystick, the USB Joystick id is 0 (because it’s the first one I plugged in), axis 2 is X, axis 3 is Y, and button 1 is fire. If I want to map this up to what we would call ‘joystick 1’ in the old days, then I need to enter: '*USBJoystick_Map 0 0 2 3 1’. Then if I do a ‘*USBJoystick_List 0’ to confirm things, I can see the mapping information at the bottom of the output.
As of version 0.7, 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.
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.
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.
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.
Obviously, this thing is far from finished. Later, I’ll post up my ‘to do’ list. It clearly needs more testing: one machine, two USB joysticks, and three games doesn’t really cut it!
All feedback is welcome.
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) may also provide useful information for me.
The output from Colin Granville's USBDescriptors output may be useful.
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.
- 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()
- Determine correct error-handling strategy for module_finalise()
- Support multiple buttons in the mapping DONE IN 0.7
- Support SerialPort 'stir', 'flag A' and 'flag B' - extra buttons?
- Decide if we need ability to reverse an axis in the mapping
- Emulate 16-bit Acorn Joystick_Read response DONE IN 0.7
- Emulate RTFM joystick API (based on Econet hardware peeks) DONE IN 0.6 (with ADFFS)
- Emulate Acorn I/O podule API (ADVAL and associated OSBYTEs)
- 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 lagacy joystick numbers as devices are discovered - useful?
- Allow Joystick actions to be mapped to keypresses or mouse moves
- Formalise an SWI interface for device enumeration and configuration. This would allow a Configure plug-in to be developed.
The latest release is attached to this post.