//===========================================================================//
// File:    l4padbindings.h                                                  //
// Project: MUNGA           Brick: PadRIO binding profiles                   //
// Contents: The rebindable input profile (vRIO bindings format)             //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//

#pragma once

#include "..\munga\style.h"

//########################################################################
// The bindings file (vRIO's format, shared grammar):
//
//   key <name>      button <addr> [toggle]
//   key <name>      axis <axis> deflect <n> | rate <n>
//   pad <button>    button <addr> [toggle]
//   padaxis <src>   axis <axis> [invert] [deadzone <d>] [rate <n>]
//   joydev <slot>   [product-name substring...]
//   joyaxis <src>   axis <axis> [invert] [deadzone <d>] [rate <n>]
//   joybutton <n>   button <addr> [toggle]
//   joyhat <n> <up|down|left|right> button <addr>
//
// <addr> is a RIO input address: lamp buttons 0x00-0x47, internal
// keypad 0x50-0x5F, external keypad 0x60-0x6F. Loaded from
// bindings.txt beside the exe; written there (self-documenting, with
// the full default profile) on first run. Bad lines are logged and
// skipped, good lines always win.
//
// The joy* rows drive generic DirectInput devices - flight sticks,
// HOTAS throttles, twist grips, rudder pedals (L4JOY.h). They attach to
// the most recent joydev slot, or slot 0 if no joydev came first. A slot
// naming a product substring binds THAT device; a bare slot binds the
// Nth attached non-XInput device. Source names follow the DirectInput
// layout - X Y Z RX RY RZ SL0 SL1 - where a twist grip is usually RZ
// and a HOTAS throttle usually Z or SL0. RP412JOYCONFIG=1 writes these
// rows for you by asking the player to move each control.
//########################################################################

enum PadBindRioAxis
{
	BindAxisThrottle = 0,
	BindAxisLeftPedal,
	BindAxisRightPedal,
	BindAxisJoystickY,
	BindAxisJoystickX,
	//
	// A signed composite, not a channel the pod has: positive presses
	// the right pedal, negative the left. One physical control - a
	// rudder bar, a twist grip, a stick axis - works the pedal pair the
	// way a foot never could, one or the other and never both. It
	// decomposes into the real pair when the poll applies it.
	//
	BindAxisPedals,
	BindAxisCount
};

enum PadBindKeyMode
{
	BindKeyDeflect = 0,	// hold at value while down, spring back
	BindKeyRate			// walk by value/second while down, position holds
};

enum PadBindPadAxis
{
	BindPadLeftStickX = 0,
	BindPadLeftStickY,
	BindPadRightStickX,
	BindPadRightStickY,
	BindPadLeftTrigger,
	BindPadRightTrigger,
	BindPadAxisCount
};

struct PadKeyButtonBinding
{
	int		virtualKey;
	int		address;		// 0x00-0x47 button, 0x50-0x6F keypad
	Logical	toggle;
	// runtime edge/latch state
	Logical	wasDown;
	Logical	latched;
};

struct PadKeyAxisBinding
{
	int		virtualKey;
	int		axis;			// PadBindRioAxis
	int		mode;			// PadBindKeyMode
	Scalar	value;
};

struct PadPadButtonBinding
{
	unsigned short	padMask;	// XINPUT_GAMEPAD_*
	int				address;
	Logical			toggle;
	Logical			wasDown;
	Logical			latched;
};

struct PadPadAxisBinding
{
	int		source;			// PadBindPadAxis
	int		axis;			// PadBindRioAxis
	Logical	invert;
	Scalar	deadzone;		// normalized 0..1
	Scalar	rate;			// 0 = direct position, >0 = speed integrate
};

//
// Generic joystick (DirectInput - L4JOY.h). device is a joydev SLOT,
// resolved to a live device at poll time by the slot's name substring or
// by its ordinal, so unplugging and replugging does not rewrite the file.
//
enum { BindJoyDeviceSlots = 4 };

enum PadBindJoyAxis
{
	BindJoyAxisX = 0,
	BindJoyAxisY,
	BindJoyAxisZ,
	BindJoyAxisRX,
	BindJoyAxisRY,
	BindJoyAxisRZ,
	BindJoyAxisSL0,
	BindJoyAxisSL1,
	BindJoyAxisCount
};

struct PadJoyAxisBinding
{
	int		device;			// joydev slot
	int		source;			// PadBindJoyAxis
	int		axis;			// PadBindRioAxis
	Logical	invert;
	Scalar	deadzone;		// normalized 0..1
	Scalar	rate;			// 0 = direct position, >0 = speed integrate
};

struct PadJoyButtonBinding
{
	int		device;			// joydev slot
	int		button;			// 0-31
	int		address;
	Logical	toggle;
	Logical	wasDown;
	Logical	latched;
};

struct PadJoyHatBinding
{
	int		device;			// joydev slot
	int		hat;			// 0-3
	int		direction;		// 0 up, 1 right, 2 down, 3 left
	int		address;
};

struct PadBindingProfile
{
	enum
	{
		maxKeyButtons	= 128,
		maxKeyAxes		= 32,
		maxPadButtons	= 32,
		maxPadAxes		= 16,
		maxJoyAxes		= 24,
		maxJoyButtons	= 48,
		maxJoyHats		= 16
	};

	PadKeyButtonBinding		keyButtons[maxKeyButtons];
	int						keyButtonCount;
	PadKeyAxisBinding		keyAxes[maxKeyAxes];
	int						keyAxisCount;
	PadPadButtonBinding		padButtons[maxPadButtons];
	int						padButtonCount;
	PadPadAxisBinding		padAxes[maxPadAxes];
	int						padAxisCount;

	PadJoyAxisBinding		joyAxes[maxJoyAxes];
	int						joyAxisCount;
	PadJoyButtonBinding		joyButtons[maxJoyButtons];
	int						joyButtonCount;
	PadJoyHatBinding		joyHats[maxJoyHats];
	int						joyHatCount;
	// "" = take the slot's ordinal attached device
	char					joyDeviceMatch[BindJoyDeviceSlots][64];
};

// Load bindings.txt from the working directory into the profile,
// writing the default profile file first when absent. Errors go to
// the debug log with line numbers.
void
	PadBindings_Load(PadBindingProfile *profile);
