1
0
Fork 0
forked from len0rd/rockbox
foxbox/apps/plugins/sdl/progs/duke3d/Game/src/control.c
Franklin Wei a855d62025 Port of Duke Nukem 3D
This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL
for Rockbox.

Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9
2017-12-23 21:01:26 -05:00

930 lines
18 KiB
C

//-------------------------------------------------------------------------
/*
Copyright (C) 1996, 2003 - 3D Realms Entertainment
This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
Duke Nukem 3D is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
aint32_t with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Original Source: 1996 - Todd Replogle
Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
*/
//-------------------------------------------------------------------------
#include "duke3d.h"
#include "control.h"
#include "mouse.h"
#include "joystick.h"
//***************************************************************************
//
// GLOBALS
//
//***************************************************************************
// FIX_00018: Removed the "smoothmouse" option. This was just a bad fix. Mouse is now faster,
// smoother.
// extern int g_CV_EnableSmoothMouse;
// extern int g_CV_SmoothMouseSensX;
// extern int g_CV_SmoothMouseSensY;
uint32 CONTROL_RudderEnabled;
boolean CONTROL_MousePresent;
boolean CONTROL_JoysPresent[ MaxJoys ];
boolean CONTROL_MouseEnabled;
boolean CONTROL_JoystickEnabled;
byte CONTROL_JoystickPort;
uint32 CONTROL_MouseButtonState1;
uint32 CONTROL_MouseButtonState2;
// FIX_00019: DigitalAxis Handling now supported. (cool for medkit use)
uint32 CONTROL_MouseDigitalAxisState1;
uint32 CONTROL_MouseDigitalAxisState2;
//uint32 CONTROL_ButtonHeldState1;
//uint32 CONTROL_ButtonHeldState2;
uint32 CONTROL_JoyButtonState1;
uint32 CONTROL_JoyButtonState2;
uint32 CONTROL_JoyHatState1; //[MAXJOYHATS];
uint32 CONTROL_JoyHatState2; //[MAXJOYHATS];
static short mouseButtons = 0;
static short lastmousebuttons = 0;
static short joyHats[MAXJOYHATS];
static short lastjoyHats[MAXJOYHATS];
static int32 mousePositionX = 0;
static int32 mousePositionY = 0;
static int32 mouseRelativeX = 0;
static int32 mouseRelativeY = 0;
//***************************************************************************
//
// FUNCTIONS
//
//***************************************************************************
// Joystick/Gamepad bindings
static int32 JoyAxisMapping[MAXJOYAXES];
static int32 JoyHatMapping[MAXJOYHATS][8];
static int32 JoyButtonMapping[MAXJOYBUTTONS];
static float JoyAnalogScale[MAXJOYAXES];
static int32 JoyAnalogDeadzone[MAXJOYAXES];
int ACTION(int i)
{
//Keyboard input
if( (KB_KeyDown[KeyMapping[i].key1]) ||
(KB_KeyDown[KeyMapping[i].key2])
)
{
return 1;
}
// Check mouse
if((ControllerType == controltype_keyboardandmouse) ||
(ControllerType == controltype_joystickandmouse))
{
//Mouse buttons
if ((i)>31)
{
if((CONTROL_MouseButtonState2>>( (i) - 32) ) & 1)
{
return 1;
}
}
else
{
if((CONTROL_MouseButtonState1>> (i) ) & 1)
{
return 1;
}
}
// FIX_00019: DigitalAxis Handling now supported. (cool for medkit use)
//Mouse Digital Axes
if ((i)>31)
{
if((CONTROL_MouseDigitalAxisState2>>( (i) - 32) ) & 1)
{
return 1;
}
}
else
{
if((CONTROL_MouseDigitalAxisState1>> (i) ) & 1)
{
return 1;
}
}
}
// Check joystick
if((ControllerType == controltype_keyboardandjoystick) ||
(ControllerType == controltype_joystickandmouse)
)
{
if ((i)>31)
{
// Check the joystick
if( (CONTROL_JoyButtonState2 >> (i - 32)) & 1)
{
return 1;
}
// Check the hats
if( (CONTROL_JoyHatState2 >> (i - 32)) & 1)
{
return 1;
}
}
else
{
if( (CONTROL_JoyButtonState1 >> i) & 1)
{
return 1;
}
// Check the hats
if( (CONTROL_JoyHatState1 >> i) & 1)
{
return 1;
}
}
}
return 0;
}
int RESET_ACTION(int i)
{
KB_KeyDown[KeyMapping[i].key1] = 0;
KB_KeyDown[KeyMapping[i].key2] = 0;
return 0;
}
static void SETMOUSEBUTTON(int i)
{
//CONTROL_MouseButtonState1 |= (1<<i);
int b;
if (i < 32)
{
b = 1 << i;
CONTROL_MouseButtonState1 |= b;
}
else
{
i -= 32;
b = 1 << i;
CONTROL_MouseButtonState2 |= b;
}
}
void RESMOUSEBUTTON(int i)
{
//CONTROL_MouseButtonState1 &= ~(1<<i);
int b;
if (i < 32) {
b = 1 << i;
CONTROL_MouseButtonState1 &= ~b;
} else {
i -= 32;
b = 1 << i;
CONTROL_MouseButtonState2 &= ~b;
}
}
// FIX_00019: DigitalAxis Handling now supported. (cool for medkit use)
void SETMOUSEDIGITALAXIS(int i)
{
int b;
if (i<0)
return;
if (i < 32)
{
b = 1 << i;
CONTROL_MouseDigitalAxisState1 |= b;
}
else
{
i -= 32;
b = 1 << i;
CONTROL_MouseDigitalAxisState2 |= b;
}
}
void RESMOUSEDIGITALAXIS(int i)
{
int b;
if (i<0)
return;
if (i < 32)
{
b = 1 << i;
CONTROL_MouseDigitalAxisState1 &= ~b;
}
else
{
i -= 32;
b = 1 << i;
CONTROL_MouseDigitalAxisState2 &= ~b;
}
}
static void SETJOYBUTTON(int i)
{
//CONTROL_JoyButtonState |= (1<<i);
int b;
if (i < 32)
{
b = 1 << i;
CONTROL_JoyButtonState1 |= b;
}
else
{
i -= 32;
b = 1 << i;
CONTROL_JoyButtonState2 |= b;
}
}
static void RESJOYBUTTON(int i)
{
int b;
if (i < 32) {
b = 1 << i;
CONTROL_JoyButtonState1 &= ~b;
} else {
i -= 32;
b = 1 << i;
CONTROL_JoyButtonState2 &= ~b;
}
}
static void SETHATBUTTON(int i)
{
//CONTROL_JoyHatState1 |= (1<<i);
int b;
if (i < 32)
{
b = 1 << i;
CONTROL_JoyHatState1 |= b;
}
else
{
i -= 32;
b = 1 << i;
CONTROL_JoyHatState2 |= b;
}
}
static void RESHATBUTTON(int i)
{
//CONTROL_JoyHatState1 &= ~(1<<i);
int b;
if (i < 32) {
b = 1 << i;
CONTROL_JoyHatState1 &= ~b;
} else {
i -= 32;
b = 1 << i;
CONTROL_JoyHatState2 &= ~b;
}
}
void CONTROL_UpdateKeyboardState(int key, int pressed)
{
/*
if(pressed)
{
CONTROL_KeyStates[key] = 1;
}
else
{
CONTROL_KeyStates[key] = 0;
}
*/
/*
int i;
for (i = 0; i < MAXGAMEBUTTONS; i++)
{
if (KeyMapping[i].key_active == false)
{
continue;
}
if (KeyMapping[i].key1 == key ||
KeyMapping[i].key2 == key)
{
if (pressed)
{
SETBUTTON(i);
}
else
{
RESBUTTON(i);
}
}
}
*/
}
void CONTROL_MapKey( int32 which, kb_scancode key1, kb_scancode key2 )
{
// FIX_00020: Protect you from assigning a function to the ESC key through duke3d.cfg
if(key1==sc_Escape || key2==sc_Escape)
{
if(key1==sc_Escape)
key1=0;
else
key2=0;
printf("Discarding ESCAPE key for function : %s\n", gamefunctions[which]);
}
if(key1 || key2)
KeyMapping[which].key_active = true;
else
KeyMapping[which].key_active = false;
KeyMapping[which].key1 = key1;
KeyMapping[which].key2 = key2;
}
void CONTROL_MapButton
(
int32 whichfunction,
int32 whichbutton,
boolean clicked_or_doubleclicked
)
{
if(clicked_or_doubleclicked)
return; // TODO
if(whichbutton < 0 || whichbutton >= MAXMOUSEBUTTONS)
return;
MouseMapping[whichbutton] = whichfunction;
}
void CONTROL_MapJoyButton(int32 whichfunction, int32 whichbutton, boolean doubleclicked)
{
if(whichbutton < 0 || whichbutton >= MAXJOYBUTTONS)
{
return;
}
if(doubleclicked)
return; // TODO
JoyButtonMapping[whichbutton] = whichfunction;
}
void CONTROL_MapJoyHat(int32 whichfunction, int32 whichhat, int32 whichvalue)
{
if(whichhat < 0 || whichhat >= MAXJOYHATS)
{
return;
}
JoyHatMapping[whichhat][whichvalue] = whichfunction;
}
void CONTROL_DefineFlag( int32 which, boolean toggle )
{
// STUBBED("CONTROL_DefineFlag");
}
boolean CONTROL_FlagActive( int32 which )
{
STUBBED("CONTROL_FlagActive");
return false;
}
void CONTROL_ClearAssignments( void )
{
STUBBED("CONTROL_ClearAssignments");
}
void CONTROL_GetUserInput( UserInput *info )
{
STUBBED("CONTROL_GetUserInput");
}
void CONTROL_GetInput( ControlInfo *info )
{
int32 sens_X = CONTROL_GetMouseSensitivity_X();
int32 sens_Y = CONTROL_GetMouseSensitivity_Y();
int32 mx = 0, my = 0;
int i, j;
memset(info, '\0', sizeof (ControlInfo));
//info->dx = info->dz = 0;
_handle_events(); // get the very last mouse position before reading it.
MOUSE_GetDelta(&mx,&my);
//GetCursorPos(&point);
// SDL_GetMouseState(&x, &y);
// SDL_WarpMouse(160, 100);
//mx = (-xx+point.x)<<2;
//my = (-yy+point.y)<<2;
//xx=point.x; yy=point.y;
info->dyaw = (mx * sens_X);
switch(ControllerType)
{
case controltype_keyboardandjoystick:
{
}
break;
case controltype_joystickandmouse:
// Not sure what I was thinking here...
// Commented this out because it totally breaks smooth mouse etc...
/*
{
// Mouse should use pitch instead of forward movement.
info->dpitch = my * sens*2;
}
break;
*/
default:
{
// If mouse aim is active
if( myaimmode )
{
// FIX_00052: Y axis for the mouse is now twice as sensitive as before
info->dpitch = (my * sens_Y * 2);
}
else
{
info->dz = (my * sens_Y * 2);
}
}
break;
}
// TODO: releasing the mouse button does not honor if a keyboard key with
// the same function is still pressed. how should it?
for(i=0; i<MAXMOUSEBUTTONS;++i)
{
if( MouseMapping[i] != -1 )
{
if(!(lastmousebuttons & (1<<i)) && mouseButtons & (1<<i))
{
SETMOUSEBUTTON(MouseMapping[i]); //MouseMapping[i]
//printf("mouse button: %d\n", i);
}
else if(lastmousebuttons & (1<<i) && !(mouseButtons & (1<<i)))
{
RESMOUSEBUTTON(MouseMapping[i]);//MouseMapping[i]
}
}
}
lastmousebuttons = mouseButtons;
// FIX_00019: DigitalAxis Handling now supported. (cool for medkit use)
// update digital axis
RESMOUSEDIGITALAXIS(MouseDigitalAxeMapping[0][0]);
RESMOUSEDIGITALAXIS(MouseDigitalAxeMapping[0][1]);
RESMOUSEDIGITALAXIS(MouseDigitalAxeMapping[1][0]);
RESMOUSEDIGITALAXIS(MouseDigitalAxeMapping[1][1]);
if (mx < 0)
{
SETMOUSEDIGITALAXIS(MouseDigitalAxeMapping[0][0]);
}
else if (mx > 0)
{
SETMOUSEDIGITALAXIS(MouseDigitalAxeMapping[0][1]);
}
if (my < 0)
{
SETMOUSEDIGITALAXIS(MouseDigitalAxeMapping[1][0]);
}
else if (my > 0)
{
SETMOUSEDIGITALAXIS(MouseDigitalAxeMapping[1][1]);
}
// update stick state.
if ((CONTROL_JoystickEnabled) && (_joystick_update()))
{
// Check the hats
JOYSTICK_UpdateHats();
// TODO: make this NOT use the BUTTON() system for storing the hat input. (requires much game code changing)
for(i=0; i<MAXJOYHATS; i++)
{
for(j=0; j<8; j++)
{
if(!(lastjoyHats[i] & (1<<j)) && (joyHats[i] & (1<<j)))
{
SETHATBUTTON(JoyHatMapping[i][j]);
}
else if((lastjoyHats[i] & (1<<j)) && !(joyHats[i] & (1<<j)))
{
RESHATBUTTON(JoyHatMapping[i][j]);
}
}
lastjoyHats[i] = joyHats[i];
}
for(i=0; i<MAXJOYAXES;i++)
{
switch(JoyAxisMapping[i])
{
case analog_turning:
{
info->dyaw += (int32)((float)CONTROL_FilterDeadzone
(
_joystick_axis(i),
JoyAnalogDeadzone[i]
)
* JoyAnalogScale[i]
);
}
break;
case analog_strafing:
{
info->dx += (int32)((float)CONTROL_FilterDeadzone
(
_joystick_axis(i),
JoyAnalogDeadzone[i]
)
* JoyAnalogScale[i]
);
//printf("Joy %d = %d\n", i, info->dx);
}
break;
case analog_lookingupanddown:
info->dpitch += (int32)((float)CONTROL_FilterDeadzone
(
_joystick_axis(i),
JoyAnalogDeadzone[i]
)
* JoyAnalogScale[i]
);
break;
case analog_elevation: //STUB
break;
case analog_rolling: //STUB
break;
case analog_moving:
{
info->dz += (int32)((float)CONTROL_FilterDeadzone
(
_joystick_axis(i),
JoyAnalogDeadzone[i]
)
* JoyAnalogScale[i]
);
}
break;
default:
break;
}
}
// !!! FIXME: Do this.
//SETBUTTON based on _joystick_button().
for(i=0; i<MAXJOYBUTTONS;++i)
{
if(_joystick_button(i))
{
SETJOYBUTTON(JoyButtonMapping[i]);
}
else
{
RESJOYBUTTON(JoyButtonMapping[i]);
}
}
}
}
void CONTROL_ClearAction( int32 whichbutton )
{
//RESBUTTON(whichbutton);
KB_KeyDown[KeyMapping[whichbutton].key1] = 0;
KB_KeyDown[KeyMapping[whichbutton].key2] = 0;
RESJOYBUTTON(whichbutton);
RESHATBUTTON(whichbutton);
RESMOUSEDIGITALAXIS(whichbutton);
}
void CONTROL_ClearUserInput( UserInput *info )
{
STUBBED("CONTROL_ClearUserInput");
}
void CONTROL_WaitRelease( void )
{
STUBBED("CONTROL_WaitRelease");
}
void CONTROL_Ack( void )
{
STUBBED("CONTROL_Ack");
}
void CONTROL_CenterJoystick
(
void ( *CenterCenter )( void ),
void ( *UpperLeft )( void ),
void ( *LowerRight )( void ),
void ( *CenterThrottle )( void ),
void ( *CenterRudder )( void )
)
{
STUBBED("CONTROL_CenterJoystick");
}
int32 CONTROL_GetMouseSensitivity_X( void )
{
return mouseSensitivity_X;
}
void CONTROL_SetMouseSensitivity_X( int32 newsensitivity )
{
mouseSensitivity_X = newsensitivity;
}
// FIX_00014: Added Y cursor setup for mouse sensitivity in the menus
int32 CONTROL_GetMouseSensitivity_Y( void )
{
return mouseSensitivity_Y;
}
void CONTROL_SetMouseSensitivity_Y( int32 newsensitivity )
{
mouseSensitivity_Y = newsensitivity;
}
void CONTROL_Startup
(
controltype which,
int32 ( *TimeFunction )( void ),
int32 ticspersecond
)
{
int i;
// Init the joystick
_joystick_init();
for(i=0; i < MAXJOYHATS; i++)
{
joyHats[i] = 0;
lastjoyHats[i] = 0;
}
CONTROL_MouseButtonState1 = 0;
CONTROL_MouseButtonState2 = 0;
CONTROL_MouseDigitalAxisState1 = 0;
CONTROL_MouseDigitalAxisState2 = 0;
CONTROL_JoyButtonState1 = 0;
CONTROL_JoyButtonState2 = 0;
CONTROL_JoyHatState1 = 0;
CONTROL_JoyHatState2 = 0;
}
void CONTROL_Shutdown( void )
{
_joystick_deinit();
}
void CONTROL_MapAnalogAxis
(
int32 whichaxis,
int32 whichanalog
)
{
//STUBBED("CONTROL_MapAnalogAxis");
if(whichaxis < MAXJOYAXES)
{
JoyAxisMapping[whichaxis] = whichanalog;
}
}
// FIX_00019: DigitalAxis Handling now supported. (cool for medkit use)
void CONTROL_MapDigitalAxis
(
int32 whichaxis,
int32 whichfunction,
int32 direction
)
{
if(whichaxis < 0 || whichaxis >= MAXMOUSEAXES || direction < 0 || direction >= 2)
return;
MouseDigitalAxeMapping[whichaxis][direction] = whichfunction;
}
void CONTROL_SetAnalogAxisScale
(
int32 whichaxis,
float axisscale
)
{
if(whichaxis < MAXJOYAXES)
{
// Set it... make sure we don't let them set it to 0.. div by 0 is bad.
JoyAnalogScale[whichaxis] = (axisscale == 0) ? 1.0f : axisscale;
}
}
void CONTROL_SetAnalogAxisDeadzone
(
int32 whichaxis,
int32 axisdeadzone
)
{
if(whichaxis < MAXJOYAXES)
{
// Set it...
JoyAnalogDeadzone[whichaxis] = axisdeadzone;
}
}
int32 CONTROL_FilterDeadzone
(
int32 axisvalue,
int32 axisdeadzone
)
{
if((axisvalue < axisdeadzone) && (axisvalue > -axisdeadzone))
{
return 0;
}
return axisvalue;
}
int32 CONTROL_GetFilteredAxisValue(int32 axis)
{
return (int32)((float)CONTROL_FilterDeadzone
(
_joystick_axis(axis),
JoyAnalogDeadzone[axis]
)
* JoyAnalogScale[axis]
);
}
void CONTROL_PrintAxes( void )
{
STUBBED("CONTROL_PrintAxes");
}
boolean MOUSE_Init( void )
{
memset(MouseMapping,-1,sizeof(MouseMapping));
memset(MouseDigitalAxeMapping, -1, sizeof(MouseDigitalAxeMapping));
return true;
}
void MOUSE_Shutdown( void )
{
STUBBED("MOUSE_Shutdown");
}
void MOUSE_ShowCursor( void )
{
STUBBED("MOUSE_ShowCursor");
}
void MOUSE_HideCursor( void )
{
STUBBED("MOUSE_HideCursor");
}
static void updateMouse(void)
{
// this is in buildengine.
short x, y;
getmousevalues(&x, &y, &mouseButtons);
mouseRelativeX += x;
mouseRelativeY += y;
mousePositionX += x;
mousePositionY += y;
}
int32 MOUSE_GetButtons( void )
{
//updateMouse();
return ((int32) mouseButtons);
}
void MOUSE_GetPosition( int32*x, int32*y )
{
if (x) *x = mousePositionX;
if (y) *y = mousePositionY;
}
void MOUSE_GetDelta( int32*x, int32*y )
{
updateMouse();
if (x) *x = mouseRelativeX;
if (y) *y = mouseRelativeY;
mouseRelativeX = 0;
mouseRelativeY = 0;
}
void JOYSTICK_UpdateHats()
{
int i;
for(i=0; i<MAXJOYHATS; i++)
{
//for(j=0; j<8; j++)
//{
joyHats[i] = _joystick_hat(i);
//}
}
}