mirror of
https://github.com/thug1src/thug.git
synced 2024-12-02 12:56:45 +00:00
532 lines
16 KiB
C
532 lines
16 KiB
C
|
/*****************************************************************************
|
||
|
** **
|
||
|
** Neversoft Entertainment **
|
||
|
** **
|
||
|
** Copyright (C) 1999 - All Rights Reserved **
|
||
|
** **
|
||
|
******************************************************************************
|
||
|
** **
|
||
|
** Project: GEL (Game Engine Library) **
|
||
|
** **
|
||
|
** Module: Input (Inp) **
|
||
|
** **
|
||
|
** File name: gel/inpman.h **
|
||
|
** **
|
||
|
** Created: 05/26/2000 - spg **
|
||
|
** **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#ifndef __GEL_INPMAN_H
|
||
|
#define __GEL_INPMAN_H
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Includes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#ifndef __CORE_DEFINES_H
|
||
|
#include <core/defines.h>
|
||
|
#endif
|
||
|
#include <core/singleton.h>
|
||
|
#include <core/list.h>
|
||
|
#include <core/task.h>
|
||
|
|
||
|
#include <sys/sioman.h>
|
||
|
#include <sys/siodev.h>
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Defines **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
#define PAD_NONE 0
|
||
|
#define PAD_U 1
|
||
|
#define PAD_D 2
|
||
|
#define PAD_L 3
|
||
|
#define PAD_R 4
|
||
|
#define PAD_UL 5
|
||
|
#define PAD_UR 6
|
||
|
#define PAD_DL 7
|
||
|
#define PAD_DR 8
|
||
|
#define PAD_CIRCLE 9
|
||
|
#define PAD_SQUARE 10
|
||
|
#define PAD_X 11
|
||
|
#define PAD_TRIANGLE 12
|
||
|
#define PAD_L1 13
|
||
|
#define PAD_L2 14
|
||
|
#define PAD_L3 15
|
||
|
#define PAD_R1 16
|
||
|
#define PAD_R2 17
|
||
|
#define PAD_R3 18
|
||
|
#define PAD_BLACK 19
|
||
|
#define PAD_WHITE 20
|
||
|
#define PAD_Z 21
|
||
|
#define PAD_NUMBUTTONS 22
|
||
|
|
||
|
namespace Inp
|
||
|
{
|
||
|
|
||
|
|
||
|
|
||
|
static const int vANALOGUE_TOL = 50; // Mick, changed back from 32, as our controllers were wandering...
|
||
|
static const int vANALOGUE_CENTER = 128;
|
||
|
|
||
|
|
||
|
extern uint32 gDebugButtons[];
|
||
|
extern uint32 gDebugBreaks[];
|
||
|
extern uint32 gDebugMakes[];
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Class Definitions **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
int GetButtonIndex(uint32 Checksum);
|
||
|
uint32 GetButtonChecksum( int whichButton );
|
||
|
|
||
|
class Data : public Spt::Class
|
||
|
{
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
friend class Server;
|
||
|
|
||
|
Data( void );
|
||
|
|
||
|
#define vMAX_ANALOG_VALUE 255
|
||
|
|
||
|
enum DigitalButtonIndex
|
||
|
{
|
||
|
vD_L2,
|
||
|
vD_R2,
|
||
|
vD_L1,
|
||
|
vD_R1,
|
||
|
vD_TRIANGLE,
|
||
|
vD_CIRCLE,
|
||
|
vD_X,
|
||
|
vD_SQUARE,
|
||
|
vD_SELECT,
|
||
|
vD_L3,
|
||
|
vD_R3,
|
||
|
vD_START,
|
||
|
vD_UP,
|
||
|
vD_RIGHT,
|
||
|
vD_DOWN,
|
||
|
vD_LEFT,
|
||
|
vD_BLACK, // Only supported on XBox
|
||
|
vD_WHITE, // Only supported on XBox
|
||
|
vD_Z, // Only supported on NGC
|
||
|
vMAX_DIGITAL_EVENTS
|
||
|
};
|
||
|
|
||
|
enum AnalogButtonIndex
|
||
|
{
|
||
|
vA_RIGHT_X, // Right analog controller stick
|
||
|
vA_RIGHT_Y,
|
||
|
vA_LEFT_X, // Left analog controller stick
|
||
|
vA_LEFT_Y,
|
||
|
vA_RIGHT,
|
||
|
vA_LEFT,
|
||
|
vA_UP,
|
||
|
vA_DOWN,
|
||
|
vA_TRIANGLE,
|
||
|
vA_CIRCLE,
|
||
|
vA_X,
|
||
|
vA_SQUARE,
|
||
|
vA_L1,
|
||
|
vA_R1,
|
||
|
vA_L2,
|
||
|
vA_R2,
|
||
|
vA_L3,
|
||
|
vA_R3,
|
||
|
// (Mick) Added the following to stop the analog values before they are clamped
|
||
|
// these values only get clamped if BOTH X and Y are in the middle
|
||
|
// the above values clamp X and Y independently
|
||
|
// leading to dead zones when rotating the stick round in a circle
|
||
|
// a significant loss in accuracy
|
||
|
vA_RIGHT_X_UNCLAMPED, // Right analog controller stick
|
||
|
vA_RIGHT_Y_UNCLAMPED,
|
||
|
vA_LEFT_X_UNCLAMPED, // Left analog controller stick
|
||
|
vA_LEFT_Y_UNCLAMPED,
|
||
|
|
||
|
vA_BLACK, // Only supported on XBox
|
||
|
vA_WHITE, // Only supported on XBox
|
||
|
|
||
|
vA_Z, // Only supported on XBox
|
||
|
|
||
|
// vA_SELECT,
|
||
|
|
||
|
vMAX_ANALOG_EVENTS
|
||
|
};
|
||
|
|
||
|
enum DigitalButtonMask
|
||
|
{
|
||
|
// These map directly to digital input in m_Buttons, m_Prev and m_New
|
||
|
mD_L2 = nBit( vD_L2 ),
|
||
|
mD_R2 = nBit( vD_R2 ),
|
||
|
mD_L1 = nBit( vD_L1 ),
|
||
|
mD_R1 = nBit( vD_R1 ),
|
||
|
mD_TRIANGLE = nBit( vD_TRIANGLE ),
|
||
|
mD_CIRCLE = nBit( vD_CIRCLE ),
|
||
|
mD_X = nBit( vD_X ),
|
||
|
mD_SQUARE = nBit( vD_SQUARE ),
|
||
|
mD_SELECT = nBit( vD_SELECT ),
|
||
|
mD_L3 = nBit( vD_L3 ),
|
||
|
mD_R3 = nBit( vD_R3 ),
|
||
|
mD_START = nBit( vD_START ),
|
||
|
mD_UP = nBit( vD_UP ),
|
||
|
mD_RIGHT = nBit( vD_RIGHT ),
|
||
|
mD_DOWN = nBit( vD_DOWN ),
|
||
|
mD_LEFT = nBit( vD_LEFT ),
|
||
|
mD_BLACK = nBit( vD_BLACK ),
|
||
|
mD_WHITE = nBit( vD_WHITE ),
|
||
|
mD_Z = nBit( vD_Z ),
|
||
|
mD_ALL = 0xffffffff
|
||
|
};
|
||
|
|
||
|
enum AnalogButtonMask
|
||
|
{
|
||
|
// These map indirectly to analog input in m_Events
|
||
|
mA_RIGHT_X = nBit( vA_RIGHT_X ), // Right analog controller stick
|
||
|
mA_RIGHT_Y = nBit( vA_RIGHT_Y ),
|
||
|
mA_LEFT_X = nBit( vA_LEFT_X ), // Left analog controller stick
|
||
|
mA_LEFT_Y = nBit( vA_LEFT_Y ),
|
||
|
mA_RIGHT = nBit( vA_RIGHT ),
|
||
|
mA_LEFT = nBit( vA_LEFT ),
|
||
|
mA_UP = nBit( vA_UP ),
|
||
|
mA_DOWN = nBit( vA_DOWN ),
|
||
|
mA_TRIANGLE = nBit( vA_TRIANGLE ),
|
||
|
mA_CIRCLE = nBit( vA_CIRCLE ),
|
||
|
mA_X = nBit( vA_X ),
|
||
|
mA_SQUARE = nBit( vA_SQUARE ),
|
||
|
mA_L1 = nBit( vA_L1 ),
|
||
|
mA_R1 = nBit( vA_R1 ),
|
||
|
mA_L2 = nBit( vA_L2 ),
|
||
|
mA_R2 = nBit( vA_R2 ),
|
||
|
mA_L3 = nBit( vA_L3 ),
|
||
|
mA_R3 = nBit( vA_R3 ),
|
||
|
mA_BLACK = nBit( vA_BLACK ),
|
||
|
mA_WHITE = nBit( vA_WHITE ),
|
||
|
mA_Z = nBit( vA_Z ),
|
||
|
// mA_SELECT = nBit( vA_SELECT ),
|
||
|
mA_ALL = 0xffffffff
|
||
|
};
|
||
|
|
||
|
|
||
|
void MaskDigitalInput( int button_mask );
|
||
|
void MaskAnalogInput( int button_mask );
|
||
|
void ConvertDigitalToAnalog( void );
|
||
|
void OverrideAnalogPadWithStick( void );
|
||
|
|
||
|
uint8 m_Event[vMAX_ANALOG_EVENTS]; // Analog info
|
||
|
uint m_Buttons; // Current accessible button info (digital)
|
||
|
uint m_Makes; // Depressed this frame
|
||
|
uint m_Breaks; // Released this frame
|
||
|
|
||
|
private:
|
||
|
|
||
|
uint m_new; // Edges (digital)
|
||
|
uint m_cur; // Current INTERNAL button info (digital)
|
||
|
uint m_prev; // last frame's trig
|
||
|
|
||
|
void handle_analog_tolerance( void );
|
||
|
};
|
||
|
|
||
|
class RecordedData : public Spt::Class
|
||
|
{
|
||
|
|
||
|
|
||
|
friend class Server;
|
||
|
|
||
|
private:
|
||
|
sint8 m_valid; // Was data valid on this frame?
|
||
|
uint8 m_event[Data::vMAX_ANALOG_EVENTS]; // Analog info
|
||
|
uint m_cur; // Current INTERNAL button info (digital)
|
||
|
|
||
|
};
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
class BaseHandler : public Tsk::BaseTask
|
||
|
{
|
||
|
|
||
|
|
||
|
friend class Manager;
|
||
|
|
||
|
public:
|
||
|
Data* m_Input; // controller input
|
||
|
SIO::Device *m_Device; // the device from which this data was obtained
|
||
|
int m_Index;
|
||
|
|
||
|
protected:
|
||
|
BaseHandler ( int index, Tsk::BaseTask::Node::Priority pri )
|
||
|
: Tsk::BaseTask( pri ), m_Index ( index )
|
||
|
{
|
||
|
Dbg_Printf( "Creating BaseHandler with Pri %d\n", pri );
|
||
|
}
|
||
|
|
||
|
|
||
|
virtual ~BaseHandler ( void ) {}
|
||
|
};
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
nTemplateSubClass( _T, Handler, BaseHandler )
|
||
|
{
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
typedef void (Code)( const Handler< _T >& );
|
||
|
|
||
|
Handler( int index, Code* const code, _T& data,
|
||
|
Lst::Node< Tsk::BaseTask >::Priority pri = Lst::Node< Tsk::BaseTask >::vNORMAL_PRIORITY );
|
||
|
|
||
|
virtual ~Handler ( void );
|
||
|
|
||
|
virtual void vCall( void ) const;
|
||
|
virtual void * GetCode(void) const;
|
||
|
_T& GetData( void ) const;
|
||
|
|
||
|
private :
|
||
|
|
||
|
Code* const code; // tasks entry point
|
||
|
_T& data; // task defined data
|
||
|
};
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
//class Server : public Spt::Class // note - need compiler fix for delete[] bug!!!
|
||
|
class Server
|
||
|
{
|
||
|
//
|
||
|
|
||
|
friend class Manager;
|
||
|
|
||
|
public:
|
||
|
Server();
|
||
|
|
||
|
void RecordInput( RecordedData *data_buffer );
|
||
|
void PlaybackInput( RecordedData *recorded_input );
|
||
|
|
||
|
private:
|
||
|
|
||
|
void service_handlers( void );
|
||
|
|
||
|
SIO::Device *m_device;
|
||
|
Tsk::Stack m_handler_stack;
|
||
|
Data m_data;
|
||
|
|
||
|
RecordedData *m_data_in;
|
||
|
void *m_data_in_end;
|
||
|
RecordedData *m_data_out;
|
||
|
void *m_data_out_end;
|
||
|
};
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
class Manager : public Spt::Class
|
||
|
{
|
||
|
|
||
|
|
||
|
public :
|
||
|
|
||
|
void AddHandler( BaseHandler &handler );
|
||
|
void ReassignHandler( BaseHandler &handler, int new_index );
|
||
|
void AddPushHandler( BaseHandler &handler );
|
||
|
Tsk::BaseTask& GetProcessHandlersTask ( void ) const;
|
||
|
|
||
|
void RecordInput( int index, RecordedData *data_buffer, int byte_length );
|
||
|
void PlaybackInput( int index, RecordedData *recorded_input, int byte_length );
|
||
|
void PushInputLogicTasks( void );
|
||
|
void PopInputLogicTasks( void );
|
||
|
bool ActuatorEnabled( int i );
|
||
|
|
||
|
void DisableActuators( void );
|
||
|
void DisableActuator( int i );
|
||
|
|
||
|
void EnableActuators( void );
|
||
|
void EnableActuator( int i );
|
||
|
void ResetActuators( void );
|
||
|
|
||
|
void SetAnalogStickOverride( bool should_override_pad );
|
||
|
bool ShouldAnalogStickOverride( void );
|
||
|
|
||
|
private :
|
||
|
~Manager ( void );
|
||
|
Manager ( void );
|
||
|
|
||
|
static Tsk::Task< Manager >::Code process_handlers;
|
||
|
|
||
|
Tsk::Task< Manager >* m_process_handlers_task;
|
||
|
Server m_server[SIO::vMAX_DEVICES];
|
||
|
bool m_override_pad_with_stick;
|
||
|
|
||
|
DeclareSingletonClass( Manager );
|
||
|
};
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Declarations **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Private Prototypes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Public Declarations **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Public Prototypes **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
** Inline Functions **
|
||
|
*****************************************************************************/
|
||
|
|
||
|
inline Tsk::BaseTask& Manager::GetProcessHandlersTask ( void ) const
|
||
|
{
|
||
|
|
||
|
|
||
|
Dbg_AssertType ( m_process_handlers_task, Tsk::BaseTask );
|
||
|
|
||
|
return *m_process_handlers_task;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
inline void Manager::AddHandler ( BaseHandler &handler )
|
||
|
{
|
||
|
|
||
|
|
||
|
Dbg_MsgAssert( handler.m_Index < SIO::vMAX_DEVICES,( "Invalid controller index" ));
|
||
|
|
||
|
m_server[handler.m_Index].m_handler_stack.AddTask( handler );
|
||
|
handler.m_Input = &m_server[handler.m_Index].m_data;
|
||
|
handler.m_Device = m_server[handler.m_Index].m_device;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
inline void Manager::ReassignHandler( BaseHandler &handler, int new_index )
|
||
|
{
|
||
|
Dbg_MsgAssert( new_index < SIO::vMAX_DEVICES,( "Invalid controller index" ));
|
||
|
|
||
|
handler.Remove();
|
||
|
m_server[new_index].m_handler_stack.AddTask( handler );
|
||
|
handler.m_Input = &m_server[new_index].m_data;
|
||
|
handler.m_Device = m_server[new_index].m_device;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
inline void Manager::AddPushHandler ( BaseHandler &handler )
|
||
|
{
|
||
|
|
||
|
|
||
|
Dbg_MsgAssert( handler.m_Index < SIO::vMAX_DEVICES,( "Invalid controller index" ));
|
||
|
|
||
|
m_server[handler.m_Index].m_handler_stack.AddPushTask( handler );
|
||
|
handler.m_Input = &m_server[handler.m_Index].m_data;
|
||
|
handler.m_Device = m_server[handler.m_Index].m_device;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
template < class _T > inline
|
||
|
Handler< _T >::Handler( int index, Code* const _code, _T& _data, Tsk::BaseTask::Node::Priority pri )
|
||
|
: BaseHandler( index, pri ), code( _code ), data( _data )
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
template < class _T > inline
|
||
|
Handler< _T >::~Handler( void )
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
template < class _T > inline
|
||
|
void Handler< _T >::vCall( void ) const
|
||
|
{
|
||
|
|
||
|
|
||
|
Dbg_AssertPtr( code );
|
||
|
code( *this );
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
template < class _T > inline
|
||
|
_T& Handler< _T >::GetData( void ) const
|
||
|
{
|
||
|
|
||
|
|
||
|
Dbg_AssertType( &data, _T );
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
template < class _T > inline
|
||
|
void * Handler< _T >::GetCode( void ) const
|
||
|
{
|
||
|
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/******************************************************************/
|
||
|
/* */
|
||
|
/* */
|
||
|
/******************************************************************/
|
||
|
|
||
|
} // namespace Inp
|
||
|
|
||
|
#endif // __GEL_INPMAN_H
|