1 /*
2 ===========================================================================
3 Copyright (C) 1999 - 2005, Id Software, Inc.
4 Copyright (C) 2000 - 2013, Raven Software, Inc.
5 Copyright (C) 2001 - 2013, Activision, Inc.
6 Copyright (C) 2013 - 2015, OpenJK contributors
7
8 This file is part of the OpenJK source code.
9
10 OpenJK is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License version 2 as
12 published by the Free Software Foundation.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 ===========================================================================
22 */
23
24 // cl_cgame.c -- client system interaction with client game
25
26 // leave this as first line for PCH reasons...
27 //
28 #include "../server/exe_headers.h"
29 #include "../ui/ui_shared.h"
30
31 #include "client.h"
32 #include "vmachine.h"
33 #include "qcommon/stringed_ingame.h"
34 #include "sys/sys_loadlib.h"
35
36 vm_t cgvm;
37 /*
38 Ghoul2 Insert Start
39 */
40
41 #if !defined(G2_H_INC)
42 #include "../ghoul2/G2.h"
43 #endif
44
45 /*
46 Ghoul2 Insert End
47 */
48
49 //FIXME: Temp
50 extern void S_UpdateAmbientSet ( const char *name, vec3_t origin );
51 extern int S_AddLocalSet( const char *name, vec3_t listener_origin, vec3_t origin, int entID, int time );
52 extern void AS_ParseSets( void );
53 extern sfxHandle_t AS_GetBModelSound( const char *name, int stage );
54 extern void AS_AddPrecacheEntry( const char *name );
55 extern menuDef_t *Menus_FindByName(const char *p);
56
57 extern qboolean R_inPVS( vec3_t p1, vec3_t p2 );
58
59 void UI_SetActiveMenu( const char* menuname,const char *menuID );
60
CL_InitCGameVM(void * gameLibrary)61 qboolean CL_InitCGameVM( void *gameLibrary )
62 {
63 typedef intptr_t SyscallProc( intptr_t, ... );
64 typedef void DllEntryProc( SyscallProc * );
65
66 DllEntryProc *dllEntry = (DllEntryProc *)Sys_LoadFunction( gameLibrary, "dllEntry" );
67 cgvm.entryPoint = (intptr_t (*)(int,...))Sys_LoadFunction( gameLibrary, "vmMain" );
68
69 if ( !cgvm.entryPoint || !dllEntry ) {
70 #ifdef JK2_MODE
71 const char *gamename = "jospgame";
72 #else
73 const char *gamename = "jagame";
74 #endif
75
76 Com_Printf( "CL_InitCGameVM: client game entry point not found in %s" ARCH_STRING DLL_EXT ": %s\n",
77 gamename, Sys_LibraryError() );
78 return qfalse;
79 }
80
81 dllEntry( VM_DllSyscall );
82
83 return qtrue;
84 }
85
86 /*
87 ====================
88 CL_GetGameState
89 ====================
90 */
CL_GetGameState(gameState_t * gs)91 void CL_GetGameState( gameState_t *gs ) {
92 *gs = cl.gameState;
93 }
94
95 /*
96 ====================
97 CL_GetGlconfig
98 ====================
99 */
CL_GetGlconfig(glconfig_t * glconfig)100 void CL_GetGlconfig( glconfig_t *glconfig ) {
101 *glconfig = cls.glconfig;
102 }
103
104
105 /*
106 ====================
107 CL_GetUserCmd
108 ====================
109 */
CL_GetUserCmd(int cmdNumber,usercmd_t * ucmd)110 qboolean CL_GetUserCmd( int cmdNumber, usercmd_t *ucmd ) {
111 // cmds[cmdNumber] is the last properly generated command
112
113 // can't return anything that we haven't created yet
114 if ( cmdNumber > cl.cmdNumber ) {
115 Com_Error( ERR_DROP, "CL_GetUserCmd: %i >= %i", cmdNumber, cl.cmdNumber );
116 }
117
118 // the usercmd has been overwritten in the wrapping
119 // buffer because it is too far out of date
120 if ( cmdNumber <= cl.cmdNumber - CMD_BACKUP ) {
121 return qfalse;
122 }
123
124 *ucmd = cl.cmds[ cmdNumber & CMD_MASK ];
125
126 return qtrue;
127 }
128
CL_GetCurrentCmdNumber(void)129 int CL_GetCurrentCmdNumber( void ) {
130 return cl.cmdNumber;
131 }
132
133
134 /*
135 ====================
136 CL_GetParseEntityState
137 ====================
138 */
139 /*
140 qboolean CL_GetParseEntityState( int parseEntityNumber, entityState_t *state ) {
141 // can't return anything that hasn't been parsed yet
142 if ( parseEntityNumber >= cl.parseEntitiesNum ) {
143 Com_Error( ERR_DROP, "CL_GetParseEntityState: %i >= %i",
144 parseEntityNumber, cl.parseEntitiesNum );
145 }
146
147 // can't return anything that has been overwritten in the circular buffer
148 if ( parseEntityNumber <= cl.parseEntitiesNum - MAX_PARSE_ENTITIES ) {
149 return qfalse;
150 }
151
152 *state = cl.parseEntities[ parseEntityNumber & ( MAX_PARSE_ENTITIES - 1 ) ];
153 return qtrue;
154 }
155 */
156
157 /*
158 ====================
159 CL_GetCurrentSnapshotNumber
160 ====================
161 */
CL_GetCurrentSnapshotNumber(int * snapshotNumber,int * serverTime)162 void CL_GetCurrentSnapshotNumber( int *snapshotNumber, int *serverTime ) {
163 *snapshotNumber = cl.frame.messageNum;
164 *serverTime = cl.frame.serverTime;
165 }
166
167 /*
168 ====================
169 CL_GetSnapshot
170 ====================
171 */
CL_GetSnapshot(int snapshotNumber,snapshot_t * snapshot)172 qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) {
173 clSnapshot_t *clSnap;
174 int i, count;
175
176 if ( snapshotNumber > cl.frame.messageNum ) {
177 Com_Error( ERR_DROP, "CL_GetSnapshot: snapshotNumber > cl.frame.messageNum" );
178 }
179
180 // if the frame has fallen out of the circular buffer, we can't return it
181 if ( cl.frame.messageNum - snapshotNumber >= PACKET_BACKUP ) {
182 return qfalse;
183 }
184
185 // if the frame is not valid, we can't return it
186 clSnap = &cl.frames[snapshotNumber & PACKET_MASK];
187 if ( !clSnap->valid ) {
188 return qfalse;
189 }
190
191 // if the entities in the frame have fallen out of their
192 // circular buffer, we can't return it
193 if ( cl.parseEntitiesNum - clSnap->parseEntitiesNum >= MAX_PARSE_ENTITIES ) {
194 return qfalse;
195 }
196
197 // write the snapshot
198 snapshot->snapFlags = clSnap->snapFlags;
199 snapshot->serverCommandSequence = clSnap->serverCommandNum;
200 snapshot->serverTime = clSnap->serverTime;
201 memcpy( snapshot->areamask, clSnap->areamask, sizeof( snapshot->areamask ) );
202 snapshot->cmdNum = clSnap->cmdNum;
203 snapshot->ps = clSnap->ps;
204 count = clSnap->numEntities;
205 if ( count > MAX_ENTITIES_IN_SNAPSHOT ) {
206 Com_DPrintf( "CL_GetSnapshot: truncated %i entities to %i\n", count, MAX_ENTITIES_IN_SNAPSHOT );
207 count = MAX_ENTITIES_IN_SNAPSHOT;
208 }
209 snapshot->numEntities = count;
210 /*
211 Ghoul2 Insert Start
212 */
213 for ( i = 0 ; i < count ; i++ )
214 {
215
216 int entNum = ( clSnap->parseEntitiesNum + i ) & (MAX_PARSE_ENTITIES-1) ;
217 snapshot->entities[i] = cl.parseEntities[ entNum ];
218 }
219 /*
220 Ghoul2 Insert End
221 */
222
223
224 // FIXME: configstring changes and server commands!!!
225
226 return qtrue;
227 }
228
229 //bg_public.h won't cooperate in here
230 #define EF_PERMANENT 0x00080000
231
CL_GetDefaultState(int index,entityState_t * state)232 qboolean CL_GetDefaultState(int index, entityState_t *state)
233 {
234 if (index < 0 || index >= MAX_GENTITIES)
235 {
236 return qfalse;
237 }
238
239 // Is this safe? I think so. But it's still ugly as sin.
240 if (!(sv.svEntities[index].baseline.eFlags & EF_PERMANENT))
241 // if (!(cl.entityBaselines[index].eFlags & EF_PERMANENT))
242 {
243 return qfalse;
244 }
245
246 *state = sv.svEntities[index].baseline;
247 // *state = cl.entityBaselines[index];
248
249 return qtrue;
250 }
251
252 extern float cl_mPitchOverride;
253 extern float cl_mYawOverride;
CL_SetUserCmdValue(int userCmdValue,float sensitivityScale,float mPitchOverride,float mYawOverride)254 void CL_SetUserCmdValue( int userCmdValue, float sensitivityScale, float mPitchOverride, float mYawOverride ) {
255 cl.cgameUserCmdValue = userCmdValue;
256 cl.cgameSensitivity = sensitivityScale;
257 cl_mPitchOverride = mPitchOverride;
258 cl_mYawOverride = mYawOverride;
259 }
260
261 extern vec3_t cl_overriddenAngles;
262 extern qboolean cl_overrideAngles;
CL_SetUserCmdAngles(float pitchOverride,float yawOverride,float rollOverride)263 void CL_SetUserCmdAngles( float pitchOverride, float yawOverride, float rollOverride ) {
264 cl_overriddenAngles[PITCH] = pitchOverride;
265 cl_overriddenAngles[YAW] = yawOverride;
266 cl_overriddenAngles[ROLL] = rollOverride;
267 cl_overrideAngles = qtrue;
268 }
269
CL_AddCgameCommand(const char * cmdName)270 void CL_AddCgameCommand( const char *cmdName ) {
271 Cmd_AddCommand( cmdName, NULL );
272 }
273
274 /*
275 =====================
276 CL_ConfigstringModified
277 =====================
278 */
CL_ConfigstringModified(void)279 void CL_ConfigstringModified( void ) {
280 const char *s;
281 char *old;
282 int i, index;
283 const char *dup;
284 gameState_t oldGs;
285 int len;
286
287 index = atoi( Cmd_Argv(1) );
288 if ( index < 0 || index >= MAX_CONFIGSTRINGS ) {
289 Com_Error( ERR_DROP, "configstring > MAX_CONFIGSTRINGS" );
290 }
291 s = Cmd_Argv(2);
292
293 old = cl.gameState.stringData + cl.gameState.stringOffsets[ index ];
294 if ( !strcmp( old, s ) ) {
295 return; // unchanged
296 }
297
298 // build the new gameState_t
299 oldGs = cl.gameState;
300
301 memset( &cl.gameState, 0, sizeof( cl.gameState ) );
302
303 // leave the first 0 for uninitialized strings
304 cl.gameState.dataCount = 1;
305
306 for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
307 if ( i == index ) {
308 dup = s;
309 } else {
310 dup = oldGs.stringData + oldGs.stringOffsets[ i ];
311 }
312 if ( !dup[0] ) {
313 continue; // leave with the default empty string
314 }
315
316 len = strlen( dup );
317
318 if ( len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS ) {
319 Com_Error( ERR_DROP, "MAX_GAMESTATE_CHARS exceeded" );
320 }
321
322 // append it to the gameState string buffer
323 cl.gameState.stringOffsets[ i ] = cl.gameState.dataCount;
324 memcpy( cl.gameState.stringData + cl.gameState.dataCount, dup, len + 1 );
325 cl.gameState.dataCount += len + 1;
326 }
327
328 if ( index == CS_SYSTEMINFO ) {
329 // parse serverId and other cvars
330 CL_SystemInfoChanged();
331 }
332
333 }
334
335
336 /*
337 ===================
338 CL_GetServerCommand
339
340 Set up argc/argv for the given command
341 ===================
342 */
CL_GetServerCommand(int serverCommandNumber)343 qboolean CL_GetServerCommand( int serverCommandNumber ) {
344 char *s;
345 const char *cmd;
346
347 // if we have irretrievably lost a reliable command, drop the connection
348 if ( serverCommandNumber <= clc.serverCommandSequence - MAX_RELIABLE_COMMANDS ) {
349 Com_Error( ERR_DROP, "CL_GetServerCommand: a reliable command was cycled out" );
350 return qfalse;
351 }
352
353 if ( serverCommandNumber > clc.serverCommandSequence ) {
354 Com_Error( ERR_DROP, "CL_GetServerCommand: requested a command not received" );
355 return qfalse;
356 }
357
358 s = clc.serverCommands[ serverCommandNumber & ( MAX_RELIABLE_COMMANDS - 1 ) ];
359
360 Com_DPrintf( "serverCommand: %i : %s\n", serverCommandNumber, s );
361
362 Cmd_TokenizeString( s );
363 cmd = Cmd_Argv(0);
364
365 if ( !strcmp( cmd, "disconnect" ) ) {
366 Com_Error (ERR_DISCONNECT,"Server disconnected\n");
367 }
368
369 if ( !strcmp( cmd, "cs" ) ) {
370 CL_ConfigstringModified();
371 // reparse the string, because CL_ConfigstringModified may have done another Cmd_TokenizeString()
372 Cmd_TokenizeString( s );
373 return qtrue;
374 }
375
376 // the clientLevelShot command is used during development
377 // to generate 128*128 screenshots from the intermission
378 // point of levels for the menu system to use
379 // we pass it along to the cgame to make apropriate adjustments,
380 // but we also clear the console and notify lines here
381 if ( !strcmp( cmd, "clientLevelShot" ) ) {
382 // don't do it if we aren't running the server locally,
383 // otherwise malicious remote servers could overwrite
384 // the existing thumbnails
385 if ( !com_sv_running->integer ) {
386 return qfalse;
387 }
388 // close the console
389 Con_Close();
390 // take a special screenshot next frame
391 Cbuf_AddText( "wait ; wait ; wait ; wait ; screenshot levelshot\n" );
392 return qtrue;
393 }
394
395 // we may want to put a "connect to other server" command here
396
397 // cgame can now act on the command
398 return qtrue;
399 }
400
401
402 /*
403 ====================
404 CL_CM_LoadMap
405
406 Just adds default parameters that cgame doesn't need to know about
407 ====================
408 */
CL_CM_LoadMap(const char * mapname,qboolean subBSP)409 void CL_CM_LoadMap( const char *mapname, qboolean subBSP ) {
410 int checksum;
411
412 CM_LoadMap( mapname, qtrue, &checksum, subBSP );
413 }
414
415 /*
416 ====================
417 CL_ShutdonwCGame
418
419 ====================
420 */
CL_ShutdownCGame(void)421 void CL_ShutdownCGame( void ) {
422 cls.cgameStarted = qfalse;
423
424 if ( !cgvm.entryPoint) {
425 return;
426 }
427 VM_Call( CG_SHUTDOWN );
428
429 // VM_Free( cgvm );
430 // cgvm = NULL;
431 }
432
433 #ifdef JK2_MODE
434 /*
435 ====================
436 CL_ConvertJK2SysCall
437
438 Converts a JK2 syscall to a JKA syscall
439 ====================
440 */
441
CL_ConvertJK2SysCall(cgameJK2Import_t import)442 cgameImport_t CL_ConvertJK2SysCall( cgameJK2Import_t import )
443 {
444 // FIXME: This was a 5-minute slap-hack job in order to test if this really works. CLEAN ME UP! --eez
445 switch(import)
446 {
447 case CG_PRINT_JK2:
448 return CG_PRINT;
449 break;
450 case CG_ERROR_JK2:
451 return CG_ERROR;
452 break;
453 case CG_MILLISECONDS_JK2:
454 return CG_MILLISECONDS;
455 break;
456 case CG_CVAR_REGISTER_JK2:
457 return CG_CVAR_REGISTER;
458 break;
459 case CG_CVAR_UPDATE_JK2:
460 return CG_CVAR_UPDATE;
461 break;
462 case CG_CVAR_SET_JK2:
463 return CG_CVAR_SET;
464 break;
465 case CG_ARGC_JK2:
466 return CG_ARGC;
467 break;
468 case CG_ARGV_JK2:
469 return CG_ARGV;
470 break;
471 case CG_ARGS_JK2:
472 return CG_ARGS;
473 break;
474 case CG_FS_FOPENFILE_JK2:
475 return CG_FS_FOPENFILE;
476 break;
477 case CG_FS_READ_JK2:
478 return CG_FS_READ;
479 break;
480 case CG_FS_WRITE_JK2:
481 return CG_FS_WRITE;
482 break;
483 case CG_FS_FCLOSEFILE_JK2:
484 return CG_FS_FCLOSEFILE;
485 break;
486 case CG_SENDCONSOLECOMMAND_JK2:
487 return CG_SENDCONSOLECOMMAND;
488 break;
489 case CG_ADDCOMMAND_JK2:
490 return CG_ADDCOMMAND;
491 break;
492 case CG_SENDCLIENTCOMMAND_JK2:
493 return CG_SENDCLIENTCOMMAND;
494 break;
495 case CG_UPDATESCREEN_JK2:
496 return CG_UPDATESCREEN;
497 break;
498 case CG_CM_LOADMAP_JK2:
499 return CG_CM_LOADMAP;
500 break;
501 case CG_CM_NUMINLINEMODELS_JK2:
502 return CG_CM_NUMINLINEMODELS;
503 break;
504 case CG_CM_INLINEMODEL_JK2:
505 return CG_CM_INLINEMODEL;
506 break;
507 case CG_CM_TEMPBOXMODEL_JK2:
508 return CG_CM_TEMPBOXMODEL;
509 break;
510 case CG_CM_POINTCONTENTS_JK2:
511 return CG_CM_POINTCONTENTS;
512 break;
513 case CG_CM_TRANSFORMEDPOINTCONTENTS_JK2:
514 return CG_CM_TRANSFORMEDPOINTCONTENTS;
515 break;
516 case CG_CM_BOXTRACE_JK2:
517 return CG_CM_BOXTRACE;
518 break;
519 case CG_CM_TRANSFORMEDBOXTRACE_JK2:
520 return CG_CM_TRANSFORMEDBOXTRACE;
521 break;
522 case CG_CM_MARKFRAGMENTS_JK2:
523 return CG_CM_MARKFRAGMENTS;
524 break;
525 case CG_CM_SNAPPVS_JK2:
526 return CG_CM_SNAPPVS;
527 break;
528 case CG_S_STARTSOUND_JK2:
529 return CG_S_STARTSOUND;
530 break;
531 case CG_S_STARTLOCALSOUND_JK2:
532 return CG_S_STARTLOCALSOUND;
533 break;
534 case CG_S_CLEARLOOPINGSOUNDS_JK2:
535 return CG_S_CLEARLOOPINGSOUNDS;
536 break;
537 case CG_S_ADDLOOPINGSOUND_JK2:
538 return CG_S_ADDLOOPINGSOUND;
539 break;
540 case CG_S_UPDATEENTITYPOSITION_JK2:
541 return CG_S_UPDATEENTITYPOSITION;
542 break;
543 case CG_S_RESPATIALIZE_JK2:
544 return CG_S_RESPATIALIZE;
545 break;
546 case CG_S_REGISTERSOUND_JK2:
547 return CG_S_REGISTERSOUND;
548 break;
549 case CG_S_STARTBACKGROUNDTRACK_JK2:
550 return CG_S_STARTBACKGROUNDTRACK;
551 break;
552 case CG_R_LOADWORLDMAP_JK2:
553 return CG_R_LOADWORLDMAP;
554 break;
555 case CG_R_REGISTERMODEL_JK2:
556 return CG_R_REGISTERMODEL;
557 break;
558 case CG_R_REGISTERSKIN_JK2:
559 return CG_R_REGISTERSKIN;
560 break;
561 case CG_R_REGISTERSHADER_JK2:
562 return CG_R_REGISTERSHADER;
563 break;
564 case CG_R_REGISTERSHADERNOMIP_JK2:
565 return CG_R_REGISTERSHADERNOMIP;
566 break;
567 case CG_R_REGISTERFONT_JK2:
568 return CG_R_REGISTERFONT;
569 break;
570 case CG_R_FONTSTRLENPIXELS_JK2:
571 return CG_R_FONTSTRLENPIXELS;
572 break;
573 case CG_R_FONTSTRLENCHARS_JK2:
574 return CG_R_FONTSTRLENCHARS;
575 break;
576 case CG_R_FONTHEIGHTPIXELS_JK2:
577 return CG_R_FONTHEIGHTPIXELS;
578 break;
579 case CG_R_FONTDRAWSTRING_JK2:
580 return CG_R_FONTDRAWSTRING;
581 break;
582 case CG_LANGUAGE_ISASIAN_JK2:
583 return CG_LANGUAGE_ISASIAN;
584 break;
585 case CG_LANGUAGE_USESSPACES_JK2:
586 return CG_LANGUAGE_USESSPACES;
587 break;
588 case CG_ANYLANGUAGE_READFROMSTRING_JK2:
589 return CG_ANYLANGUAGE_READFROMSTRING;
590 break;
591 case CG_R_CLEARSCENE_JK2:
592 return CG_R_CLEARSCENE;
593 break;
594 case CG_R_ADDREFENTITYTOSCENE_JK2:
595 return CG_R_ADDREFENTITYTOSCENE;
596 break;
597 case CG_R_GETLIGHTING_JK2:
598 return CG_R_GETLIGHTING;
599 break;
600 case CG_R_ADDPOLYTOSCENE_JK2:
601 return CG_R_ADDPOLYTOSCENE;
602 break;
603 case CG_R_ADDLIGHTTOSCENE_JK2:
604 return CG_R_ADDLIGHTTOSCENE;
605 break;
606 case CG_R_RENDERSCENE_JK2:
607 return CG_R_RENDERSCENE;
608 break;
609 case CG_R_SETCOLOR_JK2:
610 return CG_R_SETCOLOR;
611 break;
612 case CG_R_DRAWSTRETCHPIC_JK2:
613 return CG_R_DRAWSTRETCHPIC;
614 break;
615 case CG_R_DRAWSCREENSHOT_JK2:
616 return CG_R_DRAWSCREENSHOT;
617 break;
618 case CG_R_MODELBOUNDS_JK2:
619 return CG_R_MODELBOUNDS;
620 break;
621 case CG_R_LERPTAG_JK2:
622 return CG_R_LERPTAG;
623 break;
624 case CG_R_DRAWROTATEPIC_JK2:
625 return CG_R_DRAWROTATEPIC;
626 break;
627 case CG_R_DRAWROTATEPIC2_JK2:
628 return CG_R_DRAWROTATEPIC2;
629 break;
630 case CG_R_LA_GOGGLES_JK2:
631 return CG_R_LA_GOGGLES;
632 break;
633 case CG_R_SCISSOR_JK2:
634 return CG_R_SCISSOR;
635 break;
636 case CG_GETGLCONFIG_JK2:
637 return CG_GETGLCONFIG;
638 break;
639 case CG_GETGAMESTATE_JK2:
640 return CG_GETGAMESTATE;
641 break;
642 case CG_GETCURRENTSNAPSHOTNUMBER_JK2:
643 return CG_GETCURRENTSNAPSHOTNUMBER;
644 break;
645 case CG_GETSNAPSHOT_JK2:
646 return CG_GETSNAPSHOT;
647 break;
648 case CG_GETSERVERCOMMAND_JK2:
649 return CG_GETSERVERCOMMAND;
650 break;
651 case CG_GETCURRENTCMDNUMBER_JK2:
652 return CG_GETCURRENTCMDNUMBER;
653 break;
654 case CG_GETUSERCMD_JK2:
655 return CG_GETUSERCMD;
656 break;
657 case CG_SETUSERCMDVALUE_JK2:
658 return CG_SETUSERCMDVALUE;
659 break;
660 case CG_SETUSERCMDANGLES_JK2:
661 return CG_SETUSERCMDANGLES;
662 break;
663 case CG_S_UPDATEAMBIENTSET_JK2:
664 return CG_S_UPDATEAMBIENTSET;
665 break;
666 case CG_S_ADDLOCALSET_JK2:
667 return CG_S_ADDLOCALSET;
668 break;
669 case CG_AS_PARSESETS_JK2:
670 return CG_AS_PARSESETS;
671 break;
672 case CG_AS_ADDENTRY_JK2:
673 return CG_AS_ADDENTRY;
674 break;
675 case CG_AS_GETBMODELSOUND_JK2:
676 return CG_AS_GETBMODELSOUND;
677 break;
678 case CG_S_GETSAMPLELENGTH_JK2:
679 return CG_S_GETSAMPLELENGTH;
680 break;
681 case COM_SETORGANGLES_JK2:
682 return COM_SETORGANGLES;
683 break;
684 /*
685 Ghoul2 Insert Start
686 */
687 case CG_G2_LISTBONES_JK2:
688 return CG_G2_LISTBONES;
689 break;
690 case CG_G2_LISTSURFACES_JK2:
691 return CG_G2_LISTSURFACES;
692 break;
693 case CG_G2_HAVEWEGHOULMODELS_JK2:
694 return CG_G2_HAVEWEGHOULMODELS;
695 break;
696 case CG_G2_SETMODELS_JK2:
697 return CG_G2_SETMODELS;
698 break;
699 /*
700 Ghoul2 Insert End
701 */
702
703 case CG_R_GET_LIGHT_STYLE_JK2:
704 return CG_R_GET_LIGHT_STYLE;
705 break;
706 case CG_R_SET_LIGHT_STYLE_JK2:
707 return CG_R_SET_LIGHT_STYLE;
708 break;
709 case CG_R_GET_BMODEL_VERTS_JK2:
710 return CG_R_GET_BMODEL_VERTS;
711 break;
712 case CG_R_WORLD_EFFECT_COMMAND_JK2:
713 return CG_R_WORLD_EFFECT_COMMAND;
714 break;
715
716 case CG_CIN_PLAYCINEMATIC_JK2:
717 return CG_CIN_PLAYCINEMATIC;
718 break;
719 case CG_CIN_STOPCINEMATIC_JK2:
720 return CG_CIN_STOPCINEMATIC;
721 break;
722 case CG_CIN_RUNCINEMATIC_JK2:
723 return CG_CIN_RUNCINEMATIC;
724 break;
725 case CG_CIN_DRAWCINEMATIC_JK2:
726 return CG_CIN_DRAWCINEMATIC;
727 break;
728 case CG_CIN_SETEXTENTS_JK2:
729 return CG_CIN_SETEXTENTS;
730 break;
731 case CG_Z_MALLOC_JK2:
732 return CG_Z_MALLOC;
733 break;
734 case CG_Z_FREE_JK2:
735 return CG_Z_FREE;
736 break;
737 case CG_UI_MENU_RESET_JK2:
738 return CG_UI_MENU_RESET;
739 break;
740 case CG_UI_MENU_NEW_JK2:
741 return CG_UI_MENU_NEW;
742 break;
743 case CG_UI_PARSE_INT_JK2:
744 return CG_UI_PARSE_INT;
745 break;
746 case CG_UI_PARSE_STRING_JK2:
747 return CG_UI_PARSE_STRING;
748 break;
749 case CG_UI_PARSE_FLOAT_JK2:
750 return CG_UI_PARSE_FLOAT;
751 break;
752 case CG_UI_STARTPARSESESSION_JK2:
753 return CG_UI_STARTPARSESESSION;
754 break;
755 case CG_UI_ENDPARSESESSION_JK2:
756 return CG_UI_ENDPARSESESSION;
757 break;
758 case CG_UI_PARSEEXT_JK2:
759 return CG_UI_PARSEEXT;
760 break;
761 case CG_UI_MENUPAINT_ALL_JK2:
762 return CG_UI_MENUPAINT_ALL;
763 break;
764 case CG_UI_STRING_INIT_JK2:
765 return CG_UI_STRING_INIT;
766 break;
767 case CG_UI_GETMENUINFO_JK2:
768 return CG_UI_GETMENUINFO;
769 break;
770 case CG_SP_REGISTER_JK2:
771 return CG_SP_REGISTER;
772 break;
773 case CG_SP_GETSTRINGTEXT_JK2:
774 return CG_SP_GETSTRINGTEXT;
775 break;
776 case CG_SP_GETSTRINGTEXTSTRING_JK2:
777 // Both of these do the same thing --eez
778 return CG_SP_GETSTRINGTEXTSTRING;
779 break;
780 case CG_UI_GETITEMTEXT_JK2:
781 return CG_UI_GETITEMTEXT;
782 break;
783 case CG_ANYLANGUAGE_READFROMSTRING2_JK2:
784 return CG_ANYLANGUAGE_READFROMSTRING2;
785 break;
786 case CG_OPENJK_MENU_PAINT_JK2:
787 return CG_OPENJK_MENU_PAINT;
788 break;
789 case CG_OPENJK_GETMENU_BYNAME_JK2:
790 return CG_OPENJK_GETMENU_BYNAME;
791 break;
792 }
793 return (cgameImport_t)-1;
794 }
795
796 #endif
797 /*
798 ====================
799 CL_CgameSystemCalls
800
801 The cgame module is making a system call
802 ====================
803 */
804 void CM_SnapPVS(vec3_t origin,byte *buffer);
805 extern void Menu_Paint(menuDef_t *menu, qboolean forcePaint);
806 extern menuDef_t *Menus_FindByName(const char *p);
CL_CgameSystemCalls(intptr_t * args)807 intptr_t CL_CgameSystemCalls( intptr_t *args ) {
808 #ifdef JK2_MODE
809 args[0] = (intptr_t)CL_ConvertJK2SysCall((cgameJK2Import_t)args[0]);
810 #endif
811 switch( args[0] ) {
812 case CG_PRINT:
813 Com_Printf( "%s", VMA(1) );
814 return 0;
815 case CG_ERROR:
816 Com_Error( ERR_DROP, S_COLOR_RED"%s", VMA(1) );
817 return 0;
818 case CG_MILLISECONDS:
819 return Sys_Milliseconds();
820 case CG_CVAR_REGISTER:
821 Cvar_Register( (vmCvar_t *) VMA(1), (const char *) VMA(2), (const char *) VMA(3), args[4] );
822 return 0;
823 case CG_CVAR_UPDATE:
824 Cvar_Update( (vmCvar_t *) VMA(1) );
825 return 0;
826 case CG_CVAR_SET:
827 Cvar_Set( (const char *) VMA(1), (const char *) VMA(2) );
828 return 0;
829 case CG_ARGC:
830 return Cmd_Argc();
831 case CG_ARGV:
832 Cmd_ArgvBuffer( args[1], (char *) VMA(2), args[3] );
833 return 0;
834 case CG_ARGS:
835 Cmd_ArgsBuffer( (char *) VMA(1), args[2] );
836 return 0;
837 case CG_FS_FOPENFILE:
838 return FS_FOpenFileByMode( (const char *) VMA(1), (int *) VMA(2), (fsMode_t) args[3] );
839 case CG_FS_READ:
840 FS_Read( VMA(1), args[2], args[3] );
841 return 0;
842 case CG_FS_WRITE:
843 FS_Write( VMA(1), args[2], args[3] );
844 return 0;
845 case CG_FS_FCLOSEFILE:
846 FS_FCloseFile( args[1] );
847 return 0;
848 case CG_SENDCONSOLECOMMAND:
849 Cbuf_AddText( (const char *) VMA(1) );
850 return 0;
851 case CG_ADDCOMMAND:
852 CL_AddCgameCommand( (const char *) VMA(1) );
853 return 0;
854 case CG_SENDCLIENTCOMMAND:
855 CL_AddReliableCommand( (const char *) VMA(1) );
856 return 0;
857 case CG_UPDATESCREEN:
858 // this is used during lengthy level loading, so pump message loop
859 Com_EventLoop(); // FIXME: if a server restarts here, BAD THINGS HAPPEN!
860 SCR_UpdateScreen();
861 return 0;
862 case CG_RMG_INIT:
863 return 0;
864 case CG_CM_REGISTER_TERRAIN:
865 return 0;
866
867 case CG_RE_INIT_RENDERER_TERRAIN:
868 return 0;
869
870 case CG_CM_LOADMAP:
871 CL_CM_LoadMap( (const char *) VMA(1), (qboolean)(args[2] != 0) );
872 return 0;
873 case CG_CM_NUMINLINEMODELS:
874 return CM_NumInlineModels();
875 case CG_CM_INLINEMODEL:
876 return CM_InlineModel( args[1] );
877 case CG_CM_TEMPBOXMODEL:
878 return CM_TempBoxModel( (const float *) VMA(1), (const float *) VMA(2) );//, (int) VMA(3) );
879 case CG_CM_POINTCONTENTS:
880 return CM_PointContents( (float *)VMA(1), args[2] );
881 case CG_CM_TRANSFORMEDPOINTCONTENTS:
882 return CM_TransformedPointContents( (const float *) VMA(1), args[2], (const float *) VMA(3), (const float *) VMA(4) );
883 case CG_CM_BOXTRACE:
884 CM_BoxTrace( (trace_t *) VMA(1), (const float *) VMA(2), (const float *) VMA(3), (const float *) VMA(4), (const float *) VMA(5), args[6], args[7] );
885 return 0;
886 case CG_CM_TRANSFORMEDBOXTRACE:
887 CM_TransformedBoxTrace( (trace_t *) VMA(1), (const float *) VMA(2), (const float *) VMA(3), (const float *) VMA(4), (const float *) VMA(5), args[6], args[7], (const float *) VMA(8), (const float *) VMA(9) );
888 return 0;
889 case CG_CM_MARKFRAGMENTS:
890 return re.MarkFragments( args[1], (float(*)[3]) VMA(2), (const float *) VMA(3), args[4], (float *) VMA(5), args[6], (markFragment_t *) VMA(7) );
891 case CG_CM_SNAPPVS:
892 CM_SnapPVS((float(*))VMA(1),(byte *) VMA(2));
893 return 0;
894 case CG_S_STOPSOUNDS:
895 S_StopSounds( );
896 return 0;
897
898 case CG_S_STARTSOUND:
899 // stops an ERR_DROP internally if called illegally from game side, but note that it also gets here
900 // legally during level start where normally the internal s_soundStarted check would return. So ok to hit this.
901 if (!cls.cgameStarted) {
902 return 0;
903 }
904 S_StartSound( (float *) VMA(1), args[2], (soundChannel_t)args[3], args[4] );
905 return 0;
906 case CG_S_UPDATEAMBIENTSET:
907 // stops an ERR_DROP internally if called illegally from game side, but note that it also gets here
908 // legally during level start where normally the internal s_soundStarted check would return. So ok to hit this.
909 if (!cls.cgameStarted) {
910 return 0;
911 }
912 S_UpdateAmbientSet( (const char *) VMA(1), (float *) VMA(2) );
913 return 0;
914 case CG_S_ADDLOCALSET:
915 return S_AddLocalSet( (const char *) VMA(1), (float *) VMA(2), (float *) VMA(3), args[4], args[5] );
916 case CG_AS_PARSESETS:
917 AS_ParseSets();
918 return 0;
919 case CG_AS_ADDENTRY:
920 AS_AddPrecacheEntry( (const char *) VMA(1) );
921 return 0;
922 case CG_AS_GETBMODELSOUND:
923 return AS_GetBModelSound( (const char *) VMA(1), args[2] );
924 case CG_S_STARTLOCALSOUND:
925 // stops an ERR_DROP internally if called illegally from game side, but note that it also gets here
926 // legally during level start where normally the internal s_soundStarted check would return. So ok to hit this.
927 if (!cls.cgameStarted) {
928 return 0;
929 }
930 S_StartLocalSound( args[1], args[2] );
931 return 0;
932 case CG_S_CLEARLOOPINGSOUNDS:
933 S_ClearLoopingSounds();
934 return 0;
935 case CG_S_ADDLOOPINGSOUND:
936 // stops an ERR_DROP internally if called illegally from game side, but note that it also gets here
937 // legally during level start where normally the internal s_soundStarted check would return. So ok to hit this.
938 if (!cls.cgameStarted) {
939 return 0;
940 }
941 S_AddLoopingSound( args[1], (const float *) VMA(2), (const float *) VMA(3), args[4], (soundChannel_t)args[5] );
942 return 0;
943 case CG_S_UPDATEENTITYPOSITION:
944 S_UpdateEntityPosition( args[1], (const float *) VMA(2) );
945 return 0;
946 case CG_S_RESPATIALIZE:
947 S_Respatialize( args[1], (const float *) VMA(2), (float(*)[3]) VMA(3), (qboolean)(args[4] != 0) );
948 return 0;
949 case CG_S_REGISTERSOUND:
950 return S_RegisterSound( (const char *) VMA(1) );
951 case CG_S_STARTBACKGROUNDTRACK:
952 S_StartBackgroundTrack( (const char *) VMA(1), (const char *) VMA(2), (qboolean)(args[3] != 0) );
953 return 0;
954 case CG_S_GETSAMPLELENGTH:
955 return S_GetSampleLengthInMilliSeconds( args[1]);
956 case CG_R_LOADWORLDMAP:
957 re.LoadWorld( (const char *) VMA(1) );
958 return 0;
959 case CG_R_REGISTERMODEL:
960 return re.RegisterModel( (const char *) VMA(1) );
961 case CG_R_REGISTERSKIN:
962 return re.RegisterSkin( (const char *) VMA(1) );
963 case CG_R_REGISTERSHADER:
964 return re.RegisterShader( (const char *) VMA(1) );
965 case CG_R_REGISTERSHADERNOMIP:
966 return re.RegisterShaderNoMip( (const char *) VMA(1) );
967 case CG_R_REGISTERFONT:
968 return re.RegisterFont( (const char *) VMA(1) );
969 case CG_R_FONTSTRLENPIXELS:
970 return re.Font_StrLenPixels( (const char *) VMA(1), args[2], VMF(3) );
971 case CG_R_FONTSTRLENCHARS:
972 return re.Font_StrLenChars( (const char *) VMA(1) );
973 case CG_R_FONTHEIGHTPIXELS:
974 return re.Font_HeightPixels( args[1], VMF(2) );
975 case CG_R_FONTDRAWSTRING:
976 re.Font_DrawString(args[1],args[2], (const char *) VMA(3), (float*)args[4], args[5], args[6], VMF(7));
977 return 0;
978 case CG_LANGUAGE_ISASIAN:
979 return re.Language_IsAsian();
980 case CG_LANGUAGE_USESSPACES:
981 return re.Language_UsesSpaces();
982 case CG_ANYLANGUAGE_READFROMSTRING:
983 return re.AnyLanguage_ReadCharFromString( (char *) VMA(1), (int *) VMA(2), (qboolean *) VMA(3) );
984 case CG_ANYLANGUAGE_READFROMSTRING2:
985 return re.AnyLanguage_ReadCharFromString2( (char **) VMA(1), (qboolean *) VMA(3) );
986 case CG_R_SETREFRACTIONPROP:
987 *(re.tr_distortionAlpha()) = VMF(1);
988 *(re.tr_distortionStretch()) = VMF(2);
989 *(re.tr_distortionPrePost()) = (qboolean)args[3];
990 *(re.tr_distortionNegate()) = (qboolean)args[4];
991 return 0;
992 case CG_R_CLEARSCENE:
993 re.ClearScene();
994 return 0;
995 case CG_R_ADDREFENTITYTOSCENE:
996 re.AddRefEntityToScene( (const refEntity_t *) VMA(1) );
997 return 0;
998
999 case CG_R_INPVS:
1000 return re.R_inPVS((float *) VMA(1), (float *) VMA(2));
1001
1002 case CG_R_GETLIGHTING:
1003 return re.GetLighting( (const float * ) VMA(1), (float *) VMA(2), (float *) VMA(3), (float *) VMA(4) );
1004 case CG_R_ADDPOLYTOSCENE:
1005 re.AddPolyToScene( args[1], args[2], (const polyVert_t *) VMA(3) );
1006 return 0;
1007 case CG_R_ADDLIGHTTOSCENE:
1008 re.AddLightToScene( (const float *) VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) );
1009 return 0;
1010 case CG_R_RENDERSCENE:
1011 re.RenderScene( (const refdef_t *) VMA(1) );
1012 return 0;
1013 case CG_R_SETCOLOR:
1014 re.SetColor( (const float *) VMA(1) );
1015 return 0;
1016 case CG_R_DRAWSTRETCHPIC:
1017 re.DrawStretchPic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9] );
1018 return 0;
1019 // The below was commented out for whatever reason... /me shrugs --eez
1020 case CG_R_DRAWSCREENSHOT:
1021 re.DrawStretchRaw( VMF(1), VMF(2), VMF(3), VMF(4), SG_SCR_WIDTH, SG_SCR_HEIGHT, SCR_GetScreenshot(0), 0, qtrue);
1022 return 0;
1023 case CG_R_MODELBOUNDS:
1024 re.ModelBounds( args[1], (float *) VMA(2), (float *) VMA(3) );
1025 return 0;
1026 case CG_R_LERPTAG:
1027 re.LerpTag( (orientation_t *) VMA(1), args[2], args[3], args[4], VMF(5), (const char *) VMA(6) );
1028 return 0;
1029 case CG_R_DRAWROTATEPIC:
1030 re.DrawRotatePic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), VMF(9), args[10] );
1031 return 0;
1032 case CG_R_DRAWROTATEPIC2:
1033 re.DrawRotatePic2( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), VMF(9), args[10] );
1034 return 0;
1035 case CG_R_SETRANGEFOG:
1036 re.SetRangedFog( VMF( 1 ) );
1037 return 0;
1038 case CG_R_LA_GOGGLES:
1039 re.LAGoggles();
1040 return 0;
1041 case CG_R_SCISSOR:
1042 re.Scissor( VMF(1), VMF(2), VMF(3), VMF(4));
1043 return 0;
1044 case CG_GETGLCONFIG:
1045 CL_GetGlconfig( (glconfig_t *) VMA(1) );
1046 return 0;
1047 case CG_GETGAMESTATE:
1048 CL_GetGameState( (gameState_t *) VMA(1) );
1049 return 0;
1050 case CG_GETCURRENTSNAPSHOTNUMBER:
1051 CL_GetCurrentSnapshotNumber( (int *) VMA(1), (int *) VMA(2) );
1052 return 0;
1053 case CG_GETSNAPSHOT:
1054 return CL_GetSnapshot( args[1], (snapshot_t *) VMA(2) );
1055
1056 case CG_GETDEFAULTSTATE:
1057 return CL_GetDefaultState(args[1], (entityState_t *)VMA(2));
1058
1059 case CG_GETSERVERCOMMAND:
1060 return CL_GetServerCommand( args[1] );
1061 case CG_GETCURRENTCMDNUMBER:
1062 return CL_GetCurrentCmdNumber();
1063 case CG_GETUSERCMD:
1064 return CL_GetUserCmd( args[1], (usercmd_s *) VMA(2) );
1065 case CG_SETUSERCMDVALUE:
1066 CL_SetUserCmdValue( args[1], VMF(2), VMF(3), VMF(4) );
1067 return 0;
1068 case CG_SETUSERCMDANGLES:
1069 CL_SetUserCmdAngles( VMF(1), VMF(2), VMF(3) );
1070 return 0;
1071 case COM_SETORGANGLES:
1072 Com_SetOrgAngles((float *)VMA(1),(float *)VMA(2));
1073 return 0;
1074 /*
1075 Ghoul2 Insert Start
1076 */
1077
1078 case CG_G2_LISTSURFACES:
1079 re.G2API_ListSurfaces( (CGhoul2Info *) VMA(1) );
1080 return 0;
1081
1082 case CG_G2_LISTBONES:
1083 re.G2API_ListBones( (CGhoul2Info *) VMA(1), args[2]);
1084 return 0;
1085
1086 case CG_G2_HAVEWEGHOULMODELS:
1087 return re.G2API_HaveWeGhoul2Models( *((CGhoul2Info_v *)VMA(1)) );
1088
1089 case CG_G2_SETMODELS:
1090 re.G2API_SetGhoul2ModelIndexes( *((CGhoul2Info_v *)VMA(1)),(qhandle_t *)VMA(2),(qhandle_t *)VMA(3));
1091 return 0;
1092
1093 /*
1094 Ghoul2 Insert End
1095 */
1096
1097 case CG_R_GET_LIGHT_STYLE:
1098 re.GetLightStyle(args[1], (byte*) VMA(2) );
1099 return 0;
1100 case CG_R_SET_LIGHT_STYLE:
1101 re.SetLightStyle(args[1], args[2] );
1102 return 0;
1103
1104 case CG_R_GET_BMODEL_VERTS:
1105 re.GetBModelVerts( args[1], (float (*)[3])VMA(2), (float *)VMA(3) );
1106 return 0;
1107
1108 case CG_R_WORLD_EFFECT_COMMAND:
1109 re.WorldEffectCommand( (const char *) VMA(1) );
1110 return 0;
1111
1112 case CG_CIN_PLAYCINEMATIC:
1113 return CIN_PlayCinematic( (const char *) VMA(1), args[2], args[3], args[4], args[5], args[6], (const char *) VMA(7));
1114
1115 case CG_CIN_STOPCINEMATIC:
1116 return CIN_StopCinematic(args[1]);
1117
1118 case CG_CIN_RUNCINEMATIC:
1119 return CIN_RunCinematic(args[1]);
1120
1121 case CG_CIN_DRAWCINEMATIC:
1122 CIN_DrawCinematic(args[1]);
1123 return 0;
1124
1125 case CG_CIN_SETEXTENTS:
1126 CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]);
1127 return 0;
1128
1129 case CG_Z_MALLOC:
1130 return (intptr_t)Z_Malloc(args[1], (memtag_t) args[2], qfalse);
1131
1132 case CG_Z_FREE:
1133 Z_Free((void *) VMA(1));
1134 return 0;
1135
1136 case CG_UI_SETACTIVE_MENU:
1137 UI_SetActiveMenu((const char *) VMA(1),NULL);
1138 return 0;
1139
1140 case CG_UI_MENU_OPENBYNAME:
1141 Menus_OpenByName((const char *) VMA(1));
1142 return 0;
1143
1144 case CG_UI_MENU_RESET:
1145 Menu_Reset();
1146 return 0;
1147
1148 case CG_UI_MENU_NEW:
1149 Menu_New((char *) VMA(1));
1150 return 0;
1151
1152 case CG_UI_PARSE_INT:
1153 PC_ParseInt((int *) VMA(1));
1154 return 0;
1155
1156 case CG_UI_PARSE_STRING:
1157 PC_ParseString((const char **) VMA(1));
1158 return 0;
1159
1160 case CG_UI_PARSE_FLOAT:
1161 PC_ParseFloat((float *) VMA(1));
1162 return 0;
1163
1164 case CG_UI_STARTPARSESESSION:
1165 return(PC_StartParseSession((char *) VMA(1),(char **) VMA(2)));
1166
1167 case CG_UI_ENDPARSESESSION:
1168 PC_EndParseSession((char *) VMA(1));
1169 return 0;
1170
1171 case CG_UI_PARSEEXT:
1172 char **holdPtr;
1173
1174 holdPtr = (char **) VMA(1);
1175
1176 if(!holdPtr)
1177 {
1178 Com_Error(ERR_FATAL, "CG_UI_PARSEEXT: NULL holdPtr");
1179 }
1180
1181 *holdPtr = PC_ParseExt();
1182 return 0;
1183
1184 case CG_UI_MENUCLOSE_ALL:
1185 Menus_CloseAll();
1186 return 0;
1187
1188 case CG_UI_MENUPAINT_ALL:
1189 Menu_PaintAll();
1190 return 0;
1191
1192 case CG_OPENJK_MENU_PAINT:
1193 Menu_Paint( (menuDef_t *)VMA(1), (qboolean)(args[2] != 0) );
1194 return 0;
1195
1196 case CG_OPENJK_GETMENU_BYNAME:
1197 return (intptr_t)Menus_FindByName( (const char *)VMA(1) );
1198
1199 case CG_UI_STRING_INIT:
1200 String_Init();
1201 return 0;
1202
1203 case CG_UI_GETMENUINFO:
1204 menuDef_t *menu;
1205 int *xPos,*yPos,*w,*h,result;
1206 #ifndef JK2_MODE
1207 menu = Menus_FindByName((char *) VMA(1)); // Get menu
1208 if (menu)
1209 {
1210 xPos = (int *) VMA(2);
1211 *xPos = (int) menu->window.rect.x;
1212 yPos = (int *) VMA(3);
1213 *yPos = (int) menu->window.rect.y;
1214 w = (int *) VMA(4);
1215 *w = (int) menu->window.rect.w;
1216 h = (int *) VMA(5);
1217 *h = (int) menu->window.rect.h;
1218 result = qtrue;
1219 }
1220 else
1221 {
1222 result = qfalse;
1223 }
1224
1225 return result;
1226 #else
1227 menu = Menus_FindByName((char *) VMA(1)); // Get menu
1228 if (menu)
1229 {
1230 xPos = (int *) VMA(2);
1231 *xPos = (int) menu->window.rect.x;
1232 yPos = (int *) VMA(3);
1233 *yPos = (int) menu->window.rect.y;
1234 result = qtrue;
1235 }
1236 else
1237 {
1238 result = qfalse;
1239 }
1240
1241 return result;
1242 #endif
1243 break;
1244
1245 case CG_UI_GETITEMTEXT:
1246 itemDef_t *item;
1247 menu = Menus_FindByName((char *) VMA(1)); // Get menu
1248
1249 if (menu)
1250 {
1251 item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, (char *) VMA(2));
1252 if (item)
1253 {
1254 Q_strncpyz( (char *) VMA(3), item->text, 256 );
1255 result = qtrue;
1256 }
1257 else
1258 {
1259 result = qfalse;
1260 }
1261 }
1262 else
1263 {
1264 result = qfalse;
1265 }
1266
1267 return result;
1268
1269 case CG_UI_GETITEMINFO:
1270 menu = Menus_FindByName((char *) VMA(1)); // Get menu
1271
1272 if (menu)
1273 {
1274 qhandle_t *background;
1275
1276 item = (itemDef_s *) Menu_FindItemByName((menuDef_t *) menu, (char *) VMA(2));
1277 if (item)
1278 {
1279 xPos = (int *) VMA(3);
1280 *xPos = (int) item->window.rect.x;
1281 yPos = (int *) VMA(4);
1282 *yPos = (int) item->window.rect.y;
1283 w = (int *) VMA(5);
1284 *w = (int) item->window.rect.w;
1285 h = (int *) VMA(6);
1286 *h = (int) item->window.rect.h;
1287
1288 vec4_t *color;
1289
1290 color = (vec4_t *) VMA(7);
1291 if (!color)
1292 {
1293 return qfalse;
1294 }
1295
1296 (*color)[0] = (float) item->window.foreColor[0];
1297 (*color)[1] = (float) item->window.foreColor[1];
1298 (*color)[2] = (float) item->window.foreColor[2];
1299 (*color)[3] = (float) item->window.foreColor[3];
1300 background = (qhandle_t *) VMA(8);
1301 if (!background)
1302 {
1303 return qfalse;
1304 }
1305 *background = item->window.background;
1306
1307 result = qtrue;
1308 }
1309 else
1310 {
1311 result = qfalse;
1312 }
1313 }
1314 else
1315 {
1316 result = qfalse;
1317 }
1318
1319 return result;
1320
1321 #ifdef JK2_MODE
1322 case CG_SP_GETSTRINGTEXTSTRING:
1323 case CG_SP_GETSTRINGTEXT:
1324 const char* text;
1325
1326 assert(VMA(1));
1327 // assert(VMA(2)); // can now pass in NULL to just query the size
1328
1329 if (args[0] == CG_SP_GETSTRINGTEXT)
1330 {
1331 text = JK2SP_GetStringText( args[1] );
1332 }
1333 else
1334 {
1335 text = JK2SP_GetStringTextString( (const char *) VMA(1) );
1336 }
1337
1338 if (VMA(2)) // only if dest buffer supplied...
1339 {
1340 if ( text[0] )
1341 {
1342 Q_strncpyz( (char *) VMA(2), text, args[3] );
1343 }
1344 else
1345 {
1346 Q_strncpyz( (char *) VMA(2), "??", args[3] );
1347 }
1348 }
1349 return strlen(text);
1350
1351 case CG_SP_REGISTER:
1352 return JK2SP_Register((const char *)VMA(1), args[2] ? (SP_REGISTER_MENU | SP_REGISTER_REQUIRED) : SP_REGISTER_CLIENT);
1353 #else
1354 case CG_SP_GETSTRINGTEXTSTRING:
1355 const char* text;
1356
1357 assert(VMA(1));
1358 text = SE_GetString( (const char *) VMA(1) );
1359
1360 if (VMA(2)) // only if dest buffer supplied...
1361 {
1362 if ( text[0] )
1363 {
1364 Q_strncpyz( (char *) VMA(2), text, args[3] );
1365 }
1366 else
1367 {
1368 Com_sprintf( (char *) VMA(2), args[3], "??%s", VMA(1) );
1369 }
1370 }
1371 return strlen(text);
1372 #endif
1373
1374 default:
1375 Com_Error( ERR_DROP, "Bad cgame system trap: %ld", (long int) args[0] );
1376 }
1377 return 0;
1378 }
1379
1380
1381 /*
1382 ====================
1383 CL_InitCGame
1384
1385 Should only be called by CL_StartHunkUsers
1386 ====================
1387 */
1388 extern qboolean Sys_LowPhysicalMemory();
CL_InitCGame(void)1389 void CL_InitCGame( void ) {
1390 const char *info;
1391 const char *mapname;
1392 //int t1, t2;
1393
1394 //t1 = Sys_Milliseconds();
1395
1396 // put away the console
1397 Con_Close();
1398
1399 // find the current mapname
1400 info = cl.gameState.stringData + cl.gameState.stringOffsets[ CS_SERVERINFO ];
1401 mapname = Info_ValueForKey( info, "mapname" );
1402 Com_sprintf( cl.mapname, sizeof( cl.mapname ), "maps/%s.bsp", mapname );
1403
1404 cls.state = CA_LOADING;
1405
1406 // init for this gamestate
1407 VM_Call( CG_INIT, clc.serverCommandSequence );
1408
1409 // reset any CVAR_CHEAT cvars registered by cgame
1410 if ( !cl_connectedToCheatServer )
1411 Cvar_SetCheatState();
1412
1413 // we will send a usercmd this frame, which
1414 // will cause the server to send us the first snapshot
1415 cls.state = CA_PRIMED;
1416
1417 //t2 = Sys_Milliseconds();
1418
1419 //Com_Printf( "CL_InitCGame: %5.2f seconds\n", (t2-t1)/1000.0 );
1420 // have the renderer touch all its images, so they are present
1421 // on the card even if the driver does deferred loading
1422 re.EndRegistration();
1423
1424 // make sure everything is paged in
1425 // if (!Sys_LowPhysicalMemory())
1426 {
1427 Com_TouchMemory();
1428 }
1429
1430 // clear anything that got printed
1431 Con_ClearNotify ();
1432 }
1433
1434
1435 /*
1436 ====================
1437 CL_GameCommand
1438
1439 See if the current console command is claimed by the cgame
1440 ====================
1441 */
CL_GameCommand(void)1442 qboolean CL_GameCommand( void ) {
1443 if ( cls.state != CA_ACTIVE ) {
1444 return qfalse;
1445 }
1446
1447 return (qboolean)(VM_Call( CG_CONSOLE_COMMAND ) != 0);
1448 }
1449
1450
1451
1452 /*
1453 =====================
1454 CL_CGameRendering
1455 =====================
1456 */
CL_CGameRendering(stereoFrame_t stereo)1457 void CL_CGameRendering( stereoFrame_t stereo ) {
1458 #if 0
1459 if ( cls.state == CA_ACTIVE ) {
1460 static int counter;
1461
1462 if ( ++counter == 40 ) {
1463 VM_Debug( 2 );
1464 }
1465 }
1466 #endif
1467 int timei=cl.serverTime;
1468 if (timei>60)
1469 {
1470 timei-=0;
1471 }
1472 re.G2API_SetTime(cl.serverTime,G2T_CG_TIME);
1473 VM_Call( CG_DRAW_ACTIVE_FRAME,timei, stereo, qfalse );
1474 // VM_Debug( 0 );
1475 }
1476
1477
1478 /*
1479 =================
1480 CL_AdjustTimeDelta
1481
1482 Adjust the clients view of server time.
1483
1484 We attempt to have cl.serverTime exactly equal the server's view
1485 of time plus the timeNudge, but with variable latencies over
1486 the internet it will often need to drift a bit to match conditions.
1487
1488 Our ideal time would be to have the adjusted time aproach, but not pass,
1489 the very latest snapshot.
1490
1491 Adjustments are only made when a new snapshot arrives, which keeps the
1492 adjustment process framerate independent and prevents massive overadjustment
1493 during times of significant packet loss.
1494 =================
1495 */
1496
1497 #define RESET_TIME 300
1498
CL_AdjustTimeDelta(void)1499 void CL_AdjustTimeDelta( void ) {
1500 /*
1501 cl.newSnapshots = qfalse;
1502 // if the current time is WAY off, just correct to the current value
1503 if ( cls.realtime + cl.serverTimeDelta < cl.frame.serverTime - RESET_TIME
1504 || cls.realtime + cl.serverTimeDelta > cl.frame.serverTime + RESET_TIME ) {
1505 cl.serverTimeDelta = cl.frame.serverTime - cls.realtime;
1506 cl.oldServerTime = cl.frame.serverTime;
1507 if ( cl_showTimeDelta->integer ) {
1508 Com_Printf( "<RESET> " );
1509 }
1510 }
1511
1512 // if any of the frames between this and the previous snapshot
1513 // had to be extrapolated, nudge our sense of time back a little
1514 if ( cl.extrapolatedSnapshot ) {
1515 cl.extrapolatedSnapshot = qfalse;
1516 cl.serverTimeDelta -= 2;
1517 } else {
1518 // otherwise, move our sense of time forward to minimize total latency
1519 cl.serverTimeDelta++;
1520 }
1521
1522 if ( cl_showTimeDelta->integer ) {
1523 Com_Printf( "%i ", cl.serverTimeDelta );
1524 }
1525 */
1526 int newDelta;
1527 int deltaDelta;
1528
1529 cl.newSnapshots = qfalse;
1530
1531 newDelta = cl.frame.serverTime - cls.realtime;
1532 deltaDelta = abs( newDelta - cl.serverTimeDelta );
1533
1534 if ( deltaDelta > RESET_TIME ) {
1535 cl.serverTimeDelta = newDelta;
1536 cl.oldServerTime = cl.frame.serverTime; // FIXME: is this a problem for cgame?
1537 cl.serverTime = cl.frame.serverTime;
1538 if ( cl_showTimeDelta->integer ) {
1539 Com_Printf( "<RESET> " );
1540 }
1541 } else if ( deltaDelta > 100 ) {
1542 // fast adjust, cut the difference in half
1543 if ( cl_showTimeDelta->integer ) {
1544 Com_Printf( "<FAST> " );
1545 }
1546 cl.serverTimeDelta = ( cl.serverTimeDelta + newDelta ) >> 1;
1547 } else {
1548 // slow drift adjust, only move 1 or 2 msec
1549
1550 // if any of the frames between this and the previous snapshot
1551 // had to be extrapolated, nudge our sense of time back a little
1552 // the granularity of +1 / -2 is too high for timescale modified frametimes
1553 if ( com_timescale->value == 0 || com_timescale->value == 1 ) {
1554 if ( cl.extrapolatedSnapshot ) {
1555 cl.extrapolatedSnapshot = qfalse;
1556 cl.serverTimeDelta -= 2;
1557 } else {
1558 // otherwise, move our sense of time forward to minimize total latency
1559 cl.serverTimeDelta++;
1560 }
1561 }
1562 }
1563
1564 if ( cl_showTimeDelta->integer ) {
1565 Com_Printf( "%i ", cl.serverTimeDelta );
1566 }
1567 }
1568
1569
1570 /*
1571 ==================
1572 CL_FirstSnapshot
1573 ==================
1574 */
CL_FirstSnapshot(void)1575 void CL_FirstSnapshot( void ) {
1576
1577 re.RegisterMedia_LevelLoadEnd();
1578
1579 cls.state = CA_ACTIVE;
1580
1581 // set the timedelta so we are exactly on this first frame
1582 cl.serverTimeDelta = cl.frame.serverTime - cls.realtime;
1583 cl.oldServerTime = cl.frame.serverTime;
1584
1585 // if this is the first frame of active play,
1586 // execute the contents of activeAction now
1587 // this is to allow scripting a timedemo to start right
1588 // after loading
1589 if ( cl_activeAction->string[0] ) {
1590 Cbuf_AddText( cl_activeAction->string );
1591 Cvar_Set( "activeAction", "" );
1592 }
1593 }
1594
1595 /*
1596 ==================
1597 CL_SetCGameTime
1598 ==================
1599 */
CL_SetCGameTime(void)1600 void CL_SetCGameTime( void ) {
1601
1602 // getting a valid frame message ends the connection process
1603 if ( cls.state != CA_ACTIVE ) {
1604 if ( cls.state != CA_PRIMED ) {
1605 return;
1606 }
1607 if ( cl.newSnapshots ) {
1608 cl.newSnapshots = qfalse;
1609 CL_FirstSnapshot();
1610 }
1611
1612 if ( cls.state != CA_ACTIVE ) {
1613 return;
1614 }
1615 }
1616
1617 // if we have gotten to this point, cl.frame is guaranteed to be valid
1618 if ( !cl.frame.valid ) {
1619 Com_Error( ERR_DROP, "CL_SetCGameTime: !cl.snap.valid" );
1620 }
1621
1622 // allow pause in single player
1623 if ( sv_paused->integer && CL_CheckPaused() && com_sv_running->integer ) {
1624 // paused
1625 return;
1626 }
1627
1628 if ( cl.frame.serverTime < cl.oldFrameServerTime ) {
1629 Com_Error( ERR_DROP, "cl.frame.serverTime < cl.oldFrameServerTime" );
1630 }
1631 cl.oldFrameServerTime = cl.frame.serverTime;
1632
1633
1634 // get our current view of time
1635
1636 // cl_timeNudge is a user adjustable cvar that allows more
1637 // or less latency to be added in the interest of better
1638 // smoothness or better responsiveness.
1639 cl.serverTime = cls.realtime + cl.serverTimeDelta - cl_timeNudge->integer;
1640
1641 // guarantee that time will never flow backwards, even if
1642 // serverTimeDelta made an adjustment or cl_timeNudge was changed
1643 if ( cl.serverTime < cl.oldServerTime ) {
1644 cl.serverTime = cl.oldServerTime;
1645 }
1646 cl.oldServerTime = cl.serverTime;
1647
1648 // note if we are almost past the latest frame (without timeNudge),
1649 // so we will try and adjust back a bit when the next snapshot arrives
1650 if ( cls.realtime + cl.serverTimeDelta >= cl.frame.serverTime - 5 ) {
1651 cl.extrapolatedSnapshot = qtrue;
1652 }
1653
1654 // if we have gotten new snapshots, drift serverTimeDelta
1655 // don't do this every frame, or a period of packet loss would
1656 // make a huge adjustment
1657 if ( cl.newSnapshots ) {
1658 CL_AdjustTimeDelta();
1659 }
1660 }
1661
1662