2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team.
2018-11-25 12:35:38 +00:00
// Copyright (C) 1999-2018 by Sonic Team Junior.
2014-03-15 16:59:03 +00:00
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file screen.c
/// \brief Handles multiple resolutions, 8bpp/16bpp(highcolor) modes
# include "doomdef.h"
# include "doomstat.h"
# include "screen.h"
# include "console.h"
# include "am_map.h"
# include "i_system.h"
# include "i_video.h"
# include "r_local.h"
# include "r_sky.h"
# include "m_argv.h"
# include "m_misc.h"
# include "v_video.h"
# include "st_stuff.h"
# include "hu_stuff.h"
# include "z_zone.h"
# include "d_main.h"
# include "d_clisrv.h"
# include "f_finale.h"
2017-01-06 20:26:10 +00:00
# if defined (USEASM) && !defined (NORUSEASM) //&& (!defined (_MSC_VER) || (_MSC_VER <= 1200))
2014-03-15 16:59:03 +00:00
# define RUSEASM //MSC.NET can't patch itself
# endif
// --------------------------------------------
// assembly or c drawer routines for 8bpp/16bpp
// --------------------------------------------
void ( * wallcolfunc ) ( void ) ; // new wall column drawer to draw posts >128 high
void ( * colfunc ) ( void ) ; // standard column, up to 128 high posts
void ( * basecolfunc ) ( void ) ;
void ( * fuzzcolfunc ) ( void ) ; // standard fuzzy effect column drawer
void ( * transcolfunc ) ( void ) ; // translation column drawer
void ( * shadecolfunc ) ( void ) ; // smokie test..
void ( * spanfunc ) ( void ) ; // span drawer, use a 64x64 tile
void ( * splatfunc ) ( void ) ; // span drawer w/ transparency
void ( * basespanfunc ) ( void ) ; // default span func for color mode
void ( * transtransfunc ) ( void ) ; // translucent translated column drawer
void ( * twosmultipatchfunc ) ( void ) ; // for cols with transparent pixels
2016-11-16 18:43:25 +00:00
void ( * twosmultipatchtransfunc ) ( void ) ; // for cols with transparent pixels AND translucency
2014-03-15 16:59:03 +00:00
// ------------------
// global video state
// ------------------
viddef_t vid ;
INT32 setmodeneeded ; //video mode change needed if > 0 (the mode number to set + 1)
static CV_PossibleValue_t scr_depth_cons_t [ ] = { { 8 , " 8 bits " } , { 16 , " 16 bits " } , { 24 , " 24 bits " } , { 32 , " 32 bits " } , { 0 , NULL } } ;
2019-04-09 04:21:11 +00:00
static CV_PossibleValue_t shittyscreen_cons_t [ ] = { { 0 , " Okay " } , { 1 , " Shitty " } , { 2 , " Extra Shitty " } , { 0 , NULL } } ;
2014-03-15 16:59:03 +00:00
//added : 03-02-98: default screen mode, as loaded/saved in config
# ifdef WII
consvar_t cv_scr_width = { " scr_width " , " 640 " , CV_SAVE , CV_Unsigned , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_scr_height = { " scr_height " , " 480 " , CV_SAVE , CV_Unsigned , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_scr_depth = { " scr_depth " , " 16 bits " , CV_SAVE , scr_depth_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
# else
consvar_t cv_scr_width = { " scr_width " , " 1280 " , CV_SAVE , CV_Unsigned , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_scr_height = { " scr_height " , " 800 " , CV_SAVE , CV_Unsigned , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_scr_depth = { " scr_depth " , " 16 bits " , CV_SAVE , scr_depth_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
# endif
consvar_t cv_renderview = { " renderview " , " On " , 0 , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2019-04-09 04:21:11 +00:00
consvar_t cv_vhseffect = { " vhspause " , " On " , CV_SAVE , CV_OnOff , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
consvar_t cv_shittyscreen = { " televisionsignal " , " Okay " , CV_NOSHOWHELP , shittyscreen_cons_t , NULL , 0 , NULL , NULL , 0 , 0 , NULL } ;
2016-06-12 19:58:03 +00:00
static void SCR_ChangeFullscreen ( void ) ;
2014-03-15 16:59:03 +00:00
consvar_t cv_fullscreen = { " fullscreen " , " Yes " , CV_SAVE | CV_CALL , CV_YesNo , SCR_ChangeFullscreen , 0 , NULL , NULL , 0 , 0 , NULL } ;
// =========================================================================
// SCREEN VARIABLES
// =========================================================================
INT32 scr_bpp ; // current video mode bytes per pixel
UINT8 * scr_borderpatch ; // flat used to fill the reduced view borders set at ST_Init()
// =========================================================================
// Short and Tall sky drawer, for the current color mode
void ( * walldrawerfunc ) ( void ) ;
boolean R_ASM = true ;
boolean R_486 = false ;
boolean R_586 = false ;
boolean R_MMX = false ;
boolean R_SSE = false ;
boolean R_3DNow = false ;
boolean R_MMXExt = false ;
boolean R_SSE2 = false ;
void SCR_SetMode ( void )
{
if ( dedicated )
return ;
if ( ! setmodeneeded | | WipeInAction )
return ; // should never happen and don't change it during a wipe, BAD!
VID_SetMode ( - - setmodeneeded ) ;
V_SetPalette ( 0 ) ;
//
// setup the right draw routines for either 8bpp or 16bpp
//
if ( true ) //vid.bpp == 1) //Always run in 8bpp. todo: remove all 16bpp code?
{
spanfunc = basespanfunc = R_DrawSpan_8 ;
splatfunc = R_DrawSplat_8 ;
transcolfunc = R_DrawTranslatedColumn_8 ;
transtransfunc = R_DrawTranslatedTranslucentColumn_8 ;
colfunc = basecolfunc = R_DrawColumn_8 ;
shadecolfunc = R_DrawShadeColumn_8 ;
fuzzcolfunc = R_DrawTranslucentColumn_8 ;
walldrawerfunc = R_DrawWallColumn_8 ;
twosmultipatchfunc = R_Draw2sMultiPatchColumn_8 ;
2016-11-16 18:43:25 +00:00
twosmultipatchtransfunc = R_Draw2sMultiPatchTranslucentColumn_8 ;
2014-03-15 16:59:03 +00:00
# ifdef RUSEASM
if ( R_ASM )
{
if ( R_MMX )
{
colfunc = basecolfunc = R_DrawColumn_8_MMX ;
//shadecolfunc = R_DrawShadeColumn_8_ASM;
//fuzzcolfunc = R_DrawTranslucentColumn_8_ASM;
walldrawerfunc = R_DrawWallColumn_8_MMX ;
twosmultipatchfunc = R_Draw2sMultiPatchColumn_8_MMX ;
spanfunc = basespanfunc = R_DrawSpan_8_MMX ;
}
else
{
colfunc = basecolfunc = R_DrawColumn_8_ASM ;
//shadecolfunc = R_DrawShadeColumn_8_ASM;
//fuzzcolfunc = R_DrawTranslucentColumn_8_ASM;
walldrawerfunc = R_DrawWallColumn_8_ASM ;
twosmultipatchfunc = R_Draw2sMultiPatchColumn_8_ASM ;
}
}
# endif
}
/* else if (vid.bpp > 1)
{
I_OutputMsg ( " using highcolor mode \n " ) ;
spanfunc = basespanfunc = R_DrawSpan_16 ;
transcolfunc = R_DrawTranslatedColumn_16 ;
transtransfunc = R_DrawTranslucentColumn_16 ; // No 16bit operation for this function
colfunc = basecolfunc = R_DrawColumn_16 ;
shadecolfunc = NULL ; // detect error if used somewhere..
fuzzcolfunc = R_DrawTranslucentColumn_16 ;
walldrawerfunc = R_DrawWallColumn_16 ;
} */
else
I_Error ( " unknown bytes per pixel mode %d \n " , vid . bpp ) ;
/*#if !defined (DC) && !defined (WII)
if ( SCR_IsAspectCorrect ( vid . width , vid . height ) )
CONS_Alert ( CONS_WARNING , M_GetText ( " Resolution is not aspect-correct! \n Use a multiple of %dx%d \n " ) , BASEVIDWIDTH , BASEVIDHEIGHT ) ;
# endif* /
// set the apprpriate drawer for the sky (tall or INT16)
setmodeneeded = 0 ;
}
// do some initial settings for the game loading screen
//
void SCR_Startup ( void )
{
const CPUInfoFlags * RCpuInfo = I_CPUInfo ( ) ;
if ( ! M_CheckParm ( " -NOCPUID " ) & & RCpuInfo )
{
# if defined (__i386__) || defined (_M_IX86) || defined (__WATCOMC__)
R_486 = true ;
# endif
if ( RCpuInfo - > RDTSC )
R_586 = true ;
if ( RCpuInfo - > MMX )
R_MMX = true ;
if ( RCpuInfo - > AMD3DNow )
R_3DNow = true ;
if ( RCpuInfo - > MMXExt )
R_MMXExt = true ;
if ( RCpuInfo - > SSE )
R_SSE = true ;
if ( RCpuInfo - > SSE2 )
R_SSE2 = true ;
CONS_Printf ( " CPU Info: 486: %i, 586: %i, MMX: %i, 3DNow: %i, MMXExt: %i, SSE2: %i \n " , R_486 , R_586 , R_MMX , R_3DNow , R_MMXExt , R_SSE2 ) ;
}
if ( M_CheckParm ( " -noASM " ) )
R_ASM = false ;
if ( M_CheckParm ( " -486 " ) )
R_486 = true ;
if ( M_CheckParm ( " -586 " ) )
R_586 = true ;
if ( M_CheckParm ( " -MMX " ) )
R_MMX = true ;
if ( M_CheckParm ( " -3DNow " ) )
R_3DNow = true ;
if ( M_CheckParm ( " -MMXExt " ) )
R_MMXExt = true ;
if ( M_CheckParm ( " -SSE " ) )
R_SSE = true ;
if ( M_CheckParm ( " -noSSE " ) )
R_SSE = false ;
if ( M_CheckParm ( " -SSE2 " ) )
R_SSE2 = true ;
M_SetupMemcpy ( ) ;
if ( dedicated )
{
V_Init ( ) ;
V_SetPalette ( 0 ) ;
return ;
}
vid . modenum = 0 ;
vid . dupx = vid . width / BASEVIDWIDTH ;
vid . dupy = vid . height / BASEVIDHEIGHT ;
vid . dupx = vid . dupy = ( vid . dupx < vid . dupy ? vid . dupx : vid . dupy ) ;
vid . fdupx = FixedDiv ( vid . width * FRACUNIT , BASEVIDWIDTH * FRACUNIT ) ;
vid . fdupy = FixedDiv ( vid . height * FRACUNIT , BASEVIDHEIGHT * FRACUNIT ) ;
2014-03-20 10:29:53 +00:00
# ifdef HWRENDER
2014-03-24 20:06:13 +00:00
if ( rendermode ! = render_opengl & & rendermode ! = render_none ) // This was just placing it incorrectly at non aspect correct resolutions in opengl
2014-03-20 10:29:53 +00:00
# endif
vid . fdupx = vid . fdupy = ( vid . fdupx < vid . fdupy ? vid . fdupx : vid . fdupy ) ;
2014-03-15 16:59:03 +00:00
vid . meddupx = ( UINT8 ) ( vid . dupx > > 1 ) + 1 ;
vid . meddupy = ( UINT8 ) ( vid . dupy > > 1 ) + 1 ;
# ifdef HWRENDER
vid . fmeddupx = vid . meddupx * FRACUNIT ;
vid . fmeddupy = vid . meddupy * FRACUNIT ;
# endif
vid . smalldupx = ( UINT8 ) ( vid . dupx / 3 ) + 1 ;
vid . smalldupy = ( UINT8 ) ( vid . dupy / 3 ) + 1 ;
# ifdef HWRENDER
vid . fsmalldupx = vid . smalldupx * FRACUNIT ;
vid . fsmalldupy = vid . smalldupy * FRACUNIT ;
# endif
vid . baseratio = FRACUNIT ;
V_Init ( ) ;
CV_RegisterVar ( & cv_ticrate ) ;
CV_RegisterVar ( & cv_constextsize ) ;
V_SetPalette ( 0 ) ;
}
// Called at new frame, if the video mode has changed
//
void SCR_Recalc ( void )
{
if ( dedicated )
return ;
// bytes per pixel quick access
scr_bpp = vid . bpp ;
// scale 1,2,3 times in x and y the patches for the menus and overlays...
// calculated once and for all, used by routines in v_video.c
vid . dupx = vid . width / BASEVIDWIDTH ;
vid . dupy = vid . height / BASEVIDHEIGHT ;
vid . dupx = vid . dupy = ( vid . dupx < vid . dupy ? vid . dupx : vid . dupy ) ;
vid . fdupx = FixedDiv ( vid . width * FRACUNIT , BASEVIDWIDTH * FRACUNIT ) ;
vid . fdupy = FixedDiv ( vid . height * FRACUNIT , BASEVIDHEIGHT * FRACUNIT ) ;
2014-03-20 10:29:53 +00:00
# ifdef HWRENDER
2018-11-13 18:14:59 +00:00
//if (rendermode != render_opengl && rendermode != render_none) // This was just placing it incorrectly at non aspect correct resolutions in opengl
// 13/11/18:
// The above is no longer necessary, since we want OpenGL to be just like software now
// -- Monster Iestyn
2014-03-20 10:29:53 +00:00
# endif
vid . fdupx = vid . fdupy = ( vid . fdupx < vid . fdupy ? vid . fdupx : vid . fdupy ) ;
2014-03-15 16:59:03 +00:00
//vid.baseratio = FixedDiv(vid.height << FRACBITS, BASEVIDHEIGHT << FRACBITS);
vid . baseratio = FRACUNIT ;
vid . meddupx = ( UINT8 ) ( vid . dupx > > 1 ) + 1 ;
vid . meddupy = ( UINT8 ) ( vid . dupy > > 1 ) + 1 ;
# ifdef HWRENDER
vid . fmeddupx = vid . meddupx * FRACUNIT ;
vid . fmeddupy = vid . meddupy * FRACUNIT ;
# endif
vid . smalldupx = ( UINT8 ) ( vid . dupx / 3 ) + 1 ;
vid . smalldupy = ( UINT8 ) ( vid . dupy / 3 ) + 1 ;
# ifdef HWRENDER
vid . fsmalldupx = vid . smalldupx * FRACUNIT ;
vid . fsmalldupy = vid . smalldupy * FRACUNIT ;
# endif
// toggle off automap because some screensize-dependent values will
// be calculated next time the automap is activated.
if ( automapactive )
AM_Stop ( ) ;
// set the screen[x] ptrs on the new vidbuffers
V_Init ( ) ;
// scr_viewsize doesn't change, neither detailLevel, but the pixels
// per screenblock is different now, since we've changed resolution.
R_SetViewSize ( ) ; //just set setsizeneeded true now ..
// vid.recalc lasts only for the next refresh...
con_recalc = true ;
am_recalc = true ;
}
// Check for screen cmd-line parms: to force a resolution.
//
// Set the video mode to set at the 1st display loop (setmodeneeded)
//
void SCR_CheckDefaultMode ( void )
{
INT32 scr_forcex , scr_forcey ; // resolution asked from the cmd-line
if ( dedicated )
return ;
// 0 means not set at the cmd-line
scr_forcex = scr_forcey = 0 ;
if ( M_CheckParm ( " -width " ) & & M_IsNextParm ( ) )
scr_forcex = atoi ( M_GetNextParm ( ) ) ;
if ( M_CheckParm ( " -height " ) & & M_IsNextParm ( ) )
scr_forcey = atoi ( M_GetNextParm ( ) ) ;
if ( scr_forcex & & scr_forcey )
{
CONS_Printf ( M_GetText ( " Using resolution: %d x %d \n " ) , scr_forcex , scr_forcey ) ;
// returns -1 if not found, thus will be 0 (no mode change) if not found
setmodeneeded = VID_GetModeForSize ( scr_forcex , scr_forcey ) + 1 ;
}
else
{
CONS_Printf ( M_GetText ( " Default resolution: %d x %d (%d bits) \n " ) , cv_scr_width . value ,
cv_scr_height . value , cv_scr_depth . value ) ;
// see note above
setmodeneeded = VID_GetModeForSize ( cv_scr_width . value , cv_scr_height . value ) + 1 ;
}
}
// sets the modenum as the new default video mode to be saved in the config file
void SCR_SetDefaultMode ( void )
{
// remember the default screen size
CV_SetValue ( & cv_scr_width , vid . width ) ;
CV_SetValue ( & cv_scr_height , vid . height ) ;
CV_SetValue ( & cv_scr_depth , vid . bpp * 8 ) ;
}
// Change fullscreen on/off according to cv_fullscreen
void SCR_ChangeFullscreen ( void )
{
# ifdef DIRECTFULLSCREEN
// allow_fullscreen is set by VID_PrepareModeList
// it is used to prevent switching to fullscreen during startup
if ( ! allow_fullscreen )
return ;
if ( graphics_started )
{
VID_PrepareModeList ( ) ;
setmodeneeded = VID_GetModeForSize ( vid . width , vid . height ) + 1 ;
}
return ;
# endif
}
boolean SCR_IsAspectCorrect ( INT32 width , INT32 height )
{
return
( width % BASEVIDWIDTH = = 0
& & height % BASEVIDHEIGHT = = 0
& & width / BASEVIDWIDTH = = height / BASEVIDHEIGHT
) ;
}
// XMOD FPS display
// moved out of os-specific code for consistency
static boolean fpsgraph [ TICRATE ] ;
static tic_t lasttic ;
void SCR_DisplayTicRate ( void )
{
tic_t i ;
tic_t ontic = I_GetTime ( ) ;
tic_t totaltics = 0 ;
2019-02-16 03:08:08 +00:00
const UINT8 * ticcntcolor = NULL ;
2014-03-15 16:59:03 +00:00
for ( i = lasttic + 1 ; i < TICRATE + lasttic & & i < ontic ; + + i )
fpsgraph [ i % TICRATE ] = false ;
fpsgraph [ ontic % TICRATE ] = true ;
for ( i = 0 ; i < TICRATE ; + + i )
if ( fpsgraph [ i ] )
+ + totaltics ;
2019-02-16 03:08:08 +00:00
if ( totaltics < = TICRATE / 2 ) ticcntcolor = R_GetTranslationColormap ( TC_RAINBOW , SKINCOLOR_SALMON , GTC_CACHE ) ;
else if ( totaltics = = TICRATE ) ticcntcolor = R_GetTranslationColormap ( TC_RAINBOW , SKINCOLOR_MINT , GTC_CACHE ) ;
2014-03-15 16:59:03 +00:00
2019-02-16 03:08:08 +00:00
/*V_DrawString(vid.width-(24*vid.dupx), vid.height-(16*vid.dupy),
2014-03-15 16:59:03 +00:00
V_YELLOWMAP | V_NOSCALESTART , " FPS " ) ;
V_DrawString ( vid . width - ( 40 * vid . dupx ) , vid . height - ( 8 * vid . dupy ) ,
2019-02-16 03:08:08 +00:00
ticcntcolor | V_NOSCALESTART , va ( " %02d/%02u " , totaltics , TICRATE ) ) ; */
// draw "FPS"
V_DrawFixedPatch ( 306 < < FRACBITS , 183 < < FRACBITS , FRACUNIT , V_SNAPTOBOTTOM | V_SNAPTORIGHT , framecounter , R_GetTranslationColormap ( TC_RAINBOW , SKINCOLOR_YELLOW , GTC_CACHE ) ) ;
// draw total frame:
V_DrawPingNum ( 318 , 190 , V_SNAPTOBOTTOM | V_SNAPTORIGHT , TICRATE , ticcntcolor ) ;
// draw "/"
V_DrawFixedPatch ( 306 < < FRACBITS , 190 < < FRACBITS , FRACUNIT , V_SNAPTOBOTTOM | V_SNAPTORIGHT , frameslash , ticcntcolor ) ;
// draw our actual framerate
V_DrawPingNum ( 306 , 190 , V_SNAPTOBOTTOM | V_SNAPTORIGHT , totaltics , ticcntcolor ) ;
2014-03-15 16:59:03 +00:00
lasttic = ontic ;
}
2019-02-20 00:52:57 +00:00
// SCR_DisplayLocalPing
// Used to draw the user's local ping next to the framerate for a quick check without having to hold TAB for instance. By default, it only shows up if your ping is too high and risks getting you kicked.
void SCR_DisplayLocalPing ( void )
{
UINT32 ping = playerpingtable [ consoleplayer ] ; // consoleplayer's ping is everyone's ping in a splitnetgame :P
if ( cv_showping . value = = 1 | | ( cv_showping . value = = 2 & & ping > servermaxping ) ) // only show 2 (warning) if our ping is at a bad level
{
INT32 dispy = cv_ticrate . value ? 160 : 181 ;
HU_drawPing ( 307 , dispy , ping , V_SNAPTORIGHT | V_SNAPTOBOTTOM ) ;
}
}