<?xml version="1.0"?>
<!DOCTYPE riscos-prm PUBLIC "-//Gerph//DTD PRM documentation 1.03//EN"
                            "http://gerph.org/dtd/103/prm.dtd">

<riscos-prm>
<chapter title="Experimental Joystick driver interface (Pyromaniac)">
<section title="Introduction and overview">
<p>
The Pyromaniac Joystick module provides an experimental controller interface
for registering polling joystick drivers. It extends the existing Joystick SWI
chunk while retaining the legacy read operations for the first registered
device. It is a prototype interface and is not an allocated public RISC OS
interface.
</p>
<p>
The extended registration SWIs are available at &hex;43F50 and &hex;43F51.
They require allocation review before use in a released RISC OS component.
</p>
</section>

<section title="Technical details">
<p>
A driver registers a 32-byte joystick descriptor. The name and all descriptor
data are copied during registration, except the synchronous callback address
and private word which remain owned by the driver.
</p>
<p><offset-table>
<offset number="0" name="name" data-size="4">Pointer to a NUL-terminated joystick name.</offset>
<offset number="4" name="driver" data-size="4">Driver callback entry point.</offset>
<offset number="8" name="private-word" data-size="4">Value supplied in R12 on callback.</offset>
<offset number="12" name="flags" data-size="4">Must be zero.</offset>
<offset number="16" name="inputs" data-size="4">Number of input descriptors, from 1 to 254.</offset>
<offset number="20" name="input-list" data-size="4">Pointer to input descriptors.</offset>
<offset number="24" name="button-map" data-size="4">Pointer to a byte list of button input identifiers, terminated by 255.</offset>
<offset number="28" name="axis-map" data-size="4">Pointer to three bytes mapping X, Y and Z respectively; 255 means unavailable.</offset>
</offset-table></p>
<p>
Each input descriptor is 32 bytes. Types 0, 1 and 2 are centred X, Y and Z
axes; types 4, 5 and 6 are X, Y and Z axes whose rest position is low. Types
256 to 511 are buttons. A linear range must have a non-zero width.
</p>
<p><offset-table>
<offset number="0" name="type" data-size="4">Input type.</offset>
<offset number="4" name="name" data-size="4">Pointer to a NUL-terminated input name.</offset>
<offset number="8" name="usage" data-size="4">Usage: type in bits 0-11, sequence in bits 12-15, related input in bits 16-23; bits 24-31 must be zero.</offset>
<offset number="12" name="location" data-size="4">Physical location; reserved bits must be zero.</offset>
<offset number="16" name="minimum" data-size="4">Signed minimum raw value for a linear input.</offset>
<offset number="20" name="maximum" data-size="4">Signed maximum raw value for a linear input.</offset>
<offset number="24" name="rest" data-size="4">Signed rest value, or -1 for an unsprung input.</offset>
<offset number="28-31" state="reserved">Must be zero.</offset>
</offset-table></p>
<p>
The v1 callback is synchronous, non-blocking and read-only. R12 is the
registered private word, R0 is 0 for <em>ReadLinear</em> or 1 for
<em>ReadButton</em>, and R1 is the input identifier. It returns a signed raw
linear value or a button value of 0 or 1 in R0. Callback errors become
Joystick errors.
</p>
<p>
Experimental service notifications are disabled. Initialisation, shutdown,
registration and deregistration stub paths are retained, but no service block
is emitted until a formally allocated block is available.
</p>
</section>

<section title="SWI calls">
<swi-definition name="Joystick_Register" number="43F50" description="Register an experimental joystick driver">
<entry><register-use number="0">Pointer to the joystick descriptor.</register-use></entry>
<exit><register-use number="0">Allocated joystick number, from 0 to 254.</register-use></exit>
<use><p>Registers a validated descriptor and copies its descriptive data.</p></use>
</swi-definition>
<swi-definition name="Joystick_Deregister" number="43F51" description="Deregister an experimental joystick driver">
<entry><register-use number="0">Joystick number; all other bits must be zero.</register-use></entry>
<exit></exit>
<use><p>Removes the driver and releases copied descriptor data.</p></use>
</swi-definition>
<swi-definition name="Joystick_Read" number="43F40" description="Read joystick information or state">
<entry><register-use number="0"><p>Joystick number in bits 0-7, reason in bits 8-15, and a reason-specific input identifier in bits 16-23.</p><p><value-table head-number="Reason" head-value="Action"><value number="0">Legacy 8-bit state.</value><value number="1">Legacy 16-bit state.</value><value number="16">Joystick information and enumeration.</value><value number="17">Input information.</value><value number="18">Legacy button mapping.</value><value number="32">Scaled X, Y and Z values for the default axis mapping.</value><value number="33">Raw value and range for one linear input.</value><value number="48">One button state.</value><value number="49">One button state by usage.</value><value number="50">Packed range of up to 32 button states.</value><value number="51">Packed supplied-list button states.</value></value-table></p></register-use></entry>
<use><p>Reserved bits must be zero. Scaled values are clamped to the registered range and returned as 0 to 65535.</p></use>
</swi-definition>
</section>

<section title="Legacy compatibility">
<p>
Reasons 0 and 1 adapt joystick 0's default X/Y/Z and button mappings. Missing
X or Y axes read as the centred normalised value; unmapped buttons read clear.
Reason 0 returns signed 8-bit X and Y values and the first eight mapped button
states. Reason 1 returns normalised 16-bit X and Y values and the first eight
button states in R1.
</p>
<p>
<reference type="swi" name="Joystick_CalibrateTopRight"/> and
<reference type="swi" name="Joystick_CalibrateBottomLeft"/> return the error
<em>Joystick calibration is not implemented in this prototype</em>. Calibration
requires a later design for driver requests, persistent data and the legacy
calibration state machine.
</p>
</section>

<section title="Error messages">
<p>Registration rejects invalid descriptors, unsupported input types, invalid ranges, malformed mappings and reserved bits. Reads reject bad joystick or input identifiers, invalid usages, non-linear inputs where a linear input is required, and non-button inputs where a button is required.</p>
</section>
</chapter>
<meta>
 <maintainer><email name="Gerph" address="gerph@gerph.org" /></maintainer>
 <disclaimer><p>&copy; Gerph, 2026.</p></disclaimer>
 <history>
  <revision number="1" author="Gerph" date="14 Jul 2026" title="Experimental Pyromaniac interface">
   <change>Documented the prototype registered joystick driver interface.</change>
  </revision>
 </history>
</meta>
</riscos-prm>
