Common.cpp 87 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "../renderer/Image.h"
  23. #define MAX_PRINT_MSG_SIZE 4096
  24. #define MAX_WARNING_LIST 256
  25. typedef enum {
  26. ERP_NONE,
  27. ERP_FATAL, // exit the entire game with a popup window
  28. ERP_DROP, // print to console and disconnect from game
  29. ERP_DISCONNECT // don't kill server
  30. } errorParm_t;
  31. #if defined( _DEBUG )
  32. #define BUILD_DEBUG "-debug"
  33. #else
  34. #define BUILD_DEBUG ""
  35. #endif
  36. struct version_s {
  37. version_s( void ) { sprintf( string, "%s.%d%s %s %s %s", ENGINE_VERSION, BUILD_NUMBER, BUILD_DEBUG, BUILD_STRING, __DATE__, __TIME__ ); }
  38. char string[256];
  39. } version;
  40. idCVar com_version( "si_version", version.string, CVAR_SYSTEM|CVAR_ROM|CVAR_SERVERINFO, "engine version" );
  41. idCVar com_skipRenderer( "com_skipRenderer", "0", CVAR_BOOL|CVAR_SYSTEM, "skip the renderer completely" );
  42. idCVar com_machineSpec( "com_machineSpec", "-1", CVAR_INTEGER | CVAR_ARCHIVE | CVAR_SYSTEM, "hardware classification, -1 = not detected, 0 = low quality, 1 = medium quality, 2 = high quality, 3 = ultra quality" );
  43. idCVar com_purgeAll( "com_purgeAll", "0", CVAR_BOOL | CVAR_ARCHIVE | CVAR_SYSTEM, "purge everything between level loads" );
  44. idCVar com_memoryMarker( "com_memoryMarker", "-1", CVAR_INTEGER | CVAR_SYSTEM | CVAR_INIT, "used as a marker for memory stats" );
  45. idCVar com_preciseTic( "com_preciseTic", "1", CVAR_BOOL|CVAR_SYSTEM, "run one game tick every async thread update" );
  46. idCVar com_asyncInput( "com_asyncInput", "0", CVAR_BOOL|CVAR_SYSTEM, "sample input from the async thread" );
  47. #define ASYNCSOUND_INFO "0: mix sound inline, 1: memory mapped async mix, 2: callback mixing, 3: write async mix"
  48. #if defined( MACOS_X )
  49. idCVar com_asyncSound( "com_asyncSound", "2", CVAR_INTEGER|CVAR_SYSTEM|CVAR_ROM, ASYNCSOUND_INFO );
  50. #elif defined( __linux__ )
  51. idCVar com_asyncSound( "com_asyncSound", "3", CVAR_INTEGER|CVAR_SYSTEM|CVAR_ROM, ASYNCSOUND_INFO );
  52. #else
  53. idCVar com_asyncSound( "com_asyncSound", "1", CVAR_INTEGER|CVAR_SYSTEM, ASYNCSOUND_INFO, 0, 1 );
  54. #endif
  55. idCVar com_forceGenericSIMD( "com_forceGenericSIMD", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "force generic platform independent SIMD" );
  56. idCVar com_developer( "developer", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "developer mode" );
  57. idCVar com_allowConsole( "com_allowConsole", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "allow toggling console with the tilde key" );
  58. idCVar com_speeds( "com_speeds", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "show engine timings" );
  59. idCVar com_showFPS( "com_showFPS", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_ARCHIVE|CVAR_NOCHEAT, "show frames rendered per second" );
  60. idCVar com_showMemoryUsage( "com_showMemoryUsage", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "show total and per frame memory usage" );
  61. idCVar com_showAsyncStats( "com_showAsyncStats", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "show async network stats" );
  62. idCVar com_showSoundDecoders( "com_showSoundDecoders", "0", CVAR_BOOL|CVAR_SYSTEM|CVAR_NOCHEAT, "show sound decoders" );
  63. idCVar com_timestampPrints( "com_timestampPrints", "0", CVAR_SYSTEM, "print time with each console print, 1 = msec, 2 = sec", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  64. idCVar com_timescale( "timescale", "1", CVAR_SYSTEM | CVAR_FLOAT, "scales the time", 0.1f, 10.0f );
  65. idCVar com_logFile( "logFile", "0", CVAR_SYSTEM | CVAR_NOCHEAT, "1 = buffer log, 2 = flush after each print", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  66. idCVar com_logFileName( "logFileName", "qconsole.log", CVAR_SYSTEM | CVAR_NOCHEAT, "name of log file, if empty, qconsole.log will be used" );
  67. idCVar com_makingBuild( "com_makingBuild", "0", CVAR_BOOL | CVAR_SYSTEM, "1 when making a build" );
  68. idCVar com_updateLoadSize( "com_updateLoadSize", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "update the load size after loading a map" );
  69. idCVar com_videoRam( "com_videoRam", "64", CVAR_INTEGER | CVAR_SYSTEM | CVAR_NOCHEAT | CVAR_ARCHIVE, "holds the last amount of detected video ram" );
  70. idCVar com_product_lang_ext( "com_product_lang_ext", "1", CVAR_INTEGER | CVAR_SYSTEM | CVAR_ARCHIVE, "Extension to use when creating language files." );
  71. // com_speeds times
  72. int time_gameFrame;
  73. int time_gameDraw;
  74. int time_frontend; // renderSystem frontend time
  75. int time_backend; // renderSystem backend time
  76. int com_frameTime; // time for the current frame in milliseconds
  77. int com_frameNumber; // variable frame number
  78. volatile int com_ticNumber; // 60 hz tics
  79. int com_editors; // currently opened editor(s)
  80. bool com_editorActive; // true if an editor has focus
  81. #ifdef _WIN32
  82. HWND com_hwndMsg = NULL;
  83. bool com_outputMsg = false;
  84. unsigned int com_msgID = -1;
  85. #endif
  86. #ifdef __DOOM_DLL__
  87. idGame * game = NULL;
  88. idGameEdit * gameEdit = NULL;
  89. #endif
  90. // writes si_version to the config file - in a kinda obfuscated way
  91. //#define ID_WRITE_VERSION
  92. class idCommonLocal : public idCommon {
  93. public:
  94. idCommonLocal( void );
  95. virtual void Init( int argc, const char **argv, const char *cmdline );
  96. virtual void Shutdown( void );
  97. virtual void Quit( void );
  98. virtual bool IsInitialized( void ) const;
  99. virtual void Frame( void );
  100. virtual void GUIFrame( bool execCmd, bool network );
  101. virtual void Async( void );
  102. virtual void StartupVariable( const char *match, bool once );
  103. virtual void InitTool( const toolFlag_t tool, const idDict *dict );
  104. virtual void ActivateTool( bool active );
  105. virtual void WriteConfigToFile( const char *filename );
  106. virtual void WriteFlaggedCVarsToFile( const char *filename, int flags, const char *setCmd );
  107. virtual void BeginRedirect( char *buffer, int buffersize, void (*flush)( const char * ) );
  108. virtual void EndRedirect( void );
  109. virtual void SetRefreshOnPrint( bool set );
  110. virtual void Printf( const char *fmt, ... ) id_attribute((format(printf,2,3)));
  111. virtual void VPrintf( const char *fmt, va_list arg );
  112. virtual void DPrintf( const char *fmt, ... ) id_attribute((format(printf,2,3)));
  113. virtual void Warning( const char *fmt, ... ) id_attribute((format(printf,2,3)));
  114. virtual void DWarning( const char *fmt, ...) id_attribute((format(printf,2,3)));
  115. virtual void PrintWarnings( void );
  116. virtual void ClearWarnings( const char *reason );
  117. virtual void Error( const char *fmt, ... ) id_attribute((format(printf,2,3)));
  118. virtual void FatalError( const char *fmt, ... ) id_attribute((format(printf,2,3)));
  119. virtual const idLangDict * GetLanguageDict( void );
  120. virtual const char * KeysFromBinding( const char *bind );
  121. virtual const char * BindingFromKey( const char *key );
  122. virtual int ButtonState( int key );
  123. virtual int KeyState( int key );
  124. void InitGame( void );
  125. void ShutdownGame( bool reloading );
  126. // localization
  127. void InitLanguageDict( void );
  128. void LocalizeGui( const char *fileName, idLangDict &langDict );
  129. void LocalizeMapData( const char *fileName, idLangDict &langDict );
  130. void LocalizeSpecificMapData( const char *fileName, idLangDict &langDict, const idLangDict &replaceArgs );
  131. void SetMachineSpec( void );
  132. private:
  133. void InitCommands( void );
  134. void InitRenderSystem( void );
  135. void InitSIMD( void );
  136. bool AddStartupCommands( void );
  137. void ParseCommandLine( int argc, const char **argv );
  138. void ClearCommandLine( void );
  139. bool SafeMode( void );
  140. void CheckToolMode( void );
  141. void CloseLogFile( void );
  142. void WriteConfiguration( void );
  143. void DumpWarnings( void );
  144. void SingleAsyncTic( void );
  145. void LoadGameDLL( void );
  146. void UnloadGameDLL( void );
  147. void PrintLoadingMessage( const char *msg );
  148. void FilterLangList( idStrList* list, idStr lang );
  149. bool com_fullyInitialized;
  150. bool com_refreshOnPrint; // update the screen every print for dmap
  151. int com_errorEntered; // 0, ERP_DROP, etc
  152. bool com_shuttingDown;
  153. idFile * logFile;
  154. char errorMessage[MAX_PRINT_MSG_SIZE];
  155. char * rd_buffer;
  156. int rd_buffersize;
  157. void (*rd_flush)( const char *buffer );
  158. idStr warningCaption;
  159. idStrList warningList;
  160. idStrList errorList;
  161. int gameDLL;
  162. idLangDict languageDict;
  163. #ifdef ID_WRITE_VERSION
  164. idCompressor * config_compressor;
  165. #endif
  166. };
  167. idCommonLocal commonLocal;
  168. idCommon * common = &commonLocal;
  169. /*
  170. ==================
  171. idCommonLocal::idCommonLocal
  172. ==================
  173. */
  174. idCommonLocal::idCommonLocal( void ) {
  175. com_fullyInitialized = false;
  176. com_refreshOnPrint = false;
  177. com_errorEntered = 0;
  178. com_shuttingDown = false;
  179. logFile = NULL;
  180. strcpy( errorMessage, "" );
  181. rd_buffer = NULL;
  182. rd_buffersize = 0;
  183. rd_flush = NULL;
  184. gameDLL = 0;
  185. #ifdef ID_WRITE_VERSION
  186. config_compressor = NULL;
  187. #endif
  188. }
  189. /*
  190. ==================
  191. idCommonLocal::BeginRedirect
  192. ==================
  193. */
  194. void idCommonLocal::BeginRedirect( char *buffer, int buffersize, void (*flush)( const char *) ) {
  195. if ( !buffer || !buffersize || !flush ) {
  196. return;
  197. }
  198. rd_buffer = buffer;
  199. rd_buffersize = buffersize;
  200. rd_flush = flush;
  201. *rd_buffer = 0;
  202. }
  203. /*
  204. ==================
  205. idCommonLocal::EndRedirect
  206. ==================
  207. */
  208. void idCommonLocal::EndRedirect( void ) {
  209. if ( rd_flush && rd_buffer[ 0 ] ) {
  210. rd_flush( rd_buffer );
  211. }
  212. rd_buffer = NULL;
  213. rd_buffersize = 0;
  214. rd_flush = NULL;
  215. }
  216. #ifdef _WIN32
  217. /*
  218. ==================
  219. EnumWindowsProc
  220. ==================
  221. */
  222. BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam ) {
  223. char buff[1024];
  224. ::GetWindowText( hwnd, buff, sizeof( buff ) );
  225. if ( idStr::Icmpn( buff, EDITOR_WINDOWTEXT, strlen( EDITOR_WINDOWTEXT ) ) == 0 ) {
  226. com_hwndMsg = hwnd;
  227. return FALSE;
  228. }
  229. return TRUE;
  230. }
  231. /*
  232. ==================
  233. FindEditor
  234. ==================
  235. */
  236. bool FindEditor( void ) {
  237. com_hwndMsg = NULL;
  238. EnumWindows( EnumWindowsProc, 0 );
  239. return !( com_hwndMsg == NULL );
  240. }
  241. #endif
  242. /*
  243. ==================
  244. idCommonLocal::CloseLogFile
  245. ==================
  246. */
  247. void idCommonLocal::CloseLogFile( void ) {
  248. if ( logFile ) {
  249. com_logFile.SetBool( false ); // make sure no further VPrintf attempts to open the log file again
  250. fileSystem->CloseFile( logFile );
  251. logFile = NULL;
  252. }
  253. }
  254. /*
  255. ==================
  256. idCommonLocal::SetRefreshOnPrint
  257. ==================
  258. */
  259. void idCommonLocal::SetRefreshOnPrint( bool set ) {
  260. com_refreshOnPrint = set;
  261. }
  262. /*
  263. ==================
  264. idCommonLocal::VPrintf
  265. A raw string should NEVER be passed as fmt, because of "%f" type crashes.
  266. ==================
  267. */
  268. void idCommonLocal::VPrintf( const char *fmt, va_list args ) {
  269. char msg[MAX_PRINT_MSG_SIZE];
  270. int timeLength;
  271. static bool logFileFailed = false;
  272. // if the cvar system is not initialized
  273. if ( !cvarSystem->IsInitialized() ) {
  274. return;
  275. }
  276. // optionally put a timestamp at the beginning of each print,
  277. // so we can see how long different init sections are taking
  278. if ( com_timestampPrints.GetInteger() ) {
  279. int t = Sys_Milliseconds();
  280. if ( com_timestampPrints.GetInteger() == 1 ) {
  281. t /= 1000;
  282. }
  283. sprintf( msg, "[%i]", t );
  284. timeLength = strlen( msg );
  285. } else {
  286. timeLength = 0;
  287. }
  288. // don't overflow
  289. if ( idStr::vsnPrintf( msg+timeLength, MAX_PRINT_MSG_SIZE-timeLength-1, fmt, args ) < 0 ) {
  290. msg[sizeof(msg)-2] = '\n'; msg[sizeof(msg)-1] = '\0'; // avoid output garbling
  291. Sys_Printf( "idCommon::VPrintf: truncated to %d characters\n", strlen(msg)-1 );
  292. }
  293. if ( rd_buffer ) {
  294. if ( (int)( strlen( msg ) + strlen( rd_buffer ) ) > ( rd_buffersize - 1 ) ) {
  295. rd_flush( rd_buffer );
  296. *rd_buffer = 0;
  297. }
  298. strcat( rd_buffer, msg );
  299. return;
  300. }
  301. // echo to console buffer
  302. console->Print( msg );
  303. // remove any color codes
  304. idStr::RemoveColors( msg );
  305. // echo to dedicated console and early console
  306. Sys_Printf( "%s", msg );
  307. // print to script debugger server
  308. // DebuggerServerPrint( msg );
  309. #if 0 // !@#
  310. #if defined(_DEBUG) && defined(WIN32)
  311. if ( strlen( msg ) < 512 ) {
  312. TRACE( msg );
  313. }
  314. #endif
  315. #endif
  316. // logFile
  317. if ( com_logFile.GetInteger() && !logFileFailed && fileSystem->IsInitialized() ) {
  318. static bool recursing;
  319. if ( !logFile && !recursing ) {
  320. struct tm *newtime;
  321. ID_TIME_T aclock;
  322. const char *fileName = com_logFileName.GetString()[0] ? com_logFileName.GetString() : "qconsole.log";
  323. // fileSystem->OpenFileWrite can cause recursive prints into here
  324. recursing = true;
  325. logFile = fileSystem->OpenFileWrite( fileName );
  326. if ( !logFile ) {
  327. logFileFailed = true;
  328. FatalError( "failed to open log file '%s'\n", fileName );
  329. }
  330. recursing = false;
  331. if ( com_logFile.GetInteger() > 1 ) {
  332. // force it to not buffer so we get valid
  333. // data even if we are crashing
  334. logFile->ForceFlush();
  335. }
  336. time( &aclock );
  337. newtime = localtime( &aclock );
  338. Printf( "log file '%s' opened on %s\n", fileName, asctime( newtime ) );
  339. }
  340. if ( logFile ) {
  341. logFile->Write( msg, strlen( msg ) );
  342. logFile->Flush(); // ForceFlush doesn't help a whole lot
  343. }
  344. }
  345. // don't trigger any updates if we are in the process of doing a fatal error
  346. if ( com_errorEntered != ERP_FATAL ) {
  347. // update the console if we are in a long-running command, like dmap
  348. if ( com_refreshOnPrint ) {
  349. session->UpdateScreen();
  350. }
  351. // let session redraw the animated loading screen if necessary
  352. session->PacifierUpdate();
  353. }
  354. #ifdef _WIN32
  355. if ( com_outputMsg ) {
  356. if ( com_msgID == -1 ) {
  357. com_msgID = ::RegisterWindowMessage( DMAP_MSGID );
  358. if ( !FindEditor() ) {
  359. com_outputMsg = false;
  360. } else {
  361. Sys_ShowWindow( false );
  362. }
  363. }
  364. if ( com_hwndMsg ) {
  365. ATOM atom = ::GlobalAddAtom( msg );
  366. ::PostMessage( com_hwndMsg, com_msgID, 0, static_cast<LPARAM>(atom) );
  367. }
  368. }
  369. #endif
  370. }
  371. /*
  372. ==================
  373. idCommonLocal::Printf
  374. Both client and server can use this, and it will output to the appropriate place.
  375. A raw string should NEVER be passed as fmt, because of "%f" type crashers.
  376. ==================
  377. */
  378. void idCommonLocal::Printf( const char *fmt, ... ) {
  379. va_list argptr;
  380. va_start( argptr, fmt );
  381. VPrintf( fmt, argptr );
  382. va_end( argptr );
  383. }
  384. /*
  385. ==================
  386. idCommonLocal::DPrintf
  387. prints message that only shows up if the "developer" cvar is set
  388. ==================
  389. */
  390. void idCommonLocal::DPrintf( const char *fmt, ... ) {
  391. va_list argptr;
  392. char msg[MAX_PRINT_MSG_SIZE];
  393. if ( !cvarSystem->IsInitialized() || !com_developer.GetBool() ) {
  394. return; // don't confuse non-developers with techie stuff...
  395. }
  396. va_start( argptr, fmt );
  397. idStr::vsnPrintf( msg, sizeof(msg), fmt, argptr );
  398. va_end( argptr );
  399. msg[sizeof(msg)-1] = '\0';
  400. // never refresh the screen, which could cause reentrency problems
  401. bool temp = com_refreshOnPrint;
  402. com_refreshOnPrint = false;
  403. Printf( S_COLOR_RED"%s", msg );
  404. com_refreshOnPrint = temp;
  405. }
  406. /*
  407. ==================
  408. idCommonLocal::DWarning
  409. prints warning message in yellow that only shows up if the "developer" cvar is set
  410. ==================
  411. */
  412. void idCommonLocal::DWarning( const char *fmt, ... ) {
  413. va_list argptr;
  414. char msg[MAX_PRINT_MSG_SIZE];
  415. if ( !com_developer.GetBool() ) {
  416. return; // don't confuse non-developers with techie stuff...
  417. }
  418. va_start( argptr, fmt );
  419. idStr::vsnPrintf( msg, sizeof(msg), fmt, argptr );
  420. va_end( argptr );
  421. msg[sizeof(msg)-1] = '\0';
  422. Printf( S_COLOR_YELLOW"WARNING: %s\n", msg );
  423. }
  424. /*
  425. ==================
  426. idCommonLocal::Warning
  427. prints WARNING %s and adds the warning message to a queue to be printed later on
  428. ==================
  429. */
  430. void idCommonLocal::Warning( const char *fmt, ... ) {
  431. va_list argptr;
  432. char msg[MAX_PRINT_MSG_SIZE];
  433. va_start( argptr, fmt );
  434. idStr::vsnPrintf( msg, sizeof(msg), fmt, argptr );
  435. va_end( argptr );
  436. msg[sizeof(msg)-1] = 0;
  437. Printf( S_COLOR_YELLOW "WARNING: " S_COLOR_RED "%s\n", msg );
  438. if ( warningList.Num() < MAX_WARNING_LIST ) {
  439. warningList.AddUnique( msg );
  440. }
  441. }
  442. /*
  443. ==================
  444. idCommonLocal::PrintWarnings
  445. ==================
  446. */
  447. void idCommonLocal::PrintWarnings( void ) {
  448. int i;
  449. if ( !warningList.Num() ) {
  450. return;
  451. }
  452. warningList.Sort();
  453. Printf( "------------- Warnings ---------------\n" );
  454. Printf( "during %s...\n", warningCaption.c_str() );
  455. for ( i = 0; i < warningList.Num(); i++ ) {
  456. Printf( S_COLOR_YELLOW "WARNING: " S_COLOR_RED "%s\n", warningList[i].c_str() );
  457. }
  458. if ( warningList.Num() ) {
  459. if ( warningList.Num() >= MAX_WARNING_LIST ) {
  460. Printf( "more than %d warnings\n", MAX_WARNING_LIST );
  461. } else {
  462. Printf( "%d warnings\n", warningList.Num() );
  463. }
  464. }
  465. }
  466. /*
  467. ==================
  468. idCommonLocal::ClearWarnings
  469. ==================
  470. */
  471. void idCommonLocal::ClearWarnings( const char *reason ) {
  472. warningCaption = reason;
  473. warningList.Clear();
  474. }
  475. /*
  476. ==================
  477. idCommonLocal::DumpWarnings
  478. ==================
  479. */
  480. void idCommonLocal::DumpWarnings( void ) {
  481. int i;
  482. idFile *warningFile;
  483. if ( !warningList.Num() ) {
  484. return;
  485. }
  486. warningFile = fileSystem->OpenFileWrite( "warnings.txt", "fs_savepath" );
  487. if ( warningFile ) {
  488. warningFile->Printf( "------------- Warnings ---------------\n\n" );
  489. warningFile->Printf( "during %s...\n", warningCaption.c_str() );
  490. warningList.Sort();
  491. for ( i = 0; i < warningList.Num(); i++ ) {
  492. warningList[i].RemoveColors();
  493. warningFile->Printf( "WARNING: %s\n", warningList[i].c_str() );
  494. }
  495. if ( warningList.Num() >= MAX_WARNING_LIST ) {
  496. warningFile->Printf( "\nmore than %d warnings!\n", MAX_WARNING_LIST );
  497. } else {
  498. warningFile->Printf( "\n%d warnings.\n", warningList.Num() );
  499. }
  500. warningFile->Printf( "\n\n-------------- Errors ---------------\n\n" );
  501. errorList.Sort();
  502. for ( i = 0; i < errorList.Num(); i++ ) {
  503. errorList[i].RemoveColors();
  504. warningFile->Printf( "ERROR: %s", errorList[i].c_str() );
  505. }
  506. warningFile->ForceFlush();
  507. fileSystem->CloseFile( warningFile );
  508. #if defined(_WIN32) && !defined(_DEBUG)
  509. idStr osPath;
  510. osPath = fileSystem->RelativePathToOSPath( "warnings.txt", "fs_savepath" );
  511. WinExec( va( "Notepad.exe %s", osPath.c_str() ), SW_SHOW );
  512. #endif
  513. }
  514. }
  515. /*
  516. ==================
  517. idCommonLocal::Error
  518. ==================
  519. */
  520. void idCommonLocal::Error( const char *fmt, ... ) {
  521. va_list argptr;
  522. static int lastErrorTime;
  523. static int errorCount;
  524. int currentTime;
  525. int code = ERP_DROP;
  526. // always turn this off after an error
  527. com_refreshOnPrint = false;
  528. // when we are running automated scripts, make sure we
  529. // know if anything failed
  530. if ( cvarSystem->GetCVarInteger( "fs_copyfiles" ) ) {
  531. code = ERP_FATAL;
  532. }
  533. // if we don't have GL running, make it a fatal error
  534. if ( !renderSystem->IsOpenGLRunning() ) {
  535. code = ERP_FATAL;
  536. }
  537. // if we got a recursive error, make it fatal
  538. if ( com_errorEntered ) {
  539. // if we are recursively erroring while exiting
  540. // from a fatal error, just kill the entire
  541. // process immediately, which will prevent a
  542. // full screen rendering window covering the
  543. // error dialog
  544. if ( com_errorEntered == ERP_FATAL ) {
  545. Sys_Quit();
  546. }
  547. code = ERP_FATAL;
  548. }
  549. // if we are getting a solid stream of ERP_DROP, do an ERP_FATAL
  550. currentTime = Sys_Milliseconds();
  551. if ( currentTime - lastErrorTime < 100 ) {
  552. if ( ++errorCount > 3 ) {
  553. code = ERP_FATAL;
  554. }
  555. } else {
  556. errorCount = 0;
  557. }
  558. lastErrorTime = currentTime;
  559. com_errorEntered = code;
  560. va_start (argptr,fmt);
  561. idStr::vsnPrintf( errorMessage, sizeof(errorMessage), fmt, argptr );
  562. va_end (argptr);
  563. errorMessage[sizeof(errorMessage)-1] = '\0';
  564. // copy the error message to the clip board
  565. Sys_SetClipboardData( errorMessage );
  566. // add the message to the error list
  567. errorList.AddUnique( errorMessage );
  568. // Dont shut down the session for gui editor or debugger
  569. if ( !( com_editors & ( EDITOR_GUI | EDITOR_DEBUGGER ) ) ) {
  570. session->Stop();
  571. }
  572. if ( code == ERP_DISCONNECT ) {
  573. com_errorEntered = 0;
  574. throw idException( errorMessage );
  575. // The gui editor doesnt want thing to com_error so it handles exceptions instead
  576. } else if( com_editors & ( EDITOR_GUI | EDITOR_DEBUGGER ) ) {
  577. com_errorEntered = 0;
  578. throw idException( errorMessage );
  579. } else if ( code == ERP_DROP ) {
  580. Printf( "********************\nERROR: %s\n********************\n", errorMessage );
  581. com_errorEntered = 0;
  582. throw idException( errorMessage );
  583. } else {
  584. Printf( "********************\nERROR: %s\n********************\n", errorMessage );
  585. }
  586. if ( cvarSystem->GetCVarBool( "r_fullscreen" ) ) {
  587. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "vid_restart partial windowed\n" );
  588. }
  589. Shutdown();
  590. Sys_Error( "%s", errorMessage );
  591. }
  592. /*
  593. ==================
  594. idCommonLocal::FatalError
  595. Dump out of the game to a system dialog
  596. ==================
  597. */
  598. void idCommonLocal::FatalError( const char *fmt, ... ) {
  599. va_list argptr;
  600. // if we got a recursive error, make it fatal
  601. if ( com_errorEntered ) {
  602. // if we are recursively erroring while exiting
  603. // from a fatal error, just kill the entire
  604. // process immediately, which will prevent a
  605. // full screen rendering window covering the
  606. // error dialog
  607. Sys_Printf( "FATAL: recursed fatal error:\n%s\n", errorMessage );
  608. va_start( argptr, fmt );
  609. idStr::vsnPrintf( errorMessage, sizeof(errorMessage), fmt, argptr );
  610. va_end( argptr );
  611. errorMessage[sizeof(errorMessage)-1] = '\0';
  612. Sys_Printf( "%s\n", errorMessage );
  613. // write the console to a log file?
  614. Sys_Quit();
  615. }
  616. com_errorEntered = ERP_FATAL;
  617. va_start( argptr, fmt );
  618. idStr::vsnPrintf( errorMessage, sizeof(errorMessage), fmt, argptr );
  619. va_end( argptr );
  620. errorMessage[sizeof(errorMessage)-1] = '\0';
  621. if ( cvarSystem->GetCVarBool( "r_fullscreen" ) ) {
  622. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "vid_restart partial windowed\n" );
  623. }
  624. Sys_SetFatalError( errorMessage );
  625. Shutdown();
  626. Sys_Error( "%s", errorMessage );
  627. }
  628. /*
  629. ==================
  630. idCommonLocal::Quit
  631. ==================
  632. */
  633. void idCommonLocal::Quit( void ) {
  634. #ifdef ID_ALLOW_TOOLS
  635. if ( com_editors & EDITOR_RADIANT ) {
  636. RadiantInit();
  637. return;
  638. }
  639. #endif
  640. // don't try to shutdown if we are in a recursive error
  641. if ( !com_errorEntered ) {
  642. Shutdown();
  643. }
  644. Sys_Quit();
  645. }
  646. /*
  647. ============================================================================
  648. COMMAND LINE FUNCTIONS
  649. + characters separate the commandLine string into multiple console
  650. command lines.
  651. All of these are valid:
  652. doom +set test blah +map test
  653. doom set test blah+map test
  654. doom set test blah + map test
  655. ============================================================================
  656. */
  657. #define MAX_CONSOLE_LINES 32
  658. int com_numConsoleLines;
  659. idCmdArgs com_consoleLines[MAX_CONSOLE_LINES];
  660. /*
  661. ==================
  662. idCommonLocal::ParseCommandLine
  663. ==================
  664. */
  665. void idCommonLocal::ParseCommandLine( int argc, const char **argv ) {
  666. int i, current_count;
  667. com_numConsoleLines = 0;
  668. current_count = 0;
  669. // API says no program path
  670. for ( i = 0; i < argc; i++ ) {
  671. if ( argv[ i ][ 0 ] == '+' ) {
  672. com_numConsoleLines++;
  673. com_consoleLines[ com_numConsoleLines-1 ].AppendArg( argv[ i ] + 1 );
  674. } else {
  675. if ( !com_numConsoleLines ) {
  676. com_numConsoleLines++;
  677. }
  678. com_consoleLines[ com_numConsoleLines-1 ].AppendArg( argv[ i ] );
  679. }
  680. }
  681. }
  682. /*
  683. ==================
  684. idCommonLocal::ClearCommandLine
  685. ==================
  686. */
  687. void idCommonLocal::ClearCommandLine( void ) {
  688. com_numConsoleLines = 0;
  689. }
  690. /*
  691. ==================
  692. idCommonLocal::SafeMode
  693. Check for "safe" on the command line, which will
  694. skip loading of config file (DoomConfig.cfg)
  695. ==================
  696. */
  697. bool idCommonLocal::SafeMode( void ) {
  698. int i;
  699. for ( i = 0 ; i < com_numConsoleLines ; i++ ) {
  700. if ( !idStr::Icmp( com_consoleLines[ i ].Argv(0), "safe" )
  701. || !idStr::Icmp( com_consoleLines[ i ].Argv(0), "cvar_restart" ) ) {
  702. com_consoleLines[ i ].Clear();
  703. return true;
  704. }
  705. }
  706. return false;
  707. }
  708. /*
  709. ==================
  710. idCommonLocal::CheckToolMode
  711. Check for "renderbump", "dmap", or "editor" on the command line,
  712. and force fullscreen off in those cases
  713. ==================
  714. */
  715. void idCommonLocal::CheckToolMode( void ) {
  716. int i;
  717. for ( i = 0 ; i < com_numConsoleLines ; i++ ) {
  718. if ( !idStr::Icmp( com_consoleLines[ i ].Argv(0), "guieditor" ) ) {
  719. com_editors |= EDITOR_GUI;
  720. }
  721. else if ( !idStr::Icmp( com_consoleLines[ i ].Argv(0), "debugger" ) ) {
  722. com_editors |= EDITOR_DEBUGGER;
  723. }
  724. else if ( !idStr::Icmp( com_consoleLines[ i ].Argv(0), "editor" ) ) {
  725. com_editors |= EDITOR_RADIANT;
  726. }
  727. // Nerve: Add support for the material editor
  728. else if ( !idStr::Icmp( com_consoleLines[ i ].Argv(0), "materialEditor" ) ) {
  729. com_editors |= EDITOR_MATERIAL;
  730. }
  731. if ( !idStr::Icmp( com_consoleLines[ i ].Argv(0), "renderbump" )
  732. || !idStr::Icmp( com_consoleLines[ i ].Argv(0), "editor" )
  733. || !idStr::Icmp( com_consoleLines[ i ].Argv(0), "guieditor" )
  734. || !idStr::Icmp( com_consoleLines[ i ].Argv(0), "debugger" )
  735. || !idStr::Icmp( com_consoleLines[ i ].Argv(0), "dmap" )
  736. || !idStr::Icmp( com_consoleLines[ i ].Argv(0), "materialEditor" )
  737. ) {
  738. cvarSystem->SetCVarBool( "r_fullscreen", false );
  739. return;
  740. }
  741. }
  742. }
  743. /*
  744. ==================
  745. idCommonLocal::StartupVariable
  746. Searches for command line parameters that are set commands.
  747. If match is not NULL, only that cvar will be looked for.
  748. That is necessary because cddir and basedir need to be set
  749. before the filesystem is started, but all other sets should
  750. be after execing the config and default.
  751. ==================
  752. */
  753. void idCommonLocal::StartupVariable( const char *match, bool once ) {
  754. int i;
  755. const char *s;
  756. i = 0;
  757. while ( i < com_numConsoleLines ) {
  758. if ( strcmp( com_consoleLines[ i ].Argv( 0 ), "set" ) ) {
  759. i++;
  760. continue;
  761. }
  762. s = com_consoleLines[ i ].Argv(1);
  763. if ( !match || !idStr::Icmp( s, match ) ) {
  764. cvarSystem->SetCVarString( s, com_consoleLines[ i ].Argv( 2 ) );
  765. if ( once ) {
  766. // kill the line
  767. int j = i + 1;
  768. while ( j < com_numConsoleLines ) {
  769. com_consoleLines[ j - 1 ] = com_consoleLines[ j ];
  770. j++;
  771. }
  772. com_numConsoleLines--;
  773. continue;
  774. }
  775. }
  776. i++;
  777. }
  778. }
  779. /*
  780. ==================
  781. idCommonLocal::AddStartupCommands
  782. Adds command line parameters as script statements
  783. Commands are separated by + signs
  784. Returns true if any late commands were added, which
  785. will keep the demoloop from immediately starting
  786. ==================
  787. */
  788. bool idCommonLocal::AddStartupCommands( void ) {
  789. int i;
  790. bool added;
  791. added = false;
  792. // quote every token, so args with semicolons can work
  793. for ( i = 0; i < com_numConsoleLines; i++ ) {
  794. if ( !com_consoleLines[i].Argc() ) {
  795. continue;
  796. }
  797. // set commands won't override menu startup
  798. if ( idStr::Icmpn( com_consoleLines[i].Argv(0), "set", 3 ) ) {
  799. added = true;
  800. }
  801. // directly as tokenized so nothing gets screwed
  802. cmdSystem->BufferCommandArgs( CMD_EXEC_APPEND, com_consoleLines[i] );
  803. }
  804. return added;
  805. }
  806. /*
  807. =================
  808. idCommonLocal::InitTool
  809. =================
  810. */
  811. void idCommonLocal::InitTool( const toolFlag_t tool, const idDict *dict ) {
  812. #ifdef ID_ALLOW_TOOLS
  813. if ( tool & EDITOR_SOUND ) {
  814. SoundEditorInit( dict );
  815. } else if ( tool & EDITOR_LIGHT ) {
  816. LightEditorInit( dict );
  817. } else if ( tool & EDITOR_PARTICLE ) {
  818. ParticleEditorInit( dict );
  819. } else if ( tool & EDITOR_AF ) {
  820. AFEditorInit( dict );
  821. }
  822. #endif
  823. }
  824. /*
  825. ==================
  826. idCommonLocal::ActivateTool
  827. Activates or Deactivates a tool
  828. ==================
  829. */
  830. void idCommonLocal::ActivateTool( bool active ) {
  831. com_editorActive = active;
  832. Sys_GrabMouseCursor( !active );
  833. }
  834. /*
  835. ==================
  836. idCommonLocal::WriteFlaggedCVarsToFile
  837. ==================
  838. */
  839. void idCommonLocal::WriteFlaggedCVarsToFile( const char *filename, int flags, const char *setCmd ) {
  840. idFile *f;
  841. f = fileSystem->OpenFileWrite( filename );
  842. if ( !f ) {
  843. Printf( "Couldn't write %s.\n", filename );
  844. return;
  845. }
  846. cvarSystem->WriteFlaggedVariables( flags, setCmd, f );
  847. fileSystem->CloseFile( f );
  848. }
  849. /*
  850. ==================
  851. idCommonLocal::WriteConfigToFile
  852. ==================
  853. */
  854. void idCommonLocal::WriteConfigToFile( const char *filename ) {
  855. idFile *f;
  856. #ifdef ID_WRITE_VERSION
  857. ID_TIME_T t;
  858. char *curtime;
  859. idStr runtag;
  860. idFile_Memory compressed( "compressed" );
  861. idBase64 out;
  862. #endif
  863. f = fileSystem->OpenFileWrite( filename );
  864. if ( !f ) {
  865. Printf ("Couldn't write %s.\n", filename );
  866. return;
  867. }
  868. #ifdef ID_WRITE_VERSION
  869. assert( config_compressor );
  870. t = time( NULL );
  871. curtime = ctime( &t );
  872. sprintf( runtag, "%s - %s", cvarSystem->GetCVarString( "si_version" ), curtime );
  873. config_compressor->Init( &compressed, true, 8 );
  874. config_compressor->Write( runtag.c_str(), runtag.Length() );
  875. config_compressor->FinishCompress( );
  876. out.Encode( (const byte *)compressed.GetDataPtr(), compressed.Length() );
  877. f->Printf( "// %s\n", out.c_str() );
  878. #endif
  879. idKeyInput::WriteBindings( f );
  880. cvarSystem->WriteFlaggedVariables( CVAR_ARCHIVE, "seta", f );
  881. fileSystem->CloseFile( f );
  882. }
  883. /*
  884. ===============
  885. idCommonLocal::WriteConfiguration
  886. Writes key bindings and archived cvars to config file if modified
  887. ===============
  888. */
  889. void idCommonLocal::WriteConfiguration( void ) {
  890. // if we are quiting without fully initializing, make sure
  891. // we don't write out anything
  892. if ( !com_fullyInitialized ) {
  893. return;
  894. }
  895. if ( !( cvarSystem->GetModifiedFlags() & CVAR_ARCHIVE ) ) {
  896. return;
  897. }
  898. cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE );
  899. // disable printing out the "Writing to:" message
  900. bool developer = com_developer.GetBool();
  901. com_developer.SetBool( false );
  902. WriteConfigToFile( CONFIG_FILE );
  903. session->WriteCDKey( );
  904. // restore the developer cvar
  905. com_developer.SetBool( developer );
  906. }
  907. /*
  908. ===============
  909. KeysFromBinding()
  910. Returns the key bound to the command
  911. ===============
  912. */
  913. const char* idCommonLocal::KeysFromBinding( const char *bind ) {
  914. return idKeyInput::KeysFromBinding( bind );
  915. }
  916. /*
  917. ===============
  918. BindingFromKey()
  919. Returns the binding bound to key
  920. ===============
  921. */
  922. const char* idCommonLocal::BindingFromKey( const char *key ) {
  923. return idKeyInput::BindingFromKey( key );
  924. }
  925. /*
  926. ===============
  927. ButtonState()
  928. Returns the state of the button
  929. ===============
  930. */
  931. int idCommonLocal::ButtonState( int key ) {
  932. return usercmdGen->ButtonState(key);
  933. }
  934. /*
  935. ===============
  936. ButtonState()
  937. Returns the state of the key
  938. ===============
  939. */
  940. int idCommonLocal::KeyState( int key ) {
  941. return usercmdGen->KeyState(key);
  942. }
  943. //============================================================================
  944. #ifdef ID_ALLOW_TOOLS
  945. /*
  946. ==================
  947. Com_Editor_f
  948. we can start the editor dynamically, but we won't ever get back
  949. ==================
  950. */
  951. static void Com_Editor_f( const idCmdArgs &args ) {
  952. RadiantInit();
  953. }
  954. /*
  955. =============
  956. Com_ScriptDebugger_f
  957. =============
  958. */
  959. static void Com_ScriptDebugger_f( const idCmdArgs &args ) {
  960. // Make sure it wasnt on the command line
  961. if ( !( com_editors & EDITOR_DEBUGGER ) ) {
  962. common->Printf( "Script debugger is currently disabled\n" );
  963. // DebuggerClientLaunch();
  964. }
  965. }
  966. /*
  967. =============
  968. Com_EditGUIs_f
  969. =============
  970. */
  971. static void Com_EditGUIs_f( const idCmdArgs &args ) {
  972. GUIEditorInit();
  973. }
  974. /*
  975. =============
  976. Com_MaterialEditor_f
  977. =============
  978. */
  979. static void Com_MaterialEditor_f( const idCmdArgs &args ) {
  980. // Turn off sounds
  981. soundSystem->SetMute( true );
  982. MaterialEditorInit();
  983. }
  984. #endif // ID_ALLOW_TOOLS
  985. /*
  986. ============
  987. idCmdSystemLocal::PrintMemInfo_f
  988. This prints out memory debugging data
  989. ============
  990. */
  991. static void PrintMemInfo_f( const idCmdArgs &args ) {
  992. MemInfo_t mi;
  993. memset( &mi, 0, sizeof( mi ) );
  994. mi.filebase = session->GetCurrentMapName();
  995. renderSystem->PrintMemInfo( &mi ); // textures and models
  996. soundSystem->PrintMemInfo( &mi ); // sounds
  997. common->Printf( " Used image memory: %s bytes\n", idStr::FormatNumber( mi.imageAssetsTotal ).c_str() );
  998. mi.assetTotals += mi.imageAssetsTotal;
  999. common->Printf( " Used model memory: %s bytes\n", idStr::FormatNumber( mi.modelAssetsTotal ).c_str() );
  1000. mi.assetTotals += mi.modelAssetsTotal;
  1001. common->Printf( " Used sound memory: %s bytes\n", idStr::FormatNumber( mi.soundAssetsTotal ).c_str() );
  1002. mi.assetTotals += mi.soundAssetsTotal;
  1003. common->Printf( " Used asset memory: %s bytes\n", idStr::FormatNumber( mi.assetTotals ).c_str() );
  1004. // write overview file
  1005. idFile *f;
  1006. f = fileSystem->OpenFileAppend( "maps/printmeminfo.txt" );
  1007. if ( !f ) {
  1008. return;
  1009. }
  1010. f->Printf( "total(%s ) image(%s ) model(%s ) sound(%s ): %s\n", idStr::FormatNumber( mi.assetTotals ).c_str(), idStr::FormatNumber( mi.imageAssetsTotal ).c_str(),
  1011. idStr::FormatNumber( mi.modelAssetsTotal ).c_str(), idStr::FormatNumber( mi.soundAssetsTotal ).c_str(), mi.filebase.c_str() );
  1012. fileSystem->CloseFile( f );
  1013. }
  1014. #ifdef ID_ALLOW_TOOLS
  1015. /*
  1016. ==================
  1017. Com_EditLights_f
  1018. ==================
  1019. */
  1020. static void Com_EditLights_f( const idCmdArgs &args ) {
  1021. LightEditorInit( NULL );
  1022. cvarSystem->SetCVarInteger( "g_editEntityMode", 1 );
  1023. }
  1024. /*
  1025. ==================
  1026. Com_EditSounds_f
  1027. ==================
  1028. */
  1029. static void Com_EditSounds_f( const idCmdArgs &args ) {
  1030. SoundEditorInit( NULL );
  1031. cvarSystem->SetCVarInteger( "g_editEntityMode", 2 );
  1032. }
  1033. /*
  1034. ==================
  1035. Com_EditDecls_f
  1036. ==================
  1037. */
  1038. static void Com_EditDecls_f( const idCmdArgs &args ) {
  1039. DeclBrowserInit( NULL );
  1040. }
  1041. /*
  1042. ==================
  1043. Com_EditAFs_f
  1044. ==================
  1045. */
  1046. static void Com_EditAFs_f( const idCmdArgs &args ) {
  1047. AFEditorInit( NULL );
  1048. }
  1049. /*
  1050. ==================
  1051. Com_EditParticles_f
  1052. ==================
  1053. */
  1054. static void Com_EditParticles_f( const idCmdArgs &args ) {
  1055. ParticleEditorInit( NULL );
  1056. }
  1057. /*
  1058. ==================
  1059. Com_EditScripts_f
  1060. ==================
  1061. */
  1062. static void Com_EditScripts_f( const idCmdArgs &args ) {
  1063. ScriptEditorInit( NULL );
  1064. }
  1065. /*
  1066. ==================
  1067. Com_EditPDAs_f
  1068. ==================
  1069. */
  1070. static void Com_EditPDAs_f( const idCmdArgs &args ) {
  1071. PDAEditorInit( NULL );
  1072. }
  1073. #endif // ID_ALLOW_TOOLS
  1074. /*
  1075. ==================
  1076. Com_Error_f
  1077. Just throw a fatal error to test error shutdown procedures.
  1078. ==================
  1079. */
  1080. static void Com_Error_f( const idCmdArgs &args ) {
  1081. if ( !com_developer.GetBool() ) {
  1082. commonLocal.Printf( "error may only be used in developer mode\n" );
  1083. return;
  1084. }
  1085. if ( args.Argc() > 1 ) {
  1086. commonLocal.FatalError( "Testing fatal error" );
  1087. } else {
  1088. commonLocal.Error( "Testing drop error" );
  1089. }
  1090. }
  1091. /*
  1092. ==================
  1093. Com_Freeze_f
  1094. Just freeze in place for a given number of seconds to test error recovery.
  1095. ==================
  1096. */
  1097. static void Com_Freeze_f( const idCmdArgs &args ) {
  1098. float s;
  1099. int start, now;
  1100. if ( args.Argc() != 2 ) {
  1101. commonLocal.Printf( "freeze <seconds>\n" );
  1102. return;
  1103. }
  1104. if ( !com_developer.GetBool() ) {
  1105. commonLocal.Printf( "freeze may only be used in developer mode\n" );
  1106. return;
  1107. }
  1108. s = atof( args.Argv(1) );
  1109. start = eventLoop->Milliseconds();
  1110. while ( 1 ) {
  1111. now = eventLoop->Milliseconds();
  1112. if ( ( now - start ) * 0.001f > s ) {
  1113. break;
  1114. }
  1115. }
  1116. }
  1117. /*
  1118. =================
  1119. Com_Crash_f
  1120. A way to force a bus error for development reasons
  1121. =================
  1122. */
  1123. static void Com_Crash_f( const idCmdArgs &args ) {
  1124. if ( !com_developer.GetBool() ) {
  1125. commonLocal.Printf( "crash may only be used in developer mode\n" );
  1126. return;
  1127. }
  1128. * ( int * ) 0 = 0x12345678;
  1129. }
  1130. /*
  1131. =================
  1132. Com_Quit_f
  1133. =================
  1134. */
  1135. static void Com_Quit_f( const idCmdArgs &args ) {
  1136. commonLocal.Quit();
  1137. }
  1138. /*
  1139. ===============
  1140. Com_WriteConfig_f
  1141. Write the config file to a specific name
  1142. ===============
  1143. */
  1144. void Com_WriteConfig_f( const idCmdArgs &args ) {
  1145. idStr filename;
  1146. if ( args.Argc() != 2 ) {
  1147. commonLocal.Printf( "Usage: writeconfig <filename>\n" );
  1148. return;
  1149. }
  1150. filename = args.Argv(1);
  1151. filename.DefaultFileExtension( ".cfg" );
  1152. commonLocal.Printf( "Writing %s.\n", filename.c_str() );
  1153. commonLocal.WriteConfigToFile( filename );
  1154. }
  1155. /*
  1156. =================
  1157. Com_SetMachineSpecs_f
  1158. =================
  1159. */
  1160. void Com_SetMachineSpec_f( const idCmdArgs &args ) {
  1161. commonLocal.SetMachineSpec();
  1162. }
  1163. /*
  1164. =================
  1165. Com_ExecMachineSpecs_f
  1166. =================
  1167. */
  1168. #ifdef MACOS_X
  1169. void OSX_GetVideoCard( int& outVendorId, int& outDeviceId );
  1170. bool OSX_GetCPUIdentification( int& cpuId, bool& oldArchitecture );
  1171. #endif
  1172. void Com_ExecMachineSpec_f( const idCmdArgs &args ) {
  1173. if ( com_machineSpec.GetInteger() == 3 ) {
  1174. cvarSystem->SetCVarInteger( "image_anisotropy", 1, CVAR_ARCHIVE );
  1175. cvarSystem->SetCVarInteger( "image_lodbias", 0, CVAR_ARCHIVE );
  1176. cvarSystem->SetCVarInteger( "image_forceDownSize", 0, CVAR_ARCHIVE );
  1177. cvarSystem->SetCVarInteger( "image_roundDown", 1, CVAR_ARCHIVE );
  1178. cvarSystem->SetCVarInteger( "image_preload", 1, CVAR_ARCHIVE );
  1179. cvarSystem->SetCVarInteger( "image_useAllFormats", 1, CVAR_ARCHIVE );
  1180. cvarSystem->SetCVarInteger( "image_downSizeSpecular", 0, CVAR_ARCHIVE );
  1181. cvarSystem->SetCVarInteger( "image_downSizeBump", 0, CVAR_ARCHIVE );
  1182. cvarSystem->SetCVarInteger( "image_downSizeSpecularLimit", 64, CVAR_ARCHIVE );
  1183. cvarSystem->SetCVarInteger( "image_downSizeBumpLimit", 256, CVAR_ARCHIVE );
  1184. cvarSystem->SetCVarInteger( "image_usePrecompressedTextures", 0, CVAR_ARCHIVE );
  1185. cvarSystem->SetCVarInteger( "image_downsize", 0 , CVAR_ARCHIVE );
  1186. cvarSystem->SetCVarString( "image_filter", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE );
  1187. cvarSystem->SetCVarInteger( "image_anisotropy", 8, CVAR_ARCHIVE );
  1188. cvarSystem->SetCVarInteger( "image_useCompression", 0, CVAR_ARCHIVE );
  1189. cvarSystem->SetCVarInteger( "image_ignoreHighQuality", 0, CVAR_ARCHIVE );
  1190. cvarSystem->SetCVarInteger( "s_maxSoundsPerShader", 0, CVAR_ARCHIVE );
  1191. cvarSystem->SetCVarInteger( "r_mode", 5, CVAR_ARCHIVE );
  1192. cvarSystem->SetCVarInteger( "image_useNormalCompression", 0, CVAR_ARCHIVE );
  1193. cvarSystem->SetCVarInteger( "r_multiSamples", 0, CVAR_ARCHIVE );
  1194. } else if ( com_machineSpec.GetInteger() == 2 ) {
  1195. cvarSystem->SetCVarString( "image_filter", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE );
  1196. cvarSystem->SetCVarInteger( "image_anisotropy", 1, CVAR_ARCHIVE );
  1197. cvarSystem->SetCVarInteger( "image_lodbias", 0, CVAR_ARCHIVE );
  1198. cvarSystem->SetCVarInteger( "image_forceDownSize", 0, CVAR_ARCHIVE );
  1199. cvarSystem->SetCVarInteger( "image_roundDown", 1, CVAR_ARCHIVE );
  1200. cvarSystem->SetCVarInteger( "image_preload", 1, CVAR_ARCHIVE );
  1201. cvarSystem->SetCVarInteger( "image_useAllFormats", 1, CVAR_ARCHIVE );
  1202. cvarSystem->SetCVarInteger( "image_downSizeSpecular", 0, CVAR_ARCHIVE );
  1203. cvarSystem->SetCVarInteger( "image_downSizeBump", 0, CVAR_ARCHIVE );
  1204. cvarSystem->SetCVarInteger( "image_downSizeSpecularLimit", 64, CVAR_ARCHIVE );
  1205. cvarSystem->SetCVarInteger( "image_downSizeBumpLimit", 256, CVAR_ARCHIVE );
  1206. cvarSystem->SetCVarInteger( "image_usePrecompressedTextures", 1, CVAR_ARCHIVE );
  1207. cvarSystem->SetCVarInteger( "image_downsize", 0, CVAR_ARCHIVE );
  1208. cvarSystem->SetCVarInteger( "image_anisotropy", 8, CVAR_ARCHIVE );
  1209. cvarSystem->SetCVarInteger( "image_useCompression", 1, CVAR_ARCHIVE );
  1210. cvarSystem->SetCVarInteger( "image_ignoreHighQuality", 0, CVAR_ARCHIVE );
  1211. cvarSystem->SetCVarInteger( "s_maxSoundsPerShader", 0, CVAR_ARCHIVE );
  1212. cvarSystem->SetCVarInteger( "image_useNormalCompression", 0, CVAR_ARCHIVE );
  1213. cvarSystem->SetCVarInteger( "r_mode", 4, CVAR_ARCHIVE );
  1214. cvarSystem->SetCVarInteger( "r_multiSamples", 0, CVAR_ARCHIVE );
  1215. } else if ( com_machineSpec.GetInteger() == 1 ) {
  1216. cvarSystem->SetCVarString( "image_filter", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE );
  1217. cvarSystem->SetCVarInteger( "image_anisotropy", 1, CVAR_ARCHIVE );
  1218. cvarSystem->SetCVarInteger( "image_lodbias", 0, CVAR_ARCHIVE );
  1219. cvarSystem->SetCVarInteger( "image_downSize", 0, CVAR_ARCHIVE );
  1220. cvarSystem->SetCVarInteger( "image_forceDownSize", 0, CVAR_ARCHIVE );
  1221. cvarSystem->SetCVarInteger( "image_roundDown", 1, CVAR_ARCHIVE );
  1222. cvarSystem->SetCVarInteger( "image_preload", 1, CVAR_ARCHIVE );
  1223. cvarSystem->SetCVarInteger( "image_useCompression", 1, CVAR_ARCHIVE );
  1224. cvarSystem->SetCVarInteger( "image_useAllFormats", 1, CVAR_ARCHIVE );
  1225. cvarSystem->SetCVarInteger( "image_usePrecompressedTextures", 1, CVAR_ARCHIVE );
  1226. cvarSystem->SetCVarInteger( "image_downSizeSpecular", 0, CVAR_ARCHIVE );
  1227. cvarSystem->SetCVarInteger( "image_downSizeBump", 0, CVAR_ARCHIVE );
  1228. cvarSystem->SetCVarInteger( "image_downSizeSpecularLimit", 64, CVAR_ARCHIVE );
  1229. cvarSystem->SetCVarInteger( "image_downSizeBumpLimit", 256, CVAR_ARCHIVE );
  1230. cvarSystem->SetCVarInteger( "image_useNormalCompression", 2, CVAR_ARCHIVE );
  1231. cvarSystem->SetCVarInteger( "r_mode", 3, CVAR_ARCHIVE );
  1232. cvarSystem->SetCVarInteger( "r_multiSamples", 0, CVAR_ARCHIVE );
  1233. } else {
  1234. cvarSystem->SetCVarString( "image_filter", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE );
  1235. cvarSystem->SetCVarInteger( "image_anisotropy", 1, CVAR_ARCHIVE );
  1236. cvarSystem->SetCVarInteger( "image_lodbias", 0, CVAR_ARCHIVE );
  1237. cvarSystem->SetCVarInteger( "image_roundDown", 1, CVAR_ARCHIVE );
  1238. cvarSystem->SetCVarInteger( "image_preload", 1, CVAR_ARCHIVE );
  1239. cvarSystem->SetCVarInteger( "image_useAllFormats", 1, CVAR_ARCHIVE );
  1240. cvarSystem->SetCVarInteger( "image_usePrecompressedTextures", 1, CVAR_ARCHIVE );
  1241. cvarSystem->SetCVarInteger( "image_downSize", 1, CVAR_ARCHIVE );
  1242. cvarSystem->SetCVarInteger( "image_anisotropy", 0, CVAR_ARCHIVE );
  1243. cvarSystem->SetCVarInteger( "image_useCompression", 1, CVAR_ARCHIVE );
  1244. cvarSystem->SetCVarInteger( "image_ignoreHighQuality", 1, CVAR_ARCHIVE );
  1245. cvarSystem->SetCVarInteger( "s_maxSoundsPerShader", 1, CVAR_ARCHIVE );
  1246. cvarSystem->SetCVarInteger( "image_downSizeSpecular", 1, CVAR_ARCHIVE );
  1247. cvarSystem->SetCVarInteger( "image_downSizeBump", 1, CVAR_ARCHIVE );
  1248. cvarSystem->SetCVarInteger( "image_downSizeSpecularLimit", 64, CVAR_ARCHIVE );
  1249. cvarSystem->SetCVarInteger( "image_downSizeBumpLimit", 256, CVAR_ARCHIVE );
  1250. cvarSystem->SetCVarInteger( "r_mode", 3 , CVAR_ARCHIVE );
  1251. cvarSystem->SetCVarInteger( "image_useNormalCompression", 2, CVAR_ARCHIVE );
  1252. cvarSystem->SetCVarInteger( "r_multiSamples", 0, CVAR_ARCHIVE );
  1253. }
  1254. if ( Sys_GetVideoRam() < 128 ) {
  1255. cvarSystem->SetCVarBool( "image_ignoreHighQuality", true, CVAR_ARCHIVE );
  1256. cvarSystem->SetCVarInteger( "image_downSize", 1, CVAR_ARCHIVE );
  1257. cvarSystem->SetCVarInteger( "image_downSizeLimit", 256, CVAR_ARCHIVE );
  1258. cvarSystem->SetCVarInteger( "image_downSizeSpecular", 1, CVAR_ARCHIVE );
  1259. cvarSystem->SetCVarInteger( "image_downSizeSpecularLimit", 64, CVAR_ARCHIVE );
  1260. cvarSystem->SetCVarInteger( "image_downSizeBump", 1, CVAR_ARCHIVE );
  1261. cvarSystem->SetCVarInteger( "image_downSizeBumpLimit", 256, CVAR_ARCHIVE );
  1262. }
  1263. if ( Sys_GetSystemRam() < 512 ) {
  1264. cvarSystem->SetCVarBool( "image_ignoreHighQuality", true, CVAR_ARCHIVE );
  1265. cvarSystem->SetCVarInteger( "s_maxSoundsPerShader", 1, CVAR_ARCHIVE );
  1266. cvarSystem->SetCVarInteger( "image_downSize", 1, CVAR_ARCHIVE );
  1267. cvarSystem->SetCVarInteger( "image_downSizeLimit", 256, CVAR_ARCHIVE );
  1268. cvarSystem->SetCVarInteger( "image_downSizeSpecular", 1, CVAR_ARCHIVE );
  1269. cvarSystem->SetCVarInteger( "image_downSizeSpecularLimit", 64, CVAR_ARCHIVE );
  1270. cvarSystem->SetCVarBool( "com_purgeAll", true, CVAR_ARCHIVE );
  1271. cvarSystem->SetCVarBool( "r_forceLoadImages", true, CVAR_ARCHIVE );
  1272. } else {
  1273. cvarSystem->SetCVarBool( "com_purgeAll", false, CVAR_ARCHIVE );
  1274. cvarSystem->SetCVarBool( "r_forceLoadImages", false, CVAR_ARCHIVE );
  1275. }
  1276. bool oldCard = false;
  1277. bool nv10or20 = false;
  1278. renderSystem->GetCardCaps( oldCard, nv10or20 );
  1279. if ( oldCard ) {
  1280. cvarSystem->SetCVarBool( "g_decals", false, CVAR_ARCHIVE );
  1281. cvarSystem->SetCVarBool( "g_projectileLights", false, CVAR_ARCHIVE );
  1282. cvarSystem->SetCVarBool( "g_doubleVision", false, CVAR_ARCHIVE );
  1283. cvarSystem->SetCVarBool( "g_muzzleFlash", false, CVAR_ARCHIVE );
  1284. } else {
  1285. cvarSystem->SetCVarBool( "g_decals", true, CVAR_ARCHIVE );
  1286. cvarSystem->SetCVarBool( "g_projectileLights", true, CVAR_ARCHIVE );
  1287. cvarSystem->SetCVarBool( "g_doubleVision", true, CVAR_ARCHIVE );
  1288. cvarSystem->SetCVarBool( "g_muzzleFlash", true, CVAR_ARCHIVE );
  1289. }
  1290. if ( nv10or20 ) {
  1291. cvarSystem->SetCVarInteger( "image_useNormalCompression", 1, CVAR_ARCHIVE );
  1292. }
  1293. #if MACOS_X
  1294. // On low settings, G4 systems & 64MB FX5200/NV34 Systems should default shadows off
  1295. bool oldArch;
  1296. int vendorId, deviceId, cpuId;
  1297. OSX_GetVideoCard( vendorId, deviceId );
  1298. OSX_GetCPUIdentification( cpuId, oldArch );
  1299. bool isFX5200 = vendorId == 0x10DE && ( deviceId & 0x0FF0 ) == 0x0320;
  1300. if ( ( oldArch || ( isFX5200 && Sys_GetVideoRam() < 128 ) ) && com_machineSpec.GetInteger() == 0 ) {
  1301. cvarSystem->SetCVarBool( "r_shadows", false, CVAR_ARCHIVE );
  1302. } else {
  1303. cvarSystem->SetCVarBool( "r_shadows", true, CVAR_ARCHIVE );
  1304. }
  1305. #endif
  1306. }
  1307. /*
  1308. =================
  1309. Com_ReloadEngine_f
  1310. =================
  1311. */
  1312. void Com_ReloadEngine_f( const idCmdArgs &args ) {
  1313. bool menu = false;
  1314. if ( !commonLocal.IsInitialized() ) {
  1315. return;
  1316. }
  1317. if ( args.Argc() > 1 && idStr::Icmp( args.Argv( 1 ), "menu" ) == 0 ) {
  1318. menu = true;
  1319. }
  1320. common->Printf( "============= ReloadEngine start =============\n" );
  1321. if ( !menu ) {
  1322. Sys_ShowConsole( 1, false );
  1323. }
  1324. commonLocal.ShutdownGame( true );
  1325. commonLocal.InitGame();
  1326. if ( !menu && !idAsyncNetwork::serverDedicated.GetBool() ) {
  1327. Sys_ShowConsole( 0, false );
  1328. }
  1329. common->Printf( "============= ReloadEngine end ===============\n" );
  1330. if ( !cmdSystem->PostReloadEngine() ) {
  1331. if ( menu ) {
  1332. session->StartMenu( );
  1333. }
  1334. }
  1335. }
  1336. /*
  1337. ===============
  1338. idCommonLocal::GetLanguageDict
  1339. ===============
  1340. */
  1341. const idLangDict *idCommonLocal::GetLanguageDict( void ) {
  1342. return &languageDict;
  1343. }
  1344. /*
  1345. ===============
  1346. idCommonLocal::FilterLangList
  1347. ===============
  1348. */
  1349. void idCommonLocal::FilterLangList( idStrList* list, idStr lang ) {
  1350. idStr temp;
  1351. for( int i = 0; i < list->Num(); i++ ) {
  1352. temp = (*list)[i];
  1353. temp = temp.Right(temp.Length()-strlen("strings/"));
  1354. temp = temp.Left(lang.Length());
  1355. if(idStr::Icmp(temp, lang) != 0) {
  1356. list->RemoveIndex(i);
  1357. i--;
  1358. }
  1359. }
  1360. }
  1361. /*
  1362. ===============
  1363. idCommonLocal::InitLanguageDict
  1364. ===============
  1365. */
  1366. void idCommonLocal::InitLanguageDict( void ) {
  1367. idStr fileName;
  1368. languageDict.Clear();
  1369. //D3XP: Instead of just loading a single lang file for each language
  1370. //we are going to load all files that begin with the language name
  1371. //similar to the way pak files work. So you can place english001.lang
  1372. //to add new strings to the english language dictionary
  1373. idFileList* langFiles;
  1374. langFiles = fileSystem->ListFilesTree( "strings", ".lang", true );
  1375. idStrList langList = langFiles->GetList();
  1376. StartupVariable( "sys_lang", false ); // let it be set on the command line - this is needed because this init happens very early
  1377. idStr langName = cvarSystem->GetCVarString( "sys_lang" );
  1378. //Loop through the list and filter
  1379. idStrList currentLangList = langList;
  1380. FilterLangList(&currentLangList, langName);
  1381. if ( currentLangList.Num() == 0 ) {
  1382. // reset cvar to default and try to load again
  1383. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "reset sys_lang" );
  1384. langName = cvarSystem->GetCVarString( "sys_lang" );
  1385. currentLangList = langList;
  1386. FilterLangList(&currentLangList, langName);
  1387. }
  1388. for( int i = 0; i < currentLangList.Num(); i++ ) {
  1389. //common->Printf("%s\n", currentLangList[i].c_str());
  1390. languageDict.Load( currentLangList[i], false );
  1391. }
  1392. fileSystem->FreeFileList(langFiles);
  1393. Sys_InitScanTable();
  1394. }
  1395. /*
  1396. ===============
  1397. idCommonLocal::LocalizeSpecificMapData
  1398. ===============
  1399. */
  1400. void idCommonLocal::LocalizeSpecificMapData( const char *fileName, idLangDict &langDict, const idLangDict &replaceArgs ) {
  1401. idStr out, ws, work;
  1402. idMapFile map;
  1403. if ( map.Parse( fileName, false, false ) ) {
  1404. int count = map.GetNumEntities();
  1405. for ( int i = 0; i < count; i++ ) {
  1406. idMapEntity *ent = map.GetEntity( i );
  1407. if ( ent ) {
  1408. for ( int j = 0; j < replaceArgs.GetNumKeyVals(); j++ ) {
  1409. const idLangKeyValue *kv = replaceArgs.GetKeyVal( j );
  1410. const char *temp = ent->epairs.GetString( kv->key );
  1411. if ( temp && *temp ) {
  1412. idStr val = kv->value;
  1413. if ( val == temp ) {
  1414. ent->epairs.Set( kv->key, langDict.AddString( temp ) );
  1415. }
  1416. }
  1417. }
  1418. }
  1419. }
  1420. map.Write( fileName, ".map" );
  1421. }
  1422. }
  1423. /*
  1424. ===============
  1425. idCommonLocal::LocalizeMapData
  1426. ===============
  1427. */
  1428. void idCommonLocal::LocalizeMapData( const char *fileName, idLangDict &langDict ) {
  1429. const char *buffer = NULL;
  1430. idLexer src( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
  1431. common->SetRefreshOnPrint( true );
  1432. if ( fileSystem->ReadFile( fileName, (void**)&buffer ) > 0 ) {
  1433. src.LoadMemory( buffer, strlen(buffer), fileName );
  1434. if ( src.IsLoaded() ) {
  1435. common->Printf( "Processing %s\n", fileName );
  1436. idStr mapFileName;
  1437. idToken token, token2;
  1438. idLangDict replaceArgs;
  1439. while ( src.ReadToken( &token ) ) {
  1440. mapFileName = token;
  1441. replaceArgs.Clear();
  1442. src.ExpectTokenString( "{" );
  1443. while ( src.ReadToken( &token) ) {
  1444. if ( token == "}" ) {
  1445. break;
  1446. }
  1447. if ( src.ReadToken( &token2 ) ) {
  1448. if ( token2 == "}" ) {
  1449. break;
  1450. }
  1451. replaceArgs.AddKeyVal( token, token2 );
  1452. }
  1453. }
  1454. common->Printf( " localizing map %s...\n", mapFileName.c_str() );
  1455. LocalizeSpecificMapData( mapFileName, langDict, replaceArgs );
  1456. }
  1457. }
  1458. fileSystem->FreeFile( (void*)buffer );
  1459. }
  1460. common->SetRefreshOnPrint( false );
  1461. }
  1462. /*
  1463. ===============
  1464. idCommonLocal::LocalizeGui
  1465. ===============
  1466. */
  1467. void idCommonLocal::LocalizeGui( const char *fileName, idLangDict &langDict ) {
  1468. idStr out, ws, work;
  1469. const char *buffer = NULL;
  1470. out.Empty();
  1471. int k;
  1472. char ch;
  1473. char slash = '\\';
  1474. char tab = 't';
  1475. char nl = 'n';
  1476. idLexer src( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
  1477. if ( fileSystem->ReadFile( fileName, (void**)&buffer ) > 0 ) {
  1478. src.LoadMemory( buffer, strlen(buffer), fileName );
  1479. if ( src.IsLoaded() ) {
  1480. idFile *outFile = fileSystem->OpenFileWrite( fileName );
  1481. common->Printf( "Processing %s\n", fileName );
  1482. session->UpdateScreen();
  1483. idToken token;
  1484. while( src.ReadToken( &token ) ) {
  1485. src.GetLastWhiteSpace( ws );
  1486. out += ws;
  1487. if ( token.type == TT_STRING ) {
  1488. out += va( "\"%s\"", token.c_str() );
  1489. } else {
  1490. out += token;
  1491. }
  1492. if ( out.Length() > 200000 ) {
  1493. outFile->Write( out.c_str(), out.Length() );
  1494. out = "";
  1495. }
  1496. work = token.Right( 6 );
  1497. if ( token.Icmp( "text" ) == 0 || work.Icmp( "::text" ) == 0 || token.Icmp( "choices" ) == 0 ) {
  1498. if ( src.ReadToken( &token ) ) {
  1499. // see if already exists, if so save that id to this position in this file
  1500. // otherwise add this to the list and save the id to this position in this file
  1501. src.GetLastWhiteSpace( ws );
  1502. out += ws;
  1503. token = langDict.AddString( token );
  1504. out += "\"";
  1505. for ( k = 0; k < token.Length(); k++ ) {
  1506. ch = token[k];
  1507. if ( ch == '\t' ) {
  1508. out += slash;
  1509. out += tab;
  1510. } else if ( ch == '\n' || ch == '\r' ) {
  1511. out += slash;
  1512. out += nl;
  1513. } else {
  1514. out += ch;
  1515. }
  1516. }
  1517. out += "\"";
  1518. }
  1519. } else if ( token.Icmp( "comment" ) == 0 ) {
  1520. if ( src.ReadToken( &token ) ) {
  1521. // need to write these out by hand to preserve any \n's
  1522. // see if already exists, if so save that id to this position in this file
  1523. // otherwise add this to the list and save the id to this position in this file
  1524. src.GetLastWhiteSpace( ws );
  1525. out += ws;
  1526. out += "\"";
  1527. for ( k = 0; k < token.Length(); k++ ) {
  1528. ch = token[k];
  1529. if ( ch == '\t' ) {
  1530. out += slash;
  1531. out += tab;
  1532. } else if ( ch == '\n' || ch == '\r' ) {
  1533. out += slash;
  1534. out += nl;
  1535. } else {
  1536. out += ch;
  1537. }
  1538. }
  1539. out += "\"";
  1540. }
  1541. }
  1542. }
  1543. outFile->Write( out.c_str(), out.Length() );
  1544. fileSystem->CloseFile( outFile );
  1545. }
  1546. fileSystem->FreeFile( (void*)buffer );
  1547. }
  1548. }
  1549. /*
  1550. =================
  1551. ReloadLanguage_f
  1552. =================
  1553. */
  1554. void Com_ReloadLanguage_f( const idCmdArgs &args ) {
  1555. commonLocal.InitLanguageDict();
  1556. }
  1557. typedef idHashTable<idStrList> ListHash;
  1558. void LoadMapLocalizeData(ListHash& listHash) {
  1559. idStr fileName = "map_localize.cfg";
  1560. const char *buffer = NULL;
  1561. idLexer src( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
  1562. if ( fileSystem->ReadFile( fileName, (void**)&buffer ) > 0 ) {
  1563. src.LoadMemory( buffer, strlen(buffer), fileName );
  1564. if ( src.IsLoaded() ) {
  1565. idStr classname;
  1566. idToken token;
  1567. while ( src.ReadToken( &token ) ) {
  1568. classname = token;
  1569. src.ExpectTokenString( "{" );
  1570. idStrList list;
  1571. while ( src.ReadToken( &token) ) {
  1572. if ( token == "}" ) {
  1573. break;
  1574. }
  1575. list.Append(token);
  1576. }
  1577. listHash.Set(classname, list);
  1578. }
  1579. }
  1580. fileSystem->FreeFile( (void*)buffer );
  1581. }
  1582. }
  1583. void LoadGuiParmExcludeList(idStrList& list) {
  1584. idStr fileName = "guiparm_exclude.cfg";
  1585. const char *buffer = NULL;
  1586. idLexer src( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
  1587. if ( fileSystem->ReadFile( fileName, (void**)&buffer ) > 0 ) {
  1588. src.LoadMemory( buffer, strlen(buffer), fileName );
  1589. if ( src.IsLoaded() ) {
  1590. idStr classname;
  1591. idToken token;
  1592. while ( src.ReadToken( &token ) ) {
  1593. list.Append(token);
  1594. }
  1595. }
  1596. fileSystem->FreeFile( (void*)buffer );
  1597. }
  1598. }
  1599. bool TestMapVal(idStr& str) {
  1600. //Already Localized?
  1601. if(str.Find("#str_") != -1) {
  1602. return false;
  1603. }
  1604. return true;
  1605. }
  1606. bool TestGuiParm(const char* parm, const char* value, idStrList& excludeList) {
  1607. idStr testVal = value;
  1608. //Already Localized?
  1609. if(testVal.Find("#str_") != -1) {
  1610. return false;
  1611. }
  1612. //Numeric
  1613. if(testVal.IsNumeric()) {
  1614. return false;
  1615. }
  1616. //Contains ::
  1617. if(testVal.Find("::") != -1) {
  1618. return false;
  1619. }
  1620. //Contains /
  1621. if(testVal.Find("/") != -1) {
  1622. return false;
  1623. }
  1624. if(excludeList.Find(testVal)) {
  1625. return false;
  1626. }
  1627. return true;
  1628. }
  1629. void GetFileList(const char* dir, const char* ext, idStrList& list) {
  1630. //Recurse Subdirectories
  1631. idStrList dirList;
  1632. Sys_ListFiles(dir, "/", dirList);
  1633. for(int i = 0; i < dirList.Num(); i++) {
  1634. if(dirList[i] == "." || dirList[i] == "..") {
  1635. continue;
  1636. }
  1637. idStr fullName = va("%s/%s", dir, dirList[i].c_str());
  1638. GetFileList(fullName, ext, list);
  1639. }
  1640. idStrList fileList;
  1641. Sys_ListFiles(dir, ext, fileList);
  1642. for(int i = 0; i < fileList.Num(); i++) {
  1643. idStr fullName = va("%s/%s", dir, fileList[i].c_str());
  1644. list.Append(fullName);
  1645. }
  1646. }
  1647. int LocalizeMap(const char* mapName, idLangDict &langDict, ListHash& listHash, idStrList& excludeList, bool writeFile) {
  1648. common->Printf("Localizing Map '%s'\n", mapName);
  1649. int strCount = 0;
  1650. idMapFile map;
  1651. if ( map.Parse(mapName, false, false ) ) {
  1652. int count = map.GetNumEntities();
  1653. for ( int j = 0; j < count; j++ ) {
  1654. idMapEntity *ent = map.GetEntity( j );
  1655. if ( ent ) {
  1656. idStr classname = ent->epairs.GetString("classname");
  1657. //Hack: for info_location
  1658. bool hasLocation = false;
  1659. idStrList* list;
  1660. listHash.Get(classname, &list);
  1661. if(list) {
  1662. for(int k = 0; k < list->Num(); k++) {
  1663. idStr val = ent->epairs.GetString((*list)[k], "");
  1664. if(val.Length() && classname == "info_location" && (*list)[k] == "location") {
  1665. hasLocation = true;
  1666. }
  1667. if(val.Length() && TestMapVal(val)) {
  1668. if(!hasLocation || (*list)[k] == "location") {
  1669. //Localize it!!!
  1670. strCount++;
  1671. ent->epairs.Set( (*list)[k], langDict.AddString( val ) );
  1672. }
  1673. }
  1674. }
  1675. }
  1676. listHash.Get("all", &list);
  1677. if(list) {
  1678. for(int k = 0; k < list->Num(); k++) {
  1679. idStr val = ent->epairs.GetString((*list)[k], "");
  1680. if(val.Length() && TestMapVal(val)) {
  1681. //Localize it!!!
  1682. strCount++;
  1683. ent->epairs.Set( (*list)[k], langDict.AddString( val ) );
  1684. }
  1685. }
  1686. }
  1687. //Localize the gui_parms
  1688. const idKeyValue* kv = ent->epairs.MatchPrefix("gui_parm");
  1689. while( kv ) {
  1690. if(TestGuiParm(kv->GetKey(), kv->GetValue(), excludeList)) {
  1691. //Localize It!
  1692. strCount++;
  1693. ent->epairs.Set( kv->GetKey(), langDict.AddString( kv->GetValue() ) );
  1694. }
  1695. kv = ent->epairs.MatchPrefix( "gui_parm", kv );
  1696. }
  1697. }
  1698. }
  1699. if(writeFile && strCount > 0) {
  1700. //Before we write the map file lets make a backup of the original
  1701. idStr file = fileSystem->RelativePathToOSPath(mapName);
  1702. idStr bak = file.Left(file.Length() - 4);
  1703. bak.Append(".bak_loc");
  1704. fileSystem->CopyFile( file, bak );
  1705. map.Write( mapName, ".map" );
  1706. }
  1707. }
  1708. common->Printf("Count: %d\n", strCount);
  1709. return strCount;
  1710. }
  1711. /*
  1712. =================
  1713. LocalizeMaps_f
  1714. =================
  1715. */
  1716. void Com_LocalizeMaps_f( const idCmdArgs &args ) {
  1717. if ( args.Argc() < 2 ) {
  1718. common->Printf( "Usage: localizeMaps <count | dictupdate | all> <map>\n" );
  1719. return;
  1720. }
  1721. int strCount = 0;
  1722. bool count = false;
  1723. bool dictUpdate = false;
  1724. bool write = false;
  1725. if ( idStr::Icmp( args.Argv(1), "count" ) == 0 ) {
  1726. count = true;
  1727. } else if ( idStr::Icmp( args.Argv(1), "dictupdate" ) == 0 ) {
  1728. count = true;
  1729. dictUpdate = true;
  1730. } else if ( idStr::Icmp( args.Argv(1), "all" ) == 0 ) {
  1731. count = true;
  1732. dictUpdate = true;
  1733. write = true;
  1734. } else {
  1735. common->Printf( "Invalid Command\n" );
  1736. common->Printf( "Usage: localizeMaps <count | dictupdate | all>\n" );
  1737. return;
  1738. }
  1739. idLangDict strTable;
  1740. idStr filename = va("strings/english%.3i.lang", com_product_lang_ext.GetInteger());
  1741. if(strTable.Load( filename ) == false) {
  1742. //This is a new file so set the base index
  1743. strTable.SetBaseID(com_product_lang_ext.GetInteger()*100000);
  1744. }
  1745. common->SetRefreshOnPrint( true );
  1746. ListHash listHash;
  1747. LoadMapLocalizeData(listHash);
  1748. idStrList excludeList;
  1749. LoadGuiParmExcludeList(excludeList);
  1750. if(args.Argc() == 3) {
  1751. strCount += LocalizeMap(args.Argv(2), strTable, listHash, excludeList, write);
  1752. } else {
  1753. idStrList files;
  1754. GetFileList("z:/d3xp/d3xp/maps/game", "*.map", files);
  1755. for ( int i = 0; i < files.Num(); i++ ) {
  1756. idStr file = fileSystem->OSPathToRelativePath(files[i]);
  1757. strCount += LocalizeMap(file, strTable, listHash, excludeList, write);
  1758. }
  1759. }
  1760. if(count) {
  1761. common->Printf("Localize String Count: %d\n", strCount);
  1762. }
  1763. common->SetRefreshOnPrint( false );
  1764. if(dictUpdate) {
  1765. strTable.Save( filename );
  1766. }
  1767. }
  1768. /*
  1769. =================
  1770. LocalizeGuis_f
  1771. =================
  1772. */
  1773. void Com_LocalizeGuis_f( const idCmdArgs &args ) {
  1774. if ( args.Argc() != 2 ) {
  1775. common->Printf( "Usage: localizeGuis <all | gui>\n" );
  1776. return;
  1777. }
  1778. idLangDict strTable;
  1779. idStr filename = va("strings/english%.3i.lang", com_product_lang_ext.GetInteger());
  1780. if(strTable.Load( filename ) == false) {
  1781. //This is a new file so set the base index
  1782. strTable.SetBaseID(com_product_lang_ext.GetInteger()*100000);
  1783. }
  1784. idFileList *files;
  1785. if ( idStr::Icmp( args.Argv(1), "all" ) == 0 ) {
  1786. idStr game = cvarSystem->GetCVarString( "fs_game" );
  1787. if(game.Length()) {
  1788. files = fileSystem->ListFilesTree( "guis", "*.gui", true, game );
  1789. } else {
  1790. files = fileSystem->ListFilesTree( "guis", "*.gui", true );
  1791. }
  1792. for ( int i = 0; i < files->GetNumFiles(); i++ ) {
  1793. commonLocal.LocalizeGui( files->GetFile( i ), strTable );
  1794. }
  1795. fileSystem->FreeFileList( files );
  1796. if(game.Length()) {
  1797. files = fileSystem->ListFilesTree( "guis", "*.pd", true, game );
  1798. } else {
  1799. files = fileSystem->ListFilesTree( "guis", "*.pd", true, "d3xp" );
  1800. }
  1801. for ( int i = 0; i < files->GetNumFiles(); i++ ) {
  1802. commonLocal.LocalizeGui( files->GetFile( i ), strTable );
  1803. }
  1804. fileSystem->FreeFileList( files );
  1805. } else {
  1806. commonLocal.LocalizeGui( args.Argv(1), strTable );
  1807. }
  1808. strTable.Save( filename );
  1809. }
  1810. void Com_LocalizeGuiParmsTest_f( const idCmdArgs &args ) {
  1811. common->SetRefreshOnPrint( true );
  1812. idFile *localizeFile = fileSystem->OpenFileWrite( "gui_parm_localize.csv" );
  1813. idFile *noLocalizeFile = fileSystem->OpenFileWrite( "gui_parm_nolocalize.csv" );
  1814. idStrList excludeList;
  1815. LoadGuiParmExcludeList(excludeList);
  1816. idStrList files;
  1817. GetFileList("z:/d3xp/d3xp/maps/game", "*.map", files);
  1818. for ( int i = 0; i < files.Num(); i++ ) {
  1819. common->Printf("Testing Map '%s'\n", files[i].c_str());
  1820. idMapFile map;
  1821. idStr file = fileSystem->OSPathToRelativePath(files[i]);
  1822. if ( map.Parse(file, false, false ) ) {
  1823. int count = map.GetNumEntities();
  1824. for ( int j = 0; j < count; j++ ) {
  1825. idMapEntity *ent = map.GetEntity( j );
  1826. if ( ent ) {
  1827. const idKeyValue* kv = ent->epairs.MatchPrefix("gui_parm");
  1828. while( kv ) {
  1829. if(TestGuiParm(kv->GetKey(), kv->GetValue(), excludeList)) {
  1830. idStr out = va("%s,%s,%s\r\n", kv->GetValue().c_str(), kv->GetKey().c_str(), file.c_str());
  1831. localizeFile->Write( out.c_str(), out.Length() );
  1832. } else {
  1833. idStr out = va("%s,%s,%s\r\n", kv->GetValue().c_str(), kv->GetKey().c_str(), file.c_str());
  1834. noLocalizeFile->Write( out.c_str(), out.Length() );
  1835. }
  1836. kv = ent->epairs.MatchPrefix( "gui_parm", kv );
  1837. }
  1838. }
  1839. }
  1840. }
  1841. }
  1842. fileSystem->CloseFile( localizeFile );
  1843. fileSystem->CloseFile( noLocalizeFile );
  1844. common->SetRefreshOnPrint( false );
  1845. }
  1846. void Com_LocalizeMapsTest_f( const idCmdArgs &args ) {
  1847. ListHash listHash;
  1848. LoadMapLocalizeData(listHash);
  1849. common->SetRefreshOnPrint( true );
  1850. idFile *localizeFile = fileSystem->OpenFileWrite( "map_localize.csv" );
  1851. idStrList files;
  1852. GetFileList("z:/d3xp/d3xp/maps/game", "*.map", files);
  1853. for ( int i = 0; i < files.Num(); i++ ) {
  1854. common->Printf("Testing Map '%s'\n", files[i].c_str());
  1855. idMapFile map;
  1856. idStr file = fileSystem->OSPathToRelativePath(files[i]);
  1857. if ( map.Parse(file, false, false ) ) {
  1858. int count = map.GetNumEntities();
  1859. for ( int j = 0; j < count; j++ ) {
  1860. idMapEntity *ent = map.GetEntity( j );
  1861. if ( ent ) {
  1862. //Temp code to get a list of all entity key value pairs
  1863. /*idStr classname = ent->epairs.GetString("classname");
  1864. if(classname == "worldspawn" || classname == "func_static" || classname == "light" || classname == "speaker" || classname.Left(8) == "trigger_") {
  1865. continue;
  1866. }
  1867. for( int i = 0; i < ent->epairs.GetNumKeyVals(); i++) {
  1868. const idKeyValue* kv = ent->epairs.GetKeyVal(i);
  1869. idStr out = va("%s,%s,%s,%s\r\n", classname.c_str(), kv->GetKey().c_str(), kv->GetValue().c_str(), file.c_str());
  1870. localizeFile->Write( out.c_str(), out.Length() );
  1871. }*/
  1872. idStr classname = ent->epairs.GetString("classname");
  1873. //Hack: for info_location
  1874. bool hasLocation = false;
  1875. idStrList* list;
  1876. listHash.Get(classname, &list);
  1877. if(list) {
  1878. for(int k = 0; k < list->Num(); k++) {
  1879. idStr val = ent->epairs.GetString((*list)[k], "");
  1880. if(classname == "info_location" && (*list)[k] == "location") {
  1881. hasLocation = true;
  1882. }
  1883. if(val.Length() && TestMapVal(val)) {
  1884. if(!hasLocation || (*list)[k] == "location") {
  1885. idStr out = va("%s,%s,%s\r\n", val.c_str(), (*list)[k].c_str(), file.c_str());
  1886. localizeFile->Write( out.c_str(), out.Length() );
  1887. }
  1888. }
  1889. }
  1890. }
  1891. listHash.Get("all", &list);
  1892. if(list) {
  1893. for(int k = 0; k < list->Num(); k++) {
  1894. idStr val = ent->epairs.GetString((*list)[k], "");
  1895. if(val.Length() && TestMapVal(val)) {
  1896. idStr out = va("%s,%s,%s\r\n", val.c_str(), (*list)[k].c_str(), file.c_str());
  1897. localizeFile->Write( out.c_str(), out.Length() );
  1898. }
  1899. }
  1900. }
  1901. }
  1902. }
  1903. }
  1904. }
  1905. fileSystem->CloseFile( localizeFile );
  1906. common->SetRefreshOnPrint( false );
  1907. }
  1908. /*
  1909. =================
  1910. Com_StartBuild_f
  1911. =================
  1912. */
  1913. void Com_StartBuild_f( const idCmdArgs &args ) {
  1914. globalImages->StartBuild();
  1915. }
  1916. /*
  1917. =================
  1918. Com_FinishBuild_f
  1919. =================
  1920. */
  1921. void Com_FinishBuild_f( const idCmdArgs &args ) {
  1922. if ( game ) {
  1923. game->CacheDictionaryMedia( NULL );
  1924. }
  1925. globalImages->FinishBuild( ( args.Argc() > 1 ) );
  1926. }
  1927. /*
  1928. ==============
  1929. Com_Help_f
  1930. ==============
  1931. */
  1932. void Com_Help_f( const idCmdArgs &args ) {
  1933. common->Printf( "\nCommonly used commands:\n" );
  1934. common->Printf( " spawnServer - start the server.\n" );
  1935. common->Printf( " disconnect - shut down the server.\n" );
  1936. common->Printf( " listCmds - list all console commands.\n" );
  1937. common->Printf( " listCVars - list all console variables.\n" );
  1938. common->Printf( " kick - kick a client by number.\n" );
  1939. common->Printf( " gameKick - kick a client by name.\n" );
  1940. common->Printf( " serverNextMap - immediately load next map.\n" );
  1941. common->Printf( " serverMapRestart - restart the current map.\n" );
  1942. common->Printf( " serverForceReady - force all players to ready status.\n" );
  1943. common->Printf( "\nCommonly used variables:\n" );
  1944. common->Printf( " si_name - server name (change requires a restart to see)\n" );
  1945. common->Printf( " si_gametype - type of game.\n" );
  1946. common->Printf( " si_fragLimit - max kills to win (or lives in Last Man Standing).\n" );
  1947. common->Printf( " si_timeLimit - maximum time a game will last.\n" );
  1948. common->Printf( " si_warmup - do pre-game warmup.\n" );
  1949. common->Printf( " si_pure - pure server.\n" );
  1950. common->Printf( " g_mapCycle - name of .scriptcfg file for cycling maps.\n" );
  1951. common->Printf( "See mapcycle.scriptcfg for an example of a mapcyle script.\n\n" );
  1952. }
  1953. /*
  1954. =================
  1955. idCommonLocal::InitCommands
  1956. =================
  1957. */
  1958. void idCommonLocal::InitCommands( void ) {
  1959. cmdSystem->AddCommand( "error", Com_Error_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "causes an error" );
  1960. cmdSystem->AddCommand( "crash", Com_Crash_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "causes a crash" );
  1961. cmdSystem->AddCommand( "freeze", Com_Freeze_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "freezes the game for a number of seconds" );
  1962. cmdSystem->AddCommand( "quit", Com_Quit_f, CMD_FL_SYSTEM, "quits the game" );
  1963. cmdSystem->AddCommand( "exit", Com_Quit_f, CMD_FL_SYSTEM, "exits the game" );
  1964. cmdSystem->AddCommand( "writeConfig", Com_WriteConfig_f, CMD_FL_SYSTEM, "writes a config file" );
  1965. cmdSystem->AddCommand( "reloadEngine", Com_ReloadEngine_f, CMD_FL_SYSTEM, "reloads the engine down to including the file system" );
  1966. cmdSystem->AddCommand( "setMachineSpec", Com_SetMachineSpec_f, CMD_FL_SYSTEM, "detects system capabilities and sets com_machineSpec to appropriate value" );
  1967. cmdSystem->AddCommand( "execMachineSpec", Com_ExecMachineSpec_f, CMD_FL_SYSTEM, "execs the appropriate config files and sets cvars based on com_machineSpec" );
  1968. #if !defined( ID_DEMO_BUILD ) && !defined( ID_DEDICATED )
  1969. // compilers
  1970. cmdSystem->AddCommand( "dmap", Dmap_f, CMD_FL_TOOL, "compiles a map", idCmdSystem::ArgCompletion_MapName );
  1971. cmdSystem->AddCommand( "renderbump", RenderBump_f, CMD_FL_TOOL, "renders a bump map", idCmdSystem::ArgCompletion_ModelName );
  1972. cmdSystem->AddCommand( "renderbumpFlat", RenderBumpFlat_f, CMD_FL_TOOL, "renders a flat bump map", idCmdSystem::ArgCompletion_ModelName );
  1973. cmdSystem->AddCommand( "runAAS", RunAAS_f, CMD_FL_TOOL, "compiles an AAS file for a map", idCmdSystem::ArgCompletion_MapName );
  1974. cmdSystem->AddCommand( "runAASDir", RunAASDir_f, CMD_FL_TOOL, "compiles AAS files for all maps in a folder", idCmdSystem::ArgCompletion_MapName );
  1975. cmdSystem->AddCommand( "runReach", RunReach_f, CMD_FL_TOOL, "calculates reachability for an AAS file", idCmdSystem::ArgCompletion_MapName );
  1976. cmdSystem->AddCommand( "roq", RoQFileEncode_f, CMD_FL_TOOL, "encodes a roq file" );
  1977. #endif
  1978. #ifdef ID_ALLOW_TOOLS
  1979. // editors
  1980. cmdSystem->AddCommand( "editor", Com_Editor_f, CMD_FL_TOOL, "launches the level editor Radiant" );
  1981. cmdSystem->AddCommand( "editLights", Com_EditLights_f, CMD_FL_TOOL, "launches the in-game Light Editor" );
  1982. cmdSystem->AddCommand( "editSounds", Com_EditSounds_f, CMD_FL_TOOL, "launches the in-game Sound Editor" );
  1983. cmdSystem->AddCommand( "editDecls", Com_EditDecls_f, CMD_FL_TOOL, "launches the in-game Declaration Editor" );
  1984. cmdSystem->AddCommand( "editAFs", Com_EditAFs_f, CMD_FL_TOOL, "launches the in-game Articulated Figure Editor" );
  1985. cmdSystem->AddCommand( "editParticles", Com_EditParticles_f, CMD_FL_TOOL, "launches the in-game Particle Editor" );
  1986. cmdSystem->AddCommand( "editScripts", Com_EditScripts_f, CMD_FL_TOOL, "launches the in-game Script Editor" );
  1987. cmdSystem->AddCommand( "editGUIs", Com_EditGUIs_f, CMD_FL_TOOL, "launches the GUI Editor" );
  1988. cmdSystem->AddCommand( "editPDAs", Com_EditPDAs_f, CMD_FL_TOOL, "launches the in-game PDA Editor" );
  1989. cmdSystem->AddCommand( "debugger", Com_ScriptDebugger_f, CMD_FL_TOOL, "launches the Script Debugger" );
  1990. //BSM Nerve: Add support for the material editor
  1991. cmdSystem->AddCommand( "materialEditor", Com_MaterialEditor_f, CMD_FL_TOOL, "launches the Material Editor" );
  1992. #endif
  1993. cmdSystem->AddCommand( "printMemInfo", PrintMemInfo_f, CMD_FL_SYSTEM, "prints memory debugging data" );
  1994. // idLib commands
  1995. cmdSystem->AddCommand( "memoryDump", Mem_Dump_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "creates a memory dump" );
  1996. cmdSystem->AddCommand( "memoryDumpCompressed", Mem_DumpCompressed_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "creates a compressed memory dump" );
  1997. cmdSystem->AddCommand( "showStringMemory", idStr::ShowMemoryUsage_f, CMD_FL_SYSTEM, "shows memory used by strings" );
  1998. cmdSystem->AddCommand( "showDictMemory", idDict::ShowMemoryUsage_f, CMD_FL_SYSTEM, "shows memory used by dictionaries" );
  1999. cmdSystem->AddCommand( "listDictKeys", idDict::ListKeys_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "lists all keys used by dictionaries" );
  2000. cmdSystem->AddCommand( "listDictValues", idDict::ListValues_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "lists all values used by dictionaries" );
  2001. cmdSystem->AddCommand( "testSIMD", idSIMD::Test_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "test SIMD code" );
  2002. // localization
  2003. cmdSystem->AddCommand( "localizeGuis", Com_LocalizeGuis_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "localize guis" );
  2004. cmdSystem->AddCommand( "localizeMaps", Com_LocalizeMaps_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "localize maps" );
  2005. cmdSystem->AddCommand( "reloadLanguage", Com_ReloadLanguage_f, CMD_FL_SYSTEM, "reload language dict" );
  2006. //D3XP Localization
  2007. cmdSystem->AddCommand( "localizeGuiParmsTest", Com_LocalizeGuiParmsTest_f, CMD_FL_SYSTEM, "Create test files that show gui parms localized and ignored." );
  2008. cmdSystem->AddCommand( "localizeMapsTest", Com_LocalizeMapsTest_f, CMD_FL_SYSTEM, "Create test files that shows which strings will be localized." );
  2009. // build helpers
  2010. cmdSystem->AddCommand( "startBuild", Com_StartBuild_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "prepares to make a build" );
  2011. cmdSystem->AddCommand( "finishBuild", Com_FinishBuild_f, CMD_FL_SYSTEM|CMD_FL_CHEAT, "finishes the build process" );
  2012. #ifdef ID_DEDICATED
  2013. cmdSystem->AddCommand( "help", Com_Help_f, CMD_FL_SYSTEM, "shows help" );
  2014. #endif
  2015. }
  2016. /*
  2017. =================
  2018. idCommonLocal::InitRenderSystem
  2019. =================
  2020. */
  2021. void idCommonLocal::InitRenderSystem( void ) {
  2022. if ( com_skipRenderer.GetBool() ) {
  2023. return;
  2024. }
  2025. renderSystem->InitOpenGL();
  2026. PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04343" ) );
  2027. }
  2028. /*
  2029. =================
  2030. idCommonLocal::PrintLoadingMessage
  2031. =================
  2032. */
  2033. void idCommonLocal::PrintLoadingMessage( const char *msg ) {
  2034. if ( !( msg && *msg ) ) {
  2035. return;
  2036. }
  2037. renderSystem->BeginFrame( renderSystem->GetScreenWidth(), renderSystem->GetScreenHeight() );
  2038. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 1, 1, declManager->FindMaterial( "splashScreen" ) );
  2039. int len = strlen( msg );
  2040. renderSystem->DrawSmallStringExt( ( 640 - len * SMALLCHAR_WIDTH ) / 2, 410, msg, idVec4( 0.0f, 0.81f, 0.94f, 1.0f ), true, declManager->FindMaterial( "textures/bigchars" ) );
  2041. renderSystem->EndFrame( NULL, NULL );
  2042. }
  2043. /*
  2044. =================
  2045. idCommonLocal::InitSIMD
  2046. =================
  2047. */
  2048. void idCommonLocal::InitSIMD( void ) {
  2049. idSIMD::InitProcessor( "doom", com_forceGenericSIMD.GetBool() );
  2050. com_forceGenericSIMD.ClearModified();
  2051. }
  2052. /*
  2053. =================
  2054. idCommonLocal::Frame
  2055. =================
  2056. */
  2057. void idCommonLocal::Frame( void ) {
  2058. try {
  2059. // pump all the events
  2060. Sys_GenerateEvents();
  2061. // write config file if anything changed
  2062. WriteConfiguration();
  2063. // change SIMD implementation if required
  2064. if ( com_forceGenericSIMD.IsModified() ) {
  2065. InitSIMD();
  2066. }
  2067. eventLoop->RunEventLoop();
  2068. com_frameTime = com_ticNumber * USERCMD_MSEC;
  2069. idAsyncNetwork::RunFrame();
  2070. if ( idAsyncNetwork::IsActive() ) {
  2071. if ( idAsyncNetwork::serverDedicated.GetInteger() != 1 ) {
  2072. session->GuiFrameEvents();
  2073. session->UpdateScreen( false );
  2074. }
  2075. } else {
  2076. session->Frame();
  2077. // normal, in-sequence screen update
  2078. session->UpdateScreen( false );
  2079. }
  2080. // report timing information
  2081. if ( com_speeds.GetBool() ) {
  2082. static int lastTime;
  2083. int nowTime = Sys_Milliseconds();
  2084. int com_frameMsec = nowTime - lastTime;
  2085. lastTime = nowTime;
  2086. Printf( "frame:%i all:%3i gfr:%3i rf:%3i bk:%3i\n", com_frameNumber, com_frameMsec, time_gameFrame, time_frontend, time_backend );
  2087. time_gameFrame = 0;
  2088. time_gameDraw = 0;
  2089. }
  2090. com_frameNumber++;
  2091. // set idLib frame number for frame based memory dumps
  2092. idLib::frameNumber = com_frameNumber;
  2093. // the FPU stack better be empty at this point or some bad code or compiler bug left values on the stack
  2094. if ( !Sys_FPU_StackIsEmpty() ) {
  2095. Printf( Sys_FPU_GetState() );
  2096. FatalError( "idCommon::Frame: the FPU stack is not empty at the end of the frame\n" );
  2097. }
  2098. }
  2099. catch( idException & ) {
  2100. return; // an ERP_DROP was thrown
  2101. }
  2102. }
  2103. /*
  2104. =================
  2105. idCommonLocal::GUIFrame
  2106. =================
  2107. */
  2108. void idCommonLocal::GUIFrame( bool execCmd, bool network ) {
  2109. Sys_GenerateEvents();
  2110. eventLoop->RunEventLoop( execCmd ); // and execute any commands
  2111. com_frameTime = com_ticNumber * USERCMD_MSEC;
  2112. if ( network ) {
  2113. idAsyncNetwork::RunFrame();
  2114. }
  2115. session->Frame();
  2116. session->UpdateScreen( false );
  2117. }
  2118. /*
  2119. =================
  2120. idCommonLocal::SingleAsyncTic
  2121. The system will asyncronously call this function 60 times a second to
  2122. handle the time-critical functions that we don't want limited to
  2123. the frame rate:
  2124. sound mixing
  2125. user input generation (conditioned by com_asyncInput)
  2126. packet server operation
  2127. packet client operation
  2128. We are not using thread safe libraries, so any functionality put here must
  2129. be VERY VERY careful about what it calls.
  2130. =================
  2131. */
  2132. typedef struct {
  2133. int milliseconds; // should always be incremeting by 60hz
  2134. int deltaMsec; // should always be 16
  2135. int timeConsumed; // msec spent in Com_AsyncThread()
  2136. int clientPacketsReceived;
  2137. int serverPacketsReceived;
  2138. int mostRecentServerPacketSequence;
  2139. } asyncStats_t;
  2140. static const int MAX_ASYNC_STATS = 1024;
  2141. asyncStats_t com_asyncStats[MAX_ASYNC_STATS]; // indexed by com_ticNumber
  2142. int prevAsyncMsec;
  2143. int lastTicMsec;
  2144. void idCommonLocal::SingleAsyncTic( void ) {
  2145. // main thread code can prevent this from happening while modifying
  2146. // critical data structures
  2147. Sys_EnterCriticalSection();
  2148. asyncStats_t *stat = &com_asyncStats[com_ticNumber & (MAX_ASYNC_STATS-1)];
  2149. memset( stat, 0, sizeof( *stat ) );
  2150. stat->milliseconds = Sys_Milliseconds();
  2151. stat->deltaMsec = stat->milliseconds - com_asyncStats[(com_ticNumber - 1) & (MAX_ASYNC_STATS-1)].milliseconds;
  2152. if ( usercmdGen && com_asyncInput.GetBool() ) {
  2153. usercmdGen->UsercmdInterrupt();
  2154. }
  2155. switch ( com_asyncSound.GetInteger() ) {
  2156. case 1:
  2157. soundSystem->AsyncUpdate( stat->milliseconds );
  2158. break;
  2159. case 3:
  2160. soundSystem->AsyncUpdateWrite( stat->milliseconds );
  2161. break;
  2162. }
  2163. // we update com_ticNumber after all the background tasks
  2164. // have completed their work for this tic
  2165. com_ticNumber++;
  2166. stat->timeConsumed = Sys_Milliseconds() - stat->milliseconds;
  2167. Sys_LeaveCriticalSection();
  2168. }
  2169. /*
  2170. =================
  2171. idCommonLocal::Async
  2172. =================
  2173. */
  2174. void idCommonLocal::Async( void ) {
  2175. if ( com_shuttingDown ) {
  2176. return;
  2177. }
  2178. int msec = Sys_Milliseconds();
  2179. if ( !lastTicMsec ) {
  2180. lastTicMsec = msec - USERCMD_MSEC;
  2181. }
  2182. if ( !com_preciseTic.GetBool() ) {
  2183. // just run a single tic, even if the exact msec isn't precise
  2184. SingleAsyncTic();
  2185. return;
  2186. }
  2187. int ticMsec = USERCMD_MSEC;
  2188. // the number of msec per tic can be varies with the timescale cvar
  2189. float timescale = com_timescale.GetFloat();
  2190. if ( timescale != 1.0f ) {
  2191. ticMsec /= timescale;
  2192. if ( ticMsec < 1 ) {
  2193. ticMsec = 1;
  2194. }
  2195. }
  2196. // don't skip too many
  2197. if ( timescale == 1.0f ) {
  2198. if ( lastTicMsec + 10 * USERCMD_MSEC < msec ) {
  2199. lastTicMsec = msec - 10*USERCMD_MSEC;
  2200. }
  2201. }
  2202. while ( lastTicMsec + ticMsec <= msec ) {
  2203. SingleAsyncTic();
  2204. lastTicMsec += ticMsec;
  2205. }
  2206. }
  2207. /*
  2208. =================
  2209. idCommonLocal::LoadGameDLL
  2210. =================
  2211. */
  2212. void idCommonLocal::LoadGameDLL( void ) {
  2213. #ifdef __DOOM_DLL__
  2214. char dllPath[ MAX_OSPATH ];
  2215. gameImport_t gameImport;
  2216. gameExport_t gameExport;
  2217. GetGameAPI_t GetGameAPI;
  2218. fileSystem->FindDLL( "game", dllPath, true );
  2219. if ( !dllPath[ 0 ] ) {
  2220. common->FatalError( "couldn't find game dynamic library" );
  2221. return;
  2222. }
  2223. common->DPrintf( "Loading game DLL: '%s'\n", dllPath );
  2224. gameDLL = sys->DLL_Load( dllPath );
  2225. if ( !gameDLL ) {
  2226. common->FatalError( "couldn't load game dynamic library" );
  2227. return;
  2228. }
  2229. GetGameAPI = (GetGameAPI_t) Sys_DLL_GetProcAddress( gameDLL, "GetGameAPI" );
  2230. if ( !GetGameAPI ) {
  2231. Sys_DLL_Unload( gameDLL );
  2232. gameDLL = NULL;
  2233. common->FatalError( "couldn't find game DLL API" );
  2234. return;
  2235. }
  2236. gameImport.version = GAME_API_VERSION;
  2237. gameImport.sys = ::sys;
  2238. gameImport.common = ::common;
  2239. gameImport.cmdSystem = ::cmdSystem;
  2240. gameImport.cvarSystem = ::cvarSystem;
  2241. gameImport.fileSystem = ::fileSystem;
  2242. gameImport.networkSystem = ::networkSystem;
  2243. gameImport.renderSystem = ::renderSystem;
  2244. gameImport.soundSystem = ::soundSystem;
  2245. gameImport.renderModelManager = ::renderModelManager;
  2246. gameImport.uiManager = ::uiManager;
  2247. gameImport.declManager = ::declManager;
  2248. gameImport.AASFileManager = ::AASFileManager;
  2249. gameImport.collisionModelManager = ::collisionModelManager;
  2250. gameExport = *GetGameAPI( &gameImport );
  2251. if ( gameExport.version != GAME_API_VERSION ) {
  2252. Sys_DLL_Unload( gameDLL );
  2253. gameDLL = NULL;
  2254. common->FatalError( "wrong game DLL API version" );
  2255. return;
  2256. }
  2257. game = gameExport.game;
  2258. gameEdit = gameExport.gameEdit;
  2259. #endif
  2260. // initialize the game object
  2261. if ( game != NULL ) {
  2262. game->Init();
  2263. }
  2264. }
  2265. /*
  2266. =================
  2267. idCommonLocal::UnloadGameDLL
  2268. =================
  2269. */
  2270. void idCommonLocal::UnloadGameDLL( void ) {
  2271. // shut down the game object
  2272. if ( game != NULL ) {
  2273. game->Shutdown();
  2274. }
  2275. #ifdef __DOOM_DLL__
  2276. if ( gameDLL ) {
  2277. Sys_DLL_Unload( gameDLL );
  2278. gameDLL = NULL;
  2279. }
  2280. game = NULL;
  2281. gameEdit = NULL;
  2282. #endif
  2283. }
  2284. /*
  2285. =================
  2286. idCommonLocal::IsInitialized
  2287. =================
  2288. */
  2289. bool idCommonLocal::IsInitialized( void ) const {
  2290. return com_fullyInitialized;
  2291. }
  2292. /*
  2293. =================
  2294. idCommonLocal::SetMachineSpec
  2295. =================
  2296. */
  2297. void idCommonLocal::SetMachineSpec( void ) {
  2298. cpuid_t cpu = Sys_GetProcessorId();
  2299. double ghz = Sys_ClockTicksPerSecond() * 0.000000001f;
  2300. int vidRam = Sys_GetVideoRam();
  2301. int sysRam = Sys_GetSystemRam();
  2302. bool oldCard = false;
  2303. bool nv10or20 = false;
  2304. renderSystem->GetCardCaps( oldCard, nv10or20 );
  2305. Printf( "Detected\n \t%.2f GHz CPU\n\t%i MB of System memory\n\t%i MB of Video memory on %s\n\n", ghz, sysRam, vidRam, ( oldCard ) ? "a less than optimal video architecture" : "an optimal video architecture" );
  2306. if ( ghz >= 2.75f && vidRam >= 512 && sysRam >= 1024 && !oldCard ) {
  2307. Printf( "This system qualifies for Ultra quality!\n" );
  2308. com_machineSpec.SetInteger( 3 );
  2309. } else if ( ghz >= ( ( cpu & CPUID_AMD ) ? 1.9f : 2.19f ) && vidRam >= 256 && sysRam >= 512 && !oldCard ) {
  2310. Printf( "This system qualifies for High quality!\n" );
  2311. com_machineSpec.SetInteger( 2 );
  2312. } else if ( ghz >= ( ( cpu & CPUID_AMD ) ? 1.1f : 1.25f ) && vidRam >= 128 && sysRam >= 384 ) {
  2313. Printf( "This system qualifies for Medium quality.\n" );
  2314. com_machineSpec.SetInteger( 1 );
  2315. } else {
  2316. Printf( "This system qualifies for Low quality.\n" );
  2317. com_machineSpec.SetInteger( 0 );
  2318. }
  2319. com_videoRam.SetInteger( vidRam );
  2320. }
  2321. /*
  2322. =================
  2323. idCommonLocal::Init
  2324. =================
  2325. */
  2326. void idCommonLocal::Init( int argc, const char **argv, const char *cmdline ) {
  2327. try {
  2328. // set interface pointers used by idLib
  2329. idLib::sys = sys;
  2330. idLib::common = common;
  2331. idLib::cvarSystem = cvarSystem;
  2332. idLib::fileSystem = fileSystem;
  2333. // initialize idLib
  2334. idLib::Init();
  2335. // clear warning buffer
  2336. ClearWarnings( GAME_NAME " initialization" );
  2337. // parse command line options
  2338. idCmdArgs args;
  2339. if ( cmdline ) {
  2340. // tokenize if the OS doesn't do it for us
  2341. args.TokenizeString( cmdline, true );
  2342. argv = args.GetArgs( &argc );
  2343. }
  2344. ParseCommandLine( argc, argv );
  2345. // init console command system
  2346. cmdSystem->Init();
  2347. // init CVar system
  2348. cvarSystem->Init();
  2349. // start file logging right away, before early console or whatever
  2350. StartupVariable( "win_outputDebugString", false );
  2351. // register all static CVars
  2352. idCVar::RegisterStaticVars();
  2353. // print engine version
  2354. Printf( "%s\n", version.string );
  2355. // initialize key input/binding, done early so bind command exists
  2356. idKeyInput::Init();
  2357. // init the console so we can take prints
  2358. console->Init();
  2359. // get architecture info
  2360. Sys_Init();
  2361. // initialize networking
  2362. Sys_InitNetworking();
  2363. // override cvars from command line
  2364. StartupVariable( NULL, false );
  2365. if ( !idAsyncNetwork::serverDedicated.GetInteger() && Sys_AlreadyRunning() ) {
  2366. Sys_Quit();
  2367. }
  2368. // initialize processor specific SIMD implementation
  2369. InitSIMD();
  2370. // init commands
  2371. InitCommands();
  2372. #ifdef ID_WRITE_VERSION
  2373. config_compressor = idCompressor::AllocArithmetic();
  2374. #endif
  2375. // game specific initialization
  2376. InitGame();
  2377. // don't add startup commands if no CD key is present
  2378. #if ID_ENFORCE_KEY
  2379. if ( !session->CDKeysAreValid( false ) || !AddStartupCommands() ) {
  2380. #else
  2381. if ( !AddStartupCommands() ) {
  2382. #endif
  2383. // if the user didn't give any commands, run default action
  2384. session->StartMenu( true );
  2385. }
  2386. Printf( "--- Common Initialization Complete ---\n" );
  2387. // print all warnings queued during initialization
  2388. PrintWarnings();
  2389. #ifdef ID_DEDICATED
  2390. Printf( "\nType 'help' for dedicated server info.\n\n" );
  2391. #endif
  2392. // remove any prints from the notify lines
  2393. console->ClearNotifyLines();
  2394. ClearCommandLine();
  2395. com_fullyInitialized = true;
  2396. }
  2397. catch( idException & ) {
  2398. Sys_Error( "Error during initialization" );
  2399. }
  2400. }
  2401. /*
  2402. =================
  2403. idCommonLocal::Shutdown
  2404. =================
  2405. */
  2406. void idCommonLocal::Shutdown( void ) {
  2407. com_shuttingDown = true;
  2408. idAsyncNetwork::server.Kill();
  2409. idAsyncNetwork::client.Shutdown();
  2410. // game specific shut down
  2411. ShutdownGame( false );
  2412. // shut down non-portable system services
  2413. Sys_Shutdown();
  2414. // shut down the console
  2415. console->Shutdown();
  2416. // shut down the key system
  2417. idKeyInput::Shutdown();
  2418. // shut down the cvar system
  2419. cvarSystem->Shutdown();
  2420. // shut down the console command system
  2421. cmdSystem->Shutdown();
  2422. #ifdef ID_WRITE_VERSION
  2423. delete config_compressor;
  2424. config_compressor = NULL;
  2425. #endif
  2426. // free any buffered warning messages
  2427. ClearWarnings( GAME_NAME " shutdown" );
  2428. warningCaption.Clear();
  2429. errorList.Clear();
  2430. // free language dictionary
  2431. languageDict.Clear();
  2432. // enable leak test
  2433. Mem_EnableLeakTest( "doom" );
  2434. // shutdown idLib
  2435. idLib::ShutDown();
  2436. }
  2437. /*
  2438. =================
  2439. idCommonLocal::InitGame
  2440. =================
  2441. */
  2442. void idCommonLocal::InitGame( void ) {
  2443. // initialize the file system
  2444. fileSystem->Init();
  2445. // initialize the declaration manager
  2446. declManager->Init();
  2447. // force r_fullscreen 0 if running a tool
  2448. CheckToolMode();
  2449. idFile *file = fileSystem->OpenExplicitFileRead( fileSystem->RelativePathToOSPath( CONFIG_SPEC, "fs_savepath" ) );
  2450. bool sysDetect = ( file == NULL );
  2451. if ( file ) {
  2452. fileSystem->CloseFile( file );
  2453. } else {
  2454. file = fileSystem->OpenFileWrite( CONFIG_SPEC );
  2455. fileSystem->CloseFile( file );
  2456. }
  2457. idCmdArgs args;
  2458. if ( sysDetect ) {
  2459. SetMachineSpec();
  2460. Com_ExecMachineSpec_f( args );
  2461. }
  2462. // initialize the renderSystem data structures, but don't start OpenGL yet
  2463. renderSystem->Init();
  2464. // initialize string database right off so we can use it for loading messages
  2465. InitLanguageDict();
  2466. PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04344" ) );
  2467. // load the font, etc
  2468. console->LoadGraphics();
  2469. // init journalling, etc
  2470. eventLoop->Init();
  2471. PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04345" ) );
  2472. // exec the startup scripts
  2473. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec editor.cfg\n" );
  2474. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec default.cfg\n" );
  2475. // skip the config file if "safe" is on the command line
  2476. if ( !SafeMode() ) {
  2477. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec " CONFIG_FILE "\n" );
  2478. }
  2479. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "exec autoexec.cfg\n" );
  2480. // reload the language dictionary now that we've loaded config files
  2481. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "reloadLanguage\n" );
  2482. // run cfg execution
  2483. cmdSystem->ExecuteCommandBuffer();
  2484. // re-override anything from the config files with command line args
  2485. StartupVariable( NULL, false );
  2486. // if any archived cvars are modified after this, we will trigger a writing of the config file
  2487. cvarSystem->ClearModifiedFlags( CVAR_ARCHIVE );
  2488. // cvars are initialized, but not the rendering system. Allow preference startup dialog
  2489. Sys_DoPreferences();
  2490. // init the user command input code
  2491. usercmdGen->Init();
  2492. PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04346" ) );
  2493. // start the sound system, but don't do any hardware operations yet
  2494. soundSystem->Init();
  2495. PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04347" ) );
  2496. // init async network
  2497. idAsyncNetwork::Init();
  2498. #ifdef ID_DEDICATED
  2499. idAsyncNetwork::server.InitPort();
  2500. cvarSystem->SetCVarBool( "s_noSound", true );
  2501. #else
  2502. if ( idAsyncNetwork::serverDedicated.GetInteger() == 1 ) {
  2503. idAsyncNetwork::server.InitPort();
  2504. cvarSystem->SetCVarBool( "s_noSound", true );
  2505. } else {
  2506. // init OpenGL, which will open a window and connect sound and input hardware
  2507. PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04348" ) );
  2508. InitRenderSystem();
  2509. }
  2510. #endif
  2511. PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04349" ) );
  2512. // initialize the user interfaces
  2513. uiManager->Init();
  2514. // startup the script debugger
  2515. // DebuggerServerInit();
  2516. PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04350" ) );
  2517. // load the game dll
  2518. LoadGameDLL();
  2519. PrintLoadingMessage( common->GetLanguageDict()->GetString( "#str_04351" ) );
  2520. // init the session
  2521. session->Init();
  2522. // have to do this twice.. first one sets the correct r_mode for the renderer init
  2523. // this time around the backend is all setup correct.. a bit fugly but do not want
  2524. // to mess with all the gl init at this point.. an old vid card will never qualify for
  2525. if ( sysDetect ) {
  2526. SetMachineSpec();
  2527. Com_ExecMachineSpec_f( args );
  2528. cvarSystem->SetCVarInteger( "s_numberOfSpeakers", 6 );
  2529. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "s_restart\n" );
  2530. cmdSystem->ExecuteCommandBuffer();
  2531. }
  2532. }
  2533. /*
  2534. =================
  2535. idCommonLocal::ShutdownGame
  2536. =================
  2537. */
  2538. void idCommonLocal::ShutdownGame( bool reloading ) {
  2539. // kill sound first
  2540. idSoundWorld *sw = soundSystem->GetPlayingSoundWorld();
  2541. if ( sw ) {
  2542. sw->StopAllSounds();
  2543. }
  2544. soundSystem->ClearBuffer();
  2545. // shutdown the script debugger
  2546. // DebuggerServerShutdown();
  2547. idAsyncNetwork::client.Shutdown();
  2548. // shut down the session
  2549. session->Shutdown();
  2550. // shut down the user interfaces
  2551. uiManager->Shutdown();
  2552. // shut down the sound system
  2553. soundSystem->Shutdown();
  2554. // shut down async networking
  2555. idAsyncNetwork::Shutdown();
  2556. // shut down the user command input code
  2557. usercmdGen->Shutdown();
  2558. // shut down the event loop
  2559. eventLoop->Shutdown();
  2560. // shut down the renderSystem
  2561. renderSystem->Shutdown();
  2562. // shutdown the decl manager
  2563. declManager->Shutdown();
  2564. // unload the game dll
  2565. UnloadGameDLL();
  2566. // dump warnings to "warnings.txt"
  2567. #ifdef DEBUG
  2568. DumpWarnings();
  2569. #endif
  2570. // only shut down the log file after all output is done
  2571. CloseLogFile();
  2572. // shut down the file system
  2573. fileSystem->Shutdown( reloading );
  2574. }