From 5f41c554683756bff120185610168cf43ba763b7 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 6 Mar 2020 17:44:48 +0000 Subject: [PATCH] Removing SDL - Doom now starts! --- .../Android/jni/QzDoom/QzDoom_SurfaceView.c | 227 +-- Projects/Android/jni/QzDoom/VrCommon.h | 3 +- Projects/Android/jni/QzDoom/VrCompositor.c | 4 +- Projects/Android/jni/QzDoom/VrCompositor.h | 3 +- Projects/Android/jni/QzDoom/VrInput.h | 3 - Projects/Android/jni/QzDoom/VrInputCommon.c | 18 - Projects/Android/jni/QzDoom/VrInputDefault.c | 21 +- .../mobile/Android_src.mk | 28 +- .../jni/gzdoom-g3.3mgw_mobile/src/d_main.cpp | 5 +- .../jni/gzdoom-g3.3mgw_mobile/src/d_stats.cpp | 360 ---- .../src/gl/stereo3d/gl_oculusquest.cpp | 5 +- .../src/gl/stereo3d/gl_oculusquest.h | 2 +- .../src/gl/system/gl_framebuffer.h | 4 +- .../src/gl/system/gl_load.c | 74 +- .../src/gl/system/gl_swframebuffer.h | 4 +- .../gzdoom-g3.3mgw_mobile/src/menu/menu.cpp | 6 +- .../src/posix/cocoa/i_common.h | 77 - .../src/posix/cocoa/i_input.mm | 789 --------- .../src/posix/cocoa/i_joystick.cpp | 1254 -------------- .../src/posix/cocoa/i_main.mm | 531 ------ .../src/posix/cocoa/i_main_except.cpp | 79 - .../src/posix/cocoa/i_system.mm | 376 ----- .../src/posix/cocoa/i_video.mm | 1448 ----------------- .../src/posix/cocoa/sdlglvideo.h | 90 - .../src/posix/cocoa/st_console.h | 96 -- .../src/posix/cocoa/st_console.mm | 533 ------ .../src/posix/cocoa/st_start.mm | 194 --- .../{oculusquest => nosdl}/crashcatcher.c | 0 .../posix/{oculusquest => nosdl}/glvideo.cpp | 64 +- .../{sdl/sdlglvideo.h => nosdl/glvideo.h} | 31 +- .../posix/{oculusquest => nosdl}/hardware.cpp | 34 +- .../posix/{oculusquest => nosdl}/i_gui.cpp | 6 +- .../posix/{oculusquest => nosdl}/i_input.cpp | 0 .../{sdl/i_gui.cpp => nosdl/i_joystick.cpp} | 129 +- .../posix/{oculusquest => nosdl}/i_main.cpp | 2 +- .../src/posix/{sdl => nosdl}/i_system.cpp | 12 +- .../posix/{oculusquest => nosdl}/i_system.mm | 0 .../posix/{oculusquest => nosdl}/st_start.cpp | 0 .../posix/{oculusquest => nosdl}/video.cpp | 50 +- .../src/posix/{oculusquest => nosdl}/video.h | 28 +- .../src/posix/oculusquest/glvideo.h | 98 -- .../src/posix/oculusquest/i_joystick.cpp | 349 ---- .../src/posix/oculusquest/i_system.cpp | 496 ------ .../src/posix/osx/i_specialpaths.mm | 238 --- .../src/posix/osx/iwadpicker_cocoa.mm | 470 ------ .../src/posix/osx/zdoom-info.plist | 52 - .../src/posix/osx/zdoom.icns | Bin 90352 -> 0 bytes .../src/posix/sdl/crashcatcher.c | 428 ----- .../src/posix/sdl/hardware.cpp | 399 ----- .../src/posix/sdl/i_input.cpp | 590 ------- .../src/posix/sdl/i_joystick.cpp | 349 ---- .../src/posix/sdl/i_main.cpp | 294 ---- .../src/posix/sdl/i_system.mm | 19 - .../src/posix/sdl/sdlglvideo.cpp | 591 ------- .../src/posix/sdl/sdlvideo.cpp | 580 ------- .../src/posix/sdl/sdlvideo.h | 60 - .../src/posix/sdl/st_start.cpp | 382 ----- .../src/sound/opnmidi/opnbank.h | 12 - 58 files changed, 302 insertions(+), 11695 deletions(-) delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_common.h delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_input.mm delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_joystick.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_main.mm delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_main_except.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_system.mm delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_video.mm delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/sdlglvideo.h delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_console.h delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_console.mm delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_start.mm rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/crashcatcher.c (100%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/glvideo.cpp (81%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{sdl/sdlglvideo.h => nosdl/glvideo.h} (76%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/hardware.cpp (90%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/i_gui.cpp (98%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/i_input.cpp (100%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{sdl/i_gui.cpp => nosdl/i_joystick.cpp} (56%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/i_main.cpp (99%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{sdl => nosdl}/i_system.cpp (98%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/i_system.mm (100%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/st_start.cpp (100%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/video.cpp (83%) rename Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/{oculusquest => nosdl}/video.h (68%) delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/glvideo.h delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_joystick.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_system.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/i_specialpaths.mm delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/iwadpicker_cocoa.mm delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/zdoom-info.plist delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/zdoom.icns delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/crashcatcher.c delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/hardware.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_input.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_joystick.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_main.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_system.mm delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlglvideo.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlvideo.cpp delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlvideo.h delete mode 100644 Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/st_start.cpp diff --git a/Projects/Android/jni/QzDoom/QzDoom_SurfaceView.c b/Projects/Android/jni/QzDoom/QzDoom_SurfaceView.c index d056d8f..396ca6a 100644 --- a/Projects/Android/jni/QzDoom/QzDoom_SurfaceView.c +++ b/Projects/Android/jni/QzDoom/QzDoom_SurfaceView.c @@ -40,9 +40,8 @@ Copyright : Copyright 2015 Oculus VR, LLC. All Rights reserved. //#include -#include -#include -//#include +//#include +//#include #include "VrCompositor.h" #include "VrInput.h" @@ -509,7 +508,8 @@ static void ovrFramebuffer_Clear( ovrFramebuffer * frameBuffer ) frameBuffer->Height = 0; frameBuffer->Multisamples = 0; frameBuffer->TextureSwapChainLength = 0; - frameBuffer->TextureSwapChainIndex = 0; + frameBuffer->ProcessingTextureSwapChainIndex = 0; + frameBuffer->ReadyTextureSwapChainIndex = 0; frameBuffer->ColorTextureSwapChain = NULL; frameBuffer->DepthBuffers = NULL; frameBuffer->FrameBuffers = NULL; @@ -598,7 +598,7 @@ void ovrFramebuffer_Destroy( ovrFramebuffer * frameBuffer ) void ovrFramebuffer_SetCurrent( ovrFramebuffer * frameBuffer ) { //LOAD_GLES2(glBindFramebuffer); - GL( /*gles_*/glBindFramebuffer( GL_DRAW_FRAMEBUFFER, frameBuffer->FrameBuffers[frameBuffer->TextureSwapChainIndex] ) ); + GL( /*gles_*/glBindFramebuffer( GL_DRAW_FRAMEBUFFER, frameBuffer->FrameBuffers[frameBuffer->ProcessingTextureSwapChainIndex] ) ); } void ovrFramebuffer_SetNone() @@ -620,7 +620,8 @@ void ovrFramebuffer_Resolve( ovrFramebuffer * frameBuffer ) void ovrFramebuffer_Advance( ovrFramebuffer * frameBuffer ) { // Advance to the next texture from the set. - frameBuffer->TextureSwapChainIndex = ( frameBuffer->TextureSwapChainIndex + 1 ) % frameBuffer->TextureSwapChainLength; + frameBuffer->ReadyTextureSwapChainIndex = frameBuffer->ProcessingTextureSwapChainIndex; + frameBuffer->ProcessingTextureSwapChainIndex = ( frameBuffer->ProcessingTextureSwapChainIndex + 1 ) % frameBuffer->TextureSwapChainLength; } @@ -1327,47 +1328,6 @@ static ovrApp gAppState; static ovrJava java; static bool destroyed = false; - -void RenderFrame() -{ - //Qcommon_BeginFrame (time * 1000); - - ovrRenderer *renderer = useScreenLayer() ? &gAppState.Scene.CylinderRenderer : &gAppState.Renderer; - - // Render the eye images. - for (int eye = 0; eye < renderer->NumBuffers; eye++) { - ovrFramebuffer *frameBuffer = &(renderer->FrameBuffer[eye]); - ovrFramebuffer_SetCurrent(frameBuffer); - - { - GL(glEnable(GL_SCISSOR_TEST)); - GL(glDepthMask(GL_TRUE)); - GL(glEnable(GL_DEPTH_TEST)); - GL(glDepthFunc(GL_LEQUAL)); - - //Weusing the size of the render target - GL(glViewport(0, 0, frameBuffer->Width, frameBuffer->Height)); - GL(glScissor(0, 0, frameBuffer->Width, frameBuffer->Height)); - - GL(glClearColor(0.0f, 0.0f, 0.0f, 1.0f)); - GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); - GL(glDisable(GL_SCISSOR_TEST)); - - //Now do the drawing for this eye (or draw for left eye twice if using screen layer) - //Qcommon_Frame(useScreenLayer() ? 0 : eye); - } - - //Clear edge to prevent smearing - ovrFramebuffer_ClearEdgeTexels(frameBuffer); - ovrFramebuffer_Resolve(frameBuffer); - ovrFramebuffer_Advance(frameBuffer); - } - - - ovrFramebuffer_SetNone(); -} - - void prepareEyeBuffer(int eye ) { ovrRenderer *renderer = useScreenLayer() ? &gAppState.Scene.CylinderRenderer : &gAppState.Renderer; @@ -1482,9 +1442,9 @@ void * AppThreadFunction(void * parm ) { jclass cls = (*java.Env)->GetObjectClass(java.Env, java.ActivityObject); /* This interface could expand with ABI negotiation, callbacks, etc. */ - SDL_Android_Init(java.Env, cls); +// SDL_Android_Init(java.Env, cls); - SDL_SetMainReady(); +// SDL_SetMainReady(); // Note that AttachCurrentThread will reset the thread name. prctl(PR_SET_NAME, (long) "OVR::Main", 0, 0, 0); @@ -1634,75 +1594,6 @@ void shutdownVR() { vrapi_Shutdown(); } -ovrSubmitFrameDescription2 setupFrameDescriptor(ovrTracking2 *tracking) { - ovrSubmitFrameDescription2 frameDesc = {0 }; - if (!useScreenLayer()) { - - ovrLayerProjection2 layer = vrapi_DefaultLayerProjection2(); - layer.HeadPose = (*tracking).HeadPose; - for ( int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; eye++ ) - { - ovrFramebuffer * frameBuffer = &gAppState.Renderer.FrameBuffer[gAppState.Renderer.NumBuffers == 1 ? 0 : eye]; - layer.Textures[eye].ColorSwapChain = frameBuffer->ColorTextureSwapChain; - layer.Textures[eye].SwapChainIndex = frameBuffer->TextureSwapChainIndex; - - ovrMatrix4f projectionMatrix; - projectionMatrix = ovrMatrix4f_CreateProjectionFov(vrFOV, vrFOV, - 0.0f, 0.0f, 0.1f, 0.0f); - - layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection(&projectionMatrix); - - layer.Textures[eye].TextureRect.x = 0; - layer.Textures[eye].TextureRect.y = 0; - layer.Textures[eye].TextureRect.width = 1.0f; - layer.Textures[eye].TextureRect.height = 1.0f; - } - layer.Header.Flags |= VRAPI_FRAME_LAYER_FLAG_CHROMATIC_ABERRATION_CORRECTION; - - // Set up the description for this frame. - const ovrLayerHeader2 *layers[] = - { - &layer.Header - }; - - ovrSubmitFrameDescription2 frameDesc = {}; - frameDesc.Flags = 0; - frameDesc.SwapInterval = gAppState.SwapInterval; - frameDesc.FrameIndex = gAppState.FrameIndex; - frameDesc.DisplayTime = gAppState.DisplayTime; - frameDesc.LayerCount = 1; - frameDesc.Layers = layers; - - } else { - // Set-up the compositor layers for this frame. - // NOTE: Multiple independent layers are allowed, but they need to be added - // in a depth consistent order. - memset( gAppState.Layers, 0, sizeof( ovrLayer_Union2 ) * ovrMaxLayerCount ); - gAppState.LayerCount = 0; - - // Add a simple cylindrical layer - gAppState.Layers[gAppState.LayerCount++].Cylinder = - BuildCylinderLayer(&gAppState.Scene.CylinderRenderer, - gAppState.Scene.CylinderWidth, gAppState.Scene.CylinderHeight, tracking, radians(playerYaw) ); - - // Compose the layers for this frame. - const ovrLayerHeader2 * layerHeaders[ovrMaxLayerCount] = { 0 }; - for ( int i = 0; i < gAppState.LayerCount; i++ ) - { - layerHeaders[i] = &gAppState.Layers[i].Header; - } - - // Set up the description for this frame. - frameDesc.Flags = 0; - frameDesc.SwapInterval = gAppState.SwapInterval; - frameDesc.FrameIndex = gAppState.FrameIndex; - frameDesc.DisplayTime = gAppState.DisplayTime; - frameDesc.LayerCount = gAppState.LayerCount; - frameDesc.Layers = layerHeaders; - } - return frameDesc; -} - void incrementFrameIndex() { // This is the only place the frame index is incremented, right before @@ -1731,33 +1622,81 @@ void getTrackedRemotesOrientation(int vr_control_scheme) {//Get info for tracked } } -void submitFrame(ovrSubmitFrameDescription2 *frameDesc) +void submitFrame(ovrTracking2 *tracking) { - // Hand over the eye images to the time warp. - vrapi_SubmitFrame2(gAppState.Ovr, frameDesc); + ovrSubmitFrameDescription2 frameDesc = {0}; + + if (!useScreenLayer()) { + + ovrLayerProjection2 layer = vrapi_DefaultLayerProjection2(); + layer.HeadPose = (*tracking).HeadPose; + for ( int eye = 0; eye < VRAPI_FRAME_LAYER_EYE_MAX; eye++ ) + { + ovrFramebuffer * frameBuffer = &gAppState.Renderer.FrameBuffer[gAppState.Renderer.NumBuffers == 1 ? 0 : eye]; + layer.Textures[eye].ColorSwapChain = frameBuffer->ColorTextureSwapChain; + layer.Textures[eye].SwapChainIndex = frameBuffer->ReadyTextureSwapChainIndex; + + ovrMatrix4f projectionMatrix; + projectionMatrix = ovrMatrix4f_CreateProjectionFov(vrFOV, vrFOV, + 0.0f, 0.0f, 0.1f, 0.0f); + + layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection(&projectionMatrix); + + layer.Textures[eye].TextureRect.x = 0; + layer.Textures[eye].TextureRect.y = 0; + layer.Textures[eye].TextureRect.width = 1.0f; + layer.Textures[eye].TextureRect.height = 1.0f; + } + layer.Header.Flags |= VRAPI_FRAME_LAYER_FLAG_CHROMATIC_ABERRATION_CORRECTION; + + // Set up the description for this frame. + const ovrLayerHeader2 *layers[] = + { + &layer.Header + }; + + frameDesc.Flags = 0; + frameDesc.SwapInterval = gAppState.SwapInterval; + frameDesc.FrameIndex = gAppState.FrameIndex; + frameDesc.DisplayTime = gAppState.DisplayTime; + frameDesc.LayerCount = 1; + frameDesc.Layers = layers; + + // Hand over the eye images to the time warp. + vrapi_SubmitFrame2(gAppState.Ovr, &frameDesc); + + } else { + // Set-up the compositor layers for this frame. + // NOTE: Multiple independent layers are allowed, but they need to be added + // in a depth consistent order. + memset( gAppState.Layers, 0, sizeof( ovrLayer_Union2 ) * ovrMaxLayerCount ); + gAppState.LayerCount = 0; + + // Add a simple cylindrical layer + gAppState.Layers[gAppState.LayerCount++].Cylinder = + BuildCylinderLayer(&gAppState.Scene.CylinderRenderer, + gAppState.Scene.CylinderWidth, gAppState.Scene.CylinderHeight, tracking, radians(playerYaw) ); + + // Compose the layers for this frame. + const ovrLayerHeader2 * layerHeaders[ovrMaxLayerCount] = { 0 }; + for ( int i = 0; i < gAppState.LayerCount; i++ ) + { + layerHeaders[i] = &gAppState.Layers[i].Header; + } + + // Set up the description for this frame. + frameDesc.Flags = 0; + frameDesc.SwapInterval = gAppState.SwapInterval; + frameDesc.FrameIndex = gAppState.FrameIndex; + frameDesc.DisplayTime = gAppState.DisplayTime; + frameDesc.LayerCount = gAppState.LayerCount; + frameDesc.Layers = layerHeaders; + + // Hand over the eye images to the time warp. + vrapi_SubmitFrame2(gAppState.Ovr, &frameDesc); + } } -//Need to replicate this code in gl_oculusquest.cpp -void vr_main() -{/* - if (!destroyed) - { - processHaptics(); - - ovrTracking2 tracking; - getHMDOrientation(&tracking); - getTrackedRemotesOrientation(); - - ovrSubmitFrameDescription2 frameDesc = setupFrameDescriptor(&tracking); - - //Call the game drawing code - RenderFrame(); - - // Hand over the eye images to the time warp. - submitFrame(&frameDesc); - } - */ -} static void ovrAppThread_Create( ovrAppThread * appThread, JNIEnv * env, jobject activityObject, jclass activityClass ) { @@ -1791,7 +1730,7 @@ Activity lifecycle ================================================================================ */ -JNIEXPORT jint JNICALL SDL_JNI_OnLoad(JavaVM* vm, void* reserved); +//JNIEXPORT jint JNICALL SDL_JNI_OnLoad(JavaVM* vm, void* reserved); int JNI_OnLoad(JavaVM* vm, void* reserved) { @@ -1802,7 +1741,7 @@ int JNI_OnLoad(JavaVM* vm, void* reserved) return -1; } - return SDL_JNI_OnLoad(vm, reserved); + return JNI_VERSION_1_4; } JNIEXPORT jlong JNICALL Java_com_drbeef_qzdoom_GLES3JNILib_onCreate( JNIEnv * env, jclass activityClass, jobject activity, diff --git a/Projects/Android/jni/QzDoom/VrCommon.h b/Projects/Android/jni/QzDoom/VrCommon.h index cb6f616..0916c61 100644 --- a/Projects/Android/jni/QzDoom/VrCommon.h +++ b/Projects/Android/jni/QzDoom/VrCommon.h @@ -86,10 +86,9 @@ void getTrackedRemotesOrientation(int vr_control_scheme); void incrementFrameIndex(); -ovrSubmitFrameDescription2 setupFrameDescriptor(ovrTracking2 *tracking); void prepareEyeBuffer(int eye ); void finishEyeBuffer(int eye ); -void submitFrame(ovrSubmitFrameDescription2 *frameDesc); +void submitFrame(ovrTracking2 *tracking); #ifdef __cplusplus } // extern "C" diff --git a/Projects/Android/jni/QzDoom/VrCompositor.c b/Projects/Android/jni/QzDoom/VrCompositor.c index 314ff5b..8392f28 100644 --- a/Projects/Android/jni/QzDoom/VrCompositor.c +++ b/Projects/Android/jni/QzDoom/VrCompositor.c @@ -465,7 +465,7 @@ ovrLayerProjection2 ovrRenderer_RenderGroundPlaneToEyeBuffer( ovrRenderer * rend { ovrFramebuffer * frameBuffer = &renderer->FrameBuffer[eye]; layer.Textures[eye].ColorSwapChain = frameBuffer->ColorTextureSwapChain; - layer.Textures[eye].SwapChainIndex = frameBuffer->TextureSwapChainIndex; + layer.Textures[eye].SwapChainIndex = frameBuffer->ProcessingTextureSwapChainIndex; layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_TanAngleMatrixFromProjection( &tracking->Eye[eye].ProjectionMatrix ); } layer.Header.Flags |= VRAPI_FRAME_LAYER_FLAG_CHROMATIC_ABERRATION_CORRECTION; @@ -572,7 +572,7 @@ ovrLayerCylinder2 BuildCylinderLayer( ovrRenderer * cylinderRenderer, ovrMatrix4f modelViewMatrix = ovrMatrix4f_Multiply( &tracking->Eye[eye].ViewMatrix, &cylinderTransform ); layer.Textures[eye].TexCoordsFromTanAngles = ovrMatrix4f_Inverse( &modelViewMatrix ); layer.Textures[eye].ColorSwapChain = cylinderFrameBuffer->ColorTextureSwapChain; - layer.Textures[eye].SwapChainIndex = cylinderFrameBuffer->TextureSwapChainIndex; + layer.Textures[eye].SwapChainIndex = cylinderFrameBuffer->ReadyTextureSwapChainIndex; // Texcoord scale and bias is just a representation of the aspect ratio. The positioning // of the cylinder is handled entirely by the TexCoordsFromTanAngles matrix. diff --git a/Projects/Android/jni/QzDoom/VrCompositor.h b/Projects/Android/jni/QzDoom/VrCompositor.h index f7755f2..9169dae 100644 --- a/Projects/Android/jni/QzDoom/VrCompositor.h +++ b/Projects/Android/jni/QzDoom/VrCompositor.h @@ -59,7 +59,8 @@ typedef struct int Height; int Multisamples; int TextureSwapChainLength; - int TextureSwapChainIndex; + int ProcessingTextureSwapChainIndex; + int ReadyTextureSwapChainIndex; ovrTextureSwapChain * ColorTextureSwapChain; GLuint * DepthBuffers; GLuint * FrameBuffers; diff --git a/Projects/Android/jni/QzDoom/VrInput.h b/Projects/Android/jni/QzDoom/VrInput.h index 12aee2c..8625693 100644 --- a/Projects/Android/jni/QzDoom/VrInput.h +++ b/Projects/Android/jni/QzDoom/VrInput.h @@ -21,9 +21,6 @@ float positional_movementSideways; float positional_movementForward; float snapTurn; -void sendButtonAction(const char* action, long buttonDown); -void sendButtonActionSimple(const char* action); - void acquireTrackedRemotesData(const ovrMobile *Ovr, double displayTime); void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, ovrInputStateTrackedRemote *pDominantTrackedRemoteOld, ovrTracking* pDominantTracking, diff --git a/Projects/Android/jni/QzDoom/VrInputCommon.c b/Projects/Android/jni/QzDoom/VrInputCommon.c index fa36c33..83d17a0 100644 --- a/Projects/Android/jni/QzDoom/VrInputCommon.c +++ b/Projects/Android/jni/QzDoom/VrInputCommon.c @@ -81,29 +81,11 @@ float nonLinearFilter(float in) return val; } -void sendButtonActionSimple(const char* action) -{ - char command[256]; - snprintf( command, sizeof( command ), "%s\n", action ); -// Cbuf_AddText( command ); -} - bool between(float min, float val, float max) { return (min < val) && (val < max); } -void sendButtonAction(const char* action, long buttonDown) -{ - char command[256]; - snprintf( command, sizeof( command ), "%s\n", action ); - if (!buttonDown) - { - command[0] = '-'; - } -// Cbuf_AddText( command ); -} - void acquireTrackedRemotesData(const ovrMobile *Ovr, double displayTime) {//The amount of yaw changed by controller for ( int i = 0; ; i++ ) { ovrInputCapabilityHeader cap; diff --git a/Projects/Android/jni/QzDoom/VrInputDefault.c b/Projects/Android/jni/QzDoom/VrInputDefault.c index 8335360..4e0a80c 100644 --- a/Projects/Android/jni/QzDoom/VrInputDefault.c +++ b/Projects/Android/jni/QzDoom/VrInputDefault.c @@ -189,11 +189,13 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, if (inventoryManagementMode) { if (firingPrimary) - sendButtonActionSimple("invuse"); + { + //Select inventory item + } } else { - sendButtonAction("+attack", firingPrimary); + //fire primary } } } @@ -202,8 +204,10 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, if ((pDominantTrackedRemoteNew->Buttons & domButton1) != (pDominantTrackedRemoteOld->Buttons & domButton1) && ducked != DUCK_CROUCHED) { + ducked = (pDominantTrackedRemoteNew->Buttons & domButton1) ? DUCK_BUTTON : DUCK_NOTDUCKED; - sendButtonAction("+movedown", (pDominantTrackedRemoteNew->Buttons & domButton1)); + + //Trigger Duck } //Weapon/Inventory Chooser @@ -217,11 +221,11 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, { if (inventoryManagementMode) { - sendButtonActionSimple("invprev"); + //Previous Inventory Item } else { - sendButtonActionSimple("weapprev"); + //Next Inventory Item } } @@ -229,11 +233,11 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, { if (inventoryManagementMode) { - sendButtonActionSimple("invnext"); + //Next Inventory Item } else { - sendButtonActionSimple("weapnext"); + //Next Weapon } } itemSwitched = true; @@ -279,7 +283,8 @@ void HandleInput_Default( ovrInputStateTrackedRemote *pDominantTrackedRemoteNew, //show help computer while X/A pressed if ((pOffTrackedRemoteNew->Buttons & offButton1) != (pOffTrackedRemoteOld->Buttons & offButton1)) { - sendButtonActionSimple("cmd help"); + + //Help Computer } diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/mobile/Android_src.mk b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/mobile/Android_src.mk index 0611747..1b41432 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/mobile/Android_src.mk +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/mobile/Android_src.mk @@ -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\oculusquest \ + $(GZDOOM_TOP_PATH)/src/posix\nosdl \ $(SDL_INCLUDE_PATHS) \ $(SUPPORT_LIBS)/fluidsynth-lite/include \ $(SUPPORT_LIBS)/openal/include/AL \ @@ -71,17 +71,15 @@ PLAT_POSIX_SOURCES = \ posix/i_cd.cpp \ posix/i_steam.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 +PLAT_NOSDL_SOURCES = \ + posix/nosdl/crashcatcher.c \ + posix/nosdl/hardware.cpp \ + posix/nosdl/i_gui.cpp \ + posix/nosdl/i_joystick.cpp \ + posix/nosdl/i_system.cpp \ + posix/nosdl/glvideo.cpp \ + posix/nosdl/video.cpp \ + posix/nosdl/st_start.cpp SWRENDER_SOURCES = \ swrenderer/r_swcanvas.cpp \ @@ -595,7 +593,7 @@ LOCAL_SRC_FILES = \ $(QZDOOM_SRC) \ $(ANDROID_SRC_FILES) \ $(PLAT_POSIX_SOURCES) \ - $(PLAT_OCULUSQUEST_SOURCES) \ + $(PLAT_NOSDL_SOURCES) \ $(FASTMATH_SOURCES) \ $(PCH_SOURCES) \ x86.cpp \ @@ -634,8 +632,8 @@ LOCAL_LDLIBS += -lEGL # This is stop a linker warning for mp123 lib failing build #LOCAL_LDLIBS += -Wl,--no-warn-shared-textrel -LOCAL_STATIC_LIBRARIES := sndfile mpg123 fluidsynth-static SDL2_net libjpeg zlib_lz lzma_lz gdtoa_lz dumb_lz gme_lz bzip2_lz -LOCAL_SHARED_LIBRARIES := openal SDL2 vrapi +LOCAL_STATIC_LIBRARIES := sndfile mpg123 fluidsynth-static libjpeg zlib_lz lzma_lz gdtoa_lz dumb_lz gme_lz bzip2_lz +LOCAL_SHARED_LIBRARIES := openal vrapi LOCAL_STATIC_LIBRARIES += diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/d_main.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/d_main.cpp index 17cfbe6..b183461 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/d_main.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/d_main.cpp @@ -1064,7 +1064,7 @@ void D_DoomLoop () if (gametic > lasttic) { lasttic = gametic; - I_StartFrame (); + //I_StartFrame (); // not used } I_SetFrameTime(); @@ -2339,6 +2339,9 @@ static void CheckCmdLine() // //========================================================================== +// The command line arguments. +FArgs *Args; + void VR_DoomMain(int argc, char** argv) { progdir = "/sdcard/QzDoom/"; diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/d_stats.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/d_stats.cpp index 811caff..f3a1a74 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/d_stats.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/d_stats.cpp @@ -9,365 +9,5 @@ void D_ConfirmSendStats() { } -#else // !NO_SEND_STATS - -#if defined(_WIN32) -#define _WIN32_WINNT 0x0501 -#define WIN32_LEAN_AND_MEAN -#include -#include -extern int sys_ostype; -#else -#ifdef __APPLE__ -#include -#else // !__APPLE__ -#include -#endif // __APPLE__ -#include -#include -#include -#include -#include -#endif - -#include -#include "c_cvars.h" -#include "x86.h" -#include "version.h" -#include "v_video.h" - -EXTERN_CVAR(Bool, vid_glswfb) -extern int currentrenderer; -CVAR(Int, sys_statsenabled, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) -CVAR(String, sys_statshost, "gzstats.drdteam.org", CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) -CVAR(Int, sys_statsport, 80, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOSET) - -// Each machine will only send two reports, one when started with hardware rendering and one when started with software rendering. -#define CHECKVERSION 331 -#define CHECKVERSIONSTR "331" -CVAR(Int, sentstats_swr_done, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) -CVAR(Int, sentstats_hwr_done, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOSET) - -std::pair gl_getInfo(); - - -#ifdef _WIN32 - -bool I_HTTPRequest(const char* request) -{ - if (sys_statshost.GetHumanString() == NULL) - return false; // no host, disable - - WSADATA wsaData; - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) - { - DPrintf(DMSG_ERROR, "WSAStartup failed.\n"); - return false; - } - SOCKET Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - struct hostent *host; - host = gethostbyname(sys_statshost.GetHumanString()); - if (host == nullptr) - { - DPrintf(DMSG_ERROR, "Error looking up hostname.\n"); - return false; - } - SOCKADDR_IN SockAddr; - SockAddr.sin_port = htons(sys_statsport); - SockAddr.sin_family = AF_INET; - SockAddr.sin_addr.s_addr = *((uint32_t*)host->h_addr); - DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", sys_statshost.GetHumanString()); - if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0) - { - DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", sys_statshost.GetHumanString()); - return false; - } - send(Socket, request, (int)strlen(request), 0); - char buffer[1024]; - int nDataLength; - while ((nDataLength = recv(Socket, buffer, 1024, 0)) > 0) - { - int i = 0; - while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') - { - i++; - } - } - closesocket(Socket); - WSACleanup(); - DPrintf(DMSG_NOTIFY, "Stats send successful.\n"); - return true; -} -#else -bool I_HTTPRequest(const char* request) -{ - if (sys_statshost.GetHumanString() == NULL || sys_statshost.GetHumanString()[0] == 0) - return false; // no host, disable - - int sockfd, portno, n; - struct sockaddr_in serv_addr; - struct hostent *server; - - portno = sys_statsport; - sockfd = socket(AF_INET, SOCK_STREAM, 0); - - if (sockfd < 0) - { - DPrintf(DMSG_ERROR, "Error opening TCP socket.\n"); - return false; - } - - server = gethostbyname(sys_statshost.GetHumanString()); - if (server == NULL) - { - DPrintf(DMSG_ERROR, "Error looking up hostname.\n"); - return false; - } - bzero((char*) &serv_addr, sizeof(serv_addr)); - serv_addr.sin_family = AF_INET; - bcopy((char *)server->h_addr, - (char *)&serv_addr.sin_addr.s_addr, - server->h_length); - serv_addr.sin_port = htons(portno); - - DPrintf(DMSG_NOTIFY, "Connecting to host %s\n", sys_statshost.GetHumanString()); - if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) - { - DPrintf(DMSG_ERROR, "Connection to host %s failed!\n", sys_statshost.GetHumanString()); - return false; - } - - n = write(sockfd, request, strlen(request)); - if (n<0) - { - DPrintf(DMSG_ERROR, "Error writing to socket.\n"); - close(sockfd); - return false; - } - - char buffer[1024] = {}; - n = read(sockfd, buffer, 1023); - close(sockfd); - DPrintf(DMSG_NOTIFY, "Stats send successful.\n"); - return true; -} -#endif - -static int GetOSVersion() -{ -#ifdef _WIN32 - if (sys_ostype == 1) return 1; - if (sizeof(void*) == 4) // 32 bit - { - BOOL res; - if (IsWow64Process(GetCurrentProcess(), &res) && res) - { - return 6; - } - if (sys_ostype == 2) return 2; - else return 4; - } - else - { - if (sys_ostype == 2) return 3; - else return 5; - } - -#elif defined __APPLE__ - - if (sizeof(void*) == 4) // 32 bit - { - return 7; - } - else - { - return 8; - } - -#else - -// fall-through linux stuff here -#ifdef __arm__ - return 10; -#elif __ppc__ - return 9; -#else - if (sizeof(void*) == 4) // 32 bit - { - return 11; - } - else - { - return 12; - } -#endif - - -#endif -} - - -#ifdef _WIN32 - -static int GetCoreInfo() -{ - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL; - DWORD returnLength = 0; - int cores = 0; - uint32_t byteOffset = 0; - - auto rc = GetLogicalProcessorInformation(buffer, &returnLength); - - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { - buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength); - if (!GetLogicalProcessorInformation(buffer, &returnLength)) return 0; - } - else - { - return 0; - } - - ptr = buffer; - - while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) - { - if (ptr->Relationship == RelationProcessorCore) cores++; - byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); - ptr++; - } - free(buffer); - return cores < 2 ? 0 : cores < 4 ? 1 : cores < 6 ? 2 : cores < 8 ? 3 : 4; -} - -#else -static int GetCoreInfo() -{ - int cores = std::thread::hardware_concurrency(); - if (CPU.HyperThreading) cores /= 2; - return cores < 2? 0 : cores < 4? 1 : cores < 6? 2 : cores < 8? 3 : 4; -} -#endif - -static int GetRenderInfo() -{ - if (currentrenderer == 0) - { - if (!screen->Accel2D) return 0; - if (vid_glswfb) return 2; - if (screen->LegacyHardware()) return 6; - return 1; - } - else - { - auto info = gl_getInfo(); - if (info.first < 3.3) return 3; // Legacy OpenGL. Don't care about Intel HD 3000 on Windows being run in 'risky' mode. - if (!info.second) return 4; - return 5; - } -} - -static void D_DoHTTPRequest(const char *request) -{ - if (I_HTTPRequest(request)) - { - if (currentrenderer == 0) - { - cvar_forceset("sentstats_swr_done", CHECKVERSIONSTR); - } - else - { - cvar_forceset("sentstats_hwr_done", CHECKVERSIONSTR); - } - } -} - -void D_DoAnonStats() -{ - if (sys_statsenabled != 1) - { - return; - } - - static bool done = false; // do this only once per session. - if (done) return; - done = true; - - // Do not repeat if already sent. - if (currentrenderer == 0 && sentstats_swr_done >= CHECKVERSION) return; - if (currentrenderer == 1 && sentstats_hwr_done >= CHECKVERSION) return; - - static char requeststring[1024]; - mysnprintf(requeststring, sizeof requeststring, "GET /stats.py?render=%i&cores=%i&os=%i&renderconfig=%i HTTP/1.1\nHost: %s\nConnection: close\nUser-Agent: %s %s\n\n", - GetRenderInfo(), GetCoreInfo(), GetOSVersion(), currentrenderer, sys_statshost.GetHumanString(), GAMENAME, VERSIONSTR); - DPrintf(DMSG_NOTIFY, "Sending %s", requeststring); - std::thread t1(D_DoHTTPRequest, requeststring); - t1.detach(); -} - - - -void D_ConfirmSendStats() -{ - if (sys_statsenabled >= 0) - { - return; - } - - // TODO: texts - static const char *const MESSAGE_TEXT = "In order to decide where to focus development, the GZDoom team would like to know a little bit about the hardware it is run on.\n" \ - "For this we would like to ask you if we may send three bits of information to gzstats.drdteam.org.\n" \ - "The three items we would like to know about are:\n" \ - "- Operating system\n" \ - "- Number of processor cores\n" \ - "- Currently used renderer\n\n" \ - "All information sent will be anonymous. We will NOT be sending this information to any third party.\n" \ - "It will merely be used for decision-making about GZDoom's future development.\n" \ - "Data will only be sent at most twice per system, once for the software renderer and once for the hardware renderer.\n" \ - "If you are getting this notice more than once per renderer, please let us know on the forums. Thanks!\n\n" \ - "May we send this data? If you click 'no', nothing will be sent and you will not be asked again."; - - static const char *const TITLE_TEXT = "GZDoom needs your help!"; - - UCVarValue enabled = { 0 }; - -#ifdef _WIN32 - extern HWND Window; - enabled.Int = MessageBoxA(Window, MESSAGE_TEXT, TITLE_TEXT, MB_ICONQUESTION | MB_YESNO) == IDYES; -#elif defined __APPLE__ - const CFStringRef messageString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, MESSAGE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull); - const CFStringRef titleString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, TITLE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull); - if (messageString != nullptr && titleString != nullptr) - { - CFOptionFlags response; - const SInt32 result = CFUserNotificationDisplayAlert(0, kCFUserNotificationNoteAlertLevel, nullptr, nullptr, nullptr, - titleString, messageString, CFSTR("Yes"), CFSTR("No"), nullptr, &response); - enabled.Int = result == 0 && (response & 3) == kCFUserNotificationDefaultResponse; - CFRelease(titleString); - CFRelease(messageString); - } -#else // !__APPLE__ - const SDL_MessageBoxButtonData buttons[] = - { - { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 0, "Yes" }, - { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 1, "No" }, - }; - const SDL_MessageBoxData messageboxdata = - { - SDL_MESSAGEBOX_INFORMATION, - nullptr, - TITLE_TEXT, - MESSAGE_TEXT, - SDL_arraysize(buttons), - buttons, - nullptr - }; - int buttonid; - enabled.Int = SDL_ShowMessageBox(&messageboxdata, &buttonid) == 0 && buttonid == 0; -#endif // _WIN32 - - sys_statsenabled.ForceSet(enabled, CVAR_Int); -} #endif // NO_SEND_STATS diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.cpp index f7de673..38f9d6b 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.cpp @@ -418,7 +418,7 @@ namespace s3d leftEyeView.submitFrame(); rightEyeView.submitFrame(); - submitFrame(&frameDesc); + submitFrame(&tracking); } static int mAngleFromRadians(double radians) @@ -639,7 +639,6 @@ namespace s3d //Get controller state here - ovrTracking2 tracking; getHMDOrientation(&tracking); //Set up stuff used in the tracking code @@ -649,8 +648,6 @@ namespace s3d doomYawDegrees = GLRenderer->mAngles.Yaw.Degrees; getTrackedRemotesOrientation(vr_control_scheme); - frameDesc = setupFrameDescriptor(&tracking); - /* player_t* player = r_viewpoint.camera ? r_viewpoint.camera->player : nullptr; { LSMatrix44 mat; diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.h index 116876b..39f4a4c 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.h +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/stereo3d/gl_oculusquest.h @@ -102,7 +102,7 @@ protected: mutable int cachedViewwidth, cachedViewheight, cachedViewwindowx, cachedViewwindowy; mutable F2DDrawer * cached2DDrawer; mutable F2DDrawer * crossHairDrawer; - mutable ovrSubmitFrameDescription2 frameDesc; + mutable ovrTracking2 tracking; private: typedef Stereo3DMode super; diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_framebuffer.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_framebuffer.h index 2b87159..604e93d 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_framebuffer.h +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_framebuffer.h @@ -19,9 +19,9 @@ class OpenGLFrameBuffer : public Win32GLFrameBuffer typedef Win32GLFrameBuffer Super; #else //#include "sdlglvideo.h" -class OpenGLFrameBuffer : public OculusQuestGLFB +class OpenGLFrameBuffer : public NoSDLGLFB { - typedef OculusQuestGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux + typedef NoSDLGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux #endif diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_load.c b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_load.c index 7e4c7e6..cbdef1f 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_load.c +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_load.c @@ -53,17 +53,8 @@ static void CATCH(int a, int b, int c, int d, int e) int glesLoad = 3; // TODO fix this! -void* SDL_GL_GetProcAddress(const char* proc); static void *MOBILE_GetProcAddress(const char* name) { -/* static int jwzLoaded = 0; - if( ! jwzLoaded ) - { - void jwzgles_reset (void); - jwzgles_reset (); - jwzLoaded = 1; - } -*/ static void* h = NULL; if (h == NULL) @@ -80,7 +71,7 @@ static void *MOBILE_GetProcAddress(const char* name) } else if( glesLoad == 3 ) { - return SDL_GL_GetProcAddress( name ); + h = dlopen("libGLESv3.so", RTLD_LAZY | RTLD_LOCAL); } if (h == NULL) @@ -95,7 +86,7 @@ static void *MOBILE_GetProcAddress(const char* name) if( glesLoad == 1 ) sprintf(newName,"jwzgles_%s",name); - else if( glesLoad == 2 ) + else sprintf(newName,"%s",name); // @@ -117,66 +108,7 @@ static void *MOBILE_GetProcAddress(const char* name) #endif -#if defined(_WIN32) - -#ifdef APIENTRY -#undef APIENTRY -#endif -#include - - -#ifdef _MSC_VER -// disable inlining here because it creates an incredible amount of bloat in this file. -#pragma inline_depth(0) -#pragma warning(disable: 4055) -#pragma warning(disable: 4054) -#pragma warning(disable: 4996) -#endif - -static int TestPointer(const PROC pTest) -{ - ptrdiff_t iTest; - if(!pTest) return 0; - iTest = (ptrdiff_t)pTest; - - if(iTest == 1 || iTest == 2 || iTest == 3 || iTest == -1) return 0; - - return 1; -} - -static PROC WinGetProcAddress(const char *name) -{ - HMODULE glMod = NULL; - PROC pFunc = wglGetProcAddress((LPCSTR)name); - if(TestPointer(pFunc)) - { - return pFunc; - } - glMod = GetModuleHandleA("OpenGL32.dll"); - return (PROC)GetProcAddress(glMod, (LPCSTR)name); -} - - - -#define IntGetProcAddress(name) WinGetProcAddress(name) -#else - #if defined(__APPLE__) - #define IntGetProcAddress(name) AppleGLGetProcAddress(name) - #elif defined(__ANDROID__) - #define IntGetProcAddress(name) MOBILE_GetProcAddress((const char*)name) - #else - #if defined(__sgi) || defined(__sun) || defined(__unix__) - void* SDL_GL_GetProcAddress(const char* proc); - #define IntGetProcAddress(name) SDL_GL_GetProcAddress((const char*)name) - //#define IntGetProcAddress(name) PosixGetProcAddress((const GLubyte*)name) -/* END OF MANUAL CHANGES, DO NOT REMOVE! */ - #else /* GLX */ - #include - - #define IntGetProcAddress(name) (*glXGetProcAddressARB)((const GLubyte*)name) - #endif - #endif -#endif +#define IntGetProcAddress(name) MOBILE_GetProcAddress((const char*)name) int ogl_ext_ARB_buffer_storage = ogl_LOAD_FAILED; int ogl_ext_ARB_shader_storage_buffer_object = ogl_LOAD_FAILED; diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_swframebuffer.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_swframebuffer.h index c5126b0..007688e 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_swframebuffer.h +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/gl/system/gl_swframebuffer.h @@ -19,9 +19,9 @@ class OpenGLSWFrameBuffer : public Win32GLFrameBuffer typedef Win32GLFrameBuffer Super; #else #include "glvideo.h" -class OpenGLSWFrameBuffer : public OculusQuestGLFB +class OpenGLSWFrameBuffer : public NoSDLGLFB { - typedef OculusQuestGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux + typedef NoSDLGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux #endif diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/menu/menu.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/menu/menu.cpp index 1596485..ca1c9ba 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/menu/menu.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/menu/menu.cpp @@ -253,8 +253,8 @@ bool DMenu::CallMenuEvent(int mkey, bool fromcontroller) static void SetMouseCapture(bool on) { - if (on) I_SetMouseCapture(); - else I_ReleaseMouseCapture(); +// if (on) I_SetMouseCapture(); +// else I_ReleaseMouseCapture(); } DEFINE_ACTION_FUNCTION_NATIVE(DMenu, SetMouseCapture, SetMouseCapture) { @@ -382,7 +382,7 @@ void M_ActivateMenu(DMenu *menu) if (CurrentMenu != nullptr && CurrentMenu->mMouseCapture) { CurrentMenu->mMouseCapture = false; - I_ReleaseMouseCapture(); + //I_ReleaseMouseCapture(); } CurrentMenu = menu; GC::WriteBarrier(CurrentMenu); diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_common.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_common.h deleted file mode 100644 index be395cf..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_common.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - ** i_common.h - ** - **--------------------------------------------------------------------------- - ** Copyright 2012-2015 Alexey Lysiuk - ** 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. - **--------------------------------------------------------------------------- - ** - */ - -#ifndef COCOA_I_COMMON_INCLUDED -#define COCOA_I_COMMON_INCLUDED - -#import - - -struct RenderBufferOptions -{ - float pixelScale; - - float shiftX; - float shiftY; - - float width; - float height; - - bool dirty; -}; - -extern RenderBufferOptions rbOpts; - - -// Version of AppKit framework we are interested in -// The following values are needed to build with earlier SDKs - -#define AppKit10_7 1138 -#define AppKit10_8 1187 -#define AppKit10_9 1265 - - -@interface NSWindow(ExitAppOnClose) -- (void)exitAppOnClose; -@end - - -void I_ProcessEvent(NSEvent* event); - -void I_ProcessJoysticks(); - -NSSize I_GetContentViewSize(const NSWindow* window); -void I_SetMainWindowVisible(bool visible); -void I_SetNativeMouse(bool wantNative); - -#endif // COCOA_I_COMMON_INCLUDED diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_input.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_input.mm deleted file mode 100644 index 54b301a..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_input.mm +++ /dev/null @@ -1,789 +0,0 @@ -/* - ** i_input.mm - ** - **--------------------------------------------------------------------------- - ** Copyright 2012-2015 Alexey Lysiuk - ** 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 "i_common.h" - -#import - -#include "c_console.h" -#include "c_cvars.h" -#include "c_dispatch.h" -#include "d_event.h" -#include "d_gui.h" -#include "dikeys.h" -#include "doomdef.h" -#include "doomstat.h" -#include "v_video.h" -#include "events.h" - - -EXTERN_CVAR(Int, m_use_mouse) - -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, k_allowfullscreentoggle, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) - -CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) -{ - if (self < 0) - { - self = 0; - } - else if (self > 2) - { - self = 2; - } -} - - -extern int paused, chatmodeon; -extern constate_e ConsoleState; - -bool GUICapture; - - -namespace -{ - -// TODO: remove this magic! -size_t s_skipMouseMoves; - - -// --------------------------------------------------------------------------- - - -void CheckGUICapture() -{ - bool wantCapture = (MENU_Off == menuactive) - ? (c_down == ConsoleState || c_falling == ConsoleState || chatmodeon) - : (MENU_On == menuactive || MENU_OnNoPause == menuactive); - - // [ZZ] check active event handlers that want the UI processing - if (!wantCapture && E_CheckUiProcessors()) - { - wantCapture = true; - } - - if (wantCapture != GUICapture) - { - GUICapture = wantCapture; - - ResetButtonStates(); - } -} - -void SetCursorPosition(const NSPoint position) -{ - NSWindow* window = [NSApp keyWindow]; - if (nil == window) - { - return; - } - - const NSRect displayRect = [[window screen] frame]; - const CGPoint eventPoint = CGPointMake(position.x, displayRect.size.height - position.y); - - CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState); - - if (NULL != eventSource) - { - CGEventRef mouseMoveEvent = CGEventCreateMouseEvent(eventSource, - kCGEventMouseMoved, eventPoint, kCGMouseButtonLeft); - - if (NULL != mouseMoveEvent) - { - CGEventPost(kCGHIDEventTap, mouseMoveEvent); - CFRelease(mouseMoveEvent); - } - - CFRelease(eventSource); - } - - // TODO: remove this magic! - s_skipMouseMoves = 2; -} - -void CenterCursor() -{ - NSWindow* window = [NSApp keyWindow]; - if (nil == window) - { - return; - } - - const NSRect displayRect = [[window screen] frame]; - const NSRect windowRect = [window frame]; - const NSPoint centerPoint = { NSMidX(windowRect), NSMidY(windowRect) }; - - SetCursorPosition(centerPoint); -} - -bool IsInGame() -{ - 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; - } -} - -void CheckNativeMouse() -{ - const bool windowed = (NULL == screen) || !screen->IsFullscreen(); - bool wantNative; - - if (windowed) - { - if (![NSApp isActive] || !use_mouse) - { - wantNative = true; - } - else if (MENU_WaitKey == menuactive) - { - wantNative = false; - } - else - { - wantNative = (!m_use_mouse || MENU_WaitKey != menuactive) - && (!IsInGame() || GUICapture || paused || demoplayback); - } - } - else - { - // ungrab mouse when in the menu with mouse control on. - wantNative = m_use_mouse - && (MENU_On == menuactive || MENU_OnNoPause == menuactive); - } - - if (!wantNative && E_CheckRequireMouse()) - wantNative = true; - - I_SetNativeMouse(wantNative); -} - -} // unnamed namespace - - -void I_GetEvent() -{ - [[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode]; -} - -void I_StartTic() -{ - CheckGUICapture(); - CheckNativeMouse(); - - I_ProcessJoysticks(); - I_GetEvent(); -} - -void I_StartFrame() -{ -} - - -void I_SetMouseCapture() -{ -} - -void I_ReleaseMouseCapture() -{ -} - -void I_SetNativeMouse(bool wantNative) -{ - static bool nativeMouse = true; - static NSPoint mouseLocation; - - if (wantNative != nativeMouse) - { - nativeMouse = wantNative; - - if (!wantNative) - { - mouseLocation = [NSEvent mouseLocation]; - CenterCursor(); - } - - CGAssociateMouseAndMouseCursorPosition(wantNative); - - if (wantNative) - { - SetCursorPosition(mouseLocation); - - [NSCursor unhide]; - } - else - { - [NSCursor hide]; - } - } -} - - -// --------------------------------------------------------------------------- - - -namespace -{ - -const size_t KEY_COUNT = 128; - - -// See Carbon -> HIToolbox -> Events.h for kVK_ constants - -const uint8_t KEYCODE_TO_DIK[KEY_COUNT] = -{ - DIK_A, DIK_S, DIK_D, DIK_F, DIK_H, DIK_G, DIK_Z, DIK_X, // 0x00 - 0x07 - DIK_C, DIK_V, 0, DIK_B, DIK_Q, DIK_W, DIK_E, DIK_R, // 0x08 - 0x0F - DIK_Y, DIK_T, DIK_1, DIK_2, DIK_3, DIK_4, DIK_6, DIK_5, // 0x10 - 0x17 - DIK_EQUALS, DIK_9, DIK_7, DIK_MINUS, DIK_8, DIK_0, DIK_RBRACKET, DIK_O, // 0x18 - 0x1F - DIK_U, DIK_LBRACKET, DIK_I, DIK_P, DIK_RETURN, DIK_L, DIK_J, DIK_APOSTROPHE, // 0x20 - 0x27 - DIK_K, DIK_SEMICOLON, DIK_BACKSLASH, DIK_COMMA, DIK_SLASH, DIK_N, DIK_M, DIK_PERIOD, // 0x28 - 0x2F - DIK_TAB, DIK_SPACE, DIK_GRAVE, DIK_BACK, 0, DIK_ESCAPE, 0, DIK_LWIN, // 0x30 - 0x37 - DIK_LSHIFT, DIK_CAPITAL, DIK_LMENU, DIK_LCONTROL, DIK_RSHIFT, DIK_RMENU, DIK_RCONTROL, 0, // 0x38 - 0x3F - 0, DIK_DECIMAL, 0, DIK_MULTIPLY, 0, DIK_ADD, 0, 0, // 0x40 - 0x47 - DIK_VOLUMEUP, DIK_VOLUMEDOWN, DIK_MUTE, DIK_SLASH, DIK_NUMPADENTER, 0, DIK_SUBTRACT, 0, // 0x48 - 0x4F - 0, DIK_NUMPAD_EQUALS, DIK_NUMPAD0, DIK_NUMPAD1, DIK_NUMPAD2, DIK_NUMPAD3, DIK_NUMPAD4, DIK_NUMPAD5, // 0x50 - 0x57 - DIK_NUMPAD6, DIK_NUMPAD7, 0, DIK_NUMPAD8, DIK_NUMPAD9, 0, 0, 0, // 0x58 - 0x5F - DIK_F5, DIK_F6, DIK_F7, DIK_F3, DIK_F8, DIK_F9, 0, DIK_F11, // 0x60 - 0x67 - 0, DIK_F13, 0, DIK_F14, 0, DIK_F10, 0, DIK_F12, // 0x68 - 0x6F - 0, DIK_F15, 0, DIK_HOME, 0, DIK_DELETE, DIK_F4, DIK_END, // 0x70 - 0x77 - DIK_F2, 0, DIK_F1, DIK_LEFT, DIK_RIGHT, DIK_DOWN, DIK_UP, 0, // 0x78 - 0x7F -}; - -const uint8_t KEYCODE_TO_ASCII[KEY_COUNT] = -{ - 'a', 's', 'd', 'f', 'h', 'g', 'z', 'x', // 0x00 - 0x07 - 'c', 'v', 0, 'b', 'q', 'w', 'e', 'r', // 0x08 - 0x0F - 'y', 't', '1', '2', '3', '4', '6', '5', // 0x10 - 0x17 - '=', '9', '7', '-', '8', '0', ']', 'o', // 0x18 - 0x1F - 'u', '[', 'i', 'p', 13, 'l', 'j', '\'', // 0x20 - 0x27 - 'k', ';', '\\', ',', '/', 'n', 'm', '.', // 0x28 - 0x2F - 9, ' ', '`', 12, 0, 27, 0, 0, // 0x30 - 0x37 - 0, 0, 0, 0, 0, 0, 0, 0, // 0x38 - 0x3F - 0, 0, 0, 0, 0, 0, 0, 0, // 0x40 - 0x47 - 0, 0, 0, 0, 0, 0, 0, 0, // 0x48 - 0x4F - 0, 0, 0, 0, 0, 0, 0, 0, // 0x50 - 0x57 - 0, 0, 0, 0, 0, 0, 0, 0, // 0x58 - 0x5F - 0, 0, 0, 0, 0, 0, 0, 0, // 0x60 - 0x67 - 0, 0, 0, 0, 0, 0, 0, 0, // 0x68 - 0x6F - 0, 0, 0, 0, 0, 0, 0, 0, // 0x70 - 0x77 - 0, 0, 0, 0, 0, 0, 0, 0, // 0x78 - 0x7F -}; - - -uint8_t ModifierToDIK(const uint32_t modifier) -{ - switch (modifier) - { - case NSAlphaShiftKeyMask: return DIK_CAPITAL; - case NSShiftKeyMask: return DIK_LSHIFT; - case NSControlKeyMask: return DIK_LCONTROL; - case NSAlternateKeyMask: return DIK_LMENU; - case NSCommandKeyMask: return DIK_LWIN; - } - - return 0; -} - -int16_t ModifierFlagsToGUIKeyModifiers(NSEvent* theEvent) -{ - const NSUInteger modifiers([theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask); - return ((modifiers & NSShiftKeyMask ) ? GKM_SHIFT : 0) - | ((modifiers & NSControlKeyMask ) ? GKM_CTRL : 0) - | ((modifiers & NSAlternateKeyMask) ? GKM_ALT : 0) - | ((modifiers & NSCommandKeyMask ) ? GKM_META : 0); -} - -bool ShouldGenerateGUICharEvent(NSEvent* theEvent) -{ - const NSUInteger modifiers([theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask); - return !(modifiers & NSControlKeyMask) - && !(modifiers & NSAlternateKeyMask) - && !(modifiers & NSCommandKeyMask) - && !(modifiers & NSFunctionKeyMask); -} - - -NSStringEncoding GetEncodingForUnicodeCharacter(const unichar character) -{ - if (character >= L'\u0100' && character <= L'\u024F') - { - return NSWindowsCP1250StringEncoding; // Central and Eastern Europe - } - else if (character >= L'\u0370' && character <= L'\u03FF') - { - return NSWindowsCP1253StringEncoding; // Greek - } - else if (character >= L'\u0400' && character <= L'\u04FF') - { - return NSWindowsCP1251StringEncoding; // Cyrillic - } - - // TODO: add handling for other characters - // TODO: Turkish should use NSWindowsCP1254StringEncoding - - return NSWindowsCP1252StringEncoding; -} - -unsigned char GetCharacterFromNSEvent(NSEvent* theEvent, unichar *realchar) -{ - const NSString* unicodeCharacters = [theEvent characters]; - - if (0 == [unicodeCharacters length]) - { - return '\0'; - } - - const unichar unicodeCharacter = [unicodeCharacters characterAtIndex:0]; - const NSStringEncoding encoding = GetEncodingForUnicodeCharacter(unicodeCharacter); - - unsigned char character = '\0'; - - if (NSWindowsCP1252StringEncoding == encoding) - { - // TODO: make sure that the following is always correct - character = unicodeCharacter & 0xFF; - } - else - { - const NSData* const characters = - [[theEvent characters] dataUsingEncoding:encoding]; - - character = [characters length] > 0 - ? *static_cast([characters bytes]) - : '\0'; - } - - *realchar = unicodeCharacter; - return character; -} - -void ProcessKeyboardEventInMenu(NSEvent* theEvent) -{ - event_t event = {}; - - unichar realchar; - event.type = EV_GUI_Event; - event.subtype = NSKeyDown == [theEvent type] ? EV_GUI_KeyDown : EV_GUI_KeyUp; - event.data2 = GetCharacterFromNSEvent(theEvent, &realchar); - event.data3 = ModifierFlagsToGUIKeyModifiers(theEvent); - - if (EV_GUI_KeyDown == event.subtype && [theEvent isARepeat]) - { - event.subtype = EV_GUI_KeyRepeat; - } - - const unsigned short keyCode = [theEvent keyCode]; - - switch (keyCode) - { - case kVK_Return: event.data1 = GK_RETURN; break; - case kVK_PageUp: event.data1 = GK_PGUP; break; - case kVK_PageDown: event.data1 = GK_PGDN; break; - case kVK_End: event.data1 = GK_END; break; - case kVK_Home: event.data1 = GK_HOME; break; - case kVK_LeftArrow: event.data1 = GK_LEFT; break; - case kVK_RightArrow: event.data1 = GK_RIGHT; break; - case kVK_UpArrow: event.data1 = GK_UP; break; - case kVK_DownArrow: event.data1 = GK_DOWN; break; - case kVK_Delete: event.data1 = GK_BACKSPACE; break; - case kVK_ForwardDelete: event.data1 = GK_DEL; break; - case kVK_Escape: event.data1 = GK_ESCAPE; break; - case kVK_F1: event.data1 = GK_F1; break; - case kVK_F2: event.data1 = GK_F2; break; - case kVK_F3: event.data1 = GK_F3; break; - case kVK_F4: event.data1 = GK_F4; break; - case kVK_F5: event.data1 = GK_F5; break; - case kVK_F6: event.data1 = GK_F6; break; - case kVK_F7: event.data1 = GK_F7; break; - case kVK_F8: event.data1 = GK_F8; break; - case kVK_F9: event.data1 = GK_F9; break; - case kVK_F10: event.data1 = GK_F10; break; - case kVK_F11: event.data1 = GK_F11; break; - case kVK_F12: event.data1 = GK_F12; break; - case kVK_F13: event.data1 = GK_SYSRQ; break; - default: - event.data1 = KEYCODE_TO_ASCII[keyCode]; - break; - } - - if (event.data1 < 128) - { - event.data1 = toupper(event.data1); - - D_PostEvent(&event); - } - - if (!iscntrl(event.data2) - && EV_GUI_KeyUp != event.subtype - && ShouldGenerateGUICharEvent(theEvent)) - { - event.subtype = EV_GUI_Char; - event.data1 = realchar; - event.data2 = event.data3 & GKM_ALT; - - D_PostEvent(&event); - } -} - - -void NSEventToGameMousePosition(NSEvent* inEvent, event_t* outEvent) -{ - const NSWindow* window = [inEvent window]; - const NSView* view = [window contentView]; - - const NSPoint screenPos = [NSEvent mouseLocation]; - const NSRect screenRect = NSMakeRect(screenPos.x, screenPos.y, 0, 0); - const NSRect windowRect = [window convertRectFromScreen:screenRect]; - const NSPoint viewPos = [view convertPointToBacking:windowRect.origin]; - const CGFloat frameHeight = I_GetContentViewSize(window).height; - - outEvent->data1 = static_cast( viewPos.x); - outEvent->data2 = static_cast(frameHeight - viewPos.y); - - // Compensate letterbox adjustment done by cross-platform code - // More elegant solution is a bit problematic due to HiDPI/Retina support - outEvent->data2 += (int(frameHeight) - screen->VideoHeight) / 2; - - screen->ScaleCoordsFromWindow(outEvent->data1, outEvent->data2); -} - -void ProcessMouseMoveInMenu(NSEvent* theEvent) -{ - event_t event = {}; - - event.type = EV_GUI_Event; - event.subtype = EV_GUI_MouseMove; - event.data3 = ModifierFlagsToGUIKeyModifiers(theEvent); - - NSEventToGameMousePosition(theEvent, &event); - - D_PostEvent(&event); -} - -void ProcessMouseMoveInGame(NSEvent* theEvent) -{ - int x([theEvent deltaX]); - int y(-[theEvent deltaY]); - - if (0 == x && 0 == y) - { - return; - } - - if (!m_noprescale) - { - x *= 3; - y *= 2; - } - - event_t event = {}; - - static int lastX = 0, lastY = 0; - - if (m_filter) - { - event.x = (x + lastX) / 2; - event.y = (y + lastY) / 2; - } - else - { - event.x = x; - event.y = y; - } - - lastX = x; - lastY = y; - - if (0 != event.x || 0 != event.y) - { - event.type = EV_Mouse; - - D_PostEvent(&event); - } -} - - -void ProcessKeyboardEvent(NSEvent* theEvent) -{ - const unsigned short keyCode = [theEvent keyCode]; - if (keyCode >= KEY_COUNT) - { - assert(!"Unknown keycode"); - return; - } - - const bool isARepeat = [theEvent isARepeat]; - - if (k_allowfullscreentoggle - && (kVK_ANSI_F == keyCode) - && (NSCommandKeyMask & [theEvent modifierFlags]) - && (NSKeyDown == [theEvent type]) - && !isARepeat) - { - ToggleFullscreen = !ToggleFullscreen; - return; - } - - if (GUICapture) - { - ProcessKeyboardEventInMenu(theEvent); - } - else if (!isARepeat) - { - event_t event = {}; - - event.type = NSKeyDown == [theEvent type] ? EV_KeyDown : EV_KeyUp; - event.data1 = KEYCODE_TO_DIK[ keyCode ]; - - if (0 != event.data1) - { - event.data2 = KEYCODE_TO_ASCII[ keyCode ]; - - D_PostEvent(&event); - } - } -} - -void ProcessKeyboardFlagsEvent(NSEvent* theEvent) -{ - if (GUICapture) - { - // Ignore events from modifier keys in menu/console/chat - return; - } - - static const uint32_t FLAGS_MASK = - NSDeviceIndependentModifierFlagsMask & ~NSNumericPadKeyMask; - - const uint32_t modifiers = [theEvent modifierFlags] & FLAGS_MASK; - static uint32_t oldModifiers = 0; - const uint32_t deltaModifiers = modifiers ^ oldModifiers; - - if (0 == deltaModifiers) - { - return; - } - - event_t event = {}; - event.type = modifiers > oldModifiers ? EV_KeyDown : EV_KeyUp; - event.data1 = ModifierToDIK(deltaModifiers); - - oldModifiers = modifiers; - - if (DIK_CAPITAL == event.data1) - { - // Caps Lock is a modifier key which generates one event per state change - // but not per actual key press or release. So treat any event as key down - event.type = EV_KeyDown; - } - - D_PostEvent(&event); -} - - -void ProcessMouseMoveEvent(NSEvent* theEvent) -{ - if (!use_mouse) - { - return; - } - - if (s_skipMouseMoves > 0) - { - --s_skipMouseMoves; - return; - } - - if (GUICapture) - { - ProcessMouseMoveInMenu(theEvent); - } - else - { - ProcessMouseMoveInGame(theEvent); - } -} - -void ProcessMouseButtonEvent(NSEvent* theEvent) -{ - if (!use_mouse) - { - return; - } - - event_t event = {}; - - const NSEventType cocoaEventType = [theEvent type]; - - if (GUICapture) - { - event.type = EV_GUI_Event; - event.data3 = ModifierFlagsToGUIKeyModifiers(theEvent); - - switch (cocoaEventType) - { - case NSLeftMouseDown: event.subtype = EV_GUI_LButtonDown; break; - case NSRightMouseDown: event.subtype = EV_GUI_RButtonDown; break; - case NSOtherMouseDown: event.subtype = EV_GUI_MButtonDown; break; - case NSLeftMouseUp: event.subtype = EV_GUI_LButtonUp; break; - case NSRightMouseUp: event.subtype = EV_GUI_RButtonUp; break; - case NSOtherMouseUp: event.subtype = EV_GUI_MButtonUp; break; - default: break; - } - - NSEventToGameMousePosition(theEvent, &event); - - D_PostEvent(&event); - } - else - { - switch (cocoaEventType) - { - case NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - event.type = EV_KeyDown; - break; - - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - event.type = EV_KeyUp; - break; - - default: - break; - } - - event.data1 = MIN(KEY_MOUSE1 + [theEvent buttonNumber], NSInteger(KEY_MOUSE8)); - - D_PostEvent(&event); - } -} - -void ProcessMouseWheelEvent(NSEvent* theEvent) -{ - if (!use_mouse) - { - return; - } - - const int16_t modifiers = ModifierFlagsToGUIKeyModifiers(theEvent); - const CGFloat delta = (modifiers & GKM_SHIFT) - ? [theEvent deltaX] - : [theEvent deltaY]; - const bool isZeroDelta = fabs(delta) < 1.0E-5; - - if (isZeroDelta && GUICapture) - { - return; - } - - event_t event = {}; - - if (GUICapture) - { - event.type = EV_GUI_Event; - event.subtype = delta > 0.0f ? EV_GUI_WheelUp : EV_GUI_WheelDown; - event.data3 = modifiers; - } - else - { - event.type = isZeroDelta ? EV_KeyUp : EV_KeyDown; - event.data1 = delta > 0.0f ? KEY_MWHEELUP : KEY_MWHEELDOWN; - } - - D_PostEvent(&event); -} - -} // unnamed namespace - - -void I_ProcessEvent(NSEvent* event) -{ - const NSEventType eventType = [event type]; - - switch (eventType) - { - case NSMouseMoved: - ProcessMouseMoveEvent(event); - break; - - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSOtherMouseDown: - case NSOtherMouseUp: - ProcessMouseButtonEvent(event); - break; - - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - ProcessMouseButtonEvent(event); - ProcessMouseMoveEvent(event); - break; - - case NSScrollWheel: - ProcessMouseWheelEvent(event); - break; - - case NSKeyDown: - case NSKeyUp: - ProcessKeyboardEvent(event); - break; - - case NSFlagsChanged: - ProcessKeyboardFlagsEvent(event); - break; - - default: - break; - } -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_joystick.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_joystick.cpp deleted file mode 100644 index e7d3aa0..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_joystick.cpp +++ /dev/null @@ -1,1254 +0,0 @@ -/* - ** i_joystick.cpp - ** - **--------------------------------------------------------------------------- - ** Copyright 2012-2015 Alexey Lysiuk - ** 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 -#include -#include -#include -#include - -#include "d_event.h" -#include "doomdef.h" -#include "i_system.h" -#include "m_argv.h" -#include "m_joy.h" -#include "templates.h" -#include "v_text.h" -#include "atterm.h" - - -EXTERN_CVAR(Bool, joy_axespolling) - - -namespace -{ - -FString ToFString(const CFStringRef string) -{ - if (NULL == string) - { - return FString(); - } - - const CFIndex stringLength = CFStringGetLength(string); - - if (0 == stringLength) - { - return FString(); - } - - const size_t bufferSize = CFStringGetMaximumSizeForEncoding(stringLength, kCFStringEncodingUTF8) + 1; - - char buffer[bufferSize]; - memset(buffer, 0, bufferSize); - - CFStringGetCString(string, buffer, bufferSize, kCFStringEncodingUTF8); - - return FString(buffer); -} - - -// --------------------------------------------------------------------------- - - -class IOKitJoystick : public IJoystickConfig -{ -public: - explicit IOKitJoystick(io_object_t device); - virtual ~IOKitJoystick(); - - virtual FString GetName(); - virtual float GetSensitivity(); - virtual void SetSensitivity(float scale); - - virtual int GetNumAxes(); - virtual float GetAxisDeadZone(int axis); - virtual EJoyAxis GetAxisMap(int axis); - virtual const char* GetAxisName(int axis); - virtual float GetAxisScale(int axis); - - virtual void SetAxisDeadZone(int axis, float deadZone); - virtual void SetAxisMap(int axis, EJoyAxis gameAxis); - virtual void SetAxisScale(int axis, float scale); - - virtual bool IsSensitivityDefault(); - virtual bool IsAxisDeadZoneDefault(int axis); - virtual bool IsAxisMapDefault(int axis); - virtual bool IsAxisScaleDefault(int axis); - - virtual void SetDefaultConfig(); - virtual FString GetIdentifier(); - - void AddAxes(float axes[NUM_JOYAXIS]) const; - - void Update(); - - void UseAxesPolling(bool axesPolling); - - io_object_t* GetNotificationPtr(); - -private: - IOHIDDeviceInterface** m_interface; - IOHIDQueueInterface** m_queue; - - FString m_name; - FString m_identifier; - - float m_sensitivity; - - struct AnalogAxis - { - IOHIDElementCookie cookie; - - char name[64]; - - float value; - - int32_t minValue; - int32_t maxValue; - - float deadZone; - float defaultDeadZone; - float sensitivity; - float defaultSensitivity; - - EJoyAxis gameAxis; - EJoyAxis defaultGameAxis; - - AnalogAxis() - { - memset(this, 0, sizeof *this); - } - }; - - TArray m_axes; - - struct DigitalButton - { - IOHIDElementCookie cookie; - int32_t value; - - explicit DigitalButton(const IOHIDElementCookie cookie) - : cookie(cookie) - , value(0) - { } - }; - - TArray m_buttons; - TArray m_POVs; - - bool m_useAxesPolling; - - io_object_t m_notification; - - - static const float DEFAULT_DEADZONE; - static const float DEFAULT_SENSITIVITY; - - void ProcessAxes(); - bool ProcessAxis (const IOHIDEventStruct& event); - bool ProcessButton(const IOHIDEventStruct& event); - bool ProcessPOV (const IOHIDEventStruct& event); - - void GatherDeviceInfo(io_object_t device, CFDictionaryRef properties); - - static void GatherElementsHandler(const void* value, void* parameter); - void GatherCollectionElements(CFDictionaryRef properties); - - void AddAxis(CFDictionaryRef element); - void AddButton(CFDictionaryRef element); - void AddPOV(CFDictionaryRef element); - - void AddToQueue(IOHIDElementCookie cookie); - void RemoveFromQueue(IOHIDElementCookie cookie); -}; - - -const float IOKitJoystick::DEFAULT_DEADZONE = 0.25f; -const float IOKitJoystick::DEFAULT_SENSITIVITY = 1.0f; - - -IOHIDDeviceInterface** CreateDeviceInterface(const io_object_t device) -{ - IOCFPlugInInterface** plugInInterface = NULL; - SInt32 score = 0; - - const kern_return_t pluginResult = IOCreatePlugInInterfaceForService(device, - kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); - - IOHIDDeviceInterface** interface = NULL; - - if (KERN_SUCCESS == pluginResult) - { - // Call a method of the intermediate plug-in to create the device interface - - const HRESULT queryResult = (*plugInInterface)->QueryInterface(plugInInterface, - CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), reinterpret_cast(&interface)); - - IODestroyPlugInInterface(plugInInterface); // [?] or maybe (*plugInInterface)->Release(plugInInterface); - - if (S_OK == queryResult) - { - const IOReturn openResult = (*interface)->open(interface, 0); - - if (kIOReturnSuccess != openResult) - { - (*interface)->Release(interface); - - Printf(TEXTCOLOR_RED "IOHIDDeviceInterface::open() failed with code 0x%08X\n", openResult); - return NULL; - } - } - else - { - Printf(TEXTCOLOR_RED "IOCFPlugInInterface::QueryInterface() failed with code 0x%08X\n", - static_cast(queryResult)); - return NULL; - } - } - else - { - Printf(TEXTCOLOR_RED "IOCreatePlugInInterfaceForService() failed with code %i\n", pluginResult); - return NULL; - } - - return interface; -} - -IOHIDQueueInterface** CreateDeviceQueue(IOHIDDeviceInterface** const interface) -{ - if (NULL == interface) - { - return NULL; - } - - IOHIDQueueInterface** queue = (*interface)->allocQueue(interface); - - if (NULL == queue) - { - Printf(TEXTCOLOR_RED "IOHIDDeviceInterface::allocQueue() failed\n"); - return NULL; - } - - static const uint32_t QUEUE_FLAGS = 0; - static const uint32_t QUEUE_DEPTH = 0; - - const IOReturn queueResult = (*queue)->create(queue, QUEUE_FLAGS, QUEUE_DEPTH); - - if (kIOReturnSuccess != queueResult) - { - (*queue)->Release(queue); - - Printf(TEXTCOLOR_RED "IOHIDQueueInterface::create() failed with code 0x%08X\n", queueResult); - return NULL; - } - - return queue; -} - - -IOKitJoystick::IOKitJoystick(const io_object_t device) -: m_interface(CreateDeviceInterface(device)) -, m_queue(CreateDeviceQueue(m_interface)) -, m_sensitivity(DEFAULT_SENSITIVITY) -, m_useAxesPolling(true) -, m_notification(0) -{ - if (NULL == m_interface || NULL == m_queue) - { - return; - } - - CFMutableDictionaryRef properties = NULL; - const kern_return_t propertiesResult = - IORegistryEntryCreateCFProperties(device, &properties, kCFAllocatorDefault, kNilOptions); - - if (KERN_SUCCESS != propertiesResult || NULL == properties) - { - Printf(TEXTCOLOR_RED "IORegistryEntryCreateCFProperties() failed with code %i\n", propertiesResult); - return; - } - - GatherDeviceInfo(device, properties); - GatherCollectionElements(properties); - - CFRelease(properties); - - UseAxesPolling(joy_axespolling); - - (*m_queue)->start(m_queue); - - SetDefaultConfig(); -} - -IOKitJoystick::~IOKitJoystick() -{ - M_SaveJoystickConfig(this); - - if (0 != m_notification) - { - IOObjectRelease(m_notification); - } - - if (NULL != m_queue) - { - (*m_queue)->stop(m_queue); - (*m_queue)->dispose(m_queue); - (*m_queue)->Release(m_queue); - } - - if (NULL != m_interface) - { - (*m_interface)->close(m_interface); - (*m_interface)->Release(m_interface); - } -} - - -FString IOKitJoystick::GetName() -{ - return m_name; -} - - -float IOKitJoystick::GetSensitivity() -{ - return m_sensitivity; -} - -void IOKitJoystick::SetSensitivity(float scale) -{ - m_sensitivity = scale; -} - - -int IOKitJoystick::GetNumAxes() -{ - return static_cast(m_axes.Size()); -} - -#define IS_AXIS_VALID (static_cast(axis) < m_axes.Size()) - -float IOKitJoystick::GetAxisDeadZone(int axis) -{ - return IS_AXIS_VALID ? m_axes[axis].deadZone : 0.0f; -} - -EJoyAxis IOKitJoystick::GetAxisMap(int axis) -{ - return IS_AXIS_VALID ? m_axes[axis].gameAxis : JOYAXIS_None; -} - -const char* IOKitJoystick::GetAxisName(int axis) -{ - return IS_AXIS_VALID ? m_axes[axis].name : "Invalid"; -} - -float IOKitJoystick::GetAxisScale(int axis) -{ - return IS_AXIS_VALID ? m_axes[axis].sensitivity : 0.0f; -} - -void IOKitJoystick::SetAxisDeadZone(int axis, float deadZone) -{ - if (IS_AXIS_VALID) - { - m_axes[axis].deadZone = clamp(deadZone, 0.0f, 1.0f); - } -} - -void IOKitJoystick::SetAxisMap(int axis, EJoyAxis gameAxis) -{ - if (IS_AXIS_VALID) - { - m_axes[axis].gameAxis = (gameAxis> JOYAXIS_None && gameAxis = 3) - { - m_axes[0].gameAxis = JOYAXIS_Side; - m_axes[1].gameAxis = JOYAXIS_Forward; - m_axes[2].gameAxis = JOYAXIS_Yaw; - - // Four axes? First two are movement, last two are looking around. - - if (axisCount >= 4) - { - m_axes[3].gameAxis = JOYAXIS_Pitch; -// ??? m_axes[3].sensitivity = 0.75f; - - // Five axes? Use the fifth one for moving up and down. - - if (axisCount >= 5) - { - m_axes[4].gameAxis = JOYAXIS_Up; - } - } - } - - // If there is only one axis, then we make no assumptions about how - // the user might want to use it. - - // Preserve defaults for config saving. - - for (size_t i = 0; i < axisCount; ++i) - { - m_axes[i].defaultDeadZone = m_axes[i].deadZone; - m_axes[i].defaultSensitivity = m_axes[i].sensitivity; - m_axes[i].defaultGameAxis = m_axes[i].gameAxis; - } -} - - -FString IOKitJoystick::GetIdentifier() -{ - return m_identifier; -} - - -void IOKitJoystick::AddAxes(float axes[NUM_JOYAXIS]) const -{ - for (size_t i = 0, count = m_axes.Size(); i < count; ++i) - { - const EJoyAxis axis = m_axes[i].gameAxis; - - if (JOYAXIS_None == axis) - { - continue; - } - - axes[axis] -= m_axes[i].value; - } -} - - -void IOKitJoystick::UseAxesPolling(const bool axesPolling) -{ - m_useAxesPolling = axesPolling; - - for (size_t i = 0, count = m_axes.Size(); i < count; ++i) - { - AnalogAxis& axis = m_axes[i]; - - if (m_useAxesPolling) - { - RemoveFromQueue(axis.cookie); - } - else - { - AddToQueue(axis.cookie); - } - } -} - - -void IOKitJoystick::Update() -{ - if (NULL == m_queue) - { - return; - } - - IOHIDEventStruct event = { }; - AbsoluteTime zeroTime = { }; - - const IOReturn eventResult = (*m_queue)->getNextEvent(m_queue, &event, zeroTime, 0); - - if (kIOReturnSuccess == eventResult) - { - if (use_joystick) - { - ProcessAxis(event) || ProcessButton(event) || ProcessPOV(event); - } - } - else if (kIOReturnUnderrun != eventResult) - { - Printf(TEXTCOLOR_RED "IOHIDQueueInterface::getNextEvent() failed with code 0x%08X\n", eventResult); - } - - ProcessAxes(); -} - - -void IOKitJoystick::ProcessAxes() -{ - if (NULL == m_interface || !m_useAxesPolling) - { - return; - } - - for (size_t i = 0, count = m_axes.Size(); i < count; ++i) - { - AnalogAxis& axis = m_axes[i]; - - static const double scaledMin = -1; - static const double scaledMax = 1; - - IOHIDEventStruct event; - - if (kIOReturnSuccess == (*m_interface)->getElementValue(m_interface, axis.cookie, &event)) - { - const double scaledValue = scaledMin + - (event.value - axis.minValue) * (scaledMax - scaledMin) / (axis.maxValue - axis.minValue); - const double filteredValue = Joy_RemoveDeadZone(scaledValue, axis.deadZone, NULL); - - axis.value = static_cast(filteredValue * m_sensitivity * axis.sensitivity); - } - else - { - axis.value = 0.0f; - } - } -} - - -bool IOKitJoystick::ProcessAxis(const IOHIDEventStruct& event) -{ - if (m_useAxesPolling) - { - return false; - } - - for (size_t i = 0, count = m_axes.Size(); i < count; ++i) - { - if (event.elementCookie != m_axes[i].cookie) - { - continue; - } - - AnalogAxis& axis = m_axes[i]; - - static const double scaledMin = -1; - static const double scaledMax = 1; - - const double scaledValue = scaledMin + - (event.value - axis.minValue) * (scaledMax - scaledMin) / (axis.maxValue - axis.minValue); - const double filteredValue = Joy_RemoveDeadZone(scaledValue, axis.deadZone, NULL); - - axis.value = static_cast(filteredValue * m_sensitivity * axis.sensitivity); - - return true; - } - - return false; -} - -bool IOKitJoystick::ProcessButton(const IOHIDEventStruct& event) -{ - for (size_t i = 0, count = m_buttons.Size(); i < count; ++i) - { - if (event.elementCookie != m_buttons[i].cookie) - { - continue; - } - - int32_t& current = m_buttons[i].value; - const int32_t previous = current; - current = event.value; - - Joy_GenerateButtonEvents(previous, current, 1, static_cast(KEY_FIRSTJOYBUTTON + i)); - - return true; - } - - return false; -} - -bool IOKitJoystick::ProcessPOV(const IOHIDEventStruct& event) -{ - for (size_t i = 0, count = m_POVs.Size(); i ( - CFDictionaryGetValue(properties, CFSTR(kIOHIDManufacturerKey))); - CFStringRef productRef = static_cast( - CFDictionaryGetValue(properties, CFSTR(kIOHIDProductKey))); - CFNumberRef vendorIDRef = static_cast( - CFDictionaryGetValue(properties, CFSTR(kIOHIDVendorIDKey))); - CFNumberRef productIDRef = static_cast( - CFDictionaryGetValue(properties, CFSTR(kIOHIDProductIDKey))); - - CFMutableDictionaryRef usbProperties = NULL; - - if ( NULL == vendorRef || NULL == productRef - || NULL == vendorIDRef || NULL == productIDRef) - { - // OS X is not mirroring all USB properties to HID page, so need to look at USB device page also - // Step up two levels and get dictionary of USB properties - - io_registry_entry_t parent1; - kern_return_t ioResult = IORegistryEntryGetParentEntry(device, kIOServicePlane, &parent1); - - if (KERN_SUCCESS == ioResult) - { - io_registry_entry_t parent2; - ioResult = IORegistryEntryGetParentEntry(device, kIOServicePlane, &parent2); - - if (KERN_SUCCESS == ioResult) - { - ioResult = IORegistryEntryCreateCFProperties(parent2, &usbProperties, kCFAllocatorDefault, kNilOptions); - - if (KERN_SUCCESS != ioResult) - { - Printf(TEXTCOLOR_RED "IORegistryEntryCreateCFProperties() failed with code %i\n", ioResult); - } - - IOObjectRelease(parent2); - } - else - { - Printf(TEXTCOLOR_RED "IORegistryEntryGetParentEntry(2) failed with code %i\n", ioResult); - } - - IOObjectRelease(parent1); - } - else - { - Printf(TEXTCOLOR_RED "IORegistryEntryGetParentEntry(1) failed with code %i\n", ioResult); - } - } - - if (NULL != usbProperties) - { - if (NULL == vendorRef) - { - vendorRef = static_cast( - CFDictionaryGetValue(usbProperties, CFSTR("USB Vendor Name"))); - } - - if (NULL == productRef) - { - productRef = static_cast( - CFDictionaryGetValue(usbProperties, CFSTR("USB Product Name"))); - } - - if (NULL == vendorIDRef) - { - vendorIDRef = static_cast( - CFDictionaryGetValue(usbProperties, CFSTR("idVendor"))); - } - - if (NULL == productIDRef) - { - productIDRef = static_cast( - CFDictionaryGetValue(usbProperties, CFSTR("idProduct"))); - } - } - - m_name += ToFString(vendorRef); - m_name += " "; - m_name += ToFString(productRef); - - int vendorID = 0, productID = 0; - - if (NULL != vendorIDRef) - { - CFNumberGetValue(vendorIDRef, kCFNumberIntType, &vendorID); - } - - if (NULL != productIDRef) - { - CFNumberGetValue(productIDRef, kCFNumberIntType, &productID); - } - - m_identifier.AppendFormat("VID_%04x_PID_%04x", vendorID, productID); - - if (NULL != usbProperties) - { - CFRelease(usbProperties); - } -} - - -long GetElementValue(const CFDictionaryRef element, const CFStringRef key) -{ - const CFNumberRef number = - static_cast(CFDictionaryGetValue(element, key)); - long result = 0; - - if (NULL != number && CFGetTypeID(number) == CFNumberGetTypeID()) - { - CFNumberGetValue(number, kCFNumberLongType, &result); - } - - return result; -} - -void IOKitJoystick::GatherElementsHandler(const void* value, void* parameter) -{ - assert(NULL != value); - assert(NULL != parameter); - - const CFDictionaryRef element = static_cast(value); - IOKitJoystick* thisPtr = static_cast(parameter); - - if (CFGetTypeID(element) != CFDictionaryGetTypeID()) - { - Printf(TEXTCOLOR_RED "IOKitJoystick: Encountered wrong element type\n"); - return; - } - - const long type = GetElementValue(element, CFSTR(kIOHIDElementTypeKey)); - - if (kIOHIDElementTypeCollection == type) - { - thisPtr->GatherCollectionElements(element); - } - else if (0 != type) - { - const long usagePage = GetElementValue(element, CFSTR(kIOHIDElementUsagePageKey)); - - if (kHIDPage_GenericDesktop == usagePage) - { - const long usage = GetElementValue(element, CFSTR(kIOHIDElementUsageKey)); - - if ( kHIDUsage_GD_Slider == usage - || kHIDUsage_GD_X == usage || kHIDUsage_GD_Y == usage || kHIDUsage_GD_Z == usage - || kHIDUsage_GD_Rx == usage || kHIDUsage_GD_Ry == usage || kHIDUsage_GD_Rz == usage) - { - thisPtr->AddAxis(element); - } - else if (kHIDUsage_GD_Hatswitch == usage && thisPtr->m_POVs.Size() < 4) - { - thisPtr->AddPOV(element); - } - } - else if (kHIDPage_Button == usagePage) - { - thisPtr->AddButton(element); - } - } -} - -void IOKitJoystick::GatherCollectionElements(const CFDictionaryRef properties) -{ - const CFArrayRef topElement = static_cast( - CFDictionaryGetValue(properties, CFSTR(kIOHIDElementKey))); - - if (NULL == topElement || CFGetTypeID(topElement) != CFArrayGetTypeID()) - { - Printf(TEXTCOLOR_RED "GatherCollectionElements: invalid properties dictionary\n"); - return; - } - - const CFRange range = { 0, CFArrayGetCount(topElement) }; - - CFArrayApplyFunction(topElement, range, GatherElementsHandler, this); -} - - -IOHIDElementCookie GetElementCookie(const CFDictionaryRef element) -{ - // Use C-style cast to avoid 32/64-bit IOHIDElementCookie type issue - return (IOHIDElementCookie)GetElementValue(element, CFSTR(kIOHIDElementCookieKey)); -} - -void IOKitJoystick::AddAxis(const CFDictionaryRef element) -{ - AnalogAxis axis; - - axis.cookie = GetElementCookie(element); - axis.minValue = GetElementValue(element, CFSTR(kIOHIDElementMinKey)); - axis.maxValue = GetElementValue(element, CFSTR(kIOHIDElementMaxKey)); - - const CFStringRef nameRef = static_cast( - CFDictionaryGetValue(element, CFSTR(kIOHIDElementNameKey))); - - if (NULL != nameRef && CFStringGetTypeID() == CFGetTypeID(nameRef)) - { - CFStringGetCString(nameRef, axis.name, sizeof(axis.name) - 1, kCFStringEncodingUTF8); - } - else - { - snprintf(axis.name, sizeof(axis.name), "Axis %i", m_axes.Size() + 1); - } - - m_axes.Push(axis); -} - -void IOKitJoystick::AddButton(CFDictionaryRef element) -{ - const DigitalButton button(GetElementCookie(element)); - - m_buttons.Push(button); - - AddToQueue(button.cookie); -} - -void IOKitJoystick::AddPOV(CFDictionaryRef element) -{ - const DigitalButton pov(GetElementCookie(element)); - - m_POVs.Push(pov); - - AddToQueue(pov.cookie); -} - - -void IOKitJoystick::AddToQueue(const IOHIDElementCookie cookie) -{ - if (NULL == m_queue) - { - return; - } - - if (!(*m_queue)->hasElement(m_queue, cookie)) - { - (*m_queue)->addElement(m_queue, cookie, 0); - } -} - -void IOKitJoystick::RemoveFromQueue(const IOHIDElementCookie cookie) -{ - if (NULL == m_queue) - { - return; - } - - if ((*m_queue)->hasElement(m_queue, cookie)) - { - (*m_queue)->removeElement(m_queue, cookie); - } -} - - -io_object_t* IOKitJoystick::GetNotificationPtr() -{ - return &m_notification; -} - - -// --------------------------------------------------------------------------- - - -class IOKitJoystickManager -{ -public: - IOKitJoystickManager(); - ~IOKitJoystickManager(); - - void GetJoysticks(TArray& joysticks) const; - - void AddAxes(float axes[NUM_JOYAXIS]) const; - - // Updates axes/buttons states - void Update(); - - void UseAxesPolling(bool axesPolling); - -private: - typedef TDeletingArray JoystickList; - JoystickList m_joysticks; - - static const size_t NOTIFICATION_PORT_COUNT = 2; - - IONotificationPortRef m_notificationPorts[NOTIFICATION_PORT_COUNT]; - io_iterator_t m_notifications [NOTIFICATION_PORT_COUNT]; - - // Rebuilds device list - void Rescan(int usagePage, int usage, size_t notificationPortIndex); - void AddDevices(IONotificationPortRef notificationPort, const io_iterator_t iterator); - - static void OnDeviceAttached(void* refcon, io_iterator_t iterator); - static void OnDeviceRemoved(void* refcon, io_service_t service, - natural_t messageType, void* messageArgument); -}; - - -IOKitJoystickManager* s_joystickManager; - - -IOKitJoystickManager::IOKitJoystickManager() -{ - memset(m_notifications, 0, sizeof m_notifications); - - for (size_t i = 0; i < NOTIFICATION_PORT_COUNT; ++i) - { - m_notificationPorts[i] = IONotificationPortCreate(kIOMasterPortDefault); - - if (NULL == m_notificationPorts[i]) - { - Printf(TEXTCOLOR_RED "IONotificationPortCreate(%zu) failed\n", i); - return; - } - - CFRunLoopAddSource(CFRunLoopGetCurrent(), - IONotificationPortGetRunLoopSource(m_notificationPorts[i]), kCFRunLoopDefaultMode); - } - - Rescan(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, 0); - Rescan(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, 1); -} - -IOKitJoystickManager::~IOKitJoystickManager() -{ - for (size_t i = 0; i < NOTIFICATION_PORT_COUNT; ++i) - { - IONotificationPortRef& port = m_notificationPorts[i]; - - if (NULL != port) - { - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), - IONotificationPortGetRunLoopSource(port), kCFRunLoopDefaultMode); - - IONotificationPortDestroy(port); - port = NULL; - } - - io_iterator_t& notification = m_notifications[i]; - - if (0 != notification) - { - IOObjectRelease(notification); - notification = 0; - } - } -} - - -void IOKitJoystickManager::GetJoysticks(TArray& joysticks) const -{ - const size_t joystickCount = m_joysticks.Size(); - - joysticks.Resize(joystickCount); - - for (size_t i = 0; i < joystickCount; ++i) - { - M_LoadJoystickConfig(m_joysticks[i]); - - joysticks[i] = m_joysticks[i]; - } -} - -void IOKitJoystickManager::AddAxes(float axes[NUM_JOYAXIS]) const -{ - for (size_t i = 0, count = m_joysticks.Size(); i < count; ++i) - { - m_joysticks[i]->AddAxes(axes); - } -} - - -void IOKitJoystickManager::Update() -{ - for (size_t i = 0, count = m_joysticks.Size(); i < count; ++i) - { - m_joysticks[i]->Update(); - } -} - - -void IOKitJoystickManager::UseAxesPolling(const bool axesPolling) -{ - for (size_t i = 0, count = m_joysticks.Size(); i < count; ++i) - { - m_joysticks[i]->UseAxesPolling(axesPolling); - } -} - - -void PostDeviceChangeEvent() -{ - const event_t event = { EV_DeviceChange }; - D_PostEvent(&event); -} - - -void IOKitJoystickManager::Rescan(const int usagePage, const int usage, const size_t notificationPortIndex) -{ - CFMutableDictionaryRef deviceMatching = IOServiceMatching(kIOHIDDeviceKey); - - if (NULL == deviceMatching) - { - Printf(TEXTCOLOR_RED "IOServiceMatching() returned NULL\n"); - return; - } - - const CFNumberRef usagePageRef = - CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage); - CFDictionarySetValue(deviceMatching, CFSTR(kIOHIDPrimaryUsagePageKey), usagePageRef); - - const CFNumberRef usageRef = - CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); - CFDictionarySetValue(deviceMatching, CFSTR(kIOHIDPrimaryUsageKey), usageRef); - - assert(notificationPortIndex < NOTIFICATION_PORT_COUNT); - io_iterator_t* iteratorPtr = &m_notifications[notificationPortIndex]; - - const IONotificationPortRef notificationPort = m_notificationPorts[notificationPortIndex]; - assert(NULL != notificationPort); - - const kern_return_t notificationResult = IOServiceAddMatchingNotification(notificationPort, - kIOFirstMatchNotification, deviceMatching, OnDeviceAttached, notificationPort, iteratorPtr); - - // IOServiceAddMatchingNotification() consumes one reference of matching dictionary - // Thus CFRelease(deviceMatching) is not needed - - CFRelease(usageRef); - CFRelease(usagePageRef); - - if (KERN_SUCCESS != notificationResult) - { - Printf(TEXTCOLOR_RED "IOServiceAddMatchingNotification() failed with code %i\n", notificationResult); - } - - AddDevices(notificationPort, *iteratorPtr); -} - -void IOKitJoystickManager::AddDevices(const IONotificationPortRef notificationPort, const io_iterator_t iterator) -{ - while (io_object_t device = IOIteratorNext(iterator)) - { - IOKitJoystick* joystick = new IOKitJoystick(device); - m_joysticks.Push(joystick); - - const kern_return_t notificationResult = IOServiceAddInterestNotification(notificationPort, - device, kIOGeneralInterest, OnDeviceRemoved, joystick, joystick->GetNotificationPtr()); - if (KERN_SUCCESS != notificationResult) - { - Printf(TEXTCOLOR_RED "IOServiceAddInterestNotification() failed with code %i\n", notificationResult); - } - - IOObjectRelease(device); - - PostDeviceChangeEvent(); - } -} - - -void IOKitJoystickManager::OnDeviceAttached(void* const refcon, const io_iterator_t iterator) -{ - assert(NULL != refcon); - const IONotificationPortRef notificationPort = static_cast(refcon); - - assert(NULL != s_joystickManager); - s_joystickManager->AddDevices(notificationPort, iterator); -} - -void IOKitJoystickManager::OnDeviceRemoved(void* const refcon, io_service_t, const natural_t messageType, void*) -{ - if (messageType != kIOMessageServiceIsTerminated) - { - return; - } - - assert(NULL != refcon); - IOKitJoystick* const joystick = static_cast(refcon); - - assert(NULL != s_joystickManager); - JoystickList& joysticks = s_joystickManager->m_joysticks; - - for (unsigned int i = 0, count = joysticks.Size(); i < count; ++i) - { - if (joystick == joysticks[i]) - { - joysticks.Delete(i); - break; - } - } - - delete joystick; - - PostDeviceChangeEvent(); -} - -} // unnamed namespace - - -// --------------------------------------------------------------------------- - - -void I_ShutdownJoysticks() -{ - // Needed in order to support existing interface - // Left empty intentionally -} - -static void ShutdownJoysticks() -{ - delete s_joystickManager; - s_joystickManager = NULL; -} - -void I_GetJoysticks(TArray& sticks) -{ - // Instances of IOKitJoystick depend on GameConfig object. - // M_SaveDefaultsFinal() must be called after destruction of IOKitJoystickManager. - // To ensure this, its initialization is moved here. - // As M_LoadDefaults() was already called at this moment, - // the order of atterm's functions will be correct - - if (NULL == s_joystickManager && !Args->CheckParm("-nojoy")) - { - s_joystickManager = new IOKitJoystickManager; - atterm(ShutdownJoysticks); - } - - if (NULL != s_joystickManager) - { - s_joystickManager->GetJoysticks(sticks); - } -} - -void I_GetAxes(float axes[NUM_JOYAXIS]) -{ - for (size_t i = 0; i < NUM_JOYAXIS; ++i) - { - axes[i] = 0.0f; - } - - if (use_joystick && NULL != s_joystickManager) - { - s_joystickManager->AddAxes(axes); - } -} - -IJoystickConfig* I_UpdateDeviceList() -{ - // Does nothing, device list is always kept up-to-date - - return NULL; -} - - -// --------------------------------------------------------------------------- - - -void I_ProcessJoysticks() -{ - if (NULL != s_joystickManager) - { - s_joystickManager->Update(); - } -} - - -// --------------------------------------------------------------------------- - - -CUSTOM_CVAR(Bool, joy_axespolling, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) -{ - if (NULL != s_joystickManager) - { - s_joystickManager->UseAxesPolling(self); - } -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_main.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_main.mm deleted file mode 100644 index 9e62061..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_main.mm +++ /dev/null @@ -1,531 +0,0 @@ -/* - ** i_main.mm - ** - **--------------------------------------------------------------------------- - ** Copyright 2012-2018 Alexey Lysiuk - ** 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 "i_common.h" -#include "s_sound.h" -#include "atterm.h" - -#include -#include - -#include "c_console.h" -#include "c_cvars.h" -#include "cmdlib.h" -#include "d_main.h" -#include "doomerrors.h" -#include "i_system.h" -#include "m_argv.h" -#include "s_sound.h" -#include "st_console.h" -#include "version.h" -#include "s_music.h" - - -#define ZD_UNUSED(VARIABLE) ((void)(VARIABLE)) - - -// --------------------------------------------------------------------------- - - -CVAR (Bool, i_soundinbackground, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) -EXTERN_CVAR(Int, vid_defwidth ) -EXTERN_CVAR(Int, vid_defheight) -EXTERN_CVAR(Bool, vid_vsync ) -EXTERN_CVAR(Bool, fullscreen ) - - -// --------------------------------------------------------------------------- - - -void Mac_I_FatalError(const char* const message) -{ - I_SetMainWindowVisible(false); - S_StopMusic(true); - - FConsoleWindow::GetInstance().ShowFatalError(message); -} - - -static void I_DetectOS() -{ - SInt32 majorVersion = 0; - Gestalt(gestaltSystemVersionMajor, &majorVersion); - - SInt32 minorVersion = 0; - Gestalt(gestaltSystemVersionMinor, &minorVersion); - - SInt32 bugFixVersion = 0; - Gestalt(gestaltSystemVersionBugFix, &bugFixVersion); - - const char* name = "Unknown version"; - - if (10 == majorVersion) switch (minorVersion) - { - case 4: name = "Mac OS X Tiger"; break; - case 5: name = "Mac OS X Leopard"; break; - case 6: name = "Mac OS X Snow Leopard"; break; - case 7: name = "Mac OS X Lion"; break; - case 8: name = "OS X Mountain Lion"; break; - case 9: name = "OS X Mavericks"; break; - case 10: name = "OS X Yosemite"; break; - case 11: name = "OS X El Capitan"; break; - case 12: name = "macOS Sierra"; break; - case 13: name = "macOS High Sierra"; break; - case 14: name = "macOS Mojave"; break; - case 15: name = "macOS Catalina"; break; - } - - char release[16] = "unknown"; - size_t size = sizeof release - 1; - sysctlbyname("kern.osversion", release, &size, nullptr, 0); - - const char* const architecture = -#ifdef __i386__ - "32-bit Intel"; -#elif defined __x86_64__ - "64-bit Intel"; -#else - "Unknown"; -#endif - - Printf("OS: %s %d.%d.%d (%s) %s\n", name, - int(majorVersion), int(minorVersion), int(bugFixVersion), - release, architecture); -} - - -FArgs* Args; // command line arguments - - -// Newer versions of GCC than 4.2 have a bug with C++ exceptions in Objective-C++ code. -// To work around we'll implement the try and catch in standard C++. -// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61759 -void OriginalMainExcept(int argc, char** argv); -void OriginalMainTry(int argc, char** argv) -{ - 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); - - NSString* exePath = [[NSBundle mainBundle] executablePath]; - progdir = [[exePath stringByDeletingLastPathComponent] UTF8String]; - progdir += "/"; - - C_InitConsole(80 * 8, 25 * 8, false); - - I_DetectOS(); - D_DoomMain(); -} - -namespace -{ - -TArray s_argv; - - -void NewFailure() -{ - I_FatalError("Failed to allocate memory from system heap"); -} - -int OriginalMain(int argc, char** argv) -{ - printf(GAMENAME" %s - %s - Cocoa version\nCompiled on %s\n\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"); - - // Set reasonable default values for video settings - - const NSSize screenSize = [[NSScreen mainScreen] frame].size; - vid_defwidth = static_cast(screenSize.width); - vid_defheight = static_cast(screenSize.height); - vid_vsync = true; - fullscreen = true; - - OriginalMainExcept(argc, argv); - - return 0; -} - -} // unnamed namespace - - -// --------------------------------------------------------------------------- - - -@interface ApplicationController : NSResponder -{ -} - -- (void)keyDown:(NSEvent*)theEvent; -- (void)keyUp:(NSEvent*)theEvent; - -- (void)applicationDidBecomeActive:(NSNotification*)aNotification; -- (void)applicationWillResignActive:(NSNotification*)aNotification; - -- (void)applicationDidFinishLaunching:(NSNotification*)aNotification; - -- (BOOL)application:(NSApplication*)theApplication openFile:(NSString*)filename; - -- (void)processEvents:(NSTimer*)timer; - -@end - - -ApplicationController* appCtrl; - - -@implementation ApplicationController - -- (void)keyDown:(NSEvent*)theEvent -{ - // Empty but present to avoid playing of 'beep' alert sound - - ZD_UNUSED(theEvent); -} - -- (void)keyUp:(NSEvent*)theEvent -{ - // Empty but present to avoid playing of 'beep' alert sound - - ZD_UNUSED(theEvent); -} - - -extern bool AppActive; - -- (void)applicationDidBecomeActive:(NSNotification*)aNotification -{ - ZD_UNUSED(aNotification); - - S_SetSoundPaused(1); - - AppActive = true; -} - -- (void)applicationWillResignActive:(NSNotification*)aNotification -{ - ZD_UNUSED(aNotification); - - S_SetSoundPaused(i_soundinbackground); - - AppActive = false; -} - - -- (void)applicationDidFinishLaunching:(NSNotification*)aNotification -{ - // When starting from command line with real executable path, e.g. ZDoom.app/Contents/MacOS/ZDoom - // application remains deactivated for an unknown reason. - // The following call resolves this issue - [NSApp activateIgnoringOtherApps:YES]; - - // Setup timer for custom event loop - - NSTimer* timer = [NSTimer timerWithTimeInterval:0 - target:self - selector:@selector(processEvents:) - userInfo:nil - repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer:timer - forMode:NSDefaultRunLoopMode]; - - FConsoleWindow::CreateInstance(); - atterm(FConsoleWindow::DeleteInstance); - - const size_t argc = s_argv.Size(); - TArray argv(argc + 1, true); - - for (size_t i = 0; i < argc; ++i) - { - argv[i] = s_argv[i].LockBuffer(); - } - - argv[argc] = nullptr; - - exit(OriginalMain(argc, &argv[0])); -} - - -- (BOOL)application:(NSApplication*)theApplication openFile:(NSString*)filename -{ - ZD_UNUSED(theApplication); - - // Some parameters from command line are passed to this function - // These parameters need to be skipped to avoid duplication - // Note: SDL has different approach to fix this issue, see the same method in SDLMain.m - - const char* const charFileName = [filename UTF8String]; - - for (size_t i = 0, count = s_argv.Size(); i < count; ++i) - { - if (0 == strcmp(s_argv[i], charFileName)) - { - return FALSE; - } - } - - bool iwad = false; - - if (const char* const extPos = strrchr(charFileName, '.')) - { - iwad = 0 == stricmp(extPos, ".iwad") - || 0 == stricmp(extPos, ".ipk3") - || 0 == stricmp(extPos, ".ipk7"); - } - - s_argv.Push(iwad ? "-iwad" : "-file"); - s_argv.Push(charFileName); - - return TRUE; -} - - -- (void)processEvents:(NSTimer*)timer -{ - ZD_UNUSED(timer); - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - while (true) - { - NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate dateWithTimeIntervalSinceNow:0] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (nil == event) - { - break; - } - - I_ProcessEvent(event); - - [NSApp sendEvent:event]; - } - - [NSApp updateWindows]; - - [pool release]; -} - -@end - - -// --------------------------------------------------------------------------- - - -namespace -{ - -NSMenuItem* CreateApplicationMenu() -{ - NSMenu* menu = [NSMenu new]; - - [menu addItemWithTitle:[@"About " stringByAppendingString:@GAMENAME] - action:@selector(orderFrontStandardAboutPanel:) - keyEquivalent:@""]; - [menu addItem:[NSMenuItem separatorItem]]; - [menu addItemWithTitle:[@"Hide " stringByAppendingString:@GAMENAME] - action:@selector(hide:) - keyEquivalent:@"h"]; - [[menu addItemWithTitle:@"Hide Others" - action:@selector(hideOtherApplications:) - keyEquivalent:@"h"] - setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask]; - [menu addItemWithTitle:@"Show All" - action:@selector(unhideAllApplications:) - keyEquivalent:@""]; - [menu addItem:[NSMenuItem separatorItem]]; - [menu addItemWithTitle:[@"Quit " stringByAppendingString:@GAMENAME] - action:@selector(terminate:) - keyEquivalent:@"q"]; - - NSMenuItem* menuItem = [NSMenuItem new]; - [menuItem setSubmenu:menu]; - - if ([NSApp respondsToSelector:@selector(setAppleMenu:)]) - { - [NSApp performSelector:@selector(setAppleMenu:) withObject:menu]; - } - - return menuItem; -} - -NSMenuItem* CreateEditMenu() -{ - NSMenu* menu = [[NSMenu alloc] initWithTitle:@"Edit"]; - - [menu addItemWithTitle:@"Undo" - action:@selector(undo:) - keyEquivalent:@"z"]; - [menu addItemWithTitle:@"Redo" - action:@selector(redo:) - keyEquivalent:@"Z"]; - [menu addItem:[NSMenuItem separatorItem]]; - [menu addItemWithTitle:@"Cut" - action:@selector(cut:) - keyEquivalent:@"x"]; - [menu addItemWithTitle:@"Copy" - action:@selector(copy:) - keyEquivalent:@"c"]; - [menu addItemWithTitle:@"Paste" - action:@selector(paste:) - keyEquivalent:@"v"]; - [menu addItemWithTitle:@"Delete" - action:@selector(delete:) - keyEquivalent:@""]; - [menu addItemWithTitle:@"Select All" - action:@selector(selectAll:) - keyEquivalent:@"a"]; - - NSMenuItem* menuItem = [NSMenuItem new]; - [menuItem setSubmenu:menu]; - - return menuItem; -} - -NSMenuItem* CreateWindowMenu() -{ - NSMenu* menu = [[NSMenu alloc] initWithTitle:@"Window"]; - [NSApp setWindowsMenu:menu]; - - [menu addItemWithTitle:@"Minimize" - action:@selector(performMiniaturize:) - keyEquivalent:@"m"]; - [menu addItemWithTitle:@"Zoom" - action:@selector(performZoom:) - keyEquivalent:@""]; - [menu addItem:[NSMenuItem separatorItem]]; - [menu addItemWithTitle:@"Bring All to Front" - action:@selector(arrangeInFront:) - keyEquivalent:@""]; - - NSMenuItem* menuItem = [NSMenuItem new]; - [menuItem setSubmenu:menu]; - - return menuItem; -} - -void CreateMenu() -{ - NSMenu* menuBar = [NSMenu new]; - [menuBar addItem:CreateApplicationMenu()]; - [menuBar addItem:CreateEditMenu()]; - [menuBar addItem:CreateWindowMenu()]; - - [NSApp setMainMenu:menuBar]; -} - -void ReleaseApplicationController() -{ - if (NULL != appCtrl) - { - [NSApp setDelegate:nil]; - [NSApp deactivate]; - - [appCtrl release]; - appCtrl = NULL; - } -} - -} // unnamed namespace - - -int main(int argc, char** argv) -{ - for (int i = 0; i < argc; ++i) - { - const char* const argument = argv[i]; - -#if _DEBUG - if (0 == strcmp(argument, "-wait_for_debugger")) - { - NSAlert* alert = [[NSAlert alloc] init]; - [alert setMessageText:@GAMENAME]; - [alert setInformativeText:@"Waiting for debugger..."]; - [alert addButtonWithTitle:@"Continue"]; - [alert runModal]; - } -#endif // _DEBUG - - s_argv.Push(argument); - } - - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - [NSApplication sharedApplication]; - - // The following code isn't mandatory, - // but it enables to run the application without a bundle - if ([NSApp respondsToSelector:@selector(setActivationPolicy:)]) - { - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - } - - CreateMenu(); - - atterm(ReleaseApplicationController); - - appCtrl = [ApplicationController new]; - [NSApp setDelegate:appCtrl]; - [NSApp run]; - - [pool release]; - - return EXIT_SUCCESS; -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_main_except.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_main_except.cpp deleted file mode 100644 index e67914a..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_main_except.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - ** i_main_except.cpp - ** - **--------------------------------------------------------------------------- - ** Copyright 2012-2015 Alexey Lysiuk - ** 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. - **--------------------------------------------------------------------------- - ** - */ -// Workaround for GCC Objective-C++ with C++ exceptions bug. - -#include - -#include "doomerrors.h" -#include "vm.h" -#include "atterm.h" - -// Import some functions from i_main.mm -void Mac_I_FatalError(const char* const message); -void OriginalMainTry(int argc, char** argv); - -void OriginalMainExcept(int argc, char** argv) -{ - try - { - OriginalMainTry(argc, argv); - } - catch(const std::exception& error) - { - const char* const message = error.what(); - - if (strcmp(message, "NoRunExit")) - { - if (CVMAbortException::stacktrace.IsNotEmpty()) - { - Printf("%s", CVMAbortException::stacktrace.GetChars()); - } - - if (batchrun) - { - Printf("%s\n", message); - } - else - { - Mac_I_FatalError(message); - } - } - - exit(-1); - } - catch(...) - { - call_terms(); - throw; - } -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_system.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_system.mm deleted file mode 100644 index 4e21537..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_system.mm +++ /dev/null @@ -1,376 +0,0 @@ -/* - ** i_system.mm - ** - **--------------------------------------------------------------------------- - ** Copyright 2012-2018 Alexey Lysiuk - ** 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 "i_common.h" - -#include -#include -#include -#include - -#include "d_protocol.h" -#include "doomdef.h" -#include "doomerrors.h" -#include "doomstat.h" -#include "g_game.h" -#include "gameconfigfile.h" -#include "i_sound.h" -#include "i_system.h" -#include "st_console.h" -#include "v_text.h" -#include "x86.h" -#include "cmdlib.h" -#include "atterm.h" - - -void I_Tactile(int /*on*/, int /*off*/, int /*total*/) -{ -} - - -ticcmd_t* I_BaseTiccmd() -{ - static ticcmd_t emptycmd; - return &emptycmd; -} - - - -double PerfToSec, PerfToMillisec; - -static void CalculateCPUSpeed() -{ - long long frequency; - size_t size = sizeof frequency; - - if (0 == sysctlbyname("machdep.tsc.frequency", &frequency, &size, nullptr, 0) && 0 != frequency) - { - PerfToSec = 1.0 / frequency; - PerfToMillisec = 1000.0 / frequency; - - if (!batchrun) - { - Printf("CPU speed: %.0f MHz\n", 0.001 / PerfToMillisec); - } - } -} - -void I_Init(void) -{ - CheckCPUID(&CPU); - CalculateCPUSpeed(); - DumpCPUInfo(&CPU); - - atterm(I_ShutdownSound); - I_InitSound(); -} - -static int has_exited; - -void I_Quit() -{ - has_exited = 1; // Prevent infinitely recursive exits -- killough - - if (demorecording) - { - G_CheckDemoStatus(); - } - - C_DeinitConsole(); -} - - -extern FILE* Logfile; -bool gameisdead; - -static void I_FatalError(const char* const 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); - - extern void Mac_I_FatalError(const char*); - Mac_I_FatalError(errortext); - - // Record error to log (if logging) - if (Logfile) - { - fprintf(Logfile, "\n**** DIED WITH FATAL ERROR:\n%s\n", errortext); - fflush(Logfile); - } - - 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); - throw CRecoverableError(errortext); -} - - -void I_SetIWADInfo() -{ -} - - -void I_DebugPrint(const char *cp) -{ - NSLog(@"%s", cp); -} - - -void I_PrintStr(const char* const message) -{ - FConsoleWindow::GetInstance().AddText(message); - - // Strip out any color escape sequences before writing to output - char* const copy = new char[strlen(message) + 1]; - const char* srcp = message; - char* dstp = copy; - - while ('\0' != *srcp) - { - if (TEXTCOLOR_ESCAPE == *srcp) - { - if ('\0' != srcp[1]) - { - srcp += 2; - } - else - { - break; - } - } - else if (0x1d == *srcp || 0x1f == *srcp) // Opening and closing bar character - { - *dstp++ = '-'; - ++srcp; - } - else if (0x1e == *srcp) // Middle bar character - { - *dstp++ = '='; - ++srcp; - } - else - { - *dstp++ = *srcp++; - } - } - - *dstp = '\0'; - - fputs(copy, stdout); - delete[] copy; - fflush(stdout); -} - - -int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, const int defaultiwad) -{ - if (!showwin) - { - return defaultiwad; - } - - I_SetMainWindowVisible(false); - - extern int I_PickIWad_Cocoa(WadStuff*, int, bool, int); - const int result = I_PickIWad_Cocoa(wads, numwads, showwin, defaultiwad); - - I_SetMainWindowVisible(true); - - return result; -} - - -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 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* const filespec, findstate_t* const fileinfo) -{ - FString dir; - - const char* const 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* const handle, findstate_t* const fileinfo) -{ - findstate_t* const state = static_cast(handle); - - if (state->current < fileinfo->count) - { - return ++state->current < fileinfo->count ? 0 : -1; - } - - return -1; -} - -int I_FindClose(void* const handle) -{ - findstate_t* const state = static_cast(handle); - - if (handle != (void*)-1 && state->count > 0) - { - for (int i = 0; i < state->count; ++i) - { - free(state->namelist[i]); - } - - free(state->namelist); - state->namelist = NULL; - state->count = 0; - } - - 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* const string) -{ - NSPasteboard* const pasteBoard = [NSPasteboard generalPasteboard]; - NSString* const stringType = NSStringPboardType; - NSArray* const types = [NSArray arrayWithObjects:stringType, nil]; - NSString* const content = [NSString stringWithUTF8String:string]; - - [pasteBoard declareTypes:types - owner:nil]; - [pasteBoard setString:content - forType:stringType]; -} - -FString I_GetFromClipboard(bool returnNothing) -{ - if (returnNothing) - { - return FString(); - } - - NSPasteboard* const pasteBoard = [NSPasteboard generalPasteboard]; - NSString* const value = [pasteBoard stringForType:NSStringPboardType]; - - return FString([value UTF8String]); -} - - -unsigned int I_MakeRNGSeed() -{ - return static_cast(arc4random()); -} - - -TArray I_GetGogPaths() -{ - // GOG's Doom games are Windows only at the moment - return TArray(); -} - diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_video.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_video.mm deleted file mode 100644 index d0d4f8f..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/i_video.mm +++ /dev/null @@ -1,1448 +0,0 @@ -/* - ** i_video.mm - ** - **--------------------------------------------------------------------------- - ** Copyright 2012-2015 Alexey Lysiuk - ** 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 "gl/system/gl_load.h" - -#include "i_common.h" - -#include "bitmap.h" -#include "c_dispatch.h" -#include "doomstat.h" -#include "hardware.h" -#include "i_system.h" -#include "m_argv.h" -#include "m_png.h" -#include "r_renderer.h" -#include "swrenderer/r_swrenderer.h" -#include "st_console.h" -#include "stats.h" -#include "textures.h" -#include "v_palette.h" -#include "v_pfx.h" -#include "v_text.h" -#include "v_video.h" -#include "version.h" -#include "videomodes.h" -#include "atterm.h" - -#include "gl/system/gl_system.h" -#include "gl/data/gl_vertexbuffer.h" -#include "gl/renderer/gl_renderer.h" -#include "gl/system/gl_framebuffer.h" -#include "gl/system/gl_interface.h" -#include "gl/textures/gl_samplers.h" -#include "gl/utility/gl_clock.h" - - -@implementation NSWindow(ExitAppOnClose) - -- (void)exitAppOnClose -{ - NSButton* closeButton = [self standardWindowButton:NSWindowCloseButton]; - [closeButton setAction:@selector(terminate:)]; - [closeButton setTarget:NSApp]; -} - -@end - -@interface NSWindow(EnterFullscreenOnZoom) -- (void)enterFullscreenOnZoom; -@end - -@implementation NSWindow(EnterFullscreenOnZoom) - -- (void)enterFullscreen:(id)sender -{ - ToggleFullscreen = true; -} - -- (void)enterFullscreenOnZoom -{ - NSButton* zoomButton = [self standardWindowButton:NSWindowZoomButton]; - [zoomButton setEnabled:YES]; - [zoomButton setAction:@selector(enterFullscreen:)]; - [zoomButton setTarget:self]; -} - -@end - -DFrameBuffer *CreateGLSWFrameBuffer(int width, int height, bool bgra, bool fullscreen); - -int currentrenderer; - -CUSTOM_CVAR(Bool, vid_glswfb, true, CVAR_NOINITCALL | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) -{ - Printf("This won't take effect until " GAMENAME " is restarted.\n"); -} - -EXTERN_CVAR(Bool, ticker ) -EXTERN_CVAR(Bool, vid_vsync) -EXTERN_CVAR(Bool, vid_hidpi) - -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) - { - extern int NewWidth, NewHeight, NewBits, DisplayBits; - NewWidth = screen->VideoWidth; - NewHeight = screen->VideoHeight; - NewBits = DisplayBits; - setmodeneeded = true; - } -} - -CUSTOM_CVAR(Bool, fullscreen, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - extern int NewWidth, NewHeight, NewBits, DisplayBits; - - NewWidth = screen->VideoWidth; - NewHeight = screen->VideoHeight; - NewBits = DisplayBits; - setmodeneeded = true; -} - -CUSTOM_CVAR(Bool, vid_autoswitch, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) -{ - Printf("You must restart " GAMENAME " to apply graphics switching mode\n"); -} - -CUSTOM_CVAR(Int, vid_renderer, 0, 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", - static_cast(vid_renderer)); - self = 0; - break; - } - - Printf("You must restart " GAMENAME " to switch the renderer\n"); - } -} - -EXTERN_CVAR(Bool, gl_smooth_rendered) - - -RenderBufferOptions rbOpts; - - -// --------------------------------------------------------------------------- - - -namespace -{ - const NSInteger LEVEL_FULLSCREEN = NSMainMenuWindowLevel + 1; - const NSInteger LEVEL_WINDOWED = NSNormalWindowLevel; - - const NSUInteger STYLE_MASK_FULLSCREEN = NSBorderlessWindowMask; - const NSUInteger STYLE_MASK_WINDOWED = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; -} - - -// --------------------------------------------------------------------------- - - -@interface CocoaWindow : NSWindow -{ - NSString* m_title; -} - -- (BOOL)canBecomeKeyWindow; -- (void)setTitle:(NSString*)title; -- (void)updateTitle; - -@end - - -@implementation CocoaWindow - -- (BOOL)canBecomeKeyWindow -{ - return true; -} - -- (void)setTitle:(NSString*)title -{ - m_title = title; - - [self updateTitle]; -} - -- (void)updateTitle -{ - if (nil == m_title) - { - m_title = [NSString stringWithFormat:@"%s %s", GAMESIG, GetVersionString()]; - } - - [super setTitle:m_title]; -} - -@end - - -// --------------------------------------------------------------------------- - - -@interface CocoaView : NSOpenGLView -{ - NSCursor* m_cursor; -} - -- (void)resetCursorRects; - -- (void)setCursor:(NSCursor*)cursor; - -@end - - -@implementation CocoaView - -- (void)resetCursorRects -{ - [super resetCursorRects]; - - NSCursor* const cursor = nil == m_cursor - ? [NSCursor arrowCursor] - : m_cursor; - - [self addCursorRect:[self bounds] - cursor:cursor]; -} - -- (void)setCursor:(NSCursor*)cursor -{ - m_cursor = cursor; -} - -@end - - -// --------------------------------------------------------------------------- - - -class CocoaVideo : public IVideo -{ -public: - CocoaVideo(); - - virtual EDisplayType GetDisplayType() { return DISPLAY_Both; } - virtual void SetWindowedScale(float scale); - - virtual DFrameBuffer* CreateFrameBuffer(int width, int height, bool bgra, bool fs, DFrameBuffer* old); - - virtual void StartModeIterator(int bits, bool fullscreen); - virtual bool NextMode(int* width, int* height, bool* letterbox); - - static bool IsFullscreen(); - static void UseHiDPI(bool hiDPI); - static void SetCursor(NSCursor* cursor); - static void SetWindowVisible(bool visible); - static void SetWindowTitle(const char* title); - -private: - struct ModeIterator - { - size_t index; - int bits; - bool fullscreen; - }; - - ModeIterator m_modeIterator; - - CocoaWindow* m_window; - - int m_width; - int m_height; - bool m_fullscreen; - bool m_hiDPI; - - void SetFullscreenMode(int width, int height); - void SetWindowedMode(int width, int height); - void SetMode(int width, int height, bool fullscreen, bool hiDPI); - - static CocoaVideo* GetInstance(); -}; - - -// --------------------------------------------------------------------------- - - -class CocoaFrameBuffer : public DFrameBuffer -{ -public: - CocoaFrameBuffer(int width, int height, bool bgra, bool fullscreen); - ~CocoaFrameBuffer(); - - virtual bool Lock(bool buffer); - virtual void Unlock(); - virtual void Update(); - - virtual PalEntry* GetPalette(); - virtual void GetFlashedPalette(PalEntry pal[256]); - virtual void UpdatePalette(); - - virtual bool SetGamma(float gamma); - virtual bool SetFlash(PalEntry rgb, int amount); - virtual void GetFlash(PalEntry &rgb, int &amount); - - virtual int GetPageCount(); - - virtual bool IsFullscreen(); - - virtual void SetVSync(bool vsync); - -private: - static const size_t BYTES_PER_PIXEL = 4; - - PalEntry m_palette[256]; - bool m_needPaletteUpdate; - - uint8_t m_gammaTable[3][256]; - float m_gamma; - bool m_needGammaUpdate; - - PalEntry m_flashColor; - int m_flashAmount; - - bool UpdatePending; - - uint8_t* m_pixelBuffer; - GLuint m_texture; - - void Flip(); - - void UpdateColors(); -}; - - -// --------------------------------------------------------------------------- - - -EXTERN_CVAR(Float, Gamma) - -CUSTOM_CVAR(Float, rgamma, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - if (NULL != screen) - { - screen->SetGamma(Gamma); - } -} - -CUSTOM_CVAR(Float, ggamma, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - if (NULL != screen) - { - screen->SetGamma(Gamma); - } -} - -CUSTOM_CVAR(Float, bgamma, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - if (NULL != screen) - { - screen->SetGamma(Gamma); - } -} - - -// --------------------------------------------------------------------------- - - -extern id appCtrl; - - -namespace -{ - -cycle_t BlitCycles; -cycle_t FlipCycles; - - -CocoaWindow* CreateCocoaWindow(const NSUInteger styleMask) -{ - static const CGFloat TEMP_WIDTH = VideoModes[0].width - 1; - static const CGFloat TEMP_HEIGHT = VideoModes[0].height - 1; - - CocoaWindow* const window = [CocoaWindow alloc]; - [window initWithContentRect:NSMakeRect(0, 0, TEMP_WIDTH, TEMP_HEIGHT) - styleMask:styleMask - backing:NSBackingStoreBuffered - defer:NO]; - [window setOpaque:YES]; - [window makeFirstResponder:appCtrl]; - [window setAcceptsMouseMovedEvents:YES]; - - return window; -} - -NSOpenGLPixelFormat* CreatePixelFormat(const NSOpenGLPixelFormatAttribute profile) -{ - NSOpenGLPixelFormatAttribute attributes[16]; - size_t i = 0; - - attributes[i++] = NSOpenGLPFADoubleBuffer; - attributes[i++] = NSOpenGLPFAColorSize; - attributes[i++] = NSOpenGLPixelFormatAttribute(32); - attributes[i++] = NSOpenGLPFADepthSize; - attributes[i++] = NSOpenGLPixelFormatAttribute(24); - attributes[i++] = NSOpenGLPFAStencilSize; - attributes[i++] = NSOpenGLPixelFormatAttribute(8); - attributes[i++] = NSOpenGLPFAOpenGLProfile; - attributes[i++] = profile; - - if (!vid_autoswitch) - { - attributes[i++] = NSOpenGLPFAAllowOfflineRenderers; - } - - attributes[i] = NSOpenGLPixelFormatAttribute(0); - - return [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; -} - -} // unnamed namespace - - -// --------------------------------------------------------------------------- - - -CocoaVideo::CocoaVideo() -: m_window(CreateCocoaWindow(STYLE_MASK_WINDOWED)) -, m_width(-1) -, m_height(-1) -, m_fullscreen(false) -, m_hiDPI(false) -{ - memset(&m_modeIterator, 0, sizeof m_modeIterator); - - extern void gl_CalculateCPUSpeed(); - gl_CalculateCPUSpeed(); - - // Create OpenGL pixel format - NSOpenGLPixelFormatAttribute defaultProfile = NSOpenGLProfileVersion3_2Core; - - if (1 == vid_renderer && NSAppKitVersionNumber < AppKit10_9) - { - // There is no support for OpenGL 3.3 before Mavericks - defaultProfile = NSOpenGLProfileVersionLegacy; - } - else if (0 == vid_renderer && 0 == vid_glswfb) - { - // Software renderer uses OpenGL 2.1 for blitting - defaultProfile = NSOpenGLProfileVersionLegacy; - } - else if (const char* const glversion = Args->CheckValue("-glversion")) - { - // Check for explicit version specified in command line - const double version = strtod(glversion, nullptr) + 0.01; - if (version < 3.3) - { - defaultProfile = NSOpenGLProfileVersionLegacy; - } - } - - NSOpenGLPixelFormat* pixelFormat = CreatePixelFormat(defaultProfile); - - if (nil == pixelFormat && NSOpenGLProfileVersion3_2Core == defaultProfile) - { - pixelFormat = CreatePixelFormat(NSOpenGLProfileVersionLegacy); - } - - if (nil == pixelFormat) - { - I_FatalError("Cannot create OpenGL pixel format, graphics hardware is not supported"); - } - - // Create OpenGL context and view - - const NSRect contentRect = [m_window contentRectForFrameRect:[m_window frame]]; - NSOpenGLView* glView = [[CocoaView alloc] initWithFrame:contentRect - pixelFormat:pixelFormat]; - [[glView openGLContext] makeCurrentContext]; - - [m_window setContentView:glView]; - - FConsoleWindow::GetInstance().Show(false); -} - -void CocoaVideo::StartModeIterator(const int bits, const bool fullscreen) -{ - m_modeIterator.index = 0; - m_modeIterator.bits = bits; - m_modeIterator.fullscreen = fullscreen; -} - -bool CocoaVideo::NextMode(int* const width, int* const height, bool* const letterbox) -{ - assert(NULL != width); - assert(NULL != height); - - const int bits = m_modeIterator.bits; - - if (8 != bits && 16 != bits && 24 != bits && 32 != bits) - { - return false; - } - - size_t& index = m_modeIterator.index; - - if (index < sizeof(VideoModes) / sizeof(VideoModes[0])) - { - *width = VideoModes[index].width; - *height = VideoModes[index].height; - - if (m_modeIterator.fullscreen && NULL != letterbox) - { - const NSSize screenSize = [[m_window screen] frame].size; - const float screenRatio = screenSize.width / screenSize.height; - const float modeRatio = float(*width) / *height; - - *letterbox = fabs(screenRatio - modeRatio) > 0.001f; - } - - ++index; - - return true; - } - - return false; -} - -DFrameBuffer* CocoaVideo::CreateFrameBuffer(const int width, const int height, const bool bgra, const bool fullscreen, DFrameBuffer* const old) -{ - PalEntry flashColor = 0; - int flashAmount = 0; - - if (NULL != old) - { - if (width == m_width && height == m_height && bgra == old->IsBgra()) - { - SetMode(width, height, fullscreen, vid_hidpi); - return old; - } - - old->GetFlash(flashColor, flashAmount); - - if (old == screen) - { - screen = NULL; - } - - delete old; - } - - DFrameBuffer* fb = NULL; - - if (1 == currentrenderer) - { - fb = new OpenGLFrameBuffer(NULL, width, height, 32, 60, fullscreen); - } - else if (vid_glswfb) - { - fb = CreateGLSWFrameBuffer(width, height, bgra, fullscreen); - - if (!fb->IsValid()) - { - delete fb; - - fb = new CocoaFrameBuffer(width, height, bgra, fullscreen); - } - } - else - { - fb = new CocoaFrameBuffer(width, height, bgra, fullscreen); - } - - fb->SetFlash(flashColor, flashAmount); - - SetMode(width, height, fullscreen, vid_hidpi); - - return fb; -} - -void CocoaVideo::SetWindowedScale(float scale) -{ -} - - -bool CocoaVideo::IsFullscreen() -{ - CocoaVideo* const video = GetInstance(); - return NULL == video - ? false - : video->m_fullscreen; -} - -void CocoaVideo::UseHiDPI(const bool hiDPI) -{ - if (CocoaVideo* const video = GetInstance()) - { - video->SetMode(video->m_width, video->m_height, video->m_fullscreen, hiDPI); - } -} - -void CocoaVideo::SetCursor(NSCursor* cursor) -{ - if (CocoaVideo* const video = GetInstance()) - { - NSWindow* const window = video->m_window; - CocoaView* const view = [window contentView]; - - [view setCursor:cursor]; - [window invalidateCursorRectsForView:view]; - } -} - -void CocoaVideo::SetWindowVisible(bool visible) -{ - if (CocoaVideo* const video = GetInstance()) - { - if (visible) - { - [video->m_window orderFront:nil]; - } - else - { - [video->m_window orderOut:nil]; - } - - I_SetNativeMouse(!visible); - } -} - -void CocoaVideo::SetWindowTitle(const char* title) -{ - if (CocoaVideo* const video = GetInstance()) - { - NSString* const nsTitle = nullptr == title ? nil : - [NSString stringWithCString:title encoding:NSISOLatin1StringEncoding]; - [video->m_window setTitle:nsTitle]; - } -} - - -void CocoaVideo::SetFullscreenMode(const int width, const int height) -{ - NSScreen* screen = [m_window screen]; - - const NSRect screenFrame = [screen frame]; - const NSRect displayRect = vid_hidpi - ? [screen convertRectToBacking:screenFrame] - : screenFrame; - - const float displayWidth = displayRect.size.width; - const float displayHeight = displayRect.size.height; - - const float pixelScaleFactorX = displayWidth / static_cast(width ); - const float pixelScaleFactorY = displayHeight / static_cast(height); - - rbOpts.pixelScale = MIN(pixelScaleFactorX, pixelScaleFactorY); - - rbOpts.width = width * rbOpts.pixelScale; - rbOpts.height = height * rbOpts.pixelScale; - - rbOpts.shiftX = (displayWidth - rbOpts.width ) / 2.0f; - rbOpts.shiftY = (displayHeight - rbOpts.height) / 2.0f; - - if (!m_fullscreen) - { - [m_window setLevel:LEVEL_FULLSCREEN]; - [m_window setStyleMask:STYLE_MASK_FULLSCREEN]; - - [m_window setHidesOnDeactivate:YES]; - } - - [m_window setFrame:screenFrame display:YES]; -} - -void CocoaVideo::SetWindowedMode(const int width, const int height) -{ - rbOpts.pixelScale = 1.0f; - - rbOpts.width = static_cast(width ); - rbOpts.height = static_cast(height); - - rbOpts.shiftX = 0.0f; - rbOpts.shiftY = 0.0f; - - const NSSize windowPixelSize = NSMakeSize(width, height); - const NSSize windowSize = vid_hidpi - ? [[m_window contentView] convertSizeFromBacking:windowPixelSize] - : windowPixelSize; - - if (m_fullscreen) - { - [m_window setLevel:LEVEL_WINDOWED]; - [m_window setStyleMask:STYLE_MASK_WINDOWED]; - - [m_window setHidesOnDeactivate:NO]; - } - - [m_window setContentSize:windowSize]; - [m_window center]; - [m_window enterFullscreenOnZoom]; - [m_window exitAppOnClose]; -} - -void CocoaVideo::SetMode(const int width, const int height, const bool fullscreen, const bool hiDPI) -{ - if (fullscreen == m_fullscreen - && width == m_width - && height == m_height - && hiDPI == m_hiDPI) - { - return; - } - - NSOpenGLView* const glView = [m_window contentView]; - [glView setWantsBestResolutionOpenGLSurface:hiDPI]; - - if (fullscreen) - { - SetFullscreenMode(width, height); - } - else - { - SetWindowedMode(width, height); - } - - rbOpts.dirty = true; - - const NSSize viewSize = I_GetContentViewSize(m_window); - - glViewport(0, 0, static_cast(viewSize.width), static_cast(viewSize.height)); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - - [[NSOpenGLContext currentContext] flushBuffer]; - - [m_window updateTitle]; - - if (![m_window isKeyWindow]) - { - [m_window makeKeyAndOrderFront:nil]; - } - - m_fullscreen = fullscreen; - m_width = width; - m_height = height; - m_hiDPI = hiDPI; -} - - -CocoaVideo* CocoaVideo::GetInstance() -{ - return static_cast(Video); -} - - -// --------------------------------------------------------------------------- - - -CocoaFrameBuffer::CocoaFrameBuffer(int width, int height, bool bgra, bool fullscreen) -: DFrameBuffer(width, height, bgra) -, m_needPaletteUpdate(false) -, m_gamma(0.0f) -, m_needGammaUpdate(false) -, m_flashAmount(0) -, UpdatePending(false) -, m_pixelBuffer(new uint8_t[width * height * BYTES_PER_PIXEL]) -, m_texture(0) -{ - static bool isOpenGLInitialized; - - if (!isOpenGLInitialized) - { - if (ogl_LoadFunctions() == ogl_LOAD_FAILED) - { - I_FatalError("Failed to load OpenGL functions."); - } - isOpenGLInitialized = true; - } - - glEnable(GL_TEXTURE_RECTANGLE_ARB); - - glGenTextures(1, &m_texture); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_texture); - - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0, width, height, 0.0, -1.0, 1.0); - - GPfx.SetFormat(32, 0x000000FF, 0x0000FF00, 0x00FF0000); - - for (size_t i = 0; i < 256; ++i) - { - m_gammaTable[0][i] = m_gammaTable[1][i] = m_gammaTable[2][i] = i; - } - - memcpy(m_palette, GPalette.BaseColors, sizeof(PalEntry) * 256); - UpdateColors(); - - SetVSync(vid_vsync); -} - - -CocoaFrameBuffer::~CocoaFrameBuffer() -{ - glBindTexture(GL_TEXTURE_2D, 0); - glDeleteTextures(1, &m_texture); - - delete[] m_pixelBuffer; -} - -int CocoaFrameBuffer::GetPageCount() -{ - return 1; -} - -bool CocoaFrameBuffer::Lock(bool buffered) -{ - return DSimpleCanvas::Lock(buffered); -} - -void CocoaFrameBuffer::Unlock() -{ - if (UpdatePending && LockCount == 1) - { - Update(); - } - else if (--LockCount <= 0) - { - Buffer = NULL; - LockCount = 0; - } -} - -void CocoaFrameBuffer::Update() -{ - if (LockCount != 1) - { - if (LockCount > 0) - { - UpdatePending = true; - --LockCount; - } - return; - } - - DrawRateStuff(); - - Buffer = NULL; - LockCount = 0; - UpdatePending = false; - - BlitCycles.Reset(); - FlipCycles.Reset(); - BlitCycles.Clock(); - - if (IsBgra()) - { - CopyWithGammaBgra(m_pixelBuffer, Width * BYTES_PER_PIXEL, m_gammaTable[0], m_gammaTable[1], m_gammaTable[2], m_flashColor, m_flashAmount); - } - else - { - GPfx.Convert(MemBuffer, Pitch, m_pixelBuffer, Width * BYTES_PER_PIXEL, - Width, Height, FRACUNIT, FRACUNIT, 0, 0); - } - - FlipCycles.Clock(); - Flip(); - FlipCycles.Unclock(); - - BlitCycles.Unclock(); - - if (m_needGammaUpdate) - { - CalcGamma(rgamma == 0.0f ? m_gamma : m_gamma * rgamma, m_gammaTable[0]); - CalcGamma(ggamma == 0.0f ? m_gamma : m_gamma * ggamma, m_gammaTable[1]); - CalcGamma(bgamma == 0.0f ? m_gamma : m_gamma * bgamma, m_gammaTable[2]); - - m_needGammaUpdate = false; - m_needPaletteUpdate = true; - } - - if (m_needPaletteUpdate) - { - m_needPaletteUpdate = false; - UpdateColors(); - } -} - -void CocoaFrameBuffer::UpdateColors() -{ - PalEntry palette[256]; - - for (size_t i = 0; i < 256; ++i) - { - palette[i].r = m_gammaTable[0][m_palette[i].r]; - palette[i].g = m_gammaTable[1][m_palette[i].g]; - palette[i].b = m_gammaTable[2][m_palette[i].b]; - } - - if (0 != m_flashAmount) - { - DoBlending(palette, palette, 256, - m_gammaTable[0][m_flashColor.r], - m_gammaTable[1][m_flashColor.g], - m_gammaTable[2][m_flashColor.b], - m_flashAmount); - } - - GPfx.SetPalette(palette); -} - -PalEntry* CocoaFrameBuffer::GetPalette() -{ - return m_palette; -} - -void CocoaFrameBuffer::UpdatePalette() -{ - m_needPaletteUpdate = true; -} - -bool CocoaFrameBuffer::SetGamma(float gamma) -{ - m_gamma = gamma; - m_needGammaUpdate = true; - - return true; -} - -bool CocoaFrameBuffer::SetFlash(PalEntry rgb, int amount) -{ - m_flashColor = rgb; - m_flashAmount = amount; - m_needPaletteUpdate = true; - - return true; -} - -void CocoaFrameBuffer::GetFlash(PalEntry &rgb, int &amount) -{ - rgb = m_flashColor; - amount = m_flashAmount; -} - -void CocoaFrameBuffer::GetFlashedPalette(PalEntry pal[256]) -{ - memcpy(pal, m_palette, sizeof m_palette); - - if (0 != m_flashAmount) - { - DoBlending(pal, pal, 256, - m_flashColor.r, m_flashColor.g, m_flashColor.b, - m_flashAmount); - } -} - -bool CocoaFrameBuffer::IsFullscreen() -{ - return CocoaVideo::IsFullscreen(); -} - -void CocoaFrameBuffer::SetVSync(bool vsync) -{ - const GLint value = vsync ? 1 : 0; - - [[NSOpenGLContext currentContext] setValues:&value - forParameter:NSOpenGLCPSwapInterval]; -} - -void CocoaFrameBuffer::Flip() -{ - assert(NULL != screen); - - if (rbOpts.dirty) - { - glViewport(rbOpts.shiftX, rbOpts.shiftY, rbOpts.width, rbOpts.height); - - // TODO: Figure out why the following glClear() call is needed - // to avoid drawing of garbage in fullscreen mode when - // in-game's aspect ratio is different from display one - glClear(GL_COLOR_BUFFER_BIT); - - rbOpts.dirty = false; - } - - const GLenum format = IsBgra() ? GL_BGRA : GL_RGBA; - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, Width, Height, 0, format, GL_UNSIGNED_BYTE, m_pixelBuffer); - - glBegin(GL_QUADS); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - glTexCoord2f(0.0f, 0.0f); - glVertex2f(0.0f, 0.0f); - glTexCoord2f(Width, 0.0f); - glVertex2f(Width, 0.0f); - glTexCoord2f(Width, Height); - glVertex2f(Width, Height); - glTexCoord2f(0.0f, Height); - glVertex2f(0.0f, Height); - glEnd(); - - glFlush(); - - [[NSOpenGLContext currentContext] flushBuffer]; -} - - -// --------------------------------------------------------------------------- - - -SDLGLFB::SDLGLFB(void*, const int width, const int height, int, int, const bool fullscreen, bool bgra) -: DFrameBuffer(width, height, bgra) -, m_Lock(0) -, UpdatePending(false) -{ - CGGammaValue gammaTable[GAMMA_TABLE_SIZE]; - uint32_t actualChannelSize; - - const CGError result = CGGetDisplayTransferByTable(kCGDirectMainDisplay, GAMMA_CHANNEL_SIZE, - gammaTable, &gammaTable[GAMMA_CHANNEL_SIZE], &gammaTable[GAMMA_CHANNEL_SIZE * 2], &actualChannelSize); - m_supportsGamma = kCGErrorSuccess == result && GAMMA_CHANNEL_SIZE == actualChannelSize; - - if (m_supportsGamma) - { - for (uint32_t i = 0; i < GAMMA_TABLE_SIZE; ++i) - { - m_originalGamma[i] = static_cast(gammaTable[i] * 65535.0f); - } - } -} - -SDLGLFB::SDLGLFB() -{ -} - -SDLGLFB::~SDLGLFB() -{ -} - - -bool SDLGLFB::Lock(bool buffered) -{ - m_Lock++; - - Buffer = MemBuffer; - - return true; -} - -void SDLGLFB::Unlock() -{ - if (UpdatePending && 1 == m_Lock) - { - Update(); - } - else if (--m_Lock <= 0) - { - m_Lock = 0; - } -} - -bool SDLGLFB::IsLocked() -{ - return m_Lock > 0; -} - - -bool SDLGLFB::IsFullscreen() -{ - return CocoaVideo::IsFullscreen(); -} - -void SDLGLFB::SetVSync(bool vsync) -{ - const GLint value = vsync ? 1 : 0; - - [[NSOpenGLContext currentContext] setValues:&value - forParameter:NSOpenGLCPSwapInterval]; -} - - -void SDLGLFB::InitializeState() -{ -} - -void SDLGLFB::SwapBuffers() -{ - [[NSOpenGLContext currentContext] flushBuffer]; -} - -void SDLGLFB::SetGammaTable(uint16_t* table) -{ - if (m_supportsGamma) - { - CGGammaValue gammaTable[GAMMA_TABLE_SIZE]; - - for (uint32_t i = 0; i < GAMMA_TABLE_SIZE; ++i) - { - gammaTable[i] = static_cast(table[i] / 65535.0f); - } - - CGSetDisplayTransferByTable(kCGDirectMainDisplay, GAMMA_CHANNEL_SIZE, - gammaTable, &gammaTable[GAMMA_CHANNEL_SIZE], &gammaTable[GAMMA_CHANNEL_SIZE * 2]); - } -} - -void SDLGLFB::ResetGammaTable() -{ - if (m_supportsGamma) - { - SetGammaTable(m_originalGamma); - } -} - -int SDLGLFB::GetClientWidth() -{ - NSView *view = [[NSOpenGLContext currentContext] view]; - NSRect backingBounds = [view convertRectToBacking: [view bounds]]; - int clientWidth = (int)backingBounds.size.width; - return clientWidth > 0 ? clientWidth : Width; -} - -int SDLGLFB::GetClientHeight() -{ - NSView *view = [[NSOpenGLContext currentContext] view]; - NSRect backingBounds = [view convertRectToBacking: [view bounds]]; - int clientHeight = (int)backingBounds.size.height; - return clientHeight > 0 ? clientHeight : Height; -} - - -// --------------------------------------------------------------------------- - - -ADD_STAT(blit) -{ - FString result; - result.Format("blit=%04.1f ms flip=%04.1f ms", BlitCycles.TimeMS(), FlipCycles.TimeMS()); - return result; -} - - -IVideo* Video; - - -// --------------------------------------------------------------------------- - - -void I_ShutdownGraphics() -{ - if (NULL != screen) - { - delete screen; - screen = NULL; - } - - delete Video; - Video = NULL; -} - -void I_InitGraphics() -{ - UCVarValue val; - - val.Bool = !!Args->CheckParm("-devparm"); - ticker.SetGenericRepDefault(val, CVAR_Bool); - - Video = new CocoaVideo; - atterm(I_ShutdownGraphics); -} - - -static void I_DeleteRenderer() -{ - delete Renderer; - Renderer = NULL; -} - -void I_CreateRenderer() -{ - currentrenderer = vid_renderer; - - if (NULL == Renderer) - { - extern FRenderer* gl_CreateInterface(); - - Renderer = 1 == currentrenderer - ? gl_CreateInterface() - : new FSoftwareRenderer; - atterm(I_DeleteRenderer); - } -} - - -DFrameBuffer* I_SetMode(int &width, int &height, DFrameBuffer* old) -{ - return Video->CreateFrameBuffer(width, height, swtruecolor, fullscreen, old); -} - -bool I_CheckResolution(const int width, const int height, const int bits) -{ - int twidth, theight; - - Video->StartModeIterator(bits, 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) -{ - int twidth, theight; - int cwidth = 0, cheight = 0; - int iteration; - uint32_t closest = uint32_t(-1); - - for (iteration = 0; iteration < 2; ++iteration) - { - Video->StartModeIterator(bits, fullscreen); - - while (Video->NextMode(&twidth, &theight, NULL)) - { - if (twidth == *width && theight == *height) - { - return; - } - - if (iteration == 0 && (twidth < *width || theight < *height)) - { - continue; - } - - const uint32_t dist = (twidth - *width) * (twidth - *width) - + (theight - *height) * (theight - *height); - - if (dist < closest) - { - closest = dist; - cwidth = twidth; - cheight = theight; - } - } - - if (closest != uint32_t(-1)) - { - *width = cwidth; - *height = cheight; - return; - } - } -} - - -// --------------------------------------------------------------------------- - - -EXTERN_CVAR(Int, vid_maxfps); -EXTERN_CVAR(Bool, cl_capfps); - -// So Apple doesn't support POSIX timers and I can't find a good substitute short of -// having Objective-C Cocoa events or something like that. -void I_SetFPSLimit(int limit) -{ -} - -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); - } -} - -CUSTOM_CVAR(Bool, vid_hidpi, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - CocoaVideo::UseHiDPI(self); -} - - -// --------------------------------------------------------------------------- - - -CCMD(vid_listmodes) -{ - if (Video == NULL) - { - return; - } - - static const char* const ratios[7] = { "", " - 16:9", " - 16:10", " - 17:10", " - 5:4", "", " - 21:9" }; - int width, height; - bool letterbox; - - Video->StartModeIterator(32, screen->IsFullscreen()); - - while (Video->NextMode(&width, &height, &letterbox)) - { - const bool current = width == DisplayWidth && height == DisplayHeight; - const int ratio = CheckRatio(width, height); - - Printf(current ? PRINT_BOLD : PRINT_HIGH, "%s%4d x%5d x%3d%s%s\n", - current || !(ratio & 3) ? "" : TEXTCOLOR_GOLD, - width, height, 32, ratios[ratio], - current || !letterbox ? "" : TEXTCOLOR_BROWN " LB"); - } -} - -CCMD(vid_currentmode) -{ - Printf("%dx%dx%d\n", DisplayWidth, DisplayHeight, DisplayBits); -} - - -// --------------------------------------------------------------------------- - - -bool I_SetCursor(FTexture* cursorpic) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSCursor* cursor = nil; - - if (NULL != cursorpic && ETextureType::Null != cursorpic->UseType) - { - // Create bitmap image representation - - const NSInteger imageWidth = cursorpic->GetWidth(); - const NSInteger imageHeight = cursorpic->GetHeight(); - const NSInteger imagePitch = imageWidth * 4; - - NSBitmapImageRep* bitmapImageRep = [NSBitmapImageRep alloc]; - [bitmapImageRep initWithBitmapDataPlanes:NULL - pixelsWide:imageWidth - pixelsHigh:imageHeight - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:imagePitch - bitsPerPixel:0]; - - // Load bitmap data to representation - - uint8_t* buffer = [bitmapImageRep bitmapData]; - memset(buffer, 0, imagePitch * imageHeight); - - FBitmap bitmap(buffer, imagePitch, imageWidth, imageHeight); - cursorpic->CopyTrueColorPixels(&bitmap, 0, 0); - - // Swap red and blue components in each pixel - - for (size_t i = 0; i < size_t(imageWidth * imageHeight); ++i) - { - const size_t offset = i * 4; - - const uint8_t temp = buffer[offset ]; - buffer[offset ] = buffer[offset + 2]; - buffer[offset + 2] = temp; - } - - // Create image from representation and set it as cursor - - NSData* imageData = [bitmapImageRep representationUsingType:NSPNGFileType - properties:[NSDictionary dictionary]]; - NSImage* cursorImage = [[NSImage alloc] initWithData:imageData]; - - cursor = [[NSCursor alloc] initWithImage:cursorImage - hotSpot:NSMakePoint(0.0f, 0.0f)]; - } - - CocoaVideo::SetCursor(cursor); - - [pool release]; - - return true; -} - - -NSSize I_GetContentViewSize(const NSWindow* const window) -{ - const NSView* const view = [window contentView]; - const NSSize frameSize = [view frame].size; - - return (vid_hidpi) - ? [view convertSizeToBacking:frameSize] - : frameSize; -} - -void I_SetMainWindowVisible(bool visible) -{ - CocoaVideo::SetWindowVisible(visible); -} - -// each platform has its own specific version of this function. -void I_SetWindowTitle(const char* title) -{ - CocoaVideo::SetWindowTitle(title); -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/sdlglvideo.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/sdlglvideo.h deleted file mode 100644 index 7e98d95..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/sdlglvideo.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - ** sdlglvideo.h - ** - **--------------------------------------------------------------------------- - ** Copyright 2012-2014 Alexey Lysiuk - ** 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. - **--------------------------------------------------------------------------- - ** - */ - - -// IMPORTANT NOTE! -// This file was intentially named sdlglvideo.h but it has nothing with SDL -// The name was selected to avoid spreding of changes over the project -// The same applies to SDLGLFB class -// See gl/system/gl_framebuffer.h for details about its usage - - -#ifndef COCOA_SDLGLVIDEO_H_INCLUDED -#define COCOA_SDLGLVIDEO_H_INCLUDED - -#include "v_video.h" - -#include "gl/shaders/gl_shader.h" -#include "gl/textures/gl_hwtexture.h" - - -class SDLGLFB : public DFrameBuffer -{ -public: - // This must have the same parameters as the Windows version, even if they are not used! - SDLGLFB(void *hMonitor, int width, int height, int, int, bool fullscreen, bool bgra); - ~SDLGLFB(); - - virtual bool Lock(bool buffered = true); - virtual void Unlock(); - virtual bool IsLocked(); - - virtual bool IsFullscreen(); - virtual void SetVSync(bool vsync); - - int GetClientWidth(); - int GetClientHeight(); - - virtual int GetTrueHeight() { return GetClientHeight(); } -protected: - int m_Lock; - bool UpdatePending; - - static const uint32_t GAMMA_CHANNEL_SIZE = 256; - static const uint32_t GAMMA_CHANNEL_COUNT = 3; - static const uint32_t GAMMA_TABLE_SIZE = GAMMA_CHANNEL_SIZE * GAMMA_CHANNEL_COUNT; - - bool m_supportsGamma; - uint16_t m_originalGamma[GAMMA_TABLE_SIZE]; - - SDLGLFB(); - - void InitializeState(); - - void SwapBuffers(); - - void SetGammaTable(uint16_t* table); - void ResetGammaTable(); -}; - -#endif // COCOA_SDLGLVIDEO_H_INCLUDED diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_console.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_console.h deleted file mode 100644 index b2af7ba..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_console.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - ** st_console.h - ** - **--------------------------------------------------------------------------- - ** Copyright 2015 Alexey Lysiuk - ** 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. - **--------------------------------------------------------------------------- - ** - */ - -#ifndef COCOA_ST_CONSOLE_INCLUDED -#define COCOA_ST_CONSOLE_INCLUDED - -@class NSButton; -@class NSProgressIndicator; -@class NSScrollView; -@class NSTextField; -@class NSTextView; -@class NSView; -@class NSWindow; - -struct PalEntry; - - -class FConsoleWindow -{ -public: - static FConsoleWindow& GetInstance(); - - static void CreateInstance(); - static void DeleteInstance(); - - void Show(bool visible); - void ShowFatalError(const char* message); - - void AddText(const char* message); - - void SetTitleText(); - void SetProgressBar(bool visible); - - // FStartupScreen functionality - void Progress(int current, int maximum); - void NetInit(const char* message, int playerCount); - void NetProgress(int count); - void NetDone(); - -private: - NSWindow* m_window; - NSTextView* m_textView; - NSScrollView* m_scrollView; - NSProgressIndicator* m_progressBar; - - NSView* m_netView; - NSTextField* m_netMessageText; - NSTextField* m_netCountText; - NSProgressIndicator* m_netProgressBar; - NSButton* m_netAbortButton; - - unsigned int m_characterCount; - - int m_netCurPos; - int m_netMaxPos; - - FConsoleWindow(); - - void ExpandTextView(float height); - - void AddText(const PalEntry& color, const char* message); - - void ScrollTextToBottom(); -}; - -#endif // COCOA_ST_CONSOLE_INCLUDED diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_console.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_console.mm deleted file mode 100644 index dd876c3..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_console.mm +++ /dev/null @@ -1,533 +0,0 @@ -/* - ** st_console.mm - ** - **--------------------------------------------------------------------------- - ** Copyright 2015 Alexey Lysiuk - ** 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 "i_common.h" - -#include "d_main.h" -#include "i_system.h" -#include "st_console.h" -#include "v_text.h" -#include "version.h" -#include "i_time.h" - - -static NSColor* RGB(const uint8_t red, const uint8_t green, const uint8_t blue) -{ - return [NSColor colorWithCalibratedRed:red / 255.0f - green:green / 255.0f - blue:blue / 255.0f - alpha:1.0f]; -} - -static NSColor* RGB(const PalEntry& color) -{ - return RGB(color.r, color.g, color.b); -} - -static NSColor* RGB(const uint32_t color) -{ - return RGB(PalEntry(color)); -} - - -static const CGFloat PROGRESS_BAR_HEIGHT = 18.0f; -static const CGFloat NET_VIEW_HEIGHT = 88.0f; - - -FConsoleWindow::FConsoleWindow() -: m_window([NSWindow alloc]) -, m_textView([NSTextView alloc]) -, m_scrollView([NSScrollView alloc]) -, m_progressBar(nil) -, m_netView(nil) -, m_netMessageText(nil) -, m_netCountText(nil) -, m_netProgressBar(nil) -, m_netAbortButton(nil) -, m_characterCount(0) -, m_netCurPos(0) -, m_netMaxPos(0) -{ - const CGFloat initialWidth = 512.0f; - const CGFloat initialHeight = 384.0f; - const NSRect initialRect = NSMakeRect(0.0f, 0.0f, initialWidth, initialHeight); - - [m_textView initWithFrame:initialRect]; - [m_textView setEditable:NO]; - [m_textView setBackgroundColor:RGB(70, 70, 70)]; - [m_textView setMinSize:NSMakeSize(0.0f, initialHeight)]; - [m_textView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; - [m_textView setVerticallyResizable:YES]; - [m_textView setHorizontallyResizable:NO]; - [m_textView setAutoresizingMask:NSViewWidthSizable]; - - NSTextContainer* const textContainer = [m_textView textContainer]; - [textContainer setContainerSize:NSMakeSize(initialWidth, FLT_MAX)]; - [textContainer setWidthTracksTextView:YES]; - - [m_scrollView initWithFrame:initialRect]; - [m_scrollView setBorderType:NSNoBorder]; - [m_scrollView setHasVerticalScroller:YES]; - [m_scrollView setHasHorizontalScroller:NO]; - [m_scrollView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - [m_scrollView setDocumentView:m_textView]; - - NSString* const title = [NSString stringWithFormat:@"%s %s - Console", GAMESIG, GetVersionString()]; - - [m_window initWithContentRect:initialRect - styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask - backing:NSBackingStoreBuffered - defer:NO]; - [m_window setMinSize:[m_window frame].size]; - [m_window setShowsResizeIndicator:NO]; - [m_window setTitle:title]; - [m_window center]; - [m_window exitAppOnClose]; - - // Do not allow fullscreen mode for this window - [m_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; - - [[m_window contentView] addSubview:m_scrollView]; - - [m_window makeKeyAndOrderFront:nil]; -} - - -static FConsoleWindow* s_instance; - - -void FConsoleWindow::CreateInstance() -{ - assert(NULL == s_instance); - s_instance = new FConsoleWindow; -} - -void FConsoleWindow::DeleteInstance() -{ - assert(NULL != s_instance); - delete s_instance; - s_instance = NULL; -} - -FConsoleWindow& FConsoleWindow::GetInstance() -{ - assert(NULL != s_instance); - return *s_instance; -} - - -void FConsoleWindow::Show(const bool visible) -{ - if (visible) - { - [m_window orderFront:nil]; - } - else - { - [m_window orderOut:nil]; - } -} - -void FConsoleWindow::ShowFatalError(const char* const message) -{ - SetProgressBar(false); - NetDone(); - - const CGFloat textViewWidth = [m_scrollView frame].size.width; - - ExpandTextView(-32.0f); - - NSButton* quitButton = [[NSButton alloc] initWithFrame:NSMakeRect(textViewWidth - 76.0f, 0.0f, 72.0f, 30.0f)]; - [quitButton setAutoresizingMask:NSViewMinXMargin]; - [quitButton setBezelStyle:NSRoundedBezelStyle]; - [quitButton setTitle:@"Quit"]; - [quitButton setKeyEquivalent:@"\r"]; - [quitButton setTarget:NSApp]; - [quitButton setAction:@selector(terminate:)]; - - NSView* quitPanel = [[NSView alloc] initWithFrame:NSMakeRect(0.0f, 0.0f, textViewWidth, 32.0f)]; - [quitPanel setAutoresizingMask:NSViewWidthSizable]; - [quitPanel addSubview:quitButton]; - - [[m_window contentView] addSubview:quitPanel]; - [m_window orderFront:nil]; - - AddText(PalEntry(255, 0, 0), "\nExecution could not continue.\n"); - AddText(PalEntry(255, 255, 170), message); - AddText("\n"); - - ScrollTextToBottom(); - - [NSApp runModalForWindow:m_window]; -} - - -static const unsigned int THIRTY_FPS = 33; // milliseconds per update - - -template -struct TimedUpdater -{ - explicit TimedUpdater(const Function& function) - { - const unsigned int currentTime = I_msTime(); - - if (currentTime - m_previousTime > interval) - { - m_previousTime = currentTime; - - function(); - - [[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode]; - } - } - - static unsigned int m_previousTime; -}; - -template -unsigned int TimedUpdater::m_previousTime; - -template -static void UpdateTimed(const Function& function) -{ - TimedUpdater dummy(function); -} - - -void FConsoleWindow::AddText(const char* message) -{ - PalEntry color(223, 223, 223); - - char buffer[1024] = {}; - size_t pos = 0; - bool reset = false; - - while (*message != '\0') - { - if ((TEXTCOLOR_ESCAPE == *message && 0 != pos) - || (pos == sizeof buffer - 1) - || reset) - { - buffer[pos] = '\0'; - pos = 0; - reset = false; - - AddText(color, buffer); - } - - if (TEXTCOLOR_ESCAPE == *message) - { - const uint8_t* colorID = reinterpret_cast(message) + 1; - if ('\0' == *colorID) - { - break; - } - - const EColorRange range = V_ParseFontColor(colorID, CR_UNTRANSLATED, CR_YELLOW); - - if (range != CR_UNDEFINED) - { - color = V_LogColorFromColorRange(range); - } - - message += 2; - } - else if (0x1d == *message || 0x1f == *message) // Opening and closing bar characters - { - buffer[pos++] = '-'; - ++message; - } - else if (0x1e == *message) // Middle bar character - { - buffer[pos++] = '='; - ++message; - } - else - { - buffer[pos++] = *message++; - } - } - - if (0 != pos) - { - buffer[pos] = '\0'; - - AddText(color, buffer); - } - - if ([m_window isVisible]) - { - UpdateTimed([&]() - { - [m_textView scrollRangeToVisible:NSMakeRange(m_characterCount, 0)]; - }); - } -} - -void FConsoleWindow::AddText(const PalEntry& color, const char* const message) -{ - NSString* const text = [NSString stringWithCString:message - encoding:NSISOLatin1StringEncoding]; - - NSDictionary* const attributes = [NSDictionary dictionaryWithObjectsAndKeys: - [NSFont systemFontOfSize:14.0f], NSFontAttributeName, - RGB(color), NSForegroundColorAttributeName, - nil]; - - NSAttributedString* const formattedText = - [[NSAttributedString alloc] initWithString:text - attributes:attributes]; - [[m_textView textStorage] appendAttributedString:formattedText]; - - m_characterCount += [text length]; -} - - -void FConsoleWindow::ScrollTextToBottom() -{ - [m_textView scrollRangeToVisible:NSMakeRange(m_characterCount, 0)]; - - [[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode]; -} - - -void FConsoleWindow::SetTitleText() -{ - static const CGFloat TITLE_TEXT_HEIGHT = 32.0f; - - NSRect textViewFrame = [m_scrollView frame]; - textViewFrame.size.height -= TITLE_TEXT_HEIGHT; - [m_scrollView setFrame:textViewFrame]; - - const NSRect titleTextRect = NSMakeRect( - 0.0f, - textViewFrame.origin.y + textViewFrame.size.height, - textViewFrame.size.width, - TITLE_TEXT_HEIGHT); - - // Temporary solution for the same foreground and background colors - // It's used in graphical startup screen, with Hexen style in particular - // Native OS X backend doesn't implement this yet - - if (DoomStartupInfo.FgColor == DoomStartupInfo.BkColor) - { - DoomStartupInfo.FgColor = ~DoomStartupInfo.FgColor; - } - - NSTextField* titleText = [[NSTextField alloc] initWithFrame:titleTextRect]; - [titleText setStringValue:[NSString stringWithCString:DoomStartupInfo.Name - encoding:NSISOLatin1StringEncoding]]; - [titleText setAlignment:NSCenterTextAlignment]; - [titleText setTextColor:RGB(DoomStartupInfo.FgColor)]; - [titleText setBackgroundColor:RGB(DoomStartupInfo.BkColor)]; - [titleText setFont:[NSFont fontWithName:@"Trebuchet MS Bold" size:18.0f]]; - [titleText setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin]; - [titleText setSelectable:NO]; - [titleText setBordered:NO]; - - [[m_window contentView] addSubview:titleText]; -} - -void FConsoleWindow::SetProgressBar(const bool visible) -{ - if ( (!visible && nil == m_progressBar) - || (visible && nil != m_progressBar)) - { - return; - } - - if (visible) - { - ExpandTextView(-PROGRESS_BAR_HEIGHT); - - static const CGFloat PROGRESS_BAR_X = 2.0f; - const NSRect PROGRESS_BAR_RECT = NSMakeRect( - PROGRESS_BAR_X, 0.0f, - [m_window frame].size.width - PROGRESS_BAR_X * 2, 16.0f); - - m_progressBar = [[NSProgressIndicator alloc] initWithFrame:PROGRESS_BAR_RECT]; - [m_progressBar setIndeterminate:NO]; - [m_progressBar setAutoresizingMask:NSViewWidthSizable]; - - [[m_window contentView] addSubview:m_progressBar]; - } - else - { - ExpandTextView(PROGRESS_BAR_HEIGHT); - - [m_progressBar removeFromSuperview]; - [m_progressBar release]; - m_progressBar = nil; - } -} - - -void FConsoleWindow::ExpandTextView(const float height) -{ - NSRect textFrame = [m_scrollView frame]; - textFrame.origin.y -= height; - textFrame.size.height += height; - [m_scrollView setFrame:textFrame]; -} - - -void FConsoleWindow::Progress(const int current, const int maximum) -{ - if (nil == m_progressBar) - { - return; - } - - UpdateTimed([&]() - { - [m_progressBar setMaxValue:maximum]; - [m_progressBar setDoubleValue:current]; - }); -} - - -void FConsoleWindow::NetInit(const char* const message, const int playerCount) -{ - if (nil == m_netView) - { - SetProgressBar(false); - ExpandTextView(-NET_VIEW_HEIGHT); - - // Message like 'Waiting for players' or 'Contacting host' - m_netMessageText = [[NSTextField alloc] initWithFrame:NSMakeRect(12.0f, 64.0f, 400.0f, 16.0f)]; - [m_netMessageText setAutoresizingMask:NSViewWidthSizable]; - [m_netMessageText setDrawsBackground:NO]; - [m_netMessageText setSelectable:NO]; - [m_netMessageText setBordered:NO]; - - // Text with connected/total players count - m_netCountText = [[NSTextField alloc] initWithFrame:NSMakeRect(428.0f, 64.0f, 72.0f, 16.0f)]; - [m_netCountText setAutoresizingMask:NSViewMinXMargin]; - [m_netCountText setAlignment:NSRightTextAlignment]; - [m_netCountText setDrawsBackground:NO]; - [m_netCountText setSelectable:NO]; - [m_netCountText setBordered:NO]; - - // Connection progress - m_netProgressBar = [[NSProgressIndicator alloc] initWithFrame:NSMakeRect(12.0f, 40.0f, 488.0f, 16.0f)]; - [m_netProgressBar setAutoresizingMask:NSViewWidthSizable]; - [m_netProgressBar setMaxValue:playerCount]; - - if (0 == playerCount) - { - // Joining game - [m_netProgressBar setIndeterminate:YES]; - [m_netProgressBar startAnimation:nil]; - } - else - { - // Hosting game - [m_netProgressBar setIndeterminate:NO]; - } - - // Cancel network game button - m_netAbortButton = [[NSButton alloc] initWithFrame:NSMakeRect(432.0f, 8.0f, 72.0f, 28.0f)]; - [m_netAbortButton setAutoresizingMask:NSViewMinXMargin]; - [m_netAbortButton setBezelStyle:NSRoundedBezelStyle]; - [m_netAbortButton setTitle:@"Cancel"]; - [m_netAbortButton setKeyEquivalent:@"\r"]; - [m_netAbortButton setTarget:NSApp]; - [m_netAbortButton setAction:@selector(terminate:)]; - - // Panel for controls above - m_netView = [[NSView alloc] initWithFrame:NSMakeRect(0.0f, 0.0f, 512.0f, NET_VIEW_HEIGHT)]; - [m_netView setAutoresizingMask:NSViewWidthSizable]; - [m_netView addSubview:m_netMessageText]; - [m_netView addSubview:m_netCountText]; - [m_netView addSubview:m_netProgressBar]; - [m_netView addSubview:m_netAbortButton]; - - NSRect windowRect = [m_window frame]; - windowRect.origin.y -= NET_VIEW_HEIGHT; - windowRect.size.height += NET_VIEW_HEIGHT; - - [m_window setFrame:windowRect display:YES]; - [[m_window contentView] addSubview:m_netView]; - - ScrollTextToBottom(); - } - - [m_netMessageText setStringValue:[NSString stringWithUTF8String:message]]; - - m_netCurPos = 0; - m_netMaxPos = playerCount; - - NetProgress(1); // You always know about yourself -} - -void FConsoleWindow::NetProgress(const int count) -{ - if (0 == count) - { - ++m_netCurPos; - } - else - { - m_netCurPos = count; - } - - if (nil == m_netView) - { - return; - } - - if (m_netMaxPos > 1) - { - [m_netCountText setStringValue:[NSString stringWithFormat:@"%d / %d", m_netCurPos, m_netMaxPos]]; - [m_netProgressBar setDoubleValue:MIN(m_netCurPos, m_netMaxPos)]; - } -} - -void FConsoleWindow::NetDone() -{ - if (nil != m_netView) - { - ExpandTextView(NET_VIEW_HEIGHT); - - [m_netView removeFromSuperview]; - [m_netView release]; - m_netView = nil; - - // Released by m_netView - m_netMessageText = nil; - m_netCountText = nil; - m_netProgressBar = nil; - m_netAbortButton = nil; - } -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_start.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_start.mm deleted file mode 100644 index 6ce48e8..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/cocoa/st_start.mm +++ /dev/null @@ -1,194 +0,0 @@ -/* - ** st_start.mm - ** - **--------------------------------------------------------------------------- - ** Copyright 2015 Alexey Lysiuk - ** 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 - -#import - -#include "c_cvars.h" -#include "st_console.h" -#include "st_start.h" -#include "v_text.h" - - -FStartupScreen *StartScreen; - - -CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -{ - if (self < 0) - { - self = 0; - } - else if (self > 2) - { - self = 2; - } -} - - -// --------------------------------------------------------------------------- - - -class FBasicStartupScreen : public FStartupScreen -{ -public: - FBasicStartupScreen(int maxProgress, bool showBar); - ~FBasicStartupScreen(); - - virtual void Progress(); - - virtual void NetInit(const char* message, int playerCount); - virtual void NetProgress(int count); - virtual void NetMessage(const char *format, ...); - virtual void NetDone(); - virtual bool NetLoop(bool (*timerCallback)(void*), void* userData); -}; - - -FBasicStartupScreen::FBasicStartupScreen(int maxProgress, bool showBar) -: FStartupScreen(maxProgress) -{ - FConsoleWindow& consoleWindow = FConsoleWindow::GetInstance(); - consoleWindow.SetProgressBar(true); - consoleWindow.SetTitleText(); - -#if 0 - // Testing code, please do not remove - consoleWindow.AddText("----------------------------------------------------------------\n"); - consoleWindow.AddText("1234567890 !@#$%^&*() ,<.>/?;:'\" [{]}\\| `~-_=+ " - "This is very very very long message needed to trigger word wrapping...\n\n"); - consoleWindow.AddText("Multiline...\n\tmessage...\n\t\twith...\n\t\t\ttabs.\n\n"); - - consoleWindow.AddText(TEXTCOLOR_BRICK "TEXTCOLOR_BRICK\n" TEXTCOLOR_TAN "TEXTCOLOR_TAN\n"); - consoleWindow.AddText(TEXTCOLOR_GRAY "TEXTCOLOR_GRAY & TEXTCOLOR_GREY\n"); - consoleWindow.AddText(TEXTCOLOR_GREEN "TEXTCOLOR_GREEN\n" TEXTCOLOR_BROWN "TEXTCOLOR_BROWN\n"); - consoleWindow.AddText(TEXTCOLOR_GOLD "TEXTCOLOR_GOLD\n" TEXTCOLOR_RED "TEXTCOLOR_RED\n"); - consoleWindow.AddText(TEXTCOLOR_BLUE "TEXTCOLOR_BLUE\n" TEXTCOLOR_ORANGE "TEXTCOLOR_ORANGE\n"); - consoleWindow.AddText(TEXTCOLOR_WHITE "TEXTCOLOR_WHITE\n" TEXTCOLOR_YELLOW "TEXTCOLOR_YELLOW\n"); - consoleWindow.AddText(TEXTCOLOR_UNTRANSLATED "TEXTCOLOR_UNTRANSLATED\n"); - consoleWindow.AddText(TEXTCOLOR_BLACK "TEXTCOLOR_BLACK\n" TEXTCOLOR_LIGHTBLUE "TEXTCOLOR_LIGHTBLUE\n"); - consoleWindow.AddText(TEXTCOLOR_CREAM "TEXTCOLOR_CREAM\n" TEXTCOLOR_OLIVE "TEXTCOLOR_OLIVE\n"); - consoleWindow.AddText(TEXTCOLOR_DARKGREEN "TEXTCOLOR_DARKGREEN\n" TEXTCOLOR_DARKRED "TEXTCOLOR_DARKRED\n"); - consoleWindow.AddText(TEXTCOLOR_DARKBROWN "TEXTCOLOR_DARKBROWN\n" TEXTCOLOR_PURPLE "TEXTCOLOR_PURPLE\n"); - consoleWindow.AddText(TEXTCOLOR_DARKGRAY "TEXTCOLOR_DARKGRAY\n" TEXTCOLOR_CYAN "TEXTCOLOR_CYAN\n"); - consoleWindow.AddText(TEXTCOLOR_ICE "TEXTCOLOR_ICE\n" TEXTCOLOR_FIRE "TEXTCOLOR_FIRE\n"); - consoleWindow.AddText(TEXTCOLOR_SAPPHIRE "TEXTCOLOR_SAPPHIRE\n" TEXTCOLOR_TEAL "TEXTCOLOR_TEAL\n"); - consoleWindow.AddText(TEXTCOLOR_NORMAL "TEXTCOLOR_NORMAL\n" TEXTCOLOR_BOLD "TEXTCOLOR_BOLD\n"); - consoleWindow.AddText(TEXTCOLOR_CHAT "TEXTCOLOR_CHAT\n" TEXTCOLOR_TEAMCHAT "TEXTCOLOR_TEAMCHAT\n"); - consoleWindow.AddText("----------------------------------------------------------------\n"); -#endif // _DEBUG -} - -FBasicStartupScreen::~FBasicStartupScreen() -{ - FConsoleWindow::GetInstance().SetProgressBar(false); -} - - -void FBasicStartupScreen::Progress() -{ - if (CurPos < MaxPos) - { - ++CurPos; - } - - FConsoleWindow::GetInstance().Progress(CurPos, MaxPos); -} - - -void FBasicStartupScreen::NetInit(const char* const message, const int playerCount) -{ - FConsoleWindow::GetInstance().NetInit(message, playerCount); -} - -void FBasicStartupScreen::NetProgress(const int count) -{ - FConsoleWindow::GetInstance().NetProgress(count); -} - -void FBasicStartupScreen::NetMessage(const char* const format, ...) -{ - va_list args; - va_start(args, format); - - FString message; - message.VFormat(format, args); - va_end(args); - - Printf("%s\n", message.GetChars()); -} - -void FBasicStartupScreen::NetDone() -{ - FConsoleWindow::GetInstance().NetDone(); -} - -bool FBasicStartupScreen::NetLoop(bool (*timerCallback)(void*), void* const userData) -{ - while (true) - { - if (timerCallback(userData)) - { - break; - } - - [[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode]; - - // Do not poll to often - usleep(50000); - } - - return true; -} - - -// --------------------------------------------------------------------------- - - -FStartupScreen *FStartupScreen::CreateInstance(const int maxProgress) -{ - return new FBasicStartupScreen(maxProgress, true); -} - - -// --------------------------------------------------------------------------- - - -void ST_Endoom() -{ - extern void I_ShutdownJoysticks(); - I_ShutdownJoysticks(); - - exit(0); -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/crashcatcher.c b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/crashcatcher.c similarity index 100% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/crashcatcher.c rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/crashcatcher.c diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/glvideo.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/glvideo.cpp similarity index 81% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/glvideo.cpp rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/glvideo.cpp index 04d180a..b52a411 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/glvideo.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/glvideo.cpp @@ -114,29 +114,23 @@ CUSTOM_CVAR(Bool, gl_es, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCA // CODE -------------------------------------------------------------------- -OculusQuestGLVideo::OculusQuestGLVideo (int parm) +NoSDLGLVideo::NoSDLGLVideo (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 () +NoSDLGLVideo::~NoSDLGLVideo () { if (GLRenderer != NULL) GLRenderer->FlushTextures(); } -void OculusQuestGLVideo::StartModeIterator (int bits, bool fs) +void NoSDLGLVideo::StartModeIterator (int bits, bool fs) { IteratorMode = 0; IteratorBits = bits; } -bool OculusQuestGLVideo::NextMode (int *width, int *height, bool *letterbox) +bool NoSDLGLVideo::NextMode (int *width, int *height, bool *letterbox) { if (IteratorBits != 8) return false; @@ -151,7 +145,7 @@ bool OculusQuestGLVideo::NextMode (int *width, int *height, bool *letterbox) return false; } -DFrameBuffer *OculusQuestGLVideo::CreateFrameBuffer (int width, int height, bool bgra, bool fullscreen, DFrameBuffer *old) +DFrameBuffer *NoSDLGLVideo::CreateFrameBuffer (int width, int height, bool bgra, bool fullscreen, DFrameBuffer *old) { static int retry = 0; static int owidth, oheight; @@ -169,7 +163,7 @@ DFrameBuffer *OculusQuestGLVideo::CreateFrameBuffer (int width, int height, bool // flashAmount = 0; } - OculusQuestBaseFB *fb; + NoSDLBaseFB *fb; const char *hwBuffers = Args->CheckValue("-hwbuffers"); int buffers = 1; if (hwBuffers) @@ -183,11 +177,11 @@ DFrameBuffer *OculusQuestGLVideo::CreateFrameBuffer (int width, int height, bool return fb; } -void OculusQuestGLVideo::SetWindowedScale (float scale) +void NoSDLGLVideo::SetWindowedScale (float scale) { } -bool OculusQuestGLVideo::SetResolution (int width, int height, int bits) +bool NoSDLGLVideo::SetResolution (int width, int height, int bits) { // FIXME: Is it possible to do this without completely destroying the old // interface? @@ -196,7 +190,7 @@ bool OculusQuestGLVideo::SetResolution (int width, int height, int bits) if (GLRenderer != NULL) GLRenderer->FlushTextures(); I_ShutdownGraphics(); - Video = new OculusQuestGLVideo(0); + Video = new NoSDLGLVideo(0); if (Video == NULL) I_FatalError ("Failed to initialize display"); #if (defined(WINDOWS)) || defined(WIN32) @@ -219,7 +213,7 @@ bool OculusQuestGLVideo::SetResolution (int width, int height, int bits) extern "C" extern int glesLoad; #endif -void OculusQuestGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, const int *glver) +void NoSDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, const int *glver) { #ifdef __MOBILE__ @@ -252,73 +246,73 @@ void OculusQuestGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, c // FrameBuffer implementation ----------------------------------------------- -OculusQuestGLFB::OculusQuestGLFB (void *, int width, int height, int, int, bool fullscreen, bool bgra) - : OculusQuestBaseFB (width, height, bgra) +NoSDLGLFB::NoSDLGLFB (void *, int width, int height, int, int, bool fullscreen, bool bgra) + : NoSDLBaseFB (width, height, bgra) { } -OculusQuestGLFB::~OculusQuestGLFB () +NoSDLGLFB::~NoSDLGLFB () { } -void OculusQuestGLFB::InitializeState() +void NoSDLGLFB::InitializeState() { } -void OculusQuestGLFB::SetGammaTable(uint16_t *tbl) +void NoSDLGLFB::SetGammaTable(uint16_t *tbl) { } -void OculusQuestGLFB::ResetGammaTable() +void NoSDLGLFB::ResetGammaTable() { } -bool OculusQuestGLFB::Lock(bool buffered) +bool NoSDLGLFB::Lock(bool buffered) { m_Lock++; return true; } -bool OculusQuestGLFB::Lock () +bool NoSDLGLFB::Lock () { return Lock(false); } -void OculusQuestGLFB::Unlock () +void NoSDLGLFB::Unlock () { --m_Lock; } -bool OculusQuestGLFB::IsLocked () +bool NoSDLGLFB::IsLocked () { return m_Lock>0;// true; } -bool OculusQuestGLFB::IsFullscreen () +bool NoSDLGLFB::IsFullscreen () { return true; } -bool OculusQuestGLFB::IsValid () +bool NoSDLGLFB::IsValid () { - return DFrameBuffer::IsValid() && Screen != NULL; + return DFrameBuffer::IsValid(); } -void OculusQuestGLFB::SetVSync( bool vsync ) +void NoSDLGLFB::SetVSync( bool vsync ) { } -void OculusQuestGLFB::NewRefreshRate () +void NoSDLGLFB::NewRefreshRate () { } -void OculusQuestGLFB::SwapBuffers() +void NoSDLGLFB::SwapBuffers() { } -int OculusQuestGLFB::GetClientWidth() +int NoSDLGLFB::GetClientWidth() { uint32_t w, h; Android_GetScreenRes(&w, &h); @@ -326,7 +320,7 @@ int OculusQuestGLFB::GetClientWidth() return width; } -int OculusQuestGLFB::GetClientHeight() +int NoSDLGLFB::GetClientHeight() { uint32_t w, h; Android_GetScreenRes(&w, &h); @@ -334,7 +328,7 @@ int OculusQuestGLFB::GetClientHeight() return height; } -void OculusQuestGLFB::ScaleCoordsFromWindow(int16_t &x, int16_t &y) +void NoSDLGLFB::ScaleCoordsFromWindow(int16_t &x, int16_t &y) { uint32_t w, h; Android_GetScreenRes(&w, &h); diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlglvideo.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/glvideo.h similarity index 76% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlglvideo.h rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/glvideo.h index 3be296b..3d958bc 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlglvideo.h +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/glvideo.h @@ -12,11 +12,11 @@ EXTERN_CVAR (Color, dimcolor) struct FRenderer; FRenderer *gl_CreateInterface(); -class SDLGLVideo : public IVideo +class NoSDLGLVideo : public IVideo { public: - SDLGLVideo (int parm); - ~SDLGLVideo (); + NoSDLGLVideo (int parm); + ~NoSDLGLVideo (); EDisplayType GetDisplayType () { return DISPLAY_Both; } void SetWindowedScale (float scale); @@ -34,23 +34,22 @@ private: int IteratorBits; }; -class SDLBaseFB : public DFrameBuffer +class NoSDLBaseFB : public DFrameBuffer { typedef DFrameBuffer Super; public: using DFrameBuffer::DFrameBuffer; - virtual SDL_Window *GetSDLWindow() = 0; - - friend class SDLGLVideo; + + friend class NoSDLGLVideo; }; -class SDLGLFB : public SDLBaseFB +class NoSDLGLFB : public NoSDLBaseFB { - typedef SDLBaseFB Super; + typedef NoSDLBaseFB Super; public: // this must have the same parameters as the Windows version, even if they are not used! - SDLGLFB (void *hMonitor, int width, int height, int, int, bool fullscreen, bool bgra); - ~SDLGLFB (); + NoSDLGLFB (void *hMonitor, int width, int height, int, int, bool fullscreen, bool bgra); + ~NoSDLGLFB (); void ForceBuffering (bool force); bool Lock(bool buffered); @@ -66,14 +65,14 @@ public: void NewRefreshRate (); - friend class SDLGLVideo; + friend class NoSDLGLVideo; int GetClientWidth(); int GetClientHeight(); virtual void ScaleCoordsFromWindow(int16_t &x, int16_t &y); - SDL_Window *GetSDLWindow() override { return Screen; } +// SDL_Window *GetSDLWindow() override { return Screen; } virtual int GetTrueHeight() { return GetClientHeight(); } protected: @@ -81,13 +80,13 @@ protected: void ResetGammaTable(); void InitializeState(); - SDLGLFB () {} + NoSDLGLFB () {} uint8_t GammaTable[3][256]; bool UpdatePending; - SDL_Window *Screen; +// SDL_Window *Screen; - SDL_GLContext GLContext; +// SDL_GLContext GLContext; void UpdateColors (); diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/hardware.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/hardware.cpp similarity index 90% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/hardware.cpp rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/hardware.cpp index 86ed237..d79b265 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/hardware.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/hardware.cpp @@ -32,7 +32,6 @@ ** */ -#include #include #include @@ -100,25 +99,17 @@ void I_ShutdownGraphics () } 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); + Video = new NoSDLGLVideo(0); if (Video == NULL) I_FatalError ("Failed to initialize display"); @@ -153,28 +144,7 @@ void I_CreateRenderer() 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; + return Video->CreateFrameBuffer (width, height, swtruecolor, true, old); } bool I_CheckResolution (int width, int height, int bits) diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_gui.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_gui.cpp similarity index 98% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_gui.cpp rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_gui.cpp index 1a895a6..dce4b7c 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_gui.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_gui.cpp @@ -33,7 +33,7 @@ #include -#include +//#include #include "bitmap.h" #include "v_palette.h" @@ -41,7 +41,7 @@ bool I_SetCursor(FTexture *cursorpic) { - static SDL_Cursor *cursor; +/* static SDL_Cursor *cursor; static SDL_Surface *cursorSurface; if (cursorpic != NULL && cursorpic->UseType != ETextureType::Null) @@ -81,6 +81,6 @@ bool I_SetCursor(FTexture *cursorpic) SDL_FreeSurface(cursorSurface); cursorSurface = NULL; } - } + }*/ return true; } diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_input.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_input.cpp similarity index 100% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_input.cpp rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_input.cpp diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_gui.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_joystick.cpp similarity index 56% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_gui.cpp rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_joystick.cpp index 1a895a6..fbec151 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_gui.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_joystick.cpp @@ -1,8 +1,8 @@ /* -** i_gui.cpp +** i_joystick.cpp ** **--------------------------------------------------------------------------- -** Copyright 2008 Randy Heit +** Copyright 2005-2016 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -30,57 +30,82 @@ **--------------------------------------------------------------------------- ** */ +#include "doomdef.h" +#include "version.h" +#include "templates.h" +#include "m_joy.h" -#include +// Very small deadzone so that floating point magic doesn't happen +#define MIN_DEADZONE 0.000001f -#include - -#include "bitmap.h" -#include "v_palette.h" -#include "textures.h" - -bool I_SetCursor(FTexture *cursorpic) +CUSTOM_CVAR(Bool, joy_background, false, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL) { - 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; + Printf("This won't take effect until " GAMENAME " is restarted.\n"); +} + +class NoSDLInputJoystickManager +{ +public: + NoSDLInputJoystickManager() + { + } + ~NoSDLInputJoystickManager() + { + } + + void AddAxes(float axes[5]) + { + } + + void GetDevices(TArray &sticks) + { + } + + void ProcessInput() const + { + } +}; + +static NoSDLInputJoystickManager *JoystickManager; + +void I_StartupJoysticks() +{ + JoystickManager = new NoSDLInputJoystickManager(); +} +void I_ShutdownJoysticks() +{ + if(JoystickManager) + { + delete JoystickManager; + } +} + +void I_GetJoysticks(TArray &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; } diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_main.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_main.cpp similarity index 99% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_main.cpp rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_main.cpp index b4cf29d..4bdf1d4 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_main.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_main.cpp @@ -34,7 +34,7 @@ // HEADER FILES ------------------------------------------------------------ -#include +//#include #include #include #include diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_system.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_system.cpp similarity index 98% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_system.cpp rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_system.cpp index ccd5c1a..342790a 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_system.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_system.cpp @@ -34,7 +34,7 @@ #include #include -#include +//#include #include "doomerrors.h" #include @@ -152,7 +152,7 @@ void Mac_I_FatalError(const char* errortext); void Linux_I_FatalError(const char* errortext) { // Close window or exit fullscreen and release mouse capture - SDL_Quit(); + //SDL_Quit(); const char *str; if((str=getenv("KDE_FULL_SESSION")) && strcmp(str, "true") == 0) @@ -174,7 +174,7 @@ void Linux_I_FatalError(const char* errortext) FString message; message << GAMESIG " "; message << GetVersionString() << ": No IWAD found"; - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, message, errortext, NULL); + //SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, message, errortext, NULL); } } #endif @@ -452,17 +452,17 @@ int I_FindAttr(findstate_t* const fileinfo) void I_PutInClipboard (const char *str) { - SDL_SetClipboardText(str); + //SDL_SetClipboardText(str); } FString I_GetFromClipboard (bool use_primary_selection) { - if(char *ret = SDL_GetClipboardText()) +/* if(char *ret = SDL_GetClipboardText()) { FString text(ret); SDL_free(ret); return text; - } + }*/ return ""; } diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_system.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_system.mm similarity index 100% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_system.mm rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/i_system.mm diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/st_start.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/st_start.cpp similarity index 100% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/st_start.cpp rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/st_start.cpp diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/video.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/video.cpp similarity index 83% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/video.cpp rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/video.cpp index cb6cdfb..5e7b31a 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/video.cpp +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/video.cpp @@ -105,15 +105,15 @@ CUSTOM_CVAR (Float, bgamma, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // PRIVATE DATA DEFINITIONS ------------------------------------------------ -static cycle_t BlitCycles; -static cycle_t SDLFlipCycles; +//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) +NoSDLFB::NoSDLFB (int width, int height, bool bgra, bool fullscreen/*, SDL_Window *oldwin*/) + : NoSDLBaseFB (width, height, bgra) { int i; @@ -124,8 +124,8 @@ OculusQuestFB::OculusQuestFB (int width, int height, bool bgra, bool fullscreen, FlashAmount = 0; - Renderer = NULL; - Texture = NULL; +// Renderer = NULL; +// Texture = NULL; for (i = 0; i < 256; i++) { @@ -141,61 +141,61 @@ OculusQuestFB::OculusQuestFB (int width, int height, bool bgra, bool fullscreen, } -OculusQuestFB::~OculusQuestFB () +NoSDLFB::~NoSDLFB () { } -bool OculusQuestFB::IsValid () +bool NoSDLFB::IsValid () { return DFrameBuffer::IsValid(); } -int OculusQuestFB::GetPageCount () +int NoSDLFB::GetPageCount () { return 1; } -bool OculusQuestFB::Lock (bool buffered) +bool NoSDLFB::Lock (bool buffered) { return DSimpleCanvas::Lock (); } -bool OculusQuestFB::Relock () +bool NoSDLFB::Relock () { return DSimpleCanvas::Lock (); } -void OculusQuestFB::Unlock () +void NoSDLFB::Unlock () { --LockCount; } -void OculusQuestFB::Update () +void NoSDLFB::Update () { } -void OculusQuestFB::UpdateColors () +void NoSDLFB::UpdateColors () { } -PalEntry *OculusQuestFB::GetPalette () +PalEntry *NoSDLFB::GetPalette () { return SourcePalette; } -void OculusQuestFB::UpdatePalette () +void NoSDLFB::UpdatePalette () { NeedPalUpdate = true; } -bool OculusQuestFB::SetGamma (float gamma) +bool NoSDLFB::SetGamma (float gamma) { Gamma = gamma; NeedGammaUpdate = true; return true; } -bool OculusQuestFB::SetFlash (PalEntry rgb, int amount) +bool NoSDLFB::SetFlash (PalEntry rgb, int amount) { Flash = rgb; FlashAmount = amount; @@ -203,35 +203,35 @@ bool OculusQuestFB::SetFlash (PalEntry rgb, int amount) return true; } -void OculusQuestFB::GetFlash (PalEntry &rgb, int &amount) +void NoSDLFB::GetFlash (PalEntry &rgb, int &amount) { rgb = Flash; amount = FlashAmount; } // Q: Should I gamma adjust the returned palette? -void OculusQuestFB::GetFlashedPalette (PalEntry pal[256]) +void NoSDLFB::GetFlashedPalette (PalEntry pal[256]) { } -void OculusQuestFB::SetFullscreen (bool fullscreen) +void NoSDLFB::SetFullscreen (bool fullscreen) { } -bool OculusQuestFB::IsFullscreen () +bool NoSDLFB::IsFullscreen () { return true; } -void OculusQuestFB::ResetSDLRenderer () +void NoSDLFB::ResetSDLRenderer () { } -void OculusQuestFB::SetVSync (bool vsync) +void NoSDLFB::SetVSync (bool vsync) { } -void OculusQuestFB::ScaleCoordsFromWindow(int16_t &x, int16_t &y) +void NoSDLFB::ScaleCoordsFromWindow(int16_t &x, int16_t &y) { uint32_t w, h; Android_GetScreenRes(&w, &h); diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/video.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/video.h similarity index 68% rename from Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/video.h rename to Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/video.h index 3d1ea58..233ef1a 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/video.h +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/nosdl/video.h @@ -2,12 +2,12 @@ #include "v_video.h" #include "glvideo.h" -class OculusQuestFB : public OculusQuestBaseFB +class NoSDLFB : public NoSDLBaseFB { - typedef OculusQuestBaseFB Super; + typedef NoSDLBaseFB Super; public: - OculusQuestFB(int width, int height, bool bgra, bool fullscreen, SDL_Window *oldwin); - ~OculusQuestFB(); + NoSDLFB(int width, int height, bool bgra, bool fullscreen/*, SDL_Window *oldwin*/); + ~NoSDLFB(); bool Lock(bool buffer); void Unlock(); @@ -25,12 +25,12 @@ public: int GetPageCount(); bool IsFullscreen(); - friend class OculusQuestGLVideo; + friend class NoSDLGLVideo; virtual void SetVSync(bool vsync); virtual void ScaleCoordsFromWindow(int16_t &x, int16_t &y); - SDL_Window *GetSDLWindow() override { return Screen; } +// SDL_Window *GetSDLWindow() override { return Screen; } private: PalEntry SourcePalette[256]; @@ -40,13 +40,13 @@ private: float Gamma; bool UpdatePending; - SDL_Window *Screen; - SDL_Renderer *Renderer; - union - { - SDL_Texture *Texture; - SDL_Surface *Surface; - }; +// SDL_Window *Screen; +// SDL_Renderer *Renderer; +// union +// { +// SDL_Texture *Texture; +// SDL_Surface *Surface; +// }; bool UsingRenderer; bool NeedPalUpdate; @@ -56,5 +56,5 @@ private: void UpdateColors(); void ResetSDLRenderer(); - OculusQuestFB() {} + NoSDLFB() {} }; diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/glvideo.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/glvideo.h deleted file mode 100644 index d357650..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/glvideo.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef __SDLGLVIDEO_H__ -#define __SDLGLVIDEO_H__ - -#include "hardware.h" -#include "v_video.h" -#include -#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 diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_joystick.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_joystick.cpp deleted file mode 100644 index 9065740..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_joystick.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* -** 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 - -#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 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 &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 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 &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; -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_system.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_system.cpp deleted file mode 100644 index ccd5c1a..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/oculusquest/i_system.cpp +++ /dev/null @@ -1,496 +0,0 @@ -//----------------------------------------------------------------------------- -// -// 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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "doomerrors.h" -#include - -#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 -#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 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 I_GetGogPaths() -{ - // GOG's Doom games are Windows only at the moment - return TArray(); -} - diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/i_specialpaths.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/i_specialpaths.mm deleted file mode 100644 index 540aaf4..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/i_specialpaths.mm +++ /dev/null @@ -1,238 +0,0 @@ -/* -** i_specialpaths.mm -** Gets special system folders where data should be stored. (macOS version) -** -**--------------------------------------------------------------------------- -** Copyright 2013-2016 Randy Heit -** Copyright 2016 Christoph Oelckers -** 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 - -#include "cmdlib.h" -#include "m_misc.h" -#include "version.h" // for GAMENAME - -//=========================================================================== -// -// M_GetAppDataPath macOS -// -// Returns the path for the AppData folder. -// -//=========================================================================== - -FString M_GetAppDataPath(bool create) -{ - FString path; - - char pathstr[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX)) - { - path = pathstr; - } - else - { - path = progdir; - } - path += "/" GAMENAMELOWERCASE; - if (create) CreatePath(path); - return path; -} - -//=========================================================================== -// -// M_GetCachePath macOS -// -// Returns the path for cache GL nodes. -// -//=========================================================================== - -FString M_GetCachePath(bool create) -{ - FString path; - - char pathstr[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kApplicationSupportFolderType, create ? kCreateFolder : 0, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)pathstr, PATH_MAX)) - { - path = pathstr; - } - else - { - path = progdir; - } - path += "/zdoom/cache"; - if (create) CreatePath(path); - return path; -} - -//=========================================================================== -// -// M_GetAutoexecPath macOS -// -// Returns the expected location of autoexec.cfg. -// -//=========================================================================== - -FString M_GetAutoexecPath() -{ - FString path; - - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - path << cpath << "/" GAME_DIR "/autoexec.cfg"; - } - return path; -} - -//=========================================================================== -// -// M_GetCajunPath macOS -// -// Returns the location of the Cajun Bot definitions. -// -//=========================================================================== - -FString M_GetCajunPath(const char *botfilename) -{ - FString path; - - // Just copies the Windows code. Should this be more Mac-specific? - path << progdir << "zcajun/" << botfilename; - if (!FileExists(path)) - { - path = ""; - } - return path; -} - -//=========================================================================== -// -// M_GetConfigPath macOS -// -// Returns the path to the config file. On Windows, this can vary for reading -// vs writing. i.e. If $PROGDIR/zdoom-.ini does not exist, it will try -// to read from $PROGDIR/zdoom.ini, but it will never write to zdoom.ini. -// -//=========================================================================== - -FString M_GetConfigPath(bool for_reading) -{ - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kPreferencesFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - FString path; - path << cpath << "/" GAMENAMELOWERCASE ".ini"; - return path; - } - // Ungh. - return GAMENAMELOWERCASE ".ini"; -} - -//=========================================================================== -// -// M_GetScreenshotsPath macOS -// -// Returns the path to the default screenshots directory. -// -//=========================================================================== - -FString M_GetScreenshotsPath() -{ - FString path; - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - path << cpath << "/" GAME_DIR "/Screenshots/"; - } - else - { - path = "~/"; - } - return path; -} - -//=========================================================================== -// -// M_GetSavegamesPath macOS -// -// Returns the path to the default save games directory. -// -//=========================================================================== - -FString M_GetSavegamesPath() -{ - FString path; - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - path << cpath << "/" GAME_DIR "/Savegames/"; - } - return path; -} - -//=========================================================================== -// -// M_GetDocumentsPath Unix -// -// Returns the path to the default documents directory. -// -//=========================================================================== - -FString M_GetDocumentsPath() -{ - FString path; - char cpath[PATH_MAX]; - FSRef folder; - - if (noErr == FSFindFolder(kUserDomain, kDocumentsFolderType, kCreateFolder, &folder) && - noErr == FSRefMakePath(&folder, (UInt8*)cpath, PATH_MAX)) - { - path << cpath << "/" GAME_DIR "/"; - } - return path; -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/iwadpicker_cocoa.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/iwadpicker_cocoa.mm deleted file mode 100644 index 99be5f4..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/iwadpicker_cocoa.mm +++ /dev/null @@ -1,470 +0,0 @@ -/* - ** iwadpicker_cocoa.mm - ** - ** Implements Mac OS X native IWAD Picker. - ** - **--------------------------------------------------------------------------- - ** Copyright 2010 Braden Obrzut - ** 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 "cmdlib.h" -#include "d_main.h" -#include "version.h" -#include "c_cvars.h" -#include "m_argv.h" -#include "m_misc.h" -#include "gameconfigfile.h" - -#include -#include -#include - - -CVAR(String, osx_additional_parameters, "", CVAR_ARCHIVE | CVAR_NOSET | CVAR_GLOBALCONFIG); - -enum -{ - COLUMN_IWAD, - COLUMN_GAME, - - NUM_COLUMNS -}; - -static const char* const tableHeaders[NUM_COLUMNS] = { "IWAD", "Game" }; - -// Class to convert the IWAD data into a form that Cocoa can use. -@interface IWADTableData : NSObject -{ - NSMutableArray *data; -} - -- (void)dealloc; -- (IWADTableData *)init:(WadStuff *) wads num:(int) numwads; - -- (int)numberOfRowsInTableView:(NSTableView *)aTableView; -- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex; -@end - -@implementation IWADTableData - -- (void)dealloc -{ - [data release]; - - [super dealloc]; -} - -- (IWADTableData *)init:(WadStuff *) wads num:(int) numwads -{ - data = [[NSMutableArray alloc] initWithCapacity:numwads]; - - for(int i = 0;i < numwads;i++) - { - NSMutableDictionary *record = [[NSMutableDictionary alloc] initWithCapacity:NUM_COLUMNS]; - const char* filename = strrchr(wads[i].Path, '/'); - if(filename == NULL) - filename = wads[i].Path; - else - filename++; - [record setObject:[NSString stringWithUTF8String:filename] forKey:[NSString stringWithUTF8String:tableHeaders[COLUMN_IWAD]]]; - [record setObject:[NSString stringWithUTF8String:wads[i].Name] forKey:[NSString stringWithUTF8String:tableHeaders[COLUMN_GAME]]]; - [data addObject:record]; - [record release]; - } - - return self; -} - -- (int)numberOfRowsInTableView:(NSTableView *)aTableView -{ - return [data count]; -} - -- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex -{ - NSParameterAssert(rowIndex >= 0 && (unsigned int) rowIndex < [data count]); - NSMutableDictionary *record = [data objectAtIndex:rowIndex]; - return [record objectForKey:[aTableColumn identifier]]; -} - -@end - -static NSDictionary* GetKnownFileTypes() -{ - return [NSDictionary dictionaryWithObjectsAndKeys: - @"-file" , @"wad", - @"-file" , @"pk3", - @"-file" , @"zip", - @"-file" , @"pk7", - @"-file" , @"7z", - @"-deh" , @"deh", - @"-bex" , @"bex", - @"-exec" , @"cfg", - @"-playdemo", @"lmp", - nil]; -} - -static NSArray* GetKnownExtensions() -{ - return [GetKnownFileTypes() allKeys]; -} - -@interface NSMutableString(AppendKnownFileType) -- (void)appendKnownFileType:(NSString *)filePath; -@end - -@implementation NSMutableString(AppendKnownFileType) -- (void)appendKnownFileType:(NSString *)filePath -{ - NSString* extension = [[filePath pathExtension] lowercaseString]; - NSString* parameter = [GetKnownFileTypes() objectForKey:extension]; - - if (nil == parameter) - { - return; - } - - [self appendFormat:@"%@ \"%@\" ", parameter, filePath]; -} -@end - -// So we can listen for button actions and such we need to have an Obj-C class. -@interface IWADPicker : NSObject -{ - NSApplication *app; - NSWindow *window; - NSButton *okButton; - NSButton *cancelButton; - NSButton *browseButton; - NSTextField *parametersTextField; - bool cancelled; -} - -- (void)buttonPressed:(id) sender; -- (void)browseButtonPressed:(id) sender; -- (void)doubleClicked:(id) sender; -- (void)makeLabel:(NSTextField *)label withString:(const char*) str; -- (int)pickIWad:(WadStuff *)wads num:(int) numwads showWindow:(bool) showwin defaultWad:(int) defaultiwad; -- (NSString*)commandLineParameters; -- (void)menuActionSent:(NSNotification*)notification; -@end - -@implementation IWADPicker - -- (void)buttonPressed:(id) sender -{ - if(sender == cancelButton) - cancelled = true; - - [window orderOut:self]; - [app stopModal]; -} - -- (void)browseButtonPressed:(id) sender -{ - NSOpenPanel* openPanel = [NSOpenPanel openPanel]; - [openPanel setAllowsMultipleSelection:YES]; - [openPanel setCanChooseFiles:YES]; - [openPanel setCanChooseDirectories:YES]; - [openPanel setResolvesAliases:YES]; - [openPanel setAllowedFileTypes:GetKnownExtensions()]; - - if (NSOKButton == [openPanel runModal]) - { - NSArray* files = [openPanel URLs]; - NSMutableString* parameters = [NSMutableString string]; - - for (NSUInteger i = 0, ei = [files count]; i < ei; ++i) - { - NSString* filePath = [[files objectAtIndex:i] path]; - BOOL isDirectory = false; - - if ([[NSFileManager defaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory] && isDirectory) - { - [parameters appendFormat:@"-file \"%@\" ", filePath]; - } - else - { - [parameters appendKnownFileType:filePath]; - } - } - - if ([parameters length] > 0) - { - NSString* newParameters = [parametersTextField stringValue]; - - if ([newParameters length] > 0 - && NO == [newParameters hasSuffix:@" "]) - { - newParameters = [newParameters stringByAppendingString:@" "]; - } - - newParameters = [newParameters stringByAppendingString:parameters]; - - [parametersTextField setStringValue: newParameters]; - } - } -} - -- (void)doubleClicked:(id) sender -{ - if ([sender clickedRow] >= 0) - { - [window orderOut:self]; - [app stopModal]; - } -} - -// Apparently labels in Cocoa are uneditable text fields, so lets make this a -// little more automated. -- (void)makeLabel:(NSTextField *)label withString:(const char*) str -{ - [label setStringValue:[NSString stringWithUTF8String:str]]; - [label setBezeled:NO]; - [label setDrawsBackground:NO]; - [label setEditable:NO]; - [label setSelectable:NO]; -} - -- (int)pickIWad:(WadStuff *)wads num:(int) numwads showWindow:(bool) showwin defaultWad:(int) defaultiwad -{ - cancelled = false; - - app = [NSApplication sharedApplication]; - id windowTitle = [NSString stringWithFormat:@"%s %s", GAMENAME, GetVersionString()]; - - NSRect frame = NSMakeRect(0, 0, 440, 450); - window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSTitledWindowMask backing:NSBackingStoreBuffered defer:NO]; - [window setTitle:windowTitle]; - - NSTextField *description = [[NSTextField alloc] initWithFrame:NSMakeRect(18, 384, 402, 50)]; - [self makeLabel:description withString:GAMENAME " found more than one IWAD\nSelect from the list below to determine which one to use:"]; - [[window contentView] addSubview:description]; - [description release]; - - NSScrollView *iwadScroller = [[NSScrollView alloc] initWithFrame:NSMakeRect(20, 135, 402, 256)]; - NSTableView *iwadTable = [[NSTableView alloc] initWithFrame:[iwadScroller bounds]]; - IWADTableData *tableData = [[IWADTableData alloc] init:wads num:numwads]; - for(int i = 0;i < NUM_COLUMNS;i++) - { - NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:[NSString stringWithUTF8String:tableHeaders[i]]]; - [[column headerCell] setStringValue:[column identifier]]; - if(i == 0) - [column setMaxWidth:110]; - [column setEditable:NO]; - [column setResizingMask:NSTableColumnAutoresizingMask]; - [iwadTable addTableColumn:column]; - [column release]; - } - [iwadScroller setDocumentView:iwadTable]; - [iwadScroller setHasVerticalScroller:YES]; - [iwadTable setDataSource:tableData]; - [iwadTable sizeToFit]; - [iwadTable setDoubleAction:@selector(doubleClicked:)]; - [iwadTable setTarget:self]; - NSIndexSet *selection = [[NSIndexSet alloc] initWithIndex:defaultiwad]; - [iwadTable selectRowIndexes:selection byExtendingSelection:NO]; - [selection release]; - [iwadTable scrollRowToVisible:defaultiwad]; - [[window contentView] addSubview:iwadScroller]; - [iwadTable release]; - [iwadScroller release]; - - NSTextField *additionalParametersLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(18, 108, 144, 17)]; - [self makeLabel:additionalParametersLabel withString:"Additional Parameters:"]; - [[window contentView] addSubview:additionalParametersLabel]; - parametersTextField = [[NSTextField alloc] initWithFrame:NSMakeRect(20, 48, 402, 54)]; - [parametersTextField setStringValue:[NSString stringWithUTF8String:osx_additional_parameters]]; - [[window contentView] addSubview:parametersTextField]; - - // Doesn't look like the SDL version implements this so lets not show it. - /*NSButton *dontAsk = [[NSButton alloc] initWithFrame:NSMakeRect(18, 18, 178, 18)]; - [dontAsk setTitle:[NSString stringWithCString:"Don't ask me this again"]]; - [dontAsk setButtonType:NSSwitchButton]; - [dontAsk setState:(showwin ? NSOffState : NSOnState)]; - [[window contentView] addSubview:dontAsk];*/ - - okButton = [[NSButton alloc] initWithFrame:NSMakeRect(236, 8, 96, 32)]; - [okButton setTitle:@"OK"]; - [okButton setBezelStyle:NSRoundedBezelStyle]; - [okButton setAction:@selector(buttonPressed:)]; - [okButton setTarget:self]; - [okButton setKeyEquivalent:@"\r"]; - [[window contentView] addSubview:okButton]; - - cancelButton = [[NSButton alloc] initWithFrame:NSMakeRect(332, 8, 96, 32)]; - [cancelButton setTitle:@"Cancel"]; - [cancelButton setBezelStyle:NSRoundedBezelStyle]; - [cancelButton setAction:@selector(buttonPressed:)]; - [cancelButton setTarget:self]; - [cancelButton setKeyEquivalent:@"\033"]; - [[window contentView] addSubview:cancelButton]; - - browseButton = [[NSButton alloc] initWithFrame:NSMakeRect(14, 8, 96, 32)]; - [browseButton setTitle:@"Browse..."]; - [browseButton setBezelStyle:NSRoundedBezelStyle]; - [browseButton setAction:@selector(browseButtonPressed:)]; - [browseButton setTarget:self]; - [[window contentView] addSubview:browseButton]; - - NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; - [center addObserver:self selector:@selector(menuActionSent:) name:NSMenuDidSendActionNotification object:nil]; - - [window center]; - [app runModalForWindow:window]; - - [center removeObserver:self name:NSMenuDidSendActionNotification object:nil]; - - [window release]; - [okButton release]; - [cancelButton release]; - [browseButton release]; - - return cancelled ? -1 : [iwadTable selectedRow]; -} - -- (NSString*)commandLineParameters -{ - return [parametersTextField stringValue]; -} - -- (void)menuActionSent:(NSNotification*)notification -{ - NSDictionary* userInfo = [notification userInfo]; - NSMenuItem* menuItem = [userInfo valueForKey:@"MenuItem"]; - - if ( @selector(terminate:) == [menuItem action] ) - { - exit(0); - } -} - -@end - - -EXTERN_CVAR(String, defaultiwad) - -static NSString* GetArchitectureString() -{ -#ifdef __i386__ - return @"i386"; -#elif defined __x86_64__ - return @"x86_64"; -#endif -} - -static void RestartWithParameters(const WadStuff& wad, NSString* parameters) -{ - assert(nil != parameters); - - defaultiwad = wad.Name; - - GameConfig->DoGameSetup("Doom"); - M_SaveDefaults(NULL); - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - @try - { - NSString* executablePath = [NSString stringWithUTF8String:Args->GetArg(0)]; - - NSMutableArray* const arguments = [[NSMutableArray alloc] init]; - - // The following value shoud be equal to NSAppKitVersionNumber10_5 - // It's hard-coded in order to build with earlier SDKs - const bool canSelectArchitecture = NSAppKitVersionNumber >= 949; - - if (canSelectArchitecture) - { - [arguments addObject:@"-arch"]; - [arguments addObject:GetArchitectureString()]; - [arguments addObject:executablePath]; - - executablePath = @"/usr/bin/arch"; - } - - [arguments addObject:@"-iwad"]; - [arguments addObject:[NSString stringWithUTF8String:wad.Path]]; - - for (int i = 1, count = Args->NumArgs(); i < count; ++i) - { - NSString* currentParameter = [NSString stringWithUTF8String:Args->GetArg(i)]; - [arguments addObject:currentParameter]; - } - - wordexp_t expansion = {}; - - if (0 == wordexp([parameters UTF8String], &expansion, 0)) - { - for (size_t i = 0; i < expansion.we_wordc; ++i) - { - NSString* argumentString = [NSString stringWithCString:expansion.we_wordv[i] - encoding:NSUTF8StringEncoding]; - [arguments addObject:argumentString]; - } - - wordfree(&expansion); - } - - [NSTask launchedTaskWithLaunchPath:executablePath - arguments:arguments]; - - _exit(0); // to avoid atexit()'s functions - } - @catch (NSException* e) - { - NSLog(@"Cannot restart: %@", [e reason]); - } - - [pool release]; -} - -// Simple wrapper so we can call this from outside. -int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - - IWADPicker *picker = [IWADPicker alloc]; - int ret = [picker pickIWad:wads num:numwads showWindow:showwin defaultWad:defaultiwad]; - - NSString* parametersToAppend = [picker commandLineParameters]; - osx_additional_parameters = [parametersToAppend UTF8String]; - - if (ret >= 0) - { - if (0 != [parametersToAppend length]) - { - RestartWithParameters(wads[ret], parametersToAppend); - } - } - - [pool release]; - - return ret; -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/zdoom-info.plist b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/zdoom-info.plist deleted file mode 100644 index da2263f..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/zdoom-info.plist +++ /dev/null @@ -1,52 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${MACOSX_BUNDLE_EXECUTABLE_NAME} - CFBundleIconFile - zdoom.icns - CFBundleIdentifier - org.drdteam.gzdoom - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - GZDoom - CFBundlePackageType - APPL - CFBundleShortVersionString - Development Version - CFBundleSignature - ???? - LSApplicationCategoryType - public.app-category.action-games - LSMinimumSystemVersion - 10.7 - CFBundleDocumentTypes - - - CFBundleTypeName - Doom Resource File - CFBundleTypeRole - Viewer - CFBundleTypeExtensions - - wad - pk3 - zip - pk7 - 7z - iwad - ipk3 - ipk7 - - - - NSPrincipalClass - NSApplication - NSSupportsAutomaticGraphicsSwitching - - - diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/zdoom.icns b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/osx/zdoom.icns deleted file mode 100644 index af60dd256c2a7775562558e28da6c1696f12a4ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90352 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __linux__ -#include -#ifndef PR_SET_PTRACER -#define PR_SET_PTRACER 0x59616d61 -#endif -#elif defined (__APPLE__) || defined (__FreeBSD__) || defined(__OpenBSD__) -#include -#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; -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/hardware.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/hardware.cpp deleted file mode 100644 index bbe51a4..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/hardware.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* -** 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 -#include -#include - -#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 "sdlvideo.h" -#include "v_text.h" -#include "doomstat.h" -#include "m_argv.h" -#include "sdlglvideo.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, 0, 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 () -{ -#ifdef __APPLE__ - SDL_SetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, "0"); -#endif // __APPLE__ - - if (SDL_InitSubSystem (SDL_INIT_VIDEO) < 0) - { - I_FatalError ("Could not initialize SDL video:\n%s\n", SDL_GetError()); - return; - } - - Printf("Using video driver %s\n", SDL_GetCurrentVideoDriver()); - - UCVarValue val; - - val.Bool = !!Args->CheckParm ("-devparm"); - ticker.SetGenericRepDefault (val, CVAR_Bool); - - //currentrenderer = vid_renderer; - Video = new SDLGLVideo(0); - - if (Video == NULL) - I_FatalError ("Failed to initialize display"); - - atterm (I_ShutdownGraphics); - - Video->SetWindowedScale (vid_winscale); -} - -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) -{ -#ifdef __MOBILE__ // We want to always use the resolution of the device! - return; -#endif - - int twidth, theight; - int cwidth = 0, cheight = 0; - int iteration; - uint32_t closest = 4294967295u; - - for (iteration = 0; iteration < 2; iteration++) - { - Video->StartModeIterator (bits, screen ? screen->IsFullscreen() : fullscreen); - while (Video->NextMode (&twidth, &theight, NULL)) - { - if (twidth == *width && theight == *height) - return; - - if (iteration == 0 && (twidth < *width || theight < *height)) - continue; - - uint32_t dist = (twidth - *width) * (twidth - *width) - + (theight - *height) * (theight - *height); - - if (dist < closest) - { - closest = dist; - cwidth = twidth; - cheight = theight; - } - } - if (closest != 4294967295u) - { - *width = cwidth; - *height = cheight; - return; - } - } -} - -//========================================================================== -// -// SetFPSLimit -// -// Initializes an event timer to fire at a rate of /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__) -Semaphore FPSLimitSemaphore; - -static void FPSLimitNotify(sigval val) -{ - SEMAPHORE_SIGNAL(FPSLimitSemaphore) -} - -void I_SetFPSLimit(int limit) -{ - static sigevent FPSLimitEvent; - static timer_t FPSLimitTimer; - static bool FPSLimitTimerEnabled = false; - static bool EventSetup = false; - if(!EventSetup) - { - EventSetup = true; - FPSLimitEvent.sigev_notify = SIGEV_THREAD; - FPSLimitEvent.sigev_signo = 0; - FPSLimitEvent.sigev_value.sival_int = 0; - FPSLimitEvent.sigev_notify_function = FPSLimitNotify; - FPSLimitEvent.sigev_notify_attributes = NULL; - - SEMAPHORE_INIT(FPSLimitSemaphore, 0, 0) - } - - if (limit < 0) - { - limit = vid_maxfps; - } - // Kill any leftover timer. - if (FPSLimitTimerEnabled) - { - timer_delete(FPSLimitTimer); - FPSLimitTimerEnabled = false; - } - if (limit == 0) - { // no limit - DPrintf(DMSG_NOTIFY, "FPS timer disabled\n"); - } - else - { - FPSLimitTimerEnabled = true; - if(timer_create(CLOCK_REALTIME, &FPSLimitEvent, &FPSLimitTimer) == -1) - Printf(DMSG_WARNING, "Failed to create FPS limitter event\n"); - itimerspec period = { {0, 0}, {0, 0} }; - period.it_value.tv_nsec = period.it_interval.tv_nsec = 1000000000 / limit; - if(timer_settime(FPSLimitTimer, 0, &period, NULL) == -1) - Printf(DMSG_WARNING, "Failed to set FPS limitter timer\n"); - DPrintf(DMSG_NOTIFY, "FPS timer set to %u ms\n", (unsigned int) period.it_interval.tv_nsec / 1000000); - } -} -#else -// So Apple doesn't support POSIX timers and I can't find a good substitute short of -// having Objective-C Cocoa events or something like that. -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) -{ - static const char *ratios[7] = { "", " - 16:9", " - 16:10", "", " - 5:4", "", " - 21:9" }; - int width, height, bits; - bool letterbox; - - if (Video == NULL) - { - return; - } - for (bits = 1; bits <= 32; bits++) - { - Video->StartModeIterator (bits, screen->IsFullscreen()); - while (Video->NextMode (&width, &height, &letterbox)) - { - bool thisMode = (width == DisplayWidth && height == DisplayHeight && bits == DisplayBits); - int ratio = CheckRatio (width, height); - Printf (thisMode ? PRINT_BOLD : PRINT_HIGH, - "%s%4d x%5d x%3d%s%s\n", - thisMode || !IsRatioWidescreen(ratio) ? "" : TEXTCOLOR_GOLD, - width, height, bits, - ratios[ratio], - thisMode || !letterbox ? "" : TEXTCOLOR_BROWN " LB" - ); - } - } -} - -CCMD (vid_currentmode) -{ - Printf ("%dx%dx%d\n", DisplayWidth, DisplayHeight, DisplayBits); -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_input.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_input.cpp deleted file mode 100644 index fd9345d..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_input.cpp +++ /dev/null @@ -1,590 +0,0 @@ -/* -** 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 -#include -#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 InitKeySymMap () -{ - TMap 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 KeySymToDIK(InitKeySymMap()); - -static TMap InitKeyScanMap () -{ - TMap KeyScanToDIK; - - for (int i = 0; i < 256; ++i) - { - KeyScanToDIK[DIKToKeyScan[i]] = i; - } - - return KeyScanToDIK; -} -static const TMap 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(); -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_joystick.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_joystick.cpp deleted file mode 100644 index 9065740..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_joystick.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* -** 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 - -#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 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 &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 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 &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; -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_main.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_main.cpp deleted file mode 100644 index b4cf29d..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_main.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* -** 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 -#include -#include -#include -#include -#include -#include - -#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 -#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; -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_system.mm b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_system.mm deleted file mode 100644 index 50faf94..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/i_system.mm +++ /dev/null @@ -1,19 +0,0 @@ -#include -#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 ); - } -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlglvideo.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlglvideo.cpp deleted file mode 100644 index a36a8ec..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlglvideo.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/* -** 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 "sdlglvideo.h" -#include "sdlvideo.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" - -// 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 -------------------------------------------------------------------- - -SDLGLVideo::SDLGLVideo (int parm) -{ - IteratorBits = 0; - if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { - fprintf( stderr, "Video initialization failed: %s\n", - SDL_GetError( ) ); - } -} - -SDLGLVideo::~SDLGLVideo () -{ - if (GLRenderer != NULL) GLRenderer->FlushTextures(); -} - -void SDLGLVideo::StartModeIterator (int bits, bool fs) -{ - IteratorMode = 0; - IteratorBits = bits; -} - -bool SDLGLVideo::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 *SDLGLVideo::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) - { // Reuse the old framebuffer if its attributes are the same - SDLBaseFB *fb = static_cast (old); - if (fb->Width == width && - fb->Height == height) - { - bool fsnow = (SDL_GetWindowFlags (fb->GetSDLWindow()) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; - - if (fsnow != fullscreen) - { - SDL_SetWindowFullscreen (fb->GetSDLWindow(), fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - } - return old; - } -// old->GetFlash (flashColor, flashAmount); - delete old; - } - else - { - flashColor = 0; -// flashAmount = 0; - } - - SDLBaseFB *fb; - if (vid_renderer == 1) - { -#ifdef USE_GL_HW_BUFFERS - 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); -#else - fb = new OpenGLFrameBuffer(0, width, height, 32, 60, fullscreen); -#endif - } - else if (vid_glswfb == 0) - { - fb = new SDLFB(width, height, bgra, fullscreen, nullptr); - } - else - { - fb = (SDLBaseFB*)CreateGLSWFrameBuffer(width, height, bgra, fullscreen); - if (!fb->IsValid()) - { - delete fb; - fb = new SDLFB(width, height, bgra, fullscreen, nullptr); - } - } - - retry = 0; - - // If we could not create the framebuffer, try again with slightly - // different parameters in this order: - // 1. Try with the closest size - // 2. Try in the opposite screen mode with the original size - // 3. Try in the opposite screen mode with the closest size - // This is a somewhat confusing mass of recursion here. - - while (fb == NULL || !fb->IsValid ()) - { - if (fb != NULL) - { - delete fb; - } - - switch (retry) - { - case 0: - owidth = width; - oheight = height; - case 2: - // Try a different resolution. Hopefully that will work. - I_ClosestResolution (&width, &height, 8); - break; - - case 1: - // Try changing fullscreen mode. Maybe that will work. - width = owidth; - height = oheight; - fullscreen = !fullscreen; - break; - - default: - // I give up! - I_FatalError ("Could not create new screen (%d x %d)", owidth, oheight); - - fprintf( stderr, "!!! [SDLGLVideo::CreateFrameBuffer] Got beyond I_FatalError !!!" ); - return NULL; //[C] actually this shouldn't be reached; probably should be replaced with an ASSERT - } - - ++retry; - fb = static_cast(CreateFrameBuffer (width, height, false, fullscreen, NULL)); - } - -// fb->SetFlash (flashColor, flashAmount); - return fb; -} - -void SDLGLVideo::SetWindowedScale (float scale) -{ -} - -bool SDLGLVideo::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 SDLGLVideo(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 SDLGLVideo::SetupPixelFormat(bool allowsoftware, int multisample, const int *glver) -{ - SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 ); - SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 ); - SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 ); - SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 ); -#ifdef __MOBILE__ - SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); -#else - SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 ); -#endif - SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 8 ); - SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); - if (multisample > 0) { - SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 ); - SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, multisample ); - } - if (gl_debug) - SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); - -#ifdef __MOBILE__ - - const char *version = Args->CheckValue("-glversion"); - int major,min; - 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; - } - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, min); - return; -#endif - - if (gl_es) - { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - } - else if (glver[0] > 2) - { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, glver[0]); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, glver[1]); - } - else - { - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); - } -} - - -// FrameBuffer implementation ----------------------------------------------- - -SDLGLFB::SDLGLFB (void *, int width, int height, int, int, bool fullscreen, bool bgra) - : SDLBaseFB (width, height, bgra) -{ - // NOTE: Core profiles were added with GL 3.2, so there's no sense trying - // to set core 3.1 or 3.0. We could try a forward-compatible context - // instead, but that would be too restrictive (w.r.t. shaders). - static const int glvers[][2] = { - { 4, 5 }, { 4, 4 }, { 4, 3 }, { 4, 2 }, { 4, 1 }, { 4, 0 }, - { 3, 3 }, { 3, 2 }, { 2, 0 }, - { 0, 0 }, - }; - int glveridx = 0; - int i; - - m_Lock=0; - UpdatePending = false; - - const char *version = Args->CheckValue("-glversion"); - if (version != NULL) - { - double gl_version = strtod(version, NULL) + 0.01; - int vermaj = (int)gl_version; - int vermin = (int)(gl_version*10.0) % 10; - - while (glvers[glveridx][0] > vermaj || (glvers[glveridx][0] == vermaj && - glvers[glveridx][1] > vermin)) - { - glveridx++; - if (glvers[glveridx][0] == 0) - { - glveridx = 0; - break; - } - } - } - - FString caption; - caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime()); - - for ( ; glvers[glveridx][0] > 0; ++glveridx) - { - static_cast(Video)->SetupPixelFormat(false, 0, glvers[glveridx]); - - Screen = SDL_CreateWindow (caption, - SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), - SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), - width, height, (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)|SDL_WINDOW_OPENGL - ); - if (Screen != NULL) - { - GLContext = SDL_GL_CreateContext(Screen); - if (GLContext != NULL) - { - m_supportsGamma = -1 != SDL_GetWindowGammaRamp(Screen, - m_origGamma[0], m_origGamma[1], m_origGamma[2] - ); - return; - } - - SDL_DestroyWindow(Screen); - Screen = NULL; - } - } -} - -SDLGLFB::~SDLGLFB () -{ - if (Screen) - { - ResetGammaTable(); - - if (GLContext) - { - SDL_GL_DeleteContext(GLContext); - } - - SDL_DestroyWindow(Screen); - } -} - - - - -void SDLGLFB::InitializeState() -{ -} - -void SDLGLFB::SetGammaTable(uint16_t *tbl) -{ - if (m_supportsGamma) - { - SDL_SetWindowGammaRamp(Screen, &tbl[0], &tbl[256], &tbl[512]); - } -} - -void SDLGLFB::ResetGammaTable() -{ - if (m_supportsGamma) - { - SDL_SetWindowGammaRamp(Screen, m_origGamma[0], m_origGamma[1], m_origGamma[2]); - } -} - -bool SDLGLFB::Lock(bool buffered) -{ - m_Lock++; - Buffer = MemBuffer; - return true; -} - -bool SDLGLFB::Lock () -{ - return Lock(false); -} - -void SDLGLFB::Unlock () -{ - if (UpdatePending && m_Lock == 1) - { - Update (); - } - else if (--m_Lock <= 0) - { - m_Lock = 0; - } -} - -bool SDLGLFB::IsLocked () -{ - return m_Lock>0;// true; -} - -bool SDLGLFB::IsFullscreen () -{ - return (SDL_GetWindowFlags (Screen) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; -} - - -bool SDLGLFB::IsValid () -{ - return DFrameBuffer::IsValid() && Screen != NULL; -} - -void SDLGLFB::SetVSync( bool vsync ) -{ -#if defined (__APPLE__) - const GLint value = vsync ? 1 : 0; - CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval, &value ); -#else - if (vsync) - { - if (SDL_GL_SetSwapInterval(-1) == -1) - SDL_GL_SetSwapInterval(1); - } - else - { - SDL_GL_SetSwapInterval(0); - } -#endif -} - -void SDLGLFB::NewRefreshRate () -{ -} - -void SDLGLFB::SwapBuffers() -{ -#if !defined(__APPLE__) && !defined(__OpenBSD__) - if (vid_maxfps && !cl_capfps) - { - SEMAPHORE_WAIT(FPSLimitSemaphore) - } -#endif - - SDL_GL_SwapWindow (Screen); -} - -int SDLGLFB::GetClientWidth() -{ - int width = 0; - SDL_GL_GetDrawableSize(Screen, &width, nullptr); - return width; -} - -int SDLGLFB::GetClientHeight() -{ - int height = 0; - SDL_GL_GetDrawableSize(Screen, nullptr, &height); - return height; -} - -void SDLGLFB::ScaleCoordsFromWindow(int16_t &x, int16_t &y) -{ - int w, h; - SDL_GetWindowSize (Screen, &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); - } -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlvideo.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlvideo.cpp deleted file mode 100644 index 5eb8a7b..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlvideo.cpp +++ /dev/null @@ -1,580 +0,0 @@ -/* -** 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 "sdlvideo.h" -#include "swrenderer/r_swrenderer.h" -#include "version.h" - -#include - -#ifdef __APPLE__ -#include -#endif // __APPLE__ - -// 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 ----------------------------------------------- - -SDLFB::SDLFB (int width, int height, bool bgra, bool fullscreen, SDL_Window *oldwin) - : SDLBaseFB (width, height, bgra) -{ - int i; - - NeedPalUpdate = false; - NeedGammaUpdate = false; - UpdatePending = false; - NotPaletted = false; - FlashAmount = 0; - - if (oldwin) - { - // In some cases (Mac OS X fullscreen) SDL2 doesn't like having multiple windows which - // appears to inevitably happen while compositor animations are running. So lets try - // to reuse the existing window. - Screen = oldwin; - SDL_SetWindowSize (Screen, width, height); - SetFullscreen (fullscreen); - } - else - { - FString caption; - caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime()); - -#ifdef __ANDROID__ - SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); // Defaults to 24 which is not needed and fails on old Tegras -#endif - - Screen = SDL_CreateWindow (caption, - SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), SDL_WINDOWPOS_UNDEFINED_DISPLAY(vid_adapter), - width, height, (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)|SDL_WINDOW_RESIZABLE); - - if (Screen == NULL) - return; - } - - Renderer = NULL; - Texture = NULL; - ResetSDLRenderer (); - - 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 -} - - -SDLFB::~SDLFB () -{ - if (Renderer) - { - if (Texture) - SDL_DestroyTexture (Texture); - SDL_DestroyRenderer (Renderer); - } - - if(Screen) - { - SDL_DestroyWindow (Screen); - } -} - -bool SDLFB::IsValid () -{ - return DFrameBuffer::IsValid() && Screen != NULL; -} - -int SDLFB::GetPageCount () -{ - return 1; -} - -bool SDLFB::Lock (bool buffered) -{ - return DSimpleCanvas::Lock (); -} - -bool SDLFB::Relock () -{ - return DSimpleCanvas::Lock (); -} - -void SDLFB::Unlock () -{ - if (UpdatePending && LockCount == 1) - { - Update (); - } - else if (--LockCount <= 0) - { - Buffer = NULL; - LockCount = 0; - } -} - -void SDLFB::Update () -{ - if (LockCount != 1) - { - if (LockCount > 0) - { - UpdatePending = true; - --LockCount; - } - return; - } - - DrawRateStuff (); - -#if !defined(__APPLE__) && !defined(__OpenBSD__) - if(vid_maxfps && !cl_capfps) - { - SEMAPHORE_WAIT(FPSLimitSemaphore) - } -#endif - - Buffer = NULL; - LockCount = 0; - UpdatePending = false; - - BlitCycles.Reset(); - SDLFlipCycles.Reset(); - BlitCycles.Clock(); - - void *pixels; - int pitch; - if (UsingRenderer) - { - if (SDL_LockTexture (Texture, NULL, &pixels, &pitch)) - return; - } - else - { - if (SDL_LockSurface (Surface)) - return; - - pixels = Surface->pixels; - pitch = Surface->pitch; - } - - if (Bgra) - { - CopyWithGammaBgra(pixels, pitch, GammaTable[0], GammaTable[1], GammaTable[2], Flash, FlashAmount); - } - else if (NotPaletted) - { - GPfx.Convert (MemBuffer, Pitch, - pixels, pitch, Width, Height, - FRACUNIT, FRACUNIT, 0, 0); - } - else - { - if (pitch == Pitch) - { - memcpy (pixels, MemBuffer, Width*Height); - } - else - { - for (int y = 0; y < Height; ++y) - { - memcpy ((uint8_t *)pixels+y*pitch, MemBuffer+y*Pitch, Width); - } - } - } - - if (UsingRenderer) - { - SDL_UnlockTexture (Texture); - - SDLFlipCycles.Clock(); - SDL_RenderClear(Renderer); - SDL_RenderCopy(Renderer, Texture, NULL, NULL); - SDL_RenderPresent(Renderer); - SDLFlipCycles.Unclock(); - } - else - { - SDL_UnlockSurface (Surface); - - SDLFlipCycles.Clock(); - SDL_UpdateWindowSurface (Screen); - SDLFlipCycles.Unclock(); - } - - BlitCycles.Unclock(); - - if (NeedGammaUpdate) - { - bool Windowed = false; - NeedGammaUpdate = false; - CalcGamma ((Windowed || rgamma == 0.f) ? Gamma : (Gamma * rgamma), GammaTable[0]); - CalcGamma ((Windowed || ggamma == 0.f) ? Gamma : (Gamma * ggamma), GammaTable[1]); - CalcGamma ((Windowed || bgamma == 0.f) ? Gamma : (Gamma * bgamma), GammaTable[2]); - NeedPalUpdate = true; - } - - if (NeedPalUpdate) - { - NeedPalUpdate = false; - UpdateColors (); - } -} - -void SDLFB::UpdateColors () -{ - if (NotPaletted) - { - PalEntry palette[256]; - - for (int i = 0; i < 256; ++i) - { - palette[i].r = GammaTable[0][SourcePalette[i].r]; - palette[i].g = GammaTable[1][SourcePalette[i].g]; - palette[i].b = GammaTable[2][SourcePalette[i].b]; - } - if (FlashAmount) - { - DoBlending (palette, palette, - 256, GammaTable[0][Flash.r], GammaTable[1][Flash.g], GammaTable[2][Flash.b], - FlashAmount); - } - GPfx.SetPalette (palette); - } - else - { - SDL_Color colors[256]; - - for (int i = 0; i < 256; ++i) - { - colors[i].r = GammaTable[0][SourcePalette[i].r]; - colors[i].g = GammaTable[1][SourcePalette[i].g]; - colors[i].b = GammaTable[2][SourcePalette[i].b]; - } - if (FlashAmount) - { - DoBlending ((PalEntry *)colors, (PalEntry *)colors, - 256, GammaTable[2][Flash.b], GammaTable[1][Flash.g], GammaTable[0][Flash.r], - FlashAmount); - } - SDL_SetPaletteColors (Surface->format->palette, colors, 0, 256); - } -} - -PalEntry *SDLFB::GetPalette () -{ - return SourcePalette; -} - -void SDLFB::UpdatePalette () -{ - NeedPalUpdate = true; -} - -bool SDLFB::SetGamma (float gamma) -{ - Gamma = gamma; - NeedGammaUpdate = true; - return true; -} - -bool SDLFB::SetFlash (PalEntry rgb, int amount) -{ - Flash = rgb; - FlashAmount = amount; - NeedPalUpdate = true; - return true; -} - -void SDLFB::GetFlash (PalEntry &rgb, int &amount) -{ - rgb = Flash; - amount = FlashAmount; -} - -// Q: Should I gamma adjust the returned palette? -void SDLFB::GetFlashedPalette (PalEntry pal[256]) -{ - memcpy (pal, SourcePalette, 256*sizeof(PalEntry)); - if (FlashAmount) - { - DoBlending (pal, pal, 256, Flash.r, Flash.g, Flash.b, FlashAmount); - } -} - -void SDLFB::SetFullscreen (bool fullscreen) -{ - if (IsFullscreen() == fullscreen) - return; - - SDL_SetWindowFullscreen (Screen, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - if (!fullscreen) - { - // Restore proper window size - SDL_SetWindowSize (Screen, Width, Height); - } - - ResetSDLRenderer (); -} - -bool SDLFB::IsFullscreen () -{ - return (SDL_GetWindowFlags (Screen) & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; -} - -void SDLFB::ResetSDLRenderer () -{ - if (Renderer) - { - if (Texture) - SDL_DestroyTexture (Texture); - SDL_DestroyRenderer (Renderer); - } - - UsingRenderer = !vid_forcesurface; - if (UsingRenderer) - { -#ifdef __MOBILE__ - Renderer = SDL_CreateRenderer (Screen, -1,SDL_RENDERER_ACCELERATED); -#else - Renderer = SDL_CreateRenderer (Screen, -1,SDL_RENDERER_ACCELERATED|SDL_RENDERER_TARGETTEXTURE| - (vid_vsync ? SDL_RENDERER_PRESENTVSYNC : 0)); -#endif - - - if (!Renderer) - return; - - SDL_SetRenderDrawColor(Renderer, 0, 0, 0, 255); - - Uint32 fmt; - if (Bgra) - { - fmt = SDL_PIXELFORMAT_ARGB8888; - } - else - { - switch (vid_displaybits) - { - default: fmt = SDL_PIXELFORMAT_ARGB8888; break; - case 30: fmt = SDL_PIXELFORMAT_ARGB2101010; break; - case 24: fmt = SDL_PIXELFORMAT_RGB888; break; - case 16: fmt = SDL_PIXELFORMAT_RGB565; break; - case 15: fmt = SDL_PIXELFORMAT_ARGB1555; break; - } - } - Texture = SDL_CreateTexture (Renderer, fmt, SDL_TEXTUREACCESS_STREAMING, Width, Height); - - { - NotPaletted = true; - - Uint32 format; - SDL_QueryTexture(Texture, &format, NULL, NULL, NULL); - - Uint32 Rmask, Gmask, Bmask, Amask; - int bpp; - SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); - GPfx.SetFormat (bpp, Rmask, Gmask, Bmask); - } - } - else - { - Surface = SDL_GetWindowSurface (Screen); - - if (Surface->format->palette == NULL) - { - NotPaletted = true; - GPfx.SetFormat (Surface->format->BitsPerPixel, Surface->format->Rmask, Surface->format->Gmask, Surface->format->Bmask); - } - else - NotPaletted = false; - } - - // In fullscreen, set logical size according to animorphic ratio. - // Windowed modes are rendered to fill the window (usually 1:1) - if (IsFullscreen ()) - { - int w, h; - SDL_GetWindowSize (Screen, &w, &h); - ScaleWithAspect (w, h, Width, Height); -#ifndef __MOBILE__ - SDL_RenderSetLogicalSize (Renderer, w, h); -#endif - } -} - -void SDLFB::SetVSync (bool vsync) -{ -#ifdef __APPLE__ - if (CGLContextObj context = CGLGetCurrentContext()) - { - // Apply vsync for native backend only (where OpenGL context is set) - const GLint value = vsync ? 1 : 0; - CGLSetParameter(context, kCGLCPSwapInterval, &value); - } -#else - ResetSDLRenderer (); -#endif // __APPLE__ -} - -void SDLFB::ScaleCoordsFromWindow(int16_t &x, int16_t &y) -{ - int w, h; - SDL_GetWindowSize (Screen, &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); - } -} - -ADD_STAT (blit) -{ - FString out; - out.Format ("blit=%04.1f ms flip=%04.1f ms", - BlitCycles.TimeMS(), SDLFlipCycles.TimeMS()); - return out; -} - -// each platform has its own specific version of this function. -void I_SetWindowTitle(const char* caption) -{ - auto Screen = static_cast(screen)->GetSDLWindow(); - if (caption) - SDL_SetWindowTitle(static_cast(screen)->GetSDLWindow(), caption); - else - { - FString default_caption; - default_caption.Format(GAMESIG " %s (%s)", GetVersionString(), GetGitTime()); - SDL_SetWindowTitle(static_cast(screen)->GetSDLWindow(), default_caption); - } -} - diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlvideo.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlvideo.h deleted file mode 100644 index 31a168a..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/sdlvideo.h +++ /dev/null @@ -1,60 +0,0 @@ -#include "hardware.h" -#include "v_video.h" -#include "sdlglvideo.h" - -class SDLFB : public SDLBaseFB -{ - typedef SDLBaseFB Super; -public: - SDLFB(int width, int height, bool bgra, bool fullscreen, SDL_Window *oldwin); - ~SDLFB(); - - 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 SDLGLVideo; - - 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(); - - SDLFB() {} -}; diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/st_start.cpp b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/st_start.cpp deleted file mode 100644 index feb19b8..0000000 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/posix/sdl/st_start.cpp +++ /dev/null @@ -1,382 +0,0 @@ -/* -** 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 -#include -#include -#include - -#include "st_start.h" -#include "doomdef.h" -#include "i_system.h" -#include "c_cvars.h" -#include "atterm.h" - -#ifdef __ANDROID__ -#include -#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); -} diff --git a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/sound/opnmidi/opnbank.h b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/sound/opnmidi/opnbank.h index 0e005a3..39df8c5 100644 --- a/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/sound/opnmidi/opnbank.h +++ b/Projects/Android/jni/gzdoom-g3.3mgw_mobile/src/sound/opnmidi/opnbank.h @@ -27,18 +27,6 @@ #include #include -#ifdef ADLMIDI_buildAsApp -#include -class MutexType -{ - SDL_mutex* mut; -public: - MutexType() : mut(SDL_CreateMutex()) { } - ~MutexType() { SDL_DestroyMutex(mut); } - void Lock() { SDL_mutexP(mut); } - void Unlock() { SDL_mutexV(mut); } -}; -#endif enum { opnNoteOnMaxTime = 40000 };