WIP changes to lots of stuff..

This commit is contained in:
Simon 2020-03-05 22:30:08 +00:00
parent 442b91479e
commit 779178f798
42 changed files with 4117 additions and 187 deletions

View file

@ -0,0 +1 @@
QzDoom

View file

@ -17,10 +17,10 @@ android {
// override app plugin abiFilters for both 32 and 64-bit support
externalNativeBuild {
ndk {
abiFilters 'armeabi-v7a'
abiFilters 'arm64-v8a'
}
ndkBuild {
abiFilters 'armeabi-v7a'
abiFilters 'arm64-v8a'
}
}
minSdkVersion 24

View file

@ -25,7 +25,6 @@ Copyright : Copyright 2015 Oculus VR, LLC. All Rights reserved.
#include "argtable3.h"
#include "VrInput.h"
#include "VrCvars.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
@ -48,7 +47,30 @@ Copyright : Copyright 2015 Oculus VR, LLC. All Rights reserved.
#include "VrCompositor.h"
#include "VrInput.h"
//#include "../qzdoom/src/client/header/client.h"
//Define all variables here that were externs in the VrCommon.h
bool qzdoom_initialised;
long long global_time;
float playerHeight;
float playerYaw;
bool showingScreenLayer;
float vrFOV;
vec3_t worldPosition;
vec3_t hmdPosition;
vec3_t hmdorientation;
vec3_t positionDeltaThisFrame;
vec3_t weaponangles;
vec3_t weaponoffset;
bool weaponStabilised;
float vr_weapon_pitchadjust;
bool vr_walkdirection;
float vr_snapturn_angle;
float doomYawDegrees;
vec3_t flashlightangles;
vec3_t flashlightoffset;
int ducked;
bool player_moving;
#if !defined( EGL_OPENGL_ES3_BIT_KHR )
#define EGL_OPENGL_ES3_BIT_KHR 0x0040
@ -148,7 +170,7 @@ void setUseScreenLayer(bool use)
bool useScreenLayer()
{
return useVirtualScreen || forceVirtualScreen;
return useVirtualScreen || showingScreenLayer;
}
static void UnEscapeQuotes( char *arg )
@ -618,34 +640,17 @@ void ovrFramebuffer_ClearEdgeTexels( ovrFramebuffer * frameBuffer )
// Clear to fully opaque black.
GL( /*gles_*/glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ) );
//Glide comfort mask in and out
static float currentVLevel = 0.0f;
if (player_moving)
{
// if (currentVLevel < vr_comfort_mask->value)
// currentVLevel += vr_comfort_mask->value * 0.05;
} else{
// if (currentVLevel > 0.0f)
// currentVLevel -= vr_comfort_mask->value * 0.05;
}
bool useMask = (currentVLevel > 0.0f && currentVLevel <= 1.0f);
float width = useMask ? (frameBuffer->Width / 2.0f) * currentVLevel : 1;
float height = useMask ? (frameBuffer->Height / 2.0f) * currentVLevel : 1;
// bottom
GL( /*gles_*/glScissor( 0, 0, frameBuffer->Width, width ) );
GL( /*gles_*/glScissor( 0, 0, frameBuffer->Width, 1 ) );
GL( /*gles_*/glClear( GL_COLOR_BUFFER_BIT ) );
// top
GL( /*gles_*/glScissor( 0, frameBuffer->Height - height, frameBuffer->Width, height ) );
GL( /*gles_*/glScissor( 0, frameBuffer->Height - 1, frameBuffer->Width, 1 ) );
GL( /*gles_*/glClear( GL_COLOR_BUFFER_BIT ) );
// left
GL( /*gles_*/glScissor( 0, 0, width, frameBuffer->Height ) );
GL( /*gles_*/glScissor( 0, 0, 1, frameBuffer->Height ) );
GL( /*gles_*/glClear( GL_COLOR_BUFFER_BIT ) );
// right
GL( /*gles_*/glScissor( frameBuffer->Width - width, 0, width, frameBuffer->Height ) );
GL( /*gles_*/glScissor( frameBuffer->Width - 1, 0, 1, frameBuffer->Height ) );
GL( /*gles_*/glClear( GL_COLOR_BUFFER_BIT ) );
@ -1292,7 +1297,9 @@ void VR_Init()
//init randomiser
srand(time(NULL));
//Create Cvars
//Initialise our cvar holders
vr_weapon_pitchadjust = -20.0;
/* vr_snapturn_angle = Cvar_Get( "vr_snapturn_angle", "45", CVAR_ARCHIVE);
vr_positional_factor = Cvar_Get( "vr_positional_factor", "2000", CVAR_ARCHIVE);
vr_walkdirection = Cvar_Get( "vr_walkdirection", "0", CVAR_ARCHIVE);
@ -1302,7 +1309,6 @@ void VR_Init()
vr_weaponscale = Cvar_Get( "vr_weaponscale", "0.56", CVAR_ARCHIVE);
vr_weapon_stabilised = Cvar_Get( "vr_weapon_stabilised", "0.0", CVAR_LATCH);
vr_lasersight = Cvar_Get( "vr_lasersight", "0", CVAR_LATCH);
vr_comfort_mask = Cvar_Get( "vr_comfort_mask", "0.0", CVAR_ARCHIVE);
//The Engine (which is a derivative of Quake) uses a very specific unit size:
//Wolfenstein 3D, DOOM and QUAKE use the same coordinate/unit system:
@ -1706,22 +1712,22 @@ void incrementFrameIndex()
gAppState.FrameIndex);
}
void getTrackedRemotesOrientation() {//Get info for tracked remotes
void getTrackedRemotesOrientation(int vr_control_scheme) {//Get info for tracked remotes
acquireTrackedRemotesData(gAppState.Ovr, gAppState.DisplayTime);
//Call additional control schemes here
// switch ((int)vr_control_scheme->value)
switch ((int)vr_control_scheme)
{
// case RIGHT_HANDED_DEFAULT:
case RIGHT_HANDED_DEFAULT:
HandleInput_Default(&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new,
ovrButton_A, ovrButton_B, ovrButton_X, ovrButton_Y);
// break;
// case LEFT_HANDED_DEFAULT:
// HandleInput_Default(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new,
// &rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
// ovrButton_X, ovrButton_Y, ovrButton_A, ovrButton_B);
// break;
break;
case LEFT_HANDED_DEFAULT:
HandleInput_Default(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, &leftRemoteTracking_new,
&rightTrackedRemoteState_new, &rightTrackedRemoteState_old, &rightRemoteTracking_new,
ovrButton_X, ovrButton_Y, ovrButton_A, ovrButton_B);
break;
}
}
@ -1733,7 +1739,7 @@ void submitFrame(ovrSubmitFrameDescription2 *frameDesc)
//Need to replicate this code in gl_oculusquest.cpp
void vr_main()
{
{/*
if (!destroyed)
{
processHaptics();
@ -1750,6 +1756,7 @@ void vr_main()
// Hand over the eye images to the time warp.
submitFrame(&frameDesc);
}
*/
}
static void ovrAppThread_Create( ovrAppThread * appThread, JNIEnv * env, jobject activityObject, jclass activityClass )

View file

@ -27,34 +27,41 @@ extern "C"
#define ALOGV(...)
#endif
bool qzdoom_initialised;
extern bool qzdoom_initialised;
long long global_time;
extern long long global_time;
float playerHeight;
float playerYaw;
extern float playerHeight;
extern float playerYaw;
bool showingScreenLayer;
float vrFOV;
extern bool showingScreenLayer;
extern float vrFOV;
vec3_t worldPosition;
extern vec3_t worldPosition;
vec3_t hmdPosition;
vec3_t hmdorientation;
vec3_t positionDeltaThisFrame;
extern vec3_t hmdPosition;
extern vec3_t hmdorientation;
extern vec3_t positionDeltaThisFrame;
vec3_t weaponangles;
vec3_t weaponoffset;
extern vec3_t weaponangles;
extern vec3_t weaponoffset;
vec3_t flashlightangles;
vec3_t flashlightoffset;
extern bool weaponStabilised;
extern float vr_weapon_pitchadjust;
extern bool vr_walkdirection;
extern float vr_snapturn_angle;
extern float doomYawDegrees;
extern vec3_t flashlightangles;
extern vec3_t flashlightoffset;
#define DUCK_NOTDUCKED 0
#define DUCK_BUTTON 1
#define DUCK_CROUCHED 2
int ducked;
extern int ducked;
bool player_moving;
extern bool player_moving;
void shutdownVR();
@ -75,7 +82,7 @@ void setUseScreenLayer(bool use);
void processHaptics();
void getHMDOrientation(ovrTracking2 *tracking);
void getTrackedRemotesOrientation();
void getTrackedRemotesOrientation(int vr_control_scheme);
void incrementFrameIndex();

View file

@ -1,17 +0,0 @@
//#include <c_cvars.h>
//EXTERN_CVAR(Float, vr_snapturn_angle)
/*
cvar_t *vr_snapturn_angle;
cvar_t *vr_positional_factor;
cvar_t *vr_walkdirection;
cvar_t *vr_weapon_pitchadjust;
cvar_t *vr_lasersight;
cvar_t *vr_control_scheme;
cvar_t *vr_height_adjust;
cvar_t *vr_worldscale;
cvar_t *vr_weaponscale;
cvar_t *vr_weapon_stabilised;
cvar_t *vr_comfort_mask;
*/

View file

@ -15,16 +15,13 @@ Authors : Simon Brown
#include "VrInput.h"
//#include <doomtype.h>
//keys.h
//void Key_Event (int key, bool down, unsigned time);
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base);
void handleTrackedControllerButton(ovrInputStateTrackedRemote * trackedRemoteState, ovrInputStateTrackedRemote * prevTrackedRemoteState, uint32_t button, int key)
{
if ((trackedRemoteState->Buttons & button) != (prevTrackedRemoteState->Buttons & button))
{
//Key_Event(key, (trackedRemoteState->Buttons & button) != 0, global_time);
//Joy_GenerateButtonEvents();
}
}

View file

