2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
2016-05-18 00:42:11 +00:00
// Copyright (C) 1999-2016 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 d_main.c
/// \brief SRB2 main program
///
/// SRB2 main program (D_SRB2Main) and game loop (D_SRB2Loop),
/// plus functions to parse command line parameters, configure game
/// parameters, and call the startup functions.
# if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)
# include <sys/stat.h>
# include <sys/types.h>
# endif
# ifdef __GNUC__
# include <unistd.h> // for getcwd
# endif
# ifdef PC_DOS
# include <stdio.h> // for snprintf
int snprintf ( char * str , size_t n , const char * fmt , . . . ) ;
//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
# endif
2017-09-29 22:25:34 +00:00
# ifdef _WIN32
2014-03-15 16:59:03 +00:00
# include <direct.h>
# include <malloc.h>
# endif
# include <time.h>
# include "doomdef.h"
# include "am_map.h"
# include "console.h"
# include "d_net.h"
# include "f_finale.h"
# include "g_game.h"
# include "hu_stuff.h"
# include "i_sound.h"
# include "i_system.h"
# include "i_video.h"
# include "m_argv.h"
# include "m_menu.h"
# include "m_misc.h"
# include "p_setup.h"
# include "p_saveg.h"
# include "r_main.h"
# include "r_local.h"
# include "s_sound.h"
# include "st_stuff.h"
# include "v_video.h"
# include "w_wad.h"
# include "z_zone.h"
# include "d_main.h"
# include "d_netfil.h"
# include "m_cheat.h"
# include "y_inter.h"
# include "p_local.h" // chasecam
# include "mserv.h" // ms_RoomId
# include "m_misc.h" // screenshot functionality
# include "dehacked.h" // Dehacked list test
# include "m_cond.h" // condition initialization
# include "fastcmp.h"
2016-11-02 22:23:22 +00:00
# include "keys.h"
2017-04-29 15:40:07 +00:00
# include "filesrch.h" // refreshdirmenu, mainwadstally
2018-11-11 13:20:08 +00:00
# include "g_input.h" // tutorial mode control scheming
2014-03-15 16:59:03 +00:00
2015-01-29 00:03:41 +00:00
# ifdef CMAKECONFIG
# include "config.h"
# else
# include "config.h.in"
# endif
2014-03-15 16:59:03 +00:00
# ifdef HWRENDER
# include "hardware/hw_main.h" // 3D View Rendering
# endif
# ifdef _WINDOWS
# include "win32/win_main.h" // I_DoStartupMouse
# endif
# ifdef HW3SOUND
# include "hardware/hw3sound.h"
# endif
2015-06-10 17:42:45 +00:00
# ifdef HAVE_BLUA
# include "lua_script.h"
# endif
2015-01-01 19:50:31 +00:00
// platform independant focus loss
UINT8 window_notinfocus = false ;
2014-03-15 16:59:03 +00:00
//
// DEMO LOOP
//
static char * startupwadfiles [ MAX_WADFILES ] ;
boolean devparm = false ; // started game with -devparm
boolean singletics = false ; // timedemo
boolean lastdraw = false ;
postimg_t postimgtype = postimg_none ;
INT32 postimgparam ;
postimg_t postimgtype2 = postimg_none ;
INT32 postimgparam2 ;
// These variables are only true if
2018-09-14 14:58:41 +00:00
// whether the respective sound system is disabled
// or they're init'ed, but the player just toggled them
2018-08-23 16:42:15 +00:00
boolean midi_disabled = false ;
2014-03-15 16:59:03 +00:00
boolean sound_disabled = false ;
boolean digital_disabled = false ;
boolean advancedemo ;
# ifdef DEBUGFILE
INT32 debugload = 0 ;
# endif
char srb2home [ 256 ] = " . " ;
char srb2path [ 256 ] = " . " ;
boolean usehome = true ;
const char * pandf = " %s " PATHSEP " %s " ;
//
// EVENT HANDLING
//
// Events are asynchronous inputs generally generated by the game user.
// Events can be discarded if no responder claims them
// referenced from i_system.c for I_GetKey()
event_t events [ MAXEVENTS ] ;
INT32 eventhead , eventtail ;
boolean dedicated = false ;
//
// D_PostEvent
// Called by the I/O functions when input is detected
//
void D_PostEvent ( const event_t * ev )
{
events [ eventhead ] = * ev ;
eventhead = ( eventhead + 1 ) & ( MAXEVENTS - 1 ) ;
}
// just for lock this function
# ifndef DOXYGEN
void D_PostEvent_end ( void ) { } ;
# endif
2016-11-02 22:23:22 +00:00
// modifier keys
UINT8 shiftdown = 0 ; // 0x1 left, 0x2 right
UINT8 ctrldown = 0 ; // 0x1 left, 0x2 right
UINT8 altdown = 0 ; // 0x1 left, 0x2 right
//
// D_ModifierKeyResponder
// Sets global shift/ctrl/alt variables, never actually eats events
//
static inline void D_ModifierKeyResponder ( event_t * ev )
{
2017-02-04 23:26:37 +00:00
if ( ev - > type = = ev_keydown | | ev - > type = = ev_console ) switch ( ev - > data1 )
2016-11-02 22:23:22 +00:00
{
case KEY_LSHIFT : shiftdown | = 0x1 ; return ;
case KEY_RSHIFT : shiftdown | = 0x2 ; return ;
case KEY_LCTRL : ctrldown | = 0x1 ; return ;
case KEY_RCTRL : ctrldown | = 0x2 ; return ;
case KEY_LALT : altdown | = 0x1 ; return ;
case KEY_RALT : altdown | = 0x2 ; return ;
default : return ;
}
else if ( ev - > type = = ev_keyup ) switch ( ev - > data1 )
{
case KEY_LSHIFT : shiftdown & = ~ 0x1 ; return ;
case KEY_RSHIFT : shiftdown & = ~ 0x2 ; return ;
case KEY_LCTRL : ctrldown & = ~ 0x1 ; return ;
case KEY_RCTRL : ctrldown & = ~ 0x2 ; return ;
case KEY_LALT : altdown & = ~ 0x1 ; return ;
case KEY_RALT : altdown & = ~ 0x2 ; return ;
default : return ;
}
}
2014-03-15 16:59:03 +00:00
//
// D_ProcessEvents
// Send all the events of the given timestamp down the responder chain
//
void D_ProcessEvents ( void )
{
event_t * ev ;
for ( ; eventtail ! = eventhead ; eventtail = ( eventtail + 1 ) & ( MAXEVENTS - 1 ) )
{
ev = & events [ eventtail ] ;
2016-11-02 22:23:22 +00:00
// Set global shift/ctrl/alt down variables
D_ModifierKeyResponder ( ev ) ; // never eats events
2014-03-15 16:59:03 +00:00
// Screenshots over everything so that they can be taken anywhere.
if ( M_ScreenshotResponder ( ev ) )
continue ; // ate the event
if ( gameaction = = ga_nothing & & gamestate = = GS_TITLESCREEN )
{
if ( cht_Responder ( ev ) )
continue ;
}
// Menu input
if ( M_Responder ( ev ) )
continue ; // menu ate the event
// console input
if ( CON_Responder ( ev ) )
continue ; // ate the event
G_Responder ( ev ) ;
}
}
//
// D_Display
// draw current display, possibly wiping it from the previous
//
// wipegamestate can be set to -1 to force a wipe on the next draw
// added comment : there is a wipe eatch change of the gamestate
gamestate_t wipegamestate = GS_LEVEL ;
static void D_Display ( void )
{
2016-04-07 01:01:01 +00:00
boolean forcerefresh = false ;
2014-03-15 16:59:03 +00:00
static boolean wipe = false ;
INT32 wipedefindex = 0 ;
if ( dedicated )
return ;
if ( nodrawers )
return ; // for comparative timing/profiling
// check for change of screen size (video mode)
if ( setmodeneeded & & ! wipe )
SCR_SetMode ( ) ; // change video mode
if ( vid . recalc )
SCR_Recalc ( ) ; // NOTE! setsizeneeded is set by SCR_Recalc()
// change the view size if needed
if ( setsizeneeded )
{
R_ExecuteSetViewSize ( ) ;
2016-04-07 01:01:01 +00:00
forcerefresh = true ; // force background redraw
2014-03-15 16:59:03 +00:00
}
// draw buffered stuff to screen
// Used only by linux GGI version
I_UpdateNoBlit ( ) ;
2016-04-07 01:01:01 +00:00
// save the current screen if about to wipe
wipe = ( gamestate ! = wipegamestate ) ;
2014-03-15 16:59:03 +00:00
if ( wipe )
{
// set for all later
wipedefindex = gamestate ; // wipe_xxx_toblack
if ( gamestate = = GS_INTERMISSION )
{
if ( intertype = = int_spec ) // Special Stage
wipedefindex = wipe_specinter_toblack ;
else if ( intertype ! = int_coop ) // Multiplayer
wipedefindex = wipe_multinter_toblack ;
}
if ( rendermode ! = render_none )
{
// Fade to black first
2017-03-28 16:54:54 +00:00
if ( ! ( gamestate = = GS_LEVEL | | ( gamestate = = GS_TITLESCREEN & & titlemapinaction ) ) // fades to black on its own timing, always
2014-03-15 16:59:03 +00:00
& & wipedefs [ wipedefindex ] ! = UINT8_MAX )
{
2016-04-07 01:01:01 +00:00
F_WipeStartScreen ( ) ;
2014-03-15 16:59:03 +00:00
V_DrawFill ( 0 , 0 , BASEVIDWIDTH , BASEVIDHEIGHT , 31 ) ;
F_WipeEndScreen ( ) ;
F_RunWipe ( wipedefs [ wipedefindex ] , gamestate ! = GS_TIMEATTACK ) ;
}
F_WipeStartScreen ( ) ;
}
}
// do buffered drawing
switch ( gamestate )
{
2017-04-18 21:23:23 +00:00
case GS_TITLESCREEN :
2017-04-18 21:45:43 +00:00
if ( ! titlemapinaction ) {
2017-04-18 21:23:23 +00:00
F_TitleScreenDrawer ( ) ;
break ;
}
// Intentional fall-through
2014-03-15 16:59:03 +00:00
case GS_LEVEL :
if ( ! gametic )
break ;
HU_Erase ( ) ;
if ( automapactive )
AM_Drawer ( ) ;
break ;
case GS_INTERMISSION :
Y_IntermissionDrawer ( ) ;
HU_Erase ( ) ;
HU_Drawer ( ) ;
break ;
case GS_TIMEATTACK :
break ;
case GS_INTRO :
F_IntroDrawer ( ) ;
if ( wipegamestate = = ( gamestate_t ) - 1 )
wipe = true ;
break ;
case GS_CUTSCENE :
F_CutsceneDrawer ( ) ;
HU_Erase ( ) ;
HU_Drawer ( ) ;
break ;
case GS_GAMEEND :
F_GameEndDrawer ( ) ;
break ;
case GS_EVALUATION :
F_GameEvaluationDrawer ( ) ;
2017-09-15 19:34:46 +00:00
HU_Erase ( ) ;
2014-03-15 16:59:03 +00:00
HU_Drawer ( ) ;
break ;
case GS_CONTINUING :
F_ContinueDrawer ( ) ;
break ;
case GS_CREDITS :
F_CreditDrawer ( ) ;
HU_Erase ( ) ;
HU_Drawer ( ) ;
break ;
case GS_WAITINGPLAYERS :
// The clientconnect drawer is independent...
case GS_DEDICATEDSERVER :
case GS_NULL :
break ;
}
// clean up border stuff
// see if the border needs to be initially drawn
2017-04-18 21:45:43 +00:00
if ( gamestate = = GS_LEVEL | | ( gamestate = = GS_TITLESCREEN & & titlemapinaction ) )
2014-03-15 16:59:03 +00:00
{
// draw the view directly
2017-04-18 21:23:23 +00:00
2014-03-15 16:59:03 +00:00
if ( ! automapactive & & ! dedicated & & cv_renderview . value )
{
if ( players [ displayplayer ] . mo | | players [ displayplayer ] . playerstate = = PST_DEAD )
{
topleft = screens [ 0 ] + viewwindowy * vid . width + viewwindowx ;
objectsdrawn = 0 ;
# ifdef HWRENDER
if ( rendermode ! = render_soft )
HWR_RenderPlayerView ( 0 , & players [ displayplayer ] ) ;
else
# endif
if ( rendermode ! = render_none )
R_RenderPlayerView ( & players [ displayplayer ] ) ;
}
// render the second screen
if ( splitscreen & & players [ secondarydisplayplayer ] . mo )
{
# ifdef HWRENDER
if ( rendermode ! = render_soft )
HWR_RenderPlayerView ( 1 , & players [ secondarydisplayplayer ] ) ;
else
# endif
if ( rendermode ! = render_none )
{
viewwindowy = vid . height / 2 ;
M_Memcpy ( ylookup , ylookup2 , viewheight * sizeof ( ylookup [ 0 ] ) ) ;
topleft = screens [ 0 ] + viewwindowy * vid . width + viewwindowx ;
R_RenderPlayerView ( & players [ secondarydisplayplayer ] ) ;
viewwindowy = 0 ;
M_Memcpy ( ylookup , ylookup1 , viewheight * sizeof ( ylookup [ 0 ] ) ) ;
}
}
// Image postprocessing effect
2016-09-05 21:14:51 +00:00
if ( rendermode = = render_soft )
{
if ( postimgtype )
V_DoPostProcessor ( 0 , postimgtype , postimgparam ) ;
if ( postimgtype2 )
V_DoPostProcessor ( 1 , postimgtype2 , postimgparam2 ) ;
}
2014-03-15 16:59:03 +00:00
}
if ( lastdraw )
{
if ( rendermode = = render_soft )
2014-03-21 18:42:55 +00:00
{
2014-03-15 16:59:03 +00:00
VID_BlitLinearScreen ( screens [ 0 ] , screens [ 1 ] , vid . width * vid . bpp , vid . height , vid . width * vid . bpp , vid . rowbytes ) ;
2014-03-21 18:42:55 +00:00
usebuffer = true ;
}
2014-03-15 16:59:03 +00:00
lastdraw = false ;
}
2017-04-18 21:23:23 +00:00
if ( gamestate = = GS_LEVEL )
2017-04-18 21:45:43 +00:00
{
2017-04-18 21:23:23 +00:00
ST_Drawer ( ) ;
2017-04-18 21:45:43 +00:00
HU_Drawer ( ) ;
}
2017-04-18 21:23:23 +00:00
else
F_TitleScreenDrawer ( ) ;
2014-03-15 16:59:03 +00:00
}
// change gamma if needed
2016-04-07 01:01:01 +00:00
// (GS_LEVEL handles this already due to level-specific palettes)
if ( forcerefresh & & gamestate ! = GS_LEVEL )
2014-03-15 16:59:03 +00:00
V_SetPalette ( 0 ) ;
2016-04-07 01:01:01 +00:00
wipegamestate = gamestate ;
2014-03-15 16:59:03 +00:00
// draw pause pic
if ( paused & & cv_showhud . value & & ( ! menuactive | | netgame ) )
{
INT32 py ;
patch_t * patch ;
if ( automapactive )
py = 4 ;
else
py = viewwindowy + 4 ;
patch = W_CachePatchName ( " M_PAUSE " , PU_CACHE ) ;
V_DrawScaledPatch ( viewwindowx + ( BASEVIDWIDTH - SHORT ( patch - > width ) ) / 2 , py , 0 , patch ) ;
}
// vid size change is now finished if it was on...
vid . recalc = 0 ;
// FIXME: draw either console or menu, not the two
if ( gamestate ! = GS_TIMEATTACK )
CON_Drawer ( ) ;
M_Drawer ( ) ; // menu is drawn even on top of everything
2016-04-07 01:01:01 +00:00
// focus lost moved to M_Drawer
2015-01-01 19:50:31 +00:00
2016-04-07 01:01:01 +00:00
//
// wipe update
//
if ( wipe )
2015-01-01 19:50:31 +00:00
{
2016-04-07 01:01:01 +00:00
// note: moved up here because NetUpdate does input changes
// and input during wipe tends to mess things up
wipedefindex + = WIPEFINALSHIFT ;
if ( rendermode ! = render_none )
{
F_WipeEndScreen ( ) ;
F_RunWipe ( wipedefs [ wipedefindex ] , gamestate ! = GS_TIMEATTACK ) ;
}
2015-01-01 19:50:31 +00:00
}
2014-03-15 16:59:03 +00:00
NetUpdate ( ) ; // send out any new accumulation
// It's safe to end the game now.
if ( G_GetExitGameFlag ( ) )
{
Command_ExitGame_f ( ) ;
G_ClearExitGameFlag ( ) ;
}
//
// normal update
//
if ( ! wipe )
{
if ( cv_netstat . value )
{
char s [ 50 ] ;
Net_GetNetStat ( ) ;
s [ sizeof s - 1 ] = ' \0 ' ;
snprintf ( s , sizeof s - 1 , " get %d b/s " , getbps ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH , BASEVIDHEIGHT - ST_HEIGHT - 40 , V_YELLOWMAP , s ) ;
snprintf ( s , sizeof s - 1 , " send %d b/s " , sendbps ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH , BASEVIDHEIGHT - ST_HEIGHT - 30 , V_YELLOWMAP , s ) ;
snprintf ( s , sizeof s - 1 , " GameMiss %.2f%% " , gamelostpercent ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH , BASEVIDHEIGHT - ST_HEIGHT - 20 , V_YELLOWMAP , s ) ;
snprintf ( s , sizeof s - 1 , " SysMiss %.2f%% " , lostpercent ) ;
V_DrawRightAlignedString ( BASEVIDWIDTH , BASEVIDHEIGHT - ST_HEIGHT - 10 , V_YELLOWMAP , s ) ;
}
I_FinishUpdate ( ) ; // page flip or blit buffer
}
}
// =========================================================================
// D_SRB2Loop
// =========================================================================
tic_t rendergametic ;
void D_SRB2Loop ( void )
{
tic_t oldentertics = 0 , entertic = 0 , realtics = 0 , rendertimeout = INFTICS ;
if ( dedicated )
server = true ;
if ( M_CheckParm ( " -voodoo " ) ) // 256x256 Texture Limiter
COM_BufAddText ( " gr_voodoocompatibility on \n " ) ;
// Pushing of + parameters is now done back in D_SRB2Main, not here.
CONS_Printf ( " I_StartupKeyboard()... \n " ) ;
I_StartupKeyboard ( ) ;
# ifdef _WINDOWS
CONS_Printf ( " I_StartupMouse()... \n " ) ;
I_DoStartupMouse ( ) ;
# endif
oldentertics = I_GetTime ( ) ;
// end of loading screen: CONS_Printf() will no more call FinishUpdate()
con_startup = false ;
// make sure to do a d_display to init mode _before_ load a level
SCR_SetMode ( ) ; // change video mode
SCR_Recalc ( ) ;
// Check and print which version is executed.
// Use this as the border between setup and the main game loop being entered.
CONS_Printf (
" =========================================================================== \n "
" We hope you enjoy this game as \n "
" much as we did making it! \n "
" ...wait. =P \n "
" =========================================================================== \n " ) ;
// hack to start on a nice clear console screen.
COM_ImmedExecute ( " cls;version " ) ;
if ( rendermode = = render_soft )
V_DrawScaledPatch ( 0 , 0 , 0 , ( patch_t * ) W_CacheLumpNum ( W_GetNumForName ( " CONSBACK " ) , PU_CACHE ) ) ;
I_FinishUpdate ( ) ; // page flip or blit buffer
for ( ; ; )
{
if ( lastwipetic )
{
oldentertics = lastwipetic ;
lastwipetic = 0 ;
}
// get real tics
entertic = I_GetTime ( ) ;
realtics = entertic - oldentertics ;
oldentertics = entertic ;
2017-04-29 15:40:07 +00:00
refreshdirmenu = 0 ; // not sure where to put this, here as good as any?
2014-03-15 16:59:03 +00:00
# ifdef DEBUGFILE
if ( ! realtics )
if ( debugload )
debugload - - ;
# endif
if ( ! realtics & & ! singletics )
{
I_Sleep ( ) ;
continue ;
}
# ifdef HW3SOUND
HW3S_BeginFrameUpdate ( ) ;
# endif
// don't skip more than 10 frames at a time
// (fadein / fadeout cause massive frame skip!)
if ( realtics > 8 )
realtics = 1 ;
// process tics (but maybe not if realtic == 0)
TryRunTics ( realtics ) ;
if ( lastdraw | | singletics | | gametic > rendergametic )
{
rendergametic = gametic ;
rendertimeout = entertic + TICRATE / 17 ;
// Update display, next frame, with current state.
D_Display ( ) ;
if ( moviemode )
M_SaveFrame ( ) ;
if ( takescreenshot ) // Only take screenshots after drawing.
M_DoScreenShot ( ) ;
}
else if ( rendertimeout < entertic ) // in case the server hang or netsplit
{
// Lagless camera! Yay!
if ( gamestate = = GS_LEVEL & & netgame )
{
if ( splitscreen & & camera2 . chase )
P_MoveChaseCamera ( & players [ secondarydisplayplayer ] , & camera2 , false ) ;
if ( camera . chase )
P_MoveChaseCamera ( & players [ displayplayer ] , & camera , false ) ;
}
D_Display ( ) ;
if ( moviemode )
M_SaveFrame ( ) ;
if ( takescreenshot ) // Only take screenshots after drawing.
M_DoScreenShot ( ) ;
}
// consoleplayer -> displayplayer (hear sounds from viewpoint)
S_UpdateSounds ( ) ; // move positional sounds
// check for media change, loop music..
I_UpdateCD ( ) ;
# ifdef HW3SOUND
HW3S_EndFrameUpdate ( ) ;
# endif
2015-06-10 17:42:45 +00:00
# ifdef HAVE_BLUA
LUA_Step ( ) ;
# endif
2014-03-15 16:59:03 +00:00
}
}
//
// D_AdvanceDemo
// Called after each demo or intro demosequence finishes
//
void D_AdvanceDemo ( void )
{
advancedemo = true ;
}
// =========================================================================
// D_SRB2Main
// =========================================================================
//
// D_StartTitle
//
void D_StartTitle ( void )
{
2015-01-01 19:50:31 +00:00
INT32 i ;
2018-11-11 13:20:08 +00:00
boolean tutorialpostprompt = false ;
2017-05-14 15:45:08 +00:00
S_StopMusic ( ) ;
2014-03-15 16:59:03 +00:00
if ( netgame )
{
if ( gametype = = GT_COOP )
{
G_SetGamestate ( GS_WAITINGPLAYERS ) ; // hack to prevent a command repeat
if ( server )
{
char mapname [ 6 ] ;
strlcpy ( mapname , G_BuildMapName ( spstage_start ) , sizeof ( mapname ) ) ;
strlwr ( mapname ) ;
mapname [ 5 ] = ' \0 ' ;
COM_BufAddText ( va ( " map %s \n " , mapname ) ) ;
}
}
return ;
}
// okay, stop now
// (otherwise the game still thinks we're playing!)
SV_StopServer ( ) ;
2014-08-04 03:49:33 +00:00
SV_ResetServer ( ) ;
2014-03-15 16:59:03 +00:00
2015-01-01 19:50:31 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + )
CL_ClearPlayer ( i ) ;
splitscreen = false ;
SplitScreen_OnChange ( ) ;
botingame = false ;
botskin = 0 ;
cv_debug = 0 ;
emeralds = 0 ;
2017-08-04 00:27:31 +00:00
lastmaploaded = 0 ;
2015-01-01 19:50:31 +00:00
2014-03-15 16:59:03 +00:00
// In case someone exits out at the same time they start a time attack run,
// reset modeattacking
modeattacking = ATTACKING_NONE ;
2018-09-04 15:58:49 +00:00
// The title screen is obviously not a tutorial! (Unless I'm mistaken)
2018-11-11 13:20:08 +00:00
if ( tutorialmode )
{
// check if retained controls are custom
2018-11-11 13:46:06 +00:00
tutorialpostprompt = ( G_GetControlScheme ( gamecontroldefault [ gcs_custom ] , gclist_tutorial , num_gclist_tutorial ) = = gcs_custom
& & G_GetControlScheme ( gamecontrol , gclist_tutorial , num_gclist_tutorial ) ! = gcs_custom ) ;
G_CopyControls ( gamecontrol , gamecontroldefault [ gcs_custom ] , gclist_tutorial , num_gclist_tutorial ) ; // using gcs_custom as temp storage
2018-11-11 13:20:08 +00:00
}
2018-09-04 15:58:49 +00:00
tutorialmode = false ;
2014-03-15 16:59:03 +00:00
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't
maptol = 0 ;
2017-07-25 17:34:13 +00:00
// reset to default player stuff
COM_BufAddText ( va ( " %s \" %s \" \n " , cv_playername . name , cv_defaultplayername . string ) ) ;
COM_BufAddText ( va ( " %s \" %s \" \n " , cv_skin . name , cv_defaultskin . string ) ) ;
COM_BufAddText ( va ( " %s \" %s \" \n " , cv_playercolor . name , cv_defaultplayercolor . string ) ) ;
COM_BufAddText ( va ( " %s \" %s \" \n " , cv_playername2 . name , cv_defaultplayername2 . string ) ) ;
COM_BufAddText ( va ( " %s \" %s \" \n " , cv_skin2 . name , cv_defaultskin2 . string ) ) ;
COM_BufAddText ( va ( " %s \" %s \" \n " , cv_playercolor2 . name , cv_defaultplayercolor2 . string ) ) ;
2014-03-15 16:59:03 +00:00
gameaction = ga_nothing ;
displayplayer = consoleplayer = 0 ;
gametype = GT_COOP ;
paused = false ;
advancedemo = false ;
F_StartTitleScreen ( ) ;
CON_ToggleOff ( ) ;
// Reset the palette
if ( rendermode ! = render_none )
V_SetPaletteLump ( " PLAYPAL " ) ;
2018-11-11 13:20:08 +00:00
if ( tutorialpostprompt )
2018-11-11 14:15:43 +00:00
M_StartMessage ( " Do you want to \x82 save the recommended \x82 movement controls? \x80 \n \n Press 'Y' or 'Enter' to confirm, \n or any key to keep \n your current controls. " ,
2018-11-11 13:20:08 +00:00
M_TutorialSaveControlResponse , MM_YESNO ) ;
2014-03-15 16:59:03 +00:00
}
//
// D_AddFile
//
static void D_AddFile ( const char * file )
{
size_t pnumwadfiles ;
char * newfile ;
for ( pnumwadfiles = 0 ; startupwadfiles [ pnumwadfiles ] ; pnumwadfiles + + )
;
newfile = malloc ( strlen ( file ) + 1 ) ;
if ( ! newfile )
{
I_Error ( " No more free memory to AddFile %s " , file ) ;
}
strcpy ( newfile , file ) ;
startupwadfiles [ pnumwadfiles ] = newfile ;
}
static inline void D_CleanFile ( void )
{
size_t pnumwadfiles ;
for ( pnumwadfiles = 0 ; startupwadfiles [ pnumwadfiles ] ; pnumwadfiles + + )
{
free ( startupwadfiles [ pnumwadfiles ] ) ;
startupwadfiles [ pnumwadfiles ] = NULL ;
}
}
# ifndef _MAX_PATH
# define _MAX_PATH MAX_WADPATH
# endif
// ==========================================================================
// Identify the SRB2 version, and IWAD file to use.
// ==========================================================================
static void IdentifyVersion ( void )
{
2017-12-07 18:26:12 +00:00
char * srb2wad ;
2014-03-15 16:59:03 +00:00
const char * srb2waddir = NULL ;
2014-07-25 23:10:24 +00:00
# if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
2014-03-15 16:59:03 +00:00
// change to the directory where 'srb2.srb' is found
srb2waddir = I_LocateWad ( ) ;
# endif
// get the current directory (possible problem on NT with "." as current dir)
if ( srb2waddir )
{
strlcpy ( srb2path , srb2waddir , sizeof ( srb2path ) ) ;
}
else
{
if ( getcwd ( srb2path , 256 ) ! = NULL )
srb2waddir = srb2path ;
else
{
srb2waddir = " . " ;
}
}
2014-07-25 23:10:24 +00:00
# if defined (macintosh) && !defined (HAVE_SDL)
2014-03-15 16:59:03 +00:00
// cwd is always "/" when app is dbl-clicked
if ( ! stricmp ( srb2waddir , " / " ) )
srb2waddir = I_GetWadDir ( ) ;
# endif
// Commercial.
2017-12-07 18:26:12 +00:00
srb2wad = malloc ( strlen ( srb2waddir ) + 1 + 8 + 1 ) ;
if ( srb2wad = = NULL )
2014-03-15 16:59:03 +00:00
I_Error ( " No more free memory to look in %s " , srb2waddir ) ;
2017-12-07 18:26:12 +00:00
else
sprintf ( srb2wad , pandf , srb2waddir , " srb2.pk3 " ) ;
2014-03-15 16:59:03 +00:00
// will be overwritten in case of -cdrom or unix/win home
snprintf ( configfile , sizeof configfile , " %s " PATHSEP CONFIGFILENAME , srb2waddir ) ;
configfile [ sizeof configfile - 1 ] = ' \0 ' ;
// Load the IWAD
2017-12-07 18:26:12 +00:00
if ( srb2wad ! = NULL & & FIL_ReadFileOK ( srb2wad ) )
D_AddFile ( srb2wad ) ;
2014-03-15 16:59:03 +00:00
else
2017-12-07 18:26:12 +00:00
I_Error ( " srb2.pk3 not found! Expected in %s, ss file: %s \n " , srb2waddir , srb2wad ) ;
2014-03-15 16:59:03 +00:00
2017-12-07 18:26:12 +00:00
if ( srb2wad )
free ( srb2wad ) ;
2014-03-15 16:59:03 +00:00
// if you change the ordering of this or add/remove a file, be sure to update the md5
// checking in D_SRB2Main
// Add the maps
D_AddFile ( va ( pandf , srb2waddir , " zones.dta " ) ) ;
// Add the players
D_AddFile ( va ( pandf , srb2waddir , " player.dta " ) ) ;
2016-03-10 02:30:11 +00:00
# ifdef USE_PATCH_DTA
2014-03-15 22:55:07 +00:00
// Add our crappy patches to fix our bugs
2018-06-06 13:42:50 +00:00
D_AddFile ( va ( pandf , srb2waddir , " patch.pk3 " ) ) ;
2016-03-10 02:30:11 +00:00
# endif
2014-03-15 22:55:07 +00:00
2014-07-25 23:10:24 +00:00
# if !defined (HAVE_SDL) || defined (HAVE_MIXER)
2014-03-15 16:59:03 +00:00
{
const char * musicfile = " music.dta " ;
const char * musicpath = va ( pandf , srb2waddir , musicfile ) ;
int ms = W_VerifyNMUSlumps ( musicpath ) ; // Don't forget the music!
if ( ms = = 1 )
D_AddFile ( musicpath ) ;
else if ( ms = = 0 )
I_Error ( " File %s has been modified with non-music lumps " , musicfile ) ;
}
# endif
2016-10-23 10:44:51 +00:00
2017-04-29 15:40:07 +00:00
# ifdef DEVELOP // This section can be deleted when music_new is merged with music.dta
2016-10-23 10:44:51 +00:00
{
const char * musicfile = " music_new.dta " ;
const char * musicpath = va ( pandf , srb2waddir , musicfile ) ;
int ms = W_VerifyNMUSlumps ( musicpath ) ; // Don't forget the music!
if ( ms = = 1 )
D_AddFile ( musicpath ) ;
else if ( ms = = 0 )
I_Error ( " File %s has been modified with non-music lumps " , musicfile ) ;
2014-03-15 16:59:03 +00:00
}
# endif
}
2017-06-24 17:39:17 +00:00
# ifdef PC_DOS
2014-03-15 16:59:03 +00:00
/* ======================================================================== */
2017-06-24 17:39:17 +00:00
// Code for printing SRB2's title bar in DOS
2014-03-15 16:59:03 +00:00
/* ======================================================================== */
//
// Center the title string, then add the date and time of compilation.
//
static inline void D_MakeTitleString ( char * s )
{
char temp [ 82 ] ;
char * t ;
const char * u ;
INT32 i ;
for ( i = 0 , t = temp ; i < 82 ; i + + )
* t + + = ' ' ;
for ( t = temp + ( 80 - strlen ( s ) ) / 2 , u = s ; * u ! = ' \0 ' ; )
* t + + = * u + + ;
u = compdate ;
for ( t = temp + 1 , i = 11 ; i - - ; )
* t + + = * u + + ;
u = comptime ;
for ( t = temp + 71 , i = 8 ; i - - ; )
* t + + = * u + + ;
temp [ 80 ] = ' \0 ' ;
strcpy ( s , temp ) ;
}
2017-06-24 17:39:17 +00:00
static inline void D_Titlebar ( void )
{
2017-06-24 18:27:29 +00:00
char title1 [ 82 ] ; // srb2 title banner
char title2 [ 82 ] ;
2017-06-24 17:39:17 +00:00
strcpy ( title1 , " Sonic Robo Blast 2 " ) ;
strcpy ( title2 , " Sonic Robo Blast 2 " ) ;
D_MakeTitleString ( title1 ) ;
// SRB2 banner
clrscr ( ) ;
textattr ( ( BLUE < < 4 ) + WHITE ) ;
clreol ( ) ;
cputs ( title1 ) ;
// standard srb2 banner
textattr ( ( RED < < 4 ) + WHITE ) ;
clreol ( ) ;
gotoxy ( ( 80 - strlen ( title2 ) ) / 2 , 2 ) ;
cputs ( title2 ) ;
normvideo ( ) ;
gotoxy ( 1 , 3 ) ;
}
# endif
2014-03-15 16:59:03 +00:00
//
// D_SRB2Main
//
void D_SRB2Main ( void )
{
INT32 p ;
INT32 pstartmap = 1 ;
boolean autostart = false ;
// keep error messages until the final flush(stderr)
2017-09-29 22:25:34 +00:00
# if !defined (PC_DOS) && !defined(NOTERMIOS)
2014-03-15 16:59:03 +00:00
if ( setvbuf ( stderr , NULL , _IOFBF , 1000 ) )
I_OutputMsg ( " setvbuf didnt work \n " ) ;
# endif
# ifdef GETTEXT
// initialise locale code
M_StartupLocale ( ) ;
# endif
// get parameters from a response file (eg: srb2 @parms.txt)
M_FindResponseFile ( ) ;
// MAINCFG is now taken care of where "OBJCTCFG" is handled
G_LoadGameSettings ( ) ;
// Test Dehacked lists
DEH_Check ( ) ;
// identify the main IWAD file to use
IdentifyVersion ( ) ;
2017-09-29 22:25:34 +00:00
# if !defined(NOTERMIOS)
2014-03-15 16:59:03 +00:00
setbuf ( stdout , NULL ) ; // non-buffered output
# endif
2017-09-29 22:25:34 +00:00
#if 0 //defined (_DEBUG)
2015-01-22 19:02:38 +00:00
devparm = M_CheckParm ( " -nodebug " ) = = 0 ;
2014-03-15 16:59:03 +00:00
# else
2015-01-22 19:02:38 +00:00
devparm = M_CheckParm ( " -debug " ) ! = 0 ;
2014-03-15 16:59:03 +00:00
# endif
// for dedicated server
# if !defined (_WINDOWS) //already check in win_main.c
dedicated = M_CheckParm ( " -dedicated " ) ! = 0 ;
# endif
# ifdef PC_DOS
2017-06-24 17:39:17 +00:00
D_Titlebar ( ) ;
2014-03-15 16:59:03 +00:00
# endif
if ( devparm )
CONS_Printf ( M_GetText ( " Development mode ON. \n " ) ) ;
// default savegame
strcpy ( savegamename , SAVEGAMENAME " %u.ssg " ) ;
{
const char * userhome = D_Home ( ) ; //Alam: path to home
if ( ! userhome )
{
2017-09-29 21:27:08 +00:00
# if ((defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)) && !defined (__CYGWIN__)
2014-03-15 16:59:03 +00:00
I_Error ( " Please set $HOME to your home directory \n " ) ;
# else
if ( dedicated )
snprintf ( configfile , sizeof configfile , " d " CONFIGFILENAME ) ;
else
snprintf ( configfile , sizeof configfile , CONFIGFILENAME ) ;
# endif
}
else
{
// use user specific config file
# ifdef DEFAULTDIR
snprintf ( srb2home , sizeof srb2home , " %s " PATHSEP DEFAULTDIR , userhome ) ;
snprintf ( downloaddir , sizeof downloaddir , " %s " PATHSEP " DOWNLOAD " , srb2home ) ;
if ( dedicated )
snprintf ( configfile , sizeof configfile , " %s " PATHSEP " d " CONFIGFILENAME , srb2home ) ;
else
snprintf ( configfile , sizeof configfile , " %s " PATHSEP CONFIGFILENAME , srb2home ) ;
// can't use sprintf since there is %u in savegamename
strcatbf ( savegamename , srb2home , PATHSEP ) ;
I_mkdir ( srb2home , 0700 ) ;
# else
snprintf ( srb2home , sizeof srb2home , " %s " , userhome ) ;
snprintf ( downloaddir , sizeof downloaddir , " %s " , userhome ) ;
if ( dedicated )
snprintf ( configfile , sizeof configfile , " %s " PATHSEP " d " CONFIGFILENAME , userhome ) ;
else
snprintf ( configfile , sizeof configfile , " %s " PATHSEP CONFIGFILENAME , userhome ) ;
// can't use sprintf since there is %u in savegamename
strcatbf ( savegamename , userhome , PATHSEP ) ;
# endif
}
configfile [ sizeof configfile - 1 ] = ' \0 ' ;
}
// rand() needs seeded regardless of password
srand ( ( unsigned int ) time ( NULL ) ) ;
if ( M_CheckParm ( " -password " ) & & M_IsNextParm ( ) )
D_SetPassword ( M_GetNextParm ( ) ) ;
// add any files specified on the command line with -file wadfile
// to the wad list
2018-03-24 01:06:32 +00:00
if ( ! ( M_CheckParm ( " -connect " ) & & ! M_CheckParm ( " -server " ) ) )
2014-03-15 16:59:03 +00:00
{
if ( M_CheckParm ( " -file " ) )
{
// the parms after p are wadfile/lump names,
// until end of parms or another - preceded parm
while ( M_IsNextParm ( ) )
{
const char * s = M_GetNextParm ( ) ;
if ( s ) // Check for NULL?
{
if ( ! W_VerifyNMUSlumps ( s ) )
G_SetGameModified ( true ) ;
D_AddFile ( s ) ;
}
}
}
}
// get map from parms
if ( M_CheckParm ( " -server " ) | | dedicated )
netgame = server = true ;
if ( M_CheckParm ( " -warp " ) & & M_IsNextParm ( ) )
{
const char * word = M_GetNextParm ( ) ;
2016-07-28 15:07:26 +00:00
char ch ; // use this with sscanf to catch non-digits with
if ( fastncmp ( word , " MAP " , 3 ) ) // MAPxx name
2014-03-15 16:59:03 +00:00
pstartmap = M_MapNumber ( word [ 3 ] , word [ 4 ] ) ;
2016-07-28 15:07:26 +00:00
else if ( sscanf ( word , " %d%c " , & pstartmap , & ch ) ! = 1 ) // a plain number
I_Error ( " Cannot warp to map %s (invalid map name) \n " , word ) ;
2014-03-15 16:59:03 +00:00
// Don't check if lump exists just yet because the wads haven't been loaded!
// Just do a basic range check here.
if ( pstartmap < 1 | | pstartmap > NUMMAPS )
I_Error ( " Cannot warp to map %d (out of range) \n " , pstartmap ) ;
else
{
if ( ! M_CheckParm ( " -server " ) )
G_SetGameModified ( true ) ;
autostart = true ;
}
}
CONS_Printf ( " Z_Init(): Init zone memory allocation daemon. \n " ) ;
Z_Init ( ) ;
// adapt tables to SRB2's needs, including extra slots for dehacked file support
P_PatchInfoTables ( ) ;
//---------------------------------------------------- READY TIME
// we need to check for dedicated before initialization of some subsystems
CONS_Printf ( " I_StartupTimer()... \n " ) ;
I_StartupTimer ( ) ;
// Make backups of some SOCcable tables.
P_BackupTables ( ) ;
// Setup default unlockable conditions
M_SetupDefaultConditionSets ( ) ;
// load wad, including the main wad file
CONS_Printf ( " W_InitMultipleFiles(): Adding IWAD and main PWADs. \n " ) ;
if ( ! W_InitMultipleFiles ( startupwadfiles ) )
# ifdef _DEBUG
CONS_Error ( " A WAD file was not found or not valid. \n Check the log to see which ones. \n " ) ;
# else
I_Error ( " A WAD file was not found or not valid. \n Check the log to see which ones. \n " ) ;
# endif
D_CleanFile ( ) ;
2015-01-22 19:36:17 +00:00
# ifndef DEVELOP // md5s last updated 12/14/14
2014-03-15 16:59:03 +00:00
// Check MD5s of autoloaded files
2018-06-30 17:09:39 +00:00
//W_VerifyFileMD5(0, ASSET_HASH_SRB2_PK3); // srb2.pk3
//W_VerifyFileMD5(1, ASSET_HASH_ZONES_DTA); // zones.dta
//W_VerifyFileMD5(2, ASSET_HASH_PLAYER_DTA); // player.dta
2016-03-10 02:30:11 +00:00
# ifdef USE_PATCH_DTA
2018-06-30 17:09:39 +00:00
//W_VerifyFileMD5(3, ASSET_HASH_PATCH_PK3); // patch.pk3
2016-03-10 02:30:11 +00:00
# endif
2014-03-15 16:59:03 +00:00
// don't check music.dta because people like to modify it, and it doesn't matter if they do
// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
2016-03-10 02:30:11 +00:00
# endif //ifndef DEVELOP
2014-03-15 16:59:03 +00:00
2017-10-21 15:18:28 +00:00
mainwads = 3 ; // there are 3 wads not to unload
2016-03-10 02:30:11 +00:00
# ifdef USE_PATCH_DTA
2018-06-06 13:42:50 +00:00
+ + mainwads ; // patch.pk3 adds one more
2016-03-10 02:30:11 +00:00
# endif
2017-04-29 15:40:07 +00:00
# ifdef DEVELOP
+ + mainwads ; // music_new, too
# endif
mainwadstally = packetsizetally ;
2014-03-15 16:59:03 +00:00
cht_Init ( ) ;
//---------------------------------------------------- READY SCREEN
// we need to check for dedicated before initialization of some subsystems
CONS_Printf ( " I_StartupGraphics()... \n " ) ;
I_StartupGraphics ( ) ;
//--------------------------------------------------------- CONSOLE
// setup loading screen
SCR_Startup ( ) ;
// we need the font of the console
CONS_Printf ( " HU_Init(): Setting up heads up display. \n " ) ;
HU_Init ( ) ;
COM_Init ( ) ;
CON_Init ( ) ;
D_RegisterServerCommands ( ) ;
D_RegisterClientCommands ( ) ; // be sure that this is called before D_CheckNetGame
R_RegisterEngineStuff ( ) ;
S_RegisterSoundStuff ( ) ;
I_RegisterSysCommands ( ) ;
//--------------------------------------------------------- CONFIG.CFG
M_FirstLoadConfig ( ) ; // WARNING : this do a "COM_BufExecute()"
G_LoadGameData ( ) ;
2014-07-25 23:10:24 +00:00
# if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
2014-03-15 16:59:03 +00:00
VID_PrepareModeList ( ) ; // Regenerate Modelist according to cv_fullscreen
# endif
// set user default mode or mode set at cmdline
SCR_CheckDefaultMode ( ) ;
wipegamestate = gamestate ;
savedata . lives = 0 ; // flag this as not-used
//------------------------------------------------ COMMAND LINE PARAMS
// Initialize CD-Audio
if ( M_CheckParm ( " -usecd " ) & & ! dedicated )
I_InitCD ( ) ;
if ( M_CheckParm ( " -noupload " ) )
COM_BufAddText ( " downloading 0 \n " ) ;
CONS_Printf ( " M_Init(): Init miscellaneous info. \n " ) ;
M_Init ( ) ;
CONS_Printf ( " R_Init(): Init SRB2 refresh daemon. \n " ) ;
R_Init ( ) ;
// setting up sound
2018-02-17 05:01:42 +00:00
if ( dedicated )
{
2018-08-23 16:42:15 +00:00
sound_disabled = true ;
midi_disabled = digital_disabled = true ;
2018-02-17 05:01:42 +00:00
}
else
2018-04-03 20:11:07 +00:00
{
2018-08-23 16:30:47 +00:00
CONS_Printf ( " S_InitSfxChannels(): Setting up sound channels. \n " ) ;
2018-04-03 20:11:07 +00:00
}
2014-03-15 16:59:03 +00:00
if ( M_CheckParm ( " -nosound " ) )
2018-08-23 16:42:15 +00:00
sound_disabled = true ;
2014-03-15 16:59:03 +00:00
if ( M_CheckParm ( " -nomusic " ) ) // combines -nomidimusic and -nodigmusic
2018-08-23 16:42:15 +00:00
midi_disabled = digital_disabled = true ;
2014-03-15 16:59:03 +00:00
else
{
if ( M_CheckParm ( " -nomidimusic " ) )
2018-08-23 16:42:15 +00:00
midi_disabled = true ; ; // WARNING: DOS version initmusic in I_StartupSound
2014-03-15 16:59:03 +00:00
if ( M_CheckParm ( " -nodigmusic " ) )
2018-08-23 16:42:15 +00:00
digital_disabled = true ; // WARNING: DOS version initmusic in I_StartupSound
2014-03-15 16:59:03 +00:00
}
I_StartupSound ( ) ;
I_InitMusic ( ) ;
2018-08-23 16:30:47 +00:00
S_InitSfxChannels ( cv_soundvolume . value ) ;
2014-03-15 16:59:03 +00:00
CONS_Printf ( " ST_Init(): Init status bar. \n " ) ;
ST_Init ( ) ;
if ( M_CheckParm ( " -room " ) )
{
if ( ! M_IsNextParm ( ) )
I_Error ( " usage: -room <room_id> \n Check the Master Server's webpage for room ID numbers. \n " ) ;
2014-03-18 17:56:54 +00:00
ms_RoomId = atoi ( M_GetNextParm ( ) ) ;
2014-03-15 16:59:03 +00:00
# ifdef UPDATE_ALERT
GetMODVersion_Console ( ) ;
# endif
}
// init all NETWORK
CONS_Printf ( " D_CheckNetGame(): Checking network game status. \n " ) ;
if ( D_CheckNetGame ( ) )
autostart = true ;
// check for a driver that wants intermission stats
// start the apropriate game based on parms
if ( M_CheckParm ( " -metal " ) )
{
G_RecordMetal ( ) ;
autostart = true ;
}
else if ( M_CheckParm ( " -record " ) & & M_IsNextParm ( ) )
{
G_RecordDemo ( M_GetNextParm ( ) ) ;
autostart = true ;
}
// user settings come before "+" parameters.
if ( dedicated )
COM_ImmedExecute ( va ( " exec \" %s " PATHSEP " adedserv.cfg \" \n " , srb2home ) ) ;
else
COM_ImmedExecute ( va ( " exec \" %s " PATHSEP " autoexec.cfg \" -noerror \n " , srb2home ) ) ;
if ( ! autostart )
M_PushSpecialParameters ( ) ; // push all "+" parameters at the command buffer
// demo doesn't need anymore to be added with D_AddFile()
p = M_CheckParm ( " -playdemo " ) ;
if ( ! p )
p = M_CheckParm ( " -timedemo " ) ;
if ( p & & M_IsNextParm ( ) )
{
char tmp [ MAX_WADPATH ] ;
// add .lmp to identify the EXTERNAL demo file
// it is NOT possible to play an internal demo using -playdemo,
// rather push a playdemo command.. to do.
strcpy ( tmp , M_GetNextParm ( ) ) ;
// get spaced filename or directory
while ( M_IsNextParm ( ) )
{
strcat ( tmp , " " ) ;
strcat ( tmp , M_GetNextParm ( ) ) ;
}
FIL_DefaultExtension ( tmp , " .lmp " ) ;
CONS_Printf ( M_GetText ( " Playing demo %s. \n " ) , tmp ) ;
if ( M_CheckParm ( " -playdemo " ) )
{
singledemo = true ; // quit after one demo
G_DeferedPlayDemo ( tmp ) ;
}
else
G_TimeDemo ( tmp ) ;
G_SetGamestate ( GS_NULL ) ;
wipegamestate = GS_NULL ;
return ;
}
if ( M_CheckParm ( " -ultimatemode " ) )
{
autostart = true ;
ultimatemode = true ;
}
2017-05-13 00:47:42 +00:00
// rei/miru: bootmap (Idea: starts the game on a predefined map)
if ( bootmap & & ! ( M_CheckParm ( " -warp " ) & & M_IsNextParm ( ) ) )
{
pstartmap = bootmap ;
if ( pstartmap < 1 | | pstartmap > NUMMAPS )
I_Error ( " Cannot warp to map %d (out of range) \n " , pstartmap ) ;
else
{
autostart = true ;
}
}
2018-03-24 01:06:32 +00:00
if ( autostart | | netgame )
2014-03-15 16:59:03 +00:00
{
gameaction = ga_nothing ;
CV_ClearChangedFlags ( ) ;
// Do this here so if you run SRB2 with eg +timelimit 5, the time limit counts
// as having been modified for the first game.
M_PushSpecialParameters ( ) ; // push all "+" parameter at the command buffer
if ( M_CheckParm ( " -gametype " ) & & M_IsNextParm ( ) )
{
// from Command_Map_f
INT32 j ;
INT16 newgametype = - 1 ;
const char * sgametype = M_GetNextParm ( ) ;
2017-06-25 16:28:07 +00:00
newgametype = G_GetGametypeByName ( sgametype ) ;
if ( newgametype = = - 1 ) // reached end of the list with no match
2014-03-15 16:59:03 +00:00
{
j = atoi ( sgametype ) ; // assume they gave us a gametype number, which is okay too
if ( j > = 0 & & j < NUMGAMETYPES )
newgametype = ( INT16 ) j ;
}
if ( newgametype ! = - 1 )
{
j = gametype ;
gametype = newgametype ;
D_GameTypeChanged ( j ) ;
}
}
2018-03-24 01:06:32 +00:00
if ( server & & ! M_CheckParm ( " +map " ) )
2014-03-15 16:59:03 +00:00
{
// Prevent warping to nonexistent levels
if ( W_CheckNumForName ( G_BuildMapName ( pstartmap ) ) = = LUMPERROR )
I_Error ( " Could not warp to %s (map not found) \n " , G_BuildMapName ( pstartmap ) ) ;
// Prevent warping to locked levels
// ... unless you're in a dedicated server. Yes, technically this means you can view any level by
// running a dedicated server and joining it yourself, but that's better than making dedicated server's
// lives hell.
else if ( ! dedicated & & M_MapLocked ( pstartmap ) )
I_Error ( " You need to unlock this level before you can warp to it! \n " ) ;
else
2017-05-18 19:13:18 +00:00
{
2014-03-15 16:59:03 +00:00
D_MapChange ( pstartmap , gametype , ultimatemode , true , 0 , false , false ) ;
2017-05-18 19:13:18 +00:00
}
2014-03-15 16:59:03 +00:00
}
}
else if ( M_CheckParm ( " -skipintro " ) )
{
CON_ToggleOff ( ) ;
CON_ClearHUD ( ) ;
F_StartTitleScreen ( ) ;
}
else
F_StartIntro ( ) ; // Tails 03-03-2002
if ( dedicated & & server )
{
levelstarttic = gametic ;
G_SetGamestate ( GS_LEVEL ) ;
if ( ! P_SetupLevel ( false ) )
I_Quit ( ) ; // fail so reset game stuff
}
}
const char * D_Home ( void )
{
const char * userhome = NULL ;
# ifdef ANDROID
return " /data/data/org.srb2/ " ;
# endif
if ( M_CheckParm ( " -home " ) & & M_IsNextParm ( ) )
userhome = M_GetNextParm ( ) ;
else
{
2017-09-29 22:25:34 +00:00
# if !((defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)) && !defined (__APPLE__)
2014-03-15 16:59:03 +00:00
if ( FIL_FileOK ( CONFIGFILENAME ) )
usehome = false ; // Let's NOT use home
else
# endif
userhome = I_GetEnv ( " HOME " ) ; //Alam: my new HOME for srb2
}
2017-09-29 22:25:34 +00:00
# ifdef _WIN32 //Alam: only Win32 have APPDATA and USERPROFILE
2014-03-15 16:59:03 +00:00
if ( ! userhome & & usehome ) //Alam: Still not?
{
char * testhome = NULL ;
testhome = I_GetEnv ( " APPDATA " ) ;
if ( testhome ! = NULL
& & ( FIL_FileOK ( va ( " %s " PATHSEP " %s " PATHSEP CONFIGFILENAME , testhome , DEFAULTDIR ) ) ) )
{
userhome = testhome ;
}
}
# ifndef __CYGWIN__
if ( ! userhome & & usehome ) //Alam: All else fails?
{
char * testhome = NULL ;
testhome = I_GetEnv ( " USERPROFILE " ) ;
if ( testhome ! = NULL
& & ( FIL_FileOK ( va ( " %s " PATHSEP " %s " PATHSEP CONFIGFILENAME , testhome , DEFAULTDIR ) ) ) )
{
userhome = testhome ;
}
}
# endif // !__CYGWIN__
# endif // _WIN32
if ( usehome ) return userhome ;
else return NULL ;
}