|
|
1.1 ! root 1: // host.c -- coordinates spawning and killing of local servers ! 2: ! 3: #include "quakedef.h" ! 4: #include "r_local.h" ! 5: ! 6: /* ! 7: ! 8: A server can allways be started, even if the system started out as a client ! 9: to a remote system. ! 10: ! 11: A client can NOT be started if the system started as a dedicated server. ! 12: ! 13: Memory is cleared / released when a server or client begins, not when they end. ! 14: ! 15: */ ! 16: ! 17: quakeparms_t host_parms; ! 18: ! 19: qboolean host_initialized; // true if into command execution ! 20: ! 21: double host_frametime; ! 22: double host_time; ! 23: double realtime; // without any filtering or bounding ! 24: double oldrealtime; // last frame run ! 25: int host_framecount; ! 26: ! 27: int host_hunklevel; ! 28: ! 29: client_t *host_client; // current client ! 30: ! 31: jmp_buf host_abortserver; ! 32: ! 33: byte *host_basepal; ! 34: byte *host_colormap; ! 35: ! 36: cvar_t host_framerate = {"host_framerate","0"}; // set for slow motion ! 37: cvar_t host_speeds = {"host_speeds","0"}; // set for running times ! 38: ! 39: cvar_t sys_ticrate = {"sys_ticrate","0.05"}; ! 40: cvar_t serverprofile = {"serverprofile","0"}; ! 41: ! 42: cvar_t fraglimit = {"fraglimit","0",false,true}; ! 43: cvar_t timelimit = {"timelimit","0",false,true}; ! 44: cvar_t teamplay = {"teamplay","0",false,true}; ! 45: ! 46: cvar_t samelevel = {"samelevel","0"}; ! 47: cvar_t noexit = {"noexit","0",false,true}; ! 48: ! 49: cvar_t developer = {"developer","0"}; ! 50: ! 51: cvar_t skill = {"skill","1"}; // 0 - 3 ! 52: cvar_t deathmatch = {"deathmatch","0"}; // 0, 1, or 2 ! 53: cvar_t coop = {"coop","0"}; // 0 or 1 ! 54: ! 55: cvar_t pausable = {"pausable","1"}; ! 56: ! 57: cvar_t temp1 = {"temp1","0"}; ! 58: ! 59: ! 60: /* ! 61: ================ ! 62: Host_EndGame ! 63: ================ ! 64: */ ! 65: void Host_EndGame (char *message, ...) ! 66: { ! 67: va_list argptr; ! 68: char string[1024]; ! 69: ! 70: va_start (argptr,message); ! 71: vsprintf (string,message,argptr); ! 72: va_end (argptr); ! 73: Con_DPrintf ("Host_EndGame: %s\n",string); ! 74: ! 75: if (sv.active) ! 76: Host_ShutdownServer (false); ! 77: ! 78: if (cls.state == ca_dedicated) ! 79: Sys_Error ("Host_EndGame: %s\n",string); // dedicated servers exit ! 80: ! 81: if (cls.demonum != -1) ! 82: CL_NextDemo (); ! 83: else ! 84: CL_Disconnect (); ! 85: ! 86: longjmp (host_abortserver, 1); ! 87: } ! 88: ! 89: /* ! 90: ================ ! 91: Host_Error ! 92: ! 93: This shuts down both the client and server ! 94: ================ ! 95: */ ! 96: void Host_Error (char *error, ...) ! 97: { ! 98: va_list argptr; ! 99: char string[1024]; ! 100: static qboolean inerror = false; ! 101: ! 102: if (inerror) ! 103: Sys_Error ("Host_Error: recursively entered"); ! 104: inerror = true; ! 105: ! 106: SCR_EndLoadingPlaque (); // reenable screen updates ! 107: ! 108: va_start (argptr,error); ! 109: vsprintf (string,error,argptr); ! 110: va_end (argptr); ! 111: Con_Printf ("Host_Error: %s\n",string); ! 112: ! 113: if (sv.active) ! 114: Host_ShutdownServer (false); ! 115: ! 116: if (cls.state == ca_dedicated) ! 117: Sys_Error ("Host_Error: %s\n",string); // dedicated servers exit ! 118: ! 119: CL_Disconnect (); ! 120: cls.demonum = -1; ! 121: ! 122: inerror = false; ! 123: ! 124: longjmp (host_abortserver, 1); ! 125: } ! 126: ! 127: /* ! 128: ================ ! 129: Host_FindMaxClients ! 130: ================ ! 131: */ ! 132: void Host_FindMaxClients (void) ! 133: { ! 134: int i; ! 135: ! 136: svs.maxclients = 1; ! 137: ! 138: i = COM_CheckParm ("-dedicated"); ! 139: if (i) ! 140: { ! 141: cls.state = ca_dedicated; ! 142: if (i != (com_argc - 1)) ! 143: { ! 144: svs.maxclients = Q_atoi (com_argv[i+1]); ! 145: } ! 146: else ! 147: svs.maxclients = 8; ! 148: } ! 149: else ! 150: cls.state = ca_disconnected; ! 151: ! 152: i = COM_CheckParm ("-listen"); ! 153: if (i) ! 154: { ! 155: if (cls.state == ca_dedicated) ! 156: Sys_Error ("Only one of -dedicated or -listen can be specified"); ! 157: if (i != (com_argc - 1)) ! 158: svs.maxclients = Q_atoi (com_argv[i+1]); ! 159: else ! 160: svs.maxclients = 8; ! 161: } ! 162: if (svs.maxclients < 1) ! 163: svs.maxclients = 8; ! 164: else if (svs.maxclients > MAX_SCOREBOARD) ! 165: svs.maxclients = MAX_SCOREBOARD; ! 166: ! 167: svs.maxclientslimit = svs.maxclients; ! 168: if (svs.maxclientslimit < 4) ! 169: svs.maxclientslimit = 4; ! 170: svs.clients = Hunk_AllocName (svs.maxclientslimit*sizeof(client_t), "clients"); ! 171: ! 172: if (svs.maxclients > 1) ! 173: Cvar_SetValue ("deathmatch", 1.0); ! 174: else ! 175: Cvar_SetValue ("deathmatch", 0.0); ! 176: } ! 177: ! 178: ! 179: /* ! 180: ======================= ! 181: Host_InitLocal ! 182: ====================== ! 183: */ ! 184: void Host_InitLocal (void) ! 185: { ! 186: Host_InitCommands (); ! 187: ! 188: Cvar_RegisterVariable (&host_framerate); ! 189: Cvar_RegisterVariable (&host_speeds); ! 190: ! 191: Cvar_RegisterVariable (&sys_ticrate); ! 192: Cvar_RegisterVariable (&serverprofile); ! 193: ! 194: Cvar_RegisterVariable (&fraglimit); ! 195: Cvar_RegisterVariable (&timelimit); ! 196: Cvar_RegisterVariable (&teamplay); ! 197: Cvar_RegisterVariable (&samelevel); ! 198: Cvar_RegisterVariable (&noexit); ! 199: Cvar_RegisterVariable (&skill); ! 200: Cvar_RegisterVariable (&developer); ! 201: Cvar_RegisterVariable (&deathmatch); ! 202: Cvar_RegisterVariable (&coop); ! 203: ! 204: Cvar_RegisterVariable (&pausable); ! 205: ! 206: Cvar_RegisterVariable (&temp1); ! 207: ! 208: Host_FindMaxClients (); ! 209: ! 210: host_time = 1.0; // so a think at time 0 won't get called ! 211: } ! 212: ! 213: ! 214: /* ! 215: =============== ! 216: Host_WriteConfiguration ! 217: ! 218: Writes key bindings and archived cvars to config.cfg ! 219: =============== ! 220: */ ! 221: void Host_WriteConfiguration (void) ! 222: { ! 223: FILE *f; ! 224: ! 225: f = fopen (va("%s/config.cfg",com_gamedir), "w"); ! 226: if (!f) ! 227: { ! 228: Con_Printf ("Couldn't write config.cfg.\n"); ! 229: return; ! 230: } ! 231: ! 232: Key_WriteBindings (f); ! 233: Cvar_WriteVariables (f); ! 234: ! 235: fclose (f); ! 236: } ! 237: ! 238: ! 239: /* ! 240: ================= ! 241: SV_ClientPrintf ! 242: ! 243: Sends text across to be displayed ! 244: FIXME: make this just a stuffed echo? ! 245: ================= ! 246: */ ! 247: void SV_ClientPrintf (char *fmt, ...) ! 248: { ! 249: va_list argptr; ! 250: char string[1024]; ! 251: ! 252: va_start (argptr,fmt); ! 253: vsprintf (string, fmt,argptr); ! 254: va_end (argptr); ! 255: ! 256: MSG_WriteByte (&host_client->message, svc_print); ! 257: MSG_WriteString (&host_client->message, string); ! 258: } ! 259: ! 260: /* ! 261: ================= ! 262: SV_BroadcastPrintf ! 263: ! 264: Sends text to all active clients ! 265: ================= ! 266: */ ! 267: void SV_BroadcastPrintf (char *fmt, ...) ! 268: { ! 269: va_list argptr; ! 270: char string[1024]; ! 271: int i; ! 272: ! 273: va_start (argptr,fmt); ! 274: vsprintf (string, fmt,argptr); ! 275: va_end (argptr); ! 276: ! 277: for (i=0 ; i<svs.maxclients ; i++) ! 278: if (svs.clients[i].active && svs.clients[i].spawned) ! 279: { ! 280: MSG_WriteByte (&svs.clients[i].message, svc_print); ! 281: MSG_WriteString (&svs.clients[i].message, string); ! 282: } ! 283: } ! 284: ! 285: /* ! 286: ================= ! 287: Host_ClientCommands ! 288: ! 289: Send text over to the client to be executed ! 290: ================= ! 291: */ ! 292: void Host_ClientCommands (char *fmt, ...) ! 293: { ! 294: va_list argptr; ! 295: char string[1024]; ! 296: ! 297: va_start (argptr,fmt); ! 298: vsprintf (string, fmt,argptr); ! 299: va_end (argptr); ! 300: ! 301: MSG_WriteByte (&host_client->message, svc_stufftext); ! 302: MSG_WriteString (&host_client->message, string); ! 303: } ! 304: ! 305: /* ! 306: ===================== ! 307: SV_DropClient ! 308: ! 309: Called when the player is getting totally kicked off the host ! 310: if (crash = true), don't bother sending signofs ! 311: ===================== ! 312: */ ! 313: void SV_DropClient (qboolean crash) ! 314: { ! 315: int saveSelf; ! 316: int i; ! 317: client_t *client; ! 318: ! 319: if (!crash) ! 320: { ! 321: // send any final messages (don't check for errors) ! 322: if (NET_CanSendMessage (host_client->netconnection)) ! 323: { ! 324: MSG_WriteByte (&host_client->message, svc_disconnect); ! 325: NET_SendMessage (host_client->netconnection, &host_client->message); ! 326: } ! 327: ! 328: if (host_client->edict && host_client->spawned) ! 329: { ! 330: // call the prog function for removing a client ! 331: // this will set the body to a dead frame, among other things ! 332: saveSelf = pr_global_struct->self; ! 333: pr_global_struct->self = EDICT_TO_PROG(host_client->edict); ! 334: PR_ExecuteProgram (pr_global_struct->ClientDisconnect); ! 335: pr_global_struct->self = saveSelf; ! 336: } ! 337: ! 338: Sys_Printf ("Client %s removed\n",host_client->name); ! 339: } ! 340: ! 341: // break the net connection ! 342: NET_Close (host_client->netconnection); ! 343: host_client->netconnection = NULL; ! 344: ! 345: // free the client (the body stays around) ! 346: host_client->active = false; ! 347: host_client->name[0] = 0; ! 348: host_client->old_frags = -999999; ! 349: net_activeconnections--; ! 350: ! 351: // send notification to all clients ! 352: for (i=0, client = svs.clients ; i<svs.maxclients ; i++, client++) ! 353: { ! 354: if (!client->active) ! 355: continue; ! 356: MSG_WriteByte (&client->message, svc_updatename); ! 357: MSG_WriteByte (&client->message, host_client - svs.clients); ! 358: MSG_WriteString (&client->message, ""); ! 359: MSG_WriteByte (&client->message, svc_updatefrags); ! 360: MSG_WriteByte (&client->message, host_client - svs.clients); ! 361: MSG_WriteShort (&client->message, 0); ! 362: MSG_WriteByte (&client->message, svc_updatecolors); ! 363: MSG_WriteByte (&client->message, host_client - svs.clients); ! 364: MSG_WriteByte (&client->message, 0); ! 365: } ! 366: } ! 367: ! 368: /* ! 369: ================== ! 370: Host_ShutdownServer ! 371: ! 372: This only happens at the end of a game, not between levels ! 373: ================== ! 374: */ ! 375: void Host_ShutdownServer(qboolean crash) ! 376: { ! 377: int i; ! 378: int count; ! 379: sizebuf_t buf; ! 380: char message[4]; ! 381: double start; ! 382: ! 383: if (!sv.active) ! 384: return; ! 385: ! 386: sv.active = false; ! 387: ! 388: // stop all client sounds immediately ! 389: if (cls.state == ca_connected) ! 390: CL_Disconnect (); ! 391: ! 392: // flush any pending messages - like the score!!! ! 393: start = Sys_FloatTime(); ! 394: do ! 395: { ! 396: count = 0; ! 397: for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++) ! 398: { ! 399: if (host_client->active && host_client->message.cursize) ! 400: { ! 401: if (NET_CanSendMessage (host_client->netconnection)) ! 402: { ! 403: NET_SendMessage(host_client->netconnection, &host_client->message); ! 404: SZ_Clear (&host_client->message); ! 405: } ! 406: else ! 407: { ! 408: NET_GetMessage(host_client->netconnection); ! 409: count++; ! 410: } ! 411: } ! 412: } ! 413: if ((Sys_FloatTime() - start) > 3.0) ! 414: break; ! 415: } ! 416: while (count); ! 417: ! 418: // make sure all the clients know we're disconnecting ! 419: buf.data = message; ! 420: buf.maxsize = 4; ! 421: buf.cursize = 0; ! 422: MSG_WriteByte(&buf, svc_disconnect); ! 423: count = NET_SendToAll(&buf, 5); ! 424: if (count) ! 425: Con_Printf("Host_ShutdownServer: NET_SendToAll failed for %u clients\n", count); ! 426: ! 427: for (i=0, host_client = svs.clients ; i<svs.maxclients ; i++, host_client++) ! 428: if (host_client->active) ! 429: SV_DropClient(crash); ! 430: ! 431: // ! 432: // clear structures ! 433: // ! 434: memset (&sv, 0, sizeof(sv)); ! 435: memset (svs.clients, 0, svs.maxclientslimit*sizeof(client_t)); ! 436: } ! 437: ! 438: ! 439: /* ! 440: ================ ! 441: Host_ClearMemory ! 442: ! 443: This clears all the memory used by both the client and server, but does ! 444: not reinitialize anything. ! 445: ================ ! 446: */ ! 447: void Host_ClearMemory (void) ! 448: { ! 449: Con_DPrintf ("Clearing memory\n"); ! 450: D_FlushCaches (); ! 451: Mod_ClearAll (); ! 452: if (host_hunklevel) ! 453: Hunk_FreeToLowMark (host_hunklevel); ! 454: ! 455: cls.signon = 0; ! 456: memset (&sv, 0, sizeof(sv)); ! 457: memset (&cl, 0, sizeof(cl)); ! 458: } ! 459: ! 460: ! 461: //============================================================================ ! 462: ! 463: ! 464: /* ! 465: =================== ! 466: Host_FilterTime ! 467: ! 468: Returns false if the time is too short to run a frame ! 469: =================== ! 470: */ ! 471: qboolean Host_FilterTime (float time) ! 472: { ! 473: realtime += time; ! 474: ! 475: if (!cls.timedemo && realtime - oldrealtime < 1.0/72) ! 476: return false; // framerate is too high ! 477: ! 478: host_frametime = realtime - oldrealtime; ! 479: oldrealtime = realtime; ! 480: ! 481: if (host_framerate.value > 0) ! 482: host_frametime = host_framerate.value; ! 483: else ! 484: { // don't allow really long or short frames ! 485: if (host_frametime > 0.1) ! 486: host_frametime = 0.1; ! 487: if (host_frametime < 0.001) ! 488: host_frametime = 0.001; ! 489: } ! 490: ! 491: return true; ! 492: } ! 493: ! 494: ! 495: /* ! 496: =================== ! 497: Host_GetConsoleCommands ! 498: ! 499: Add them exactly as if they had been typed at the console ! 500: =================== ! 501: */ ! 502: void Host_GetConsoleCommands (void) ! 503: { ! 504: char *cmd; ! 505: ! 506: while (1) ! 507: { ! 508: cmd = Sys_ConsoleInput (); ! 509: if (!cmd) ! 510: break; ! 511: Cbuf_AddText (cmd); ! 512: } ! 513: } ! 514: ! 515: /* ! 516: ================== ! 517: Host_ServerFrame ! 518: ! 519: ================== ! 520: */ ! 521: void Host_ServerFrame (void) ! 522: { ! 523: // run the world state ! 524: pr_global_struct->frametime = host_frametime; ! 525: ! 526: // set the time and clear the general datagram ! 527: SV_ClearDatagram (); ! 528: ! 529: // check for new clients ! 530: SV_CheckForNewClients (); ! 531: ! 532: // read client messages ! 533: SV_RunClients (); ! 534: ! 535: // move things around and think ! 536: // allways pause in single player if in console or menus ! 537: if (!sv.paused && (svs.maxclients > 1 || key_dest == key_game) ) ! 538: SV_Physics (); ! 539: ! 540: // send all messages to the clients ! 541: SV_SendClientMessages (); ! 542: } ! 543: ! 544: /* ! 545: ================== ! 546: Host_Frame ! 547: ! 548: Runs all active servers ! 549: ================== ! 550: */ ! 551: void _Host_Frame (float time) ! 552: { ! 553: static double time1 = 0; ! 554: static double time2 = 0; ! 555: static double time3 = 0; ! 556: int pass1, pass2, pass3; ! 557: ! 558: if (setjmp (host_abortserver) ) ! 559: return; // something bad happened, or the server disconnected ! 560: ! 561: // keep the random time dependent ! 562: rand (); ! 563: ! 564: // decide the simulation time ! 565: if (!Host_FilterTime (time)) ! 566: return; // don't run too fast, or packets will flood out ! 567: ! 568: // get new key events ! 569: Sys_SendKeyEvents (); ! 570: ! 571: // allow mice or other external controllers to add commands ! 572: IN_Commands (); ! 573: ! 574: // process console commands ! 575: Cbuf_Execute (); ! 576: ! 577: NET_Poll(); ! 578: ! 579: // if running the server locally, make intentions now ! 580: if (sv.active) ! 581: CL_SendCmd (); ! 582: ! 583: //------------------- ! 584: // ! 585: // server operations ! 586: // ! 587: //------------------- ! 588: ! 589: // check for commands typed to the host ! 590: Host_GetConsoleCommands (); ! 591: ! 592: if (sv.active) ! 593: Host_ServerFrame (); ! 594: ! 595: //------------------- ! 596: // ! 597: // client operations ! 598: // ! 599: //------------------- ! 600: ! 601: // if running the server remotely, send intentions now after ! 602: // the incoming messages have been read ! 603: if (!sv.active) ! 604: CL_SendCmd (); ! 605: ! 606: host_time += host_frametime; ! 607: ! 608: // fetch results from server ! 609: if (cls.state == ca_connected) ! 610: CL_ReadFromServer (); ! 611: ! 612: // update video ! 613: if (host_speeds.value) ! 614: time1 = Sys_FloatTime (); ! 615: ! 616: SCR_UpdateScreen (); ! 617: ! 618: if (host_speeds.value) ! 619: time2 = Sys_FloatTime (); ! 620: ! 621: // update audio ! 622: if (cls.signon == SIGNONS) ! 623: { ! 624: S_Update (r_origin, vpn, vright, vup); ! 625: CL_DecayLights (); ! 626: } ! 627: else ! 628: S_Update (vec3_origin, vec3_origin, vec3_origin, vec3_origin); ! 629: ! 630: CDAudio_Update(); ! 631: ! 632: if (host_speeds.value) ! 633: { ! 634: pass1 = (time1 - time3)*1000; ! 635: time3 = Sys_FloatTime (); ! 636: pass2 = (time2 - time1)*1000; ! 637: pass3 = (time3 - time2)*1000; ! 638: Con_Printf ("%3i tot %3i server %3i gfx %3i snd\n", ! 639: pass1+pass2+pass3, pass1, pass2, pass3); ! 640: } ! 641: ! 642: host_framecount++; ! 643: } ! 644: ! 645: void Host_Frame (float time) ! 646: { ! 647: double time1, time2; ! 648: static double timetotal; ! 649: static int timecount; ! 650: int i, c, m; ! 651: ! 652: if (!serverprofile.value) ! 653: { ! 654: _Host_Frame (time); ! 655: return; ! 656: } ! 657: ! 658: time1 = Sys_FloatTime (); ! 659: _Host_Frame (time); ! 660: time2 = Sys_FloatTime (); ! 661: ! 662: timetotal += time2 - time1; ! 663: timecount++; ! 664: ! 665: if (timecount < 1000) ! 666: return; ! 667: ! 668: m = timetotal*1000/timecount; ! 669: timecount = 0; ! 670: timetotal = 0; ! 671: c = 0; ! 672: for (i=0 ; i<svs.maxclients ; i++) ! 673: { ! 674: if (svs.clients[i].active) ! 675: c++; ! 676: } ! 677: ! 678: Con_Printf ("serverprofile: %2i clients %2i msec\n", c, m); ! 679: } ! 680: ! 681: //============================================================================ ! 682: ! 683: ! 684: extern int vcrFile; ! 685: #define VCR_SIGNATURE 0x56435231 ! 686: // "VCR1" ! 687: ! 688: void Host_InitVCR (quakeparms_t *parms) ! 689: { ! 690: int i, len, n; ! 691: char *p; ! 692: ! 693: if (COM_CheckParm("-playback")) ! 694: { ! 695: if (com_argc != 2) ! 696: Sys_Error("No other parameters allowed with -playback\n"); ! 697: ! 698: Sys_FileOpenRead("quake.vcr", &vcrFile); ! 699: if (vcrFile == -1) ! 700: Sys_Error("playback file not found\n"); ! 701: ! 702: Sys_FileRead (vcrFile, &i, sizeof(int)); ! 703: if (i != VCR_SIGNATURE) ! 704: Sys_Error("Invalid signature in vcr file\n"); ! 705: ! 706: Sys_FileRead (vcrFile, &com_argc, sizeof(int)); ! 707: com_argv = malloc(com_argc * sizeof(char *)); ! 708: com_argv[0] = parms->argv[0]; ! 709: for (i = 0; i < com_argc; i++) ! 710: { ! 711: Sys_FileRead (vcrFile, &len, sizeof(int)); ! 712: p = malloc(len); ! 713: Sys_FileRead (vcrFile, p, len); ! 714: com_argv[i+1] = p; ! 715: } ! 716: com_argc++; /* add one for arg[0] */ ! 717: parms->argc = com_argc; ! 718: parms->argv = com_argv; ! 719: } ! 720: ! 721: if ( (n = COM_CheckParm("-record")) != 0) ! 722: { ! 723: vcrFile = Sys_FileOpenWrite("quake.vcr"); ! 724: ! 725: i = VCR_SIGNATURE; ! 726: Sys_FileWrite(vcrFile, &i, sizeof(int)); ! 727: i = com_argc - 1; ! 728: Sys_FileWrite(vcrFile, &i, sizeof(int)); ! 729: for (i = 1; i < com_argc; i++) ! 730: { ! 731: if (i == n) ! 732: { ! 733: len = 10; ! 734: Sys_FileWrite(vcrFile, &len, sizeof(int)); ! 735: Sys_FileWrite(vcrFile, "-playback", len); ! 736: continue; ! 737: } ! 738: len = Q_strlen(com_argv[i]) + 1; ! 739: Sys_FileWrite(vcrFile, &len, sizeof(int)); ! 740: Sys_FileWrite(vcrFile, com_argv[i], len); ! 741: } ! 742: } ! 743: ! 744: } ! 745: ! 746: /* ! 747: ==================== ! 748: Host_Init ! 749: ==================== ! 750: */ ! 751: void Host_Init (quakeparms_t *parms) ! 752: { ! 753: ! 754: if (COM_CheckParm ("-minmemory")) ! 755: parms->memsize = MINIMUM_MEMORY; ! 756: ! 757: host_parms = *parms; ! 758: ! 759: if (parms->memsize < MINIMUM_MEMORY) ! 760: Sys_Error ("Only %4.1f megs of memory reported, can't execute game", parms->memsize / (float)0x100000); ! 761: ! 762: com_argc = parms->argc; ! 763: com_argv = parms->argv; ! 764: ! 765: Memory_Init (parms->membase, parms->memsize); ! 766: Cbuf_Init (); ! 767: Cmd_Init (); ! 768: V_Init (); ! 769: Host_InitVCR (parms); ! 770: COM_Init (parms->basedir); ! 771: Host_InitLocal (); ! 772: W_LoadWadFile ("gfx.wad"); ! 773: Key_Init (); ! 774: Con_Init (); ! 775: M_Init (); ! 776: PR_Init (); ! 777: Mod_Init (); ! 778: NET_Init (); ! 779: SV_Init (); ! 780: ! 781: Con_Printf ("Exe: "__TIME__" "__DATE__"\n"); ! 782: Con_Printf ("%4.1f megabyte heap\n",parms->memsize/ (1024*1024.0)); ! 783: ! 784: R_InitTextures (); // needed even for dedicated servers ! 785: ! 786: if (cls.state != ca_dedicated) ! 787: { ! 788: host_basepal = (byte *)COM_LoadHunkFile ("gfx/palette.lmp"); ! 789: if (!host_basepal) ! 790: Sys_Error ("Couldn't load gfx/palette.lmp"); ! 791: host_colormap = (byte *)COM_LoadHunkFile ("gfx/colormap.lmp"); ! 792: if (!host_colormap) ! 793: Sys_Error ("Couldn't load gfx/colormap.lmp"); ! 794: ! 795: VID_Init (host_basepal); ! 796: ! 797: Draw_Init (); ! 798: SCR_Init (); ! 799: R_Init (); ! 800: S_Init (); ! 801: CDAudio_Init (); ! 802: Sbar_Init (); ! 803: CL_Init (); ! 804: IN_Init (); ! 805: } ! 806: ! 807: Cbuf_InsertText ("exec quake.rc\n"); ! 808: ! 809: Hunk_AllocName (0, "-HOST_HUNKLEVEL-"); ! 810: host_hunklevel = Hunk_LowMark (); ! 811: ! 812: host_initialized = true; ! 813: ! 814: Sys_Printf ("========Quake Initialized=========\n"); ! 815: } ! 816: ! 817: ! 818: /* ! 819: =============== ! 820: Host_Shutdown ! 821: ! 822: FIXME: this is a callback from Sys_Quit and Sys_Error. It would be better ! 823: to run quit through here before the final handoff to the sys code. ! 824: =============== ! 825: */ ! 826: void Host_Shutdown(void) ! 827: { ! 828: static qboolean isdown = false; ! 829: ! 830: if (isdown) ! 831: { ! 832: printf ("recursive shutdown\n"); ! 833: return; ! 834: } ! 835: isdown = true; ! 836: ! 837: Host_WriteConfiguration (); ! 838: ! 839: CDAudio_Shutdown (); ! 840: NET_Shutdown (); ! 841: S_Shutdown(); ! 842: IN_Shutdown (); ! 843: if (host_basepal) ! 844: VID_Shutdown(); ! 845: } ! 846:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.