#ifndef JOYSTICK_H_INCLUDED
#define JOYSTICK_H_INCLUDED

// Public C interface to the Joystick SWIs.
// Hdr:Interface.Joystick already defines the standard SWIs for assembler

#include <stdint.h>


// --- Standard SWIs ---
#ifndef Joystick_Read
#define Joystick_Read                   0x43F40
#endif
#ifndef Joystick_CalibrateTopRight
#define Joystick_CalibrateTopRight      0x43F41
#endif
#ifndef Joystick_CalibrateBottomLeft
#define Joystick_CalibrateBottomLeft    0x43F42
#endif

// Joystick_Read: R0 bits 0-7 = stick number, plus one of these in bits 8-15
#define Joystick_Read_8BitFlag          0
#define Joystick_Read_16BitFlag         (1u << 8)


// --- Extended SWIs ---
#ifndef Joystick_Status
#define Joystick_Status                 0x43F43
#define Joystick_Enumerate              0x43F44
#define Joystick_DeviceInfo             0x43F45
#define Joystick_AxisInfo               0x43F46
#define Joystick_AxisValues             0x43F47
// 0x43F48 is reserved (formerly Joystick_GetMapping)
#define Joystick_SetStick               0x43F49
#define Joystick_Emulate                0x43F4A
#define Joystick_SaveMapping            0x43F4B
#define Joystick_RevertToDefaultMap     0x43F4C
#define Joystick_ReloadConfig           0x43F4D
#define Joystick_ReadBindings           0x43F4E
#define Joystick_WriteBindings          0x43F4F
#define Joystick_AddBinding             0x43F50
#define Joystick_ReadDefaultBindings    0x43F51
#define Joystick_Control                0x43F52
#define Joystick_SaveSettings           0x43F53
#endif


// "No axis/button/stick": used wherever a mapping field has nothing in it
#define Joystick_NotMapped             -1000


// --- Joystick_Emulate: R0 = classic API ---
#define Joystick_Emulate_SerialPort      0
#define Joystick_Emulate_Joy             1
#define Joystick_Emulate_ADC             2

// --- Joystick_Control: R0 = output gate ---
#define Joystick_Control_Mouse           0
#define Joystick_Control_Keyboard        1


// --- Axis types (joystick_axis_info.type) ---
#define Joystick_Axis_HatX      1
#define Joystick_Axis_HatY      2
#define Joystick_Axis_DPadX     3
#define Joystick_Axis_DPadY     4
#define Joystick_Axis_X         5
#define Joystick_Axis_Y         6
#define Joystick_Axis_Z         7
#define Joystick_Axis_RX        8
#define Joystick_Axis_RY        9
#define Joystick_Axis_RZ        10
#define Joystick_Axis_Slider    11


// --- Capability bits (joystick_device_info.capabilities); the rest are 0 ---
#define Joystick_Cap_Rumble    (1u << 0)
#define Joystick_Cap_LED       (1u << 1)
#define Joystick_Cap_Battery   (1u << 2)
#define Joystick_Cap_Touchpad  (1u << 3)
#define Joystick_Cap_Sensors   (1u << 4)


// Joystick_DeviceInfo
struct joystick_device_info {
  uint32_t size;
  char     *manufacturer;
  char     *product;
  char     *serial;           // "" if the device has no real iSerialNumber
  uint32_t vendor_id;
  uint32_t product_id;
  uint32_t num_axes;
  uint32_t num_buttons;
  uint32_t num_hats;           // count of HAT/D-pad style controls (0-2)
  uint32_t capabilities;       // Joystick_Cap_* bitfield
  uint8_t  guid[16];           // SDL-style synthesised identity
  int32_t  legacy_stick_number; // Joystick_Read stick number (Joystick_SetStick), or Joystick_NotMapped
};

// Joystick_AxisInfo
struct joystick_axis_info {
  uint32_t hid_usage_page;    // raw HID usage page
  uint32_t hid_usage;         // 0 if not known
  uint32_t type;              // Joystick_Axis_*
  char     *name;
  int32_t  min, mid, max;
  int   is_digital;           // synthesised HAT/D-pad axis (-1/0/1 only)
};

// --- Binding table (Joystick_ReadBindings / WriteBindings / AddBinding) ---
// A binding is one "this source drives that target" record; a device's
// mapping is a flat list of them. See doc.Bindings.

// source_type
enum {
  Joystick_Binding_Source_Axis   = 0,   // source_index is a physical axis index (0..num_axes-1)
  Joystick_Binding_Source_Button = 1    // source_index is a physical button index (0..num_buttons-1)
};

// target_kind, and what target_index means for each
enum {
  Joystick_Binding_Target_None        = 0,  // index unused - never stored, transient only
  Joystick_Binding_Target_SlotAxis    = 1,  // index: Joystick_Binding_Axis_*
  Joystick_Binding_Target_SlotButton  = 2,  // index: 0..31  slot button
  Joystick_Binding_Target_MouseMove   = 3,  // index: Joystick_Binding_Mouse_X / Joystick_Binding_Mouse_Y
  Joystick_Binding_Target_MouseButton = 4,  // index: Joystick_Binding_MouseButton_Select / _Menu / _Adjust
  Joystick_Binding_Target_Key         = 5,  // index: RISC OS internal KeyNo (why index is 16-bit)
  Joystick_Binding_Target_ADC         = 6,  // index: 0..3  ADC channel (analogue)
  Joystick_Binding_Target_ADCButton   = 7   // index: 0..1  ADC fire button (digital)
};

// target_index values for Joystick_Binding_Target_SlotAxis
enum { Joystick_Binding_Axis_8X = 0, Joystick_Binding_Axis_8Y = 1, Joystick_Binding_Axis_16X = 2, Joystick_Binding_Axis_16Y = 3 };

// target_index values for Joystick_Binding_Target_MouseMove
enum { Joystick_Binding_Mouse_X = 0, Joystick_Binding_Mouse_Y = 1 };

// target_index values for Joystick_Binding_Target_MouseButton
enum { Joystick_Binding_MouseButton_Select = 0, Joystick_Binding_MouseButton_Menu = 1, Joystick_Binding_MouseButton_Adjust = 2 };

// flags
#define Joystick_Binding_Flag_Invert  0x01u   // reverse direction

// One binding: 12 bytes, word-aligned, no padding.
typedef struct {
  uint8_t  source_type;   // Joystick_Binding_Source_*
  uint8_t  source_index;  // physical axis or button number
  uint8_t  target_kind;   // Joystick_Binding_Target_*
  uint8_t  flags;         // Joystick_Binding_Flag_*; unknown bits rejected at write time
  uint16_t target_index;  // meaning depends on target_kind (holds KeyNo for Joystick_Binding_Target_Key)
  uint16_t reserved;      // 0
  uint32_t param;         // 0 for now; reserved for future scale/sensitivity
} joystick_binding;

// Most bindings a device can hold; Joystick_WriteBindings rejects a larger table
#define Joystick_Binding_Max  128

#endif
