mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Hardcoded music name switches Like I said earlier, it's better if all the hardcoded music switches in 2.2 start with an underscore so that it's harder to accidentally overwrite them. Should be accepted when music.dta is updated. See merge request !17
1427 lines
34 KiB
C
1427 lines
34 KiB
C
// SONIC ROBO BLAST 2
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
|
// Copyright (C) 1999-2016 by Sonic Team Junior.
|
|
//
|
|
// 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
|
|
|
|
#if (defined (_WIN32) && !defined (_WIN32_WCE)) && !defined (_XBOX)
|
|
#include <direct.h>
|
|
#include <malloc.h>
|
|
#endif
|
|
|
|
#if !defined (UNDER_CE)
|
|
#include <time.h>
|
|
#elif defined (_XBOX)
|
|
#define NO_TIME
|
|
#endif
|
|
|
|
#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"
|
|
|
|
#ifdef CMAKECONFIG
|
|
#include "config.h"
|
|
#else
|
|
#include "config.h.in"
|
|
#endif
|
|
|
|
#ifdef _XBOX
|
|
#include "sdl/SRB2XBOX/xboxhelp.h"
|
|
#endif
|
|
|
|
#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
|
|
|
|
#ifdef HAVE_BLUA
|
|
#include "lua_script.h"
|
|
#endif
|
|
|
|
// platform independant focus loss
|
|
UINT8 window_notinfocus = false;
|
|
|
|
//
|
|
// DEMO LOOP
|
|
//
|
|
//static INT32 demosequence;
|
|
static const char *pagename = "MAP1PIC";
|
|
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;
|
|
|
|
#ifdef _XBOX
|
|
boolean nomidimusic = true, nosound = true;
|
|
boolean nodigimusic = true;
|
|
#else
|
|
boolean nomidimusic = false, nosound = false;
|
|
boolean nodigimusic = false; // No fmod-based music
|
|
#endif
|
|
|
|
// These variables are only true if
|
|
// the respective sound system is initialized
|
|
// and active, but no sounds/music should play.
|
|
boolean music_disabled = false;
|
|
boolean sound_disabled = false;
|
|
boolean digital_disabled = false;
|
|
|
|
boolean advancedemo;
|
|
#ifdef DEBUGFILE
|
|
INT32 debugload = 0;
|
|
#endif
|
|
|
|
#ifdef _arch_dreamcast
|
|
char srb2home[256] = "/cd";
|
|
char srb2path[256] = "/cd";
|
|
#else
|
|
char srb2home[256] = ".";
|
|
char srb2path[256] = ".";
|
|
#endif
|
|
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
|
|
|
|
//
|
|
// 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];
|
|
|
|
// 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)
|
|
{
|
|
boolean forcerefresh = false;
|
|
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();
|
|
forcerefresh = true; // force background redraw
|
|
}
|
|
|
|
// draw buffered stuff to screen
|
|
// Used only by linux GGI version
|
|
I_UpdateNoBlit();
|
|
|
|
// save the current screen if about to wipe
|
|
wipe = (gamestate != wipegamestate);
|
|
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
|
|
if (gamestate != GS_LEVEL // fades to black on its own timing, always
|
|
&& wipedefs[wipedefindex] != UINT8_MAX)
|
|
{
|
|
F_WipeStartScreen();
|
|
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
|
|
F_WipeEndScreen();
|
|
F_RunWipe(wipedefs[wipedefindex], gamestate != GS_TIMEATTACK);
|
|
}
|
|
|
|
F_WipeStartScreen();
|
|
}
|
|
}
|
|
|
|
// do buffered drawing
|
|
switch (gamestate)
|
|
{
|
|
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();
|
|
HU_Drawer();
|
|
break;
|
|
|
|
case GS_CONTINUING:
|
|
F_ContinueDrawer();
|
|
break;
|
|
|
|
case GS_CREDITS:
|
|
F_CreditDrawer();
|
|
HU_Erase();
|
|
HU_Drawer();
|
|
break;
|
|
|
|
case GS_TITLESCREEN:
|
|
F_TitleScreenDrawer();
|
|
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
|
|
if (gamestate == GS_LEVEL)
|
|
{
|
|
// draw the view directly
|
|
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
|
|
if (postimgtype)
|
|
V_DoPostProcessor(0, postimgtype, postimgparam);
|
|
if (postimgtype2)
|
|
V_DoPostProcessor(1, postimgtype2, postimgparam2);
|
|
}
|
|
|
|
if (lastdraw)
|
|
{
|
|
if (rendermode == render_soft)
|
|
{
|
|
VID_BlitLinearScreen(screens[0], screens[1], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes);
|
|
usebuffer = true;
|
|
}
|
|
lastdraw = false;
|
|
}
|
|
|
|
ST_Drawer();
|
|
|
|
HU_Drawer();
|
|
}
|
|
|
|
// change gamma if needed
|
|
// (GS_LEVEL handles this already due to level-specific palettes)
|
|
if (forcerefresh && gamestate != GS_LEVEL)
|
|
V_SetPalette(0);
|
|
|
|
wipegamestate = gamestate;
|
|
|
|
// 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
|
|
// focus lost moved to M_Drawer
|
|
|
|
//
|
|
// wipe update
|
|
//
|
|
if (wipe)
|
|
{
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
#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
|
|
|
|
#ifdef HAVE_BLUA
|
|
LUA_Step();
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//
|
|
// D_AdvanceDemo
|
|
// Called after each demo or intro demosequence finishes
|
|
//
|
|
void D_AdvanceDemo(void)
|
|
{
|
|
advancedemo = true;
|
|
}
|
|
|
|
// =========================================================================
|
|
// D_SRB2Main
|
|
// =========================================================================
|
|
|
|
//
|
|
// D_StartTitle
|
|
//
|
|
void D_StartTitle(void)
|
|
{
|
|
INT32 i;
|
|
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();
|
|
SV_ResetServer();
|
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
|
CL_ClearPlayer(i);
|
|
|
|
splitscreen = false;
|
|
SplitScreen_OnChange();
|
|
botingame = false;
|
|
botskin = 0;
|
|
cv_debug = 0;
|
|
emeralds = 0;
|
|
|
|
// In case someone exits out at the same time they start a time attack run,
|
|
// reset modeattacking
|
|
modeattacking = ATTACKING_NONE;
|
|
|
|
// empty maptol so mario/etc sounds don't play in sound test when they shouldn't
|
|
maptol = 0;
|
|
|
|
gameaction = ga_nothing;
|
|
playerdeadview = false;
|
|
displayplayer = consoleplayer = 0;
|
|
//demosequence = -1;
|
|
gametype = GT_COOP;
|
|
paused = false;
|
|
advancedemo = false;
|
|
F_StartTitleScreen();
|
|
CON_ToggleOff();
|
|
|
|
// Reset the palette
|
|
#ifdef HWRENDER
|
|
if (rendermode == render_opengl)
|
|
HWR_SetPaletteColor(0);
|
|
else
|
|
#endif
|
|
if (rendermode != render_none)
|
|
V_SetPaletteLump("PLAYPAL");
|
|
}
|
|
|
|
//
|
|
// 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)
|
|
{
|
|
char *srb2wad1, *srb2wad2;
|
|
const char *srb2waddir = NULL;
|
|
|
|
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
|
|
// 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 !defined(_WIN32_WCE) && !defined(_PS3)
|
|
if (getcwd(srb2path, 256) != NULL)
|
|
srb2waddir = srb2path;
|
|
else
|
|
#endif
|
|
{
|
|
#ifdef _arch_dreamcast
|
|
srb2waddir = "/cd";
|
|
#else
|
|
srb2waddir = ".";
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if defined (macintosh) && !defined (HAVE_SDL)
|
|
// cwd is always "/" when app is dbl-clicked
|
|
if (!stricmp(srb2waddir, "/"))
|
|
srb2waddir = I_GetWadDir();
|
|
#endif
|
|
// Commercial.
|
|
srb2wad1 = malloc(strlen(srb2waddir)+1+8+1);
|
|
srb2wad2 = malloc(strlen(srb2waddir)+1+8+1);
|
|
if (srb2wad1 == NULL && srb2wad2 == NULL)
|
|
I_Error("No more free memory to look in %s", srb2waddir);
|
|
if (srb2wad1 != NULL)
|
|
sprintf(srb2wad1, pandf, srb2waddir, "srb2.srb");
|
|
if (srb2wad2 != NULL)
|
|
sprintf(srb2wad2, pandf, srb2waddir, "srb2.wad");
|
|
|
|
// 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
|
|
if (srb2wad2 != NULL && FIL_ReadFileOK(srb2wad2))
|
|
D_AddFile(srb2wad2);
|
|
else if (srb2wad1 != NULL && FIL_ReadFileOK(srb2wad1))
|
|
D_AddFile(srb2wad1);
|
|
else
|
|
I_Error("SRB2.SRB/SRB2.WAD not found! Expected in %s, ss files: %s and %s\n", srb2waddir, srb2wad1, srb2wad2);
|
|
|
|
if (srb2wad1)
|
|
free(srb2wad1);
|
|
if (srb2wad2)
|
|
free(srb2wad2);
|
|
|
|
// 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"));
|
|
|
|
// Add the weapons
|
|
D_AddFile(va(pandf,srb2waddir,"rings.dta"));
|
|
|
|
#ifdef USE_PATCH_DTA
|
|
// Add our crappy patches to fix our bugs
|
|
D_AddFile(va(pandf,srb2waddir,"patch.dta"));
|
|
#endif
|
|
|
|
#if !defined (HAVE_SDL) || defined (HAVE_MIXER)
|
|
{
|
|
#if defined (DC) && 0
|
|
const char *musicfile = "music_dc.dta";
|
|
#else
|
|
const char *musicfile = "music.dta";
|
|
#endif
|
|
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
|
|
|
|
#if 1 // This section can be deleted when music_new is merged with music.dta
|
|
{
|
|
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);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* ======================================================================== */
|
|
// Just print the nice red titlebar like the original SRB2 for DOS.
|
|
/* ======================================================================== */
|
|
#ifdef PC_DOS
|
|
static inline void D_Titlebar(char *title1, char *title2)
|
|
{
|
|
// 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
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
|
|
//
|
|
// D_SRB2Main
|
|
//
|
|
void D_SRB2Main(void)
|
|
{
|
|
INT32 p;
|
|
char srb2[82]; // srb2 title banner
|
|
char title[82];
|
|
|
|
INT32 pstartmap = 1;
|
|
boolean autostart = false;
|
|
|
|
// keep error messages until the final flush(stderr)
|
|
#if !defined (PC_DOS) && !defined (_WIN32_WCE) && !defined(NOTERMIOS)
|
|
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();
|
|
|
|
#if !defined (_WIN32_WCE) && !defined(NOTERMIOS)
|
|
setbuf(stdout, NULL); // non-buffered output
|
|
#endif
|
|
|
|
#if defined (_WIN32_WCE) //|| defined (_DEBUG) || defined (GP2X)
|
|
devparm = M_CheckParm("-nodebug") == 0;
|
|
#else
|
|
devparm = M_CheckParm("-debug") != 0;
|
|
#endif
|
|
|
|
// for dedicated server
|
|
#if !defined (_WINDOWS) //already check in win_main.c
|
|
dedicated = M_CheckParm("-dedicated") != 0;
|
|
#endif
|
|
|
|
strcpy(title, "Sonic Robo Blast 2");
|
|
strcpy(srb2, "Sonic Robo Blast 2");
|
|
D_MakeTitleString(srb2);
|
|
|
|
#ifdef PC_DOS
|
|
D_Titlebar(srb2, title);
|
|
#endif
|
|
|
|
#if defined (__OS2__) && !defined (HAVE_SDL)
|
|
// set PM window title
|
|
snprintf(pmData->title, sizeof (pmData->title),
|
|
"Sonic Robo Blast 2" VERSIONSTRING ": %s",
|
|
title);
|
|
pmData->title[sizeof (pmData->title) - 1] = '\0';
|
|
#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)
|
|
{
|
|
#if ((defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)) && !defined (__CYGWIN__) && !defined (DC) && !defined (PSP) && !defined(GP2X)
|
|
I_Error("Please set $HOME to your home directory\n");
|
|
#elif defined (_WIN32_WCE) && 0
|
|
if (dedicated)
|
|
snprintf(configfile, sizeof configfile, "/Storage Card/SRB2DEMO/d"CONFIGFILENAME);
|
|
else
|
|
snprintf(configfile, sizeof configfile, "/Storage Card/SRB2DEMO/"CONFIGFILENAME);
|
|
#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';
|
|
|
|
#ifdef _arch_dreamcast
|
|
strcpy(downloaddir, "/ram"); // the dreamcast's TMP
|
|
#endif
|
|
}
|
|
|
|
// rand() needs seeded regardless of password
|
|
srand((unsigned int)time(NULL));
|
|
|
|
if (M_CheckParm("-password") && M_IsNextParm())
|
|
D_SetPassword(M_GetNextParm());
|
|
else
|
|
{
|
|
size_t z;
|
|
char junkpw[25];
|
|
for (z = 0; z < 24; z++)
|
|
junkpw[z] = (char)(rand() & 64)+32;
|
|
junkpw[24] = '\0';
|
|
D_SetPassword(junkpw);
|
|
}
|
|
|
|
// add any files specified on the command line with -file wadfile
|
|
// to the wad list
|
|
if (!(M_CheckParm("-connect")))
|
|
{
|
|
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();
|
|
char ch; // use this with sscanf to catch non-digits with
|
|
if (fastncmp(word, "MAP", 3)) // MAPxx name
|
|
pstartmap = M_MapNumber(word[3], word[4]);
|
|
else if (sscanf(word, "%d%c", &pstartmap, &ch) != 1) // a plain number
|
|
I_Error("Cannot warp to map %s (invalid map name)\n", word);
|
|
// 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.\nCheck the log to see which ones.\n");
|
|
#else
|
|
I_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n");
|
|
#endif
|
|
D_CleanFile();
|
|
|
|
#ifndef DEVELOP // md5s last updated 12/14/14
|
|
|
|
// Check MD5s of autoloaded files
|
|
//W_VerifyFileMD5(0, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad
|
|
//W_VerifyFileMD5(1, ASSET_HASH_ZONES_DTA); // zones.dta
|
|
//W_VerifyFileMD5(2, ASSET_HASH_PLAYER_DTA); // player.dta
|
|
//W_VerifyFileMD5(3, ASSET_HASH_RINGS_DTA); // rings.dta
|
|
#ifdef USE_PATCH_DTA
|
|
W_VerifyFileMD5(4, ASSET_HASH_PATCH_DTA); // patch.dta
|
|
#endif
|
|
|
|
// 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.
|
|
#endif //ifndef DEVELOP
|
|
|
|
mainwads = 4; // there are 4 wads not to unload
|
|
#ifdef USE_PATCH_DTA
|
|
++mainwads; // patch.dta adds one more
|
|
#endif
|
|
|
|
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();
|
|
// libogc has a CON_Init function, we must rename SRB2's CON_Init in WII/libogc
|
|
#ifndef _WII
|
|
CON_Init();
|
|
#else
|
|
CON_InitWii();
|
|
#endif
|
|
|
|
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();
|
|
|
|
#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
|
|
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
|
|
CONS_Printf("S_Init(): Setting up sound.\n");
|
|
if (M_CheckParm("-nosound"))
|
|
nosound = true;
|
|
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
|
|
nomidimusic = nodigimusic = true;
|
|
else
|
|
{
|
|
if (M_CheckParm("-nomidimusic"))
|
|
nomidimusic = true; ; // WARNING: DOS version initmusic in I_StartupSound
|
|
if (M_CheckParm("-nodigmusic"))
|
|
nodigimusic = true; // WARNING: DOS version initmusic in I_StartupSound
|
|
}
|
|
I_StartupSound();
|
|
I_InitMusic();
|
|
S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value);
|
|
|
|
CONS_Printf("ST_Init(): Init status bar.\n");
|
|
ST_Init();
|
|
|
|
if (M_CheckParm("-room"))
|
|
{
|
|
if (!M_IsNextParm())
|
|
I_Error("usage: -room <room_id>\nCheck the Master Server's webpage for room ID numbers.\n");
|
|
ms_RoomId = atoi(M_GetNextParm());
|
|
|
|
#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;
|
|
}
|
|
|
|
if (autostart || netgame || M_CheckParm("+connect") || M_CheckParm("-connect"))
|
|
{
|
|
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();
|
|
|
|
for (j = 0; gametype_cons_t[j].strvalue; j++)
|
|
if (!strcasecmp(gametype_cons_t[j].strvalue, sgametype))
|
|
{
|
|
newgametype = (INT16)gametype_cons_t[j].value;
|
|
break;
|
|
}
|
|
if (!gametype_cons_t[j].strvalue) // reached end of the list with no match
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
if (server && !M_CheckParm("+map") && !M_CheckParm("+connect")
|
|
&& !M_CheckParm("-connect"))
|
|
{
|
|
// 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
|
|
D_MapChange(pstartmap, gametype, ultimatemode, true, 0, false, false);
|
|
}
|
|
}
|
|
else if (M_CheckParm("-skipintro"))
|
|
{
|
|
CON_ToggleOff();
|
|
CON_ClearHUD();
|
|
F_StartTitleScreen();
|
|
}
|
|
else
|
|
F_StartIntro(); // Tails 03-03-2002
|
|
|
|
if (dedicated && server)
|
|
{
|
|
pagename = "TITLESKY";
|
|
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
|
|
#ifdef _arch_dreamcast
|
|
char VMUHOME[] = "HOME=/vmu/a1";
|
|
putenv(VMUHOME); //don't use I_PutEnv
|
|
#endif
|
|
|
|
if (M_CheckParm("-home") && M_IsNextParm())
|
|
userhome = M_GetNextParm();
|
|
else
|
|
{
|
|
#if defined (GP2X)
|
|
usehome = false; //let use the CWD
|
|
return NULL;
|
|
#elif !((defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON)) && !defined (__APPLE__) && !defined(_WIN32_WCE)
|
|
if (FIL_FileOK(CONFIGFILENAME))
|
|
usehome = false; // Let's NOT use home
|
|
else
|
|
#endif
|
|
userhome = I_GetEnv("HOME"); //Alam: my new HOME for srb2
|
|
}
|
|
#if defined (_WIN32) && !defined(_WIN32_WCE) //Alam: only Win32 have APPDATA and USERPROFILE
|
|
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;
|
|
}
|