@ -14,27 +14,16 @@ Authors : Simon Brown
#include <VrApi_Types.h>
#include "VrInput.h"
#include "VrCvars.h"
//#include "../quake2/src/client/header/client.h"
//extern cvar_t *cl_forwardspeed;
//cvar_t *sv_cheats;
//extern cvar_t *vr_weapon_stabilised;
#include "doomkeys.h"
void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, ovrInputStateTrackedRemote *pDominantTrackedRemoteOld, ovrTracking* pDominantTracking,
ovrInputStateTrackedRemote *pOffTrackedRemoteNew, ovrInputStateTrackedRemote *pOffTrackedRemoteOld, ovrTracking* pOffTracking,
int domButton1, int domButton2, int offButton1, int offButton2 )
{
//Ensure handedness is set correctly
//Cvar_Set("hand", vr_control_scheme->value < 10 ? "0" : "1");
//Get the cvar
//sv_cheats = Cvar_Get("cheats", "0", CVAR_ARCHIVE);
/* static bool dominantGripPushed = false;
static bool dominantGripPushed = false;
static float dominantGripPushTime = 0.0f;
static bool inventoryManagementMode = false;
@ -44,17 +33,12 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
(pOffTrackedRemoteNew->Buttons & offButton2)) {
showingScreenLayer = !showingScreenLayer;
//Check we are in multiplayer
if (isMultiplayer()) {
sendButtonActionSimple("score");
}
}
//Menu button
handleTrackedControllerButton(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, ovrButton_Enter, K_ESCAPE);
handleTrackedControllerButton(&leftTrackedRemoteState_new, &leftTrackedRemoteState_old, ovrButton_Enter, KEY_ESCAPE);
if (cls.key_dest == key_menu)
/* if (cls.key_dest == key_menu)
{
int leftJoyState = (pOffTrackedRemoteNew->Joystick.x > 0.7f ? 1 : 0);
if (leftJoyState != (pOffTrackedRemoteOld->Joystick.x > 0.7f ? 1 : 0)) {
@ -77,7 +61,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
handleTrackedControllerButton(pDominantTrackedRemoteNew, pDominantTrackedRemoteOld, ovrButton_Trigger, K_ENTER);
handleTrackedControllerButton(pDominantTrackedRemoteNew, pDominantTrackedRemoteOld, domButton2, K_ESCAPE);
}
else
else */
{
float distance = sqrtf(powf(pOffTracking->HeadPose.Pose.Position.x - pDominantTracking->HeadPose.Pose.Position.x, 2) +
powf(pOffTracking->HeadPose.Pose.Position.y - pDominantTracking->HeadPose.Pose.Position.y, 2) +
@ -91,12 +75,12 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
{
if (distance < 0.50f)
{
Cvar_ForceSet("vr_weapon_stabilised", "1.0");
weaponStabilised = true;
}
}
else
{
Cvar_ForceSet("vr_weapon_stabilised", "0.0");
weaponStabilised = false;
}
}
@ -109,19 +93,19 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
{
vec2_t v;
rotateAboutOrigin(-weaponoffset[0], weaponoffset[2], (cl.refdef.viewangles[YAW] - hmdorientation[YAW]), v);
// rotateAboutOrigin(-weaponoffset[0], weaponoffset[2], (doomYawDegrees - hmdorientation[YAW]), v);
weaponoffset[0] = v[0];
weaponoffset[2] = v[1];
}
//Set gun angles - We need to calculate all those we might need (including adjustments) for the client to then take its pick
const ovrQuatf quatRemote = pDominantTracking->HeadPose.Pose.Orientation;
QuatToYawPitchRoll(quatRemote, vr_weapon_pitchadjust->value, weaponangles);
weaponangles[YAW] += (cl.refdef.viewangles[YAW] - hmdorientation[YAW]);
QuatToYawPitchRoll(quatRemote, vr_weapon_pitchadjust, weaponangles);
weaponangles[YAW] += (doomYawDegrees - hmdorientation[YAW]);
weaponangles[ROLL] *= -1.0f;
if (vr_weapon_stabilised->value == 1.0f)
if (weaponStabilised)
{
float z = pOffTracking->HeadPose.Pose.Position.z - pDominantTracking->HeadPose.Pose.Position.z;
float x = pOffTracking->HeadPose.Pose.Position.x - pDominantTracking->HeadPose.Pose.Position.x;
@ -129,15 +113,13 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
float zxDist = length(x, z);
if (zxDist != 0.0f && z != 0.0f) {
VectorSet(weaponangles, -degrees(atanf(y / zxDist)), (cl.refdef.viewangles[YAW] - hmdorientation[YAW]) - degrees(atan2f(x, -z)), weaponangles[ROLL]);
VectorSet(weaponangles, -degrees(atanf(y / zxDist)), (doomYawDegrees - hmdorientation[YAW]) - degrees(atan2f(x, -z)), weaponangles[ROLL]);
}
}
if ((pDominantTrackedRemoteNew->Buttons & ovrButton_GripTrigger) !=
(pDominantTrackedRemoteOld->Buttons & ovrButton_GripTrigger)) {
sendButtonActionSimple("inven");
inventoryManagementMode = (pDominantTrackedRemoteNew->Buttons & ovrButton_GripTrigger) > 0;
}
}
@ -149,16 +131,16 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
flashlightoffset[2] = pOffTracking->HeadPose.Pose.Position.z - hmdPosition[2];
vec2_t v;
rotateAboutOrigin(-flashlightoffset[0], flashlightoffset[2], (cl.refdef.viewangles[YAW] - hmdorientation[YAW]), v);
rotateAboutOrigin(-flashlightoffset[0], flashlightoffset[2], (doomYawDegrees - hmdorientation[YAW]), v);
flashlightoffset[0] = v[0];
flashlightoffset[2] = v[1];
QuatToYawPitchRoll(pOffTracking->HeadPose.Pose.Orientation, 15.0f, flashlightangles);
flashlightangles[YAW] += (cl.refdef.viewangles[YAW] - hmdorientation[YAW]);
flashlightangles[YAW] += (doomYawDegrees - hmdorientation[YAW]);
if (vr_walkdirection->value == 0) {
controllerYawHeading = -cl.refdef.viewangles[YAW] + flashlightangles[YAW];
if (vr_walkdirection == 0) {
controllerYawHeading = -doomYawDegrees + flashlightangles[YAW];
}
else
{
@ -175,7 +157,8 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
//This section corrects for the fact that the controller actually controls direction of movement, but we want to move relative to the direction the
//player is facing for positional tracking
float multiplier = (vr_positional_factor->value) / (cl_forwardspeed->value *
float vr_positional_factor = 1700;
float multiplier = (vr_positional_factor) / (1.0 *
((pOffTrackedRemoteNew->Buttons & ovrButton_Trigger) ? 1.5f : 1.0f));
vec2_t v;
@ -189,8 +172,8 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
positional_movementForward);
//Jump (B Button)
handleTrackedControllerButton(pDominantTrackedRemoteNew,
pDominantTrackedRemoteOld, domButton2, K_SPACE);
// handleTrackedControllerButton(pDominantTrackedRemoteNew,
// pDominantTrackedRemoteOld, domButton2, K_SPACE);
//We need to record if we have started firing primary so that releasing trigger will stop firing, if user has pushed grip
//in meantime, then it wouldn't stop the gun firing and it would get stuck
@ -272,12 +255,6 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
(pDominantTrackedRemoteOld->Buttons & ovrButton_Joystick)
&& (pDominantTrackedRemoteNew->Buttons & ovrButton_Joystick)) {
if (vr_lasersight->value != 0.0)
{
Cvar_ForceSet("vr_lasersight", "0.0");
} else {
Cvar_ForceSet("vr_lasersight", "1.0");
}
}
//Apply a filter and quadratic scaler so small movements are easier to make
@ -311,10 +288,6 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
(pOffTrackedRemoteOld->Buttons & ovrButton_Joystick)
&& (pOffTrackedRemoteNew->Buttons & ovrButton_Joystick)) {
//If cheats enabled, give all weapons/pickups to player
if (sv_cheats->value == 1.0f) {
Cbuf_AddText("give all\n");
}
}
@ -323,17 +296,17 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
static bool firingPrimary = false;
//Run
handleTrackedControllerButton(pOffTrackedRemoteNew,
pOffTrackedRemoteOld,
ovrButton_Trigger, K_SHIFT);
// handleTrackedControllerButton(pOffTrackedRemoteNew,
// pOffTrackedRemoteOld,
// ovrButton_Trigger, K_SHIFT);
static int increaseSnap = true;
if (pDominantTrackedRemoteNew->Joystick.x > 0.6f)
{
if (increaseSnap)
{
snapTurn -= vr_snapturn_angle->value;
if (vr_snapturn_angle->value > 10.0f) {
snapTurn -= vr_snapturn_angle;
if (vr_snapturn_angle > 10.0f) {
increaseSnap = false;
}
@ -351,10 +324,10 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
{
if (decreaseSnap)
{
snapTurn += vr_snapturn_angle->value;
snapTurn += vr_snapturn_angle;
//If snap turn configured for less than 10 degrees
if (vr_snapturn_angle->value > 10.0f) {
if (vr_snapturn_angle > 10.0f) {
decreaseSnap = false;
}
@ -369,7 +342,7 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew,
}
}
}
*/
//Save state
rightTrackedRemoteState_old = rightTrackedRemoteState_new;
leftTrackedRemoteState_old = leftTrackedRemoteState_new;

View file

@ -0,0 +1,201 @@
//
// Created by simon on 04/03/2020.
//
#ifndef QZDOOM_DOOMKEYS_H
#define QZDOOM_DOOMKEYS_H
//
// DOOM keyboard definition. Everything below 0x100 matches
// a mode 1 keyboard scan code.
//
#define KEY_PAUSE 0xc5 // DIK_PAUSE
#define KEY_RIGHTARROW 0xcd // DIK_RIGHT
#define KEY_LEFTARROW 0xcb // DIK_LEFT
#define KEY_UPARROW 0xc8 // DIK_UP
#define KEY_DOWNARROW 0xd0 // DIK_DOWN
#define KEY_ESCAPE 0x01 // DIK_ESCAPE
#define KEY_ENTER 0x1c // DIK_RETURN
#define KEY_SPACE 0x39 // DIK_SPACE
#define KEY_TAB 0x0f // DIK_TAB
#define KEY_F1 0x3b // DIK_F1
#define KEY_F2 0x3c // DIK_F2
#define KEY_F3 0x3d // DIK_F3
#define KEY_F4 0x3e // DIK_F4
#define KEY_F5 0x3f // DIK_F5
#define KEY_F6 0x40 // DIK_F6
#define KEY_F7 0x41 // DIK_F7
#define KEY_F8 0x42 // DIK_F8
#define KEY_F9 0x43 // DIK_F9
#define KEY_F10 0x44 // DIK_F10
#define KEY_F11 0x57 // DIK_F11
#define KEY_F12 0x58 // DIK_F12
#define KEY_GRAVE 0x29 // DIK_GRAVE
#define KEY_BACKSPACE 0x0e // DIK_BACK
#define KEY_EQUALS 0x0d // DIK_EQUALS
#define KEY_MINUS 0x0c // DIK_MINUS
#define KEY_LSHIFT 0x2A // DIK_LSHIFT
#define KEY_LCTRL 0x1d // DIK_LCONTROL
#define KEY_LALT 0x38 // DIK_LMENU
#define KEY_RSHIFT KEY_LSHIFT
#define KEY_RCTRL KEY_LCTRL
#define KEY_RALT KEY_LALT
#define KEY_INS 0xd2 // DIK_INSERT
#define KEY_DEL 0xd3 // DIK_DELETE
#define KEY_END 0xcf // DIK_END
#define KEY_HOME 0xc7 // DIK_HOME
#define KEY_PGUP 0xc9 // DIK_PRIOR
#define KEY_PGDN 0xd1 // DIK_NEXT
#define KEY_MOUSE1 0x100
#define KEY_MOUSE2 0x101
#define KEY_MOUSE3 0x102
#define KEY_MOUSE4 0x103
#define KEY_MOUSE5 0x104
#define KEY_MOUSE6 0x105
#define KEY_MOUSE7 0x106
#define KEY_MOUSE8 0x107
#define KEY_FIRSTJOYBUTTON 0x108
#define KEY_FIRSTJOY2BUTTON 0x128
#define KEY_FIRSTJOY3BUTTON 0x148
#define KEY_FIRSTJOY4BUTTON 0x168
#define KEY_JOY1 (KEY_FIRSTJOYBUTTON+0)
#define KEY_JOY2 (KEY_FIRSTJOYBUTTON+1)
#define KEY_JOY3 (KEY_FIRSTJOYBUTTON+2)
#define KEY_JOY4 (KEY_FIRSTJOYBUTTON+3)
#define KEY_JOY5 (KEY_FIRSTJOYBUTTON+4)
#define KEY_JOY6 (KEY_FIRSTJOYBUTTON+5)
#define KEY_JOY7 (KEY_FIRSTJOYBUTTON+6)
#define KEY_JOY8 (KEY_FIRSTJOYBUTTON+7)
#define KEY_LASTJOYBUTTON 0x187
#define KEY_JOYPOV1_UP 0x188
#define KEY_JOYPOV1_RIGHT 0x189
#define KEY_JOYPOV1_DOWN 0x18a
#define KEY_JOYPOV1_LEFT 0x18b
#define KEY_JOYPOV2_UP 0x18c
#define KEY_JOYPOV3_UP 0x190
#define KEY_JOYPOV4_UP 0x194
#define KEY_MWHEELUP 0x198
#define KEY_MWHEELDOWN 0x199
#define KEY_MWHEELRIGHT 0x19A
#define KEY_MWHEELLEFT 0x19B
#define KEY_JOYAXIS1PLUS 0x19C
#define KEY_JOYAXIS1MINUS 0x19D
#define KEY_JOYAXIS2PLUS 0x19E
#define KEY_JOYAXIS2MINUS 0x19F
#define KEY_JOYAXIS3PLUS 0x1A0
#define KEY_JOYAXIS3MINUS 0x1A1
#define KEY_JOYAXIS4PLUS 0x1A2
#define KEY_JOYAXIS4MINUS 0x1A3
#define KEY_JOYAXIS5PLUS 0x1A4
#define KEY_JOYAXIS5MINUS 0x1A5
#define KEY_JOYAXIS6PLUS 0x1A6
#define KEY_JOYAXIS6MINUS 0x1A7
#define KEY_JOYAXIS7PLUS 0x1A8
#define KEY_JOYAXIS7MINUS 0x1A9
#define KEY_JOYAXIS8PLUS 0x1AA
#define KEY_JOYAXIS8MINUS 0x1AB
#define NUM_JOYAXISBUTTONS 8
#define KEY_PAD_LTHUMB_RIGHT 0x1AC
#define KEY_PAD_LTHUMB_LEFT 0x1AD
#define KEY_PAD_LTHUMB_DOWN 0x1AE
#define KEY_PAD_LTHUMB_UP 0x1AF
#define KEY_PAD_RTHUMB_RIGHT 0x1B0
#define KEY_PAD_RTHUMB_LEFT 0x1B1
#define KEY_PAD_RTHUMB_DOWN 0x1B2
#define KEY_PAD_RTHUMB_UP 0x1B3
#define KEY_PAD_DPAD_UP 0x1B4
#define KEY_PAD_DPAD_DOWN 0x1B5
#define KEY_PAD_DPAD_LEFT 0x1B6
#define KEY_PAD_DPAD_RIGHT 0x1B7
#define KEY_PAD_START 0x1B8
#define KEY_PAD_BACK 0x1B9
#define KEY_PAD_LTHUMB 0x1BA
#define KEY_PAD_RTHUMB 0x1BB
#define KEY_PAD_LSHOULDER 0x1BC
#define KEY_PAD_RSHOULDER 0x1BD
#define KEY_PAD_LTRIGGER 0x1BE
#define KEY_PAD_RTRIGGER 0x1BF
#define KEY_PAD_A 0x1C0
#define KEY_PAD_B 0x1C1
#define KEY_PAD_X 0x1C2
#define KEY_PAD_Y 0x1C3
#define KEY_JOY2POV1_UP 0x1C4
#define KEY_JOY2POV2_UP 0x1C8
#define KEY_JOY2POV3_UP 0x1CC
#define KEY_JOY2POV4_UP 0x1D0
#define KEY_JOY3POV1_UP 0x1D4
#define KEY_JOY3POV2_UP 0x1D8
#define KEY_JOY3POV3_UP 0x1DC
#define KEY_JOY3POV4_UP 0x1E0
#define KEY_JOY4POV1_UP 0x1E4
#define KEY_JOY4POV2_UP 0x1E8
#define KEY_JOY4POV3_UP 0x1EC
#define KEY_JOY4POV4_UP 0x1F0
#define KEY_JOY2AXIS1PLUS 0x1F4
#define KEY_JOY2AXIS1MINUS 0x1F5
#define KEY_JOY2AXIS2PLUS 0x1F6
#define KEY_JOY2AXIS2MINUS 0x1F7
#define KEY_JOY2AXIS3PLUS 0x1F8
#define KEY_JOY2AXIS3MINUS 0x1F9
#define KEY_JOY2AXIS4PLUS 0x1FA
#define KEY_JOY2AXIS4MINUS 0x1FB
#define KEY_JOY2AXIS5PLUS 0x1FC
#define KEY_JOY2AXIS5MINUS 0x1FD
#define KEY_JOY2AXIS6PLUS 0x1FE
#define KEY_JOY2AXIS6MINUS 0x1FF
#define KEY_JOY2AXIS7PLUS 0x200
#define KEY_JOY2AXIS7MINUS 0x201
#define KEY_JOY2AXIS8PLUS 0x202
#define KEY_JOY2AXIS8MINUS 0x203
#define KEY_JOY3AXIS1PLUS 0x204
#define KEY_JOY3AXIS1MINUS 0x205
#define KEY_JOY3AXIS2PLUS 0x206
#define KEY_JOY3AXIS2MINUS 0x207
#define KEY_JOY3AXIS3PLUS 0x208
#define KEY_JOY3AXIS3MINUS 0x209
#define KEY_JOY3AXIS4PLUS 0x20A
#define KEY_JOY3AXIS4MINUS 0x20B
#define KEY_JOY3AXIS5PLUS 0x20C
#define KEY_JOY3AXIS5MINUS 0x20D
#define KEY_JOY3AXIS6PLUS 0x20E
#define KEY_JOY3AXIS6MINUS 0x20F
#define KEY_JOY3AXIS7PLUS 0x210
#define KEY_JOY3AXIS7MINUS 0x211
#define KEY_JOY3AXIS8PLUS 0x212
#define KEY_JOY3AXIS8MINUS 0x213
#define KEY_JOY4AXIS1PLUS 0x214
#define KEY_JOY4AXIS1MINUS 0x215
#define KEY_JOY4AXIS2PLUS 0x216
#define KEY_JOY4AXIS2MINUS 0x217
#define KEY_JOY4AXIS3PLUS 0x218
#define KEY_JOY4AXIS3MINUS 0x219
#define KEY_JOY4AXIS4PLUS 0x21A
#define KEY_JOY4AXIS4MINUS 0x21B
#define KEY_JOY4AXIS5PLUS 0x21C
#define KEY_JOY4AXIS5MINUS 0x21D
#define KEY_JOY4AXIS6PLUS 0x21E
#define KEY_JOY4AXIS6MINUS 0x21F
#define KEY_JOY4AXIS7PLUS 0x220
#define KEY_JOY4AXIS7MINUS 0x221
#define KEY_JOY4AXIS8PLUS 0x222
#define KEY_JOY4AXIS8MINUS 0x223
#define NUM_KEYS 0x224
#endif //QZDOOM_DOOMKEYS_H

View file

@ -44,7 +44,7 @@ LOCAL_C_INCLUDES := \
$(GZDOOM_TOP_PATH)/src/scripting \
$(GZDOOM_TOP_PATH)/src/scripting/vm \
$(GZDOOM_TOP_PATH)/src/posix \
$(GZDOOM_TOP_PATH)/src/posix\sdl \
$(GZDOOM_TOP_PATH)/src/posix\oculusquest \
$(SDL_INCLUDE_PATHS) \
$(SUPPORT_LIBS)/fluidsynth-lite/include \
$(SUPPORT_LIBS)/openal/include/AL \
@ -71,17 +71,17 @@ PLAT_POSIX_SOURCES = \
posix/i_cd.cpp \
posix/i_steam.cpp
PLAT_SDL_SOURCES = \
posix/sdl/crashcatcher.c \
posix/sdl/hardware.cpp \
posix/sdl/i_gui.cpp \
posix/sdl/i_input.cpp \
posix/sdl/i_joystick.cpp \
posix/sdl/i_main.cpp \
posix/sdl/i_system.cpp \
posix/sdl/sdlglvideo.cpp \
posix/sdl/sdlvideo.cpp \
posix/sdl/st_start.cpp
PLAT_OCULUSQUEST_SOURCES = \
posix/oculusquest/crashcatcher.c \
posix/oculusquest/hardware.cpp \
posix/oculusquest/i_gui.cpp \
posix/oculusquest/i_input.cpp \
posix/oculusquest/i_joystick.cpp \
posix/oculusquest/i_main.cpp \
posix/oculusquest/i_system.cpp \
posix/oculusquest/glvideo.cpp \
posix/oculusquest/video.cpp \
posix/oculusquest/st_start.cpp
SWRENDER_SOURCES = \
swrenderer/r_swcanvas.cpp \
@ -595,7 +595,7 @@ LOCAL_SRC_FILES = \
$(QZDOOM_SRC) \
$(ANDROID_SRC_FILES) \
$(PLAT_POSIX_SOURCES) \
$(PLAT_SDL_SOURCES) \
$(PLAT_OCULUSQUEST_SOURCES) \
$(FASTMATH_SOURCES) \
$(PCH_SOURCES) \
x86.cpp \

View file

@ -44,7 +44,7 @@ FString M_GetAppDataPath(bool create)
{
// Don't use GAME_DIR and such so that ZDoom and its child ports can
// share the node cache.
FString path = NicePath("./lzdoom/config/" GAMENAMELOWERCASE);
FString path = NicePath("./config/");
if (create)
{
CreatePath(path);
@ -57,7 +57,7 @@ FString GetUserFile (const char *file)
FString path;
struct stat info;
path = NicePath("./lzdoom/config/");
path = NicePath("./config/");
if (stat (path, &info) == -1)
{
@ -92,7 +92,7 @@ FString M_GetCachePath(bool create)
{
// Don't use GAME_DIR and such so that ZDoom and its child ports can
// share the node cache.
FString path = NicePath("./lzdoom/cache/");
FString path = NicePath("./cache/");
if (create)
{
CreatePath(path);
@ -165,7 +165,7 @@ FString M_GetConfigPath(bool for_reading)
FString M_GetScreenshotsPath()
{
return NicePath("./lzdoom/screenshots/");
return NicePath("./screenshots/");
}
//===========================================================================
@ -178,7 +178,7 @@ FString M_GetScreenshotsPath()
FString M_GetSavegamesPath()
{
return NicePath("./lzdoom/saves/");
return NicePath("./saves/");
}
//===========================================================================
@ -191,5 +191,5 @@ FString M_GetSavegamesPath()
FString M_GetDocumentsPath()
{
return NicePath("./lzdoom/");
return NicePath("./");
}

View file

@ -711,7 +711,7 @@ void D_Display ()
if (viewactive)
{
DAngle fov = 90.f;
DAngle fov = 104.f;
AActor *cam = players[consoleplayer].camera;
if (cam)
{
@ -1071,7 +1071,7 @@ void D_DoomLoop ()
// process one or more tics
if (singletics)
{
I_StartTic ();
//I_StartTic ();
D_ProcessEvents ();
G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]);
if (advancedemo)
@ -1091,7 +1091,7 @@ void D_DoomLoop ()
TryRunTics (); // will run at least one tic
}
// Update display, next frame, with current state.
I_StartTic ();
//I_StartTic ();
D_Display ();
S_UpdateMusic();
if (wantToRestart)
@ -2724,7 +2724,7 @@ void D_DoomMain ()
V_Init2();
gl_PatchMenu();
UpdateJoystickMenu(NULL);
//UpdateJoystickMenu(NULL);
v = Args->CheckValue ("-loadgame");
if (v)
@ -2799,8 +2799,8 @@ void D_DoomMain ()
D_DoAnonStats();
if (I_FriendlyWindowTitle)
I_SetWindowTitle(DoomStartupInfo.Name.GetChars());
// if (I_FriendlyWindowTitle)
// I_SetWindowTitle(DoomStartupInfo.Name.GetChars());
D_DoomLoop (); // this only returns if a 'restart' CCMD is given.
//

View file

@ -990,7 +990,7 @@ void NetUpdate (void)
// build new ticcmds for console player
for (i = 0; i < newtics; i++)
{
I_StartTic ();
//I_StartTic ();
D_ProcessEvents ();
if (pauseext || (maketic - gametic) / ticdup >= BACKUPTICS/2-1)
break; // can't hold any more

View file

@ -796,6 +796,9 @@ void FGLRenderer::Flush()
}
else
{
const bool is2D = (gamestate != GS_LEVEL);
if (is2D) stereo3dMode.SetUp();
// Render 2D to eye textures
for (int eye_ix = 0; eye_ix < stereo3dMode.eye_count(); ++eye_ix)
{
@ -803,6 +806,9 @@ void FGLRenderer::Flush()
mBuffers->BindEyeFB(eye_ix);
glViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
glScissor(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
//Only adjust HUD if we are 3D (otherwise we are rendering to a cylinder compositor layer)
if (!is2D) stereo3dMode.getEyePose(eye_ix)->AdjustHud();
m2DDrawer->Draw();
FGLDebug::PopGroup();
}
@ -812,6 +818,7 @@ void FGLRenderer::Flush()
FGLDebug::PushGroup("PresentEyes");
stereo3dMode.Present();
FGLDebug::PopGroup();
if (is2D) stereo3dMode.TearDown();
}
}

View file

@ -60,10 +60,11 @@ EXTERN_CVAR(Int, gl_multisample);
EXTERN_CVAR(Float, vr_vunits_per_meter)
EXTERN_CVAR(Float, vr_floor_offset)
//EXTERN_CVAR(Bool, oculusquest_rightHanded)
//EXTERN_CVAR(Bool, oculusquest_moveFollowsOffHand)
EXTERN_CVAR(Int, vr_control_scheme)
EXTERN_CVAR(Bool, vr_moveFollowsOffHand)
//EXTERN_CVAR(Bool, oculusquest_drawControllers)
//EXTERN_CVAR(Float, oculusquest_weaponRotate);
EXTERN_CVAR(Float, vr_weaponRotate);
EXTERN_CVAR(Float, vr_snapTurn);
//EXTERN_CVAR(Float, oculusquest_weaponScale);
CVAR(Float, oculusquest_kill_momentum, 0.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@ -117,6 +118,7 @@ namespace s3d
/* virtual */
void OculusQuestEyePose::GetViewShift(FLOATTYPE yaw, FLOATTYPE outViewShift[3]) const
{
doomYawDegrees = yaw;
outViewShift[0] = outViewShift[1] = outViewShift[2] = 0;
}
@ -266,7 +268,8 @@ namespace s3d
, crossHairDrawer(new F2DDrawer)
, cached2DDrawer(nullptr)
{
eye_ptrs.Push(&leftEyeView); // initially default behavior to Mono non-stereo rendering
eye_ptrs.Push(&leftEyeView);
eye_ptrs.Push(&rightEyeView);
//Get this from my code
Android_GetScreenRes(&sceneWidth, &sceneHeight);
@ -274,8 +277,6 @@ namespace s3d
leftEyeView.initialize();
rightEyeView.initialize();
eye_ptrs.Push(&rightEyeView); // NOW we render to two eyes
crossHairDrawer->Clear();
}
@ -365,10 +366,10 @@ namespace s3d
bool OculusQuestMode::GetWeaponTransform(VSMatrix* out) const
{
long oculusquest_rightHanded = 1;
long oculusquest_rightHanded = vr_control_scheme < 10;
if (GetHandTransform(oculusquest_rightHanded ? 1 : 0, out))
{
//out->rotate(oculusquest_weaponRotate, 1, 0, 0);
//out->rotate(vr_weaponRotate, 1, 0, 0); - not needed, done in the C
if (!oculusquest_rightHanded)
out->scale(-1.0f, 1.0f, 1.0f);
return true;
@ -640,7 +641,13 @@ namespace s3d
//Get controller state here
ovrTracking2 tracking;
getHMDOrientation(&tracking);
getTrackedRemotesOrientation();
//Set up stuff used in the tracking code
vr_weapon_pitchadjust = vr_weaponRotate;
vr_snapturn_angle = vr_snapTurn;
vr_walkdirection = !vr_moveFollowsOffHand; //FIX THIS!
doomYawDegrees = GLRenderer->mAngles.Yaw.Degrees;
getTrackedRemotesOrientation(vr_control_scheme);
frameDesc = setupFrameDescriptor(&tracking);

View file

@ -50,7 +50,7 @@ CUSTOM_CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFI
}
// intraocular distance in meters
CVAR(Float, vr_ipd, 0.062f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // METERS
CVAR(Float, vr_ipd, 0.064f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // METERS
// distance between viewer and the display screen
CVAR(Float, vr_screendist, 0.80f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // METERS
@ -60,7 +60,7 @@ CVAR(Float, vr_vunits_per_meter, 30.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // MET
CVAR(Float, vr_floor_offset, 0.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // METERS
CVAR(Bool, vr_rightHanded, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, vr_control_scheme, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Bool, vr_moveFollowsOffHand, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
@ -70,6 +70,8 @@ CVAR(Float, vr_weaponRotate, -30, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, vr_weaponScale, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, vr_snapTurn, 45.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
// Manage changing of 3D modes:
namespace s3d {

View file

@ -82,7 +82,7 @@ OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, int width, int height, int
#else
OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen) :
#endif
Super(hMonitor, width, height, bits, refreshHz, fullscreen, false)
Super(hMonitor, width, height, bits, refreshHz, fullscreen, false)
{
// SetVSync needs to be at the very top to workaround a bug in Nvidia's OpenGL driver.
// If wglSwapIntervalEXT is called after glBindFramebuffer in a frame the setting is not changed!

View file

@ -4,7 +4,7 @@
#ifdef _WIN32
#include "win32gliface.h"
#else
#include "sdlglvideo.h"
#include "glvideo.h"
#endif
#include <memory>
@ -19,9 +19,9 @@ class OpenGLFrameBuffer : public Win32GLFrameBuffer
typedef Win32GLFrameBuffer Super;
#else
//#include "sdlglvideo.h"
class OpenGLFrameBuffer : public SDLGLFB
class OpenGLFrameBuffer : public OculusQuestGLFB
{
typedef SDLGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux
typedef OculusQuestGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux
#endif

View file

@ -51,7 +51,7 @@ static void CATCH(int a, int b, int c, int d, int e)
LOGI("CAUGHT BAD");
}
int glesLoad = 2; // TODO fix this!
int glesLoad = 3; // TODO fix this!
void* SDL_GL_GetProcAddress(const char* proc);
static void *MOBILE_GetProcAddress(const char* name)

View file

@ -18,10 +18,10 @@ class OpenGLSWFrameBuffer : public Win32GLFrameBuffer
{
typedef Win32GLFrameBuffer Super;
#else
#include "sdlglvideo.h"
class OpenGLSWFrameBuffer : public SDLGLFB
#include "glvideo.h"
class OpenGLSWFrameBuffer : public OculusQuestGLFB
{
typedef SDLGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux
typedef OculusQuestGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux
#endif

View file

@ -51,8 +51,12 @@ EXTERN_CVAR(Bool, use_joystick);
bool M_LoadJoystickConfig(IJoystickConfig *joy);
void M_SaveJoystickConfig(IJoystickConfig *joy);
//We use these from the C controller handlers
extern "C" {
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base);
}
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys);
int Joy_XYAxesToButtons(double x, double y);
double Joy_RemoveDeadZone(double axisval, double deadzone, uint8_t *buttons);

View file

@ -150,6 +150,8 @@ static void BuildModesList (int hiwidth, int hiheight, int hi_bits)
}
showbits = BitTranslate[DummyDepthCvar];
return;
if (Video != NULL)
{
Video->StartModeIterator (showbits, screen->IsFullscreen());

View file

@ -0,0 +1,428 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#ifdef __linux__
#include <sys/prctl.h>
#ifndef PR_SET_PTRACER
#define PR_SET_PTRACER 0x59616d61
#endif
#elif defined (__APPLE__) || defined (__FreeBSD__) || defined(__OpenBSD__)
#include <signal.h>
#endif
static const char crash_switch[] = "--cc-handle-crash";
static const char fatal_err[] = "\n\n*** Fatal Error ***\n";
static const char pipe_err[] = "!!! Failed to create pipe\n";
static const char fork_err[] = "!!! Failed to fork debug process\n";
static const char exec_err[] = "!!! Failed to exec debug process\n";
static char argv0[PATH_MAX];
static char altstack[SIGSTKSZ];
static struct {
int signum;
pid_t pid;
int has_siginfo;
siginfo_t siginfo;
char buf[4096];
} crash_info;
static const struct {
const char *name;
int signum;
} signals[] = {
{ "Segmentation fault", SIGSEGV },
{ "Illegal instruction", SIGILL },
{ "FPU exception", SIGFPE },
{ "System BUS error", SIGBUS },
{ NULL, 0 }
};
static const struct {
int code;
const char *name;
} sigill_codes[] = {
#ifndef __FreeBSD__
{ ILL_ILLOPC, "Illegal opcode" },
{ ILL_ILLOPN, "Illegal operand" },
{ ILL_ILLADR, "Illegal addressing mode" },
{ ILL_ILLTRP, "Illegal trap" },
{ ILL_PRVOPC, "Privileged opcode" },
{ ILL_PRVREG, "Privileged register" },
{ ILL_COPROC, "Coprocessor error" },
{ ILL_BADSTK, "Internal stack error" },
#endif
{ 0, NULL }
};
static const struct {
int code;
const char *name;
} sigfpe_codes[] = {
{ FPE_INTDIV, "Integer divide by zero" },
{ FPE_INTOVF, "Integer overflow" },
{ FPE_FLTDIV, "Floating point divide by zero" },
{ FPE_FLTOVF, "Floating point overflow" },
{ FPE_FLTUND, "Floating point underflow" },
{ FPE_FLTRES, "Floating point inexact result" },
{ FPE_FLTINV, "Floating point invalid operation" },
{ FPE_FLTSUB, "Subscript out of range" },
{ 0, NULL }
};
static const struct {
int code;
const char *name;
} sigsegv_codes[] = {
#ifndef __FreeBSD__
{ SEGV_MAPERR, "Address not mapped to object" },
{ SEGV_ACCERR, "Invalid permissions for mapped object" },
#endif
{ 0, NULL }
};
static const struct {
int code;
const char *name;
} sigbus_codes[] = {
#ifndef __FreeBSD__
{ BUS_ADRALN, "Invalid address alignment" },
{ BUS_ADRERR, "Non-existent physical address" },
{ BUS_OBJERR, "Object specific hardware error" },
#endif
{ 0, NULL }
};
static int (*cc_user_info)(char*, char*);
static void gdb_info(pid_t pid)
{
char respfile[64];
char cmd_buf[128];
FILE *f;
int fd;
/* Create a temp file to put gdb commands into */
strcpy(respfile, "gdb-respfile-XXXXXX");
if((fd=mkstemp(respfile)) >= 0 && (f=fdopen(fd, "w")) != NULL)
{
fprintf(f, "attach %d\n"
"shell echo \"\"\n"
"shell echo \"* Loaded Libraries\"\n"
"info sharedlibrary\n"
"shell echo \"\"\n"
"shell echo \"* Threads\"\n"
"info threads\n"
"shell echo \"\"\n"
"shell echo \"* FPU Status\"\n"
"info float\n"
"shell echo \"\"\n"
"shell echo \"* Registers\"\n"
"info registers\n"
"shell echo \"\"\n"
"shell echo \"* Backtrace\"\n"
"thread apply all backtrace full\n"
"detach\n"
"quit\n", pid);
fclose(f);
/* Run gdb and print process info. */
snprintf(cmd_buf, sizeof(cmd_buf), "gdb --quiet --batch --command=%s", respfile);
printf("Executing: %s\n", cmd_buf);
fflush(stdout);
system(cmd_buf);
/* Clean up */
remove(respfile);
}
else
{
/* Error creating temp file */
if(fd >= 0)
{
close(fd);
remove(respfile);
}
printf("!!! Could not create gdb command file\n");
}
fflush(stdout);
}
static void sys_info(void)
{
#ifdef __unix__
system("echo \"System: `uname -a`\"");
putchar('\n');
fflush(stdout);
#endif
}
static size_t safe_write(int fd, const void *buf, size_t len)
{
size_t ret = 0;
while(ret < len)
{
ssize_t rem;
if((rem=write(fd, (const char*)buf+ret, len-ret)) == -1)
{
if(errno == EINTR)
continue;
break;
}
ret += rem;
}
return ret;
}
static void crash_catcher(int signum, siginfo_t *siginfo, void *context)
{
//ucontext_t *ucontext = (ucontext_t*)context;
pid_t dbg_pid;
int fd[2];
/* Make sure the effective uid is the real uid */
if(getuid() != geteuid())
{
raise(signum);
return;
}
safe_write(STDERR_FILENO, fatal_err, sizeof(fatal_err)-1);
if(pipe(fd) == -1)
{
safe_write(STDERR_FILENO, pipe_err, sizeof(pipe_err)-1);
raise(signum);
return;
}
crash_info.signum = signum;
crash_info.pid = getpid();
crash_info.has_siginfo = !!siginfo;
if(siginfo)
crash_info.siginfo = *siginfo;
if(cc_user_info)
cc_user_info(crash_info.buf, crash_info.buf+sizeof(crash_info.buf));
/* Fork off to start a crash handler */
switch((dbg_pid=fork()))
{
/* Error */
case -1:
safe_write(STDERR_FILENO, fork_err, sizeof(fork_err)-1);
raise(signum);
return;
case 0:
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
close(fd[1]);
execl(argv0, argv0, crash_switch, NULL);
safe_write(STDERR_FILENO, exec_err, sizeof(exec_err)-1);
_exit(1);
default:
#ifdef __linux__
prctl(PR_SET_PTRACER, dbg_pid, 0, 0, 0);
#endif
safe_write(fd[1], &crash_info, sizeof(crash_info));
close(fd[0]);
close(fd[1]);
/* Wait; we'll be killed when gdb is done */
do {
int status;
if(waitpid(dbg_pid, &status, 0) == dbg_pid &&
(WIFEXITED(status) || WIFSIGNALED(status)))
{
/* The debug process died before it could kill us */
raise(signum);
break;
}
} while(1);
}
}
static void crash_handler(const char *logfile)
{
const char *sigdesc = "";
int i;
if(fread(&crash_info, sizeof(crash_info), 1, stdin) != 1)
{
fprintf(stderr, "!!! Failed to retrieve info from crashed process\n");
exit(1);
}
/* Get the signal description */
for(i = 0;signals[i].name;++i)
{
if(signals[i].signum == crash_info.signum)
{
sigdesc = signals[i].name;
break;
}
}
if(crash_info.has_siginfo)
{
switch(crash_info.signum)
{
case SIGSEGV:
for(i = 0;sigsegv_codes[i].name;++i)
{
if(sigsegv_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigsegv_codes[i].name;
break;
}
}
break;
case SIGFPE:
for(i = 0;sigfpe_codes[i].name;++i)
{
if(sigfpe_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigfpe_codes[i].name;
break;
}
}
break;
case SIGILL:
for(i = 0;sigill_codes[i].name;++i)
{
if(sigill_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigill_codes[i].name;
break;
}
}
break;
case SIGBUS:
for(i = 0;sigbus_codes[i].name;++i)
{
if(sigbus_codes[i].code == crash_info.siginfo.si_code)
{
sigdesc = sigbus_codes[i].name;
break;
}
}
break;
}
}
fprintf(stderr, "%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
fprintf(stderr, "Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stderr);
if(logfile)
{
/* Create crash log file and redirect shell output to it */
if(freopen(logfile, "wa", stdout) != stdout)
{
fprintf(stderr, "!!! Could not create %s following signal\n", logfile);
exit(1);
}
fprintf(stderr, "Generating %s and killing process %d, please wait... ", logfile, crash_info.pid);
printf("*** Fatal Error ***\n"
"%s (signal %i)\n", sigdesc, crash_info.signum);
if(crash_info.has_siginfo)
printf("Address: %p\n", crash_info.siginfo.si_addr);
fputc('\n', stdout);
fflush(stdout);
}
sys_info();
crash_info.buf[sizeof(crash_info.buf)-1] = '\0';
printf("%s\n", crash_info.buf);
fflush(stdout);
if(crash_info.pid > 0)
{
gdb_info(crash_info.pid);
kill(crash_info.pid, SIGKILL);
}
if(logfile)
{
const char *str;
char buf[512];
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
snprintf(buf, sizeof(buf), "kdialog --title \"Very Fatal Error\" --textbox \"%s\" 800 600", logfile);
else if((str=getenv("GNOME_DESKTOP_SESSION_ID")) && str[0] != '\0')
snprintf(buf, sizeof(buf), "gxmessage -buttons \"Okay:0\" -geometry 800x600 -title \"Very Fatal Error\" -center -file \"%s\"", logfile);
else
snprintf(buf, sizeof(buf), "xmessage -buttons \"Okay:0\" -center -file \"%s\"", logfile);
system(buf);
}
exit(0);
}
int cc_install_handlers(int argc, char **argv, int num_signals, int *signals, const char *logfile, int (*user_info)(char*, char*))
{
struct sigaction sa;
stack_t altss;
int retval;
if(argc == 2 && strcmp(argv[1], crash_switch) == 0)
crash_handler(logfile);
cc_user_info = user_info;
if(argv[0][0] == '/')
snprintf(argv0, sizeof(argv0), "%s", argv[0]);
else
{
getcwd(argv0, sizeof(argv0));
retval = strlen(argv0);
snprintf(argv0+retval, sizeof(argv0)-retval, "/%s", argv[0]);
}
/* Set an alternate signal stack so SIGSEGVs caused by stack overflows
* still run */
altss.ss_sp = altstack;
altss.ss_flags = 0;
altss.ss_size = sizeof(altstack);
sigaltstack(&altss, NULL);
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = crash_catcher;
sa.sa_flags = SA_RESETHAND | SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&sa.sa_mask);
retval = 0;
while(num_signals--)
{
if((*signals != SIGSEGV && *signals != SIGILL && *signals != SIGFPE &&
*signals != SIGBUS) || sigaction(*signals, &sa, NULL) == -1)
{
*signals = 0;
retval = -1;
}
++signals;
}
return retval;
}

View file

@ -0,0 +1,370 @@
/*
** sdlglvideo.cpp
**
**---------------------------------------------------------------------------
** Copyright 2005-2016 Christoph Oelckers et.al.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include "doomtype.h"
#include "templates.h"
#include "i_system.h"
#include "i_video.h"
#include "m_argv.h"
#include "v_video.h"
#include "v_pfx.h"
#include "stats.h"
#include "version.h"
#include "c_console.h"
#include "videomodes.h"
#include "glvideo.h"
#include "video.h"
#include "gl/system/gl_system.h"
#include "r_defs.h"
#include "gl/gl_functions.h"
//#include "gl/gl_intern.h"
#include "gl/renderer/gl_renderer.h"
#include "gl/system/gl_framebuffer.h"
#include "gl/shaders/gl_shader.h"
#include "gl/utility/gl_templates.h"
#include "gl/textures/gl_material.h"
#include "gl/system/gl_cvars.h"
#include <QzDoom/VrCommon.h>
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern IVideo *Video;
// extern int vid_renderer;
EXTERN_CVAR (Float, Gamma)
EXTERN_CVAR (Int, vid_adapter)
EXTERN_CVAR (Int, vid_displaybits)
EXTERN_CVAR (Int, vid_renderer)
EXTERN_CVAR (Int, vid_maxfps)
EXTERN_CVAR (Bool, cl_capfps)
DFrameBuffer *CreateGLSWFrameBuffer(int width, int height, bool bgra, bool fullscreen);
// PUBLIC DATA DEFINITIONS -------------------------------------------------
CUSTOM_CVAR(Bool, gl_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
Printf("This won't take effect until " GAMENAME " is restarted.\n");
}
#ifdef __arm__
CUSTOM_CVAR(Bool, vid_glswfb, false, CVAR_NOINITCALL)
{
Printf("This won't take effect until " GAMENAME " is restarted.\n");
}
CUSTOM_CVAR(Bool, gl_es, false, CVAR_NOINITCALL)
{
Printf("This won't take effect until " GAMENAME " is restarted.\n");
}
#else
CUSTOM_CVAR(Bool, vid_glswfb, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
Printf("This won't take effect until " GAMENAME " is restarted.\n");
}
CUSTOM_CVAR(Bool, gl_es, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
Printf("This won't take effect until " GAMENAME " is restarted.\n");
}
#endif
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
OculusQuestGLVideo::OculusQuestGLVideo (int parm)
{
IteratorBits = 0;
//I think we have to do this still
if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
fprintf( stderr, "Video initialization failed: %s\n",
SDL_GetError( ) );
}
}
OculusQuestGLVideo::~OculusQuestGLVideo ()
{
if (GLRenderer != NULL) GLRenderer->FlushTextures();
}
void OculusQuestGLVideo::StartModeIterator (int bits, bool fs)
{
IteratorMode = 0;
IteratorBits = bits;
}
bool OculusQuestGLVideo::NextMode (int *width, int *height, bool *letterbox)
{
if (IteratorBits != 8)
return false;
if ((unsigned)IteratorMode < sizeof(VideoModes)/sizeof(VideoModes[0]))
{
*width = VideoModes[IteratorMode].width;
*height = VideoModes[IteratorMode].height;
++IteratorMode;
return true;
}
return false;
}
DFrameBuffer *OculusQuestGLVideo::CreateFrameBuffer (int width, int height, bool bgra, bool fullscreen, DFrameBuffer *old)
{
static int retry = 0;
static int owidth, oheight;
PalEntry flashColor;
// int flashAmount;
if (old != NULL)
{
delete old;
}
else
{
flashColor = 0;
// flashAmount = 0;
}
OculusQuestBaseFB *fb;
const char *hwBuffers = Args->CheckValue("-hwbuffers");
int buffers = 1;
if (hwBuffers)
{
buffers = atoi(hwBuffers);
}
Printf("HW buffers = %d\n", buffers);
fb = new OpenGLFrameBuffer(0, width, height, 32, 60, fullscreen, buffers);
retry = 0;
return fb;
}
void OculusQuestGLVideo::SetWindowedScale (float scale)
{
}
bool OculusQuestGLVideo::SetResolution (int width, int height, int bits)
{
// FIXME: Is it possible to do this without completely destroying the old
// interface?
#ifndef NO_GL
if (GLRenderer != NULL) GLRenderer->FlushTextures();
I_ShutdownGraphics();
Video = new OculusQuestGLVideo(0);
if (Video == NULL) I_FatalError ("Failed to initialize display");
#if (defined(WINDOWS)) || defined(WIN32)
bits=32;
#else
bits=24;
#endif
V_DoModeSetup(width, height, bits);
#endif
return true; // We must return true because the old video context no longer exists.
}
//==========================================================================
//
//
//
//==========================================================================
#ifdef __MOBILE__
extern "C" extern int glesLoad;
#endif
void OculusQuestGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, const int *glver)
{
#ifdef __MOBILE__
int major,min;
const char *version = Args->CheckValue("-glversion");
if( !strcmp(version, "gles1") )
{
glesLoad = 1;
major = 1;
min = 0;
}
else if ( !strcmp(version, "gles2") )
{
glesLoad = 2;
major = 2;
min = 0;
}
else if ( !strcmp(version, "gles3") )
{
glesLoad = 3;
major = 3;
min = 1;
}
#endif
}
// FrameBuffer implementation -----------------------------------------------
OculusQuestGLFB::OculusQuestGLFB (void *, int width, int height, int, int, bool fullscreen, bool bgra)
: OculusQuestBaseFB (width, height, bgra)
{
}
OculusQuestGLFB::~OculusQuestGLFB ()
{
}
void OculusQuestGLFB::InitializeState()
{
}
void OculusQuestGLFB::SetGammaTable(uint16_t *tbl)
{
}
void OculusQuestGLFB::ResetGammaTable()
{
}
bool OculusQuestGLFB::Lock(bool buffered)
{
m_Lock++;
return true;
}
bool OculusQuestGLFB::Lock ()
{
return Lock(false);
}
void OculusQuestGLFB::Unlock ()
{
--m_Lock;
}
bool OculusQuestGLFB::IsLocked ()
{
return m_Lock>0;// true;
}
bool OculusQuestGLFB::IsFullscreen ()
{
return true;
}
bool OculusQuestGLFB::IsValid ()
{
return DFrameBuffer::IsValid() && Screen != NULL;
}
void OculusQuestGLFB::SetVSync( bool vsync )
{
}
void OculusQuestGLFB::NewRefreshRate ()
{
}
void OculusQuestGLFB::SwapBuffers()
{
}
int OculusQuestGLFB::GetClientWidth()
{
uint32_t w, h;
Android_GetScreenRes(&w, &h);
int width = w;
return width;
}
int OculusQuestGLFB::GetClientHeight()
{
uint32_t w, h;
Android_GetScreenRes(&w, &h);
int height = h;
return height;
}
void OculusQuestGLFB::ScaleCoordsFromWindow(int16_t &x, int16_t &y)
{
uint32_t w, h;
Android_GetScreenRes(&w, &h);
// Detect if we're doing scaling in the Window and adjust the mouse
// coordinates accordingly. This could be more efficent, but I
// don't think performance is an issue in the menus.
if(IsFullscreen())
{
int realw = w, realh = h;
ScaleWithAspect (realw, realh, SCREENWIDTH, SCREENHEIGHT);
if (realw != SCREENWIDTH || realh != SCREENHEIGHT)
{
double xratio = (double)SCREENWIDTH/realw;
double yratio = (double)SCREENHEIGHT/realh;
if (realw < w)
{
x = (x - (w - realw)/2)*xratio;
y *= yratio;
}
else
{
y = (y - (h - realh)/2)*yratio;
x *= xratio;
}
}
}
else
{
x = (int16_t)(x*Width/w);
y = (int16_t)(y*Height/h);
}
}

View file

@ -0,0 +1,98 @@
#ifndef __SDLGLVIDEO_H__
#define __SDLGLVIDEO_H__
#include "hardware.h"
#include "v_video.h"
#include <SDL.h>
#include "gl/system/gl_system.h"
EXTERN_CVAR (Float, dimamount)
EXTERN_CVAR (Color, dimcolor)
struct FRenderer;
FRenderer *gl_CreateInterface();
class OculusQuestGLVideo : public IVideo
{
public:
OculusQuestGLVideo (int parm);
~OculusQuestGLVideo ();
EDisplayType GetDisplayType () { return DISPLAY_Both; }
void SetWindowedScale (float scale);
DFrameBuffer *CreateFrameBuffer (int width, int height, bool bgra, bool fs, DFrameBuffer *old);
void StartModeIterator (int bits, bool fs);
bool NextMode (int *width, int *height, bool *letterbox);
bool SetResolution (int width, int height, int bits);
void SetupPixelFormat(bool allowsoftware, int multisample, const int *glver);
private:
int IteratorMode;
int IteratorBits;
};
class OculusQuestBaseFB : public DFrameBuffer
{
typedef DFrameBuffer Super;
public:
using DFrameBuffer::DFrameBuffer;
virtual SDL_Window *GetSDLWindow() = 0;
friend class OculusQuestGLVideo;
};
class OculusQuestGLFB : public OculusQuestBaseFB
{
typedef OculusQuestBaseFB Super;
public:
// this must have the same parameters as the Windows version, even if they are not used!
OculusQuestGLFB (void *hMonitor, int width, int height, int, int, bool fullscreen, bool bgra);
~OculusQuestGLFB ();
void ForceBuffering (bool force);
bool Lock(bool buffered);
bool Lock ();
void Unlock();
bool IsLocked ();
bool IsValid ();
bool IsFullscreen ();
virtual void SetVSync( bool vsync );
void SwapBuffers();
void NewRefreshRate ();
friend class OculusQuestGLVideo;
int GetClientWidth();
int GetClientHeight();
virtual void ScaleCoordsFromWindow(int16_t &x, int16_t &y);
SDL_Window *GetSDLWindow() override { return Screen; }
virtual int GetTrueHeight() { return GetClientHeight(); }
protected:
void SetGammaTable(uint16_t *tbl);
void ResetGammaTable();
void InitializeState();
OculusQuestGLFB () {}
uint8_t GammaTable[3][256];
bool UpdatePending;
SDL_Window *Screen;
SDL_GLContext GLContext;
void UpdateColors ();
int m_Lock;
Uint16 m_origGamma[3][256];
bool m_supportsGamma;
};
#endif

View file

@ -0,0 +1,287 @@
/*
** hardware.cpp
** Somewhat OS-independant interface to the screen, mouse, keyboard, and stick
**
**---------------------------------------------------------------------------
** Copyright 1998-2006 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <SDL.h>
#include <signal.h>
#include <time.h>
#include "version.h"
#include "hardware.h"
#include "i_video.h"
#include "i_system.h"
#include "c_console.h"
#include "c_cvars.h"
#include "c_dispatch.h"
#include "video.h"
#include "v_text.h"
#include "doomstat.h"
#include "m_argv.h"
#include "glvideo.h"
#include "r_renderer.h"
#include "swrenderer/r_swrenderer.h"
#include "atterm.h"
EXTERN_CVAR (Bool, ticker)
EXTERN_CVAR (Bool, fullscreen)
EXTERN_CVAR (Bool, swtruecolor)
EXTERN_CVAR (Float, vid_winscale)
IVideo *Video;
extern int NewWidth, NewHeight, NewBits, DisplayBits;
bool V_DoModeSetup (int width, int height, int bits);
void I_RestartRenderer();
int currentrenderer;
// [ZDoomGL]
CUSTOM_CVAR (Int, vid_renderer, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
// 0: Software renderer
// 1: OpenGL renderer
if (self != currentrenderer)
{
switch (self)
{
case 0:
Printf("Switching to software renderer...\n");
break;
case 1:
Printf("Switching to OpenGL renderer...\n");
break;
default:
Printf("Unknown renderer (%d). Falling back to software renderer...\n", (int) vid_renderer);
self = 0; // make sure to actually switch to the software renderer
break;
}
Printf("You must restart " GAMENAME " to switch the renderer\n");
}
}
void I_ShutdownGraphics ()
{
if (screen)
{
DFrameBuffer *s = screen;
screen = NULL;
delete s;
}
if (Video)
delete Video, Video = NULL;
SDL_QuitSubSystem (SDL_INIT_VIDEO);
}
void I_InitGraphics ()
{
if (SDL_InitSubSystem (SDL_INIT_VIDEO) < 0)
{
I_FatalError ("Could not initialize SDL video:\n%s\n", SDL_GetError());
return;
}
UCVarValue val;
val.Bool = !!Args->CheckParm ("-devparm");
ticker.SetGenericRepDefault (val, CVAR_Bool);
currentrenderer = vid_renderer;
Video = new OculusQuestGLVideo(0);
if (Video == NULL)
I_FatalError ("Failed to initialize display");
atterm (I_ShutdownGraphics);
Video->SetWindowedScale (vid_winscale);
currentrenderer = vid_renderer;
}
static void I_DeleteRenderer()
{
if (Renderer != NULL) delete Renderer;
}
void I_CreateRenderer()
{
currentrenderer = vid_renderer;
if (Renderer == NULL)
{
if (currentrenderer==1) Renderer = gl_CreateInterface();
else Renderer = new FSoftwareRenderer;
atterm(I_DeleteRenderer);
}
}
/** Remaining code is common to Win32 and Linux **/
// VIDEO WRAPPERS ---------------------------------------------------------
DFrameBuffer *I_SetMode (int &width, int &height, DFrameBuffer *old)
{
bool fs = false;
switch (Video->GetDisplayType ())
{
case DISPLAY_WindowOnly:
fs = false;
break;
case DISPLAY_FullscreenOnly:
fs = true;
break;
case DISPLAY_Both:
fs = fullscreen;
break;
}
DFrameBuffer *res = Video->CreateFrameBuffer (width, height, swtruecolor, fs, old);
/* Right now, CreateFrameBuffer cannot return NULL
if (res == NULL)
{
I_FatalError ("Mode %dx%d is unavailable\n", width, height);
}
*/
return res;
}
bool I_CheckResolution (int width, int height, int bits)
{
int twidth, theight;
Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen);
while (Video->NextMode (&twidth, &theight, NULL))
{
if (width == twidth && height == theight)
return true;
}
return false;
}
void I_ClosestResolution (int *width, int *height, int bits)
{
return;
}
//==========================================================================
//
// SetFPSLimit
//
// Initializes an event timer to fire at a rate of <limit>/sec. The video
// update will wait for this timer to trigger before updating.
//
// Pass 0 as the limit for unlimited.
// Pass a negative value for the limit to use the value of vid_maxfps.
//
//==========================================================================
EXTERN_CVAR(Int, vid_maxfps);
EXTERN_CVAR(Bool, cl_capfps);
#if !defined(__APPLE__) && !defined(__OpenBSD__)
static void FPSLimitNotify(sigval val)
{
}
void I_SetFPSLimit(int limit)
{
}
#endif
CUSTOM_CVAR (Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (vid_maxfps < TICRATE && vid_maxfps != 0)
{
vid_maxfps = TICRATE;
}
else if (vid_maxfps > 1000)
{
vid_maxfps = 1000;
}
else if (cl_capfps == 0)
{
I_SetFPSLimit(vid_maxfps);
}
}
extern int NewWidth, NewHeight, NewBits, DisplayBits;
CUSTOM_CVAR(Bool, swtruecolor, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
{
// Strictly speaking this doesn't require a mode switch, but it is the easiest
// way to force a CreateFramebuffer call without a lot of refactoring.
if (currentrenderer == 0)
{
NewWidth = screen->VideoWidth;
NewHeight = screen->VideoHeight;
NewBits = DisplayBits;
setmodeneeded = true;
}
}
CUSTOM_CVAR (Bool, fullscreen, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
{
NewWidth = screen->VideoWidth;
NewHeight = screen->VideoHeight;
NewBits = DisplayBits;
setmodeneeded = true;
}
CUSTOM_CVAR (Float, vid_winscale, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self < 1.f)
{
self = 1.f;
}
else if (Video)
{
Video->SetWindowedScale (self);
NewWidth = screen->VideoWidth;
NewHeight = screen->VideoHeight;
NewBits = DisplayBits;
setmodeneeded = true;
}
}
CCMD (vid_listmodes)
{
Printf ("Just.. dont!\n");
}
CCMD (vid_currentmode)
{
Printf ("%dx%dx%d\n", DisplayWidth, DisplayHeight, DisplayBits);
}

View file

@ -0,0 +1,86 @@
/*
** i_gui.cpp
**
**---------------------------------------------------------------------------
** Copyright 2008 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <string.h>
#include <SDL.h>
#include "bitmap.h"
#include "v_palette.h"
#include "textures.h"
bool I_SetCursor(FTexture *cursorpic)
{
static SDL_Cursor *cursor;
static SDL_Surface *cursorSurface;
if (cursorpic != NULL && cursorpic->UseType != ETextureType::Null)
{
// Must be no larger than 32x32.
if (cursorpic->GetWidth() > 32 || cursorpic->GetHeight() > 32)
{
return false;
}
if (cursorSurface == NULL)
cursorSurface = SDL_CreateRGBSurface (0, 32, 32, 32, MAKEARGB(0,255,0,0), MAKEARGB(0,0,255,0), MAKEARGB(0,0,0,255), MAKEARGB(255,0,0,0));
SDL_LockSurface(cursorSurface);
uint8_t buffer[32*32*4];
memset(buffer, 0, 32*32*4);
FBitmap bmp(buffer, 32*4, 32, 32);
cursorpic->CopyTrueColorPixels(&bmp, 0, 0);
memcpy(cursorSurface->pixels, bmp.GetPixels(), 32*32*4);
SDL_UnlockSurface(cursorSurface);
if (cursor)
SDL_FreeCursor (cursor);
cursor = SDL_CreateColorCursor (cursorSurface, 0, 0);
SDL_SetCursor (cursor);
}
else
{
if (cursor)
{
SDL_SetCursor (NULL);
SDL_FreeCursor (cursor);
cursor = NULL;
}
if (cursorSurface != NULL)
{
SDL_FreeSurface(cursorSurface);
cursorSurface = NULL;
}
}
return true;
}

View file

@ -0,0 +1,590 @@
/*
** i_input.cpp
**
**---------------------------------------------------------------------------
** Copyright 2005-2016 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <SDL.h>
#include <ctype.h>
#include "doomtype.h"
#include "c_dispatch.h"
#include "doomdef.h"
#include "doomstat.h"
#include "m_argv.h"
#include "i_input.h"
#include "v_video.h"
#include "d_main.h"
#include "d_event.h"
#include "d_gui.h"
#include "c_console.h"
#include "c_cvars.h"
#include "i_system.h"
#include "c_dispatch.h"
#include "dikeys.h"
#include "templates.h"
#include "s_sound.h"
#include "events.h"
#include "utf8.h"
static void I_CheckGUICapture ();
static void I_CheckNativeMouse ();
bool GUICapture;
static bool NativeMouse = true;
extern int paused;
CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, m_noprescale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, m_filter, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, i_soundinbackground, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
EXTERN_CVAR (Bool, fullscreen)
extern int WaitingForKey, chatmodeon;
extern constate_e ConsoleState;
static const SDL_Keycode DIKToKeySym[256] =
{
0, SDLK_ESCAPE, SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6,
SDLK_7, SDLK_8, SDLK_9, SDLK_0,SDLK_MINUS, SDLK_EQUALS, SDLK_BACKSPACE, SDLK_TAB,
SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u, SDLK_i,
SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET, SDLK_RETURN, SDLK_LCTRL, SDLK_a, SDLK_s,
SDLK_d, SDLK_f, SDLK_g, SDLK_h, SDLK_j, SDLK_k, SDLK_l, SDLK_SEMICOLON,
SDLK_QUOTE, SDLK_BACKQUOTE, SDLK_LSHIFT, SDLK_BACKSLASH, SDLK_z, SDLK_x, SDLK_c, SDLK_v,
SDLK_b, SDLK_n, SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH, SDLK_RSHIFT, SDLK_KP_MULTIPLY,
SDLK_LALT, SDLK_SPACE, SDLK_CAPSLOCK, SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5,
SDLK_F6, SDLK_F7, SDLK_F8, SDLK_F9, SDLK_F10, SDLK_NUMLOCKCLEAR, SDLK_SCROLLLOCK, SDLK_KP_7,
SDLK_KP_8, SDLK_KP_9, SDLK_KP_MINUS, SDLK_KP_4, SDLK_KP_5, SDLK_KP_6, SDLK_KP_PLUS, SDLK_KP_1,
SDLK_KP_2, SDLK_KP_3, SDLK_KP_0, SDLK_KP_PERIOD, 0, 0, 0, SDLK_F11,
SDLK_F12, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, SDLK_F13, SDLK_F14, SDLK_F15, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, SDLK_KP_EQUALS, 0, 0,
0, SDLK_AT, SDLK_COLON, 0, 0, 0, 0, 0,
0, 0, 0, 0, SDLK_KP_ENTER, SDLK_RCTRL, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, SDLK_KP_COMMA, 0, SDLK_KP_DIVIDE, 0, SDLK_SYSREQ,
SDLK_RALT, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, SDLK_PAUSE, 0, SDLK_HOME,
SDLK_UP, SDLK_PAGEUP, 0, SDLK_LEFT, 0, SDLK_RIGHT, 0, SDLK_END,
SDLK_DOWN, SDLK_PAGEDOWN, SDLK_INSERT, SDLK_DELETE, 0, 0, 0, 0,
0, 0, 0, SDLK_LGUI, SDLK_RGUI, SDLK_MENU, SDLK_POWER, SDLK_SLEEP,
0, 0, 0, 0, 0, SDLK_AC_SEARCH, SDLK_AC_BOOKMARKS, SDLK_AC_REFRESH,
SDLK_AC_STOP, SDLK_AC_FORWARD, SDLK_AC_BACK, SDLK_COMPUTER, SDLK_MAIL, SDLK_MEDIASELECT, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static const SDL_Scancode DIKToKeyScan[256] =
{
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_ESCAPE, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3, SDL_SCANCODE_4, SDL_SCANCODE_5, SDL_SCANCODE_6,
SDL_SCANCODE_7, SDL_SCANCODE_8, SDL_SCANCODE_9, SDL_SCANCODE_0 ,SDL_SCANCODE_MINUS, SDL_SCANCODE_EQUALS, SDL_SCANCODE_BACKSPACE, SDL_SCANCODE_TAB,
SDL_SCANCODE_Q, SDL_SCANCODE_W, SDL_SCANCODE_E, SDL_SCANCODE_R, SDL_SCANCODE_T, SDL_SCANCODE_Y, SDL_SCANCODE_U, SDL_SCANCODE_I,
SDL_SCANCODE_O, SDL_SCANCODE_P, SDL_SCANCODE_LEFTBRACKET, SDL_SCANCODE_RIGHTBRACKET, SDL_SCANCODE_RETURN, SDL_SCANCODE_LCTRL, SDL_SCANCODE_A, SDL_SCANCODE_S,
SDL_SCANCODE_D, SDL_SCANCODE_F, SDL_SCANCODE_G, SDL_SCANCODE_H, SDL_SCANCODE_J, SDL_SCANCODE_K, SDL_SCANCODE_L, SDL_SCANCODE_SEMICOLON,
SDL_SCANCODE_APOSTROPHE, SDL_SCANCODE_GRAVE, SDL_SCANCODE_LSHIFT, SDL_SCANCODE_BACKSLASH, SDL_SCANCODE_Z, SDL_SCANCODE_X, SDL_SCANCODE_C, SDL_SCANCODE_V,
SDL_SCANCODE_B, SDL_SCANCODE_N, SDL_SCANCODE_M, SDL_SCANCODE_COMMA, SDL_SCANCODE_PERIOD, SDL_SCANCODE_SLASH, SDL_SCANCODE_RSHIFT, SDL_SCANCODE_KP_MULTIPLY,
SDL_SCANCODE_LALT, SDL_SCANCODE_SPACE, SDL_SCANCODE_CAPSLOCK, SDL_SCANCODE_F1, SDL_SCANCODE_F2, SDL_SCANCODE_F3, SDL_SCANCODE_F4, SDL_SCANCODE_F5,
SDL_SCANCODE_F6, SDL_SCANCODE_F7, SDL_SCANCODE_F8, SDL_SCANCODE_F9, SDL_SCANCODE_F10, SDL_SCANCODE_NUMLOCKCLEAR, SDL_SCANCODE_SCROLLLOCK, SDL_SCANCODE_KP_7,
SDL_SCANCODE_KP_8, SDL_SCANCODE_KP_9, SDL_SCANCODE_KP_MINUS, SDL_SCANCODE_KP_4, SDL_SCANCODE_KP_5, SDL_SCANCODE_KP_6, SDL_SCANCODE_KP_PLUS, SDL_SCANCODE_KP_1,
SDL_SCANCODE_KP_2, SDL_SCANCODE_KP_3, SDL_SCANCODE_KP_0, SDL_SCANCODE_KP_PERIOD, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F11,
SDL_SCANCODE_F12, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_F13, SDL_SCANCODE_F14, SDL_SCANCODE_F15, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_KP_EQUALS, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_KP_ENTER, SDL_SCANCODE_RCTRL, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_KP_COMMA, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_KP_DIVIDE, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_SYSREQ,
SDL_SCANCODE_RALT, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_PAUSE, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_HOME,
SDL_SCANCODE_UP, SDL_SCANCODE_PAGEUP, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_RIGHT, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_END,
SDL_SCANCODE_DOWN, SDL_SCANCODE_PAGEDOWN, SDL_SCANCODE_INSERT, SDL_SCANCODE_DELETE, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_LGUI, SDL_SCANCODE_RGUI, SDL_SCANCODE_MENU, SDL_SCANCODE_POWER, SDL_SCANCODE_SLEEP,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_AC_SEARCH, SDL_SCANCODE_AC_BOOKMARKS, SDL_SCANCODE_AC_REFRESH,
SDL_SCANCODE_AC_STOP, SDL_SCANCODE_AC_FORWARD, SDL_SCANCODE_AC_BACK, SDL_SCANCODE_COMPUTER, SDL_SCANCODE_MAIL, SDL_SCANCODE_MEDIASELECT, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN,
SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN
};
static TMap<SDL_Keycode, uint8_t> InitKeySymMap ()
{
TMap<SDL_Keycode, uint8_t> KeySymToDIK;
for (int i = 0; i < 256; ++i)
{
KeySymToDIK[DIKToKeySym[i]] = i;
}
KeySymToDIK[0] = 0;
KeySymToDIK[SDLK_RSHIFT] = DIK_LSHIFT;
KeySymToDIK[SDLK_RCTRL] = DIK_LCONTROL;
KeySymToDIK[SDLK_RALT] = DIK_LMENU;
// Depending on your Linux flavor, you may get SDLK_PRINT or SDLK_SYSREQ
KeySymToDIK[SDLK_PRINTSCREEN] = DIK_SYSRQ;
return KeySymToDIK;
}
static const TMap<SDL_Keycode, uint8_t> KeySymToDIK(InitKeySymMap());
static TMap<SDL_Scancode, uint8_t> InitKeyScanMap ()
{
TMap<SDL_Scancode, uint8_t> KeyScanToDIK;
for (int i = 0; i < 256; ++i)
{
KeyScanToDIK[DIKToKeyScan[i]] = i;
}
return KeyScanToDIK;
}
static const TMap<SDL_Scancode, uint8_t> KeyScanToDIK(InitKeyScanMap());
static void I_CheckGUICapture ()
{
bool wantCapt;
if (menuactive == MENU_Off)
{
wantCapt = ConsoleState == c_down || ConsoleState == c_falling || chatmodeon;
}
else
{
wantCapt = (menuactive == MENU_On || menuactive == MENU_OnNoPause);
}
// [ZZ] check active event handlers that want the UI processing
if (!wantCapt && E_CheckUiProcessors())
wantCapt = true;
if (wantCapt != GUICapture)
{
GUICapture = wantCapt;
ResetButtonStates();
}
}
void I_SetMouseCapture()
{
// Clear out any mouse movement.
SDL_GetRelativeMouseState (NULL, NULL);
SDL_SetRelativeMouseMode (SDL_TRUE);
#ifdef __MOBILE__
// Need to clear this again because setting mode above adds relative values
SDL_GetRelativeMouseState (NULL, NULL);
#endif
}
void I_ReleaseMouseCapture()
{
SDL_SetRelativeMouseMode (SDL_FALSE);
}
static void PostMouseMove (int x, int y)
{
static int lastx = 0, lasty = 0;
event_t ev = { 0,0,0,0,0,0,0 };
if (m_filter)
{
ev.x = (x + lastx) / 2;
ev.y = (y + lasty) / 2;
}
else
{
ev.x = x;
ev.y = y;
}
lastx = x;
lasty = y;
if (ev.x | ev.y)
{
ev.type = EV_Mouse;
D_PostEvent (&ev);
}
}
static void MouseRead ()
{
int x, y;
if (NativeMouse)
{
return;
}
SDL_GetRelativeMouseState (&x, &y);
if (!m_noprescale)
{
x *= 3;
y *= 2;
}
if (x | y)
{
PostMouseMove (x, -y);
}
}
CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE)
{
if (self < 0) self = 0;
else if (self > 2) self = 2;
}
static bool inGame()
{
switch (mouse_capturemode)
{
default:
case 0:
return gamestate == GS_LEVEL;
case 1:
return gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_FINALE;
case 2:
return true;
}
}
static void I_CheckNativeMouse ()
{
bool focus = SDL_GetKeyboardFocus() != NULL;
bool fs = screen->IsFullscreen();
bool wantNative = !focus || (!use_mouse || GUICapture || paused || demoplayback || !inGame());
if (wantNative != NativeMouse)
{
NativeMouse = wantNative;
SDL_ShowCursor (wantNative);
if (wantNative)
I_ReleaseMouseCapture ();
else
I_SetMouseCapture ();
}
}
void MessagePump (const SDL_Event &sev)
{
static int lastx = 0, lasty = 0;
int x, y;
event_t event = { 0,0,0,0,0,0,0 };
switch (sev.type)
{
case SDL_QUIT:
exit (0);
case SDL_WINDOWEVENT:
switch (sev.window.event)
{
extern bool AppActive;
case SDL_WINDOWEVENT_FOCUS_GAINED:
S_SetSoundPaused(1);
AppActive = true;
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
S_SetSoundPaused(i_soundinbackground);
AppActive = false;
break;
}
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
if (!GUICapture)
{
event.type = sev.type == SDL_MOUSEBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
switch (sev.button.button)
{
case SDL_BUTTON_LEFT: event.data1 = KEY_MOUSE1; break;
case SDL_BUTTON_MIDDLE: event.data1 = KEY_MOUSE3; break;
case SDL_BUTTON_RIGHT: event.data1 = KEY_MOUSE2; break;
case SDL_BUTTON_X1: event.data1 = KEY_MOUSE4; break;
case SDL_BUTTON_X2: event.data1 = KEY_MOUSE5; break;
case 6: event.data1 = KEY_MOUSE6; break;
case 7: event.data1 = KEY_MOUSE7; break;
case 8: event.data1 = KEY_MOUSE8; break;
default: printf("SDL mouse button %s %d\n",
sev.type == SDL_MOUSEBUTTONDOWN ? "down" : "up", sev.button.button); break;
}
if (event.data1 != 0)
{
D_PostEvent(&event);
}
}
else if ((sev.button.button >= SDL_BUTTON_LEFT && sev.button.button <= SDL_BUTTON_X2))
{
int x, y;
SDL_GetMouseState(&x, &y);
event.type = EV_GUI_Event;
event.data1 = x;
event.data2 = y;
screen->ScaleCoordsFromWindow(event.data1, event.data2);
if (sev.type == SDL_MOUSEBUTTONDOWN)
{
switch(sev.button.button)
{
case SDL_BUTTON_LEFT: event.subtype = EV_GUI_LButtonDown; break;
case SDL_BUTTON_MIDDLE: event.subtype = EV_GUI_MButtonDown; break;
case SDL_BUTTON_RIGHT: event.subtype = EV_GUI_RButtonDown; break;
case SDL_BUTTON_X1: event.subtype = EV_GUI_BackButtonDown; break;
case SDL_BUTTON_X2: event.subtype = EV_GUI_FwdButtonDown; break;
default: assert(false); event.subtype = EV_GUI_None; break;
}
}
else
{
switch(sev.button.button)
{
case SDL_BUTTON_LEFT: event.subtype = EV_GUI_LButtonUp; break;
case SDL_BUTTON_MIDDLE: event.subtype = EV_GUI_MButtonUp; break;
case SDL_BUTTON_RIGHT: event.subtype = EV_GUI_RButtonUp; break;
case SDL_BUTTON_X1: event.subtype = EV_GUI_BackButtonUp; break;
case SDL_BUTTON_X2: event.subtype = EV_GUI_FwdButtonUp; break;
default: assert(false); event.subtype = EV_GUI_None; break;
}
}
SDL_Keymod kmod = SDL_GetModState();
event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
((kmod & KMOD_ALT) ? GKM_ALT : 0);
D_PostEvent(&event);
}
break;
case SDL_MOUSEMOTION:
if (GUICapture)
{
event.data1 = sev.motion.x;
event.data2 = sev.motion.y;
screen->ScaleCoordsFromWindow(event.data1, event.data2);
event.type = EV_GUI_Event;
event.subtype = EV_GUI_MouseMove;
SDL_Keymod kmod = SDL_GetModState();
event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
((kmod & KMOD_ALT) ? GKM_ALT : 0);
D_PostEvent(&event);
}
break;
case SDL_MOUSEWHEEL:
if (GUICapture)
{
event.type = EV_GUI_Event;
if (sev.wheel.y == 0)
event.subtype = sev.wheel.x > 0 ? EV_GUI_WheelRight : EV_GUI_WheelLeft;
else
event.subtype = sev.wheel.y > 0 ? EV_GUI_WheelUp : EV_GUI_WheelDown;
SDL_Keymod kmod = SDL_GetModState();
event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
((kmod & KMOD_ALT) ? GKM_ALT : 0);
D_PostEvent (&event);
}
else
{
event.type = EV_KeyDown;
if (sev.wheel.y != 0)
event.data1 = sev.wheel.y > 0 ? KEY_MWHEELUP : KEY_MWHEELDOWN;
else
event.data1 = sev.wheel.x > 0 ? KEY_MWHEELRIGHT : KEY_MWHEELLEFT;
D_PostEvent (&event);
event.type = EV_KeyUp;
D_PostEvent (&event);
}
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
if (!GUICapture)
{
if (sev.key.repeat)
{
break;
}
event.type = sev.type == SDL_KEYDOWN ? EV_KeyDown : EV_KeyUp;
// Try to look up our key mapped key for conversion to DirectInput.
// If that fails, then we'll do a lookup against the scan code,
// which may not return the right key, but at least the key should
// work in the game.
if (const uint8_t *dik = KeySymToDIK.CheckKey (sev.key.keysym.sym))
event.data1 = *dik;
else if (const uint8_t *dik = KeyScanToDIK.CheckKey (sev.key.keysym.scancode))
event.data1 = *dik;
if (event.data1)
{
if (sev.key.keysym.sym < 256)
{
event.data2 = sev.key.keysym.sym;
}
D_PostEvent (&event);
}
}
else
{
event.type = EV_GUI_Event;
event.subtype = sev.type == SDL_KEYDOWN ? EV_GUI_KeyDown : EV_GUI_KeyUp;
SDL_Keymod kmod = SDL_GetModState();
event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
((kmod & KMOD_ALT) ? GKM_ALT : 0);
if (event.subtype == EV_GUI_KeyDown && sev.key.repeat)
{
event.subtype = EV_GUI_KeyRepeat;
}
switch (sev.key.keysym.sym)
{
case SDLK_KP_ENTER: event.data1 = GK_RETURN; break;
case SDLK_PAGEUP: event.data1 = GK_PGUP; break;
case SDLK_PAGEDOWN: event.data1 = GK_PGDN; break;
case SDLK_END: event.data1 = GK_END; break;
case SDLK_HOME: event.data1 = GK_HOME; break;
case SDLK_LEFT: event.data1 = GK_LEFT; break;
case SDLK_RIGHT: event.data1 = GK_RIGHT; break;
case SDLK_UP: event.data1 = GK_UP; break;
case SDLK_DOWN: event.data1 = GK_DOWN; break;
case SDLK_DELETE: event.data1 = GK_DEL; break;
case SDLK_ESCAPE: event.data1 = GK_ESCAPE; break;
case SDLK_F1: event.data1 = GK_F1; break;
case SDLK_F2: event.data1 = GK_F2; break;
case SDLK_F3: event.data1 = GK_F3; break;
case SDLK_F4: event.data1 = GK_F4; break;
case SDLK_F5: event.data1 = GK_F5; break;
case SDLK_F6: event.data1 = GK_F6; break;
case SDLK_F7: event.data1 = GK_F7; break;
case SDLK_F8: event.data1 = GK_F8; break;
case SDLK_F9: event.data1 = GK_F9; break;
case SDLK_F10: event.data1 = GK_F10; break;
case SDLK_F11: event.data1 = GK_F11; break;
case SDLK_F12: event.data1 = GK_F12; break;
case SDLK_SYSREQ: event.data1 = GK_SYSRQ; break;
default:
if (sev.key.keysym.sym < 256)
{
event.data1 = sev.key.keysym.sym;
}
break;
}
if (event.data1 < 128)
{
event.data1 = toupper(event.data1);
D_PostEvent (&event);
}
}
break;
case SDL_TEXTINPUT:
if (GUICapture)
{
int size;
int unichar = utf8_decode((const uint8_t*)sev.text.text, &size);
if (size != 4)
{
event.type = EV_GUI_Event;
event.subtype = EV_GUI_Char;
event.data1 = (int16_t)unichar;
event.data2 = !!(SDL_GetModState() & KMOD_ALT);
D_PostEvent (&event);
}
}
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
if (!GUICapture)
{
event.type = sev.type == SDL_JOYBUTTONDOWN ? EV_KeyDown : EV_KeyUp;
event.data1 = KEY_FIRSTJOYBUTTON + sev.jbutton.button;
if(event.data1 != 0)
D_PostEvent(&event);
}
break;
}
}
void I_GetEvent ()
{
SDL_Event sev;
while (SDL_PollEvent (&sev))
{
MessagePump (sev);
}
if (use_mouse)
{
MouseRead ();
}
}
void I_StartTic ()
{
I_CheckGUICapture ();
I_CheckNativeMouse ();
I_GetEvent ();
}
void I_ProcessJoysticks ();
void I_StartFrame ()
{
I_ProcessJoysticks();
}

View file

@ -0,0 +1,349 @@
/*
** i_joystick.cpp
**
**---------------------------------------------------------------------------
** Copyright 2005-2016 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <SDL.h>
#include "doomdef.h"
#include "version.h"
#include "templates.h"
#include "m_joy.h"
// Very small deadzone so that floating point magic doesn't happen
#define MIN_DEADZONE 0.000001f
CUSTOM_CVAR(Bool, joy_background, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL)
{
Printf("This won't take effect until " GAMENAME " is restarted.\n");
}
class SDLInputJoystick: public IJoystickConfig
{
public:
SDLInputJoystick(int DeviceIndex) : DeviceIndex(DeviceIndex), Multiplier(1.0f)
{
Device = SDL_JoystickOpen(DeviceIndex);
if(Device != NULL)
{
NumAxes = SDL_JoystickNumAxes(Device);
NumHats = SDL_JoystickNumHats(Device);
SetDefaultConfig();
}
}
~SDLInputJoystick()
{
if(Device != NULL)
M_SaveJoystickConfig(this);
SDL_JoystickClose(Device);
}
bool IsValid() const
{
return Device != NULL;
}
FString GetName()
{
return SDL_JoystickName(Device);
}
float GetSensitivity()
{
return Multiplier;
}
void SetSensitivity(float scale)
{
Multiplier = scale;
}
int GetNumAxes()
{
return NumAxes + NumHats*2;
}
float GetAxisDeadZone(int axis)
{
return Axes[axis].DeadZone;
}
EJoyAxis GetAxisMap(int axis)
{
return Axes[axis].GameAxis;
}
const char *GetAxisName(int axis)
{
return Axes[axis].Name.GetChars();
}
float GetAxisScale(int axis)
{
return Axes[axis].Multiplier;
}
void SetAxisDeadZone(int axis, float zone)
{
Axes[axis].DeadZone = clamp(zone, MIN_DEADZONE, 1.f);
}
void SetAxisMap(int axis, EJoyAxis gameaxis)
{
Axes[axis].GameAxis = gameaxis;
}
void SetAxisScale(int axis, float scale)
{
Axes[axis].Multiplier = scale;
}
// Used by the saver to not save properties that are at their defaults.
bool IsSensitivityDefault()
{
return Multiplier == 1.0f;
}
bool IsAxisDeadZoneDefault(int axis)
{
return Axes[axis].DeadZone <= MIN_DEADZONE;
}
bool IsAxisMapDefault(int axis)
{
if(axis >= 5)
return Axes[axis].GameAxis == JOYAXIS_None;
return Axes[axis].GameAxis == DefaultAxes[axis];
}
bool IsAxisScaleDefault(int axis)
{
return Axes[axis].Multiplier == 1.0f;
}
void SetDefaultConfig()
{
for(int i = 0;i < GetNumAxes();i++)
{
AxisInfo info;
if(i < NumAxes)
info.Name.Format("Axis %d", i+1);
else
info.Name.Format("Hat %d (%c)", (i-NumAxes)/2 + 1, (i-NumAxes)%2 == 0 ? 'x' : 'y');
info.DeadZone = MIN_DEADZONE;
info.Multiplier = 1.0f;
info.Value = 0.0;
info.ButtonValue = 0;
if(i >= 5)
info.GameAxis = JOYAXIS_None;
else
info.GameAxis = DefaultAxes[i];
Axes.Push(info);
}
}
FString GetIdentifier()
{
char id[16];
mysnprintf(id, countof(id), "JS:%d", DeviceIndex);
return id;
}
void AddAxes(float axes[NUM_JOYAXIS])
{
// Add to game axes.
for (int i = 0; i < GetNumAxes(); ++i)
{
if(Axes[i].GameAxis != JOYAXIS_None)
axes[Axes[i].GameAxis] -= float(Axes[i].Value * Multiplier * Axes[i].Multiplier);
}
}
void ProcessInput()
{
uint8_t buttonstate;
for (int i = 0; i < NumAxes; ++i)
{
buttonstate = 0;
Axes[i].Value = SDL_JoystickGetAxis(Device, i)/32767.0;
Axes[i].Value = Joy_RemoveDeadZone(Axes[i].Value, Axes[i].DeadZone, &buttonstate);
// Map button to axis
// X and Y are handled differently so if we have 2 or more axes then we'll use that code instead.
if (NumAxes == 1 || (i >= 2 && i < NUM_JOYAXISBUTTONS))
{
Joy_GenerateButtonEvents(Axes[i].ButtonValue, buttonstate, 2, KEY_JOYAXIS1PLUS + i*2);
Axes[i].ButtonValue = buttonstate;
}
}
if(NumAxes > 1)
{
buttonstate = Joy_XYAxesToButtons(Axes[0].Value, Axes[1].Value);
Joy_GenerateButtonEvents(Axes[0].ButtonValue, buttonstate, 4, KEY_JOYAXIS1PLUS);
Axes[0].ButtonValue = buttonstate;
}
// Map POV hats to buttons and axes. Why axes? Well apparently I have
// a gamepad where the left control stick is a POV hat (instead of the
// d-pad like you would expect, no that's pressure sensitive). Also
// KDE's joystick dialog maps them to axes as well.
for (int i = 0; i < NumHats; ++i)
{
AxisInfo &x = Axes[NumAxes + i*2];
AxisInfo &y = Axes[NumAxes + i*2 + 1];
buttonstate = SDL_JoystickGetHat(Device, i);
// If we're going to assume that we can pass SDL's value into
// Joy_GenerateButtonEvents then we might as well assume the format here.
if(buttonstate & 0x1) // Up
y.Value = -1.0;
else if(buttonstate & 0x4) // Down
y.Value = 1.0;
else
y.Value = 0.0;
if(buttonstate & 0x2) // Left
x.Value = 1.0;
else if(buttonstate & 0x8) // Right
x.Value = -1.0;
else
x.Value = 0.0;
if(i < 4)
{
Joy_GenerateButtonEvents(x.ButtonValue, buttonstate, 4, KEY_JOYPOV1_UP + i*4);
x.ButtonValue = buttonstate;
}
}
}
protected:
struct AxisInfo
{
FString Name;
float DeadZone;
float Multiplier;
EJoyAxis GameAxis;
double Value;
uint8_t ButtonValue;
};
static const EJoyAxis DefaultAxes[5];
int DeviceIndex;
SDL_Joystick *Device;
float Multiplier;
TArray<AxisInfo> Axes;
int NumAxes;
int NumHats;
};
const EJoyAxis SDLInputJoystick::DefaultAxes[5] = {JOYAXIS_Side, JOYAXIS_Forward, JOYAXIS_Pitch, JOYAXIS_Yaw, JOYAXIS_Up};
class SDLInputJoystickManager
{
public:
SDLInputJoystickManager()
{
for(int i = 0;i < SDL_NumJoysticks();i++)
{
SDLInputJoystick *device = new SDLInputJoystick(i);
if(device->IsValid())
Joysticks.Push(device);
else
delete device;
}
}
~SDLInputJoystickManager()
{
for(unsigned int i = 0;i < Joysticks.Size();i++)
delete Joysticks[i];
}
void AddAxes(float axes[NUM_JOYAXIS])
{
for(unsigned int i = 0;i < Joysticks.Size();i++)
Joysticks[i]->AddAxes(axes);
}
void GetDevices(TArray<IJoystickConfig *> &sticks)
{
for(unsigned int i = 0;i < Joysticks.Size();i++)
{
M_LoadJoystickConfig(Joysticks[i]);
sticks.Push(Joysticks[i]);
}
}
void ProcessInput() const
{
for(unsigned int i = 0;i < Joysticks.Size();++i)
Joysticks[i]->ProcessInput();
}
protected:
TArray<SDLInputJoystick *> Joysticks;
};
static SDLInputJoystickManager *JoystickManager;
void I_StartupJoysticks()
{
if (joy_background)
SDL_SetHint("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", "1");
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) >= 0)
JoystickManager = new SDLInputJoystickManager();
}
void I_ShutdownJoysticks()
{
if(JoystickManager)
{
delete JoystickManager;
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
}
}
void I_GetJoysticks(TArray<IJoystickConfig *> &sticks)
{
sticks.Clear();
JoystickManager->GetDevices(sticks);
}
void I_GetAxes(float axes[NUM_JOYAXIS])
{
for (int i = 0; i < NUM_JOYAXIS; ++i)
{
axes[i] = 0;
}
if (use_joystick)
{
JoystickManager->AddAxes(axes);
}
}
void I_ProcessJoysticks()
{
if (use_joystick)
JoystickManager->ProcessInput();
}
IJoystickConfig *I_UpdateDeviceList()
{
return NULL;
}

View file

@ -0,0 +1,294 @@
/*
** i_main.cpp
** System-specific startup code. Eventually calls D_DoomMain.
**
**---------------------------------------------------------------------------
** Copyright 1998-2007 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include <SDL.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <new>
#include <sys/param.h>
#include <locale.h>
#include "doomerrors.h"
#include "m_argv.h"
#include "d_main.h"
#include "i_system.h"
#include "i_video.h"
#include "c_console.h"
#include "errors.h"
#include "version.h"
#include "w_wad.h"
#include "g_level.h"
#include "g_levellocals.h"
#include "r_state.h"
#include "cmdlib.h"
#include "r_utility.h"
#include "doomstat.h"
#include "vm.h"
#include "atterm.h"
// MACROS ------------------------------------------------------------------
// The maximum number of functions that can be registered with atterm.
#define MAX_TERMS 64
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
extern "C" int cc_install_handlers(int, char**, int, int*, const char*, int(*)(char*, char*));
#ifdef __APPLE__
void Mac_I_FatalError(const char* errortext);
#endif
#ifdef __linux__
void Linux_I_FatalError(const char* errortext);
#endif
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern volatile int game_running;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
// The command line arguments.
FArgs *Args;
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
void exit_handler(int dummy) {
game_running = 0;
}
static void NewFailure ()
{
I_FatalError ("Failed to allocate memory from system heap");
}
static int DoomSpecificInfo (char *buffer, char *end)
{
const char *arg;
int size = end-buffer-2;
int i, p;
p = 0;
p += snprintf (buffer+p, size-p, GAMENAME" version %s (%s)\n", GetVersionString(), GetGitHash());
#ifdef __VERSION__
p += snprintf (buffer+p, size-p, "Compiler version: %s\n", __VERSION__);
#endif
p += snprintf (buffer+p, size-p, "\nCommand line:");
for (i = 0; i < Args->NumArgs(); ++i)
{
p += snprintf (buffer+p, size-p, " %s", Args->GetArg(i));
}
p += snprintf (buffer+p, size-p, "\n");
for (i = 0; (arg = Wads.GetWadName (i)) != NULL; ++i)
{
p += snprintf (buffer+p, size-p, "\nWad %d: %s", i, arg);
}
if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL)
{
p += snprintf (buffer+p, size-p, "\n\nNot in a level.");
}
else
{
p += snprintf (buffer+p, size-p, "\n\nCurrent map: %s", level.MapName.GetChars());
if (!viewactive)
{
p += snprintf (buffer+p, size-p, "\n\nView not active.");
}
else
{
p += snprintf (buffer+p, size-p, "\n\nviewx = %f", r_viewpoint.Pos.X);
p += snprintf (buffer+p, size-p, "\nviewy = %f", r_viewpoint.Pos.Y);
p += snprintf (buffer+p, size-p, "\nviewz = %f", r_viewpoint.Pos.Z);
p += snprintf (buffer+p, size-p, "\nviewangle = %f", r_viewpoint.Angles.Yaw.Degrees);
}
}
buffer[p++] = '\n';
buffer[p++] = '\0';
return p;
}
void I_StartupJoysticks();
void I_ShutdownJoysticks();
#ifdef __ANDROID__
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,"JNITouchControlsUtils", __VA_ARGS__))
int main_android (int argc, char **argv)
{
#else
int main (int argc, char **argv)
{
#endif
#if !defined (__APPLE__) && !defined (__ANDROID__)
{
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
cc_install_handlers(argc, argv, 4, s, GAMENAMELOWERCASE "-crash.log", DoomSpecificInfo);
}
#endif // !__APPLE__
printf(GAMENAME" %s - %s - SDL version\nCompiled on %s\n",
GetVersionString(), GetGitTime(), __DATE__);
seteuid (getuid ());
std::set_new_handler (NewFailure);
// Set LC_NUMERIC environment variable in case some library decides to
// clear the setlocale call at least this will be correct.
// Note that the LANG environment variable is overridden by LC_*
setenv ("LC_NUMERIC", "C", 1);
setlocale (LC_ALL, "C");
if (SDL_Init (0) < 0)
{
fprintf (stderr, "Could not initialize SDL:\n%s\n", SDL_GetError());
return -1;
}
atterm (SDL_Quit);
printf("\n");
try
{
Args = new FArgs(argc, argv);
/*
killough 1/98:
This fixes some problems with exit handling
during abnormal situations.
The old code called I_Quit() to end program,
while now I_Quit() is installed as an exit
handler and exit() is called to exit, either
normally or abnormally. Seg faults are caught
and the error handler is used, to prevent
being left in graphics mode or having very
loud SFX noise because the sound card is
left in an unstable state.
*/
atexit (call_terms);
atterm (I_Quit);
/*
Register signal handlers to interrupt D_DoomMain and D_DoomLoop, allowing
call_terms() to be invoked at the conclusion of the main thread/quit menu
rather than at exit. The atexit() call can remain to handle edge cases
where a signal cannot be intercepted, such as Alt+F4 or closing the window
via the GUI.
Fixes segmentation fault on exit when using the KMSDRM SDL video driver.
*/
signal(SIGINT, exit_handler);
signal(SIGTERM, exit_handler);
// Should we even be doing anything with progdir on Unix systems?
char program[PATH_MAX];
if (realpath (argv[0], program) == NULL)
strcpy (program, argv[0]);
char *slash = strrchr (program, '/');
if (slash != NULL)
{
*(slash + 1) = '\0';
progdir = program;
}
else
{
progdir = "./";
}
I_StartupJoysticks();
C_InitConsole (80*8, 25*8, false);
D_DoomMain ();
}
catch (std::exception &error)
{
I_ShutdownJoysticks();
const char *const message = error.what();
if (strcmp(message, "NoRunExit"))
{
if (CVMAbortException::stacktrace.IsNotEmpty())
{
Printf("%s", CVMAbortException::stacktrace.GetChars());
}
#ifdef __ANDROID__
LOGI("FATAL ERROR: %s", message);
#endif
if (batchrun)
{
Printf("%s\n", message);
}
else
{
#ifdef __APPLE__
Mac_I_FatalError(message);
#endif // __APPLE__
#ifdef __linux__
Linux_I_FatalError(message);
#endif // __linux__
}
}
exit (-1);
}
catch (...)
{
call_terms ();
throw;
}
call_terms();
return 0;
}

View file

@ -0,0 +1,496 @@
//-----------------------------------------------------------------------------
//
// Copyright 1993-1996 id Software
// Copyright 1999-2016 Randy Heit
//
// This program 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 3 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
// along with this program. If not, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
//
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fnmatch.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <SDL.h>
#include "doomerrors.h"
#include <math.h>
#include "doomtype.h"
#include "doomstat.h"
#include "version.h"
#include "doomdef.h"
#include "cmdlib.h"
#include "m_argv.h"
#include "m_misc.h"
#include "i_video.h"
#include "i_sound.h"
#include "i_music.h"
#include "x86.h"
#include "d_main.h"
#include "d_net.h"
#include "g_game.h"
#include "i_system.h"
#include "c_dispatch.h"
#include "atterm.h"
#include "templates.h"
#include "v_palette.h"
#include "textures.h"
#include "bitmap.h"
#include "stats.h"
#include "hardware.h"
#include "gameconfigfile.h"
#include "m_fixed.h"
#include "g_level.h"
extern "C"
{
double SecondsPerCycle = 1e-8;
double CyclesPerSecond = 1e8;
}
#ifndef NO_GTK
bool I_GtkAvailable ();
int I_PickIWad_Gtk (WadStuff *wads, int numwads, bool showwin, int defaultiwad);
void I_FatalError_Gtk(const char* errortext);
#elif defined(__APPLE__)
int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad);
#endif
double PerfToSec, PerfToMillisec;
void I_Tactile (int /*on*/, int /*off*/, int /*total*/)
{
}
ticcmd_t emptycmd;
ticcmd_t *I_BaseTiccmd(void)
{
return &emptycmd;
}
void I_BeginRead(void)
{
}
void I_EndRead(void)
{
}
//
// I_Init
//
void I_Init (void)
{
CheckCPUID (&CPU);
DumpCPUInfo (&CPU);
atterm (I_ShutdownSound);
I_InitSound ();
}
//
// I_Quit
//
static int has_exited;
void I_Quit (void)
{
has_exited = 1; /* Prevent infinitely recursive exits -- killough */
if (demorecording)
G_CheckDemoStatus();
C_DeinitConsole();
}
//
// I_Error
//
extern FILE *Logfile;
bool gameisdead;
#ifdef __APPLE__
void Mac_I_FatalError(const char* errortext);
#endif
#ifdef __ANDROID__
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,"Gzdoom", __VA_ARGS__))
#endif
#ifdef __linux__
void Linux_I_FatalError(const char* errortext)
{
// Close window or exit fullscreen and release mouse capture
SDL_Quit();
const char *str;
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
{
FString cmd;
cmd << "kdialog --title \"" GAMESIG " ";
cmd << GetVersionString() << ": No IWAD found\" ";
cmd << "--msgbox \"" << errortext << "\"";
popen(cmd, "r");
}
#ifndef NO_GTK
else if (I_GtkAvailable())
{
I_FatalError_Gtk(errortext);
}
#endif
else
{
FString message;
message << GAMESIG " ";
message << GetVersionString() << ": No IWAD found";
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, message, errortext, NULL);
}
}
#endif
void I_FatalError (const char *error, va_list ap)
{
static bool alreadyThrown = false;
gameisdead = true;
if (!alreadyThrown) // ignore all but the first message -- killough
{
alreadyThrown = true;
char errortext[MAX_ERRORTEXT];
int index;
index = vsnprintf (errortext, MAX_ERRORTEXT, error, ap);
#ifdef __APPLE__
Mac_I_FatalError(errortext);
#endif // __APPLE__
#ifdef __ANDROID__
LOGI("FATAL ERROR: %s", errortext);
#endif
#ifdef __linux__
Linux_I_FatalError(errortext);
#endif
// Record error to log (if logging)
if (Logfile)
{
fprintf (Logfile, "\n**** DIED WITH FATAL ERROR:\n%s\n", errortext);
fflush (Logfile);
}
// throw CFatalError (errortext);
fprintf (stderr, "%s\n", errortext);
exit (-1);
}
if (!has_exited) // If it hasn't exited yet, exit now -- killough
{
has_exited = 1; // Prevent infinitely recursive exits -- killough
exit(-1);
}
}
void I_FatalError(const char* const error, ...)
{
va_list argptr;
va_start(argptr, error);
I_FatalError(error, argptr);
va_end(argptr);
}
void I_Error (const char *error, ...)
{
va_list argptr;
char errortext[MAX_ERRORTEXT];
va_start(argptr, error);
myvsnprintf (errortext, MAX_ERRORTEXT, error, argptr);
va_end (argptr);
#ifdef __ANDROID__
LOGI("ERROR: %s", errortext);
#endif
throw CRecoverableError(errortext);
}
void I_SetIWADInfo ()
{
}
void I_DebugPrint(const char *cp)
{
}
void I_PrintStr(const char *cp)
{
// Strip out any color escape sequences before writing to debug output
TArray<char> copy(strlen(cp) + 1, true);
const char * srcp = cp;
char * dstp = copy.Data();
while (*srcp != 0)
{
if (*srcp != 0x1c && *srcp != 0x1d && *srcp != 0x1e && *srcp != 0x1f)
{
*dstp++ = *srcp++;
}
else
{
if (srcp[1] != 0) srcp += 2;
else break;
}
}
*dstp = 0;
fputs(copy.Data(), stdout);
fflush(stdout);
}
int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad)
{
int i;
if (!showwin)
{
return defaultiwad;
}
#ifndef __APPLE__
const char *str;
if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0)
{
FString cmd("kdialog --title \"" GAMESIG " ");
cmd << GetVersionString() << ": Select an IWAD to use\""
" --menu \"" GAMENAME " found more than one IWAD\n"
"Select from the list below to determine which one to use:\"";
for(i = 0; i < numwads; ++i)
{
const char *filepart = strrchr(wads[i].Path, '/');
if(filepart == NULL)
filepart = wads[i].Path;
else
filepart++;
// Menu entries are specified in "tag" "item" pairs, where when a
// particular item is selected (and the Okay button clicked), its
// corresponding tag is printed to stdout for identification.
cmd.AppendFormat(" \"%d\" \"%s (%s)\"", i, wads[i].Name.GetChars(), filepart);
}
if(defaultiwad >= 0 && defaultiwad < numwads)
{
const char *filepart = strrchr(wads[defaultiwad].Path, '/');
if(filepart == NULL)
filepart = wads[defaultiwad].Path;
else
filepart++;
cmd.AppendFormat(" --default \"%s (%s)\"", wads[defaultiwad].Name.GetChars(), filepart);
}
FILE *f = popen(cmd, "r");
if(f != NULL)
{
char gotstr[16];
if(fgets(gotstr, sizeof(gotstr), f) == NULL ||
sscanf(gotstr, "%d", &i) != 1)
i = -1;
// Exit status = 1 means the selection was canceled (either by
// Cancel/Esc or the X button), not that there was an error running
// the program. In that case, nothing was printed so fgets will
// have failed. Other values can indicate an error running the app,
// so fall back to whatever else can be used.
int status = pclose(f);
if(WIFEXITED(status) && (WEXITSTATUS(status) == 0 || WEXITSTATUS(status) == 1))
return i;
}
}
#endif
#ifndef NO_GTK
if (I_GtkAvailable())
{
return I_PickIWad_Gtk (wads, numwads, showwin, defaultiwad);
}
#endif
#ifdef __APPLE__
return I_PickIWad_Cocoa (wads, numwads, showwin, defaultiwad);
#endif
printf ("Please select a game wad (or 0 to exit):\n");
for (i = 0; i < numwads; ++i)
{
const char *filepart = strrchr (wads[i].Path, '/');
if (filepart == NULL)
filepart = wads[i].Path;
else
filepart++;
printf ("%d. %s (%s)\n", i+1, wads[i].Name.GetChars(), filepart);
}
printf ("Which one? ");
if (scanf ("%d", &i) != 1 || i > numwads)
return -1;
return i-1;
}
bool I_WriteIniFailed ()
{
printf ("The config file %s could not be saved:\n%s\n", GameConfig->GetPathName(), strerror(errno));
return false;
// return true to retry
}
static const char *pattern;
#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED < 1080
static int matchfile (struct dirent *ent)
#else
static int matchfile (const struct dirent *ent)
#endif
{
return fnmatch (pattern, ent->d_name, FNM_NOESCAPE) == 0;
}
void *I_FindFirst (const char *filespec, findstate_t *fileinfo)
{
FString dir;
const char *slash = strrchr (filespec, '/');
if (slash)
{
pattern = slash+1;
dir = FString(filespec, slash-filespec+1);
}
else
{
pattern = filespec;
dir = ".";
}
fileinfo->current = 0;
fileinfo->count = scandir (dir.GetChars(), &fileinfo->namelist,
matchfile, alphasort);
if (fileinfo->count > 0)
{
return fileinfo;
}
return (void*)-1;
}
int I_FindNext (void *handle, findstate_t *fileinfo)
{
findstate_t *state = (findstate_t *)handle;
if (state->current < fileinfo->count)
{
return ++state->current < fileinfo->count ? 0 : -1;
}
return -1;
}
int I_FindClose (void *handle)
{
findstate_t *state = (findstate_t *)handle;
if (handle != (void*)-1 && state->count > 0)
{
for(int i = 0;i < state->count;++i)
free (state->namelist[i]);
state->count = 0;
free (state->namelist);
state->namelist = NULL;
}
return 0;
}
int I_FindAttr(findstate_t* const fileinfo)
{
dirent* const ent = fileinfo->namelist[fileinfo->current];
bool isdir;
if (DirEntryExists(ent->d_name, &isdir))
{
return isdir ? FA_DIREC : 0;
}
return 0;
}
void I_PutInClipboard (const char *str)
{
SDL_SetClipboardText(str);
}
FString I_GetFromClipboard (bool use_primary_selection)
{
if(char *ret = SDL_GetClipboardText())
{
FString text(ret);
SDL_free(ret);
return text;
}
return "";
}
// Return a random seed, preferably one with lots of entropy.
unsigned int I_MakeRNGSeed()
{
unsigned int seed;
int file;
// Try reading from /dev/urandom first, then /dev/random, then
// if all else fails, use a crappy seed from time().
seed = time(NULL);
file = open("/dev/urandom", O_RDONLY);
if (file < 0)
{
file = open("/dev/random", O_RDONLY);
}
if (file >= 0)
{
read(file, &seed, sizeof(seed));
close(file);
}
return seed;
}
TArray<FString> I_GetGogPaths()
{
// GOG's Doom games are Windows only at the moment
return TArray<FString>();
}

View file

@ -0,0 +1,19 @@
#include <CoreFoundation/CoreFoundation.h>
#include "SDL.h"
void Mac_I_FatalError(const char* errortext)
{
// Close window or exit fullscreen and release mouse capture
SDL_Quit();
const CFStringRef errorString = CFStringCreateWithCStringNoCopy( kCFAllocatorDefault,
errortext, kCFStringEncodingASCII, kCFAllocatorNull );
if ( NULL != errorString )
{
CFOptionFlags dummy;
CFUserNotificationDisplayAlert( 0, kCFUserNotificationStopAlertLevel, NULL, NULL, NULL,
CFSTR( "Fatal Error" ), errorString, CFSTR( "Exit" ), NULL, NULL, &dummy );
CFRelease( errorString );
}
}

View file

@ -0,0 +1,382 @@
/*
** st_start.cpp
** Handles the startup screen.
**
**---------------------------------------------------------------------------
** Copyright 2006-2007 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <termios.h>
#include "st_start.h"
#include "doomdef.h"
#include "i_system.h"
#include "c_cvars.h"
#include "atterm.h"
#ifdef __ANDROID__
#include <android/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,"NETOWRK",__VA_ARGS__)
#define fprintf my_fprintf
void my_fprintf(FILE * x, const char *format, ...)
{
FString str;
va_list argptr;
va_start (argptr, format);
str.VFormat (format, argptr);
va_end (argptr);
//fprintf (stderr, "\r%-40s\n", str.GetChars());
//addTextConsoleBox(str.GetChars());
}
#endif
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
class FTTYStartupScreen : public FStartupScreen
{
public:
FTTYStartupScreen(int max_progress);
~FTTYStartupScreen();
void Progress();
void NetInit(const char *message, int num_players);
void NetProgress(int count);
void NetMessage(const char *format, ...); // cover for printf
void NetDone();
bool NetLoop(bool (*timer_callback)(void *), void *userdata);
protected:
bool DidNetInit;
int NetMaxPos, NetCurPos;
const char *TheNetMessage;
termios OldTermIOS;
};
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
void I_ShutdownJoysticks();
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void DeleteStartupScreen();
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
FStartupScreen *StartScreen;
CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (self < 0) self = 0;
else if (self > 2) self=2;
}
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static const char SpinnyProgressChars[4] = { '|', '/', '-', '\\' };
// CODE --------------------------------------------------------------------
//==========================================================================
//
// FStartupScreen :: CreateInstance
//
// Initializes the startup screen for the detected game.
// Sets the size of the progress bar and displays the startup screen.
//
//==========================================================================
FStartupScreen *FStartupScreen::CreateInstance(int max_progress)
{
atterm(DeleteStartupScreen);
return new FTTYStartupScreen(max_progress);
}
//===========================================================================
//
// DeleteStartupScreen
//
// Makes sure the startup screen has been deleted before quitting.
//
//===========================================================================
void DeleteStartupScreen()
{
if (StartScreen != NULL)
{
delete StartScreen;
StartScreen = NULL;
}
}
//===========================================================================
//
// FTTYStartupScreen Constructor
//
// Sets the size of the progress bar and displays the startup screen.
//
//===========================================================================
FTTYStartupScreen::FTTYStartupScreen(int max_progress)
: FStartupScreen(max_progress)
{
DidNetInit = false;
NetMaxPos = 0;
NetCurPos = 0;
TheNetMessage = NULL;
}
//===========================================================================
//
// FTTYStartupScreen Destructor
//
// Called just before entering graphics mode to deconstruct the startup
// screen.
//
//===========================================================================
FTTYStartupScreen::~FTTYStartupScreen()
{
NetDone(); // Just in case it wasn't called yet and needs to be.
}
//===========================================================================
//
// FTTYStartupScreen :: Progress
//
// If there was a progress bar, this would move it. But the basic TTY
// startup screen doesn't have one, so this function does nothing.
//
//===========================================================================
void FTTYStartupScreen::Progress()
{
}
//===========================================================================
//
// FTTYStartupScreen :: NetInit
//
// Sets stdin for unbuffered I/O, displays the given message, and shows
// a progress meter.
//
//===========================================================================
void FTTYStartupScreen::NetInit(const char *message, int numplayers)
{
if (!DidNetInit)
{
termios rawtermios;
fprintf (stderr, "Press 'Q' to abort network game synchronization.");
// Set stdin to raw mode so we can get keypresses in ST_CheckNetAbort()
// immediately without waiting for an EOL.
tcgetattr (STDIN_FILENO, &OldTermIOS);
rawtermios = OldTermIOS;
rawtermios.c_lflag &= ~(ICANON | ECHO);
tcsetattr (STDIN_FILENO, TCSANOW, &rawtermios);
DidNetInit = true;
}
if (numplayers == 1)
{
// Status message without any real progress info.
fprintf (stderr, "\n%s.", message);
}
else
{
fprintf (stderr, "\n%s: ", message);
}
fflush (stderr);
TheNetMessage = message;
NetMaxPos = numplayers;
NetCurPos = 0;
NetProgress(1); // You always know about yourself
}
//===========================================================================
//
// FTTYStartupScreen :: NetDone
//
// Restores the old stdin tty settings.
//
//===========================================================================
void FTTYStartupScreen::NetDone()
{
// Restore stdin settings
if (DidNetInit)
{
tcsetattr (STDIN_FILENO, TCSANOW, &OldTermIOS);
printf ("\n");
DidNetInit = false;
}
}
//===========================================================================
//
// FTTYStartupScreen :: NetMessage
//
// Call this between NetInit() and NetDone() instead of Printf() to
// display messages, because the progress meter is mixed in the same output
// stream as normal messages.
//
//===========================================================================
void FTTYStartupScreen::NetMessage(const char *format, ...)
{
FString str;
va_list argptr;
va_start (argptr, format);
str.VFormat (format, argptr);
va_end (argptr);
fprintf (stderr, "\r%-40s\n", str.GetChars());
}
//===========================================================================
//
// FTTYStartupScreen :: NetProgress
//
// Sets the network progress meter. If count is 0, it gets bumped by 1.
// Otherwise, it is set to count.
//
//===========================================================================
void FTTYStartupScreen::NetProgress(int count)
{
int i;
if (count == 0)
{
NetCurPos++;
}
else if (count > 0)
{
NetCurPos = count;
}
if (NetMaxPos == 0)
{
// Spinny-type progress meter, because we're a guest waiting for the host.
fprintf (stderr, "\r%s: %c", TheNetMessage, SpinnyProgressChars[NetCurPos & 3]);
fflush (stderr);
}
else if (NetMaxPos > 1)
{
// Dotty-type progress meter.
fprintf (stderr, "\r%s: ", TheNetMessage);
for (i = 0; i < NetCurPos; ++i)
{
fputc ('.', stderr);
}
fprintf (stderr, "%*c[%2d/%2d]", NetMaxPos + 1 - NetCurPos, ' ', NetCurPos, NetMaxPos);
fflush (stderr);
}
}
//===========================================================================
//
// FTTYStartupScreen :: NetLoop
//
// The timer_callback function is called at least two times per second
// and passed the userdata value. It should return true to stop the loop and
// return control to the caller or false to continue the loop.
//
// ST_NetLoop will return true if the loop was halted by the callback and
// false if the loop was halted because the user wants to abort the
// network synchronization.
//
//===========================================================================
bool FTTYStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
{
fd_set rfds;
struct timeval tv;
int retval;
char k;
for (;;)
{
// Don't flood the network with packets on startup.
tv.tv_sec = 0;
tv.tv_usec = 500000;
FD_ZERO (&rfds);
FD_SET (STDIN_FILENO, &rfds);
retval = select (1, &rfds, NULL, NULL, &tv);
#ifdef __ANDROID__
usleep(1000*200);
//The select command is to wait for the console input to be ready, obv don't need this on droid
retval = 0;
#endif
if (retval == -1)
{
// Error
}
else if (retval == 0)
{
if (timer_callback (userdata))
{
fputc ('\n', stderr);
return true;
}
}
else if (read (STDIN_FILENO, &k, 1) == 1)
{
// Check input on stdin
if (k == 'q' || k == 'Q')
{
fprintf (stderr, "\nNetwork game synchronization aborted.");
return false;
}
}
}
}
void ST_Endoom()
{
I_ShutdownJoysticks();
call_terms();
exit(0);
}

View file

@ -0,0 +1,274 @@
/*
** sdlvideo.cpp
**
**---------------------------------------------------------------------------
** Copyright 2005-2016 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
// HEADER FILES ------------------------------------------------------------
#include "doomtype.h"
#include "templates.h"
#include "i_system.h"
#include "i_video.h"
#include "v_video.h"
#include "v_pfx.h"
#include "stats.h"
#include "v_palette.h"
#include "video.h"
#include "swrenderer/r_swrenderer.h"
#include "version.h"
#include <QzDoom/VrCommon.h>
#include <SDL.h>
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
struct MiniModeInfo
{
uint16_t Width, Height;
};
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern IVideo *Video;
extern bool GUICapture;
EXTERN_CVAR (Float, Gamma)
EXTERN_CVAR (Int, vid_maxfps)
EXTERN_CVAR (Bool, cl_capfps)
EXTERN_CVAR (Bool, vid_vsync)
// PUBLIC DATA DEFINITIONS -------------------------------------------------
CVAR (Int, vid_adapter, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, vid_displaybits, 32, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, vid_forcesurface, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CUSTOM_CVAR (Float, rgamma, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (screen != NULL)
{
screen->SetGamma (Gamma);
}
}
CUSTOM_CVAR (Float, ggamma, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (screen != NULL)
{
screen->SetGamma (Gamma);
}
}
CUSTOM_CVAR (Float, bgamma, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (screen != NULL)
{
screen->SetGamma (Gamma);
}
}
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static cycle_t BlitCycles;
static cycle_t SDLFlipCycles;
// CODE --------------------------------------------------------------------
// FrameBuffer implementation -----------------------------------------------
OculusQuestFB::OculusQuestFB (int width, int height, bool bgra, bool fullscreen, SDL_Window *oldwin)
: OculusQuestBaseFB (width, height, bgra)
{
int i;
NeedPalUpdate = false;
NeedGammaUpdate = false;
UpdatePending = false;
NotPaletted = false;
FlashAmount = 0;
Renderer = NULL;
Texture = NULL;
for (i = 0; i < 256; i++)
{
GammaTable[0][i] = GammaTable[1][i] = GammaTable[2][i] = i;
}
memcpy (SourcePalette, GPalette.BaseColors, sizeof(PalEntry)*256);
UpdateColors ();
#ifdef __APPLE__
SetVSync (vid_vsync);
#endif
}
OculusQuestFB::~OculusQuestFB ()
{
}
bool OculusQuestFB::IsValid ()
{
return DFrameBuffer::IsValid();
}
int OculusQuestFB::GetPageCount ()
{
return 1;
}
bool OculusQuestFB::Lock (bool buffered)
{
return DSimpleCanvas::Lock ();
}
bool OculusQuestFB::Relock ()
{
return DSimpleCanvas::Lock ();
}
void OculusQuestFB::Unlock ()
{
--LockCount;
}
void OculusQuestFB::Update ()
{
}
void OculusQuestFB::UpdateColors ()
{
}
PalEntry *OculusQuestFB::GetPalette ()
{
return SourcePalette;
}
void OculusQuestFB::UpdatePalette ()
{
NeedPalUpdate = true;
}
bool OculusQuestFB::SetGamma (float gamma)
{
Gamma = gamma;
NeedGammaUpdate = true;
return true;
}
bool OculusQuestFB::SetFlash (PalEntry rgb, int amount)
{
Flash = rgb;
FlashAmount = amount;
NeedPalUpdate = true;
return true;
}
void OculusQuestFB::GetFlash (PalEntry &rgb, int &amount)
{
rgb = Flash;
amount = FlashAmount;
}
// Q: Should I gamma adjust the returned palette?
void OculusQuestFB::GetFlashedPalette (PalEntry pal[256])
{
}
void OculusQuestFB::SetFullscreen (bool fullscreen)
{
}
bool OculusQuestFB::IsFullscreen ()
{
return true;
}
void OculusQuestFB::ResetSDLRenderer ()
{
}
void OculusQuestFB::SetVSync (bool vsync)
{
}
void OculusQuestFB::ScaleCoordsFromWindow(int16_t &x, int16_t &y)
{
uint32_t w, h;
Android_GetScreenRes(&w, &h);
// Detect if we're doing scaling in the Window and adjust the mouse
// coordinates accordingly. This could be more efficent, but I
// don't think performance is an issue in the menus.
if(IsFullscreen())
{
int realw = w, realh = h;
ScaleWithAspect (realw, realh, SCREENWIDTH, SCREENHEIGHT);
if (realw != SCREENWIDTH || realh != SCREENHEIGHT)
{
double xratio = (double)SCREENWIDTH/realw;
double yratio = (double)SCREENHEIGHT/realh;
if (realw < w)
{
x = (x - (w - realw)/2)*xratio;
y *= yratio;
}
else
{
y = (y - (h - realh)/2)*yratio;
x *= xratio;
}
}
}
else
{
x = (int16_t)(x*Width/w);
y = (int16_t)(y*Height/h);
}
}
// each platform has its own specific version of this function.
void I_SetWindowTitle(const char* caption)
{
}

View file

@ -0,0 +1,60 @@
#include "hardware.h"
#include "v_video.h"
#include "glvideo.h"
class OculusQuestFB : public OculusQuestBaseFB
{
typedef OculusQuestBaseFB Super;
public:
OculusQuestFB(int width, int height, bool bgra, bool fullscreen, SDL_Window *oldwin);
~OculusQuestFB();
bool Lock(bool buffer);
void Unlock();
bool Relock();
void ForceBuffering(bool force);
bool IsValid();
void Update();
PalEntry *GetPalette();
void GetFlashedPalette(PalEntry pal[256]);
void UpdatePalette();
bool SetGamma(float gamma);
bool SetFlash(PalEntry rgb, int amount);
void GetFlash(PalEntry &rgb, int &amount);
void SetFullscreen(bool fullscreen);
int GetPageCount();
bool IsFullscreen();
friend class OculusQuestGLVideo;
virtual void SetVSync(bool vsync);
virtual void ScaleCoordsFromWindow(int16_t &x, int16_t &y);
SDL_Window *GetSDLWindow() override { return Screen; }
private:
PalEntry SourcePalette[256];
uint8_t GammaTable[3][256];
PalEntry Flash;
int FlashAmount;
float Gamma;
bool UpdatePending;
SDL_Window *Screen;
SDL_Renderer *Renderer;
union
{
SDL_Texture *Texture;
SDL_Surface *Surface;
};
bool UsingRenderer;
bool NeedPalUpdate;
bool NeedGammaUpdate;
bool NotPaletted;
void UpdateColors();
void ResetSDLRenderer();
OculusQuestFB() {}
};

View file

@ -41,6 +41,8 @@
#include <stdio.h>
#include <gl/system/gl_framebuffer.h>
#include <QzDoom/VrCommon.h>
#include "i_system.h"
#include "x86.h"
@ -170,8 +172,8 @@ static uint32_t Col2RGB8_2[63][256];
// There's also only one, not four.
DFrameBuffer *screen;
CVAR (Int, vid_defwidth, 640, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, vid_defheight, 480, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, vid_defwidth, 1280, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, vid_defheight, 1280, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, vid_defbits, 8, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, vid_fps, false, 0)
CVAR (Bool, ticker, false, 0)
@ -1432,6 +1434,7 @@ bool IVideo::SetResolution (int width, int height, int bits)
oldbits = bits;
}
I_ClosestResolution (&width, &height, bits);
if (!I_CheckResolution (width, height, bits))
{ // Try specified resolution
@ -1446,6 +1449,8 @@ bool IVideo::SetResolution (int width, int height, int bits)
bits = oldbits;
}
}
return V_DoModeSetup (width, height, bits);
}
@ -1523,8 +1528,10 @@ void V_Init (bool restart)
{
if (height == 0)
{
width = vid_defwidth;
height = vid_defheight;
uint32_t uWidth, uHeight;
Android_GetScreenRes(&uWidth, &uHeight);
width = uWidth;
height = uHeight;
}
else
{

View file

@ -97,11 +97,8 @@ const char *GetVersionString();
// More stuff that needs to be different for derivatives.
#define GAMENAME "LZDoom"
#define WGAMENAME L"LZDoom"
#define GAMENAMELOWERCASE "lzdoom"
#define FORUM_URL "http://forum.zdoom.org/"
#define BUGS_FORUM_URL "http://forum.zdoom.org/viewforum.php?f=2"
#define GAMENAME "QzDoom"
#define GAMENAMELOWERCASE "qzdoom"
#if defined(__APPLE__) || defined(_WIN32)
#define GAME_DIR GAMENAME

View file

@ -1 +1 @@
qzdoom --supersampling 1.4 -iwad freedom2.wad
qzdoom --supersampling 1.3 -iwad DOOM.WAD

BIN
assets/res/brightmaps.pk3 Normal file

Binary file not shown.

BIN
assets/res/lights.pk3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -166,6 +166,8 @@ import static android.system.Os.setenv;
new File("/sdcard/QzDoom/res").mkdirs();
copy_asset("/sdcard/QzDoom", "res/lzdoom.pk3");
copy_asset("/sdcard/QzDoom", "res/lz_game_support.pk3");
copy_asset("/sdcard/QzDoom", "res/lights.pk3");
copy_asset("/sdcard/QzDoom", "res/brightmaps.pk3");
//Read these from a file and pass through
commandLineParams = new String("doom");