2022-11-12 02:07:24 +00:00
2014-03-15 16:59:03 +00:00
// Emacs style mode select -*- C++ -*-
2018-11-01 18:47:19 +00:00
// SONIC ROBO BLAST 2
2014-03-15 16:59:03 +00:00
//-----------------------------------------------------------------------------
//
// Copyright (C) 1993-1996 by id Software, Inc.
// Portions Copyright (C) 1998-2000 by DooM Legacy Team.
2022-03-03 19:24:46 +00:00
// Copyright (C) 2014-2022 by Sonic Team Junior.
2014-03-15 16:59:03 +00:00
//
// 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 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//-----------------------------------------------------------------------------
/// \file
/// \brief SRB2 graphics stuff for SDL
# include <stdlib.h>
# include <signal.h>
# ifdef _MSC_VER
# pragma warning(disable : 4214 4244)
# endif
2014-07-25 23:10:24 +00:00
# ifdef HAVE_SDL
2016-05-22 03:53:04 +00:00
# define _MATH_DEFINES_DEFINED
2014-03-15 16:59:03 +00:00
# include "SDL.h"
# ifdef _MSC_VER
2019-12-05 15:51:55 +00:00
# include <windows.h>
2014-03-15 16:59:03 +00:00
# pragma warning(default : 4214 4244)
# endif
# ifdef HAVE_TTF
# include "i_ttf.h"
# endif
# ifdef HAVE_IMAGE
# include "SDL_image.h"
2020-11-15 04:52:55 +00:00
# elif defined (__unix__) || (!defined(__APPLE__) && defined (UNIXCOMMON)) // Windows & Mac don't need this, as SDL will do it for us.
2018-08-10 21:08:39 +00:00
# define LOAD_XPM //I want XPM!
# include "IMG_xpm.c" //Alam: I don't want to add SDL_Image.dll/so
# define HAVE_IMAGE //I have SDL_Image, sortof
2014-03-15 16:59:03 +00:00
# endif
# ifdef HAVE_IMAGE
# include "SDL_icon.xpm"
# endif
# include "../doomdef.h"
2017-09-16 19:26:04 +00:00
# ifdef _WIN32
2014-03-15 16:59:03 +00:00
# include "SDL_syswm.h"
# endif
# include "../doomstat.h"
# include "../i_system.h"
# include "../v_video.h"
# include "../m_argv.h"
# include "../m_menu.h"
# include "../d_main.h"
# include "../s_sound.h"
2023-01-27 01:26:28 +00:00
# include "../i_joy.h"
2014-03-15 16:59:03 +00:00
# include "../st_stuff.h"
2020-01-01 12:29:07 +00:00
# include "../hu_stuff.h"
2014-03-15 16:59:03 +00:00
# include "../g_game.h"
# include "../i_video.h"
# include "../console.h"
# include "../command.h"
2019-09-08 21:27:35 +00:00
# include "../r_main.h"
2021-08-18 18:58:13 +00:00
# include "../lua_script.h"
# include "../lua_libs.h"
2020-03-15 15:47:55 +00:00
# include "../lua_hook.h"
2014-03-15 16:59:03 +00:00
# include "sdlmain.h"
# ifdef HWRENDER
# include "../hardware/hw_main.h"
# include "../hardware/hw_drv.h"
// For dynamic referencing of HW rendering functions
# include "hwsym_sdl.h"
# include "ogl_sdl.h"
# endif
// maximum number of windowed modes (see windowedModes[][])
2014-09-01 00:59:41 +00:00
# define MAXWINMODES (18)
2014-03-15 16:59:03 +00:00
/** \brief
*/
static INT32 numVidModes = - 1 ;
/** \brief
*/
static char vidModeName [ 33 ] [ 32 ] ; // allow 33 different modes
2020-01-27 04:57:55 +00:00
rendermode_t rendermode = render_soft ;
2020-08-15 01:27:16 +00:00
rendermode_t chosenrendermode = render_none ; // set by command line arguments
2014-03-15 16:59:03 +00:00
boolean highcolor = false ;
// synchronize page flipping with screen refresh
2020-10-07 06:04:23 +00:00
consvar_t cv_vidwait = CVAR_INIT ( " vid_wait " , " On " , CV_SAVE , CV_OnOff , NULL ) ;
static consvar_t cv_stretch = CVAR_INIT ( " stretch " , " Off " , CV_SAVE | CV_NOSHOWHELP , CV_OnOff , NULL ) ;
static consvar_t cv_alwaysgrabmouse = CVAR_INIT ( " alwaysgrabmouse " , " Off " , CV_SAVE , CV_OnOff , NULL ) ;
2014-03-15 16:59:03 +00:00
UINT8 graphics_started = 0 ; // Is used in console.c and screen.c
// To disable fullscreen at startup; is set in VID_PrepareModeList
boolean allow_fullscreen = false ;
static SDL_bool disable_fullscreen = SDL_FALSE ;
# define USE_FULLSCREEN (disable_fullscreen||!allow_fullscreen)?0:cv_fullscreen.value
static SDL_bool disable_mouse = SDL_FALSE ;
2014-07-26 07:06:00 +00:00
# define USE_MOUSEINPUT (!disable_mouse && cv_usemouse.value && havefocus)
2014-03-15 16:59:03 +00:00
# define MOUSE_MENU false //(!disable_mouse && cv_usemouse.value && menuactive && !USE_FULLSCREEN)
# define MOUSEBUTTONS_MAX MOUSEBUTTONS
// first entry in the modelist which is not bigger than MAXVIDWIDTHxMAXVIDHEIGHT
static INT32 firstEntry = 0 ;
2017-08-21 20:38:29 +00:00
// Total mouse motion X/Y offsets
static INT32 mousemovex = 0 , mousemovey = 0 ;
2014-03-15 16:59:03 +00:00
// SDL vars
static SDL_Surface * vidSurface = NULL ;
static SDL_Surface * bufSurface = NULL ;
static SDL_Surface * icoSurface = NULL ;
static SDL_Color localPalette [ 256 ] ;
2014-07-26 07:06:00 +00:00
#if 0
2014-03-15 16:59:03 +00:00
static SDL_Rect * * modeList = NULL ;
static Uint8 BitsPerPixel = 16 ;
# endif
2014-11-14 00:06:38 +00:00
Uint16 realwidth = BASEVIDWIDTH ;
Uint16 realheight = BASEVIDHEIGHT ;
2014-03-15 16:59:03 +00:00
static SDL_bool mousegrabok = SDL_TRUE ;
2016-06-07 19:54:08 +00:00
static SDL_bool wrapmouseok = SDL_FALSE ;
# define HalfWarpMouse(x,y) if (wrapmouseok) SDL_WarpMouseInWindow(window, (Uint16)(x / 2),(Uint16)(y / 2))
2014-03-15 16:59:03 +00:00
static SDL_bool videoblitok = SDL_FALSE ;
static SDL_bool exposevideo = SDL_FALSE ;
2014-07-26 07:06:00 +00:00
static SDL_bool usesdl2soft = SDL_FALSE ;
static SDL_bool borderlesswindow = SDL_FALSE ;
// SDL2 vars
SDL_Window * window ;
SDL_Renderer * renderer ;
static SDL_Texture * texture ;
static SDL_bool havefocus = SDL_TRUE ;
static const char * fallback_resolution_name = " Fallback " ;
2014-03-15 16:59:03 +00:00
// windowed video modes from which to choose from.
static INT32 windowedModes [ MAXWINMODES ] [ 2 ] =
{
{ 1920 , 1200 } , // 1.60,6.00
2014-07-26 07:06:00 +00:00
{ 1920 , 1080 } , // 1.66
2014-03-15 16:59:03 +00:00
{ 1680 , 1050 } , // 1.60,5.25
2014-09-01 00:59:41 +00:00
{ 1600 , 1200 } , // 1.33
2014-07-26 07:06:00 +00:00
{ 1600 , 900 } , // 1.66
{ 1366 , 768 } , // 1.66
2014-03-15 16:59:03 +00:00
{ 1440 , 900 } , // 1.60,4.50
2014-07-26 07:06:00 +00:00
{ 1280 , 1024 } , // 1.33?
2014-03-15 16:59:03 +00:00
{ 1280 , 960 } , // 1.33,4.00
{ 1280 , 800 } , // 1.60,4.00
2014-07-26 07:06:00 +00:00
{ 1280 , 720 } , // 1.66
2014-03-15 16:59:03 +00:00
{ 1152 , 864 } , // 1.33,3.60
{ 1024 , 768 } , // 1.33,3.20
{ 800 , 600 } , // 1.33,2.50
{ 640 , 480 } , // 1.33,2.00
{ 640 , 400 } , // 1.60,2.00
{ 320 , 240 } , // 1.33,1.00
{ 320 , 200 } , // 1.60,1.00
} ;
2014-07-26 07:06:00 +00:00
static void Impl_VideoSetupSDLBuffer ( void ) ;
static void Impl_VideoSetupBuffer ( void ) ;
static SDL_bool Impl_CreateWindow ( SDL_bool fullscreen ) ;
2017-06-25 19:22:01 +00:00
//static void Impl_SetWindowName(const char *title);
2014-07-26 07:06:00 +00:00
static void Impl_SetWindowIcon ( void ) ;
2020-02-16 01:23:05 +00:00
static void SDLSetMode ( INT32 width , INT32 height , SDL_bool fullscreen , SDL_bool reposition )
2014-03-15 16:59:03 +00:00
{
2014-07-26 07:06:00 +00:00
static SDL_bool wasfullscreen = SDL_FALSE ;
Uint32 rmask ;
Uint32 gmask ;
Uint32 bmask ;
Uint32 amask ;
int bpp = 16 ;
int sw_texture_format = SDL_PIXELFORMAT_ABGR8888 ;
realwidth = vid . width ;
realheight = vid . height ;
if ( window )
2014-03-15 16:59:03 +00:00
{
2014-07-26 07:06:00 +00:00
if ( fullscreen )
{
wasfullscreen = SDL_TRUE ;
SDL_SetWindowFullscreen ( window , SDL_WINDOW_FULLSCREEN_DESKTOP ) ;
}
2017-05-15 15:35:32 +00:00
else // windowed mode
2014-07-26 07:06:00 +00:00
{
2017-05-15 15:35:32 +00:00
if ( wasfullscreen )
{
wasfullscreen = SDL_FALSE ;
SDL_SetWindowFullscreen ( window , 0 ) ;
}
2014-07-26 07:06:00 +00:00
// Reposition window only in windowed mode
SDL_SetWindowSize ( window , width , height ) ;
2020-02-16 01:23:05 +00:00
if ( reposition )
{
SDL_SetWindowPosition ( window ,
SDL_WINDOWPOS_CENTERED_DISPLAY ( SDL_GetWindowDisplayIndex ( window ) ) ,
SDL_WINDOWPOS_CENTERED_DISPLAY ( SDL_GetWindowDisplayIndex ( window ) )
) ;
}
2014-07-26 07:06:00 +00:00
}
}
else
{
Impl_CreateWindow ( fullscreen ) ;
wasfullscreen = fullscreen ;
SDL_SetWindowSize ( window , width , height ) ;
if ( fullscreen )
{
SDL_SetWindowFullscreen ( window , SDL_WINDOW_FULLSCREEN_DESKTOP ) ;
}
}
2016-01-11 14:51:55 +00:00
# ifdef HWRENDER
2014-07-26 07:06:00 +00:00
if ( rendermode = = render_opengl )
{
OglSdlSurface ( vid . width , vid . height ) ;
}
2016-01-11 14:51:55 +00:00
# endif
2014-07-26 07:06:00 +00:00
if ( rendermode = = render_soft )
{
SDL_RenderClear ( renderer ) ;
SDL_RenderSetLogicalSize ( renderer , width , height ) ;
// Set up Texture
realwidth = width ;
realheight = height ;
if ( texture ! = NULL )
{
SDL_DestroyTexture ( texture ) ;
}
if ( ! usesdl2soft )
{
sw_texture_format = SDL_PIXELFORMAT_RGB565 ;
}
else
{
bpp = 32 ;
sw_texture_format = SDL_PIXELFORMAT_RGBA8888 ;
}
texture = SDL_CreateTexture ( renderer , sw_texture_format , SDL_TEXTUREACCESS_STREAMING , width , height ) ;
// Set up SW surface
if ( vidSurface ! = NULL )
{
SDL_FreeSurface ( vidSurface ) ;
}
2016-05-10 22:20:14 +00:00
if ( vid . buffer )
{
free ( vid . buffer ) ;
vid . buffer = NULL ;
}
2014-07-26 07:06:00 +00:00
SDL_PixelFormatEnumToMasks ( sw_texture_format , & bpp , & rmask , & gmask , & bmask , & amask ) ;
vidSurface = SDL_CreateRGBSurface ( 0 , width , height , bpp , rmask , gmask , bmask , amask ) ;
2014-03-15 16:59:03 +00:00
}
}
2014-11-13 21:19:39 +00:00
static INT32 Impl_SDL_Scancode_To_Keycode ( SDL_Scancode code )
{
if ( code > = SDL_SCANCODE_A & & code < = SDL_SCANCODE_Z )
{
// get lowercase ASCII
return code - SDL_SCANCODE_A + ' a ' ;
}
if ( code > = SDL_SCANCODE_1 & & code < = SDL_SCANCODE_9 )
{
return code - SDL_SCANCODE_1 + ' 1 ' ;
}
else if ( code = = SDL_SCANCODE_0 )
{
return ' 0 ' ;
}
2015-01-01 07:09:23 +00:00
if ( code > = SDL_SCANCODE_F1 & & code < = SDL_SCANCODE_F10 )
2014-11-13 21:19:39 +00:00
{
return KEY_F1 + ( code - SDL_SCANCODE_F1 ) ;
}
switch ( code )
{
2016-11-23 17:08:37 +00:00
// F11 and F12 are separated from the rest of the function keys
case SDL_SCANCODE_F11 : return KEY_F11 ;
case SDL_SCANCODE_F12 : return KEY_F12 ;
case SDL_SCANCODE_KP_0 : return KEY_KEYPAD0 ;
case SDL_SCANCODE_KP_1 : return KEY_KEYPAD1 ;
case SDL_SCANCODE_KP_2 : return KEY_KEYPAD2 ;
case SDL_SCANCODE_KP_3 : return KEY_KEYPAD3 ;
case SDL_SCANCODE_KP_4 : return KEY_KEYPAD4 ;
case SDL_SCANCODE_KP_5 : return KEY_KEYPAD5 ;
case SDL_SCANCODE_KP_6 : return KEY_KEYPAD6 ;
case SDL_SCANCODE_KP_7 : return KEY_KEYPAD7 ;
case SDL_SCANCODE_KP_8 : return KEY_KEYPAD8 ;
case SDL_SCANCODE_KP_9 : return KEY_KEYPAD9 ;
case SDL_SCANCODE_RETURN : return KEY_ENTER ;
case SDL_SCANCODE_ESCAPE : return KEY_ESCAPE ;
case SDL_SCANCODE_BACKSPACE : return KEY_BACKSPACE ;
case SDL_SCANCODE_TAB : return KEY_TAB ;
case SDL_SCANCODE_SPACE : return KEY_SPACE ;
case SDL_SCANCODE_MINUS : return KEY_MINUS ;
case SDL_SCANCODE_EQUALS : return KEY_EQUALS ;
case SDL_SCANCODE_LEFTBRACKET : return ' [ ' ;
case SDL_SCANCODE_RIGHTBRACKET : return ' ] ' ;
case SDL_SCANCODE_BACKSLASH : return ' \\ ' ;
case SDL_SCANCODE_NONUSHASH : return ' # ' ;
case SDL_SCANCODE_SEMICOLON : return ' ; ' ;
case SDL_SCANCODE_APOSTROPHE : return ' \' ' ;
case SDL_SCANCODE_GRAVE : return ' ` ' ;
case SDL_SCANCODE_COMMA : return ' , ' ;
case SDL_SCANCODE_PERIOD : return ' . ' ;
case SDL_SCANCODE_SLASH : return ' / ' ;
case SDL_SCANCODE_CAPSLOCK : return KEY_CAPSLOCK ;
case SDL_SCANCODE_PRINTSCREEN : return 0 ; // undefined?
case SDL_SCANCODE_SCROLLLOCK : return KEY_SCROLLLOCK ;
case SDL_SCANCODE_PAUSE : return KEY_PAUSE ;
case SDL_SCANCODE_INSERT : return KEY_INS ;
case SDL_SCANCODE_HOME : return KEY_HOME ;
case SDL_SCANCODE_PAGEUP : return KEY_PGUP ;
case SDL_SCANCODE_DELETE : return KEY_DEL ;
case SDL_SCANCODE_END : return KEY_END ;
case SDL_SCANCODE_PAGEDOWN : return KEY_PGDN ;
case SDL_SCANCODE_RIGHT : return KEY_RIGHTARROW ;
case SDL_SCANCODE_LEFT : return KEY_LEFTARROW ;
case SDL_SCANCODE_DOWN : return KEY_DOWNARROW ;
case SDL_SCANCODE_UP : return KEY_UPARROW ;
case SDL_SCANCODE_NUMLOCKCLEAR : return KEY_NUMLOCK ;
case SDL_SCANCODE_KP_DIVIDE : return KEY_KPADSLASH ;
case SDL_SCANCODE_KP_MULTIPLY : return ' * ' ; // undefined?
case SDL_SCANCODE_KP_MINUS : return KEY_MINUSPAD ;
case SDL_SCANCODE_KP_PLUS : return KEY_PLUSPAD ;
case SDL_SCANCODE_KP_ENTER : return KEY_ENTER ;
case SDL_SCANCODE_KP_PERIOD : return KEY_KPADDEL ;
case SDL_SCANCODE_NONUSBACKSLASH : return ' \\ ' ;
case SDL_SCANCODE_LSHIFT : return KEY_LSHIFT ;
case SDL_SCANCODE_RSHIFT : return KEY_RSHIFT ;
case SDL_SCANCODE_LCTRL : return KEY_LCTRL ;
case SDL_SCANCODE_RCTRL : return KEY_RCTRL ;
case SDL_SCANCODE_LALT : return KEY_LALT ;
case SDL_SCANCODE_RALT : return KEY_RALT ;
case SDL_SCANCODE_LGUI : return KEY_LEFTWIN ;
case SDL_SCANCODE_RGUI : return KEY_RIGHTWIN ;
default : break ;
2014-11-13 21:19:39 +00:00
}
2019-12-25 19:22:01 +00:00
2014-11-13 21:19:39 +00:00
return 0 ;
}
2020-01-18 19:18:20 +00:00
static boolean IgnoreMouse ( void )
{
if ( cv_alwaysgrabmouse . value )
return false ;
if ( menuactive )
return ! M_MouseNeeded ( ) ;
2020-04-24 16:33:35 +00:00
if ( paused | | con_destlines | | chat_on )
return true ;
2020-06-06 22:40:33 +00:00
if ( gamestate ! = GS_LEVEL & & gamestate ! = GS_INTERMISSION & &
gamestate ! = GS_CONTINUING & & gamestate ! = GS_CUTSCENE )
2020-01-18 19:18:20 +00:00
return true ;
2021-08-18 18:58:13 +00:00
if ( ! mousegrabbedbylua )
return true ;
2020-01-18 19:18:20 +00:00
return false ;
}
2019-03-30 05:00:47 +00:00
static void SDLdoGrabMouse ( void )
{
SDL_ShowCursor ( SDL_DISABLE ) ;
SDL_SetWindowGrab ( window , SDL_TRUE ) ;
if ( SDL_SetRelativeMouseMode ( SDL_TRUE ) = = 0 ) // already warps mouse if successful
wrapmouseok = SDL_TRUE ; // TODO: is wrapmouseok or HalfWarpMouse needed anymore?
}
2014-03-15 16:59:03 +00:00
static void SDLdoUngrabMouse ( void )
{
2018-12-24 03:05:09 +00:00
SDL_ShowCursor ( SDL_ENABLE ) ;
2014-07-26 07:06:00 +00:00
SDL_SetWindowGrab ( window , SDL_FALSE ) ;
2016-06-07 19:54:08 +00:00
wrapmouseok = SDL_FALSE ;
SDL_SetRelativeMouseMode ( SDL_FALSE ) ;
2014-03-15 16:59:03 +00:00
}
void SDLforceUngrabMouse ( void )
{
2014-07-26 07:06:00 +00:00
if ( SDL_WasInit ( SDL_INIT_VIDEO ) = = SDL_INIT_VIDEO & & window ! = NULL )
2020-01-01 23:47:20 +00:00
SDLdoUngrabMouse ( ) ;
2014-03-15 16:59:03 +00:00
}
2020-01-01 23:45:28 +00:00
void I_UpdateMouseGrab ( void )
{
if ( SDL_WasInit ( SDL_INIT_VIDEO ) = = SDL_INIT_VIDEO & & window ! = NULL
& & SDL_GetMouseFocus ( ) = = window & & SDL_GetKeyboardFocus ( ) = = window
2020-01-18 19:18:20 +00:00
& & USE_MOUSEINPUT & & ! IgnoreMouse ( ) )
2020-01-01 23:45:28 +00:00
SDLdoGrabMouse ( ) ;
}
2021-03-26 02:14:59 +00:00
void I_SetMouseGrab ( boolean grab )
{
if ( grab )
SDLdoGrabMouse ( ) ;
else
SDLdoUngrabMouse ( ) ;
}
2014-03-15 16:59:03 +00:00
static void VID_Command_NumModes_f ( void )
{
CONS_Printf ( M_GetText ( " %d video mode(s) available(s) \n " ) , VID_NumModes ( ) ) ;
}
2016-11-23 16:51:37 +00:00
// SDL2 doesn't have SDL_GetVideoSurface or a lot of the SDL_Surface flags that SDL 1.2 had
2014-03-15 16:59:03 +00:00
static void SurfaceInfo ( const SDL_Surface * infoSurface , const char * SurfaceText )
{
INT32 vfBPP ;
if ( ! infoSurface )
return ;
if ( ! SurfaceText )
SurfaceText = M_GetText ( " Unknown Surface " ) ;
vfBPP = infoSurface - > format ? infoSurface - > format - > BitsPerPixel : 0 ;
CONS_Printf ( " \x82 " " %s \n " , SurfaceText ) ;
CONS_Printf ( M_GetText ( " %ix%i at %i bit color \n " ) , infoSurface - > w , infoSurface - > h , vfBPP ) ;
2016-11-23 16:51:37 +00:00
if ( infoSurface - > flags & SDL_PREALLOC )
2014-03-15 16:59:03 +00:00
CONS_Printf ( " %s " , M_GetText ( " Uses preallocated memory \n " ) ) ;
else
CONS_Printf ( " %s " , M_GetText ( " Stored in system memory \n " ) ) ;
if ( infoSurface - > flags & SDL_RLEACCEL )
CONS_Printf ( " %s " , M_GetText ( " Colorkey RLE acceleration blit \n " ) ) ;
}
static void VID_Command_Info_f ( void )
{
2023-01-27 01:26:28 +00:00
#if 0
SDL2STUB ( ) ;
# else
#if 0
const SDL_VideoInfo * videoInfo ;
videoInfo = SDL_GetVideoInfo ( ) ; //Alam: Double-Check
if ( videoInfo )
{
CONS_Printf ( " %s " , M_GetText ( " Video Interface Capabilities: \n " ) ) ;
if ( videoInfo - > hw_available )
CONS_Printf ( " %s " , M_GetText ( " Hardware surfaces \n " ) ) ;
if ( videoInfo - > wm_available )
CONS_Printf ( " %s " , M_GetText ( " Window manager \n " ) ) ;
//UnusedBits1 :6
//UnusedBits2 :1
if ( videoInfo - > blit_hw )
CONS_Printf ( " %s " , M_GetText ( " Accelerated blits HW-2-HW \n " ) ) ;
if ( videoInfo - > blit_hw_CC )
CONS_Printf ( " %s " , M_GetText ( " Accelerated blits HW-2-HW with Colorkey \n " ) ) ;
if ( videoInfo - > wm_available )
CONS_Printf ( " %s " , M_GetText ( " Accelerated blits HW-2-HW with Alpha \n " ) ) ;
if ( videoInfo - > blit_sw )
{
CONS_Printf ( " %s " , M_GetText ( " Accelerated blits SW-2-HW \n " ) ) ;
if ( ! M_CheckParm ( " -noblit " ) ) videoblitok = SDL_TRUE ;
}
if ( videoInfo - > blit_sw_CC )
CONS_Printf ( " %s " , M_GetText ( " Accelerated blits SW-2-HW with Colorkey \n " ) ) ;
if ( videoInfo - > blit_sw_A )
CONS_Printf ( " %s " , M_GetText ( " Accelerated blits SW-2-HW with Alpha \n " ) ) ;
if ( videoInfo - > blit_fill )
CONS_Printf ( " %s " , M_GetText ( " Accelerated Color filling \n " ) ) ;
//UnusedBits3 :16
if ( videoInfo - > video_mem )
CONS_Printf ( M_GetText ( " There is %i KB of video memory \n " ) , videoInfo - > video_mem ) ;
else
CONS_Printf ( " %s " , M_GetText ( " There no video memory for SDL \n " ) ) ;
//*vfmt
}
# else
2014-07-26 07:06:00 +00:00
if ( ! M_CheckParm ( " -noblit " ) ) videoblitok = SDL_TRUE ;
2023-01-27 01:26:28 +00:00
# endif
2014-07-26 07:06:00 +00:00
SurfaceInfo ( bufSurface , M_GetText ( " Current Engine Mode " ) ) ;
2014-03-15 16:59:03 +00:00
SurfaceInfo ( vidSurface , M_GetText ( " Current Video Mode " ) ) ;
2023-01-27 01:26:28 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
static void VID_Command_ModeList_f ( void )
{
2014-09-01 00:15:08 +00:00
// List windowed modes
INT32 i = 0 ;
CONS_Printf ( " NOTE: Under SDL2, all modes are supported on all platforms. \n " ) ;
CONS_Printf ( " Under opengl, fullscreen only supports native desktop resolution. \n " ) ;
CONS_Printf ( " Under software, the mode is stretched up to desktop resolution. \n " ) ;
for ( i = 0 ; i < MAXWINMODES ; i + + )
2014-03-15 16:59:03 +00:00
{
2014-09-01 00:15:08 +00:00
CONS_Printf ( " %2d: %dx%d \n " , i , windowedModes [ i ] [ 0 ] , windowedModes [ i ] [ 1 ] ) ;
2014-03-15 16:59:03 +00:00
}
}
static void VID_Command_Mode_f ( void )
{
INT32 modenum ;
if ( COM_Argc ( ) ! = 2 )
{
CONS_Printf ( M_GetText ( " vid_mode <modenum> : set video mode, current video mode %i \n " ) , vid . modenum ) ;
return ;
}
modenum = atoi ( COM_Argv ( 1 ) ) ;
if ( modenum > = VID_NumModes ( ) )
CONS_Printf ( M_GetText ( " Video mode not present \n " ) ) ;
else
setmodeneeded = modenum + 1 ; // request vid mode change
}
2023-01-27 01:26:28 +00:00
static inline void SDLJoyRemap ( event_t * event )
{
( void ) event ;
}
static INT32 SDLJoyAxis ( const Sint16 axis , evtype_t which )
{
// -32768 to 32767
INT32 raxis = axis / 32 ;
if ( which = = ev_joystick )
{
if ( Joystick . bGamepadStyle )
{
// gamepad control type, on or off, live or die
if ( raxis < - ( JOYAXISRANGE / 2 ) )
raxis = - 1 ;
else if ( raxis > ( JOYAXISRANGE / 2 ) )
raxis = 1 ;
else
raxis = 0 ;
}
else
{
raxis = JoyInfo . scale ! = 1 ? ( ( raxis / JoyInfo . scale ) * JoyInfo . scale ) : raxis ;
# ifdef SDL_JDEADZONE
if ( - SDL_JDEADZONE < = raxis & & raxis < = SDL_JDEADZONE )
raxis = 0 ;
# endif
}
}
else if ( which = = ev_joystick2 )
{
if ( Joystick2 . bGamepadStyle )
{
// gamepad control type, on or off, live or die
if ( raxis < - ( JOYAXISRANGE / 2 ) )
raxis = - 1 ;
else if ( raxis > ( JOYAXISRANGE / 2 ) )
raxis = 1 ;
else raxis = 0 ;
}
else
{
raxis = JoyInfo2 . scale ! = 1 ? ( ( raxis / JoyInfo2 . scale ) * JoyInfo2 . scale ) : raxis ;
# ifdef SDL_JDEADZONE
if ( - SDL_JDEADZONE < = raxis & & raxis < = SDL_JDEADZONE )
raxis = 0 ;
# endif
}
}
return raxis ;
}
2014-07-26 07:06:00 +00:00
static void Impl_HandleWindowEvent ( SDL_WindowEvent evt )
{
2016-11-30 17:21:28 +00:00
static SDL_bool firsttimeonmouse = SDL_TRUE ;
2014-07-26 07:06:00 +00:00
static SDL_bool mousefocus = SDL_TRUE ;
static SDL_bool kbfocus = SDL_TRUE ;
switch ( evt . event )
{
case SDL_WINDOWEVENT_ENTER :
mousefocus = SDL_TRUE ;
break ;
case SDL_WINDOWEVENT_LEAVE :
mousefocus = SDL_FALSE ;
break ;
case SDL_WINDOWEVENT_FOCUS_GAINED :
kbfocus = SDL_TRUE ;
mousefocus = SDL_TRUE ;
break ;
case SDL_WINDOWEVENT_FOCUS_LOST :
kbfocus = SDL_FALSE ;
mousefocus = SDL_FALSE ;
break ;
case SDL_WINDOWEVENT_MAXIMIZED :
break ;
}
if ( mousefocus & & kbfocus )
{
2015-01-01 19:50:31 +00:00
// Tell game we got focus back, resume music if necessary
window_notinfocus = false ;
if ( ! paused )
2023-01-27 01:26:28 +00:00
S_ResumeAudio ( ) ; //resume it
2015-01-01 19:50:31 +00:00
2023-01-27 01:26:28 +00:00
if ( ! firsttimeonmouse )
{
if ( cv_usemouse . value ) I_StartupMouse ( ) ;
}
//else firsttimeonmouse = SDL_FALSE;
2019-03-30 05:00:47 +00:00
2020-01-18 19:18:20 +00:00
if ( USE_MOUSEINPUT & & ! IgnoreMouse ( ) )
2019-03-30 05:00:47 +00:00
SDLdoGrabMouse ( ) ;
2014-07-26 07:06:00 +00:00
}
else if ( ! mousefocus & & ! kbfocus )
{
2015-01-01 19:50:31 +00:00
// Tell game we lost focus, pause music
window_notinfocus = true ;
2023-01-27 01:26:28 +00:00
if ( ! cv_playmusicifunfocused . value )
2019-10-24 00:21:09 +00:00
S_PauseAudio ( ) ;
2023-01-27 01:26:28 +00:00
if ( ! cv_playsoundsifunfocused . value )
2019-10-24 00:21:09 +00:00
S_StopSounds ( ) ;
2015-01-01 19:50:31 +00:00
2016-11-30 17:21:28 +00:00
if ( ! disable_mouse )
2023-01-27 01:26:28 +00:00
{
2014-07-26 07:06:00 +00:00
SDLforceUngrabMouse ( ) ;
2023-01-27 01:26:28 +00:00
}
2014-07-26 07:06:00 +00:00
memset ( gamekeydown , 0 , NUMKEYS ) ; // TODO this is a scary memset
2016-11-30 17:21:28 +00:00
if ( MOUSE_MENU )
2023-01-27 01:26:28 +00:00
{
2014-07-26 07:06:00 +00:00
SDLdoUngrabMouse ( ) ;
2023-01-27 01:26:28 +00:00
}
2014-07-26 07:06:00 +00:00
}
2023-01-27 01:26:28 +00:00
2014-07-26 07:06:00 +00:00
}
static void Impl_HandleKeyboardEvent ( SDL_KeyboardEvent evt , Uint32 type )
{
event_t event ;
if ( type = = SDL_KEYUP )
2023-01-27 01:26:28 +00:00
{
2014-07-26 07:06:00 +00:00
event . type = ev_keyup ;
2023-01-27 01:26:28 +00:00
}
2014-07-26 07:06:00 +00:00
else if ( type = = SDL_KEYDOWN )
2023-01-27 01:26:28 +00:00
{
2014-07-26 07:06:00 +00:00
event . type = ev_keydown ;
2023-01-27 01:26:28 +00:00
}
2014-07-26 07:06:00 +00:00
else
2023-01-27 01:26:28 +00:00
{
2014-07-26 07:06:00 +00:00
return ;
2023-01-27 01:26:28 +00:00
}
2021-08-14 21:42:39 +00:00
event . key = Impl_SDL_Scancode_To_Keycode ( evt . keysym . scancode ) ;
2021-08-14 18:33:20 +00:00
event . repeated = ( evt . repeat ! = 0 ) ;
2023-01-27 01:26:28 +00:00
if ( event . key ) D_PostEvent ( & event ) ;
2014-07-26 07:06:00 +00:00
}
static void Impl_HandleMouseMotionEvent ( SDL_MouseMotionEvent evt )
{
2020-01-01 23:38:43 +00:00
static boolean firstmove = true ;
2014-11-13 07:04:17 +00:00
if ( USE_MOUSEINPUT )
2014-07-26 07:06:00 +00:00
{
2020-01-18 19:18:20 +00:00
if ( ( SDL_GetMouseFocus ( ) ! = window & & SDL_GetKeyboardFocus ( ) ! = window ) | | ( IgnoreMouse ( ) & & ! firstmove ) )
2014-11-13 07:04:17 +00:00
{
2016-11-30 17:21:28 +00:00
SDLdoUngrabMouse ( ) ;
2020-01-01 23:38:43 +00:00
firstmove = false ;
2014-11-13 07:04:17 +00:00
return ;
}
2014-11-12 00:55:07 +00:00
2017-08-21 20:38:29 +00:00
// If using relative mouse mode, don't post an event_t just now,
// add on the offsets so we can make an overall event later.
2016-06-07 21:16:11 +00:00
if ( SDL_GetRelativeMouseMode ( ) )
2014-11-13 07:04:17 +00:00
{
2017-08-19 20:39:04 +00:00
if ( SDL_GetMouseFocus ( ) = = window & & SDL_GetKeyboardFocus ( ) = = window )
{
2021-03-26 02:14:59 +00:00
mousemovex + = evt . xrel ;
mousemovey + = evt . yrel ;
2017-08-19 20:39:04 +00:00
SDL_SetWindowGrab ( window , SDL_TRUE ) ;
}
2020-01-01 23:38:43 +00:00
firstmove = false ;
2014-11-13 07:04:17 +00:00
return ;
}
2017-08-19 20:39:04 +00:00
2017-08-22 21:53:18 +00:00
// If the event is from warping the pointer to middle
2017-08-21 20:38:29 +00:00
// of the screen then ignore it.
2017-08-19 20:39:04 +00:00
if ( ( evt . x = = realwidth / 2 ) & & ( evt . y = = realheight / 2 ) )
2014-11-13 07:04:17 +00:00
{
2020-01-01 23:38:43 +00:00
firstmove = false ;
2014-11-13 07:04:17 +00:00
return ;
}
2014-07-26 07:06:00 +00:00
2017-08-22 21:53:18 +00:00
// Don't send an event_t if not in relative mouse mode anymore,
// just grab and set relative mode
// this fixes the stupid camera jerk on mouse entering bug
// -- Monster Iestyn
2014-11-13 07:04:17 +00:00
if ( SDL_GetMouseFocus ( ) = = window & & SDL_GetKeyboardFocus ( ) = = window )
{
2019-03-30 05:00:47 +00:00
SDLdoGrabMouse ( ) ;
2014-11-13 07:04:17 +00:00
}
2014-07-26 07:06:00 +00:00
}
2020-01-01 23:38:43 +00:00
firstmove = false ;
2014-07-26 07:06:00 +00:00
}
static void Impl_HandleMouseButtonEvent ( SDL_MouseButtonEvent evt , Uint32 type )
{
event_t event ;
SDL_memset ( & event , 0 , sizeof ( event_t ) ) ;
2018-05-28 20:29:46 +00:00
// Ignore the event if the mouse is not actually focused on the window.
// This can happen if you used the mouse to restore keyboard focus;
// this apparently makes a mouse button down event but not a mouse button up event,
// resulting in whatever key was pressed down getting "stuck" if we don't ignore it.
// -- Monster Iestyn (28/05/18)
2020-01-18 19:18:20 +00:00
if ( SDL_GetMouseFocus ( ) ! = window | | IgnoreMouse ( ) )
2018-05-28 20:29:46 +00:00
return ;
2023-01-27 01:26:28 +00:00
/// \todo inputEvent.button.which
2014-07-26 07:06:00 +00:00
if ( USE_MOUSEINPUT )
{
if ( type = = SDL_MOUSEBUTTONUP )
2023-01-27 01:26:28 +00:00
{
2014-07-26 07:06:00 +00:00
event . type = ev_keyup ;
2023-01-27 01:26:28 +00:00
}
2014-07-26 07:06:00 +00:00
else if ( type = = SDL_MOUSEBUTTONDOWN )
2022-11-14 03:37:08 +00:00
{
2023-01-27 01:26:28 +00:00
event . type = ev_keydown ;
}
else return ;
if ( evt . button = = SDL_BUTTON_MIDDLE )
2022-11-14 03:37:08 +00:00
event . key = KEY_MOUSE1 + 2 ;
2023-01-27 01:26:28 +00:00
else if ( evt . button = = SDL_BUTTON_RIGHT )
event . key = KEY_MOUSE1 + 1 ;
else if ( evt . button = = SDL_BUTTON_LEFT )
event . key = KEY_MOUSE1 ;
else if ( evt . button = = SDL_BUTTON_X1 )
2021-08-14 21:42:39 +00:00
event . key = KEY_MOUSE1 + 3 ;
2023-01-27 01:26:28 +00:00
else if ( evt . button = = SDL_BUTTON_X2 )
2021-08-14 21:42:39 +00:00
event . key = KEY_MOUSE1 + 4 ;
2023-01-27 01:26:28 +00:00
if ( event . type = = ev_keyup | | event . type = = ev_keydown )
{
D_PostEvent ( & event ) ;
2014-07-26 07:06:00 +00:00
}
}
}
static void Impl_HandleMouseWheelEvent ( SDL_MouseWheelEvent evt )
{
event_t event ;
SDL_memset ( & event , 0 , sizeof ( event_t ) ) ;
if ( evt . y > 0 )
{
2021-08-14 21:42:39 +00:00
event . key = KEY_MOUSEWHEELUP ;
2014-07-26 07:06:00 +00:00
event . type = ev_keydown ;
}
if ( evt . y < 0 )
{
2021-08-14 21:42:39 +00:00
event . key = KEY_MOUSEWHEELDOWN ;
2014-07-26 07:06:00 +00:00
event . type = ev_keydown ;
}
if ( evt . y = = 0 )
{
2021-08-14 21:42:39 +00:00
event . key = 0 ;
2014-07-26 07:06:00 +00:00
event . type = ev_keyup ;
}
if ( event . type = = ev_keyup | | event . type = = ev_keydown )
{
D_PostEvent ( & event ) ;
}
}
2023-01-27 01:26:28 +00:00
static void Impl_HandleJoystickAxisEvent ( SDL_JoyAxisEvent evt )
{
event_t event ;
SDL_JoystickID joyid [ 2 ] ;
// Determine the Joystick IDs for each current open joystick
joyid [ 0 ] = SDL_JoystickInstanceID ( JoyInfo . dev ) ;
joyid [ 1 ] = SDL_JoystickInstanceID ( JoyInfo2 . dev ) ;
evt . axis + + ;
event . key = event . x = event . y = INT32_MAX ;
if ( evt . which = = joyid [ 0 ] )
{
event . type = ev_joystick ;
}
else if ( evt . which = = joyid [ 1 ] )
{
event . type = ev_joystick2 ;
}
else return ;
//axis
if ( evt . axis > JOYAXISSET * 2 )
return ;
//vaule
if ( evt . axis % 2 )
{
event . key = evt . axis / 2 ;
event . x = SDLJoyAxis ( evt . value , event . type ) ;
}
else
{
evt . axis - - ;
event . key = evt . axis / 2 ;
event . y = SDLJoyAxis ( evt . value , event . type ) ;
}
D_PostEvent ( & event ) ;
}
#if 0
static void Impl_HandleJoystickHatEvent ( SDL_JoyHatEvent evt )
{
event_t event ;
SDL_JoystickID joyid [ 2 ] ;
// Determine the Joystick IDs for each current open joystick
joyid [ 0 ] = SDL_JoystickInstanceID ( JoyInfo . dev ) ;
joyid [ 1 ] = SDL_JoystickInstanceID ( JoyInfo2 . dev ) ;
if ( evt . hat > = JOYHATS )
return ; // ignore hats with too high an index
if ( evt . which = = joyid [ 0 ] )
{
event . key = KEY_HAT1 + ( evt . hat * 4 ) ;
}
else if ( evt . which = = joyid [ 1 ] )
{
event . key = KEY_2HAT1 + ( evt . hat * 4 ) ;
}
else return ;
// NOTE: UNFINISHED
}
# endif
static void Impl_HandleJoystickButtonEvent ( SDL_JoyButtonEvent evt , Uint32 type )
{
event_t event ;
SDL_JoystickID joyid [ 2 ] ;
// Determine the Joystick IDs for each current open joystick
joyid [ 0 ] = SDL_JoystickInstanceID ( JoyInfo . dev ) ;
joyid [ 1 ] = SDL_JoystickInstanceID ( JoyInfo2 . dev ) ;
if ( evt . which = = joyid [ 0 ] )
{
event . key = KEY_JOY1 ;
}
else if ( evt . which = = joyid [ 1 ] )
{
event . key = KEY_2JOY1 ;
}
else return ;
if ( type = = SDL_JOYBUTTONUP )
{
event . type = ev_keyup ;
}
else if ( type = = SDL_JOYBUTTONDOWN )
{
event . type = ev_keydown ;
}
else return ;
if ( evt . button < JOYBUTTONS )
{
event . key + = evt . button ;
}
else return ;
SDLJoyRemap ( & event ) ;
if ( event . type ! = ev_console ) D_PostEvent ( & event ) ;
}
2014-03-15 16:59:03 +00:00
void I_GetEvent ( void )
{
2014-07-26 07:06:00 +00:00
SDL_Event evt ;
2014-11-13 09:51:33 +00:00
// We only want the first motion event,
// otherwise we'll end up catching the warp back to center.
2017-08-19 20:39:04 +00:00
//int mouseMotionOnce = 0;
2014-07-26 07:06:00 +00:00
if ( ! graphics_started )
{
return ;
}
2017-08-21 20:38:29 +00:00
mousemovex = mousemovey = 0 ;
2014-07-26 07:06:00 +00:00
while ( SDL_PollEvent ( & evt ) )
{
switch ( evt . type )
{
case SDL_WINDOWEVENT :
Impl_HandleWindowEvent ( evt . window ) ;
break ;
case SDL_KEYUP :
case SDL_KEYDOWN :
Impl_HandleKeyboardEvent ( evt . key , evt . type ) ;
break ;
case SDL_MOUSEMOTION :
2017-08-19 20:39:04 +00:00
//if (!mouseMotionOnce)
Impl_HandleMouseMotionEvent ( evt . motion ) ;
//mouseMotionOnce = 1;
2014-07-26 07:06:00 +00:00
break ;
case SDL_MOUSEBUTTONUP :
case SDL_MOUSEBUTTONDOWN :
Impl_HandleMouseButtonEvent ( evt . button , evt . type ) ;
break ;
case SDL_MOUSEWHEEL :
Impl_HandleMouseWheelEvent ( evt . wheel ) ;
break ;
2023-01-27 01:26:28 +00:00
case SDL_JOYAXISMOTION :
Impl_HandleJoystickAxisEvent ( evt . jaxis ) ;
break ;
#if 0
case SDL_JOYHATMOTION :
Impl_HandleJoystickHatEvent ( evt . jhat )
2018-12-02 17:12:05 +00:00
break ;
2023-01-27 01:26:28 +00:00
# endif
case SDL_JOYBUTTONUP :
case SDL_JOYBUTTONDOWN :
Impl_HandleJoystickButtonEvent ( evt . jbutton , evt . type ) ;
2014-07-26 07:06:00 +00:00
break ;
2023-01-27 01:26:28 +00:00
case SDL_JOYDEVICEADDED :
{
SDL_Joystick * newjoy = SDL_JoystickOpen ( evt . jdevice . which ) ;
CONS_Debug ( DBG_GAMELOGIC , " Joystick device index %d added \n " , evt . jdevice . which + 1 ) ;
// Because SDL's device index is unstable, we're going to cheat here a bit:
// For the first joystick setting that is NOT active:
// 1. Set cv_usejoystickX.value to the new device index (this does not change what is written to config.cfg)
// 2. Set OTHERS' cv_usejoystickX.value to THEIR new device index, because it likely changed
// * If device doesn't exist, switch cv_usejoystick back to default value (.string)
// * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value!
if ( newjoy & & ( ! JoyInfo . dev | | ! SDL_JoystickGetAttached ( JoyInfo . dev ) )
& & JoyInfo2 . dev ! = newjoy ) // don't override a currently active device
{
cv_usejoystick . value = evt . jdevice . which + 1 ;
if ( JoyInfo2 . dev )
cv_usejoystick2 . value = I_GetJoystickDeviceIndex ( JoyInfo2 . dev ) + 1 ;
else if ( atoi ( cv_usejoystick2 . string ) ! = JoyInfo . oldjoy
& & atoi ( cv_usejoystick2 . string ) ! = cv_usejoystick . value )
cv_usejoystick2 . value = atoi ( cv_usejoystick2 . string ) ;
else if ( atoi ( cv_usejoystick . string ) ! = JoyInfo . oldjoy
& & atoi ( cv_usejoystick . string ) ! = cv_usejoystick . value )
cv_usejoystick2 . value = atoi ( cv_usejoystick . string ) ;
else // we tried...
cv_usejoystick2 . value = 0 ;
}
else if ( newjoy & & ( ! JoyInfo2 . dev | | ! SDL_JoystickGetAttached ( JoyInfo2 . dev ) )
& & JoyInfo . dev ! = newjoy ) // don't override a currently active device
{
cv_usejoystick2 . value = evt . jdevice . which + 1 ;
if ( JoyInfo . dev )
cv_usejoystick . value = I_GetJoystickDeviceIndex ( JoyInfo . dev ) + 1 ;
else if ( atoi ( cv_usejoystick . string ) ! = JoyInfo2 . oldjoy
& & atoi ( cv_usejoystick . string ) ! = cv_usejoystick2 . value )
cv_usejoystick . value = atoi ( cv_usejoystick . string ) ;
else if ( atoi ( cv_usejoystick2 . string ) ! = JoyInfo2 . oldjoy
& & atoi ( cv_usejoystick2 . string ) ! = cv_usejoystick2 . value )
cv_usejoystick . value = atoi ( cv_usejoystick2 . string ) ;
else // we tried...
cv_usejoystick . value = 0 ;
}
// Was cv_usejoystick disabled in settings?
if ( ! strcmp ( cv_usejoystick . string , " 0 " ) | | ! cv_usejoystick . value )
cv_usejoystick . value = 0 ;
else if ( atoi ( cv_usejoystick . string ) < = I_NumJoys ( ) // don't mess if we intentionally set higher than NumJoys
& & cv_usejoystick . value ) // update the cvar ONLY if a device exists
CV_SetValue ( & cv_usejoystick , cv_usejoystick . value ) ;
if ( ! strcmp ( cv_usejoystick2 . string , " 0 " ) | | ! cv_usejoystick2 . value )
cv_usejoystick2 . value = 0 ;
else if ( atoi ( cv_usejoystick2 . string ) < = I_NumJoys ( ) // don't mess if we intentionally set higher than NumJoys
& & cv_usejoystick2 . value ) // update the cvar ONLY if a device exists
CV_SetValue ( & cv_usejoystick2 , cv_usejoystick2 . value ) ;
// Update all joysticks' init states
// This is a little wasteful since cv_usejoystick already calls this, but
// we need to do this in case CV_SetValue did nothing because the string was already same.
// if the device is already active, this should do nothing, effectively.
I_InitJoystick ( ) ;
I_InitJoystick2 ( ) ;
CONS_Debug ( DBG_GAMELOGIC , " Joystick1 device index: %d \n " , JoyInfo . oldjoy ) ;
CONS_Debug ( DBG_GAMELOGIC , " Joystick2 device index: %d \n " , JoyInfo2 . oldjoy ) ;
// update the menu
if ( currentMenu = = & OP_JoystickSetDef )
M_SetupJoystickMenu ( 0 ) ;
if ( JoyInfo . dev ! = newjoy & & JoyInfo2 . dev ! = newjoy )
SDL_JoystickClose ( newjoy ) ;
}
2018-12-06 15:54:58 +00:00
break ;
2023-01-27 01:26:28 +00:00
case SDL_JOYDEVICEREMOVED :
if ( JoyInfo . dev & & ! SDL_JoystickGetAttached ( JoyInfo . dev ) )
{
CONS_Debug ( DBG_GAMELOGIC , " Joystick1 removed, device index: %d \n " , JoyInfo . oldjoy ) ;
I_ShutdownJoystick ( ) ;
}
if ( JoyInfo2 . dev & & ! SDL_JoystickGetAttached ( JoyInfo2 . dev ) )
{
CONS_Debug ( DBG_GAMELOGIC , " Joystick2 removed, device index: %d \n " , JoyInfo2 . oldjoy ) ;
I_ShutdownJoystick2 ( ) ;
}
// Update the device indexes, because they likely changed
// * If device doesn't exist, switch cv_usejoystick back to default value (.string)
// * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value!
if ( JoyInfo . dev )
cv_usejoystick . value = JoyInfo . oldjoy = I_GetJoystickDeviceIndex ( JoyInfo . dev ) + 1 ;
else if ( atoi ( cv_usejoystick . string ) ! = JoyInfo2 . oldjoy )
cv_usejoystick . value = atoi ( cv_usejoystick . string ) ;
else if ( atoi ( cv_usejoystick2 . string ) ! = JoyInfo2 . oldjoy )
cv_usejoystick . value = atoi ( cv_usejoystick2 . string ) ;
else // we tried...
cv_usejoystick . value = 0 ;
if ( JoyInfo2 . dev )
cv_usejoystick2 . value = JoyInfo2 . oldjoy = I_GetJoystickDeviceIndex ( JoyInfo2 . dev ) + 1 ;
else if ( atoi ( cv_usejoystick2 . string ) ! = JoyInfo . oldjoy )
cv_usejoystick2 . value = atoi ( cv_usejoystick2 . string ) ;
else if ( atoi ( cv_usejoystick . string ) ! = JoyInfo . oldjoy )
cv_usejoystick2 . value = atoi ( cv_usejoystick . string ) ;
else // we tried...
cv_usejoystick2 . value = 0 ;
// Was cv_usejoystick disabled in settings?
if ( ! strcmp ( cv_usejoystick . string , " 0 " ) )
cv_usejoystick . value = 0 ;
else if ( atoi ( cv_usejoystick . string ) < = I_NumJoys ( ) // don't mess if we intentionally set higher than NumJoys
& & cv_usejoystick . value ) // update the cvar ONLY if a device exists
CV_SetValue ( & cv_usejoystick , cv_usejoystick . value ) ;
if ( ! strcmp ( cv_usejoystick2 . string , " 0 " ) )
cv_usejoystick2 . value = 0 ;
else if ( atoi ( cv_usejoystick2 . string ) < = I_NumJoys ( ) // don't mess if we intentionally set higher than NumJoys
& & cv_usejoystick2 . value ) // update the cvar ONLY if a device exists
CV_SetValue ( & cv_usejoystick2 , cv_usejoystick2 . value ) ;
CONS_Debug ( DBG_GAMELOGIC , " Joystick1 device index: %d \n " , JoyInfo . oldjoy ) ;
CONS_Debug ( DBG_GAMELOGIC , " Joystick2 device index: %d \n " , JoyInfo2 . oldjoy ) ;
// update the menu
if ( currentMenu = = & OP_JoystickSetDef )
M_SetupJoystickMenu ( 0 ) ;
2022-11-12 02:07:24 +00:00
break ;
2014-07-26 07:06:00 +00:00
case SDL_QUIT :
2020-12-12 11:06:57 +00:00
LUA_HookBool ( true , HOOK ( GameQuit ) ) ;
2014-07-26 07:06:00 +00:00
I_Quit ( ) ;
break ;
}
}
2017-08-21 20:38:29 +00:00
// Send all relative mouse movement as one single mouse event.
2017-08-19 20:39:04 +00:00
if ( mousemovex | | mousemovey )
{
event_t event ;
2017-08-21 20:38:29 +00:00
int wwidth , wheight ;
SDL_GetWindowSize ( window , & wwidth , & wheight ) ;
//SDL_memset(&event, 0, sizeof(event_t));
2017-08-19 20:39:04 +00:00
event . type = ev_mouse ;
2021-08-14 21:42:39 +00:00
event . key = 0 ;
event . x = ( INT32 ) lround ( mousemovex * ( ( float ) wwidth / ( float ) realwidth ) ) ;
event . y = ( INT32 ) lround ( mousemovey * ( ( float ) wheight / ( float ) realheight ) ) ;
2017-08-19 20:39:04 +00:00
D_PostEvent ( & event ) ;
}
2014-07-26 07:06:00 +00:00
// In order to make wheels act like buttons, we have to set their state to Up.
// This is because wheel messages don't have an up/down state.
gamekeydown [ KEY_MOUSEWHEELDOWN ] = gamekeydown [ KEY_MOUSEWHEELUP ] = 0 ;
2014-03-15 16:59:03 +00:00
}
void I_StartupMouse ( void )
{
2016-11-30 17:21:28 +00:00
static SDL_bool firsttimeonmouse = SDL_TRUE ;
2014-03-15 16:59:03 +00:00
if ( disable_mouse )
return ;
2016-11-30 17:21:28 +00:00
2014-03-15 16:59:03 +00:00
if ( ! firsttimeonmouse )
2016-06-07 20:19:24 +00:00
{
2014-03-15 16:59:03 +00:00
HalfWarpMouse ( realwidth , realheight ) ; // warp to center
2016-06-07 20:19:24 +00:00
}
2014-03-15 16:59:03 +00:00
else
firsttimeonmouse = SDL_FALSE ;
2020-01-18 19:18:20 +00:00
if ( cv_usemouse . value & & ! IgnoreMouse ( ) )
2019-03-30 05:00:47 +00:00
SDLdoGrabMouse ( ) ;
2014-03-15 16:59:03 +00:00
else
SDLdoUngrabMouse ( ) ;
}
//
// I_OsPolling
//
void I_OsPolling ( void )
{
2019-01-18 00:47:01 +00:00
SDL_Keymod mod ;
2014-03-15 16:59:03 +00:00
if ( consolevent )
I_GetConsoleEvents ( ) ;
2023-01-27 01:26:28 +00:00
if ( SDL_WasInit ( SDL_INIT_JOYSTICK ) = = SDL_INIT_JOYSTICK )
{
SDL_JoystickUpdate ( ) ;
I_GetJoystickEvents ( ) ;
I_GetJoystick2Events ( ) ;
}
2014-03-15 16:59:03 +00:00
I_GetMouseEvents ( ) ;
2023-01-27 01:26:28 +00:00
2014-03-15 16:59:03 +00:00
I_GetEvent ( ) ;
2019-01-18 00:47:01 +00:00
mod = SDL_GetModState ( ) ;
/* Handle here so that our state is always synched with the system. */
shiftdown = ctrldown = altdown = 0 ;
capslock = false ;
if ( mod & KMOD_LSHIFT ) shiftdown | = 1 ;
if ( mod & KMOD_RSHIFT ) shiftdown | = 2 ;
if ( mod & KMOD_LCTRL ) ctrldown | = 1 ;
if ( mod & KMOD_RCTRL ) ctrldown | = 2 ;
if ( mod & KMOD_LALT ) altdown | = 1 ;
if ( mod & KMOD_RALT ) altdown | = 2 ;
if ( mod & KMOD_CAPS ) capslock = true ;
2014-03-15 16:59:03 +00:00
}
//
// I_UpdateNoBlit
//
void I_UpdateNoBlit ( void )
{
2014-07-26 07:06:00 +00:00
if ( rendermode = = render_none )
2014-03-15 16:59:03 +00:00
return ;
2014-07-26 07:06:00 +00:00
if ( exposevideo )
{
2014-03-15 16:59:03 +00:00
# ifdef HWRENDER
2014-07-26 07:06:00 +00:00
if ( rendermode = = render_opengl )
{
OglSdlFinishUpdate ( cv_vidwait . value ) ;
}
else
2014-03-15 16:59:03 +00:00
# endif
2014-07-26 07:06:00 +00:00
if ( rendermode = = render_soft )
{
SDL_RenderCopy ( renderer , texture , NULL , NULL ) ;
SDL_RenderPresent ( renderer ) ;
}
}
2014-03-15 16:59:03 +00:00
exposevideo = SDL_FALSE ;
}
// I_SkipFrame
//
// Returns true if it thinks we can afford to skip this frame
// from PrBoom's src/SDL/i_video.c
static inline boolean I_SkipFrame ( void )
{
2022-03-26 20:32:43 +00:00
# if 1
2022-03-26 21:16:13 +00:00
// While I fixed the FPS counter bugging out with this,
// I actually really like being able to pause and
// use perfstats to measure rendering performance
// without game logic changes.
2022-03-26 20:32:43 +00:00
return false ;
# else
2014-03-15 16:59:03 +00:00
static boolean skip = false ;
skip = ! skip ;
switch ( gamestate )
{
case GS_LEVEL :
if ( ! paused )
return false ;
2017-09-28 13:39:47 +00:00
/* FALLTHRU */
2017-01-28 13:13:03 +00:00
//case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible
2014-03-15 16:59:03 +00:00
case GS_WAITINGPLAYERS :
return skip ; // Skip odd frames
default :
return false ;
}
2019-05-08 14:36:37 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
//
// I_FinishUpdate
//
2022-03-26 21:16:13 +00:00
static SDL_Rect src_rect = { 0 , 0 , 0 , 0 } ;
2014-03-15 16:59:03 +00:00
void I_FinishUpdate ( void )
{
2014-07-26 07:06:00 +00:00
if ( rendermode = = render_none )
2014-03-15 16:59:03 +00:00
return ; //Alam: No software or OpenGl surface
2022-04-25 06:12:27 +00:00
SCR_CalculateFPS ( ) ;
2022-03-26 20:32:43 +00:00
2014-03-15 16:59:03 +00:00
if ( I_SkipFrame ( ) )
return ;
2020-05-15 12:39:27 +00:00
if ( marathonmode )
SCR_DisplayMarathonInfo ( ) ;
2017-04-17 00:09:47 +00:00
// draw captions if enabled
if ( cv_closedcaptioning . value )
SCR_ClosedCaptions ( ) ;
2019-11-23 21:09:02 +00:00
if ( cv_ticrate . value )
SCR_DisplayTicRate ( ) ;
2019-11-18 01:22:47 +00:00
2019-11-23 21:09:02 +00:00
if ( cv_showping . value & & netgame & & consoleplayer ! = serverplayer )
SCR_DisplayLocalPing ( ) ;
2014-03-15 16:59:03 +00:00
2017-05-15 14:24:40 +00:00
if ( rendermode = = render_soft & & screens [ 0 ] )
2014-03-15 16:59:03 +00:00
{
2014-07-26 07:06:00 +00:00
if ( ! bufSurface ) //Double-Check
2014-03-15 16:59:03 +00:00
{
2014-07-26 07:06:00 +00:00
Impl_VideoSetupSDLBuffer ( ) ;
2014-03-15 16:59:03 +00:00
}
2022-03-26 21:16:13 +00:00
2014-07-26 07:06:00 +00:00
if ( bufSurface )
2014-03-15 16:59:03 +00:00
{
2022-03-26 21:16:13 +00:00
SDL_BlitSurface ( bufSurface , & src_rect , vidSurface , & src_rect ) ;
2014-07-26 07:06:00 +00:00
// Fury -- there's no way around UpdateTexture, the GL backend uses it anyway
SDL_LockSurface ( vidSurface ) ;
2022-03-26 21:16:13 +00:00
SDL_UpdateTexture ( texture , & src_rect , vidSurface - > pixels , vidSurface - > pitch ) ;
2014-07-26 07:06:00 +00:00
SDL_UnlockSurface ( vidSurface ) ;
2014-03-15 16:59:03 +00:00
}
2022-03-26 21:16:13 +00:00
2014-07-26 07:06:00 +00:00
SDL_RenderClear ( renderer ) ;
2022-03-26 21:16:13 +00:00
SDL_RenderCopy ( renderer , texture , & src_rect , NULL ) ;
2014-07-26 07:06:00 +00:00
SDL_RenderPresent ( renderer ) ;
2014-03-15 16:59:03 +00:00
}
# ifdef HWRENDER
2017-05-15 14:24:40 +00:00
else if ( rendermode = = render_opengl )
2014-03-15 16:59:03 +00:00
{
OglSdlFinishUpdate ( cv_vidwait . value ) ;
}
# endif
2022-03-26 21:16:13 +00:00
2014-03-15 16:59:03 +00:00
exposevideo = SDL_FALSE ;
}
//
// I_UpdateNoVsync
//
void I_UpdateNoVsync ( void )
{
INT32 real_vidwait = cv_vidwait . value ;
cv_vidwait . value = 0 ;
I_FinishUpdate ( ) ;
cv_vidwait . value = real_vidwait ;
}
//
// I_ReadScreen
//
void I_ReadScreen ( UINT8 * scr )
{
if ( rendermode ! = render_soft )
I_Error ( " I_ReadScreen: called while in non-software mode " ) ;
else
VID_BlitLinearScreen ( screens [ 0 ] , scr ,
vid . width * vid . bpp , vid . height ,
vid . rowbytes , vid . rowbytes ) ;
}
//
// I_SetPalette
//
void I_SetPalette ( RGBA_t * palette )
{
size_t i ;
for ( i = 0 ; i < 256 ; i + + )
{
localPalette [ i ] . r = palette [ i ] . s . red ;
localPalette [ i ] . g = palette [ i ] . s . green ;
localPalette [ i ] . b = palette [ i ] . s . blue ;
}
2014-07-26 07:06:00 +00:00
//if (vidSurface) SDL_SetPaletteColors(vidSurface->format->palette, localPalette, 0, 256);
// Fury -- SDL2 vidSurface is a 32-bit surface buffer copied to the texture. It's not palletized, like bufSurface.
if ( bufSurface ) SDL_SetPaletteColors ( bufSurface - > format - > palette , localPalette , 0 , 256 ) ;
2014-03-15 16:59:03 +00:00
}
// return number of fullscreen + X11 modes
2018-11-08 16:26:55 +00:00
INT32 VID_NumModes ( void )
2014-03-15 16:59:03 +00:00
{
if ( USE_FULLSCREEN & & numVidModes ! = - 1 )
return numVidModes - firstEntry ;
else
return MAXWINMODES ;
}
2018-11-08 16:26:55 +00:00
const char * VID_GetModeName ( INT32 modeNum )
2014-03-15 16:59:03 +00:00
{
2014-07-26 07:06:00 +00:00
#if 0
2014-03-15 16:59:03 +00:00
if ( USE_FULLSCREEN & & numVidModes ! = - 1 ) // fullscreen modes
{
modeNum + = firstEntry ;
if ( modeNum > = numVidModes )
return NULL ;
sprintf ( & vidModeName [ modeNum ] [ 0 ] , " %dx%d " ,
modeList [ modeNum ] - > w ,
modeList [ modeNum ] - > h ) ;
}
else // windowed modes
{
2014-07-26 07:06:00 +00:00
# endif
if ( modeNum = = - 1 )
{
return fallback_resolution_name ;
}
2014-03-15 16:59:03 +00:00
if ( modeNum > MAXWINMODES )
return NULL ;
sprintf ( & vidModeName [ modeNum ] [ 0 ] , " %dx%d " ,
windowedModes [ modeNum ] [ 0 ] ,
windowedModes [ modeNum ] [ 1 ] ) ;
2014-07-26 07:06:00 +00:00
//}
2014-03-15 16:59:03 +00:00
return & vidModeName [ modeNum ] [ 0 ] ;
}
2018-11-08 16:26:55 +00:00
INT32 VID_GetModeForSize ( INT32 w , INT32 h )
2014-03-15 16:59:03 +00:00
{
2014-07-26 07:06:00 +00:00
int i ;
for ( i = 0 ; i < MAXWINMODES ; i + + )
{
if ( windowedModes [ i ] [ 0 ] = = w & & windowedModes [ i ] [ 1 ] = = h )
{
return i ;
}
}
return - 1 ;
#if 0
2014-03-15 16:59:03 +00:00
INT32 matchMode = - 1 , i ;
2014-03-22 19:54:46 +00:00
VID_PrepareModeList ( ) ;
2014-03-15 16:59:03 +00:00
if ( USE_FULLSCREEN & & numVidModes ! = - 1 )
{
for ( i = firstEntry ; i < numVidModes ; i + + )
{
if ( modeList [ i ] - > w = = w & &
modeList [ i ] - > h = = h )
{
matchMode = i ;
break ;
}
}
if ( - 1 = = matchMode ) // use smaller mode
{
w - = w % BASEVIDWIDTH ;
h - = h % BASEVIDHEIGHT ;
for ( i = firstEntry ; i < numVidModes ; i + + )
{
if ( modeList [ i ] - > w = = w & &
modeList [ i ] - > h = = h )
{
matchMode = i ;
break ;
}
}
if ( - 1 = = matchMode ) // use smallest mode
matchMode = numVidModes - 1 ;
}
matchMode - = firstEntry ;
}
else
{
for ( i = 0 ; i < MAXWINMODES ; i + + )
{
if ( windowedModes [ i ] [ 0 ] = = w & &
windowedModes [ i ] [ 1 ] = = h )
{
matchMode = i ;
break ;
}
}
if ( - 1 = = matchMode ) // use smaller mode
{
w - = w % BASEVIDWIDTH ;
h - = h % BASEVIDHEIGHT ;
for ( i = 0 ; i < MAXWINMODES ; i + + )
{
if ( windowedModes [ i ] [ 0 ] = = w & &
windowedModes [ i ] [ 1 ] = = h )
{
matchMode = i ;
break ;
}
}
if ( - 1 = = matchMode ) // use smallest mode
matchMode = MAXWINMODES - 1 ;
}
}
return matchMode ;
2014-07-26 07:06:00 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
void VID_PrepareModeList ( void )
{
2014-07-26 07:06:00 +00:00
// Under SDL2, we just use the windowed modes list, and scale in windowed fullscreen.
allow_fullscreen = true ;
#if 0
2014-03-15 16:59:03 +00:00
INT32 i ;
firstEntry = 0 ;
2014-03-22 19:54:46 +00:00
# ifdef HWRENDER
if ( rendermode = = render_opengl )
modeList = SDL_ListModes ( NULL , SDL_OPENGL | SDL_FULLSCREEN ) ;
else
# endif
modeList = SDL_ListModes ( NULL , surfaceFlagsF | SDL_HWSURFACE ) ; //Alam: At least hardware surface
2014-03-15 16:59:03 +00:00
if ( disable_fullscreen ? 0 : cv_fullscreen . value ) // only fullscreen needs preparation
{
if ( - 1 ! = numVidModes )
{
for ( i = 0 ; i < numVidModes ; i + + )
{
if ( modeList [ i ] - > w < = MAXVIDWIDTH & &
modeList [ i ] - > h < = MAXVIDHEIGHT )
{
firstEntry = i ;
break ;
}
}
}
}
allow_fullscreen = true ;
2014-07-26 07:06:00 +00:00
# endif
2014-03-15 16:59:03 +00:00
}
2019-09-09 00:37:24 +00:00
static SDL_bool Impl_CreateContext ( void )
2019-09-08 21:27:35 +00:00
{
// Renderer-specific stuff
# ifdef HWRENDER
2020-08-15 01:27:16 +00:00
if ( ( rendermode = = render_opengl )
& & ( vid . glstate ! = VID_GL_LIBRARY_ERROR ) )
2019-09-08 21:27:35 +00:00
{
if ( ! sdlglcontext )
sdlglcontext = SDL_GL_CreateContext ( window ) ;
if ( sdlglcontext = = NULL )
{
SDL_DestroyWindow ( window ) ;
I_Error ( " Failed to create a GL context: %s \n " , SDL_GetError ( ) ) ;
}
SDL_GL_MakeCurrent ( window , sdlglcontext ) ;
}
else
# endif
if ( rendermode = = render_soft )
{
2019-09-09 00:37:24 +00:00
int flags = 0 ; // Use this to set SDL_RENDERER_* flags now
2019-09-08 21:27:35 +00:00
if ( usesdl2soft )
flags | = SDL_RENDERER_SOFTWARE ;
2022-03-27 03:48:08 +00:00
#if 0
// This shit is BROKEN.
// - The version of SDL we're using cannot toggle VSync at runtime. We'll need a new SDL version implemented to have this work properly.
// - cv_vidwait is initialized before config is loaded, so it's forced to default value at runtime, and forced off when switching. The config loading code would need restructured.
// - With both this & frame interpolation on, I_FinishUpdate takes x10 longer. At this point, it is simpler to use a standard FPS cap.
// So you can probably guess why I'm kinda over this, I'm just disabling it.
2019-09-08 21:27:35 +00:00
else if ( cv_vidwait . value )
flags | = SDL_RENDERER_PRESENTVSYNC ;
2022-03-27 03:48:08 +00:00
# endif
2019-09-08 21:27:35 +00:00
if ( ! renderer )
renderer = SDL_CreateRenderer ( window , - 1 , flags ) ;
if ( renderer = = NULL )
{
CONS_Printf ( M_GetText ( " Couldn't create rendering context: %s \n " ) , SDL_GetError ( ) ) ;
return SDL_FALSE ;
}
SDL_RenderSetLogicalSize ( renderer , BASEVIDWIDTH , BASEVIDHEIGHT ) ;
}
return SDL_TRUE ;
}
2020-02-18 00:11:56 +00:00
void VID_CheckGLLoaded ( rendermode_t oldrender )
2020-01-27 04:57:55 +00:00
{
2020-08-31 23:09:41 +00:00
( void ) oldrender ;
2020-02-18 00:11:56 +00:00
# ifdef HWRENDER
2020-08-15 01:27:16 +00:00
if ( vid . glstate = = VID_GL_LIBRARY_ERROR ) // Well, it didn't work the first time anyway.
2020-01-27 04:57:55 +00:00
{
2020-01-27 04:57:55 +00:00
CONS_Alert ( CONS_ERROR , " OpenGL never loaded \n " ) ;
2020-01-27 04:57:55 +00:00
rendermode = oldrender ;
if ( chosenrendermode = = render_opengl ) // fallback to software
rendermode = render_soft ;
if ( setrenderneeded )
{
CV_StealthSetValue ( & cv_renderer , oldrender ) ;
setrenderneeded = 0 ;
}
}
# endif
2020-02-18 00:11:56 +00:00
}
2020-01-27 04:57:55 +00:00
2020-08-15 01:27:16 +00:00
boolean VID_CheckRenderer ( void )
2019-09-08 21:27:35 +00:00
{
2020-02-18 00:58:32 +00:00
boolean rendererchanged = false ;
boolean contextcreated = false ;
2020-08-15 01:27:16 +00:00
# ifdef HWRENDER
2020-01-27 04:57:55 +00:00
rendermode_t oldrenderer = rendermode ;
2020-08-15 01:27:16 +00:00
# endif
2020-01-27 04:57:55 +00:00
2019-09-09 00:37:24 +00:00
if ( dedicated )
2020-08-15 01:27:16 +00:00
return false ;
2019-09-09 00:37:24 +00:00
2019-09-08 21:27:35 +00:00
if ( setrenderneeded )
{
rendermode = setrenderneeded ;
2020-02-18 00:58:32 +00:00
rendererchanged = true ;
2020-02-16 01:23:05 +00:00
2020-01-27 04:57:55 +00:00
# ifdef HWRENDER
2020-02-15 17:10:55 +00:00
if ( rendermode = = render_opengl )
{
2020-01-27 04:57:55 +00:00
VID_CheckGLLoaded ( oldrenderer ) ;
2020-02-18 00:58:32 +00:00
2020-02-15 17:10:55 +00:00
// Initialise OpenGL before calling SDLSetMode!!!
2020-02-18 00:58:32 +00:00
// This is because SDLSetMode calls OglSdlSurface.
2020-08-15 01:27:16 +00:00
if ( vid . glstate = = VID_GL_LIBRARY_NOTLOADED )
2020-02-18 00:58:32 +00:00
{
2020-02-18 00:11:56 +00:00
VID_StartupOpenGL ( ) ;
2020-08-15 01:27:16 +00:00
2020-02-18 00:58:32 +00:00
// Loaded successfully!
2020-08-15 01:27:16 +00:00
if ( vid . glstate = = VID_GL_LIBRARY_LOADED )
2020-02-18 00:58:32 +00:00
{
// Destroy the current window, if it exists.
if ( window )
{
SDL_DestroyWindow ( window ) ;
window = NULL ;
}
// Destroy the current window rendering context, if that also exists.
if ( renderer )
{
SDL_DestroyRenderer ( renderer ) ;
renderer = NULL ;
}
// Create a new window.
Impl_CreateWindow ( USE_FULLSCREEN ) ;
// From there, the OpenGL context was already created.
contextcreated = true ;
}
}
2020-08-15 01:27:16 +00:00
else if ( vid . glstate = = VID_GL_LIBRARY_ERROR )
2020-02-18 00:58:32 +00:00
rendererchanged = false ;
2020-02-15 17:10:55 +00:00
}
2020-01-27 04:57:55 +00:00
# endif
2020-02-16 01:23:05 +00:00
2020-02-18 00:58:32 +00:00
if ( ! contextcreated )
Impl_CreateContext ( ) ;
setrenderneeded = 0 ;
2019-09-08 21:27:35 +00:00
}
2020-11-22 20:22:18 +00:00
SDLSetMode ( vid . width , vid . height , USE_FULLSCREEN , ( setmodeneeded ? SDL_TRUE : SDL_FALSE ) ) ;
2019-11-10 03:04:11 +00:00
Impl_VideoSetupBuffer ( ) ;
2019-09-08 21:27:35 +00:00
if ( rendermode = = render_soft )
{
if ( bufSurface )
{
SDL_FreeSurface ( bufSurface ) ;
bufSurface = NULL ;
}
2020-02-18 00:58:32 +00:00
2020-08-15 01:27:16 +00:00
SCR_SetDrawFuncs ( ) ;
2019-09-08 21:27:35 +00:00
}
2019-09-09 01:25:18 +00:00
# ifdef HWRENDER
2020-08-15 01:27:16 +00:00
else if ( rendermode = = render_opengl & & rendererchanged )
2020-02-18 00:58:32 +00:00
{
2020-08-15 01:27:16 +00:00
HWR_Switch ( ) ;
V_SetPalette ( 0 ) ;
2020-02-18 00:58:32 +00:00
}
2019-09-09 01:25:18 +00:00
# endif
2020-08-15 01:27:16 +00:00
return rendererchanged ;
2019-09-08 21:27:35 +00:00
}
2022-04-28 02:42:47 +00:00
static UINT32 refresh_rate ;
static UINT32 VID_GetRefreshRate ( void )
{
int index = SDL_GetWindowDisplayIndex ( window ) ;
SDL_DisplayMode m ;
if ( SDL_WasInit ( SDL_INIT_VIDEO ) = = 0 )
{
// Video not init yet.
return 0 ;
}
if ( SDL_GetCurrentDisplayMode ( index , & m ) ! = 0 )
{
// Error has occurred.
return 0 ;
}
return m . refresh_rate ;
}
2014-03-15 16:59:03 +00:00
INT32 VID_SetMode ( INT32 modeNum )
{
SDLdoUngrabMouse ( ) ;
2014-07-26 07:06:00 +00:00
vid . recalc = 1 ;
vid . bpp = 1 ;
2019-09-09 00:37:24 +00:00
if ( modeNum < 0 )
modeNum = 0 ;
if ( modeNum > = MAXWINMODES )
modeNum = MAXWINMODES - 1 ;
vid . width = windowedModes [ modeNum ] [ 0 ] ;
vid . height = windowedModes [ modeNum ] [ 1 ] ;
vid . modenum = modeNum ;
2017-06-25 19:22:01 +00:00
//Impl_SetWindowName("SRB2 "VERSIONSTRING);
2022-03-26 21:16:13 +00:00
src_rect . w = vid . width ;
src_rect . h = vid . height ;
2022-04-28 02:42:47 +00:00
refresh_rate = VID_GetRefreshRate ( ) ;
2019-09-08 21:27:35 +00:00
VID_CheckRenderer ( ) ;
2014-07-26 07:06:00 +00:00
return SDL_TRUE ;
}
static SDL_bool Impl_CreateWindow ( SDL_bool fullscreen )
{
int flags = 0 ;
2016-11-21 22:07:05 +00:00
if ( rendermode = = render_none ) // dedicated
return SDL_TRUE ; // Monster Iestyn -- not sure if it really matters what we return here tbh
2014-07-26 07:06:00 +00:00
if ( window ! = NULL )
return SDL_FALSE ;
if ( fullscreen )
flags | = SDL_WINDOW_FULLSCREEN_DESKTOP ;
if ( borderlesswindow )
flags | = SDL_WINDOW_BORDERLESS ;
2014-03-15 16:59:03 +00:00
# ifdef HWRENDER
2020-08-15 01:27:16 +00:00
if ( vid . glstate = = VID_GL_LIBRARY_LOADED )
2020-02-17 15:14:51 +00:00
flags | = SDL_WINDOW_OPENGL ;
2021-10-08 19:47:22 +00:00
// Without a 24-bit depth buffer many visuals are ruined by z-fighting.
// Some GPU drivers may give us a 16-bit depth buffer since the
// default value for SDL_GL_DEPTH_SIZE is 16.
SDL_GL_SetAttribute ( SDL_GL_DEPTH_SIZE , 24 ) ;
2016-11-21 22:07:05 +00:00
# endif
// Create a window
window = SDL_CreateWindow ( " SRB2 " VERSIONSTRING , SDL_WINDOWPOS_CENTERED , SDL_WINDOWPOS_CENTERED ,
realwidth , realheight , flags ) ;
2020-04-26 22:46:43 +00:00
2016-11-21 22:07:05 +00:00
if ( window = = NULL )
{
CONS_Printf ( M_GetText ( " Couldn't create window: %s \n " ) , SDL_GetError ( ) ) ;
return SDL_FALSE ;
}
2020-04-26 22:46:43 +00:00
Impl_SetWindowIcon ( ) ;
2019-09-09 00:37:24 +00:00
return Impl_CreateContext ( ) ;
2014-07-26 07:06:00 +00:00
}
2014-03-15 16:59:03 +00:00
2017-06-25 19:22:01 +00:00
/*
2014-07-26 07:06:00 +00:00
static void Impl_SetWindowName ( const char * title )
{
2017-06-25 19:22:01 +00:00
if ( window = = NULL )
2014-03-15 16:59:03 +00:00
{
2014-07-26 07:06:00 +00:00
return ;
2014-03-15 16:59:03 +00:00
}
2014-07-26 07:06:00 +00:00
SDL_SetWindowTitle ( window , title ) ;
}
2017-06-25 19:22:01 +00:00
*/
2014-03-15 16:59:03 +00:00
2014-07-26 07:06:00 +00:00
static void Impl_SetWindowIcon ( void )
{
2020-04-26 22:46:43 +00:00
if ( window & & icoSurface )
2020-08-08 08:16:47 +00:00
SDL_SetWindowIcon ( window , icoSurface ) ;
2014-07-26 07:06:00 +00:00
}
2014-03-15 16:59:03 +00:00
2014-07-26 07:06:00 +00:00
static void Impl_VideoSetupSDLBuffer ( void )
{
if ( bufSurface ! = NULL )
{
SDL_FreeSurface ( bufSurface ) ;
bufSurface = NULL ;
}
// Set up the SDL palletized buffer (copied to vidbuffer before being rendered to texture)
if ( vid . bpp = = 1 )
{
bufSurface = SDL_CreateRGBSurfaceFrom ( screens [ 0 ] , vid . width , vid . height , 8 ,
( int ) vid . rowbytes , 0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 ) ; // 256 mode
}
else if ( vid . bpp = = 2 ) // Fury -- don't think this is used at all anymore
{
bufSurface = SDL_CreateRGBSurfaceFrom ( screens [ 0 ] , vid . width , vid . height , 15 ,
( int ) vid . rowbytes , 0x00007C00 , 0x000003E0 , 0x0000001F , 0x00000000 ) ; // 555 mode
}
if ( bufSurface )
{
SDL_SetPaletteColors ( bufSurface - > format - > palette , localPalette , 0 , 256 ) ;
}
else
{
I_Error ( " %s " , M_GetText ( " No system memory for SDL buffer surface \n " ) ) ;
}
}
2014-03-15 16:59:03 +00:00
2014-07-26 07:06:00 +00:00
static void Impl_VideoSetupBuffer ( void )
{
// Set up game's software render buffer
2019-12-25 08:43:46 +00:00
vid . rowbytes = vid . width * vid . bpp ;
vid . direct = NULL ;
if ( vid . buffer )
free ( vid . buffer ) ;
vid . buffer = calloc ( vid . rowbytes * vid . height , NUMSCREENS ) ;
if ( ! vid . buffer )
2014-07-26 07:06:00 +00:00
{
2019-12-25 08:43:46 +00:00
I_Error ( " %s " , M_GetText ( " Not enough memory for video buffer \n " ) ) ;
2014-07-26 07:06:00 +00:00
}
2014-03-15 16:59:03 +00:00
}
void I_StartupGraphics ( void )
{
2014-03-18 03:37:56 +00:00
if ( dedicated )
{
rendermode = render_none ;
return ;
}
if ( graphics_started )
2014-03-15 16:59:03 +00:00
return ;
COM_AddCommand ( " vid_nummodes " , VID_Command_NumModes_f ) ;
COM_AddCommand ( " vid_info " , VID_Command_Info_f ) ;
COM_AddCommand ( " vid_modelist " , VID_Command_ModeList_f ) ;
COM_AddCommand ( " vid_mode " , VID_Command_Mode_f ) ;
CV_RegisterVar ( & cv_vidwait ) ;
CV_RegisterVar ( & cv_stretch ) ;
2020-01-02 23:25:58 +00:00
CV_RegisterVar ( & cv_alwaysgrabmouse ) ;
2014-03-15 16:59:03 +00:00
disable_mouse = M_CheckParm ( " -nomouse " ) ;
2014-07-26 07:06:00 +00:00
disable_fullscreen = M_CheckParm ( " -win " ) ? 1 : 0 ;
2014-03-15 16:59:03 +00:00
keyboard_started = true ;
# if !defined(HAVE_TTF)
2016-02-23 07:05:36 +00:00
// Previously audio was init here for questionable reasons?
2014-03-15 16:59:03 +00:00
if ( SDL_InitSubSystem ( SDL_INIT_VIDEO ) < 0 )
{
2016-02-23 07:05:36 +00:00
CONS_Printf ( M_GetText ( " Couldn't initialize SDL's Video System: %s \n " ) , SDL_GetError ( ) ) ;
return ;
2014-03-15 16:59:03 +00:00
}
# endif
{
2016-05-09 03:34:43 +00:00
const char * vd = SDL_GetCurrentVideoDriver ( ) ;
//CONS_Printf(M_GetText("Starting up with video driver: %s\n"), vd);
if ( vd & & (
strncasecmp ( vd , " gcvideo " , 8 ) = = 0 | |
strncasecmp ( vd , " fbcon " , 6 ) = = 0 | |
strncasecmp ( vd , " wii " , 4 ) = = 0 | |
strncasecmp ( vd , " psl1ght " , 8 ) = = 0
) )
2014-03-15 16:59:03 +00:00
framebuffer = SDL_TRUE ;
}
2019-09-08 21:27:35 +00:00
2020-08-15 01:27:16 +00:00
// Renderer choices
// Takes priority over the config.
if ( M_CheckParm ( " -renderer " ) )
{
INT32 i = 0 ;
CV_PossibleValue_t * renderer_list = cv_renderer_t ;
const char * modeparm = M_GetNextParm ( ) ;
while ( renderer_list [ i ] . strvalue )
{
if ( ! stricmp ( modeparm , renderer_list [ i ] . strvalue ) )
{
chosenrendermode = renderer_list [ i ] . value ;
break ;
}
i + + ;
}
}
// Choose Software renderer
2019-12-17 21:04:05 +00:00
else if ( M_CheckParm ( " -software " ) )
2020-08-15 01:27:16 +00:00
chosenrendermode = render_soft ;
# ifdef HWRENDER
// Choose OpenGL renderer
else if ( M_CheckParm ( " -opengl " ) )
chosenrendermode = render_opengl ;
// Don't startup OpenGL
if ( M_CheckParm ( " -nogl " ) )
{
vid . glstate = VID_GL_LIBRARY_ERROR ;
if ( chosenrendermode = = render_opengl )
chosenrendermode = render_none ;
}
2019-09-09 01:25:18 +00:00
# endif
2020-08-15 01:27:16 +00:00
if ( chosenrendermode ! = render_none )
rendermode = chosenrendermode ;
2014-03-15 16:59:03 +00:00
2014-07-26 07:06:00 +00:00
usesdl2soft = M_CheckParm ( " -softblit " ) ;
borderlesswindow = M_CheckParm ( " -borderless " ) ;
2014-03-15 16:59:03 +00:00
2014-07-26 07:06:00 +00:00
//SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2);
VID_Command_ModeList_f ( ) ;
2020-02-18 00:58:32 +00:00
2014-03-15 16:59:03 +00:00
# ifdef HWRENDER
2020-08-15 01:27:16 +00:00
if ( rendermode = = render_opengl )
2020-02-18 00:11:56 +00:00
VID_StartupOpenGL ( ) ;
2014-03-15 16:59:03 +00:00
# endif
2014-07-26 07:06:00 +00:00
2020-04-26 22:46:43 +00:00
// Window icon
# ifdef HAVE_IMAGE
icoSurface = IMG_ReadXPMFromArray ( SDL_icon_xpm ) ;
2020-08-08 08:16:47 +00:00
# endif
2020-04-26 22:46:43 +00:00
2014-07-26 07:06:00 +00:00
// Fury: we do window initialization after GL setup to allow
// SDL_GL_LoadLibrary to work well on Windows
2014-11-12 00:55:07 +00:00
2014-07-26 07:06:00 +00:00
// Create window
//Impl_CreateWindow(USE_FULLSCREEN);
2015-01-01 19:50:31 +00:00
//Impl_SetWindowName("SRB2 "VERSIONSTRING);
2014-07-26 07:06:00 +00:00
VID_SetMode ( VID_GetModeForSize ( BASEVIDWIDTH , BASEVIDHEIGHT ) ) ;
2014-11-12 00:55:07 +00:00
2014-07-26 07:06:00 +00:00
vid . width = BASEVIDWIDTH ; // Default size for startup
vid . height = BASEVIDHEIGHT ; // BitsPerPixel is the SDL interface's
vid . recalc = true ; // Set up the console stufff
vid . direct = NULL ; // Maybe direct access?
vid . bpp = 1 ; // This is the game engine's Bpp
vid . WndParent = NULL ; //For the window?
# ifdef HAVE_TTF
I_ShutdownTTF ( ) ;
2014-03-15 16:59:03 +00:00
# endif
2014-07-26 07:06:00 +00:00
VID_SetMode ( VID_GetModeForSize ( BASEVIDWIDTH , BASEVIDHEIGHT ) ) ;
2014-03-15 16:59:03 +00:00
if ( M_CheckParm ( " -nomousegrab " ) )
mousegrabok = SDL_FALSE ;
2014-07-26 07:06:00 +00:00
#if 0 // defined (_DEBUG)
2014-03-15 16:59:03 +00:00
else
{
char videodriver [ 4 ] = { ' S ' , ' D ' , ' L ' , 0 } ;
if ( ! M_CheckParm ( " -mousegrab " ) & &
2014-07-26 07:06:00 +00:00
* strncpy ( videodriver , SDL_GetCurrentVideoDriver ( ) , 4 ) ! = ' \0 ' & &
strncasecmp ( " x11 " , videodriver , 4 ) = = 0 )
2014-03-15 16:59:03 +00:00
mousegrabok = SDL_FALSE ; //X11's XGrabPointer not good
}
# endif
realwidth = ( Uint16 ) vid . width ;
realheight = ( Uint16 ) vid . height ;
VID_Command_Info_f ( ) ;
SDLdoUngrabMouse ( ) ;
2018-12-23 23:54:15 +00:00
SDL_RaiseWindow ( window ) ;
2018-12-24 03:05:09 +00:00
if ( mousegrabok & & ! disable_mouse )
2020-01-01 12:29:07 +00:00
SDLdoGrabMouse ( ) ;
2018-12-23 23:54:15 +00:00
2014-03-15 16:59:03 +00:00
graphics_started = true ;
}
2020-02-18 00:11:56 +00:00
void VID_StartupOpenGL ( void )
2019-09-09 01:25:18 +00:00
{
# ifdef HWRENDER
static boolean glstartup = false ;
if ( ! glstartup )
{
2020-02-18 00:58:32 +00:00
CONS_Printf ( " VID_StartupOpenGL()... \n " ) ;
2019-09-09 01:25:18 +00:00
HWD . pfnInit = hwSym ( " Init " , NULL ) ;
HWD . pfnFinishUpdate = NULL ;
HWD . pfnDraw2DLine = hwSym ( " Draw2DLine " , NULL ) ;
HWD . pfnDrawPolygon = hwSym ( " DrawPolygon " , NULL ) ;
2020-06-07 18:20:52 +00:00
HWD . pfnDrawIndexedTriangles = hwSym ( " DrawIndexedTriangles " , NULL ) ;
2019-11-12 23:25:40 +00:00
HWD . pfnRenderSkyDome = hwSym ( " RenderSkyDome " , NULL ) ;
2019-09-09 01:25:18 +00:00
HWD . pfnSetBlend = hwSym ( " SetBlend " , NULL ) ;
HWD . pfnClearBuffer = hwSym ( " ClearBuffer " , NULL ) ;
HWD . pfnSetTexture = hwSym ( " SetTexture " , NULL ) ;
2020-01-28 03:16:38 +00:00
HWD . pfnUpdateTexture = hwSym ( " UpdateTexture " , NULL ) ;
2020-08-08 08:16:47 +00:00
HWD . pfnDeleteTexture = hwSym ( " DeleteTexture " , NULL ) ;
2019-09-09 01:25:18 +00:00
HWD . pfnReadRect = hwSym ( " ReadRect " , NULL ) ;
HWD . pfnGClipRect = hwSym ( " GClipRect " , NULL ) ;
HWD . pfnClearMipMapCache = hwSym ( " ClearMipMapCache " , NULL ) ;
HWD . pfnSetSpecialState = hwSym ( " SetSpecialState " , NULL ) ;
HWD . pfnSetPalette = hwSym ( " SetPalette " , NULL ) ;
HWD . pfnGetTextureUsed = hwSym ( " GetTextureUsed " , NULL ) ;
2019-11-12 23:25:40 +00:00
HWD . pfnDrawModel = hwSym ( " DrawModel " , NULL ) ;
HWD . pfnCreateModelVBOs = hwSym ( " CreateModelVBOs " , NULL ) ;
2019-09-09 01:25:18 +00:00
HWD . pfnSetTransform = hwSym ( " SetTransform " , NULL ) ;
HWD . pfnPostImgRedraw = hwSym ( " PostImgRedraw " , NULL ) ;
HWD . pfnFlushScreenTextures = hwSym ( " FlushScreenTextures " , NULL ) ;
HWD . pfnStartScreenWipe = hwSym ( " StartScreenWipe " , NULL ) ;
HWD . pfnEndScreenWipe = hwSym ( " EndScreenWipe " , NULL ) ;
HWD . pfnDoScreenWipe = hwSym ( " DoScreenWipe " , NULL ) ;
HWD . pfnDrawIntermissionBG = hwSym ( " DrawIntermissionBG " , NULL ) ;
HWD . pfnMakeScreenTexture = hwSym ( " MakeScreenTexture " , NULL ) ;
HWD . pfnMakeScreenFinalTexture = hwSym ( " MakeScreenFinalTexture " , NULL ) ;
HWD . pfnDrawScreenFinalTexture = hwSym ( " DrawScreenFinalTexture " , NULL ) ;
2020-01-27 04:57:55 +00:00
2020-08-07 21:17:05 +00:00
HWD . pfnCompileShaders = hwSym ( " CompileShaders " , NULL ) ;
HWD . pfnCleanShaders = hwSym ( " CleanShaders " , NULL ) ;
2020-01-24 00:25:54 +00:00
HWD . pfnSetShader = hwSym ( " SetShader " , NULL ) ;
HWD . pfnUnSetShader = hwSym ( " UnSetShader " , NULL ) ;
2020-01-07 12:35:39 +00:00
2020-01-24 00:25:54 +00:00
HWD . pfnSetShaderInfo = hwSym ( " SetShaderInfo " , NULL ) ;
2020-01-07 12:35:39 +00:00
HWD . pfnLoadCustomShader = hwSym ( " LoadCustomShader " , NULL ) ;
2020-08-15 01:27:16 +00:00
vid . glstate = HWD . pfnInit ( ) ? VID_GL_LIBRARY_LOADED : VID_GL_LIBRARY_ERROR ; // let load the OpenGL library
2020-02-15 16:51:32 +00:00
2020-08-15 01:27:16 +00:00
if ( vid . glstate = = VID_GL_LIBRARY_ERROR )
2020-01-27 04:57:55 +00:00
{
2019-09-09 01:25:18 +00:00
rendermode = render_soft ;
2020-01-27 04:57:55 +00:00
setrenderneeded = 0 ;
}
glstartup = true ;
2019-09-09 01:25:18 +00:00
}
# endif
}
2014-03-15 16:59:03 +00:00
void I_ShutdownGraphics ( void )
{
const rendermode_t oldrendermode = rendermode ;
rendermode = render_none ;
if ( icoSurface ) SDL_FreeSurface ( icoSurface ) ;
icoSurface = NULL ;
2017-05-15 14:43:31 +00:00
if ( oldrendermode = = render_soft )
2014-03-15 16:59:03 +00:00
{
2016-05-10 22:20:14 +00:00
if ( vidSurface ) SDL_FreeSurface ( vidSurface ) ;
vidSurface = NULL ;
2014-03-15 16:59:03 +00:00
if ( vid . buffer ) free ( vid . buffer ) ;
vid . buffer = NULL ;
if ( bufSurface ) SDL_FreeSurface ( bufSurface ) ;
bufSurface = NULL ;
}
2015-01-01 19:50:31 +00:00
I_OutputMsg ( " I_ShutdownGraphics(): " ) ;
2014-03-15 16:59:03 +00:00
// was graphics initialized anyway?
if ( ! graphics_started )
2015-01-01 19:50:31 +00:00
{
I_OutputMsg ( " graphics never started \n " ) ;
2014-03-15 16:59:03 +00:00
return ;
2015-01-01 19:50:31 +00:00
}
2014-03-15 16:59:03 +00:00
graphics_started = false ;
2015-01-01 19:50:31 +00:00
I_OutputMsg ( " shut down \n " ) ;
2014-03-15 16:59:03 +00:00
# ifdef HWRENDER
if ( GLUhandle )
hwClose ( GLUhandle ) ;
2014-07-26 07:06:00 +00:00
if ( sdlglcontext )
{
SDL_GL_DeleteContext ( sdlglcontext ) ;
}
2014-03-15 16:59:03 +00:00
# endif
SDL_QuitSubSystem ( SDL_INIT_VIDEO ) ;
framebuffer = SDL_FALSE ;
}
# endif
2021-03-26 02:14:59 +00:00
void I_GetCursorPosition ( INT32 * x , INT32 * y )
{
SDL_GetMouseState ( x , y ) ;
}
2022-03-27 03:48:08 +00:00
UINT32 I_GetRefreshRate ( void )
{
2022-04-28 02:42:47 +00:00
// Moved to VID_GetRefreshRate.
// Precalculating it like that won't work as
// well for windowed mode since you can drag
// the window around, but very slow PCs might have
// trouble querying mode over and over again.
return refresh_rate ;
2022-03-27 03:48:08 +00:00
}