260 lines
6.1 KiB
C
260 lines
6.1 KiB
C
|
// I_cyber.c
|
||
|
|
||
|
#include <dos.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
|
||
|
/*
|
||
|
====================================================
|
||
|
|
||
|
Doom control structure
|
||
|
|
||
|
The keybaord and joystick will add to the values set by the cyberman,
|
||
|
to a maximum of 0x19000 for forwardmove and sidemove. Angleturn is
|
||
|
not bounded at all.
|
||
|
|
||
|
parm normal fast
|
||
|
----- ------ ----
|
||
|
forwardmove 0xc800 0x19000
|
||
|
sidemove 0xc000 0x14000
|
||
|
angleturn 0x2800000 0x5000000
|
||
|
|
||
|
The keyboard and joystick have a 1/3 second slow turn of 0x1400000 under
|
||
|
normal speed to help aiming.
|
||
|
|
||
|
|
||
|
|
||
|
====================================================
|
||
|
*/
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
char forwardmove; // *2048 for move
|
||
|
char sidemove; // *2048 for move
|
||
|
short angleturn; // <<16 for angle delta
|
||
|
short consistancy; // checks for net game
|
||
|
unsigned char chatchar;
|
||
|
unsigned char buttons;
|
||
|
} ticcmd_t;
|
||
|
|
||
|
#define BT_ATTACK 1
|
||
|
#define BT_USE 2
|
||
|
#define BT_CHANGE 4 // if true, the next 3 bits hold weapon num
|
||
|
#define BT_WEAPONMASK (8+16+32)
|
||
|
#define BT_WEAPONSHIFT 3
|
||
|
|
||
|
|
||
|
|
||
|
//==================================================
|
||
|
//
|
||
|
// CyberMan detection and usage info
|
||
|
//
|
||
|
//==================================================
|
||
|
#define DPMI_INT 0x31
|
||
|
#define MOUSE_INT 0x33
|
||
|
|
||
|
#define DOSMEMSIZE 64 // enough for any SWIFT structure
|
||
|
|
||
|
typedef struct {
|
||
|
short x;
|
||
|
short y;
|
||
|
short z;
|
||
|
short pitch;
|
||
|
short roll;
|
||
|
short yaw;
|
||
|
short buttons;
|
||
|
} SWIFT_3DStatus;
|
||
|
|
||
|
// DPMI real mode interrupt structure
|
||
|
static struct rminfo {
|
||
|
long EDI;
|
||
|
long ESI;
|
||
|
long EBP;
|
||
|
long reserved_by_system;
|
||
|
long EBX;
|
||
|
long EDX;
|
||
|
long ECX;
|
||
|
long EAX;
|
||
|
short flags;
|
||
|
short ES,DS,FS,GS,IP,CS,SP,SS;
|
||
|
} RMI;
|
||
|
|
||
|
typedef struct {
|
||
|
unsigned char deviceType;
|
||
|
unsigned char majorVersion;
|
||
|
unsigned char minorVersion;
|
||
|
unsigned char absRelFlags;
|
||
|
unsigned char centeringFlags;
|
||
|
unsigned char reserved[5];
|
||
|
} StaticDeviceData;
|
||
|
|
||
|
// values for deviceType:
|
||
|
#define DEVTYPE_CYBERMAN 1
|
||
|
|
||
|
short selector;
|
||
|
unsigned short segment; // segment of DOS memory block
|
||
|
SWIFT_3DStatus *cyberstat;
|
||
|
int isCyberPresent; // is CyberMan present?
|
||
|
|
||
|
|
||
|
static union REGS regs;
|
||
|
static struct SREGS sregs;
|
||
|
|
||
|
|
||
|
extern int mousepresent;
|
||
|
|
||
|
//===========================================================
|
||
|
//
|
||
|
// I_StartupCyberMan
|
||
|
//
|
||
|
// If a cyberman is present, init it and set isCyberPresent to 1
|
||
|
//===========================================================
|
||
|
void I_StartupCyberMan(void)
|
||
|
{
|
||
|
StaticDeviceData *pbuf;
|
||
|
int success = 0;
|
||
|
|
||
|
isCyberPresent = 0;
|
||
|
|
||
|
cyberstat = (SWIFT_3DStatus *)I_AllocLow (DOSMEMSIZE);
|
||
|
segment = (int)cyberstat>>4;
|
||
|
|
||
|
pbuf = (StaticDeviceData *)cyberstat;
|
||
|
memset(pbuf, 0, sizeof (StaticDeviceData));
|
||
|
|
||
|
// Use DPMI call 300h to issue mouse interrupt
|
||
|
memset(&RMI, 0, sizeof(RMI));
|
||
|
RMI.EAX = 0x53C1; // SWIFT: Get Static Device Data
|
||
|
RMI.ES = segment;
|
||
|
RMI.EDX = 0;
|
||
|
memset(&sregs, 0, sizeof (sregs));
|
||
|
regs.w.ax = 0x0300; // DPMI: simulate interrupt
|
||
|
regs.w.bx = MOUSE_INT;
|
||
|
regs.w.cx = 0;
|
||
|
regs.x.edi = FP_OFF(&RMI);
|
||
|
sregs.es = FP_SEG(&RMI);
|
||
|
int386x( DPMI_INT, ®s, ®s, &sregs );
|
||
|
|
||
|
if ((short)RMI.EAX != 1)
|
||
|
{
|
||
|
// SWIFT functions not present
|
||
|
tprintf("CyberMan: Wrong mouse driver - no SWIFT support (AX=%04x).\n",
|
||
|
(unsigned)(short)RMI.EAX);
|
||
|
}
|
||
|
else
|
||
|
if (pbuf->deviceType != DEVTYPE_CYBERMAN)
|
||
|
{
|
||
|
// no SWIFT device, or not CyberMan
|
||
|
if (pbuf->deviceType == 0)
|
||
|
{
|
||
|
tprintf("CyberMan: no SWIFT device connected.\n");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tprintf("CyberMan: SWIFT device is not a CyberMan! (type=%d)\n",
|
||
|
pbuf->deviceType);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tprintf("CyberMan: CyberMan %d.%02d connected.\n",
|
||
|
pbuf->majorVersion, pbuf->minorVersion);
|
||
|
isCyberPresent = 1;
|
||
|
mousepresent = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
===============
|
||
|
=
|
||
|
= I_ReadCyberCmds
|
||
|
=
|
||
|
===============
|
||
|
*/
|
||
|
|
||
|
|
||
|
int oldpos;
|
||
|
|
||
|
void I_ReadCyberCmd (ticcmd_t *cmd)
|
||
|
{
|
||
|
int delta;
|
||
|
|
||
|
// Use DPMI call 300h to issue mouse interrupt
|
||
|
memset(&RMI, 0, sizeof(RMI));
|
||
|
RMI.EAX = 0x5301; // SWIFT: Get Position and Buttons
|
||
|
RMI.ES = segment;
|
||
|
RMI.EDX = 0;
|
||
|
memset(&sregs, 0, sizeof (sregs));
|
||
|
regs.w.ax = 0x0300; // DPMI: simulate interrupt
|
||
|
regs.w.bx = MOUSE_INT;
|
||
|
regs.w.cx = 0;
|
||
|
regs.x.edi = FP_OFF(&RMI);
|
||
|
sregs.es = FP_SEG(&RMI);
|
||
|
int386x( DPMI_INT, ®s, ®s, &sregs );
|
||
|
|
||
|
if (cyberstat->y < -7900)
|
||
|
cmd->forwardmove = 0xc800/2048;
|
||
|
else if (cyberstat->y > 7900)
|
||
|
cmd->forwardmove = -0xc800/2048;
|
||
|
|
||
|
if (cyberstat->buttons & 4)
|
||
|
cmd->buttons |= BT_ATTACK;
|
||
|
if (cyberstat->buttons & 2)
|
||
|
cmd->buttons |= BT_USE;
|
||
|
|
||
|
delta = cyberstat->x - oldpos;
|
||
|
oldpos = cyberstat->x;
|
||
|
|
||
|
if (cyberstat->buttons & 1)
|
||
|
{ // strafe
|
||
|
if (cyberstat->x < -7900)
|
||
|
cmd->sidemove = -0xc800/2048;
|
||
|
else if (cyberstat->x > 7900)
|
||
|
cmd->sidemove = 0xc800/2048;
|
||
|
else
|
||
|
cmd->sidemove = delta*40/2048;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (cyberstat->x < -7900)
|
||
|
cmd->angleturn = 0x280;
|
||
|
else if (cyberstat->x > 7900)
|
||
|
cmd->angleturn = -0x280;
|
||
|
else
|
||
|
cmd->angleturn = -delta*0xa/16;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void I_Tactile (int on, int off, int total)
|
||
|
{
|
||
|
if (!isCyberPresent)
|
||
|
return;
|
||
|
|
||
|
on /= 5;
|
||
|
off /= 5;
|
||
|
total /= 40;
|
||
|
if (on > 255)
|
||
|
on = 255;
|
||
|
if (off > 255)
|
||
|
off = 255;
|
||
|
if (total > 255)
|
||
|
total = 255;
|
||
|
|
||
|
memset(&RMI, 0, sizeof(RMI));
|
||
|
RMI.EAX = 0x5330; // SWIFT: Get Position and Buttons
|
||
|
RMI.EBX = on*256+off;
|
||
|
RMI.ECX = total;
|
||
|
memset(&sregs, 0, sizeof (sregs));
|
||
|
regs.w.ax = 0x0300; // DPMI: simulate interrupt
|
||
|
regs.w.bx = MOUSE_INT;
|
||
|
regs.w.cx = 0;
|
||
|
regs.x.edi = FP_OFF(&RMI);
|
||
|
sregs.es = FP_SEG(&RMI);
|
||
|
int386x( DPMI_INT, ®s, ®s, &sregs );
|
||
|
}
|