SeriousSam.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "StdH.h"
  13. #include <io.h>
  14. #include <fcntl.h>
  15. #include <sys/stat.h>
  16. #include <process.h>
  17. #include <Engine/CurrentVersion.h>
  18. #include <GameMP/Game.h>
  19. #define DECL_DLL
  20. #include <EntitiesMP/Global.h>
  21. #include "resource.h"
  22. #include "SplashScreen.h"
  23. #include "MainWindow.h"
  24. #include "GlSettings.h"
  25. #include "LevelInfo.h"
  26. #include "LCDDrawing.h"
  27. #include "CmdLine.h"
  28. #include "Credits.h"
  29. extern CGame *_pGame = NULL;
  30. // application state variables
  31. extern BOOL _bRunning = TRUE;
  32. extern BOOL _bQuitScreen = TRUE;
  33. extern BOOL bMenuActive = FALSE;
  34. extern BOOL bMenuRendering = FALSE;
  35. extern BOOL _bDefiningKey;
  36. static BOOL _bReconsiderInput = FALSE;
  37. extern PIX _pixDesktopWidth = 0; // desktop width when started (for some tests)
  38. static INDEX sam_iMaxFPSActive = 500;
  39. static INDEX sam_iMaxFPSInactive = 10;
  40. static INDEX sam_bPauseOnMinimize = TRUE; // auto-pause when window has been minimized
  41. extern INDEX sam_bWideScreen = FALSE;
  42. extern FLOAT sam_fPlayerOffset = 0.0f;
  43. // display mode settings
  44. extern INDEX sam_bFullScreenActive = FALSE;
  45. extern INDEX sam_iScreenSizeI = 1024; // current size of the window
  46. extern INDEX sam_iScreenSizeJ = 768; // current size of the window
  47. extern INDEX sam_iDisplayDepth = 0; // 0==default, 1==16bit, 2==32bit
  48. extern INDEX sam_iDisplayAdapter = 0;
  49. extern INDEX sam_iGfxAPI = 0; // 0==OpenGL
  50. extern INDEX sam_bFirstStarted = FALSE;
  51. extern FLOAT sam_tmDisplayModeReport = 5.0f;
  52. extern INDEX sam_bShowAllLevels = FALSE;
  53. extern INDEX sam_bMentalActivated = FALSE;
  54. // network settings
  55. extern CTString sam_strNetworkSettings = "";
  56. // command line
  57. extern CTString sam_strCommandLine = "";
  58. // 0...app started for the first time
  59. // 1...all ok
  60. // 2...automatic fallback
  61. static INDEX _iDisplayModeChangeFlag = 0;
  62. static TIME _tmDisplayModeChanged = 100.0f; // when display mode was last changed
  63. // rendering preferences for automatic settings
  64. extern INDEX sam_iVideoSetup = 1; // 0==speed, 1==normal, 2==quality, 3==custom
  65. // automatic adjustment of audio quality
  66. extern BOOL sam_bAutoAdjustAudio = TRUE;
  67. extern INDEX sam_bAutoPlayDemos = TRUE;
  68. static INDEX _bInAutoPlayLoop = TRUE;
  69. // menu calling
  70. extern INDEX sam_bMenuSave = FALSE;
  71. extern INDEX sam_bMenuLoad = FALSE;
  72. extern INDEX sam_bMenuControls = FALSE;
  73. extern INDEX sam_bMenuHiScore = FALSE;
  74. extern INDEX sam_bToggleConsole = FALSE;
  75. extern INDEX sam_iStartCredits = FALSE;
  76. // for mod re-loading
  77. extern CTFileName _fnmModToLoad = CTString("");
  78. extern CTString _strModServerJoin = CTString("");
  79. extern CTString _strURLToVisit = CTString("");
  80. // state variables fo addon execution
  81. // 0 - nothing
  82. // 1 - start (invoke console)
  83. // 2 - console invoked, waiting for one redraw
  84. extern INDEX _iAddonExecState = 0;
  85. extern CTFileName _fnmAddonToExec = CTString("");
  86. // logo textures
  87. static CTextureObject _toLogoCT;
  88. static CTextureObject _toLogoODI;
  89. static CTextureObject _toLogoEAX;
  90. extern CTextureObject *_ptoLogoCT = NULL;
  91. extern CTextureObject *_ptoLogoODI = NULL;
  92. extern CTextureObject *_ptoLogoEAX = NULL;
  93. extern CTString sam_strVersion = "1.10";
  94. extern CTString sam_strModName = TRANS("- O P E N S O U R C E -");
  95. extern CTString sam_strFirstLevel = "Levels\\LevelsMP\\1_0_InTheLastEpisode.wld";
  96. extern CTString sam_strIntroLevel = "Levels\\LevelsMP\\Intro.wld";
  97. extern CTString sam_strGameName = "serioussamse";
  98. extern CTString sam_strTechTestLevel = "Levels\\LevelsMP\\TechTest.wld";
  99. extern CTString sam_strTrainingLevel = "Levels\\KarnakDemo.wld";
  100. ENGINE_API extern INDEX snd_iFormat;
  101. // main window canvas
  102. CDrawPort *pdp;
  103. CDrawPort *pdpNormal;
  104. CDrawPort *pdpWideScreen;
  105. CViewPort *pvpViewPort;
  106. HINSTANCE _hInstance;
  107. static void PlayDemo(void* pArgs)
  108. {
  109. CTString strDemoFilename = *NEXTARGUMENT(CTString*);
  110. _gmMenuGameMode = GM_DEMO;
  111. CTFileName fnDemo = "demos\\" + strDemoFilename + ".dem";
  112. extern BOOL LSLoadDemo(const CTFileName &fnm);
  113. LSLoadDemo(fnDemo);
  114. }
  115. static void ApplyRenderingPreferences(void)
  116. {
  117. ApplyGLSettings(TRUE);
  118. }
  119. extern void ApplyVideoMode(void)
  120. {
  121. StartNewMode( (GfxAPIType)sam_iGfxAPI, sam_iDisplayAdapter, sam_iScreenSizeI, sam_iScreenSizeJ,
  122. (enum DisplayDepth)sam_iDisplayDepth, sam_bFullScreenActive);
  123. }
  124. static void BenchMark(void)
  125. {
  126. _pGfx->Benchmark(pvpViewPort, pdp);
  127. }
  128. static void QuitGame(void)
  129. {
  130. _bRunning = FALSE;
  131. _bQuitScreen = FALSE;
  132. }
  133. // check if another app is already running
  134. static HANDLE _hLock = NULL;
  135. static CTFileName _fnmLock;
  136. static void DirectoryLockOn(void)
  137. {
  138. // create lock filename
  139. _fnmLock = _fnmApplicationPath+"SeriousSam.loc";
  140. // try to open lock file
  141. _hLock = CreateFileA(
  142. _fnmLock,
  143. GENERIC_WRITE,
  144. 0/*no sharing*/,
  145. NULL, // pointer to security attributes
  146. CREATE_ALWAYS,
  147. FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, // file attributes
  148. NULL);
  149. // if failed
  150. if (_hLock==NULL || GetLastError()!=0) {
  151. // report warning
  152. CPrintF(TRANS("WARNING: SeriousSam didn't shut down properly last time!\n"));
  153. }
  154. }
  155. static void DirectoryLockOff(void)
  156. {
  157. // if lock is open
  158. if (_hLock!=NULL) {
  159. // close it
  160. CloseHandle(_hLock);
  161. }
  162. }
  163. void End(void);
  164. // automaticaly manage input enable/disable toggling
  165. static BOOL _bInputEnabled = FALSE;
  166. void UpdateInputEnabledState(void)
  167. {
  168. // do nothing if window is invalid
  169. if( _hwndMain==NULL) return;
  170. // input should be enabled if application is active
  171. // and no menu is active and no console is active
  172. BOOL bShouldBeEnabled = (!IsIconic(_hwndMain) && !bMenuActive && _pGame->gm_csConsoleState==CS_OFF
  173. && (_pGame->gm_csComputerState==CS_OFF || _pGame->gm_csComputerState==CS_ONINBACKGROUND))
  174. || _bDefiningKey;
  175. // if should be turned off
  176. if( (!bShouldBeEnabled && _bInputEnabled) || _bReconsiderInput) {
  177. // disable it and remember new state
  178. _pInput->DisableInput();
  179. _bInputEnabled = FALSE;
  180. }
  181. // if should be turned on
  182. if( bShouldBeEnabled && !_bInputEnabled) {
  183. // enable it and remember new state
  184. _pInput->EnableInput(_hwndMain);
  185. _bInputEnabled = TRUE;
  186. }
  187. _bReconsiderInput = FALSE;
  188. }
  189. // automaticaly manage pause toggling
  190. void UpdatePauseState(void)
  191. {
  192. BOOL bShouldPause = (_gmRunningGameMode==GM_SINGLE_PLAYER) && (bMenuActive ||
  193. _pGame->gm_csConsoleState ==CS_ON || _pGame->gm_csConsoleState ==CS_TURNINGON || _pGame->gm_csConsoleState ==CS_TURNINGOFF ||
  194. _pGame->gm_csComputerState==CS_ON || _pGame->gm_csComputerState==CS_TURNINGON || _pGame->gm_csComputerState==CS_TURNINGOFF);
  195. _pNetwork->SetLocalPause(bShouldPause);
  196. }
  197. // limit current frame rate if neeeded
  198. void LimitFrameRate(void)
  199. {
  200. // measure passed time for each loop
  201. static CTimerValue tvLast(-1.0f);
  202. CTimerValue tvNow = _pTimer->GetHighPrecisionTimer();
  203. TIME tmCurrentDelta = (tvNow-tvLast).GetSeconds();
  204. // limit maximum frame rate
  205. sam_iMaxFPSActive = ClampDn( (INDEX)sam_iMaxFPSActive, 1L);
  206. sam_iMaxFPSInactive = ClampDn( (INDEX)sam_iMaxFPSInactive, 1L);
  207. INDEX iMaxFPS = sam_iMaxFPSActive;
  208. if( IsIconic(_hwndMain)) iMaxFPS = sam_iMaxFPSInactive;
  209. if(_pGame->gm_CurrentSplitScreenCfg==CGame::SSC_DEDICATED) {
  210. iMaxFPS = ClampDn(iMaxFPS, 60L); // never go very slow if dedicated server
  211. }
  212. TIME tmWantedDelta = 1.0f / iMaxFPS;
  213. if( tmCurrentDelta<tmWantedDelta) Sleep( (tmWantedDelta-tmCurrentDelta)*1000.0f);
  214. // remember new time
  215. tvLast = _pTimer->GetHighPrecisionTimer();
  216. }
  217. // load first demo
  218. void StartNextDemo(void)
  219. {
  220. if (!sam_bAutoPlayDemos || !_bInAutoPlayLoop) {
  221. _bInAutoPlayLoop = FALSE;
  222. return;
  223. }
  224. // skip if no demos
  225. if(_lhAutoDemos.IsEmpty()) {
  226. _bInAutoPlayLoop = FALSE;
  227. return;
  228. }
  229. // get first demo level and cycle the list
  230. CLevelInfo *pli = LIST_HEAD(_lhAutoDemos, CLevelInfo, li_lnNode);
  231. pli->li_lnNode.Remove();
  232. _lhAutoDemos.AddTail(pli->li_lnNode);
  233. // if intro
  234. if (pli->li_fnLevel==sam_strIntroLevel) {
  235. // start intro
  236. _gmRunningGameMode = GM_NONE;
  237. _pGame->gm_aiStartLocalPlayers[0] = 0;
  238. _pGame->gm_aiStartLocalPlayers[1] = -1;
  239. _pGame->gm_aiStartLocalPlayers[2] = -1;
  240. _pGame->gm_aiStartLocalPlayers[3] = -1;
  241. _pGame->gm_strNetworkProvider = "Local";
  242. _pGame->gm_StartSplitScreenCfg = CGame::SSC_PLAY1;
  243. _pShell->SetINDEX("gam_iStartDifficulty", CSessionProperties::GD_NORMAL);
  244. _pShell->SetINDEX("gam_iStartMode", CSessionProperties::GM_FLYOVER);
  245. CUniversalSessionProperties sp;
  246. _pGame->SetSinglePlayerSession(sp);
  247. _pGame->gm_bFirstLoading = TRUE;
  248. if (_pGame->NewGame( sam_strIntroLevel, sam_strIntroLevel, sp)) {
  249. _gmRunningGameMode = GM_INTRO;
  250. }
  251. // if not intro
  252. } else {
  253. // start the demo
  254. _pGame->gm_StartSplitScreenCfg = CGame::SSC_OBSERVER;
  255. _pGame->gm_aiStartLocalPlayers[0] = -1;
  256. _pGame->gm_aiStartLocalPlayers[1] = -1;
  257. _pGame->gm_aiStartLocalPlayers[2] = -1;
  258. _pGame->gm_aiStartLocalPlayers[3] = -1;
  259. // play the demo
  260. _pGame->gm_strNetworkProvider = "Local";
  261. _gmRunningGameMode = GM_NONE;
  262. if( _pGame->StartDemoPlay( pli->li_fnLevel)) {
  263. _gmRunningGameMode = GM_DEMO;
  264. CON_DiscardLastLineTimes();
  265. }
  266. }
  267. if (_gmRunningGameMode==GM_NONE) {
  268. _bInAutoPlayLoop = FALSE;
  269. }
  270. }
  271. BOOL _bCDPathFound = FALSE;
  272. BOOL FileExistsOnHD(const CTString &strFile)
  273. {
  274. FILE *f = fopen(_fnmApplicationPath+strFile, "rb");
  275. if (f!=NULL) {
  276. fclose(f);
  277. return TRUE;
  278. } else {
  279. return FALSE;
  280. }
  281. }
  282. void TrimString(char *str)
  283. {
  284. int i = strlen(str);
  285. if (str[i-1]=='\n' || str[i-1]=='\r') {
  286. str[i-1]=0;
  287. }
  288. }
  289. // run web browser and view an url
  290. void RunBrowser(const char *strUrl)
  291. {
  292. int iResult = (int)ShellExecuteA( _hwndMain, "OPEN", strUrl, NULL, NULL, SW_SHOWMAXIMIZED);
  293. if (iResult<32) {
  294. // should report error?
  295. NOTHING;
  296. }
  297. }
  298. void LoadAndForceTexture(CTextureObject &to, CTextureObject *&pto, const CTFileName &fnm)
  299. {
  300. try {
  301. to.SetData_t(fnm);
  302. CTextureData *ptd = (CTextureData*)to.GetData();
  303. ptd->Force( TEX_CONSTANT);
  304. ptd = ptd->td_ptdBaseTexture;
  305. if( ptd!=NULL) ptd->Force( TEX_CONSTANT);
  306. pto = &to;
  307. } catch( char *pchrError) {
  308. (void*)pchrError;
  309. pto = NULL;
  310. }
  311. }
  312. void InitializeGame(void)
  313. {
  314. try {
  315. #ifndef NDEBUG
  316. #define GAMEDLL (_fnmApplicationExe.FileDir()+"Game"+_strModExt+"D.dll")
  317. #else
  318. #define GAMEDLL (_fnmApplicationExe.FileDir()+"Game"+_strModExt+".dll")
  319. #endif
  320. CTFileName fnmExpanded;
  321. ExpandFilePath(EFP_READ, CTString(GAMEDLL), fnmExpanded);
  322. CPrintF(TRANS("Loading game library '%s'...\n"), (const char *)fnmExpanded);
  323. HMODULE hGame = LoadLibraryA(fnmExpanded);
  324. if (hGame==NULL) {
  325. ThrowF_t("%s", GetWindowsError(GetLastError()));
  326. }
  327. CGame* (*GAME_Create)(void) = (CGame* (*)(void))GetProcAddress(hGame, "GAME_Create");
  328. if (GAME_Create==NULL) {
  329. ThrowF_t("%s", GetWindowsError(GetLastError()));
  330. }
  331. _pGame = GAME_Create();
  332. } catch (char *strError) {
  333. FatalError("%s", strError);
  334. }
  335. // init game - this will load persistent symbols
  336. _pGame->Initialize(CTString("Data\\SeriousSam.gms"));
  337. }
  338. BOOL Init( HINSTANCE hInstance, int nCmdShow, CTString strCmdLine)
  339. {
  340. _hInstance = hInstance;
  341. ShowSplashScreen(hInstance);
  342. // remember desktop width
  343. _pixDesktopWidth = ::GetSystemMetrics(SM_CXSCREEN);
  344. // prepare main window
  345. MainWindow_Init();
  346. OpenMainWindowInvisible();
  347. // parse command line before initializing engine
  348. ParseCommandLine(strCmdLine);
  349. // initialize engine
  350. SE_InitEngine(sam_strGameName);
  351. SE_LoadDefaultFonts();
  352. // now print the output of command line parsing
  353. CPrintF("%s", cmd_strOutput);
  354. // lock the directory
  355. DirectoryLockOn();
  356. // load all translation tables
  357. InitTranslation();
  358. try {
  359. AddTranslationTablesDir_t(CTString("Data\\Translations\\"), CTString("*.txt"));
  360. FinishTranslationTable();
  361. } catch (char *strError) {
  362. FatalError("%s", strError);
  363. }
  364. // always disable all warnings when in serious sam
  365. _pShell->Execute( "con_bNoWarnings=1;");
  366. // declare shell symbols
  367. _pShell->DeclareSymbol("user void PlayDemo(CTString);", &PlayDemo);
  368. _pShell->DeclareSymbol("persistent INDEX sam_bFullScreen;", &sam_bFullScreenActive);
  369. _pShell->DeclareSymbol("persistent INDEX sam_iScreenSizeI;", &sam_iScreenSizeI);
  370. _pShell->DeclareSymbol("persistent INDEX sam_iScreenSizeJ;", &sam_iScreenSizeJ);
  371. _pShell->DeclareSymbol("persistent INDEX sam_iDisplayDepth;", &sam_iDisplayDepth);
  372. _pShell->DeclareSymbol("persistent INDEX sam_iDisplayAdapter;", &sam_iDisplayAdapter);
  373. _pShell->DeclareSymbol("persistent INDEX sam_iGfxAPI;", &sam_iGfxAPI);
  374. _pShell->DeclareSymbol("persistent INDEX sam_bFirstStarted;", &sam_bFirstStarted);
  375. _pShell->DeclareSymbol("persistent INDEX sam_bAutoAdjustAudio;", &sam_bAutoAdjustAudio);
  376. _pShell->DeclareSymbol("persistent user INDEX sam_bWideScreen;", &sam_bWideScreen);
  377. _pShell->DeclareSymbol("persistent user FLOAT sam_fPlayerOffset;", &sam_fPlayerOffset);
  378. _pShell->DeclareSymbol("persistent user INDEX sam_bAutoPlayDemos;", &sam_bAutoPlayDemos);
  379. _pShell->DeclareSymbol("persistent user INDEX sam_iMaxFPSActive;", &sam_iMaxFPSActive);
  380. _pShell->DeclareSymbol("persistent user INDEX sam_iMaxFPSInactive;", &sam_iMaxFPSInactive);
  381. _pShell->DeclareSymbol("persistent user INDEX sam_bPauseOnMinimize;", &sam_bPauseOnMinimize);
  382. _pShell->DeclareSymbol("persistent user FLOAT sam_tmDisplayModeReport;", &sam_tmDisplayModeReport);
  383. _pShell->DeclareSymbol("persistent user CTString sam_strNetworkSettings;", &sam_strNetworkSettings);
  384. _pShell->DeclareSymbol("persistent user CTString sam_strIntroLevel;", &sam_strIntroLevel);
  385. _pShell->DeclareSymbol("persistent user CTString sam_strGameName;", &sam_strGameName);
  386. _pShell->DeclareSymbol("user CTString sam_strVersion;", &sam_strVersion);
  387. _pShell->DeclareSymbol("user CTString sam_strFirstLevel;", &sam_strFirstLevel);
  388. _pShell->DeclareSymbol("user CTString sam_strModName;", &sam_strModName);
  389. _pShell->DeclareSymbol("persistent INDEX sam_bShowAllLevels;", &sam_bShowAllLevels);
  390. _pShell->DeclareSymbol("persistent INDEX sam_bMentalActivated;", &sam_bMentalActivated);
  391. _pShell->DeclareSymbol("user CTString sam_strTechTestLevel;", &sam_strTechTestLevel);
  392. _pShell->DeclareSymbol("user CTString sam_strTrainingLevel;", &sam_strTrainingLevel);
  393. _pShell->DeclareSymbol("user void Quit(void);", &QuitGame);
  394. _pShell->DeclareSymbol("persistent user INDEX sam_iVideoSetup;", &sam_iVideoSetup);
  395. _pShell->DeclareSymbol("user void ApplyRenderingPreferences(void);", &ApplyRenderingPreferences);
  396. _pShell->DeclareSymbol("user void ApplyVideoMode(void);", &ApplyVideoMode);
  397. _pShell->DeclareSymbol("user void Benchmark(void);", &BenchMark);
  398. _pShell->DeclareSymbol("user INDEX sam_bMenuSave;", &sam_bMenuSave);
  399. _pShell->DeclareSymbol("user INDEX sam_bMenuLoad;", &sam_bMenuLoad);
  400. _pShell->DeclareSymbol("user INDEX sam_bMenuControls;", &sam_bMenuControls);
  401. _pShell->DeclareSymbol("user INDEX sam_bMenuHiScore;", &sam_bMenuHiScore);
  402. _pShell->DeclareSymbol("user INDEX sam_bToggleConsole;",&sam_bToggleConsole);
  403. _pShell->DeclareSymbol("INDEX sam_iStartCredits;", &sam_iStartCredits);
  404. InitializeGame();
  405. _pNetwork->md_strGameID = sam_strGameName;
  406. LCDInit();
  407. if( sam_bFirstStarted) {
  408. InfoMessage("%s", TRANS(
  409. "SeriousSam is starting for the first time.\n"
  410. "If you experience any problems, please consult\n"
  411. "ReadMe file for troubleshooting information."));
  412. }
  413. // initialize sound library
  414. snd_iFormat = Clamp( snd_iFormat, (INDEX)CSoundLibrary::SF_NONE, (INDEX)CSoundLibrary::SF_44100_16);
  415. _pSound->SetFormat( (enum CSoundLibrary::SoundFormat)snd_iFormat);
  416. if (sam_bAutoAdjustAudio) {
  417. _pShell->Execute("include \"Scripts\\Addons\\SFX-AutoAdjust.ini\"");
  418. }
  419. // execute script given on command line
  420. if (cmd_strScript!="") {
  421. CPrintF("Command line script: '%s'\n", cmd_strScript);
  422. CTString strCmd;
  423. strCmd.PrintF("include \"%s\"", cmd_strScript);
  424. _pShell->Execute(strCmd);
  425. }
  426. // load logo textures
  427. LoadAndForceTexture(_toLogoCT, _ptoLogoCT, CTFILENAME("Textures\\Logo\\LogoCT.tex"));
  428. LoadAndForceTexture(_toLogoODI, _ptoLogoODI, CTFILENAME("Textures\\Logo\\GodGamesLogo.tex"));
  429. LoadAndForceTexture(_toLogoEAX, _ptoLogoEAX, CTFILENAME("Textures\\Logo\\LogoEAX.tex"));
  430. // !! NOTE !! Re-enable these to allow mod support.
  431. LoadStringVar(CTString("Data\\Var\\Sam_Version.var"), sam_strVersion);
  432. LoadStringVar(CTString("Data\\Var\\ModName.var"), sam_strModName);
  433. CPrintF(TRANS("Serious Sam version: %s\n"), sam_strVersion);
  434. CPrintF(TRANS("Active mod: %s\n"), sam_strModName);
  435. InitializeMenus();
  436. // if there is a mod
  437. if (_fnmMod!="") {
  438. // execute the mod startup script
  439. _pShell->Execute(CTString("include \"Scripts\\Mod_startup.ini\";"));
  440. }
  441. // init gl settings module
  442. InitGLSettings();
  443. // init level-info subsystem
  444. LoadLevelsList();
  445. LoadDemosList();
  446. // apply application mode
  447. StartNewMode( (GfxAPIType)sam_iGfxAPI, sam_iDisplayAdapter, sam_iScreenSizeI, sam_iScreenSizeJ,
  448. (enum DisplayDepth)sam_iDisplayDepth, sam_bFullScreenActive);
  449. // set default mode reporting
  450. if( sam_bFirstStarted) {
  451. _iDisplayModeChangeFlag = 0;
  452. sam_bFirstStarted = FALSE;
  453. }
  454. HideSplashScreen();
  455. if (cmd_strPassword!="") {
  456. _pShell->SetString("net_strConnectPassword", cmd_strPassword);
  457. }
  458. // if connecting to server from command line
  459. if (cmd_strServer!="") {
  460. CTString strPort = "";
  461. if (cmd_iPort>0) {
  462. _pShell->SetINDEX("net_iPort", cmd_iPort);
  463. strPort.PrintF(":%d", cmd_iPort);
  464. }
  465. CPrintF(TRANS("Command line connection: '%s%s'\n"), cmd_strServer, strPort);
  466. // go to join menu
  467. _pGame->gam_strJoinAddress = cmd_strServer;
  468. if (cmd_bQuickJoin) {
  469. extern void JoinNetworkGame(void);
  470. JoinNetworkGame();
  471. } else {
  472. StartMenus("join");
  473. }
  474. // if starting world from command line
  475. } else if (cmd_strWorld!="") {
  476. CPrintF(TRANS("Command line world: '%s'\n"), cmd_strWorld);
  477. // try to start the game with that level
  478. try {
  479. if (cmd_iGoToMarker>=0) {
  480. CPrintF(TRANS("Command line marker: %d\n"), cmd_iGoToMarker);
  481. CTString strCommand;
  482. strCommand.PrintF("cht_iGoToMarker = %d;", cmd_iGoToMarker);
  483. _pShell->Execute(strCommand);
  484. }
  485. _pGame->gam_strCustomLevel = cmd_strWorld;
  486. if (cmd_bServer) {
  487. extern void StartNetworkGame(void);
  488. StartNetworkGame();
  489. } else {
  490. extern void StartSinglePlayerGame(void);
  491. StartSinglePlayerGame();
  492. }
  493. } catch (char *strError) {
  494. CPrintF(TRANS("Cannot start '%s': '%s'\n"), cmd_strWorld, strError);
  495. }
  496. // if no relevant starting at command line
  497. } else {
  498. StartNextDemo();
  499. }
  500. return TRUE;
  501. }
  502. void End(void)
  503. {
  504. _pGame->DisableLoadingHook();
  505. // cleanup level-info subsystem
  506. ClearLevelsList();
  507. ClearDemosList();
  508. // destroy the main window and its canvas
  509. if (pvpViewPort!=NULL) {
  510. _pGfx->DestroyWindowCanvas( pvpViewPort);
  511. pvpViewPort = NULL;
  512. pdpNormal = NULL;
  513. }
  514. CloseMainWindow();
  515. MainWindow_End();
  516. DestroyMenus();
  517. _pGame->End();
  518. LCDEnd();
  519. // unlock the directory
  520. DirectoryLockOff();
  521. SE_EndEngine();
  522. }
  523. // print display mode info if needed
  524. void PrintDisplayModeInfo(void)
  525. {
  526. // skip if timed out
  527. if( _pTimer->GetRealTimeTick() > (_tmDisplayModeChanged+sam_tmDisplayModeReport)) return;
  528. // cache some general vars
  529. SLONG slDPWidth = pdp->GetWidth();
  530. SLONG slDPHeight = pdp->GetHeight();
  531. if( pdp->IsDualHead()) slDPWidth/=2;
  532. CDisplayMode dm;
  533. dm.dm_pixSizeI = slDPWidth;
  534. dm.dm_pixSizeJ = slDPHeight;
  535. // determine proper text scale for statistics display
  536. FLOAT fTextScale = (FLOAT)slDPWidth/640.0f;
  537. // get resolution
  538. CTString strRes;
  539. extern CTString _strPreferencesDescription;
  540. strRes.PrintF( "%dx%dx%s", slDPWidth, slDPHeight, _pGfx->gl_dmCurrentDisplayMode.DepthString());
  541. if( dm.IsDualHead()) strRes += TRANS(" DualMonitor");
  542. if( dm.IsWideScreen()) strRes += TRANS(" WideScreen");
  543. if( _pGfx->gl_eCurrentAPI==GAT_OGL) strRes += " (OpenGL)";
  544. #ifdef SE1_D3D
  545. else if( _pGfx->gl_eCurrentAPI==GAT_D3D) strRes += " (Direct3D)";
  546. #endif // SE1_D3D
  547. CTString strDescr;
  548. strDescr.PrintF("\n%s (%s)\n", _strPreferencesDescription, RenderingPreferencesDescription(sam_iVideoSetup));
  549. strRes+=strDescr;
  550. // tell if application is started for the first time, or failed to set mode
  551. if( _iDisplayModeChangeFlag==0) {
  552. strRes += TRANS("Display mode set by default!");
  553. } else if( _iDisplayModeChangeFlag==2) {
  554. strRes += TRANS("Last mode set failed!");
  555. }
  556. // print it all
  557. pdp->SetFont( _pfdDisplayFont);
  558. pdp->SetTextScaling( fTextScale);
  559. pdp->SetTextAspect( 1.0f);
  560. pdp->PutText( strRes, slDPWidth*0.05f, slDPHeight*0.85f, LCDGetColor(C_GREEN|255, "display mode"));
  561. }
  562. // do the main game loop and render screen
  563. void DoGame(void)
  564. {
  565. // set flag if not in game
  566. if( !_pGame->gm_bGameOn) _gmRunningGameMode = GM_NONE;
  567. if( _gmRunningGameMode==GM_DEMO && _pNetwork->IsDemoPlayFinished()
  568. ||_gmRunningGameMode==GM_INTRO && _pNetwork->IsGameFinished()) {
  569. _pGame->StopGame();
  570. _gmRunningGameMode = GM_NONE;
  571. // load next demo
  572. StartNextDemo();
  573. if (!_bInAutoPlayLoop) {
  574. // start menu
  575. StartMenus();
  576. }
  577. }
  578. // do the main game loop
  579. if( _gmRunningGameMode != GM_NONE) {
  580. _pGame->GameMainLoop();
  581. // if game is not started
  582. } else {
  583. // just handle broadcast messages
  584. _pNetwork->GameInactive();
  585. }
  586. if (sam_iStartCredits>0) {
  587. Credits_On(sam_iStartCredits);
  588. sam_iStartCredits = 0;
  589. }
  590. if (sam_iStartCredits<0) {
  591. Credits_Off();
  592. sam_iStartCredits = 0;
  593. }
  594. if( _gmRunningGameMode==GM_NONE) {
  595. Credits_Off();
  596. sam_iStartCredits = 0;
  597. }
  598. // redraw the view
  599. if( !IsIconic(_hwndMain) && pdp!=NULL && pdp->Lock())
  600. {
  601. if( _gmRunningGameMode!=GM_NONE && !bMenuActive ) {
  602. // handle pretouching of textures and shadowmaps
  603. pdp->Unlock();
  604. _pGame->GameRedrawView( pdp, (_pGame->gm_csConsoleState!=CS_OFF || bMenuActive)?0:GRV_SHOWEXTRAS);
  605. pdp->Lock();
  606. _pGame->ComputerRender(pdp);
  607. pdp->Unlock();
  608. CDrawPort dpScroller(pdp, TRUE);
  609. dpScroller.Lock();
  610. if (Credits_Render(&dpScroller)==0) {
  611. Credits_Off();
  612. }
  613. dpScroller.Unlock();
  614. pdp->Lock();
  615. } else {
  616. pdp->Fill( LCDGetColor(C_dGREEN|CT_OPAQUE, "bcg fill"));
  617. }
  618. // do menu
  619. if( bMenuRendering) {
  620. // clear z-buffer
  621. pdp->FillZBuffer( ZBUF_BACK);
  622. // remember if we should render menus next tick
  623. bMenuRendering = DoMenu(pdp);
  624. }
  625. // print display mode info if needed
  626. PrintDisplayModeInfo();
  627. // render console
  628. _pGame->ConsoleRender(pdp);
  629. // done with all
  630. pdp->Unlock();
  631. // clear upper and lower parts of screen if in wide screen mode
  632. if( pdp==pdpWideScreen && pdpNormal->Lock()) {
  633. const PIX pixWidth = pdpWideScreen->GetWidth();
  634. const PIX pixHeight = (pdpNormal->GetHeight() - pdpWideScreen->GetHeight()) /2;
  635. const PIX pixJOfs = pixHeight + pdpWideScreen->GetHeight()-1;
  636. pdpNormal->Fill( 0, 0, pixWidth, pixHeight, C_BLACK|CT_OPAQUE);
  637. pdpNormal->Fill( 0, pixJOfs, pixWidth, pixHeight, C_BLACK|CT_OPAQUE);
  638. pdpNormal->Unlock();
  639. }
  640. // show
  641. pvpViewPort->SwapBuffers();
  642. }
  643. }
  644. void TeleportPlayer(int iPosition)
  645. {
  646. CTString strCommand;
  647. strCommand.PrintF( "cht_iGoToMarker = %d;", iPosition);
  648. _pShell->Execute(strCommand);
  649. }
  650. CTextureObject _toStarField;
  651. static FLOAT _fLastVolume = 1.0f;
  652. void RenderStarfield(CDrawPort *pdp, FLOAT fStrength)
  653. {
  654. CTextureData *ptd = (CTextureData *)_toStarField.GetData();
  655. // skip if no texture
  656. if(ptd==NULL) return;
  657. PIX pixSizeI = pdp->GetWidth();
  658. PIX pixSizeJ = pdp->GetHeight();
  659. FLOAT fStretch = pixSizeI/640.0f;
  660. fStretch*=FLOAT(ptd->GetPixWidth())/ptd->GetWidth();
  661. PIXaabbox2D boxScreen(PIX2D(0,0), PIX2D(pixSizeI, pixSizeJ));
  662. MEXaabbox2D boxTexture(MEX2D(0, 0), MEX2D(pixSizeI/fStretch, pixSizeJ/fStretch));
  663. pdp->PutTexture(&_toStarField, boxScreen, boxTexture, LerpColor(C_BLACK, C_WHITE, fStrength)|CT_OPAQUE);
  664. }
  665. FLOAT RenderQuitScreen(CDrawPort *pdp, CViewPort *pvp)
  666. {
  667. CDrawPort dpQuit(pdp, TRUE);
  668. CDrawPort dpWide;
  669. dpQuit.MakeWideScreen(&dpWide);
  670. // redraw the view
  671. if (!dpWide.Lock()) {
  672. return 0;
  673. }
  674. dpWide.Fill(C_BLACK|CT_OPAQUE);
  675. RenderStarfield(&dpWide, _fLastVolume);
  676. FLOAT fVolume = Credits_Render(&dpWide);
  677. _fLastVolume = fVolume;
  678. dpWide.Unlock();
  679. pvp->SwapBuffers();
  680. return fVolume;
  681. }
  682. void QuitScreenLoop(void)
  683. {
  684. Credits_On(3);
  685. CSoundObject soMusic;
  686. try {
  687. _toStarField.SetData_t(CTFILENAME("Textures\\Background\\Night01\\Stars01.tex"));
  688. soMusic.Play_t(CTFILENAME("Music\\Credits.mp3"), SOF_NONGAME|SOF_MUSIC|SOF_LOOP);
  689. } catch (char *strError) {
  690. CPrintF("%s\n", strError);
  691. }
  692. // while it is still running
  693. FOREVER {
  694. FLOAT fVolume = RenderQuitScreen(pdp, pvpViewPort);
  695. if (fVolume<=0) {
  696. return;
  697. }
  698. // assure we can listen to non-3d sounds
  699. soMusic.SetVolume(fVolume, fVolume);
  700. _pSound->UpdateSounds();
  701. // while there are any messages in the message queue
  702. MSG msg;
  703. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  704. // if it is not a keyboard or mouse message
  705. if(msg.message==WM_LBUTTONDOWN||
  706. msg.message==WM_RBUTTONDOWN||
  707. msg.message==WM_KEYDOWN) {
  708. return;
  709. }
  710. }
  711. //Sleep(5);
  712. }
  713. }
  714. int SubMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  715. {
  716. (void)hPrevInstance;
  717. if( !Init( hInstance, nCmdShow, lpCmdLine )) return FALSE;
  718. // initialy, application is running and active, console and menu are off
  719. _bRunning = TRUE;
  720. _bQuitScreen = TRUE;
  721. _pGame->gm_csConsoleState = CS_OFF;
  722. _pGame->gm_csComputerState = CS_OFF;
  723. // bMenuActive = FALSE;
  724. // bMenuRendering = FALSE;
  725. // while it is still running
  726. while( _bRunning && _fnmModToLoad=="")
  727. {
  728. // while there are any messages in the message queue
  729. MSG msg;
  730. while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE)) {
  731. // if it is not a mouse message
  732. if( !(msg.message>=WM_MOUSEFIRST && msg.message<=WM_MOUSELAST) ) {
  733. // if not system key messages
  734. if( !(msg.message==WM_KEYDOWN && msg.wParam==VK_F10
  735. ||msg.message==WM_SYSKEYDOWN)) {
  736. // dispatch it
  737. TranslateMessage(&msg);
  738. DispatchMessage(&msg);
  739. }
  740. }
  741. // system commands (also send by the application itself)
  742. if( msg.message==WM_SYSCOMMAND)
  743. {
  744. switch( msg.wParam & ~0x0F) {
  745. // if should minimize
  746. case SC_MINIMIZE:
  747. if( _bWindowChanging) break;
  748. _bWindowChanging = TRUE;
  749. _bReconsiderInput = TRUE;
  750. // if allowed, not already paused and only in single player game mode
  751. if( sam_bPauseOnMinimize && !_pNetwork->IsPaused() && _gmRunningGameMode==GM_SINGLE_PLAYER) {
  752. // pause game
  753. _pNetwork->TogglePause();
  754. }
  755. // if in full screen
  756. if( sam_bFullScreenActive) {
  757. // reset display mode and minimize window
  758. _pGfx->ResetDisplayMode();
  759. ShowWindow(_hwndMain, SW_MINIMIZE);
  760. // if not in full screen
  761. } else {
  762. // just minimize the window
  763. ShowWindow(_hwndMain, SW_MINIMIZE);
  764. }
  765. break;
  766. // if should restore
  767. case SC_RESTORE:
  768. if( _bWindowChanging) break;
  769. _bWindowChanging = TRUE;
  770. _bReconsiderInput = TRUE;
  771. // if in full screen
  772. if( sam_bFullScreenActive) {
  773. ShowWindow(_hwndMain, SW_SHOWNORMAL);
  774. // set the display mode once again
  775. StartNewMode( (GfxAPIType)sam_iGfxAPI, sam_iDisplayAdapter, sam_iScreenSizeI, sam_iScreenSizeJ,
  776. (enum DisplayDepth)sam_iDisplayDepth, sam_bFullScreenActive);
  777. // if not in full screen
  778. } else {
  779. // restore window
  780. ShowWindow(_hwndMain, SW_SHOWNORMAL);
  781. }
  782. break;
  783. // if should maximize
  784. case SC_MAXIMIZE:
  785. if( _bWindowChanging) break;
  786. _bWindowChanging = TRUE;
  787. _bReconsiderInput = TRUE;
  788. // go to full screen
  789. StartNewMode( (GfxAPIType)sam_iGfxAPI, sam_iDisplayAdapter, sam_iScreenSizeI, sam_iScreenSizeJ,
  790. (enum DisplayDepth)sam_iDisplayDepth, TRUE);
  791. ShowWindow( _hwndMain, SW_SHOWNORMAL);
  792. break;
  793. }
  794. }
  795. // toggle full-screen on alt-enter
  796. if( msg.message==WM_SYSKEYDOWN && msg.wParam==VK_RETURN && !IsIconic(_hwndMain)) {
  797. StartNewMode( (GfxAPIType)sam_iGfxAPI, sam_iDisplayAdapter, sam_iScreenSizeI, sam_iScreenSizeJ,
  798. (enum DisplayDepth)sam_iDisplayDepth, !sam_bFullScreenActive);
  799. }
  800. // if application should stop
  801. if( msg.message==WM_QUIT || msg.message==WM_CLOSE) {
  802. // stop running
  803. _bRunning = FALSE;
  804. _bQuitScreen = FALSE;
  805. }
  806. // if application is deactivated or minimized
  807. if( (msg.message==WM_ACTIVATE && (LOWORD(msg.wParam)==WA_INACTIVE || HIWORD(msg.wParam)))
  808. || msg.message==WM_CANCELMODE
  809. || msg.message==WM_KILLFOCUS
  810. || (msg.message==WM_ACTIVATEAPP && !msg.wParam)) {
  811. // if application is running and in full screen mode
  812. if( !_bWindowChanging && _bRunning) {
  813. // minimize if in full screen
  814. if( sam_bFullScreenActive) PostMessage(NULL, WM_SYSCOMMAND, SC_MINIMIZE, 0);
  815. // just disable input if not in full screen
  816. else _pInput->DisableInput();
  817. }
  818. }
  819. // if application is activated or minimized
  820. else if( (msg.message==WM_ACTIVATE && (LOWORD(msg.wParam)==WA_ACTIVE || LOWORD(msg.wParam)==WA_CLICKACTIVE))
  821. || msg.message==WM_SETFOCUS
  822. || (msg.message==WM_ACTIVATEAPP && msg.wParam)) {
  823. // enable input back again if needed
  824. _bReconsiderInput = TRUE;
  825. }
  826. if (msg.message==WM_KEYDOWN && msg.wParam==VK_ESCAPE &&
  827. (_gmRunningGameMode==GM_DEMO || _gmRunningGameMode==GM_INTRO)) {
  828. _pGame->StopGame();
  829. _gmRunningGameMode=GM_NONE;
  830. }
  831. if (_pGame->gm_csConsoleState==CS_TALK && msg.message==WM_KEYDOWN && msg.wParam==VK_ESCAPE) {
  832. _pGame->gm_csConsoleState = CS_OFF;
  833. msg.message=WM_NULL;
  834. }
  835. BOOL bMenuForced = (_gmRunningGameMode==GM_NONE &&
  836. (_pGame->gm_csConsoleState==CS_OFF || _pGame->gm_csConsoleState==CS_TURNINGOFF));
  837. BOOL bMenuToggle = (msg.message==WM_KEYDOWN && msg.wParam==VK_ESCAPE
  838. && (_pGame->gm_csComputerState==CS_OFF || _pGame->gm_csComputerState==CS_ONINBACKGROUND));
  839. if( !bMenuActive) {
  840. if( bMenuForced || bMenuToggle) {
  841. // if console is active
  842. if( _pGame->gm_csConsoleState==CS_ON || _pGame->gm_csConsoleState==CS_TURNINGON) {
  843. // deactivate it
  844. _pGame->gm_csConsoleState = CS_TURNINGOFF;
  845. _iAddonExecState = 0;
  846. }
  847. // delete key down message so menu would not exit because of it
  848. msg.message=WM_NULL;
  849. // start menu
  850. StartMenus();
  851. }
  852. } else {
  853. if (bMenuForced && bMenuToggle && pgmCurrentMenu->gm_pgmParentMenu == NULL) {
  854. // delete key down message so menu would not exit because of it
  855. msg.message=WM_NULL;
  856. }
  857. }
  858. // if neither menu nor console is running
  859. if (!bMenuActive && (_pGame->gm_csConsoleState==CS_OFF || _pGame->gm_csConsoleState==CS_TURNINGOFF)) {
  860. // if current menu is not root
  861. if (!IsMenusInRoot()) {
  862. // start current menu
  863. StartMenus();
  864. }
  865. }
  866. if (sam_bMenuSave) {
  867. sam_bMenuSave = FALSE;
  868. StartMenus("save");
  869. }
  870. if (sam_bMenuLoad) {
  871. sam_bMenuLoad = FALSE;
  872. StartMenus("load");
  873. }
  874. if (sam_bMenuControls) {
  875. sam_bMenuControls = FALSE;
  876. StartMenus("controls");
  877. }
  878. if (sam_bMenuHiScore) {
  879. sam_bMenuHiScore = FALSE;
  880. StartMenus("hiscore");
  881. }
  882. // interpret console key presses
  883. if (_iAddonExecState==0) {
  884. if (msg.message==WM_KEYDOWN) {
  885. _pGame->ConsoleKeyDown(msg);
  886. if (_pGame->gm_csConsoleState!=CS_ON) {
  887. _pGame->ComputerKeyDown(msg);
  888. }
  889. } else if (msg.message==WM_KEYUP) {
  890. // special handler for talk (not to invoke return key bind)
  891. if( msg.wParam==VK_RETURN && _pGame->gm_csConsoleState==CS_TALK) _pGame->gm_csConsoleState = CS_OFF;
  892. } else if (msg.message==WM_CHAR) {
  893. _pGame->ConsoleChar(msg);
  894. }
  895. if (msg.message==WM_LBUTTONDOWN
  896. ||msg.message==WM_RBUTTONDOWN
  897. ||msg.message==WM_LBUTTONDBLCLK
  898. ||msg.message==WM_RBUTTONDBLCLK
  899. ||msg.message==WM_LBUTTONUP
  900. ||msg.message==WM_RBUTTONUP) {
  901. if (_pGame->gm_csConsoleState!=CS_ON) {
  902. _pGame->ComputerKeyDown(msg);
  903. }
  904. }
  905. }
  906. // if menu is active and no input on
  907. if( bMenuActive && !_pInput->IsInputEnabled()) {
  908. // pass keyboard/mouse messages to menu
  909. if(msg.message==WM_KEYDOWN) {
  910. MenuOnKeyDown( msg.wParam);
  911. } else if (msg.message==WM_LBUTTONDOWN || msg.message==WM_LBUTTONDBLCLK) {
  912. MenuOnKeyDown(VK_LBUTTON);
  913. } else if (msg.message==WM_RBUTTONDOWN || msg.message==WM_RBUTTONDBLCLK) {
  914. MenuOnKeyDown(VK_RBUTTON);
  915. } else if (msg.message==WM_MOUSEMOVE) {
  916. MenuOnMouseMove(LOWORD(msg.lParam), HIWORD(msg.lParam));
  917. #ifndef WM_MOUSEWHEEL
  918. #define WM_MOUSEWHEEL 0x020A
  919. #endif
  920. } else if (msg.message==WM_MOUSEWHEEL) {
  921. SWORD swDir = SWORD(UWORD(HIWORD(msg.wParam)));
  922. if (swDir>0) {
  923. MenuOnKeyDown(11);
  924. } else if (swDir<0) {
  925. MenuOnKeyDown(10);
  926. }
  927. } else if (msg.message==WM_CHAR) {
  928. MenuOnChar(msg);
  929. }
  930. }
  931. // if toggling console
  932. BOOL bConsoleKey = sam_bToggleConsole || msg.message==WM_KEYDOWN &&
  933. (MapVirtualKey(msg.wParam, 0)==41 // scan code for '~'
  934. || msg.wParam==VK_F1 || (msg.wParam==VK_ESCAPE && _iAddonExecState==3));
  935. if(bConsoleKey && !_bDefiningKey)
  936. {
  937. sam_bToggleConsole = FALSE;
  938. if( _iAddonExecState==3) _iAddonExecState = 0;
  939. // if it is up, or pulling up
  940. if( _pGame->gm_csConsoleState==CS_OFF || _pGame->gm_csConsoleState==CS_TURNINGOFF) {
  941. // start it moving down and disable menu
  942. _pGame->gm_csConsoleState = CS_TURNINGON;
  943. // stop all IFeel effects
  944. IFeel_StopEffect(NULL);
  945. if( bMenuActive) {
  946. StopMenus(FALSE);
  947. }
  948. // if it is down, or dropping down
  949. } else if( _pGame->gm_csConsoleState==CS_ON || _pGame->gm_csConsoleState==CS_TURNINGON) {
  950. // start it moving up
  951. _pGame->gm_csConsoleState = CS_TURNINGOFF;
  952. }
  953. }
  954. if (_pShell->GetINDEX("con_bTalk") && _pGame->gm_csConsoleState==CS_OFF) {
  955. _pShell->SetINDEX("con_bTalk", FALSE);
  956. _pGame->gm_csConsoleState = CS_TALK;
  957. }
  958. // if pause pressed
  959. if (msg.message==WM_KEYDOWN && msg.wParam==VK_PAUSE) {
  960. // toggle pause
  961. _pNetwork->TogglePause();
  962. }
  963. // if command sent from external application
  964. if (msg.message==WM_COMMAND) {
  965. // if teleport player
  966. if (msg.wParam==1001) {
  967. // teleport player
  968. TeleportPlayer(msg.lParam);
  969. // restore
  970. PostMessage(NULL, WM_SYSCOMMAND, SC_RESTORE, 0);
  971. }
  972. }
  973. // if demo is playing
  974. if (_gmRunningGameMode==GM_DEMO ||
  975. _gmRunningGameMode==GM_INTRO ) {
  976. // check if escape is pressed
  977. BOOL bEscape = (msg.message==WM_KEYDOWN && msg.wParam==VK_ESCAPE);
  978. // check if console-invoke key is pressed
  979. BOOL bTilde = (msg.message==WM_KEYDOWN &&
  980. (msg.wParam==VK_F1 || MapVirtualKey(msg.wParam, 0)==41));// scan code for '~'
  981. // check if any key is pressed
  982. BOOL bAnyKey = (
  983. (msg.message==WM_KEYDOWN && (msg.wParam==VK_SPACE || msg.wParam==VK_RETURN))||
  984. msg.message==WM_LBUTTONDOWN||msg.message==WM_RBUTTONDOWN);
  985. // if escape is pressed
  986. if (bEscape) {
  987. // stop demo
  988. _pGame->StopGame();
  989. _bInAutoPlayLoop = FALSE;
  990. _gmRunningGameMode = GM_NONE;
  991. // if any other key is pressed except console invoking
  992. } else if (bAnyKey && !bTilde) {
  993. // if not in menu or in console
  994. if (!bMenuActive && !bMenuRendering && _pGame->gm_csConsoleState==CS_OFF) {
  995. // skip to next demo
  996. _pGame->StopGame();
  997. _gmRunningGameMode = GM_NONE;
  998. StartNextDemo();
  999. }
  1000. }
  1001. }
  1002. } // loop while there are messages
  1003. // when all messages are removed, window has surely changed
  1004. _bWindowChanging = FALSE;
  1005. // get real cursor position
  1006. if( _pGame->gm_csComputerState!=CS_OFF && _pGame->gm_csComputerState!=CS_ONINBACKGROUND) {
  1007. POINT pt;
  1008. ::GetCursorPos(&pt);
  1009. ::ScreenToClient(_hwndMain, &pt);
  1010. _pGame->ComputerMouseMove(pt.x, pt.y);
  1011. }
  1012. // if addon is to be executed
  1013. if (_iAddonExecState==1) {
  1014. // print header and start console
  1015. CPrintF(TRANS("---- Executing addon: '%s'\n"), (const char*)_fnmAddonToExec);
  1016. sam_bToggleConsole = TRUE;
  1017. _iAddonExecState = 2;
  1018. // if addon is ready for execution
  1019. } else if (_iAddonExecState==2 && _pGame->gm_csConsoleState == CS_ON) {
  1020. // execute it
  1021. CTString strCmd;
  1022. strCmd.PrintF("include \"%s\"", (const char*)_fnmAddonToExec);
  1023. _pShell->Execute(strCmd);
  1024. CPrintF(TRANS("Addon done, press Escape to close console\n"));
  1025. _iAddonExecState = 3;
  1026. }
  1027. // automaticaly manage input enable/disable toggling
  1028. UpdateInputEnabledState();
  1029. // automaticaly manage pause toggling
  1030. UpdatePauseState();
  1031. // notify game whether menu is active
  1032. _pGame->gm_bMenuOn = bMenuActive;
  1033. // do the main game loop and render screen
  1034. DoGame();
  1035. // limit current frame rate if neeeded
  1036. LimitFrameRate();
  1037. } // end of main application loop
  1038. _pInput->DisableInput();
  1039. _pGame->StopGame();
  1040. if (_fnmModToLoad!="") {
  1041. char strCmd [64] = {0};
  1042. char strParam [128] = {0};
  1043. STARTUPINFOA cif;
  1044. ZeroMemory(&cif,sizeof(STARTUPINFOA));
  1045. PROCESS_INFORMATION pi;
  1046. strcpy_s(strCmd,"SeriousSam.exe");
  1047. strcpy_s(strParam," +game ");
  1048. strcat_s(strParam,_fnmModToLoad.FileName());
  1049. if (_strModServerJoin!="") {
  1050. strcat_s(strParam," +connect ");
  1051. strcat_s(strParam,_strModServerJoin);
  1052. strcat_s(strParam," +quickjoin");
  1053. }
  1054. if (CreateProcessA(strCmd,strParam,NULL,NULL,FALSE,CREATE_DEFAULT_ERROR_MODE,NULL,NULL,&cif,&pi) == FALSE)
  1055. {
  1056. MessageBox(0, L"error launching the Mod!\n", L"Serious Sam", MB_OK|MB_ICONERROR);
  1057. }
  1058. }
  1059. // invoke quit screen if needed
  1060. if( _bQuitScreen && _fnmModToLoad=="") QuitScreenLoop();
  1061. End();
  1062. return TRUE;
  1063. }
  1064. /*
  1065. void CheckModReload(void)
  1066. {
  1067. if (_fnmModToLoad!="") {
  1068. CTString strCommand = _fnmApplicationExe.FileDir()+"SeriousSam.exe";
  1069. //+mod "+_fnmModToLoad.FileName()+"\"";
  1070. CTString strMod = _fnmModToLoad.FileName();
  1071. const char *argv[7];
  1072. argv[0] = strCommand;
  1073. argv[1] = "+game";
  1074. argv[2] = strMod;
  1075. argv[3] = NULL;
  1076. if (_strModServerJoin!="") {
  1077. argv[3] = "+connect";
  1078. argv[4] = _strModServerJoin;
  1079. argv[5] = "+quickjoin";
  1080. argv[6] = NULL;
  1081. }
  1082. _execv(strCommand, argv);
  1083. }
  1084. }*/
  1085. void CheckTeaser(void)
  1086. {
  1087. CTFileName fnmTeaser = _fnmApplicationExe.FileDir()+CTString("AfterSam.exe");
  1088. if (fopen(fnmTeaser, "r")!=NULL) {
  1089. Sleep(500);
  1090. _execl(fnmTeaser, "\""+fnmTeaser+"\"", NULL);
  1091. }
  1092. }
  1093. void CheckBrowser(void)
  1094. {
  1095. if (_strURLToVisit!="") {
  1096. RunBrowser(_strURLToVisit);
  1097. }
  1098. }
  1099. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  1100. LPSTR lpCmdLine, int nCmdShow)
  1101. {
  1102. int iResult;
  1103. CTSTREAM_BEGIN {
  1104. iResult = SubMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
  1105. } CTSTREAM_END;
  1106. //CheckModReload();
  1107. CheckTeaser();
  1108. CheckBrowser();
  1109. return iResult;
  1110. }
  1111. // try to start a new display mode
  1112. BOOL TryToSetDisplayMode( enum GfxAPIType eGfxAPI, INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ,
  1113. enum DisplayDepth eColorDepth, BOOL bFullScreenMode)
  1114. {
  1115. CDisplayMode dmTmp;
  1116. dmTmp.dm_ddDepth = eColorDepth;
  1117. CPrintF( TRANS(" Starting display mode: %dx%dx%s (%s)\n"),
  1118. pixSizeI, pixSizeJ, dmTmp.DepthString(),
  1119. bFullScreenMode ? TRANS("fullscreen") : TRANS("window"));
  1120. // mark to start ignoring window size/position messages until settled down
  1121. _bWindowChanging = TRUE;
  1122. // destroy canvas if existing
  1123. _pGame->DisableLoadingHook();
  1124. if( pvpViewPort!=NULL) {
  1125. _pGfx->DestroyWindowCanvas( pvpViewPort);
  1126. pvpViewPort = NULL;
  1127. pdpNormal = NULL;
  1128. }
  1129. // close the application window
  1130. CloseMainWindow();
  1131. // try to set new display mode
  1132. BOOL bSuccess;
  1133. if( bFullScreenMode) {
  1134. #ifdef SE1_D3D
  1135. if( eGfxAPI==GAT_D3D) OpenMainWindowFullScreen( pixSizeI, pixSizeJ);
  1136. #endif // SE1_D3D
  1137. bSuccess = _pGfx->SetDisplayMode( eGfxAPI, iAdapter, pixSizeI, pixSizeJ, eColorDepth);
  1138. if( bSuccess && eGfxAPI==GAT_OGL) OpenMainWindowFullScreen( pixSizeI, pixSizeJ);
  1139. } else {
  1140. #ifdef SE1_D3D
  1141. if( eGfxAPI==GAT_D3D) OpenMainWindowNormal( pixSizeI, pixSizeJ);
  1142. #endif // SE1_D3D
  1143. bSuccess = _pGfx->ResetDisplayMode( eGfxAPI);
  1144. if( bSuccess && eGfxAPI==GAT_OGL) OpenMainWindowNormal( pixSizeI, pixSizeJ);
  1145. #ifdef SE1_D3D
  1146. if( bSuccess && eGfxAPI==GAT_D3D) ResetMainWindowNormal();
  1147. #endif // SE1_D3D
  1148. }
  1149. // if new mode was set
  1150. if( bSuccess) {
  1151. // create canvas
  1152. ASSERT( pvpViewPort==NULL);
  1153. ASSERT( pdpNormal==NULL);
  1154. _pGfx->CreateWindowCanvas( _hwndMain, &pvpViewPort, &pdpNormal);
  1155. // erase context of both buffers (for the sake of wide-screen)
  1156. pdp = pdpNormal;
  1157. if( pdp!=NULL && pdp->Lock()) {
  1158. pdp->Fill(C_BLACK|CT_OPAQUE);
  1159. pdp->Unlock();
  1160. pvpViewPort->SwapBuffers();
  1161. pdp->Lock();
  1162. pdp->Fill(C_BLACK|CT_OPAQUE);
  1163. pdp->Unlock();
  1164. pvpViewPort->SwapBuffers();
  1165. }
  1166. // lets try some wide screen screaming :)
  1167. const PIX pixYBegAdj = pdp->GetHeight() * 21/24;
  1168. const PIX pixYEndAdj = pdp->GetHeight() * 3/24;
  1169. const PIX pixXEnd = pdp->GetWidth();
  1170. pdpWideScreen = new CDrawPort( pdp, PIXaabbox2D( PIX2D(0,pixYBegAdj), PIX2D(pixXEnd, pixYEndAdj)));
  1171. pdpWideScreen->dp_fWideAdjustment = 9.0f / 12.0f;
  1172. if( sam_bWideScreen) pdp = pdpWideScreen;
  1173. // initial screen fill and swap, just to get context running
  1174. BOOL bSuccess = FALSE;
  1175. if( pdp!=NULL && pdp->Lock()) {
  1176. pdp->Fill( LCDGetColor( C_dGREEN|CT_OPAQUE, "bcg fill"));
  1177. pdp->Unlock();
  1178. pvpViewPort->SwapBuffers();
  1179. bSuccess = TRUE;
  1180. }
  1181. _pGame->EnableLoadingHook(pdp);
  1182. // if the mode is not working, or is not accelerated
  1183. if( !bSuccess || !_pGfx->IsCurrentModeAccelerated())
  1184. { // report error
  1185. CPrintF( TRANS("This mode does not support hardware acceleration.\n"));
  1186. // destroy canvas if existing
  1187. if( pvpViewPort!=NULL) {
  1188. _pGame->DisableLoadingHook();
  1189. _pGfx->DestroyWindowCanvas( pvpViewPort);
  1190. pvpViewPort = NULL;
  1191. pdpNormal = NULL;
  1192. }
  1193. // close the application window
  1194. CloseMainWindow();
  1195. // report failure
  1196. return FALSE;
  1197. }
  1198. // remember new settings
  1199. sam_bFullScreenActive = bFullScreenMode;
  1200. sam_iScreenSizeI = pixSizeI;
  1201. sam_iScreenSizeJ = pixSizeJ;
  1202. sam_iDisplayDepth = eColorDepth;
  1203. sam_iDisplayAdapter = iAdapter;
  1204. sam_iGfxAPI = eGfxAPI;
  1205. // report success
  1206. return TRUE;
  1207. // if couldn't set new mode
  1208. } else {
  1209. // close the application window
  1210. CloseMainWindow();
  1211. // report failure
  1212. return FALSE;
  1213. }
  1214. }
  1215. // list of possible display modes for recovery
  1216. const INDEX aDefaultModes[][3] =
  1217. { // color, API, adapter
  1218. { DD_DEFAULT, GAT_OGL, 0},
  1219. { DD_16BIT, GAT_OGL, 0},
  1220. { DD_16BIT, GAT_OGL, 1}, // 3dfx Voodoo2
  1221. #ifdef SE1_D3D
  1222. { DD_DEFAULT, GAT_D3D, 0},
  1223. { DD_16BIT, GAT_D3D, 0},
  1224. { DD_16BIT, GAT_D3D, 1},
  1225. #endif // SE1_D3D
  1226. };
  1227. const INDEX ctDefaultModes = ARRAYCOUNT(aDefaultModes);
  1228. // start new display mode
  1229. void StartNewMode( enum GfxAPIType eGfxAPI, INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ,
  1230. enum DisplayDepth eColorDepth, BOOL bFullScreenMode)
  1231. {
  1232. CPrintF( TRANS("\n* START NEW DISPLAY MODE ...\n"));
  1233. // try to set the mode
  1234. BOOL bSuccess = TryToSetDisplayMode( eGfxAPI, iAdapter, pixSizeI, pixSizeJ, eColorDepth, bFullScreenMode);
  1235. // if failed
  1236. if( !bSuccess)
  1237. {
  1238. // report failure and reset to default resolution
  1239. _iDisplayModeChangeFlag = 2; // failure
  1240. CPrintF( TRANS("Requested display mode could not be set!\n"));
  1241. pixSizeI = 640;
  1242. pixSizeJ = 480;
  1243. bFullScreenMode = TRUE;
  1244. // try to revert to one of recovery modes
  1245. for( INDEX iMode=0; iMode<ctDefaultModes; iMode++) {
  1246. eColorDepth = (DisplayDepth)aDefaultModes[iMode][0];
  1247. eGfxAPI = (GfxAPIType) aDefaultModes[iMode][1];
  1248. iAdapter = aDefaultModes[iMode][2];
  1249. CPrintF(TRANS("\nTrying recovery mode %d...\n"), iMode);
  1250. bSuccess = TryToSetDisplayMode( eGfxAPI, iAdapter, pixSizeI, pixSizeJ, eColorDepth, bFullScreenMode);
  1251. if( bSuccess) break;
  1252. }
  1253. // if all failed
  1254. if( !bSuccess) {
  1255. FatalError(TRANS(
  1256. "Cannot set display mode!\n"
  1257. "Serious Sam was unable to find display mode with hardware acceleration.\n"
  1258. "Make sure you install proper drivers for your video card as recommended\n"
  1259. "in documentation and set your desktop to 16 bit (65536 colors).\n"
  1260. "Please see ReadMe file for troubleshooting information.\n"));
  1261. }
  1262. // if succeeded
  1263. } else {
  1264. _iDisplayModeChangeFlag = 1; // all ok
  1265. }
  1266. // apply 3D-acc settings
  1267. ApplyGLSettings(FALSE);
  1268. // remember time of mode setting
  1269. _tmDisplayModeChanged = _pTimer->GetRealTimeTick();
  1270. }