SRB2/src/sdl12/i_video.c
toasterbabe 3e29ee3f01 Closed captioning!
* Provides a helpful description for the hearing impaired, whether permanent, temporary or situational.
* Consvar "closedcaptioning", with on/off values available.
* Only works if sounds are on. This is frustrating. I will see what I can do to allow it to work with sounds off in future, but for now it's dependent in order to properly accept or decline sounds.
* Thanks to MI for making that wiki page a lot more comprehensive a few days ago.

* Weapon ring is now a seperate sfx_wepfir instead of doubling up on sfx_thok.

* Also, made V_StringWidth work with V_NOSCALESTART.
2017-04-17 01:09:47 +01:00

2104 lines
53 KiB
C

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// Copyright (C) 1993-1996 by id Software, Inc.
// Portions Copyright (C) 1998-2000 by DooM Legacy Team.
//
// 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>
#ifndef _WIN32_WCE
#include <signal.h>
#endif
#ifdef _MSC_VER
#pragma warning(disable : 4214 4244)
#endif
#ifdef HAVE_SDL
#include "SDL.h"
#ifdef _MSC_VER
#pragma warning(default : 4214 4244)
#endif
#if SDL_VERSION_ATLEAST(1,2,9) && defined (_arch_dreamcast)
#define HAVE_DCSDL
#include "SDL_dreamcast.h"
#endif
#if SDL_VERSION_ATLEAST(1,2,9) && defined (GP2X)
#define HAVE_GP2XSDL
#include "SDL_gp2x.h"
#endif
#if SDL_VERSION_ATLEAST(1,3,0)
#define SDLK_EQUALS SDLK_KP_EQUALSAS400
#define SDLK_LMETA SDLK_LGUI
#define SDLK_RMETA SDLK_RGUI
#else
#define HAVE_SDLMETAKEYS
#endif
#ifdef HAVE_TTF
#include "i_ttf.h"
#endif
#ifdef HAVE_IMAGE
#include "SDL_image.h"
#elseif !(defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X))
#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
#endif
#ifdef HAVE_IMAGE
#include "SDL_icon.xpm"
#endif
#include "../doomdef.h"
#if defined (_WIN32) && !defined (_XBOX)
#include "SDL_syswm.h"
#endif
#ifdef _arch_dreamcast
#include <conio/conio.h>
#include <dc/maple.h>
#include <dc/maple/vmu.h>
//#include "SRB2DC/VMU.xbm"
//#include <dc/pvr.h>
//#define malloc pvr_mem_malloc
//#define free pvr_mem_free
#endif
#if defined (_XBOX) && defined (__GNUC__)
#include <openxdk/debug.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"
#include "../i_sound.h" // midi pause/unpause
#include "../i_joy.h"
#include "../st_stuff.h"
#include "../g_game.h"
#include "../i_video.h"
#include "../console.h"
#include "../command.h"
#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
#ifdef REMOTE_DEBUGGING
#ifdef _WII
#include <debug.h>
#endif
#endif
#ifdef HAVE_FILTER
#define FILTERS
#include "filter/filters.h"
#endif
// maximum number of windowed modes (see windowedModes[][])
#if defined (_WIN32_WCE) || defined (DC) || defined (PSP) || defined(GP2X)
#define MAXWINMODES (1)
#elif defined (WII)
#define MAXWINMODES (8)
#elif defined (_PS3)
#define MAXWINMODES (26)
#else
#define MAXWINMODES (27)
#endif
/** \brief
*/
static INT32 numVidModes = -1;
/** \brief
*/
static char vidModeName[33][32]; // allow 33 different modes
rendermode_t rendermode=render_soft;
boolean highcolor = false;
// synchronize page flipping with screen refresh
#if defined(DC) || (defined(GP2X) && !defined(HAVE_GP2XSDL))
consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#else
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
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;
#define USE_MOUSEINPUT (!disable_mouse && cv_usemouse.value && SDL_GetAppState() & SDL_APPACTIVE)
#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;
// SDL vars
#ifndef HWRENDER //[segabor] !!! I had problem compiling this source with gcc 3.3
static SDL_Surface *vidSurface = NULL;
#endif
static SDL_Surface *bufSurface = NULL;
static SDL_Surface *icoSurface = NULL;
static SDL_Color localPalette[256];
static SDL_Rect **modeList = NULL;
#ifdef DC
static Uint8 BitsPerPixel = 15;
#else
static Uint8 BitsPerPixel = 16;
#endif
static Uint16 realwidth = BASEVIDWIDTH;
static Uint16 realheight = BASEVIDHEIGHT;
#ifdef _WIN32_WCE
static const Uint32 surfaceFlagsW = SDL_HWPALETTE; //Can't handle WinCE changing sides
#else
static const Uint32 surfaceFlagsW = SDL_HWPALETTE/*|SDL_RESIZABLE*/;
#endif
#ifdef _PSP
static const Uint32 surfaceFlagsF = SDL_HWSURFACE|SDL_FULLSCREEN;
#else
static const Uint32 surfaceFlagsF = SDL_HWPALETTE|SDL_FULLSCREEN;
#endif
static SDL_bool mousegrabok = SDL_TRUE;
#define HalfWarpMouse(x,y) SDL_WarpMouse((Uint16)(x/2),(Uint16)(y/2))
#if defined (_WIN32_WCE) || defined (DC) || defined (PSP) || defined(GP2X)
static SDL_bool videoblitok = SDL_TRUE;
#else
static SDL_bool videoblitok = SDL_FALSE;
#endif
static SDL_bool exposevideo = SDL_FALSE;
// windowed video modes from which to choose from.
static INT32 windowedModes[MAXWINMODES][2] =
{
#if !(defined (_WIN32_WCE) || defined (DC) || defined (PSP) || defined (GP2X))
#ifndef WII
#ifndef _PS3
{1920,1200}, // 1.60,6.00
#endif
{1680,1050}, // 1.60,5.25
{1600,1200}, // 1.33,5.00
{1600,1000}, // 1.60,5.00
{1536,1152}, // 1.33,4.80
{1536, 960}, // 1.60,4.80
{1440, 900}, // 1.60,4.50
{1400,1050}, // 1.33,4.375
{1400, 875}, // 1.60,4.375
{1360, 850}, // 1.60,4.25
{1280, 960}, // 1.33,4.00
{1280, 800}, // 1.60,4.00
{1152, 864}, // 1.33,3.60
{1120, 700}, // 1.60,3.50
{1024, 768}, // 1.33,3.20
{ 960, 720}, // 1.33,3.00
{ 960, 600}, // 1.60,3.00
{ 800, 600}, // 1.33,2.50
{ 800, 500}, // 1.60,2.50
#endif
{ 640, 480}, // 1.33,2.00
{ 640, 400}, // 1.60,2.00
{ 576, 432}, // 1.33,1.80
{ 512, 384}, // 1.33,1.60
{ 416, 312}, // 1.33,1.30
{ 400, 300}, // 1.33,1.25
{ 320, 240}, // 1.33,1.00
#endif
{ 320, 200}, // 1.60,1.00
};
static void SDLSetMode(INT32 width, INT32 height, INT32 bpp, Uint32 flags)
{
const char *SDLVD = I_GetEnv("SDL_VIDEODRIVER");
#ifdef _WIN32_WCE
if (bpp < 16)
bpp = 16; // 256 mode poo
#endif
#ifdef _WII
bpp = 16; // 8-bit mode poo
#endif
#ifdef DC
if (bpp < 15)
bpp = 15;
height = 240;
#endif
#ifdef PSP
bpp = 16;
#endif
#ifdef GP2X
bpp = 16;
#ifdef HAVE_GP2XSDL
height = 240;
#endif
#endif
#ifdef FILTERS
bpp = Setupf2x(width, height, bpp);
#endif
if (SDLVD && strncasecmp(SDLVD,"glSDL",6) == 0) //for glSDL videodriver
vidSurface = SDL_SetVideoMode(width, height,0,SDL_DOUBLEBUF);
#ifdef _WII // don't want it to use HWSURFACE, so make it first here
else if (SDL_VideoModeOK(width, height, bpp, flags|SDL_SWSURFACE|SDL_DOUBLEBUF) >= bpp) // SDL Wii uses double buffering
vidSurface = SDL_SetVideoMode(width, height, bpp, flags|SDL_SWSURFACE|SDL_DOUBLEBUF);
#endif
else if (cv_vidwait.value && videoblitok && SDL_VideoModeOK(width, height, bpp, flags|SDL_HWSURFACE|SDL_DOUBLEBUF) >= bpp)
vidSurface = SDL_SetVideoMode(width, height, bpp, flags|SDL_HWSURFACE|SDL_DOUBLEBUF);
else if (videoblitok && SDL_VideoModeOK(width, height, bpp, flags|SDL_HWSURFACE) >= bpp)
vidSurface = SDL_SetVideoMode(width, height, bpp, flags|SDL_HWSURFACE);
else if (SDL_VideoModeOK(width, height, bpp, flags|SDL_SWSURFACE) >= bpp)
vidSurface = SDL_SetVideoMode(width, height, bpp, flags|SDL_SWSURFACE);
else return;
realwidth = (Uint16)width;
realheight = (Uint16)height;
#ifdef HAVE_DCSDL
//SDL_DC_SetWindow(320,200);
SDL_DC_EmulateMouse(SDL_FALSE);
SDL_DC_EmulateKeyboard(SDL_TRUE);
#endif
#ifdef HAVE_GP2XSDL
SDL_ShowCursor(SDL_DISABLE); //For GP2X Open2x
#endif
#ifdef FILTERS
if (vidSurface && preSurface && f2xSurface)
{
vid.width = width/2;
vid.height = height/2;
}
#endif
}
//
// Translates the SDL key into SRB2 key
//
static INT32 SDLatekey(SDLKey sym)
{
INT32 rc = sym + 0x80;
#ifdef _WIN32_WCE
if (sym == SDLK_KP8)
sym = SDLK_UP;
else if (sym == SDLK_KP4)
sym = SDLK_LEFT;
else if (sym == SDLK_KP6)
sym = SDLK_RIGHT;
else if (sym == SDLK_KP2)
sym = SDLK_DOWN;
#endif
switch (sym)
{
case SDLK_LEFT:
rc = KEY_LEFTARROW;
break;
case SDLK_RIGHT:
rc = KEY_RIGHTARROW;
break;
case SDLK_DOWN:
rc = KEY_DOWNARROW;
break;
case SDLK_UP:
rc = KEY_UPARROW;
break;
case SDLK_ESCAPE:
rc = KEY_ESCAPE;
break;
case SDLK_SPACE:
rc = KEY_SPACE;
break;
case SDLK_RETURN:
case SDLK_KP_ENTER:
rc = KEY_ENTER;
break;
case SDLK_TAB:
rc = KEY_TAB;
break;
case SDLK_F1:
rc = KEY_F1;
break;
case SDLK_F2:
rc = KEY_F2;
break;
case SDLK_F3:
rc = KEY_F3;
break;
case SDLK_F4:
rc = KEY_F4;
break;
case SDLK_F5:
rc = KEY_F5;
break;
case SDLK_F6:
rc = KEY_F6;
break;
case SDLK_F7:
rc = KEY_F7;
break;
case SDLK_F8:
rc = KEY_F8;
break;
case SDLK_F9:
rc = KEY_F9;
break;
case SDLK_F10:
rc = KEY_F10;
break;
case SDLK_F11:
rc = KEY_F11;
break;
case SDLK_F12:
rc = KEY_F12;
break;
case SDLK_BACKSPACE:
rc = KEY_BACKSPACE;
break;
case SDLK_DELETE:
rc = KEY_DEL;
break;
case SDLK_KP_EQUALS: //Alam & Logan: WTF? Mac KB haves one! XD
case SDLK_PAUSE:
rc = KEY_PAUSE;
break;
case SDLK_EQUALS:
case SDLK_PLUS:
rc = KEY_EQUALS;
break;
case SDLK_MINUS:
rc = KEY_MINUS;
break;
case SDLK_LSHIFT:
rc = KEY_LSHIFT;
break;
case SDLK_RSHIFT:
rc = KEY_RSHIFT;
break;
case SDLK_CAPSLOCK:
rc = KEY_CAPSLOCK;
break;
case SDLK_LCTRL:
rc = KEY_LCTRL;
break;
case SDLK_RCTRL:
rc = KEY_RCTRL;
break;
case SDLK_LALT:
rc = KEY_LALT;
break;
case SDLK_RALT:
rc = KEY_RALT;
break;
case SDLK_NUMLOCK:
rc = KEY_NUMLOCK;
break;
case SDLK_SCROLLOCK:
rc = KEY_SCROLLLOCK;
break;
case SDLK_PAGEUP:
rc = KEY_PGUP;
break;
case SDLK_PAGEDOWN:
rc = KEY_PGDN;
break;
case SDLK_END:
rc = KEY_END;
break;
case SDLK_HOME:
rc = KEY_HOME;
break;
case SDLK_INSERT:
rc = KEY_INS;
break;
case SDLK_KP0:
rc = KEY_KEYPAD0;
break;
case SDLK_KP1:
rc = KEY_KEYPAD1;
break;
case SDLK_KP2:
rc = KEY_KEYPAD2;
break;
case SDLK_KP3:
rc = KEY_KEYPAD3;
break;
case SDLK_KP4:
rc = KEY_KEYPAD4;
break;
case SDLK_KP5:
rc = KEY_KEYPAD5;
break;
case SDLK_KP6:
rc = KEY_KEYPAD6;
break;
case SDLK_KP7:
rc = KEY_KEYPAD7;
break;
case SDLK_KP8:
rc = KEY_KEYPAD8;
break;
case SDLK_KP9:
rc = KEY_KEYPAD9;
break;
case SDLK_KP_PERIOD:
rc = KEY_KPADDEL;
break;
case SDLK_KP_DIVIDE:
rc = KEY_KPADSLASH;
break;
case SDLK_KP_MULTIPLY:
rc = '*';
break;
case SDLK_KP_MINUS:
rc = KEY_MINUSPAD;
break;
case SDLK_KP_PLUS:
rc = KEY_PLUSPAD;
break;
#ifndef _arch_dreamcast
case SDLK_LSUPER:
#ifdef HAVE_SDLMETAKEYS
case SDLK_LMETA:
#endif
rc = KEY_LEFTWIN;
break;
case SDLK_RSUPER:
#ifdef HAVE_SDLMETAKEYS
case SDLK_RMETA:
#endif
rc = KEY_RIGHTWIN;
break;
case SDLK_MENU:
rc = KEY_MENU;
break;
#endif
default:
if (sym >= SDLK_SPACE && sym <= SDLK_DELETE)
rc = sym - SDLK_SPACE + ' ';
else if (sym >= 'A' && sym <= 'Z')
rc = sym - 'A' + 'a';
else if (sym)
{
I_OutputMsg("Unknown Keycode %i, Name: %s\n",sym, SDL_GetKeyName( sym ));
}
else if (!sym) rc = 0;
break;
}
return rc;
}
static void SDLdoUngrabMouse(void)
{
if (SDL_GRAB_ON == SDL_WM_GrabInput(SDL_GRAB_QUERY))
{
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
}
void SDLforceUngrabMouse(void)
{
if (SDL_WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO)
SDL_WM_GrabInput(SDL_GRAB_OFF);
}
static void VID_Command_NumModes_f (void)
{
CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), VID_NumModes());
}
static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText)
{
INT32 vfBPP;
const SDL_Surface *VidSur = SDL_GetVideoSurface();
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);
if (infoSurface->flags&SDL_HWSURFACE)
CONS_Printf("%s", M_GetText(" Stored in video memory\n"));
else if (infoSurface->flags&SDL_OPENGL)
CONS_Printf("%s", M_GetText(" Stored in an OpenGL context\n"));
else if (infoSurface->flags&SDL_PREALLOC)
CONS_Printf("%s", M_GetText(" Uses preallocated memory\n"));
else
CONS_Printf("%s", M_GetText(" Stored in system memory\n"));
if (infoSurface->flags&SDL_ASYNCBLIT)
CONS_Printf("%s", M_GetText(" Uses asynchronous blits if possible\n"));
else
CONS_Printf("%s", M_GetText(" Uses synchronous blits if possible\n"));
if (infoSurface->flags&SDL_ANYFORMAT)
CONS_Printf("%s", M_GetText(" Allows any pixel-format\n"));
if (infoSurface->flags&SDL_HWPALETTE)
CONS_Printf("%s", M_GetText(" Has exclusive palette access\n"));
else if (VidSur == infoSurface)
CONS_Printf("%s", M_GetText(" Has nonexclusive palette access\n"));
if (infoSurface->flags&SDL_DOUBLEBUF)
CONS_Printf("%s", M_GetText(" Double buffered\n"));
else if (VidSur == infoSurface)
CONS_Printf("%s", M_GetText(" No hardware flipping\n"));
if (infoSurface->flags&SDL_FULLSCREEN)
CONS_Printf("%s", M_GetText(" Full screen\n"));
else if (infoSurface->flags&SDL_RESIZABLE)
CONS_Printf("%s", M_GetText(" Resizable window\n"));
else if (VidSur == infoSurface)
CONS_Printf("%s", M_GetText(" Nonresizable window\n"));
if (infoSurface->flags&SDL_HWACCEL)
CONS_Printf("%s", M_GetText(" Uses hardware acceleration blit\n"));
if (infoSurface->flags&SDL_SRCCOLORKEY)
CONS_Printf("%s", M_GetText(" Use colorkey blitting\n"));
if (infoSurface->flags&SDL_RLEACCEL)
CONS_Printf("%s", M_GetText(" Colorkey RLE acceleration blit\n"));
if (infoSurface->flags&SDL_SRCALPHA)
CONS_Printf("%s", M_GetText(" Use alpha blending acceleration blit\n"));
}
static void VID_Command_Info_f (void)
{
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
}
SurfaceInfo(bufSurface, M_GetText("Current Engine Mode"));
#ifdef FILTERS
SurfaceInfo(preSurface, M_GetText("Prebuffer Mode"));
SurfaceInfo(f2xSurface, M_GetText("Postbuffer Mode"));
#endif
SurfaceInfo(vidSurface, M_GetText("Current Video Mode"));
}
static void VID_Command_ModeList_f(void)
{
#if !defined (DC) && !defined (_WIN32_WCE) && !defined (_PSP) && !defined(GP2X)
INT32 i;
#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
if (modeList == (SDL_Rect **)0 && cv_fullscreen.value)
{
CONS_Printf("%s", M_GetText("No video modes present\n"));
cv_fullscreen.value = 0;
}
else if (modeList != (SDL_Rect **)0)
{
numVidModes = 0;
if (modeList == (SDL_Rect **)-1)
numVidModes = -1; // should not happen with fullscreen modes
else while (modeList[numVidModes])
numVidModes++;
}
CONS_Printf(M_GetText("Found %d FullScreen Video Modes:\n"), numVidModes);
for (i=0 ; i<numVidModes; i++)
{ // fullscreen modes
INT32 modeNum = firstEntry + i;
if (modeNum >= numVidModes)
break;
CONS_Printf(M_GetText("%dx%d and "),
modeList[modeNum]->w,
modeList[modeNum]->h);
}
CONS_Printf("%s", M_GetText("None\n"));
#endif
}
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
}
#if defined(RPC_NO_WINDOWS_H) && !defined(_WIN32_WCE)
static VOID MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(hWnd);
UNREFERENCED_PARAMETER(message);
UNREFERENCED_PARAMETER(wParam);
switch (message)
{
case WM_SETTEXT:
COM_BufAddText((LPCSTR)lParam);
break;
}
}
#endif
#if 0 //#ifdef _WIN32
// Disable Composition in Vista DWM (Desktop Window Manager) ----------------
static HMODULE DMdll = NULL;
typedef HRESULT (CALLBACK *P_DwmIsCompositionEnabled) (BOOL *pfEnabled);
static P_DwmIsCompositionEnabled pfnDwmIsCompositionEnabled = NULL;
typedef HRESULT (CALLBACK *P_DwmEnableComposition) (BOOL fEnable);
static P_DwmEnableComposition pfnDwmEnableComposition = NULL;
static BOOL AeroWasEnabled = FALSE;
static inline VOID UnloadDM(VOID)
{
pfnDwmEnableComposition = NULL;
pfnDwmIsCompositionEnabled = NULL;
if (DMdll) FreeLibrary(DMdll);
DMdll = NULL;
}
static inline BOOL LoadDM(VOID)
{
if (DMdll)
return TRUE;
DMdll = LoadLibraryA("dwmapi.dll");
if (DMdll)
I_OutputMsg("dmwapi.dll loaded, Vista's Desktop Window Manager API\n");
else
return FALSE;
pfnDwmIsCompositionEnabled = (P_DwmIsCompositionEnabled)GetProcAddress(DMdll, "DwmIsCompositionEnabled");
if (pfnDwmIsCompositionEnabled)
I_OutputMsg("Composition Aero API found, DwmIsCompositionEnabled\n");
pfnDwmEnableComposition = (P_DwmEnableComposition)GetProcAddress(DMdll, "DwmEnableComposition");
if (pfnDwmEnableComposition)
I_OutputMsg("Composition Aero API found, DwmEnableComposition\n");
return TRUE;
}
static inline VOID DisableAero(VOID)
{
BOOL pfnDwmEnableCompositiond = FALSE;
AeroWasEnabled = FALSE;
if (!LoadDM())
return;
if (pfnDwmIsCompositionEnabled && SUCCEEDED(pfnDwmIsCompositionEnabled(&pfnDwmEnableCompositiond)))
I_OutputMsg("Got the result of DwmIsCompositionEnabled, %i\n", pfnDwmEnableCompositiond);
else
return;
if ((AeroWasEnabled = pfnDwmEnableCompositiond))
I_OutputMsg("Disable the Aero rendering\n");
else
return;
if (pfnDwmEnableComposition && SUCCEEDED(pfnDwmEnableComposition(FALSE)))
I_OutputMsg("Aero rendering disabled\n");
else
I_OutputMsg("We failed to disable the Aero rendering\n");
}
static inline VOID ResetAero(VOID)
{
if (pfnDwmEnableComposition && AeroWasEnabled)
{
if (SUCCEEDED(pfnDwmEnableComposition(AeroWasEnabled)))
I_OutputMsg("Aero rendering setting restored\n");
else
I_OutputMsg("We failed to restore Aero rendering\n");
}
UnloadDM();
}
#endif
static inline void SDLJoyRemap(event_t *event)
{
#if defined(GP2X)
#define GP2X_BUTTON_UP (0)
#define GP2X_BUTTON_DOWN (4)
#define GP2X_BUTTON_LEFT (2)
#define GP2X_BUTTON_RIGHT (6)
#define GP2X_BUTTON_UPLEFT (1)
#define GP2X_BUTTON_UPRIGHT (7)
#define GP2X_BUTTON_DOWNLEFT (3)
#define GP2X_BUTTON_DOWNRIGHT (5)
#define GP2X_BUTTON_CLICK (18)
#define GP2X_BUTTON_A (12)
#define GP2X_BUTTON_B (13)
#define GP2X_BUTTON_X (14)
#define GP2X_BUTTON_Y (15)
#define GP2X_BUTTON_L (10)
#define GP2X_BUTTON_R (11)
#define GP2X_BUTTON_START (8)
#define GP2X_BUTTON_SELECT (9)
#define GP2X_BUTTON_VOLUP (16)
#define GP2X_BUTTON_VOLDOWN (17)
if ((event->type == ev_keydown || event->type == ev_keyup) && (KEY_JOY1 <= event->data1 && event->data1 <= KEY_JOY1+JOYBUTTONS))
{
INT32 button = event->data1-KEY_JOY1;
if (button <= 7)
{
static UINT8 DPAD = 0;
if (event->type == ev_keyup)
{
event->type = ev_console;
DPAD &= ~(1<<button);
}
else
{
event->type = ev_joystick;
DPAD |= 1<<button;
}
event->data2 = event->data3 = INT32_MAX;
if ((DPAD & (1<<GP2X_BUTTON_UP)) && ((DPAD & (1<<GP2X_BUTTON_UPLEFT)) || (DPAD & (1<<GP2X_BUTTON_UPRIGHT))))
button = GP2X_BUTTON_UP;
if ((DPAD & (1<<GP2X_BUTTON_LEFT)) && ((DPAD & (1<<GP2X_BUTTON_UPLEFT)) || (DPAD & (1<<GP2X_BUTTON_DOWNLEFT))))
button = GP2X_BUTTON_LEFT;
if ((DPAD & (1<<GP2X_BUTTON_DOWN)) && ((DPAD & (1<<GP2X_BUTTON_DOWNLEFT)) || (DPAD & (1<<GP2X_BUTTON_DOWNRIGHT))))
button = GP2X_BUTTON_DOWN;
if ((DPAD & (1<<GP2X_BUTTON_RIGHT)) && ((DPAD & (1<<GP2X_BUTTON_UPRIGHT)) || (DPAD & (1<<GP2X_BUTTON_DOWNRIGHT))))
button = GP2X_BUTTON_RIGHT;
if (DPAD == 0)
{
event->type = ev_joystick;
event->data2 = event->data3 = 0;
}
else switch (button)
{
case GP2X_BUTTON_UP:
event->data3 = -1;
break;
case GP2X_BUTTON_DOWN:
event->data3 = 1;
break;
case GP2X_BUTTON_LEFT:
event->data2 = -1;
break;
case GP2X_BUTTON_RIGHT:
event->data2 = 1;
break;
case GP2X_BUTTON_UPLEFT:
event->data2 = -1;
event->data3 = -1;
break;
case GP2X_BUTTON_UPRIGHT:
event->data2 = 1;
event->data3 = -1;
break;
case GP2X_BUTTON_DOWNLEFT:
event->data2 = -1;
event->data3 = 1;
break;
case GP2X_BUTTON_DOWNRIGHT:
event->data2 = 1;
event->data3 = 1;
default:
break;
}
event->data1 = 0;
return;
}
else switch (button)
{
case GP2X_BUTTON_CLICK:
event->data1 = KEY_ENTER;
break;
case GP2X_BUTTON_A:
event->data1 = KEY_JOY1+0;
break;
case GP2X_BUTTON_B:
event->data1 = KEY_JOY1+2;
break;
case GP2X_BUTTON_X:
event->data1 = KEY_JOY1+3;
break;
case GP2X_BUTTON_Y:
event->data1 = KEY_JOY1+1;
break;
case GP2X_BUTTON_L:
event->data1 = KEY_JOY1+4;
break;
case GP2X_BUTTON_R:
event->data1 = KEY_JOY1+5;
break;
case GP2X_BUTTON_START:
event->data1 = KEY_ESCAPE;
break;
case GP2X_BUTTON_SELECT:
event->data1 = KEY_JOY1+8;
break;
case GP2X_BUTTON_VOLUP:
event->data1 = KEY_JOY1+6;
break;
case GP2X_BUTTON_VOLDOWN:
event->data1 = KEY_JOY1+7;
break;
default:
break;
}
//I_OutputMsg("Button %i: event key %i and type: %i\n", button, event->data1, event->type);
}
#elif defined(_PSP)
if (event->data1 > KEY_JOY1 + 9 + 2) // All button after D-Pad and Select/Start
event->data1 -= 4; // remap D-pad to Hats, offset of -4
else if (event->data1 == KEY_JOY1 + 6) // Down
event->data1 = KEY_HAT1+1;
else if (event->data1 == KEY_JOY1 + 7) // Left
event->data1 = KEY_HAT1+2;
else if (event->data1 == KEY_JOY1 + 8) // Up
event->data1 = KEY_HAT1+0;
else if (event->data1 == KEY_JOY1 + 9) // Right
event->data1 = KEY_HAT1+3;
else if (event->data1 == KEY_JOY1 + 10) // Select
event->data1 = KEY_TAB;
else if (event->data1 == KEY_JOY1 + 11) // Start
event->data1 = KEY_ESCAPE;
#else
(void)event;
#endif
}
static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which)
{
#ifdef _arch_dreamcast // -128 to 127 SDL for DC have give us a smaller range
INT32 raxis = axis*8;
#else // -32768 to 32767
INT32 raxis = axis/32;
#endif
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;
}
void I_GetEvent(void)
{
SDL_Event inputEvent;
static SDL_bool sdlquit = SDL_FALSE; //Alam: once, just once
event_t event;
if (!graphics_started)
return;
memset(&inputEvent, 0x00, sizeof(inputEvent));
while (SDL_PollEvent(&inputEvent))
{
memset(&event,0x00,sizeof (event_t));
switch (inputEvent.type)
{
case SDL_ACTIVEEVENT:
if (inputEvent.active.state & (SDL_APPACTIVE|SDL_APPINPUTFOCUS))
{
// pause music when alt-tab
if (inputEvent.active.gain /*&& !paused */)
{
static SDL_bool firsttimeonmouse = SDL_TRUE;
if (!firsttimeonmouse)
{
if (cv_usemouse.value) I_StartupMouse();
}
else firsttimeonmouse = SDL_FALSE;
//if (!netgame && !con_destlines) paused = false;
if (gamestate == GS_LEVEL)
if (!paused) I_ResumeSong(0); //resume it
}
else /*if (!paused)*/
{
if (!disable_mouse)
SDLforceUngrabMouse();
if (!netgame && gamestate == GS_LEVEL) paused = true;
memset(gamekeydown, 0, NUMKEYS);
//S_PauseSound();
if (gamestate == GS_LEVEL)
I_PauseSong(0); //pause it
}
}
if (MOUSE_MENU)
{
SDLdoUngrabMouse();
break;
}
if ((SDL_APPMOUSEFOCUS&inputEvent.active.state) && USE_MOUSEINPUT && inputEvent.active.gain)
HalfWarpMouse(realwidth, realheight);
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
/// \todo inputEvent.key.which?
if (inputEvent.type == SDL_KEYUP)
event.type = ev_keyup;
else if (inputEvent.type == SDL_KEYDOWN)
event.type = ev_keydown;
else break;
event.data1 = SDLatekey(inputEvent.key.keysym.sym);
if (event.data1) D_PostEvent(&event);
break;
case SDL_MOUSEMOTION:
/// \todo inputEvent.motion.which
if (MOUSE_MENU)
{
SDLdoUngrabMouse();
break;
}
if (USE_MOUSEINPUT)
{
// If the event is from warping the pointer back to middle
// of the screen then ignore it.
if ((inputEvent.motion.x == realwidth/2) &&
(inputEvent.motion.y == realheight/2))
{
break;
}
else
{
event.data2 = +inputEvent.motion.xrel;
event.data3 = -inputEvent.motion.yrel;
}
event.type = ev_mouse;
D_PostEvent(&event);
// Warp the pointer back to the middle of the window
// or we cannot move any further if it's at a border.
if ((inputEvent.motion.x < (realwidth/2 )-(realwidth/4 )) ||
(inputEvent.motion.y < (realheight/2)-(realheight/4)) ||
(inputEvent.motion.x > (realwidth/2 )+(realwidth/4 )) ||
(inputEvent.motion.y > (realheight/2)+(realheight/4) ) )
{
//if (SDL_GRAB_ON == SDL_WM_GrabInput(SDL_GRAB_QUERY) || !mousegrabok)
HalfWarpMouse(realwidth, realheight);
}
}
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
/// \todo inputEvent.button.which
if (USE_MOUSEINPUT)
{
if (inputEvent.type == SDL_MOUSEBUTTONUP)
event.type = ev_keyup;
else if (inputEvent.type == SDL_MOUSEBUTTONDOWN)
event.type = ev_keydown;
else break;
if (inputEvent.button.button==SDL_BUTTON_WHEELUP || inputEvent.button.button==SDL_BUTTON_WHEELDOWN)
{
if (inputEvent.type == SDL_MOUSEBUTTONUP)
event.data1 = 0; //Alam: dumb! this could be a real button with some mice
else
event.data1 = KEY_MOUSEWHEELUP + inputEvent.button.button - SDL_BUTTON_WHEELUP;
}
else if (inputEvent.button.button == SDL_BUTTON_MIDDLE)
event.data1 = KEY_MOUSE1+2;
else if (inputEvent.button.button == SDL_BUTTON_RIGHT)
event.data1 = KEY_MOUSE1+1;
else if (inputEvent.button.button <= MOUSEBUTTONS)
event.data1 = KEY_MOUSE1 + inputEvent.button.button - SDL_BUTTON_LEFT;
if (event.data1) D_PostEvent(&event);
}
break;
case SDL_JOYAXISMOTION:
inputEvent.jaxis.which++;
inputEvent.jaxis.axis++;
event.data1 = event.data2 = event.data3 = INT32_MAX;
if (cv_usejoystick.value == inputEvent.jaxis.which)
{
event.type = ev_joystick;
}
else if (cv_usejoystick.value == inputEvent.jaxis.which)
{
event.type = ev_joystick2;
}
else break;
//axis
if (inputEvent.jaxis.axis > JOYAXISSET*2)
break;
//vaule
if (inputEvent.jaxis.axis%2)
{
event.data1 = inputEvent.jaxis.axis / 2;
event.data2 = SDLJoyAxis(inputEvent.jaxis.value, event.type);
}
else
{
inputEvent.jaxis.axis--;
event.data1 = inputEvent.jaxis.axis / 2;
event.data3 = SDLJoyAxis(inputEvent.jaxis.value, event.type);
}
D_PostEvent(&event);
break;
case SDL_JOYBALLMOTION:
case SDL_JOYHATMOTION:
break; //NONE
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
inputEvent.jbutton.which++;
if (cv_usejoystick.value == inputEvent.jbutton.which)
event.data1 = KEY_JOY1;
else if (cv_usejoystick.value == inputEvent.jbutton.which)
event.data1 = KEY_2JOY1;
else break;
if (inputEvent.type == SDL_JOYBUTTONUP)
event.type = ev_keyup;
else if (inputEvent.type == SDL_JOYBUTTONDOWN)
event.type = ev_keydown;
else break;
if (inputEvent.jbutton.button < JOYBUTTONS)
event.data1 += inputEvent.jbutton.button;
else
break;
SDLJoyRemap(&event);
if (event.type != ev_console) D_PostEvent(&event);
break;
#ifndef _WIN32_WCE
case SDL_QUIT:
if (!sdlquit)
{
sdlquit = SDL_TRUE;
M_QuitResponse('y');
}
break;
#endif
#if defined(RPC_NO_WINDOWS_H) && !defined(_WIN32_WCE)
case SDL_SYSWMEVENT:
MainWndproc(inputEvent.syswm.msg->hwnd,
inputEvent.syswm.msg->msg,
inputEvent.syswm.msg->wParam,
inputEvent.syswm.msg->lParam);
break;
#endif
case SDL_VIDEORESIZE:
if (gamestate == GS_LEVEL || gamestate == GS_TITLESCREEN || gamestate == GS_EVALUATION)
setmodeneeded = VID_GetModeForSize(inputEvent.resize.w,inputEvent.resize.h)+1;
if (render_soft == rendermode)
{
#ifdef FILTERS
INT32 filtervalue = cv_filter.value;
if (blitfilter) CV_SetValue(&cv_filter,1);
#endif
SDLSetMode(realwidth, realheight, vid.bpp*8, surfaceFlagsW);
if (vidSurface) SDL_SetColors(vidSurface, localPalette, 0, 256);
#ifdef FILTERS
CV_SetValue(&cv_filter,filtervalue);
#endif
}
else
SDLSetMode(realwidth, realheight, vid.bpp*8, surfaceFlagsW);
if (!vidSurface)
I_Error("Could not reset vidmode: %s\n",SDL_GetError());
break;
case SDL_VIDEOEXPOSE:
exposevideo = SDL_TRUE;
break;
default:
break;
}
}
//reset wheel like in win32, I don't understand it but works
gamekeydown[KEY_MOUSEWHEELDOWN] = gamekeydown[KEY_MOUSEWHEELUP] = 0;
}
void I_StartupMouse(void)
{
static SDL_bool firsttimeonmouse = SDL_TRUE;
if (disable_mouse)
return;
if (!firsttimeonmouse)
HalfWarpMouse(realwidth, realheight); // warp to center
else
firsttimeonmouse = SDL_FALSE;
if (cv_usemouse.value)
return;
else
SDLdoUngrabMouse();
}
//
// I_OsPolling
//
void I_OsPolling(void)
{
if (consolevent)
I_GetConsoleEvents();
if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK)
{
SDL_JoystickUpdate();
I_GetJoystickEvents();
I_GetJoystick2Events();
}
#ifdef _arch_dreamcast
//vmu_set_icon(VMU_bits);
#endif
I_GetMouseEvents();
I_GetEvent();
}
//
// I_UpdateNoBlit
//
void I_UpdateNoBlit(void)
{
if (!vidSurface)
return;
#ifdef HWRENDER
if (rendermode != render_soft)
OglSdlFinishUpdate(cv_vidwait.value);
else
#endif
if (vidSurface->flags&SDL_DOUBLEBUF)
SDL_Flip(vidSurface);
else if (exposevideo)
SDL_UpdateRect(vidSurface, 0, 0, 0, 0);
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)
{
static boolean skip = false;
if (render_soft != rendermode)
return false;
skip = !skip;
#if 0 //(defined (GP2X) || defined (PSP) || defined (_arch_dreamcast))
return skip;
#endif
switch (gamestate)
{
case GS_LEVEL:
if (!paused)
return false;
//case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible
case GS_WAITINGPLAYERS:
return skip; // Skip odd frames
default:
return false;
}
}
static inline SDL_bool SDLmatchVideoformat(void)
{
const SDL_PixelFormat *vidformat = vidSurface->format;
const INT32 vfBPP = vidformat?vidformat->BitsPerPixel:0;
return (((vfBPP == 8 && vid.bpp == 1 &&
!vidformat->Rmask && !vidformat->Gmask && !vidformat->Bmask) ||
(vfBPP == 15 && vid.bpp == 2 && vidformat->Rmask == 0x7C00 &&
vidformat->Gmask == 0x03E0 && vidformat->Bmask == 0x001F )) &&
!vidformat->Amask && (vidSurface->flags & SDL_RLEACCEL) == 0);
}
//
// I_FinishUpdate
//
void I_FinishUpdate(void)
{
if (!vidSurface)
return; //Alam: No software or OpenGl surface
if (I_SkipFrame())
return;
// draw captions if enabled
if (cv_closedcaptioning.value)
SCR_ClosedCaptions();
if (cv_ticrate.value)
SCR_DisplayTicRate();
if (render_soft == rendermode && screens[0])
{
SDL_Rect *dstrect = NULL;
SDL_Rect rect = {0, 0, 0, 0};
SDL_PixelFormat *vidformat = vidSurface->format;
int lockedsf = 0, blited = 0;
rect.w = (Sint16)vid.width;
rect.h = (Sint16)vid.height;
if (vidSurface->h > vid.height)
rect.y = (Sint16)((vidSurface->h-vid.height)/2);
dstrect = &rect;
if (!bufSurface && !vid.direct) //Double-Check
{
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) bufSurface = SDL_CreateRGBSurfaceFrom(screens[0],vid.width,vid.height,15,
(int)vid.rowbytes,0x00007C00,0x000003E0,0x0000001F,0x00000000); // 555 mode
if (bufSurface) SDL_SetColors(bufSurface, localPalette, 0, 256);
else I_OutputMsg("No system memory for SDL buffer surface\n");
}
#ifdef FILTERS
FilterBlit(bufSurface);
if (f2xSurface) //Alam: filter!
{
//I_OutputMsg("2x Filter Code\n");
blited = SDL_BlitSurface(f2xSurface,NULL,vidSurface,NULL);
}
else
#endif
#if 0
if (SDLmatchVideoformat() && !vid.direct)//Alam: DOS Way
{
if (SDL_MUSTLOCK(vidSurface)) lockedsf = SDL_LockSurface(vidSurface);
if (lockedsf == 0)
{
if (vidSurface->pixels > vid.height)
{
UINT8 *ptr = vidSurface->pixels;
size_t half_excess = vidSurface->pitch*(vidSurface->height-vid.height)/2;
memset(ptr, 0x1F, half_excess);
ptr += half_excess;
VID_BlitLinearScreen(screens[0], ptr, vid.width*vid.bpp, vid.height,
vid.rowbytes, vidSurface->pitch);
ptr += vid.height*vidSurface->pitch;
memset(ptr, 0x1F, half_excess);
}
else
VID_BlitLinearScreen(screens[0], vidSurface->pixels, vid.width*vid.bpp,
vid.height, vid.rowbytes, vidSurface->pitch );
if (SDL_MUSTLOCK(vidSurface)) SDL_UnlockSurface(vidSurface);
}
}
else
#endif
if (bufSurface) //Alam: New Way to send video data
{
blited = SDL_BlitSurface(bufSurface,NULL,vidSurface,dstrect);
}
else if (vid.bpp == 1 && !vid.direct)
{
Uint8 *bP,*vP; //Src, Dst
Uint16 bW, vW; // Pitch Remainder
Sint32 pH, pW; //Height, Width
bP = (Uint8 *)screens[0];
bW = (Uint16)(vid.rowbytes - vid.width);
//I_OutputMsg("Old Copy Code\n");
if (SDL_MUSTLOCK(vidSurface)) lockedsf = SDL_LockSurface(vidSurface);
vP = (Uint8 *)vidSurface->pixels;
vW = (Uint16)(vidSurface->pitch - vidSurface->w*vidformat->BytesPerPixel);
if (vidSurface->h > vid.height)
vP += vidSurface->pitch*(vidSurface->h-vid.height)/2;
if (lockedsf == 0 && vidSurface->pixels)
{
if (vidformat->BytesPerPixel == 2)
{
for (pH=0;pH < vidSurface->h;pH++)
{
for (pW=0;pW < vidSurface->w;pW++)
{
*((Uint16 *)(void *)vP) = (Uint16)SDL_MapRGB(vidformat,
localPalette[*bP].r,localPalette[*bP].g,localPalette[*bP].b);
bP++;
vP += 2;
}
bP += bW;
vP += vW;
}
}
else if (vidformat->BytesPerPixel == 3)
{
for (pH=0;pH < vidSurface->h;pH++)
{
for (pW=0;pW < vidSurface->w;pW++)
{
*((Uint32 *)(void *)vP) = SDL_MapRGB(vidformat,
localPalette[*bP].r,localPalette[*bP].g,localPalette[*bP].b);
bP++;
vP += 3;
}
bP += bW;
vP += vW;
}
}
else if (vidformat->BytesPerPixel == 4)
{
for (pH=0;pH < vidSurface->h;pH++)
{
for (pW=0;pW < vidSurface->w;pW++)
{
*((Uint32 *)(void *)vP) = SDL_MapRGB(vidformat,
localPalette[*bP].r,localPalette[*bP].g,localPalette[*bP].b);
bP++;
vP += 4;
}
bP += bW;
vP += vW;
}
}
else
{
;//NOP
}
}
if (SDL_MUSTLOCK(vidSurface)) SDL_UnlockSurface(vidSurface);
}
else /// \todo 15t15,15tN, others?
{
;//NOP
}
#ifdef HAVE_GP2XSDL
//if (blited == 0)
SDL_GP2X_WaitForBlitter();
#endif
if (lockedsf == 0 && blited == 0 && vidSurface->flags&SDL_DOUBLEBUF)
SDL_Flip(vidSurface);
else if (blited != -2 && lockedsf == 0) //Alam: -2 for Win32 Direct, yea, i know
SDL_UpdateRect(vidSurface, rect.x, rect.y, 0, 0); //Alam: almost always
else
I_OutputMsg("%s\n",SDL_GetError());
}
#ifdef HWRENDER
else
{
OglSdlFinishUpdate(cv_vidwait.value);
}
#endif
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;
}
if (vidSurface) SDL_SetColors(vidSurface, localPalette, 0, 256);
if (bufSurface) SDL_SetColors(bufSurface, localPalette, 0, 256);
}
// return number of fullscreen + X11 modes
INT32 VID_NumModes(void)
{
if (USE_FULLSCREEN && numVidModes != -1)
return numVidModes - firstEntry;
else
return MAXWINMODES;
}
const char *VID_GetModeName(INT32 modeNum)
{
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
{
if (modeNum > MAXWINMODES)
return NULL;
sprintf(&vidModeName[modeNum][0], "%dx%d",
windowedModes[modeNum][0],
windowedModes[modeNum][1]);
}
return &vidModeName[modeNum][0];
}
INT32 VID_GetModeForSize(INT32 w, INT32 h)
{
INT32 matchMode = -1, i;
VID_PrepareModeList();
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;
}
void VID_PrepareModeList(void)
{
INT32 i;
firstEntry = 0;
#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
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;
}
static inline void SDLESSet(void)
{
#ifdef HAVE_DCSDL
INT32 j;
SDL_DC_SetVideoDriver(SDL_DC_DIRECT_VIDEO); //SDL_DC_DMA_VIDEO
for (j=0;j<4;j++)
{
SDL_DC_MapKey(j,SDL_DC_START,SDLK_ESCAPE);
SDL_DC_MapKey(j,SDL_DC_A,SDLK_UNKNOWN);
SDL_DC_MapKey(j,SDL_DC_B,SDLK_UNKNOWN);
SDL_DC_MapKey(j,SDL_DC_X,SDLK_UNKNOWN);
SDL_DC_MapKey(j,SDL_DC_Y,SDLK_UNKNOWN);
SDL_DC_MapKey(j,SDL_DC_L,SDLK_UNKNOWN);
SDL_DC_MapKey(j,SDL_DC_R,SDLK_UNKNOWN);
//SDL_DC_MapKey(j,SDL_DC_LEFT,SDLK_UNKNOWN);
//SDL_DC_MapKey(j,SDL_DC_RIGHT,SDLK_UNKNOWN);
//SDL_DC_MapKey(j,SDL_DC_UP,SDLK_UNKNOWN);
//SDL_DC_MapKey(j,SDL_DC_DOWN,SDLK_UNKNOWN);
}
//SDL_DC_MapKey(0,SDL_DC_L,SDLK_LEFTBRACKET);
//SDL_DC_MapKey(0,SDL_DC_R,SDLK_RIGHTBRACKET);
//SDL_DC_MapKey(0,SDL_DC_START,SDLK_UNKNOWN);
//SDL_DC_MapKey(1,SDL_DC_L,SDLK_z);
//SDL_DC_MapKey(1,SDL_DC_R,SDLK_x);
#endif
#ifdef HAVE_GP2XSDL
SDL_GP2X_MiniDisplay(0,0);
//SDL_GP2X_DenyGfxMemory(NULL, 0);
SDL_GP2X_AllowGfxMemory(NULL, 0);
#endif
}
static void SDLWMSet(void)
{
#ifdef RPC_NO_WINDOWS_H
SDL_SysWMinfo SDLWM;
memset(&SDLWM,0,sizeof (SDL_SysWMinfo));
SDL_VERSION(&SDLWM.version)
if (SDL_GetWMInfo(&SDLWM))
vid.WndParent = SDLWM.window;
else
vid.WndParent = INVALID_HANDLE_VALUE;
if (vid.WndParent != INVALID_HANDLE_VALUE)
{
SetFocus(vid.WndParent);
ShowWindow(vid.WndParent, SW_SHOW);
}
#ifndef _WIN32_WCE
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
#endif
#endif
SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
}
static void* SDLGetDirect(void)
{
#if 0 //#ifndef __MACH__ // Do not directly access the MacOSX's OpenGL memory
if (!SDL_MUSTLOCK(vidSurface) && SDLmatchVideoformat())
{
vid.rowbytes = vidSurface->pitch;
return vidSurface->pixels;
}
#endif // you can not use the video memory in pixels member in fullscreen mode
return NULL;
}
INT32 VID_SetMode(INT32 modeNum)
{
#ifdef _WIN32_WCE
(void)modeNum;
#else
SDLdoUngrabMouse();
vid.recalc = true;
BitsPerPixel = (Uint8)cv_scr_depth.value;
//vid.bpp = BitsPerPixel==8?1:2;
// Window title
SDL_WM_SetCaption("SRB2 "VERSIONSTRING, "SRB2");
if (render_soft == rendermode)
{
//Alam: SDL_Video system free vidSurface for me
if (vid.buffer) free(vid.buffer);
vid.buffer = NULL;
if (bufSurface) SDL_FreeSurface(bufSurface);
bufSurface = NULL;
}
if (USE_FULLSCREEN)
{
if (numVidModes != -1)
{
modeNum += firstEntry;
vid.width = modeList[modeNum]->w;
vid.height = modeList[modeNum]->h;
}
else
{
vid.width = windowedModes[modeNum][0];
vid.height = windowedModes[modeNum][1];
}
if (render_soft == rendermode)
{
SDLSetMode(vid.width, vid.height, BitsPerPixel, surfaceFlagsF);
if (!vidSurface)
{
cv_fullscreen.value = 0;
modeNum = VID_GetModeForSize(vid.width,vid.height);
vid.width = windowedModes[modeNum][0];
vid.height = windowedModes[modeNum][1];
SDLSetMode(vid.width, vid.height, BitsPerPixel, surfaceFlagsW);
if (!vidSurface)
I_Error("Could not set vidmode: %s\n",SDL_GetError());
}
}
#ifdef HWRENDER
else // (render_soft != rendermode)
{
if (!OglSdlSurface(vid.width, vid.height, true))
{
cv_fullscreen.value = 0;
modeNum = VID_GetModeForSize(vid.width,vid.height);
vid.width = windowedModes[modeNum][0];
vid.height = windowedModes[modeNum][1];
if (!OglSdlSurface(vid.width, vid.height,false))
I_Error("Could not set vidmode: %s\n",SDL_GetError());
}
realwidth = (Uint16)vid.width;
realheight = (Uint16)vid.height;
}
#endif
}
else //(cv_fullscreen.value)
{
vid.width = windowedModes[modeNum][0];
vid.height = windowedModes[modeNum][1];
if (render_soft == rendermode)
{
SDLSetMode(vid.width, vid.height, BitsPerPixel, surfaceFlagsW);
if (!vidSurface)
I_Error("Could not set vidmode: %s\n",SDL_GetError());
}
#ifdef HWRENDER
else //(render_soft != rendermode)
{
if (!OglSdlSurface(vid.width, vid.height, false))
I_Error("Could not set vidmode: %s\n",SDL_GetError());
realwidth = (Uint16)vid.width;
realheight = (Uint16)vid.height;
}
#endif
}
vid.modenum = VID_GetModeForSize(vidSurface->w,vidSurface->h);
if (render_soft == rendermode)
{
vid.rowbytes = vid.width*vid.bpp;
vid.direct = SDLGetDirect();
vid.buffer = malloc(vid.rowbytes*vid.height*NUMSCREENS);
if (vid.buffer) memset(vid.buffer,0x00,vid.rowbytes*vid.height*NUMSCREENS);
else I_Error ("Not enough memory for video buffer\n");
}
#if 0 // broken
if (!cv_stretch.value && (float)vid.width/vid.height != ((float)BASEVIDWIDTH/BASEVIDHEIGHT))
vid.height = (INT32)(vid.width * ((float)BASEVIDHEIGHT/BASEVIDWIDTH));// Adjust the height to match
#endif
#endif
I_StartupMouse();
SDLWMSet();
return true;
}
void I_StartupGraphics(void)
{
static char SDLNOMOUSE[] = "SDL_NOMOUSE=1";
static char SDLVIDEOMID[] = "SDL_VIDEO_CENTERED=center";
if (dedicated)
{
rendermode = render_none;
return;
}
if (graphics_started)
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);
#ifdef FILTERS
CV_RegisterVar (&cv_filter);
#endif
#ifdef _PSP // pitch is 0, mod of 0 crash
disable_mouse = true;
#else
disable_mouse = M_CheckParm("-nomouse");
#endif
if (disable_mouse)
I_PutEnv(SDLNOMOUSE);
if (!I_GetEnv("SDL_VIDEO_CENTERED"))
I_PutEnv(SDLVIDEOMID);
disable_fullscreen = M_CheckParm("-win");
keyboard_started = true;
#ifdef _arch_dreamcast
conio_shutdown();
#endif
#if !defined(HAVE_TTF)
#ifdef _WIN32 // Initialize Audio as well, otherwise Win32's DirectX can not use audio
if (SDL_InitSubSystem(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0)
#else //SDL_OpenAudio will do SDL_InitSubSystem(SDL_INIT_AUDIO)
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0)
#endif
{
#ifdef _WIN32
if (SDL_WasInit(SDL_INIT_AUDIO)==0)
CONS_Printf(M_GetText("Couldn't initialize SDL's Audio System with Video System: %s\n"), SDL_GetError());
if (SDL_WasInit(SDL_INIT_VIDEO)==0)
#endif
{
CONS_Printf(M_GetText("Couldn't initialize SDL's Video System: %s\n"), SDL_GetError());
return;
}
}
#ifdef REMOTE_DEBUGGING
#ifdef _WII
_break(); // break for debugger
#endif
#endif
#endif
{
char vd[100]; //stack space for video name
CONS_Printf(M_GetText("Starting up with video driver : %s\n"), SDL_VideoDriverName(vd,100));
if (strncasecmp(vd, "gcvideo", 8) == 0 || strncasecmp(vd, "fbcon", 6) == 0 || strncasecmp(vd, "wii", 4) == 0 || strncasecmp(vd, "psl1ght", 8) == 0)
framebuffer = SDL_TRUE;
}
if (M_CheckParm("-software"))
rendermode = render_soft;
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2);
SDLESSet();
VID_Command_ModeList_f();
vid.buffer = NULL; // For software mode
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();
#endif
// Window title
#ifdef _WIN32_WCE
SDL_WM_SetCaption("SRB2 "VERSIONSTRING, "SRB2");
#else
SDL_WM_SetCaption("SRB2: Starting up", "SRB2");
#endif
// Window icon
#ifdef HAVE_IMAGE
icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm);
#endif
SDL_WM_SetIcon(icoSurface, NULL);
#ifdef _WIN32
//DisableAero(); //also disable Aero on Vista
#endif
#ifdef HWRENDER
if (M_CheckParm("-opengl") || rendermode == render_opengl)
{
rendermode = render_opengl;
HWD.pfnInit = hwSym("Init",NULL);
HWD.pfnFinishUpdate = NULL;
HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL);
HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL);
HWD.pfnSetBlend = hwSym("SetBlend",NULL);
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
HWD.pfnSetTexture = hwSym("SetTexture",NULL);
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);
HWD.pfnDrawMD2 = hwSym("DrawMD2",NULL);
HWD.pfnDrawMD2i = hwSym("DrawMD2i",NULL);
HWD.pfnSetTransform = hwSym("SetTransform",NULL);
HWD.pfnGetRenderVersion = hwSym("GetRenderVersion",NULL);
#ifdef SHUFFLE
HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL);
#endif
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);
// check gl renderer lib
if (HWD.pfnGetRenderVersion() != VERSION)
I_Error("%s", M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n"));
#if 1 //#ifdef _WIN32_WCE
vid.width = BASEVIDWIDTH;
vid.height = BASEVIDHEIGHT;
#else
vid.width = 640; // hack to make voodoo cards work in 640x480
vid.height = 480;
#endif
if (HWD.pfnInit(I_Error)) // let load the OpenGL library
{
/*
* We want at least 1 bit R, G, and B,
* and at least 16 bpp. Why 1 bit? May be more?
*/
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 1);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 1);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
if (!OglSdlSurface(vid.width, vid.height, (USE_FULLSCREEN)))
if (!OglSdlSurface(vid.width, vid.height, !(USE_FULLSCREEN)))
rendermode = render_soft;
}
else
rendermode = render_soft;
}
#else
rendermode = render_soft; //force software mode when there no HWRENDER code
#endif
if (render_soft == rendermode)
{
#if defined(_WII)
vid.width = 640;
vid.height = 480;
#elif defined(_PS3)
vid.width = 720;
vid.height = 480;
#else
vid.width = BASEVIDWIDTH;
vid.height = BASEVIDHEIGHT;
#endif
SDLSetMode(vid.width, vid.height, BitsPerPixel, surfaceFlagsW);
if (!vidSurface)
{
CONS_Printf(M_GetText("Could not set vidmode: %s\n") ,SDL_GetError());
vid.rowbytes = 0;
graphics_started = true;
return;
}
vid.rowbytes = vid.width * vid.bpp;
vid.direct = SDLGetDirect();
vid.buffer = malloc(vid.rowbytes*vid.height*NUMSCREENS);
if (vid.buffer) memset(vid.buffer,0x00,vid.rowbytes*vid.height*NUMSCREENS);
else CONS_Printf("%s", M_GetText("Not enough memory for video buffer\n"));
}
if (M_CheckParm("-nomousegrab"))
mousegrabok = SDL_FALSE;
#ifdef _DEBUG
else
{
char videodriver[4] = {'S','D','L',0};
if (!M_CheckParm("-mousegrab") &&
SDL_VideoDriverName(videodriver,4) &&
strncasecmp("X11",videodriver,4) == 0)
mousegrabok = SDL_FALSE; //X11's XGrabPointer not good
}
#endif
realwidth = (Uint16)vid.width;
realheight = (Uint16)vid.height;
VID_Command_Info_f();
if (!disable_mouse) SDL_ShowCursor(SDL_DISABLE);
SDLdoUngrabMouse();
SDLWMSet();
graphics_started = true;
}
void I_ShutdownGraphics(void)
{
const rendermode_t oldrendermode = rendermode;
rendermode = render_none;
if (icoSurface) SDL_FreeSurface(icoSurface);
icoSurface = NULL;
if (render_soft == oldrendermode)
{
vidSurface = NULL; //Alam: SDL_Video system free vidSurface for me
if (vid.buffer) free(vid.buffer);
vid.buffer = NULL;
if (bufSurface) SDL_FreeSurface(bufSurface);
bufSurface = NULL;
#ifdef FILTERS
if (preSurface) SDL_FreeSurface(preSurface);
preSurface = NULL;
if (f2xSurface) SDL_FreeSurface(f2xSurface);
f2xSurface = NULL;
#endif
}
// was graphics initialized anyway?
if (!graphics_started)
return;
CONS_Printf("I_ShutdownGraphics: ");
#ifdef _WIN32
//ResetAero();
#endif
graphics_started = false;
CONS_Printf("%s", M_GetText("shut down\n"));
#ifdef HWRENDER
if (GLUhandle)
hwClose(GLUhandle);
#endif
#ifndef _arch_dreamcast
SDL_QuitSubSystem(SDL_INIT_VIDEO);
#endif
framebuffer = SDL_FALSE;
}
#endif