2009-05-02 23:03:37 +02:00
/*
2009-05-03 00:28:34 +02:00
* Copyright ( C ) 2002 - 2007 The DOSBox Team
2009-05-02 23:03:37 +02: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
2009-05-03 00:02:15 +02:00
* GNU General Public License for more details .
2009-05-02 23:03:37 +02:00
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
2009-05-02 23:43:00 +02:00
2009-05-03 00:44:30 +02:00
/* $Id: sdlmain.cpp,v 1.134 2007/08/26 18:03:25 qbix79 Exp $ */
2009-05-02 23:43:00 +02:00
2009-05-02 23:35:44 +02:00
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
2009-05-02 23:03:37 +02:00
2009-05-02 23:43:00 +02:00
# include <stdlib.h>
2009-05-02 23:03:37 +02:00
# include <string.h>
# include <stdio.h>
2009-05-02 23:35:44 +02:00
# include <unistd.h>
2009-05-02 23:43:00 +02:00
# include <stdarg.h>
2009-05-03 00:08:43 +02:00
# include <sys/types.h>
2009-05-03 00:37:32 +02:00
# ifdef WIN32
# include <signal.h>
# endif
2009-05-02 23:35:44 +02:00
# include "SDL.h"
2009-05-02 23:20:05 +02:00
2009-05-02 23:03:37 +02:00
# include "dosbox.h"
# include "video.h"
# include "mouse.h"
# include "pic.h"
# include "timer.h"
2009-05-02 23:20:05 +02:00
# include "setup.h"
2009-05-02 23:53:27 +02:00
# include "support.h"
2009-05-02 23:20:05 +02:00
# include "debug.h"
2009-05-03 00:02:15 +02:00
# include "mapper.h"
2009-05-03 00:18:08 +02:00
# include "vga.h"
# include "keyboard.h"
2009-05-03 00:02:15 +02:00
//#define DISABLE_JOYSTICK
2009-05-02 23:03:37 +02:00
2009-05-02 23:53:27 +02:00
# if C_OPENGL
# include "SDL_opengl.h"
# ifndef APIENTRY
# define APIENTRY
# endif
# ifndef APIENTRYP
# define APIENTRYP APIENTRY *
# endif
# ifdef __WIN32__
# define NVIDIA_PixelDataRange 1
2009-05-03 00:02:15 +02:00
2009-05-02 23:53:27 +02:00
# ifndef WGL_NV_allocate_memory
# define WGL_NV_allocate_memory 1
typedef void * ( APIENTRY * PFNWGLALLOCATEMEMORYNVPROC ) ( int size , float readfreq , float writefreq , float priority ) ;
typedef void ( APIENTRY * PFNWGLFREEMEMORYNVPROC ) ( void * pointer ) ;
2009-05-03 00:02:15 +02:00
# endif
2009-05-02 23:53:27 +02:00
PFNWGLALLOCATEMEMORYNVPROC db_glAllocateMemoryNV = NULL ;
PFNWGLFREEMEMORYNVPROC db_glFreeMemoryNV = NULL ;
2009-05-03 00:02:15 +02:00
2009-05-02 23:53:27 +02:00
# else
# endif
# if defined(NVIDIA_PixelDataRange)
2009-05-03 00:02:15 +02:00
2009-05-02 23:53:27 +02:00
# ifndef GL_NV_pixel_data_range
# define GL_NV_pixel_data_range 1
# define GL_WRITE_PIXEL_DATA_RANGE_NV 0x8878
typedef void ( APIENTRYP PFNGLPIXELDATARANGENVPROC ) ( GLenum target , GLsizei length , GLvoid * pointer ) ;
typedef void ( APIENTRYP PFNGLFLUSHPIXELDATARANGENVPROC ) ( GLenum target ) ;
# endif
2009-05-03 00:02:15 +02:00
PFNGLPIXELDATARANGENVPROC glPixelDataRangeNV = NULL ;
2009-05-02 23:53:27 +02:00
# endif
# endif //C_OPENGL
2009-05-02 23:43:00 +02:00
# if !(ENVIRON_INCLUDED)
2009-05-02 23:35:44 +02:00
extern char * * environ ;
# endif
2009-05-02 23:03:37 +02:00
2009-05-02 23:43:00 +02:00
# ifdef WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
2009-05-03 00:18:08 +02:00
# if (HAVE_DDRAW_H)
2009-05-03 00:02:15 +02:00
# include <ddraw.h>
struct private_hwdata {
LPDIRECTDRAWSURFACE3 dd_surface ;
LPDIRECTDRAWSURFACE3 dd_writebuf ;
} ;
# endif
2009-05-02 23:43:00 +02:00
# define STDOUT_FILE TEXT("stdout.txt")
# define STDERR_FILE TEXT("stderr.txt")
2009-05-02 23:53:27 +02:00
# define DEFAULT_CONFIG_FILE " / dosbox.conf"
# elif defined(MACOSX)
# define DEFAULT_CONFIG_FILE " / Library / Preferences / DOSBox Preferences"
# else /*linux freebsd*/
# define DEFAULT_CONFIG_FILE " / .dosboxrc"
2009-05-02 23:43:00 +02:00
# endif
2009-05-03 00:02:15 +02:00
# if C_SET_PRIORITY
# include <sys/resource.h>
# define PRIO_TOTAL (PRIO_MAX-PRIO_MIN)
# endif
2009-05-03 00:18:08 +02:00
# ifdef OS2
# define INCL_DOS
# define INCL_WIN
# include <os2.h>
# endif
2009-05-02 23:53:27 +02:00
enum SCREEN_TYPES {
SCREEN_SURFACE ,
2009-05-03 00:02:15 +02:00
SCREEN_SURFACE_DDRAW ,
2009-05-02 23:53:27 +02:00
SCREEN_OVERLAY ,
SCREEN_OPENGL
} ;
2009-05-03 00:02:15 +02:00
enum PRIORITY_LEVELS {
2009-05-03 00:28:34 +02:00
PRIORITY_LEVEL_PAUSE ,
2009-05-03 00:18:08 +02:00
PRIORITY_LEVEL_LOWEST ,
2009-05-03 00:02:15 +02:00
PRIORITY_LEVEL_LOWER ,
PRIORITY_LEVEL_NORMAL ,
PRIORITY_LEVEL_HIGHER ,
PRIORITY_LEVEL_HIGHEST
} ;
2009-05-02 23:53:27 +02:00
2009-05-02 23:03:37 +02:00
struct SDL_Block {
2009-05-02 23:53:27 +02:00
bool active ; //If this isn't set don't draw
bool updating ;
struct {
Bit32u width ;
Bit32u height ;
2009-05-03 00:18:08 +02:00
Bit32u bpp ;
2009-05-03 00:02:15 +02:00
Bitu flags ;
2009-05-02 23:53:27 +02:00
double scalex , scaley ;
2009-05-03 00:18:08 +02:00
GFX_CallBack_t callback ;
2009-05-02 23:53:27 +02:00
} draw ;
2009-05-02 23:43:00 +02:00
bool wait_on_error ;
2009-05-02 23:53:27 +02:00
struct {
2009-05-03 00:18:08 +02:00
struct {
Bit16u width , height ;
bool fixed ;
} full ;
struct {
Bit16u width , height ;
} window ;
Bit8u bpp ;
2009-05-02 23:53:27 +02:00
bool fullscreen ;
bool doublebuf ;
SCREEN_TYPES type ;
SCREEN_TYPES want_type ;
} desktop ;
# if C_OPENGL
struct {
Bitu pitch ;
void * framebuf ;
GLuint texture ;
GLuint displaylist ;
GLint max_texsize ;
bool bilinear ;
bool packed_pixel ;
bool paletted_texture ;
# if defined(NVIDIA_PixelDataRange)
bool pixel_data_range ;
# endif
} opengl ;
# endif
2009-05-03 00:02:15 +02:00
struct {
SDL_Surface * surface ;
2009-05-03 00:18:08 +02:00
# if (HAVE_DDRAW_H) && defined(WIN32)
2009-05-03 00:02:15 +02:00
RECT rect ;
# endif
2009-05-03 00:18:08 +02:00
} blit ;
2009-05-03 00:02:15 +02:00
struct {
PRIORITY_LEVELS focus ;
PRIORITY_LEVELS nofocus ;
} priority ;
2009-05-02 23:53:27 +02:00
SDL_Rect clip ;
2009-05-02 23:03:37 +02:00
SDL_Surface * surface ;
2009-05-02 23:53:27 +02:00
SDL_Overlay * overlay ;
2009-05-02 23:35:44 +02:00
SDL_cond * cond ;
2009-05-02 23:20:05 +02:00
struct {
bool autolock ;
bool autoenable ;
bool requestlock ;
bool locked ;
Bitu sensitivity ;
} mouse ;
2009-05-03 00:18:08 +02:00
SDL_Rect updateRects [ 1024 ] ;
2009-05-03 00:28:34 +02:00
Bitu num_joysticks ;
# if defined (WIN32)
bool using_windib ;
# endif
2009-05-02 23:03:37 +02:00
} ;
static SDL_Block sdl ;
2009-05-03 00:28:34 +02:00
extern const char * RunningProgram ;
extern bool CPU_CycleAutoAdjust ;
2009-05-03 00:08:43 +02:00
//Globals for keyboard initialisation
bool startup_state_numlock = false ;
bool startup_state_capslock = false ;
2009-05-03 00:28:34 +02:00
void GFX_SetTitle ( Bit32s cycles , Bits frameskip , bool paused ) {
2009-05-02 23:43:00 +02:00
char title [ 200 ] = { 0 } ;
2009-05-03 00:28:34 +02:00
static Bit32s internal_cycles = 0 ;
2009-05-02 23:43:00 +02:00
static Bits internal_frameskip = 0 ;
if ( cycles ! = - 1 ) internal_cycles = cycles ;
if ( frameskip ! = - 1 ) internal_frameskip = frameskip ;
2009-05-03 00:28:34 +02:00
if ( CPU_CycleAutoAdjust ) {
if ( internal_cycles > = 100 )
sprintf ( title , " DOSBox %s, Cpu Cycles: max, Frameskip %2d, Program: %8s " , VERSION , internal_frameskip , RunningProgram ) ;
else
sprintf ( title , " DOSBox %s, Cpu Cycles: [%3d%%], Frameskip %2d, Program: %8s " , VERSION , internal_cycles , internal_frameskip , RunningProgram ) ;
} else {
2009-05-03 00:18:08 +02:00
sprintf ( title , " DOSBox %s, Cpu Cycles: %8d, Frameskip %2d, Program: %8s " , VERSION , internal_cycles , internal_frameskip , RunningProgram ) ;
2009-05-03 00:28:34 +02:00
}
2009-05-03 00:18:08 +02:00
if ( paused ) strcat ( title , " PAUSED " ) ;
2009-05-02 23:43:00 +02:00
SDL_WM_SetCaption ( title , VERSION ) ;
}
2009-05-03 00:18:08 +02:00
static void PauseDOSBox ( bool pressed ) {
if ( ! pressed )
return ;
2009-05-03 00:02:15 +02:00
GFX_SetTitle ( - 1 , - 1 , true ) ;
bool paused = true ;
2009-05-03 00:18:08 +02:00
KEYBOARD_ClrBuffer ( ) ;
2009-05-03 00:02:15 +02:00
SDL_Delay ( 500 ) ;
SDL_Event event ;
while ( SDL_PollEvent ( & event ) ) {
// flush event queue.
}
while ( paused ) {
SDL_WaitEvent ( & event ) ; // since we're not polling, cpu usage drops to 0.
switch ( event . type ) {
2009-05-03 00:28:34 +02:00
case SDL_QUIT : throw ( 0 ) ; break ;
2009-05-03 00:02:15 +02:00
case SDL_KEYDOWN : // Must use Pause/Break Key to resume.
case SDL_KEYUP :
if ( event . key . keysym . sym = = SDLK_PAUSE ) {
paused = false ;
GFX_SetTitle ( - 1 , - 1 , false ) ;
break ;
}
}
}
}
2009-05-03 00:28:34 +02:00
# if defined (WIN32)
bool GFX_SDLUsingWinDIB ( void ) {
return sdl . using_windib ;
}
# endif
2009-05-03 00:02:15 +02:00
2009-05-02 23:03:37 +02:00
/* Reset the screen with current values in the sdl structure */
2009-05-03 00:02:15 +02:00
Bitu GFX_GetBestMode ( Bitu flags ) {
Bitu testbpp , gotbpp ;
2009-05-02 23:53:27 +02:00
switch ( sdl . desktop . want_type ) {
case SCREEN_SURFACE :
2009-05-03 00:02:15 +02:00
check_surface :
/* Check if we can satisfy the depth it loves */
2009-05-03 00:18:08 +02:00
if ( flags & GFX_LOVE_8 ) testbpp = 8 ;
else if ( flags & GFX_LOVE_15 ) testbpp = 15 ;
else if ( flags & GFX_LOVE_16 ) testbpp = 16 ;
else if ( flags & GFX_LOVE_32 ) testbpp = 32 ;
2009-05-03 00:37:32 +02:00
else testbpp = 0 ;
2009-05-03 00:02:15 +02:00
check_gotbpp :
if ( sdl . desktop . fullscreen ) gotbpp = SDL_VideoModeOK ( 640 , 480 , testbpp , SDL_FULLSCREEN | SDL_HWSURFACE | SDL_HWPALETTE ) ;
else gotbpp = sdl . desktop . bpp ;
/* If we can't get our favorite mode check for another working one */
switch ( gotbpp ) {
case 8 :
2009-05-03 00:18:08 +02:00
if ( flags & GFX_CAN_8 ) flags & = ~ ( GFX_CAN_15 | GFX_CAN_16 | GFX_CAN_32 ) ;
2009-05-03 00:02:15 +02:00
break ;
case 15 :
2009-05-03 00:18:08 +02:00
if ( flags & GFX_CAN_15 ) flags & = ~ ( GFX_CAN_8 | GFX_CAN_16 | GFX_CAN_32 ) ;
break ;
2009-05-03 00:02:15 +02:00
case 16 :
2009-05-03 00:18:08 +02:00
if ( flags & GFX_CAN_16 ) flags & = ~ ( GFX_CAN_8 | GFX_CAN_15 | GFX_CAN_32 ) ;
2009-05-03 00:02:15 +02:00
break ;
case 24 :
case 32 :
2009-05-03 00:18:08 +02:00
if ( flags & GFX_CAN_32 ) flags & = ~ ( GFX_CAN_8 | GFX_CAN_15 | GFX_CAN_16 ) ;
2009-05-03 00:02:15 +02:00
break ;
2009-05-02 23:35:44 +02:00
}
2009-05-03 00:18:08 +02:00
flags | = GFX_CAN_RANDOM ;
2009-05-02 23:53:27 +02:00
break ;
2009-05-03 00:18:08 +02:00
# if (HAVE_DDRAW_H) && defined(WIN32)
2009-05-03 00:02:15 +02:00
case SCREEN_SURFACE_DDRAW :
2009-05-03 00:18:08 +02:00
if ( ! ( flags & ( GFX_CAN_15 | GFX_CAN_16 | GFX_CAN_32 ) ) ) goto check_surface ;
if ( flags & GFX_LOVE_15 ) testbpp = 15 ;
else if ( flags & GFX_LOVE_16 ) testbpp = 16 ;
else if ( flags & GFX_LOVE_32 ) testbpp = 32 ;
2009-05-03 00:02:15 +02:00
else testbpp = 0 ;
2009-05-03 00:18:08 +02:00
flags | = GFX_SCALING ;
2009-05-03 00:02:15 +02:00
goto check_gotbpp ;
# endif
2009-05-02 23:53:27 +02:00
case SCREEN_OVERLAY :
2009-05-03 00:18:08 +02:00
if ( flags & GFX_RGBONLY | | ! ( flags & GFX_CAN_32 ) ) goto check_surface ;
flags | = GFX_SCALING ;
flags & = ~ ( GFX_CAN_8 | GFX_CAN_15 | GFX_CAN_16 ) ;
2009-05-02 23:53:27 +02:00
break ;
# if C_OPENGL
case SCREEN_OPENGL :
2009-05-03 00:18:08 +02:00
if ( flags & GFX_RGBONLY | | ! ( flags & GFX_CAN_32 ) ) goto check_surface ;
flags | = GFX_SCALING ;
flags & = ~ ( GFX_CAN_8 | GFX_CAN_15 | GFX_CAN_16 ) ;
2009-05-02 23:53:27 +02:00
break ;
# endif
2009-05-02 23:03:37 +02:00
}
2009-05-03 00:02:15 +02:00
return flags ;
2009-05-02 23:53:27 +02:00
}
2009-05-02 23:35:44 +02:00
2009-05-03 00:02:15 +02:00
void GFX_ResetScreen ( void ) {
2009-05-02 23:53:27 +02:00
GFX_Stop ( ) ;
2009-05-03 00:28:34 +02:00
if ( sdl . draw . callback )
( sdl . draw . callback ) ( GFX_CallBackReset ) ;
2009-05-02 23:27:47 +02:00
GFX_Start ( ) ;
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:53:27 +02:00
static int int_log2 ( int val ) {
int log = 0 ;
while ( ( val > > = 1 ) ! = 0 )
log + + ;
return log ;
}
2009-05-02 23:03:37 +02:00
2009-05-03 00:02:15 +02:00
2009-05-03 00:18:08 +02:00
static SDL_Surface * GFX_SetupSurfaceScaled ( Bit32u sdl_flags , Bit32u bpp ) {
Bit16u fixedWidth ;
Bit16u fixedHeight ;
2009-05-03 00:02:15 +02:00
if ( sdl . desktop . fullscreen ) {
2009-05-03 00:18:08 +02:00
fixedWidth = sdl . desktop . full . fixed ? sdl . desktop . full . width : 0 ;
fixedHeight = sdl . desktop . full . fixed ? sdl . desktop . full . height : 0 ;
sdl_flags | = SDL_FULLSCREEN | SDL_HWSURFACE ;
} else {
fixedWidth = sdl . desktop . window . width ;
fixedHeight = sdl . desktop . window . height ;
sdl_flags | = SDL_HWSURFACE ;
}
if ( fixedWidth & & fixedHeight ) {
double ratio_w = ( double ) fixedWidth / ( sdl . draw . width * sdl . draw . scalex ) ;
double ratio_h = ( double ) fixedHeight / ( sdl . draw . height * sdl . draw . scaley ) ;
if ( ratio_w < ratio_h ) {
sdl . clip . w = fixedWidth ;
sdl . clip . h = ( Bit16u ) ( sdl . draw . height * sdl . draw . scaley * ratio_w ) ;
2009-05-03 00:02:15 +02:00
} else {
2009-05-03 00:18:08 +02:00
sdl . clip . w = ( Bit16u ) ( sdl . draw . width * sdl . draw . scalex * ratio_h ) ;
sdl . clip . h = ( Bit16u ) fixedHeight ;
2009-05-03 00:02:15 +02:00
}
2009-05-03 00:18:08 +02:00
if ( sdl . desktop . fullscreen )
sdl . surface = SDL_SetVideoMode ( fixedWidth , fixedHeight , bpp , sdl_flags ) ;
else
sdl . surface = SDL_SetVideoMode ( sdl . clip . w , sdl . clip . h , bpp , sdl_flags ) ;
if ( sdl . surface & & sdl . surface - > flags & SDL_FULLSCREEN ) {
sdl . clip . x = ( Sint16 ) ( ( sdl . surface - > w - sdl . clip . w ) / 2 ) ;
sdl . clip . y = ( Sint16 ) ( ( sdl . surface - > h - sdl . clip . h ) / 2 ) ;
} else {
sdl . clip . x = 0 ;
sdl . clip . y = 0 ;
}
return sdl . surface ;
2009-05-03 00:02:15 +02:00
} else {
sdl . clip . x = 0 ; sdl . clip . y = 0 ;
2009-05-03 00:18:08 +02:00
sdl . clip . w = ( Bit16u ) ( sdl . draw . width * sdl . draw . scalex ) ;
sdl . clip . h = ( Bit16u ) ( sdl . draw . height * sdl . draw . scaley ) ;
sdl . surface = SDL_SetVideoMode ( sdl . clip . w , sdl . clip . h , bpp , sdl_flags ) ;
return sdl . surface ;
2009-05-03 00:02:15 +02:00
}
}
2009-05-03 00:18:08 +02:00
Bitu GFX_SetSize ( Bitu width , Bitu height , Bitu flags , double scalex , double scaley , GFX_CallBack_t callback ) {
if ( sdl . updating )
GFX_EndUpdate ( 0 ) ;
2009-05-02 23:53:27 +02:00
sdl . draw . width = width ;
sdl . draw . height = height ;
2009-05-03 00:18:08 +02:00
sdl . draw . callback = callback ;
2009-05-02 23:53:27 +02:00
sdl . draw . scalex = scalex ;
sdl . draw . scaley = scaley ;
2009-05-03 00:37:32 +02:00
Bitu bpp = 0 ;
2009-05-03 00:28:34 +02:00
Bitu retFlags = 0 ;
2009-05-03 00:18:08 +02:00
if ( sdl . blit . surface ) {
SDL_FreeSurface ( sdl . blit . surface ) ;
sdl . blit . surface = 0 ;
}
2009-05-02 23:53:27 +02:00
switch ( sdl . desktop . want_type ) {
case SCREEN_SURFACE :
dosurface :
2009-05-03 00:18:08 +02:00
if ( flags & GFX_CAN_8 ) bpp = 8 ;
if ( flags & GFX_CAN_15 ) bpp = 15 ;
if ( flags & GFX_CAN_16 ) bpp = 16 ;
if ( flags & GFX_CAN_32 ) bpp = 32 ;
2009-05-02 23:53:27 +02:00
sdl . desktop . type = SCREEN_SURFACE ;
sdl . clip . w = width ;
sdl . clip . h = height ;
if ( sdl . desktop . fullscreen ) {
2009-05-03 00:18:08 +02:00
if ( sdl . desktop . full . fixed ) {
sdl . clip . x = ( Sint16 ) ( ( sdl . desktop . full . width - width ) / 2 ) ;
sdl . clip . y = ( Sint16 ) ( ( sdl . desktop . full . height - height ) / 2 ) ;
sdl . surface = SDL_SetVideoMode ( sdl . desktop . full . width , sdl . desktop . full . height , bpp ,
SDL_FULLSCREEN | ( ( flags & GFX_CAN_RANDOM ) ? SDL_SWSURFACE : SDL_HWSURFACE ) |
( sdl . desktop . doublebuf ? SDL_DOUBLEBUF | SDL_ASYNCBLIT : 0 ) | SDL_HWPALETTE ) ;
if ( sdl . surface = = NULL ) E_Exit ( " Could not set fullscreen video mode %ix%i-%i: %s " , sdl . desktop . full . width , sdl . desktop . full . height , bpp , SDL_GetError ( ) ) ;
2009-05-02 23:53:27 +02:00
} else {
sdl . clip . x = 0 ; sdl . clip . y = 0 ;
sdl . surface = SDL_SetVideoMode ( width , height , bpp ,
2009-05-03 00:18:08 +02:00
SDL_FULLSCREEN | ( ( flags & GFX_CAN_RANDOM ) ? SDL_SWSURFACE : SDL_HWSURFACE ) |
( sdl . desktop . doublebuf ? SDL_DOUBLEBUF | SDL_ASYNCBLIT : 0 ) | SDL_HWPALETTE ) ;
if ( sdl . surface = = NULL )
E_Exit ( " Could not set fullscreen video mode %ix%i-%i: %s " , width , height , bpp , SDL_GetError ( ) ) ;
2009-05-02 23:53:27 +02:00
}
} else {
sdl . clip . x = 0 ; sdl . clip . y = 0 ;
2009-05-03 00:18:08 +02:00
sdl . surface = SDL_SetVideoMode ( width , height , bpp , ( flags & GFX_CAN_RANDOM ) ? SDL_SWSURFACE : SDL_HWSURFACE ) ;
# ifdef WIN32
if ( sdl . surface = = NULL ) {
SDL_QuitSubSystem ( SDL_INIT_VIDEO ) ;
2009-05-03 00:37:32 +02:00
if ( ! sdl . using_windib ) {
LOG_MSG ( " Failed to create hardware surface. \n Restarting video subsystem with windib enabled. " ) ;
putenv ( " SDL_VIDEODRIVER=windib " ) ;
sdl . using_windib = true ;
} else {
LOG_MSG ( " Failed to create hardware surface. \n Restarting video subsystem with directx enabled. " ) ;
putenv ( " SDL_VIDEODRIVER=directx " ) ;
sdl . using_windib = false ;
}
2009-05-03 00:18:08 +02:00
SDL_InitSubSystem ( SDL_INIT_VIDEO ) ;
sdl . surface = SDL_SetVideoMode ( width , height , bpp , SDL_HWSURFACE ) ;
}
# endif
if ( sdl . surface = = NULL )
E_Exit ( " Could not set windowed video mode %ix%i-%i: %s " , width , height , bpp , SDL_GetError ( ) ) ;
2009-05-02 23:53:27 +02:00
}
2009-05-03 00:18:08 +02:00
if ( sdl . surface ) {
switch ( sdl . surface - > format - > BitsPerPixel ) {
case 8 :
retFlags = GFX_CAN_8 ;
break ;
case 15 :
retFlags = GFX_CAN_15 ;
2009-05-03 00:02:15 +02:00
break ;
2009-05-03 00:18:08 +02:00
case 16 :
retFlags = GFX_CAN_16 ;
break ;
case 32 :
retFlags = GFX_CAN_32 ;
break ;
}
if ( retFlags & & ( sdl . surface - > flags & SDL_HWSURFACE ) )
retFlags | = GFX_HARDWARE ;
if ( retFlags & & ( sdl . surface - > flags & SDL_DOUBLEBUF ) ) {
sdl . blit . surface = SDL_CreateRGBSurface ( SDL_HWSURFACE ,
sdl . draw . width , sdl . draw . height ,
sdl . surface - > format - > BitsPerPixel ,
sdl . surface - > format - > Rmask ,
sdl . surface - > format - > Gmask ,
sdl . surface - > format - > Bmask ,
0 ) ;
/* If this one fails be ready for some flickering... */
}
2009-05-03 00:02:15 +02:00
}
2009-05-02 23:53:27 +02:00
break ;
2009-05-03 00:18:08 +02:00
# if (HAVE_DDRAW_H) && defined(WIN32)
2009-05-03 00:02:15 +02:00
case SCREEN_SURFACE_DDRAW :
2009-05-03 00:18:08 +02:00
if ( flags & GFX_CAN_15 ) bpp = 15 ;
if ( flags & GFX_CAN_16 ) bpp = 16 ;
if ( flags & GFX_CAN_32 ) bpp = 32 ;
2009-05-03 00:02:15 +02:00
if ( ! GFX_SetupSurfaceScaled ( ( sdl . desktop . doublebuf & & sdl . desktop . fullscreen ) ? SDL_DOUBLEBUF : 0 , bpp ) ) goto dosurface ;
sdl . blit . rect . top = sdl . clip . y ;
sdl . blit . rect . left = sdl . clip . x ;
sdl . blit . rect . right = sdl . clip . x + sdl . clip . w ;
sdl . blit . rect . bottom = sdl . clip . y + sdl . clip . h ;
sdl . blit . surface = SDL_CreateRGBSurface ( SDL_HWSURFACE , sdl . draw . width , sdl . draw . height ,
sdl . surface - > format - > BitsPerPixel ,
sdl . surface - > format - > Rmask ,
sdl . surface - > format - > Gmask ,
sdl . surface - > format - > Bmask ,
0 ) ;
if ( ! sdl . blit . surface | | ( ! sdl . blit . surface - > flags & SDL_HWSURFACE ) ) {
2009-05-03 00:37:32 +02:00
if ( sdl . blit . surface ) {
SDL_FreeSurface ( sdl . blit . surface ) ;
sdl . blit . surface = 0 ;
}
2009-05-03 00:02:15 +02:00
LOG_MSG ( " Failed to create ddraw surface, back to normal surface. " ) ;
goto dosurface ;
}
switch ( sdl . surface - > format - > BitsPerPixel ) {
2009-05-03 00:18:08 +02:00
case 15 :
retFlags = GFX_CAN_15 | GFX_SCALING | GFX_HARDWARE ;
break ;
case 16 :
retFlags = GFX_CAN_16 | GFX_SCALING | GFX_HARDWARE ;
break ;
case 32 :
retFlags = GFX_CAN_32 | GFX_SCALING | GFX_HARDWARE ;
break ;
2009-05-03 00:02:15 +02:00
}
sdl . desktop . type = SCREEN_SURFACE_DDRAW ;
break ;
# endif
2009-05-02 23:53:27 +02:00
case SCREEN_OVERLAY :
2009-05-03 00:02:15 +02:00
if ( sdl . overlay ) {
SDL_FreeYUVOverlay ( sdl . overlay ) ;
sdl . overlay = 0 ;
2009-05-02 23:53:27 +02:00
}
2009-05-03 00:18:08 +02:00
if ( ! ( flags & GFX_CAN_32 ) | | ( flags & GFX_RGBONLY ) ) goto dosurface ;
2009-05-03 00:02:15 +02:00
if ( ! GFX_SetupSurfaceScaled ( 0 , 0 ) ) goto dosurface ;
2009-05-02 23:53:27 +02:00
sdl . overlay = SDL_CreateYUVOverlay ( width * 2 , height , SDL_UYVY_OVERLAY , sdl . surface ) ;
if ( ! sdl . overlay ) {
LOG_MSG ( " SDL:Failed to create overlay, switching back to surface " ) ;
goto dosurface ;
}
sdl . desktop . type = SCREEN_OVERLAY ;
2009-05-03 00:18:08 +02:00
retFlags = GFX_CAN_32 | GFX_SCALING | GFX_HARDWARE ;
2009-05-02 23:53:27 +02:00
break ;
# if C_OPENGL
case SCREEN_OPENGL :
{
if ( sdl . opengl . framebuf ) {
# if defined(NVIDIA_PixelDataRange)
if ( sdl . opengl . pixel_data_range ) db_glFreeMemoryNV ( sdl . opengl . framebuf ) ;
else
# endif
free ( sdl . opengl . framebuf ) ;
}
sdl . opengl . framebuf = 0 ;
2009-05-03 00:18:08 +02:00
if ( ! ( flags & GFX_CAN_32 ) | | ( flags & GFX_RGBONLY ) ) goto dosurface ;
2009-05-02 23:53:27 +02:00
int texsize = 2 < < int_log2 ( width > height ? width : height ) ;
if ( texsize > sdl . opengl . max_texsize ) {
LOG_MSG ( " SDL:OPENGL:No support for texturesize of %d, falling back to surface " , texsize ) ;
goto dosurface ;
}
SDL_GL_SetAttribute ( SDL_GL_DOUBLEBUFFER , 1 ) ;
2009-05-03 00:28:34 +02:00
# if defined (WIN32) && SDL_VERSION_ATLEAST(1, 2, 11)
SDL_GL_SetAttribute ( SDL_GL_SWAP_CONTROL , 0 ) ;
# endif
2009-05-03 00:02:15 +02:00
GFX_SetupSurfaceScaled ( SDL_OPENGL , 0 ) ;
2009-05-02 23:53:27 +02:00
if ( ! sdl . surface | | sdl . surface - > format - > BitsPerPixel < 15 ) {
LOG_MSG ( " SDL:OPENGL:Can't open drawing surface, are you running in 16bpp(or higher) mode? " ) ;
goto dosurface ;
}
/* Create the texture and display list */
# if defined(NVIDIA_PixelDataRange)
if ( sdl . opengl . pixel_data_range ) {
sdl . opengl . framebuf = db_glAllocateMemoryNV ( width * height * 4 , 0.0 , 1.0 , 1.0 ) ;
glPixelDataRangeNV ( GL_WRITE_PIXEL_DATA_RANGE_NV , width * height * 4 , sdl . opengl . framebuf ) ;
glEnableClientState ( GL_WRITE_PIXEL_DATA_RANGE_NV ) ;
} else {
# else
{
# endif
sdl . opengl . framebuf = malloc ( width * height * 4 ) ; //32 bit color
}
sdl . opengl . pitch = width * 4 ;
glViewport ( sdl . clip . x , sdl . clip . y , sdl . clip . w , sdl . clip . h ) ;
glMatrixMode ( GL_PROJECTION ) ;
glDeleteTextures ( 1 , & sdl . opengl . texture ) ;
glGenTextures ( 1 , & sdl . opengl . texture ) ;
glBindTexture ( GL_TEXTURE_2D , sdl . opengl . texture ) ;
// No borders
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP ) ;
if ( sdl . opengl . bilinear ) {
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
} else {
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
}
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA8 , texsize , texsize , 0 , GL_BGRA_EXT , GL_UNSIGNED_BYTE , 0 ) ;
glClearColor ( 0.0 , 0.0 , 0.0 , 1.0 ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
2009-05-03 00:02:15 +02:00
SDL_GL_SwapBuffers ( ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
2009-05-02 23:53:27 +02:00
glShadeModel ( GL_FLAT ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_LIGHTING ) ;
glDisable ( GL_CULL_FACE ) ;
glEnable ( GL_TEXTURE_2D ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
GLfloat tex_width = ( ( GLfloat ) ( width ) / ( GLfloat ) texsize ) ;
GLfloat tex_height = ( ( GLfloat ) ( height ) / ( GLfloat ) texsize ) ;
if ( glIsList ( sdl . opengl . displaylist ) ) glDeleteLists ( sdl . opengl . displaylist , 1 ) ;
sdl . opengl . displaylist = glGenLists ( 1 ) ;
glNewList ( sdl . opengl . displaylist , GL_COMPILE ) ;
glBindTexture ( GL_TEXTURE_2D , sdl . opengl . texture ) ;
glBegin ( GL_QUADS ) ;
// lower left
glTexCoord2f ( 0 , tex_height ) ; glVertex2f ( - 1.0f , - 1.0f ) ;
// lower right
glTexCoord2f ( tex_width , tex_height ) ; glVertex2f ( 1.0f , - 1.0f ) ;
// upper right
glTexCoord2f ( tex_width , 0 ) ; glVertex2f ( 1.0f , 1.0f ) ;
// upper left
glTexCoord2f ( 0 , 0 ) ; glVertex2f ( - 1.0f , 1.0f ) ;
glEnd ( ) ;
glEndList ( ) ;
sdl . desktop . type = SCREEN_OPENGL ;
2009-05-03 00:18:08 +02:00
retFlags = GFX_CAN_32 | GFX_SCALING ;
# if defined(NVIDIA_PixelDataRange)
if ( sdl . opengl . pixel_data_range )
retFlags | = GFX_HARDWARE ;
# endif
break ;
2009-05-02 23:53:27 +02:00
} //OPENGL
# endif //C_OPENGL
} //CASE
2009-05-03 00:18:08 +02:00
if ( retFlags )
GFX_Start ( ) ;
if ( ! sdl . mouse . autoenable ) SDL_ShowCursor ( sdl . mouse . autolock ? SDL_DISABLE : SDL_ENABLE ) ;
return retFlags ;
2009-05-02 23:03:37 +02:00
}
2009-05-03 00:18:08 +02:00
void GFX_CaptureMouse ( void ) {
2009-05-02 23:20:05 +02:00
sdl . mouse . locked = ! sdl . mouse . locked ;
if ( sdl . mouse . locked ) {
2009-05-02 23:03:37 +02:00
SDL_WM_GrabInput ( SDL_GRAB_ON ) ;
SDL_ShowCursor ( SDL_DISABLE ) ;
} else {
SDL_WM_GrabInput ( SDL_GRAB_OFF ) ;
2009-05-03 00:18:08 +02:00
if ( sdl . mouse . autoenable | | ! sdl . mouse . autolock ) SDL_ShowCursor ( SDL_ENABLE ) ;
2009-05-02 23:03:37 +02:00
}
2009-05-03 00:02:15 +02:00
mouselocked = sdl . mouse . locked ;
}
2009-05-03 00:18:08 +02:00
bool mouselocked ; //Global variable for mapper
static void CaptureMouse ( bool pressed ) {
if ( ! pressed )
return ;
GFX_CaptureMouse ( ) ;
2009-05-02 23:03:37 +02:00
}
2009-05-03 00:18:08 +02:00
void GFX_SwitchFullScreen ( void ) {
2009-05-02 23:53:27 +02:00
sdl . desktop . fullscreen = ! sdl . desktop . fullscreen ;
if ( sdl . desktop . fullscreen ) {
2009-05-03 00:18:08 +02:00
if ( ! sdl . mouse . locked ) GFX_CaptureMouse ( ) ;
2009-05-02 23:27:47 +02:00
} else {
2009-05-03 00:18:08 +02:00
if ( sdl . mouse . locked ) GFX_CaptureMouse ( ) ;
2009-05-02 23:03:37 +02:00
}
2009-05-03 00:02:15 +02:00
GFX_ResetScreen ( ) ;
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:35:44 +02:00
2009-05-03 00:18:08 +02:00
static void SwitchFullScreen ( bool pressed ) {
if ( ! pressed )
return ;
GFX_SwitchFullScreen ( ) ;
2009-05-02 23:20:05 +02:00
}
2009-05-02 23:03:37 +02:00
2009-05-03 00:18:08 +02:00
2009-05-02 23:53:27 +02:00
bool GFX_StartUpdate ( Bit8u * & pixels , Bitu & pitch ) {
2009-05-03 00:28:34 +02:00
if ( ! sdl . active | | sdl . updating )
return false ;
2009-05-02 23:53:27 +02:00
switch ( sdl . desktop . type ) {
case SCREEN_SURFACE :
2009-05-03 00:18:08 +02:00
if ( sdl . blit . surface ) {
if ( SDL_MUSTLOCK ( sdl . blit . surface ) & & SDL_LockSurface ( sdl . blit . surface ) )
2009-05-02 23:53:27 +02:00
return false ;
2009-05-03 00:18:08 +02:00
pixels = ( Bit8u * ) sdl . blit . surface - > pixels ;
pitch = sdl . blit . surface - > pitch ;
} else {
if ( SDL_MUSTLOCK ( sdl . surface ) & & SDL_LockSurface ( sdl . surface ) )
return false ;
pixels = ( Bit8u * ) sdl . surface - > pixels ;
pixels + = sdl . clip . y * sdl . surface - > pitch ;
pixels + = sdl . clip . x * sdl . surface - > format - > BytesPerPixel ;
pitch = sdl . surface - > pitch ;
2009-05-02 23:35:44 +02:00
}
2009-05-03 00:18:08 +02:00
sdl . updating = true ;
2009-05-02 23:53:27 +02:00
return true ;
2009-05-03 00:18:08 +02:00
# if (HAVE_DDRAW_H) && defined(WIN32)
2009-05-03 00:02:15 +02:00
case SCREEN_SURFACE_DDRAW :
if ( SDL_LockSurface ( sdl . blit . surface ) ) {
// LOG_MSG("SDL Lock failed");
return false ;
}
pixels = ( Bit8u * ) sdl . blit . surface - > pixels ;
pitch = sdl . blit . surface - > pitch ;
2009-05-03 00:18:08 +02:00
sdl . updating = true ;
2009-05-03 00:02:15 +02:00
return true ;
# endif
2009-05-02 23:53:27 +02:00
case SCREEN_OVERLAY :
SDL_LockYUVOverlay ( sdl . overlay ) ;
pixels = ( Bit8u * ) * ( sdl . overlay - > pixels ) ;
pitch = * ( sdl . overlay - > pitches ) ;
2009-05-03 00:18:08 +02:00
sdl . updating = true ;
2009-05-02 23:53:27 +02:00
return true ;
# if C_OPENGL
case SCREEN_OPENGL :
pixels = ( Bit8u * ) sdl . opengl . framebuf ;
pitch = sdl . opengl . pitch ;
2009-05-03 00:18:08 +02:00
sdl . updating = true ;
2009-05-02 23:53:27 +02:00
return true ;
# endif
}
return false ;
}
2009-05-03 00:18:08 +02:00
void GFX_EndUpdate ( const Bit16u * changedLines ) {
2009-05-03 00:02:15 +02:00
int ret ;
2009-05-03 00:28:34 +02:00
if ( ! sdl . updating )
return ;
2009-05-02 23:53:27 +02:00
sdl . updating = false ;
switch ( sdl . desktop . type ) {
case SCREEN_SURFACE :
2009-05-02 23:35:44 +02:00
if ( SDL_MUSTLOCK ( sdl . surface ) ) {
2009-05-03 00:18:08 +02:00
if ( sdl . blit . surface ) {
SDL_UnlockSurface ( sdl . blit . surface ) ;
int Blit = SDL_BlitSurface ( sdl . blit . surface , 0 , sdl . surface , & sdl . clip ) ;
LOG ( LOG_MISC , LOG_WARN ) ( " BlitSurface returned %d " , Blit ) ;
} else {
SDL_UnlockSurface ( sdl . surface ) ;
}
SDL_Flip ( sdl . surface ) ;
} else if ( changedLines ) {
Bitu y = 0 , index = 0 , rectCount = 0 ;
while ( y < sdl . draw . height ) {
if ( ! ( index & 1 ) ) {
y + = changedLines [ index ] ;
} else {
SDL_Rect * rect = & sdl . updateRects [ rectCount + + ] ;
rect - > x = sdl . clip . x ;
rect - > y = sdl . clip . y + y ;
rect - > w = ( Bit16u ) sdl . draw . width ;
rect - > h = changedLines [ index ] ;
#if 0
if ( rect - > h + rect - > y > sdl . surface - > h ) {
LOG_MSG ( " WTF " ) ;
}
# endif
y + = changedLines [ index ] ;
}
index + + ;
}
if ( rectCount )
SDL_UpdateRects ( sdl . surface , rectCount , sdl . updateRects ) ;
2009-05-02 23:35:44 +02:00
}
2009-05-02 23:53:27 +02:00
break ;
2009-05-03 00:18:08 +02:00
# if (HAVE_DDRAW_H) && defined(WIN32)
2009-05-03 00:02:15 +02:00
case SCREEN_SURFACE_DDRAW :
2009-05-03 00:28:34 +02:00
SDL_UnlockSurface ( sdl . blit . surface ) ;
2009-05-03 00:02:15 +02:00
ret = IDirectDrawSurface3_Blt (
sdl . surface - > hwdata - > dd_writebuf , & sdl . blit . rect ,
sdl . blit . surface - > hwdata - > dd_surface , 0 ,
DDBLT_WAIT , NULL ) ;
switch ( ret ) {
case DD_OK :
break ;
case DDERR_SURFACELOST :
IDirectDrawSurface3_Restore ( sdl . blit . surface - > hwdata - > dd_surface ) ;
2009-05-03 00:18:08 +02:00
IDirectDrawSurface3_Restore ( sdl . surface - > hwdata - > dd_surface ) ;
2009-05-03 00:02:15 +02:00
break ;
default :
LOG_MSG ( " DDRAW:Failed to blit, error %X " , ret ) ;
}
SDL_Flip ( sdl . surface ) ;
break ;
# endif
2009-05-02 23:53:27 +02:00
case SCREEN_OVERLAY :
SDL_UnlockYUVOverlay ( sdl . overlay ) ;
SDL_DisplayYUVOverlay ( sdl . overlay , & sdl . clip ) ;
break ;
# if C_OPENGL
case SCREEN_OPENGL :
2009-05-03 00:18:08 +02:00
# if defined(NVIDIA_PixelDataRange)
if ( sdl . opengl . pixel_data_range ) {
glBindTexture ( GL_TEXTURE_2D , sdl . opengl . texture ) ;
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , 0 ,
sdl . draw . width , sdl . draw . height , GL_BGRA_EXT ,
GL_UNSIGNED_INT_8_8_8_8_REV , sdl . opengl . framebuf ) ;
glCallList ( sdl . opengl . displaylist ) ;
SDL_GL_SwapBuffers ( ) ;
} else
# endif
if ( changedLines ) {
Bitu y = 0 , index = 0 ;
glBindTexture ( GL_TEXTURE_2D , sdl . opengl . texture ) ;
while ( y < sdl . draw . height ) {
if ( ! ( index & 1 ) ) {
y + = changedLines [ index ] ;
} else {
Bit8u * pixels = ( Bit8u * ) sdl . opengl . framebuf + y * sdl . opengl . pitch ;
Bitu height = changedLines [ index ] ;
glTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , y ,
sdl . draw . width , height , GL_BGRA_EXT ,
GL_UNSIGNED_INT_8_8_8_8_REV , pixels ) ;
y + = height ;
}
index + + ;
}
glCallList ( sdl . opengl . displaylist ) ;
SDL_GL_SwapBuffers ( ) ;
}
2009-05-02 23:53:27 +02:00
break ;
2009-05-02 23:35:44 +02:00
# endif
2009-05-02 23:03:37 +02:00
2009-05-02 23:53:27 +02:00
}
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:27:47 +02:00
2009-05-02 23:03:37 +02:00
void GFX_SetPalette ( Bitu start , Bitu count , GFX_PalEntry * entries ) {
2009-05-02 23:35:44 +02:00
/* I should probably not change the GFX_PalEntry :) */
2009-05-02 23:53:27 +02:00
if ( sdl . surface - > flags & SDL_HWPALETTE ) {
2009-05-02 23:03:37 +02:00
if ( ! SDL_SetPalette ( sdl . surface , SDL_PHYSPAL , ( SDL_Color * ) entries , start , count ) ) {
E_Exit ( " SDL:Can't set palette " ) ;
}
} else {
if ( ! SDL_SetPalette ( sdl . surface , SDL_LOGPAL , ( SDL_Color * ) entries , start , count ) ) {
E_Exit ( " SDL:Can't set palette " ) ;
}
}
}
2009-05-02 23:27:47 +02:00
Bitu GFX_GetRGB ( Bit8u red , Bit8u green , Bit8u blue ) {
2009-05-02 23:53:27 +02:00
switch ( sdl . desktop . type ) {
case SCREEN_SURFACE :
2009-05-03 00:02:15 +02:00
case SCREEN_SURFACE_DDRAW :
2009-05-02 23:53:27 +02:00
return SDL_MapRGB ( sdl . surface - > format , red , green , blue ) ;
case SCREEN_OVERLAY :
{
Bit8u y = ( 9797 * ( red ) + 19237 * ( green ) + 3734 * ( blue ) ) > > 15 ;
Bit8u u = ( 18492 * ( ( blue ) - ( y ) ) > > 15 ) + 128 ;
Bit8u v = ( 23372 * ( ( red ) - ( y ) ) > > 15 ) + 128 ;
2009-05-03 00:02:15 +02:00
# ifdef WORDS_BIGENDIAN
return ( y < < 0 ) | ( v < < 8 ) | ( y < < 16 ) | ( u < < 24 ) ;
# else
2009-05-02 23:53:27 +02:00
return ( u < < 0 ) | ( y < < 8 ) | ( v < < 16 ) | ( y < < 24 ) ;
2009-05-03 00:02:15 +02:00
# endif
2009-05-02 23:53:27 +02:00
}
case SCREEN_OPENGL :
// return ((red << 0) | (green << 8) | (blue << 16)) | (255 << 24);
//USE BGRA
return ( ( blue < < 0 ) | ( green < < 8 ) | ( red < < 16 ) ) | ( 255 < < 24 ) ;
}
return 0 ;
2009-05-02 23:03:37 +02:00
}
void GFX_Stop ( ) {
2009-05-03 00:18:08 +02:00
if ( sdl . updating )
GFX_EndUpdate ( 0 ) ;
2009-05-02 23:03:37 +02:00
sdl . active = false ;
2009-05-02 23:35:44 +02:00
}
2009-05-02 23:03:37 +02:00
void GFX_Start ( ) {
sdl . active = true ;
}
2009-05-02 23:20:05 +02:00
static void GUI_ShutDown ( Section * sec ) {
GFX_Stop ( ) ;
2009-05-03 00:18:08 +02:00
if ( sdl . draw . callback ) ( sdl . draw . callback ) ( GFX_CallBackStop ) ;
if ( sdl . mouse . locked ) GFX_CaptureMouse ( ) ;
if ( sdl . desktop . fullscreen ) GFX_SwitchFullScreen ( ) ;
2009-05-02 23:35:44 +02:00
}
2009-05-03 00:18:08 +02:00
static void KillSwitch ( bool pressed ) {
if ( ! pressed )
return ;
2009-05-02 23:35:44 +02:00
throw 1 ;
2009-05-02 23:20:05 +02:00
}
2009-05-02 23:03:37 +02:00
2009-05-03 00:02:15 +02:00
static void SetPriority ( PRIORITY_LEVELS level ) {
2009-05-03 00:08:43 +02:00
# if C_SET_PRIORITY
// Do nothing if priorties are not the same and not root, else the highest
// priority can not be set as users can only lower priority (not restore it)
if ( ( sdl . priority . focus ! = sdl . priority . nofocus ) & &
( getuid ( ) ! = 0 ) ) return ;
# endif
2009-05-03 00:02:15 +02:00
switch ( level ) {
# ifdef WIN32
2009-05-03 00:28:34 +02:00
case PRIORITY_LEVEL_PAUSE : // if DOSBox is paused, assume idle priority
2009-05-03 00:18:08 +02:00
case PRIORITY_LEVEL_LOWEST :
SetPriorityClass ( GetCurrentProcess ( ) , IDLE_PRIORITY_CLASS ) ;
break ;
2009-05-03 00:02:15 +02:00
case PRIORITY_LEVEL_LOWER :
SetPriorityClass ( GetCurrentProcess ( ) , BELOW_NORMAL_PRIORITY_CLASS ) ;
break ;
case PRIORITY_LEVEL_NORMAL :
SetPriorityClass ( GetCurrentProcess ( ) , NORMAL_PRIORITY_CLASS ) ;
break ;
case PRIORITY_LEVEL_HIGHER :
SetPriorityClass ( GetCurrentProcess ( ) , ABOVE_NORMAL_PRIORITY_CLASS ) ;
break ;
case PRIORITY_LEVEL_HIGHEST :
SetPriorityClass ( GetCurrentProcess ( ) , HIGH_PRIORITY_CLASS ) ;
break ;
# elif C_SET_PRIORITY
2009-05-03 00:08:43 +02:00
/* Linux use group as dosbox has mulitple threads under linux */
2009-05-03 00:28:34 +02:00
case PRIORITY_LEVEL_PAUSE : // if DOSBox is paused, assume idle priority
2009-05-03 00:18:08 +02:00
case PRIORITY_LEVEL_LOWEST :
setpriority ( PRIO_PGRP , 0 , PRIO_MAX ) ;
break ;
2009-05-03 00:02:15 +02:00
case PRIORITY_LEVEL_LOWER :
2009-05-03 00:08:43 +02:00
setpriority ( PRIO_PGRP , 0 , PRIO_MAX - ( PRIO_TOTAL / 3 ) ) ;
2009-05-03 00:02:15 +02:00
break ;
case PRIORITY_LEVEL_NORMAL :
2009-05-03 00:08:43 +02:00
setpriority ( PRIO_PGRP , 0 , PRIO_MAX - ( PRIO_TOTAL / 2 ) ) ;
2009-05-03 00:02:15 +02:00
break ;
case PRIORITY_LEVEL_HIGHER :
2009-05-03 00:08:43 +02:00
setpriority ( PRIO_PGRP , 0 , PRIO_MAX - ( ( 3 * PRIO_TOTAL ) / 5 ) ) ;
2009-05-03 00:02:15 +02:00
break ;
case PRIORITY_LEVEL_HIGHEST :
2009-05-03 00:08:43 +02:00
setpriority ( PRIO_PGRP , 0 , PRIO_MAX - ( ( 3 * PRIO_TOTAL ) / 4 ) ) ;
2009-05-03 00:02:15 +02:00
break ;
# endif
default :
break ;
}
}
2009-05-03 00:18:08 +02:00
static unsigned char logo [ 32 * 32 * 4 ] = {
# include "dosbox_logo.h"
} ;
2009-05-02 23:20:05 +02:00
static void GUI_StartUp ( Section * sec ) {
sec - > AddDestroyFunction ( & GUI_ShutDown ) ;
Section_prop * section = static_cast < Section_prop * > ( sec ) ;
2009-05-02 23:03:37 +02:00
sdl . active = false ;
2009-05-02 23:53:27 +02:00
sdl . updating = false ;
2009-05-03 00:18:08 +02:00
2009-05-03 00:44:30 +02:00
# if !defined(MACOSX)
2009-05-03 00:18:08 +02:00
/* Set Icon (must be done before any sdl_setvideomode call) */
2009-05-03 00:44:30 +02:00
/* But don't set it on OS X, as we use a nicer external icon there. */
2009-05-03 00:18:08 +02:00
# if WORDS_BIGENDIAN
SDL_Surface * logos = SDL_CreateRGBSurfaceFrom ( ( void * ) logo , 32 , 32 , 32 , 128 , 0xff000000 , 0x00ff0000 , 0x0000ff00 , 0 ) ;
# else
SDL_Surface * logos = SDL_CreateRGBSurfaceFrom ( ( void * ) logo , 32 , 32 , 32 , 128 , 0x000000ff , 0x0000ff00 , 0x00ff0000 , 0 ) ;
# endif
SDL_WM_SetIcon ( logos , NULL ) ;
2009-05-03 00:44:30 +02:00
# endif
2009-05-03 00:18:08 +02:00
2009-05-02 23:53:27 +02:00
sdl . desktop . fullscreen = section - > Get_bool ( " fullscreen " ) ;
2009-05-02 23:43:00 +02:00
sdl . wait_on_error = section - > Get_bool ( " waitonerror " ) ;
2009-05-03 00:02:15 +02:00
const char * priority = section - > Get_string ( " priority " ) ;
if ( priority & & priority [ 0 ] ) {
Bitu next ;
2009-05-03 00:18:08 +02:00
if ( ! strncasecmp ( priority , " lowest " , 6 ) ) {
sdl . priority . focus = PRIORITY_LEVEL_LOWEST ; next = 6 ;
} else if ( ! strncasecmp ( priority , " lower " , 5 ) ) {
2009-05-03 00:02:15 +02:00
sdl . priority . focus = PRIORITY_LEVEL_LOWER ; next = 5 ;
} else if ( ! strncasecmp ( priority , " normal " , 6 ) ) {
sdl . priority . focus = PRIORITY_LEVEL_NORMAL ; next = 6 ;
} else if ( ! strncasecmp ( priority , " higher " , 6 ) ) {
sdl . priority . focus = PRIORITY_LEVEL_HIGHER ; next = 6 ;
} else if ( ! strncasecmp ( priority , " highest " , 7 ) ) {
sdl . priority . focus = PRIORITY_LEVEL_HIGHEST ; next = 7 ;
} else {
next = 0 ; sdl . priority . focus = PRIORITY_LEVEL_HIGHER ;
}
priority = & priority [ next ] ;
if ( next & & priority [ 0 ] = = ' , ' & & priority [ 1 ] ) {
priority + + ;
2009-05-03 00:18:08 +02:00
if ( ! strncasecmp ( priority , " lowest " , 6 ) ) {
sdl . priority . nofocus = PRIORITY_LEVEL_LOWEST ;
} else if ( ! strncasecmp ( priority , " lower " , 5 ) ) {
2009-05-03 00:02:15 +02:00
sdl . priority . nofocus = PRIORITY_LEVEL_LOWER ;
} else if ( ! strncasecmp ( priority , " normal " , 6 ) ) {
sdl . priority . nofocus = PRIORITY_LEVEL_NORMAL ;
} else if ( ! strncasecmp ( priority , " higher " , 6 ) ) {
sdl . priority . nofocus = PRIORITY_LEVEL_HIGHER ;
} else if ( ! strncasecmp ( priority , " highest " , 7 ) ) {
sdl . priority . nofocus = PRIORITY_LEVEL_HIGHEST ;
2009-05-03 00:28:34 +02:00
} else if ( ! strncasecmp ( priority , " pause " , 5 ) ) {
/* we only check for pause here, because it makes no sense
* for DOSBox to be paused while it has focus
*/
sdl . priority . nofocus = PRIORITY_LEVEL_PAUSE ;
2009-05-03 00:02:15 +02:00
} else {
sdl . priority . nofocus = PRIORITY_LEVEL_NORMAL ;
}
} else sdl . priority . nofocus = sdl . priority . focus ;
} else {
sdl . priority . focus = PRIORITY_LEVEL_HIGHER ;
sdl . priority . nofocus = PRIORITY_LEVEL_NORMAL ;
}
2009-05-03 00:08:43 +02:00
SetPriority ( sdl . priority . focus ) ; //Assume focus on startup
2009-05-02 23:20:05 +02:00
sdl . mouse . locked = false ;
2009-05-03 00:02:15 +02:00
mouselocked = false ; //Global for mapper
2009-05-02 23:20:05 +02:00
sdl . mouse . requestlock = false ;
2009-05-03 00:18:08 +02:00
sdl . desktop . full . fixed = false ;
2009-05-03 00:02:15 +02:00
const char * fullresolution = section - > Get_string ( " fullresolution " ) ;
2009-05-03 00:18:08 +02:00
sdl . desktop . full . width = 0 ;
sdl . desktop . full . height = 0 ;
2009-05-03 00:02:15 +02:00
if ( fullresolution & & * fullresolution ) {
2009-05-03 00:18:08 +02:00
char res [ 100 ] ;
strncpy ( res , fullresolution , sizeof ( res ) ) ;
2009-05-03 00:02:15 +02:00
fullresolution = lowcase ( res ) ; //so x and X are allowed
2009-05-03 00:18:08 +02:00
if ( strcmp ( fullresolution , " original " ) ) {
sdl . desktop . full . fixed = true ;
char * height = const_cast < char * > ( strchr ( fullresolution , ' x ' ) ) ;
if ( height & & * height ) {
* height = 0 ;
sdl . desktop . full . height = atoi ( height + 1 ) ;
sdl . desktop . full . width = atoi ( res ) ;
}
}
}
2009-05-03 00:02:15 +02:00
2009-05-03 00:18:08 +02:00
sdl . desktop . window . width = 0 ;
sdl . desktop . window . height = 0 ;
const char * windowresolution = section - > Get_string ( " windowresolution " ) ;
if ( windowresolution & & * windowresolution ) {
char res [ 100 ] ;
strncpy ( res , windowresolution , sizeof ( res ) ) ;
windowresolution = lowcase ( res ) ; //so x and X are allowed
if ( strcmp ( windowresolution , " original " ) ) {
char * height = const_cast < char * > ( strchr ( windowresolution , ' x ' ) ) ;
if ( height & & * height ) {
* height = 0 ;
sdl . desktop . window . height = atoi ( height + 1 ) ;
sdl . desktop . window . width = atoi ( res ) ;
}
2009-05-03 00:02:15 +02:00
}
}
2009-05-02 23:53:27 +02:00
sdl . desktop . doublebuf = section - > Get_bool ( " fulldouble " ) ;
2009-05-03 00:18:08 +02:00
if ( ! sdl . desktop . full . width ) {
2009-05-02 23:53:27 +02:00
# ifdef WIN32
2009-05-03 00:18:08 +02:00
sdl . desktop . full . width = GetSystemMetrics ( SM_CXSCREEN ) ;
2009-05-02 23:53:27 +02:00
# else
2009-05-03 00:18:08 +02:00
sdl . desktop . full . width = 1024 ;
2009-05-02 23:53:27 +02:00
# endif
}
2009-05-03 00:18:08 +02:00
if ( ! sdl . desktop . full . height ) {
2009-05-02 23:53:27 +02:00
# ifdef WIN32
2009-05-03 00:18:08 +02:00
sdl . desktop . full . height = GetSystemMetrics ( SM_CYSCREEN ) ;
2009-05-02 23:53:27 +02:00
# else
2009-05-03 00:18:08 +02:00
sdl . desktop . full . height = 768 ;
2009-05-02 23:53:27 +02:00
# endif
}
2009-05-03 00:08:43 +02:00
sdl . mouse . autoenable = section - > Get_bool ( " autolock " ) ;
2009-05-03 00:18:08 +02:00
if ( ! sdl . mouse . autoenable ) SDL_ShowCursor ( SDL_DISABLE ) ;
2009-05-02 23:20:05 +02:00
sdl . mouse . autolock = false ;
sdl . mouse . sensitivity = section - > Get_int ( " sensitivity " ) ;
2009-05-02 23:53:27 +02:00
const char * output = section - > Get_string ( " output " ) ;
if ( ! strcasecmp ( output , " surface " ) ) {
sdl . desktop . want_type = SCREEN_SURFACE ;
2009-05-03 00:18:08 +02:00
# if (HAVE_DDRAW_H) && defined(WIN32)
2009-05-03 00:02:15 +02:00
} else if ( ! strcasecmp ( output , " ddraw " ) ) {
sdl . desktop . want_type = SCREEN_SURFACE_DDRAW ;
# endif
2009-05-02 23:53:27 +02:00
} else if ( ! strcasecmp ( output , " overlay " ) ) {
sdl . desktop . want_type = SCREEN_OVERLAY ;
# if C_OPENGL
} else if ( ! strcasecmp ( output , " opengl " ) ) {
sdl . desktop . want_type = SCREEN_OPENGL ;
sdl . opengl . bilinear = true ;
} else if ( ! strcasecmp ( output , " openglnb " ) ) {
sdl . desktop . want_type = SCREEN_OPENGL ;
sdl . opengl . bilinear = false ;
# endif
} else {
LOG_MSG ( " SDL:Unsupported output device %s, switching back to surface " , output ) ;
sdl . desktop . want_type = SCREEN_SURFACE ;
}
sdl . overlay = 0 ;
# if C_OPENGL
2009-05-03 00:02:15 +02:00
if ( sdl . desktop . want_type = = SCREEN_OPENGL ) { /* OPENGL is requested */
2009-05-02 23:53:27 +02:00
sdl . surface = SDL_SetVideoMode ( 640 , 400 , 0 , SDL_OPENGL ) ;
2009-05-03 00:18:08 +02:00
if ( sdl . surface = = NULL ) {
LOG_MSG ( " Could not initialize OpenGL, switching back to surface " ) ;
sdl . desktop . want_type = SCREEN_SURFACE ;
} else {
2009-05-02 23:53:27 +02:00
sdl . opengl . framebuf = 0 ;
sdl . opengl . texture = 0 ;
sdl . opengl . displaylist = 0 ;
glGetIntegerv ( GL_MAX_TEXTURE_SIZE , & sdl . opengl . max_texsize ) ;
# if defined(__WIN32__) && defined(NVIDIA_PixelDataRange)
glPixelDataRangeNV = ( PFNGLPIXELDATARANGENVPROC ) wglGetProcAddress ( " glPixelDataRangeNV " ) ;
db_glAllocateMemoryNV = ( PFNWGLALLOCATEMEMORYNVPROC ) wglGetProcAddress ( " wglAllocateMemoryNV " ) ;
db_glFreeMemoryNV = ( PFNWGLFREEMEMORYNVPROC ) wglGetProcAddress ( " wglFreeMemoryNV " ) ;
# endif
const char * gl_ext = ( const char * ) glGetString ( GL_EXTENSIONS ) ;
2009-05-03 00:02:15 +02:00
if ( gl_ext & & * gl_ext ) {
sdl . opengl . packed_pixel = ( strstr ( gl_ext , " EXT_packed_pixels " ) > 0 ) ;
sdl . opengl . paletted_texture = ( strstr ( gl_ext , " EXT_paletted_texture " ) > 0 ) ;
2009-05-02 23:53:27 +02:00
# if defined(NVIDIA_PixelDataRange)
2009-05-03 00:02:15 +02:00
sdl . opengl . pixel_data_range = ( strstr ( gl_ext , " GL_NV_pixel_data_range " ) > 0 ) & &
glPixelDataRangeNV & & db_glAllocateMemoryNV & & db_glFreeMemoryNV ;
2009-05-03 00:18:08 +02:00
sdl . opengl . pixel_data_range = 0 ;
2009-05-02 23:35:44 +02:00
# endif
2009-05-03 00:02:15 +02:00
} else {
sdl . opengl . packed_pixel = sdl . opengl . paletted_texture = false ;
}
2009-05-03 00:18:08 +02:00
}
2009-05-03 00:02:15 +02:00
} /* OPENGL is requested end */
2009-05-02 23:53:27 +02:00
# endif //OPENGL
2009-05-02 23:35:44 +02:00
/* Initialize screen for first time */
2009-05-02 23:43:00 +02:00
sdl . surface = SDL_SetVideoMode ( 640 , 400 , 0 , 0 ) ;
2009-05-03 00:18:08 +02:00
if ( sdl . surface = = NULL ) E_Exit ( " Could not initialize video: %s " , SDL_GetError ( ) ) ;
2009-05-02 23:53:27 +02:00
sdl . desktop . bpp = sdl . surface - > format - > BitsPerPixel ;
if ( sdl . desktop . bpp = = 24 ) {
2009-05-02 23:43:00 +02:00
LOG_MSG ( " SDL:You are running in 24 bpp mode, this will slow down things! " ) ;
}
2009-05-03 00:02:15 +02:00
GFX_Stop ( ) ;
/* Get some Event handlers */
MAPPER_AddHandler ( KillSwitch , MK_f9 , MMOD1 , " shutdown " , " ShutDown " ) ;
MAPPER_AddHandler ( CaptureMouse , MK_f10 , MMOD1 , " capmouse " , " Cap Mouse " ) ;
MAPPER_AddHandler ( SwitchFullScreen , MK_return , MMOD2 , " fullscr " , " Fullscreen " ) ;
# if C_DEBUG
/* Pause binds with activate-debugger */
# else
2009-05-03 00:18:08 +02:00
MAPPER_AddHandler ( PauseDOSBox , MK_pause , MMOD2 , " pause " , " Pause " ) ;
2009-05-03 00:02:15 +02:00
# endif
2009-05-03 00:08:43 +02:00
/* Get Keyboard state of numlock and capslock */
SDLMod keystate = SDL_GetModState ( ) ;
if ( keystate & KMOD_NUM ) startup_state_numlock = true ;
if ( keystate & KMOD_CAPS ) startup_state_capslock = true ;
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:20:05 +02:00
void Mouse_AutoLock ( bool enable ) {
sdl . mouse . autolock = enable ;
2009-05-03 00:18:08 +02:00
if ( sdl . mouse . autoenable ) sdl . mouse . requestlock = enable ;
else {
SDL_ShowCursor ( enable ? SDL_DISABLE : SDL_ENABLE ) ;
sdl . mouse . requestlock = false ;
}
2009-05-02 23:20:05 +02:00
}
2009-05-02 23:03:37 +02:00
static void HandleMouseMotion ( SDL_MouseMotionEvent * motion ) {
2009-05-03 00:18:08 +02:00
if ( sdl . mouse . locked | | ! sdl . mouse . autoenable )
2009-05-03 00:37:32 +02:00
Mouse_CursorMoved ( ( float ) motion - > xrel * sdl . mouse . sensitivity / 100.0f ,
( float ) motion - > yrel * sdl . mouse . sensitivity / 100.0f ,
( float ) ( motion - > x - sdl . clip . x ) / ( sdl . clip . w - 1 ) * sdl . mouse . sensitivity / 100.0f ,
( float ) ( motion - > y - sdl . clip . y ) / ( sdl . clip . h - 1 ) * sdl . mouse . sensitivity / 100.0f ,
sdl . mouse . locked ) ;
2009-05-02 23:03:37 +02:00
}
static void HandleMouseButton ( SDL_MouseButtonEvent * button ) {
switch ( button - > state ) {
case SDL_PRESSED :
2009-05-02 23:27:47 +02:00
if ( sdl . mouse . requestlock & & ! sdl . mouse . locked ) {
2009-05-03 00:18:08 +02:00
GFX_CaptureMouse ( ) ;
2009-05-02 23:27:47 +02:00
// Dont pass klick to mouse handler
break ;
}
2009-05-03 00:18:08 +02:00
if ( ! sdl . mouse . autoenable & & sdl . mouse . autolock & & button - > button = = SDL_BUTTON_MIDDLE ) {
GFX_CaptureMouse ( ) ;
break ;
}
2009-05-02 23:03:37 +02:00
switch ( button - > button ) {
case SDL_BUTTON_LEFT :
Mouse_ButtonPressed ( 0 ) ;
break ;
case SDL_BUTTON_RIGHT :
Mouse_ButtonPressed ( 1 ) ;
break ;
case SDL_BUTTON_MIDDLE :
Mouse_ButtonPressed ( 2 ) ;
break ;
}
break ;
case SDL_RELEASED :
switch ( button - > button ) {
case SDL_BUTTON_LEFT :
Mouse_ButtonReleased ( 0 ) ;
break ;
case SDL_BUTTON_RIGHT :
Mouse_ButtonReleased ( 1 ) ;
break ;
case SDL_BUTTON_MIDDLE :
Mouse_ButtonReleased ( 2 ) ;
break ;
}
break ;
}
}
2009-05-02 23:35:44 +02:00
static Bit8u laltstate = SDL_KEYUP ;
2009-05-03 00:02:15 +02:00
static Bit8u raltstate = SDL_KEYUP ;
2009-05-02 23:03:37 +02:00
void GFX_Events ( ) {
SDL_Event event ;
2009-05-03 00:28:34 +02:00
# if defined (REDUCE_JOYSTICK_POLLING)
static int poll_delay = 0 ;
2009-05-03 00:37:32 +02:00
int time = GetTicks ( ) ;
2009-05-03 00:28:34 +02:00
if ( time - poll_delay > 20 ) {
poll_delay = time ;
if ( sdl . num_joysticks > 0 ) SDL_JoystickUpdate ( ) ;
MAPPER_UpdateJoysticks ( ) ;
}
# endif
2009-05-02 23:03:37 +02:00
while ( SDL_PollEvent ( & event ) ) {
2009-05-03 00:28:34 +02:00
switch ( event . type ) {
2009-05-02 23:20:05 +02:00
case SDL_ACTIVEEVENT :
if ( event . active . state & SDL_APPINPUTFOCUS ) {
2009-05-03 00:02:15 +02:00
if ( event . active . gain ) {
if ( sdl . desktop . fullscreen & & ! sdl . mouse . locked )
2009-05-03 00:28:34 +02:00
GFX_CaptureMouse ( ) ;
2009-05-03 00:02:15 +02:00
SetPriority ( sdl . priority . focus ) ;
} else {
2009-05-03 00:18:08 +02:00
if ( sdl . mouse . locked ) {
# ifdef WIN32
if ( sdl . desktop . fullscreen ) {
VGA_KillDrawing ( ) ;
sdl . desktop . fullscreen = false ;
GFX_ResetScreen ( ) ;
}
# endif
GFX_CaptureMouse ( ) ;
}
2009-05-03 00:02:15 +02:00
SetPriority ( sdl . priority . nofocus ) ;
2009-05-03 00:18:08 +02:00
MAPPER_LosingFocus ( ) ;
2009-05-02 23:20:05 +02:00
}
}
2009-05-03 00:28:34 +02:00
/* Non-focus priority is set to pause; check to see if we've lost window or input focus
* i . e . has the window been minimised or made inactive ?
*/
if ( sdl . priority . nofocus = = PRIORITY_LEVEL_PAUSE ) {
if ( ( event . active . state & ( SDL_APPINPUTFOCUS | SDL_APPACTIVE ) ) & & ( ! event . active . gain ) ) {
/* Window has lost focus, pause the emulator.
* This is similar to what PauseDOSBox ( ) does , but the exit criteria is different .
* Instead of waiting for the user to hit Alt - Break , we wait for the window to
* regain window or input focus .
*/
bool paused = true ;
SDL_Event ev ;
GFX_SetTitle ( - 1 , - 1 , true ) ;
KEYBOARD_ClrBuffer ( ) ;
SDL_Delay ( 500 ) ;
while ( SDL_PollEvent ( & ev ) ) {
// flush event queue.
}
while ( paused ) {
// WaitEvent waits for an event rather than polling, so CPU usage drops to zero
SDL_WaitEvent ( & ev ) ;
switch ( ev . type ) {
case SDL_QUIT : throw ( 0 ) ; break ; // a bit redundant at linux at least as the active events gets before the quit event.
case SDL_ACTIVEEVENT : // wait until we get window focus back
if ( ev . active . state & ( SDL_APPINPUTFOCUS | SDL_APPACTIVE ) ) {
// We've got focus back, so unpause and break out of the loop
if ( ev . active . gain ) {
paused = false ;
GFX_SetTitle ( - 1 , - 1 , false ) ;
}
/* Now poke a "release ALT" command into the keyboard buffer
* we have to do this , otherwise ALT will ' stick ' and cause
* problems with the app running in the DOSBox .
*/
KEYBOARD_AddKey ( KBD_leftalt , false ) ;
KEYBOARD_AddKey ( KBD_rightalt , false ) ;
}
break ;
}
}
}
}
2009-05-02 23:20:05 +02:00
break ;
2009-05-02 23:03:37 +02:00
case SDL_MOUSEMOTION :
HandleMouseMotion ( & event . motion ) ;
break ;
case SDL_MOUSEBUTTONDOWN :
case SDL_MOUSEBUTTONUP :
HandleMouseButton ( & event . button ) ;
break ;
case SDL_VIDEORESIZE :
2009-05-02 23:53:27 +02:00
// HandleVideoResize(&event.resize);
2009-05-02 23:03:37 +02:00
break ;
case SDL_QUIT :
2009-05-02 23:43:00 +02:00
throw ( 0 ) ;
2009-05-02 23:03:37 +02:00
break ;
2009-05-03 00:18:08 +02:00
case SDL_VIDEOEXPOSE :
if ( sdl . draw . callback ) sdl . draw . callback ( GFX_CallBackRedraw ) ;
break ;
2009-05-03 00:02:15 +02:00
# ifdef WIN32
case SDL_KEYDOWN :
case SDL_KEYUP :
// ignore event alt+tab
if ( event . key . keysym . sym = = SDLK_LALT ) laltstate = event . key . type ;
if ( event . key . keysym . sym = = SDLK_RALT ) raltstate = event . key . type ;
if ( ( ( event . key . keysym . sym = = SDLK_TAB ) ) & &
( ( laltstate = = SDL_KEYDOWN ) | | ( raltstate = = SDL_KEYDOWN ) ) ) break ;
# endif
default :
void MAPPER_CheckEvent ( SDL_Event * event ) ;
MAPPER_CheckEvent ( & event ) ;
2009-05-02 23:03:37 +02:00
}
2009-05-03 00:28:34 +02:00
}
2009-05-02 23:03:37 +02:00
}
2009-05-03 00:37:32 +02:00
# if defined (WIN32)
static BOOL WINAPI ConsoleEventHandler ( DWORD event ) {
switch ( event ) {
case CTRL_SHUTDOWN_EVENT :
case CTRL_LOGOFF_EVENT :
case CTRL_CLOSE_EVENT :
case CTRL_BREAK_EVENT :
raise ( SIGTERM ) ;
return TRUE ;
case CTRL_C_EVENT :
default : //pass to the next handler
return FALSE ;
}
}
# endif
2009-05-03 00:18:08 +02:00
/* static variable to show wether there is not a valid stdout.
* Fixes some bugs when - noconsole is used in a read only directory */
static bool no_stdout = false ;
2009-05-03 00:28:34 +02:00
void GFX_ShowMsg ( char const * format , . . . ) {
2009-05-02 23:43:00 +02:00
char buf [ 512 ] ;
va_list msg ;
va_start ( msg , format ) ;
vsprintf ( buf , format , msg ) ;
strcat ( buf , " \n " ) ;
va_end ( msg ) ;
2009-05-03 00:18:08 +02:00
if ( ! no_stdout ) printf ( buf ) ;
2009-05-02 23:03:37 +02:00
} ;
int main ( int argc , char * argv [ ] ) {
2009-05-02 23:20:05 +02:00
try {
CommandLine com_line ( argc , argv ) ;
Config myconf ( & com_line ) ;
control = & myconf ;
2009-05-02 23:43:00 +02:00
/* Can't disable the console with debugger enabled */
# if defined(WIN32) && !(C_DEBUG)
if ( control - > cmdline - > FindExist ( " -noconsole " ) ) {
FreeConsole ( ) ;
/* Redirect standard input and standard output */
2009-05-03 00:18:08 +02:00
if ( freopen ( STDOUT_FILE , " w " , stdout ) = = NULL )
no_stdout = true ; // No stdout so don't write messages
2009-05-02 23:43:00 +02:00
freopen ( STDERR_FILE , " w " , stderr ) ;
setvbuf ( stdout , NULL , _IOLBF , BUFSIZ ) ; /* Line buffered */
setbuf ( stderr , NULL ) ; /* No buffering */
} else {
if ( AllocConsole ( ) ) {
fclose ( stdin ) ;
fclose ( stdout ) ;
fclose ( stderr ) ;
2009-05-03 00:44:30 +02:00
freopen ( " CONIN$ " , " r " , stdin ) ;
2009-05-02 23:43:00 +02:00
freopen ( " CONOUT$ " , " w " , stdout ) ;
freopen ( " CONOUT$ " , " w " , stderr ) ;
}
2009-05-03 00:18:08 +02:00
SetConsoleTitle ( " DOSBox Status Window " ) ;
2009-05-02 23:43:00 +02:00
}
# endif //defined(WIN32) && !(C_DEBUG)
2009-05-03 00:44:30 +02:00
if ( control - > cmdline - > FindExist ( " -version " ) | |
control - > cmdline - > FindExist ( " --version " ) ) {
printf ( " \n DOSBox version %s, copyright 2002-2007 DOSBox Team. \n \n " , VERSION ) ;
printf ( " DOSBox is written by the DOSBox Team (See AUTHORS file)) \n " ) ;
printf ( " DOSBox comes with ABSOLUTELY NO WARRANTY. This is free software, \n " ) ;
printf ( " and you are welcome to redistribute it under certain conditions; \n " ) ;
printf ( " please read the COPYING file thoroughly before doing so. \n \n " ) ;
return 0 ;
}
2009-05-02 23:35:44 +02:00
# if C_DEBUG
DEBUG_SetupConsole ( ) ;
# endif
2009-05-03 00:18:08 +02:00
2009-05-03 00:37:32 +02:00
# if defined(WIN32)
SetConsoleCtrlHandler ( ( PHANDLER_ROUTINE ) ConsoleEventHandler , TRUE ) ;
# endif
2009-05-03 00:18:08 +02:00
# ifdef OS2
PPIB pib ;
PTIB tib ;
DosGetInfoBlocks ( & tib , & pib ) ;
if ( pib - > pib_ultype = = 2 ) pib - > pib_ultype = 3 ;
setbuf ( stdout , NULL ) ;
setbuf ( stderr , NULL ) ;
# endif
2009-05-03 00:44:30 +02:00
/* Display Welcometext in the console */
LOG_MSG ( " DOSBox version %s " , VERSION ) ;
LOG_MSG ( " Copyright 2002-2007 DOSBox Team, published under GNU GPL. " ) ;
LOG_MSG ( " --- " ) ;
/* Init SDL */
2009-05-03 00:02:15 +02:00
if ( SDL_Init ( SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_CDROM
2009-05-03 00:18:08 +02:00
| SDL_INIT_NOPARACHUTE
2009-05-03 00:28:34 +02:00
) < 0 ) E_Exit ( " Can't init SDL %s " , SDL_GetError ( ) ) ;
2009-05-02 23:03:37 +02:00
# ifndef DISABLE_JOYSTICK
2009-05-03 00:28:34 +02:00
//Initialise Joystick seperately. This way we can warn when it fails instead
//of exiting the application
if ( SDL_InitSubSystem ( SDL_INIT_JOYSTICK ) < 0 ) LOG_MSG ( " Failed to init joystick support " ) ;
2009-05-02 23:03:37 +02:00
# endif
2009-05-03 00:28:34 +02:00
# if defined (WIN32)
# if SDL_VERSION_ATLEAST(1, 2, 10)
sdl . using_windib = true ;
# else
sdl . using_windib = false ;
# endif
char sdl_drv_name [ 128 ] ;
if ( getenv ( " SDL_VIDEODRIVER " ) = = NULL ) {
if ( SDL_VideoDriverName ( sdl_drv_name , 128 ) ! = NULL ) {
2009-05-03 00:37:32 +02:00
sdl . using_windib = false ;
2009-05-03 00:28:34 +02:00
if ( strcmp ( sdl_drv_name , " directx " ) ! = 0 ) {
SDL_QuitSubSystem ( SDL_INIT_VIDEO ) ;
putenv ( " SDL_VIDEODRIVER=directx " ) ;
2009-05-03 00:37:32 +02:00
if ( SDL_InitSubSystem ( SDL_INIT_VIDEO ) < 0 ) {
putenv ( " SDL_VIDEODRIVER=windib " ) ;
if ( SDL_InitSubSystem ( SDL_INIT_VIDEO ) < 0 ) E_Exit ( " Can't init SDL Video %s " , SDL_GetError ( ) ) ;
sdl . using_windib = true ;
}
2009-05-03 00:28:34 +02:00
}
}
} else {
char * sdl_videodrv = getenv ( " SDL_VIDEODRIVER " ) ;
if ( strcmp ( sdl_videodrv , " directx " ) = = 0 ) sdl . using_windib = false ;
else if ( strcmp ( sdl_videodrv , " windib " ) = = 0 ) sdl . using_windib = true ;
}
if ( SDL_VideoDriverName ( sdl_drv_name , 128 ) ! = NULL ) {
if ( strcmp ( sdl_drv_name , " windib " ) = = 0 ) LOG_MSG ( " SDL_Init: Starting up with SDL windib video driver. \n Try to update your video card and directx drivers! " ) ;
}
# endif
sdl . num_joysticks = SDL_NumJoysticks ( ) ;
2009-05-02 23:20:05 +02:00
Section_prop * sdl_sec = control - > AddSection_prop ( " sdl " , & GUI_StartUp ) ;
2009-05-03 00:02:15 +02:00
sdl_sec - > AddInitFunction ( & MAPPER_StartUp ) ;
2009-05-02 23:20:05 +02:00
sdl_sec - > Add_bool ( " fullscreen " , false ) ;
2009-05-02 23:53:27 +02:00
sdl_sec - > Add_bool ( " fulldouble " , false ) ;
2009-05-03 00:18:08 +02:00
sdl_sec - > Add_string ( " fullresolution " , " original " ) ;
sdl_sec - > Add_string ( " windowresolution " , " original " ) ;
2009-05-02 23:53:27 +02:00
sdl_sec - > Add_string ( " output " , " surface " ) ;
2009-05-02 23:20:05 +02:00
sdl_sec - > Add_bool ( " autolock " , true ) ;
sdl_sec - > Add_int ( " sensitivity " , 100 ) ;
2009-05-02 23:43:00 +02:00
sdl_sec - > Add_bool ( " waitonerror " , true ) ;
2009-05-03 00:02:15 +02:00
sdl_sec - > Add_string ( " priority " , " higher,normal " ) ;
sdl_sec - > Add_string ( " mapperfile " , " mapper.txt " ) ;
2009-05-03 00:18:08 +02:00
sdl_sec - > Add_bool ( " usescancodes " , true ) ;
2009-05-02 23:53:27 +02:00
2009-05-02 23:43:00 +02:00
MSG_Add ( " SDL_CONFIGFILE_HELP " ,
" fullscreen -- Start dosbox directly in fullscreen. \n "
2009-05-02 23:53:27 +02:00
" fulldouble -- Use double buffering in fullscreen. \n "
2009-05-03 00:18:08 +02:00
" fullresolution -- What resolution to use for fullscreen: original or fixed size (e.g. 1024x768). \n "
" windowresolution -- Scale the window to this size IF the output device supports hardware scaling. \n "
2009-05-02 23:53:27 +02:00
" output -- What to use for output: surface,overlay "
# if C_OPENGL
" ,opengl,openglnb "
2009-05-03 00:02:15 +02:00
# endif
2009-05-03 00:18:08 +02:00
# if (HAVE_DDRAW_H) && defined(WIN32)
2009-05-03 00:02:15 +02:00
" ,ddraw "
2009-05-02 23:53:27 +02:00
# endif
" . \n "
2009-05-02 23:43:00 +02:00
" autolock -- Mouse will automatically lock, if you click on the screen. \n "
" sensitiviy -- Mouse sensitivity. \n "
" waitonerror -- Wait before closing the console if dosbox has an error. \n "
2009-05-03 00:28:34 +02:00
" priority -- Priority levels for dosbox: lowest,lower,normal,higher,highest,pause (when not focussed). \n "
2009-05-03 00:02:15 +02:00
" Second entry behind the comma is for when dosbox is not focused/minimized. \n "
" mapperfile -- File used to load/save the key/event mappings from. \n "
2009-05-03 00:18:08 +02:00
" usescancodes -- Avoid usage of symkeys, might not work on all operating systems. \n "
2009-05-03 00:02:15 +02:00
) ;
2009-05-02 23:53:27 +02:00
/* Init all the dosbox subsystems */
2009-05-02 23:20:05 +02:00
DOSBOX_Init ( ) ;
std : : string config_file ;
2009-05-03 00:28:34 +02:00
bool parsed_anyconfigfile = false ;
// First parse the configfile in the $HOME directory
if ( ( getenv ( " HOME " ) ! = NULL ) ) {
config_file = ( std : : string ) getenv ( " HOME " ) +
( std : : string ) DEFAULT_CONFIG_FILE ;
if ( control - > ParseConfigFile ( config_file . c_str ( ) ) ) parsed_anyconfigfile = true ;
2009-05-02 23:53:27 +02:00
}
2009-05-03 00:28:34 +02:00
// Add extra settings from dosbox.conf in the local directory if there is no configfile specified at the commandline
if ( ! control - > cmdline - > FindString ( " -conf " , config_file , true ) ) config_file = " dosbox.conf " ;
if ( control - > ParseConfigFile ( config_file . c_str ( ) ) ) parsed_anyconfigfile = true ;
// Add extra settings from additional configfiles at the commandline
while ( control - > cmdline - > FindString ( " -conf " , config_file , true ) )
if ( control - > ParseConfigFile ( config_file . c_str ( ) ) ) parsed_anyconfigfile = true ;
// Give a message if no configfile whatsoever was found.
if ( ! parsed_anyconfigfile ) LOG_MSG ( " CONFIG: Using default settings. Create a configfile to change them " ) ;
2009-05-02 23:43:00 +02:00
# if (ENVIRON_LINKED)
2009-05-02 23:35:44 +02:00
control - > ParseEnv ( environ ) ;
2009-05-02 23:43:00 +02:00
# endif
2009-05-02 23:20:05 +02:00
/* Init all the sections */
control - > Init ( ) ;
/* Some extra SDL Functions */
if ( control - > cmdline - > FindExist ( " -fullscreen " ) | | sdl_sec - > Get_bool ( " fullscreen " ) ) {
2009-05-02 23:53:27 +02:00
if ( ! sdl . desktop . fullscreen ) { //only switch if not allready in fullscreen
2009-05-03 00:18:08 +02:00
GFX_SwitchFullScreen ( ) ;
2009-05-02 23:53:27 +02:00
}
2009-05-02 23:20:05 +02:00
}
2009-05-03 00:02:15 +02:00
/* Init the keyMapper */
MAPPER_Init ( ) ;
2009-05-03 00:18:08 +02:00
if ( control - > cmdline - > FindExist ( " -startmapper " ) ) MAPPER_Run ( true ) ;
2009-05-03 00:02:15 +02:00
2009-05-02 23:20:05 +02:00
/* Start up main machine */
control - > StartUp ( ) ;
/* Shutdown everything */
} catch ( char * error ) {
2009-05-03 00:18:08 +02:00
GFX_ShowMsg ( " Exit to error: %s " , error ) ;
fflush ( NULL ) ;
2009-05-02 23:43:00 +02:00
if ( sdl . wait_on_error ) {
//TODO Maybe look for some way to show message in linux?
# if (C_DEBUG)
2009-05-03 00:18:08 +02:00
GFX_ShowMsg ( " Press enter to continue " ) ;
fflush ( NULL ) ;
2009-05-02 23:43:00 +02:00
fgetc ( stdin ) ;
# elif defined(WIN32)
Sleep ( 5000 ) ;
# endif
}
2009-05-02 23:03:37 +02:00
}
2009-05-02 23:43:00 +02:00
catch ( int ) {
2009-05-03 00:02:15 +02:00
; //nothing pressed killswitch
}
2009-05-03 00:08:43 +02:00
catch ( . . . ) {
throw ; //dunno what happened. rethrow for sdl to catch
2009-05-02 23:35:44 +02:00
}
2009-05-03 00:08:43 +02:00
SDL_Quit ( ) ; //Let's hope sdl will quit as well when it catches an exception
2009-05-02 23:53:27 +02:00
return 0 ;
2009-05-02 23:20:05 +02:00
} ;