gnuboy-for-dfi/sys/thinlib/lib/tl_joy.c

205 lines
4.4 KiB
C

/*
** thinlib (c) 2001 Matthew Conte (matt@conte.com)
**
**
** tl_joy.c
**
** DOS joystick reading routines
**
** $Id: $
*/
#include <dos.h>
#include "tl_types.h"
#include "tl_int.h"
#include "tl_joy.h"
#include "tl_event.h"
#define JOY_PORT 0x201
#define JOY_TIMEOUT 10000
#define J1_A 0x10
#define J1_B 0x20
#define J2_A 0x40
#define J2_B 0x80
#define J1_X 0x01
#define J1_Y 0x02
#define J2_X 0x04
#define J2_Y 0x08
#define JOY_CENTER 0xAA
#define JOY_MIN_THRESH 0.7
#define JOY_MAX_THRESH 1.3
static struct joyinfo_s
{
int id; /* callback ID */
int x_minthresh, x_maxthresh;
int y_minthresh, y_maxthresh;
int x_read, y_read;
uint8 button_state;
bool disconnected;
} joyinfo;
static joy_t joystick;
/* Read data in from joy port */
static int _portread(void)
{
/* Set timeout to max number of samples */
int timeout = JOY_TIMEOUT;
uint8 port_val;
joyinfo.x_read = 0;
joyinfo.y_read = 0;
THIN_DISABLE_INTS();
/* Clear the latch and request a sample */
port_val = inportb(JOY_PORT);
outportb(JOY_PORT, port_val);
do
{
port_val = inportb(JOY_PORT);
if (port_val & J1_X)
joyinfo.x_read++;
if (port_val & J1_Y)
joyinfo.y_read++;
}
while (--timeout && (port_val & 3));
joyinfo.button_state = port_val;
THIN_ENABLE_INTS();
if (0 == timeout)
return -1;
else
return 0;
}
void _poll_joystick(void)
{
int i;
joy_t old;
thin_event_t event;
old = joystick;
if (_portread())
{
joyinfo.disconnected = true;
return;
}
/* Calc X axis */
joystick.left = (joyinfo.x_read < joyinfo.x_minthresh) ? true : false;
joystick.right = (joyinfo.x_read > joyinfo.x_maxthresh) ? true : false;
/* Calc Y axis */
joystick.up = (joyinfo.y_read < joyinfo.y_minthresh) ? true : false;
joystick.down = (joyinfo.y_read > joyinfo.y_maxthresh) ? true : false;
/* Get button status */
/* note that buttons returned by hardware are inverted logic */
joystick.button[0] = (joyinfo.button_state & J1_A) ? false : true;
joystick.button[1] = (joyinfo.button_state & J2_A) ? false : true;
joystick.button[2] = (joyinfo.button_state & J1_B) ? false : true;
joystick.button[3] = (joyinfo.button_state & J2_B) ? false : true;
/* generate some events if necessary */
if (joystick.left != old.left)
{
event.type = THIN_JOY_MOTION;
event.data.joy_motion.dir = THIN_JOY_LEFT;
event.data.joy_motion.state = joystick.left;
thin_event_add(&event);
}
if (joystick.right != old.right)
{
event.type = THIN_JOY_MOTION;
event.data.joy_motion.dir = THIN_JOY_RIGHT;
event.data.joy_motion.state = joystick.right;
thin_event_add(&event);
}
if (joystick.up != old.up)
{
event.type = THIN_JOY_MOTION;
event.data.joy_motion.dir = THIN_JOY_UP;
event.data.joy_motion.state = joystick.up;
thin_event_add(&event);
}
if (joystick.down != old.down)
{
event.type = THIN_JOY_MOTION;
event.data.joy_motion.dir = THIN_JOY_DOWN;
event.data.joy_motion.state = joystick.down;
thin_event_add(&event);
}
for (i = 0; i < JOY_MAX_BUTTONS; i++)
{
if (joystick.button[i] != old.button[i])
{
event.type = joystick.button[i] ? THIN_JOY_BUTTON_PRESS : THIN_JOY_BUTTON_RELEASE;
event.data.joy_button = i;
thin_event_add(&event);
}
}
}
int thin_joy_read(joy_t *joy)
{
if (joyinfo.disconnected)
return -1;
*joy = joystick;
return 0;
}
/* Detect presence of joystick */
int thin_joy_init(void)
{
joyinfo.disconnected = true;
if (_portread())
return -1;
joyinfo.id = thin_event_add_callback((event_callback_t) _poll_joystick);
if (-1 == joyinfo.id)
return -1;
joyinfo.disconnected = false;
/* Set the threshhold */
joyinfo.x_minthresh = JOY_MIN_THRESH * joyinfo.x_read;
joyinfo.x_maxthresh = JOY_MAX_THRESH * joyinfo.x_read;
joyinfo.y_minthresh = JOY_MIN_THRESH * joyinfo.y_read;
joyinfo.y_maxthresh = JOY_MAX_THRESH * joyinfo.y_read;
return 0;
}
void thin_joy_shutdown(void)
{
joyinfo.disconnected = true;
if (-1 != joyinfo.id)
{
thin_event_remove_callback(joyinfo.id);
joyinfo.id = -1;
}
}
/*
** $Log: $
*/