heretic/Heretic Source/I_CYBER.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, &regs, &regs, &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, &regs, &regs, &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, &regs, &regs, &sregs );
}