1 /*
2 ===========================================================================
3 Copyright (C) 2013 - 2015, OpenJK contributors
4 
5 This file is part of the OpenJK source code.
6 
7 OpenJK is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
18 ===========================================================================
19 */
20 
21 // cl_uiapi.c  -- client system interaction with client game
22 #include "qcommon/RoffSystem.h"
23 #include "qcommon/stringed_ingame.h"
24 #include "qcommon/timing.h"
25 #include "client.h"
26 #include "cl_lan.h"
27 #include "botlib/botlib.h"
28 #include "snd_ambient.h"
29 #include "FXExport.h"
30 #include "FxUtil.h"
31 
32 extern IHeapAllocator *G2VertSpaceClient;
33 extern botlib_export_t *botlib_export;
34 
35 // ui interface
36 static uiExport_t *uie; // ui export table
37 static vm_t *uivm; // ui vm, valid for legacy and new api
38 
39 //
40 // ui vmMain calls
41 //
42 
UIVM_Init(qboolean inGameLoad)43 void UIVM_Init( qboolean inGameLoad ) {
44 	if ( uivm->isLegacy ) {
45 		VM_Call( uivm, UI_INIT, inGameLoad );
46 		return;
47 	}
48 	VMSwap v( uivm );
49 
50 	uie->Init( inGameLoad );
51 }
52 
UIVM_Shutdown(void)53 void UIVM_Shutdown( void ) {
54 	if ( uivm->isLegacy ) {
55 		VM_Call( uivm, UI_SHUTDOWN );
56 		VM_Call( uivm, UI_MENU_RESET );
57 		return;
58 	}
59 	VMSwap v( uivm );
60 
61 	uie->Shutdown();
62 	uie->MenuReset();
63 }
64 
UIVM_KeyEvent(int key,qboolean down)65 void UIVM_KeyEvent( int key, qboolean down ) {
66 	if ( uivm->isLegacy ) {
67 		VM_Call( uivm, UI_KEY_EVENT, key, down );
68 		return;
69 	}
70 	VMSwap v( uivm );
71 
72 	uie->KeyEvent( key, down );
73 }
74 
UIVM_MouseEvent(int dx,int dy)75 void UIVM_MouseEvent( int dx, int dy ) {
76 	if ( uivm->isLegacy ) {
77 		VM_Call( uivm, UI_MOUSE_EVENT, dx, dy );
78 		return;
79 	}
80 	VMSwap v( uivm );
81 
82 	uie->MouseEvent( dx, dy );
83 }
84 
UIVM_Refresh(int realtime)85 void UIVM_Refresh( int realtime ) {
86 	if ( uivm->isLegacy ) {
87 		VM_Call( uivm, UI_REFRESH, realtime );
88 		return;
89 	}
90 	VMSwap v( uivm );
91 
92 	uie->Refresh( realtime );
93 }
94 
UIVM_IsFullscreen(void)95 qboolean UIVM_IsFullscreen( void ) {
96 	if ( uivm->isLegacy ) {
97 		return (qboolean)VM_Call( uivm, UI_IS_FULLSCREEN );
98 	}
99 	VMSwap v( uivm );
100 
101 	return uie->IsFullscreen();
102 }
103 
UIVM_SetActiveMenu(uiMenuCommand_t menu)104 void UIVM_SetActiveMenu( uiMenuCommand_t menu ) {
105 	if ( uivm->isLegacy ) {
106 		VM_Call( uivm, UI_SET_ACTIVE_MENU, menu );
107 		return;
108 	}
109 	VMSwap v( uivm );
110 
111 	uie->SetActiveMenu( menu );
112 }
113 
UIVM_ConsoleCommand(int realTime)114 qboolean UIVM_ConsoleCommand( int realTime ) {
115 	if ( uivm->isLegacy ) {
116 		return (qboolean)VM_Call( uivm, UI_CONSOLE_COMMAND, realTime );
117 	}
118 	VMSwap v( uivm );
119 
120 	return uie->ConsoleCommand( realTime );
121 }
UIVM_DrawConnectScreen(qboolean overlay)122 void UIVM_DrawConnectScreen( qboolean overlay ) {
123 	if ( uivm->isLegacy ) {
124 		VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, overlay );
125 		return;
126 	}
127 	VMSwap v( uivm );
128 
129 	uie->DrawConnectScreen( overlay );
130 }
131 
132 //
133 // ui syscalls
134 //	only used by legacy mods!
135 //
136 
137 // wrappers and such
138 
CL_Milliseconds(void)139 static int CL_Milliseconds( void ) {
140 	return Sys_Milliseconds();
141 }
142 
CL_Cvar_Get(const char * var_name,const char * value,uint32_t flags)143 static void CL_Cvar_Get( const char *var_name, const char *value, uint32_t flags ) {
144 	Cvar_Register( NULL, var_name, value, flags );
145 }
146 
CL_GetClientState(uiClientState_t * state)147 static void CL_GetClientState( uiClientState_t *state ) {
148 	state->connectPacketCount = clc.connectPacketCount;
149 	state->connState = cls.state;
150 	Q_strncpyz( state->servername, cls.servername, sizeof( state->servername ) );
151 	Q_strncpyz( state->updateInfoString, cls.updateInfoString, sizeof( state->updateInfoString ) );
152 	Q_strncpyz( state->messageString, clc.serverMessage, sizeof( state->messageString ) );
153 	state->clientNum = cl.snap.ps.clientNum;
154 }
155 
CL_GetGlconfig(glconfig_t * config)156 static void CL_GetGlconfig( glconfig_t *config ) {
157 	*config = cls.glconfig;
158 }
159 
GetClipboardData(char * buf,int buflen)160 static void GetClipboardData( char *buf, int buflen ) {
161 	char	*cbd, *c;
162 
163 	c = cbd = Sys_GetClipboardData();
164 	if ( !cbd ) {
165 		*buf = 0;
166 		return;
167 	}
168 
169 	for ( int i = 0, end = buflen - 1; *c && i < end; i++ )
170 	{
171 		uint32_t utf32 = ConvertUTF8ToUTF32( c, &c );
172 		buf[i] = ConvertUTF32ToExpectedCharset( utf32 );
173 	}
174 
175 	Z_Free( cbd );
176 }
177 
GetConfigString(int index,char * buf,int size)178 static int GetConfigString(int index, char *buf, int size)
179 {
180 	int		offset;
181 
182 	if (index < 0 || index >= MAX_CONFIGSTRINGS)
183 		return qfalse;
184 
185 	offset = cl.gameState.stringOffsets[index];
186 	if (!offset) {
187 		if( size ) {
188 			buf[0] = 0;
189 		}
190 		return qfalse;
191 	}
192 
193 	Q_strncpyz( buf, cl.gameState.stringData+offset, size);
194 
195 	return qtrue;
196 }
197 
Key_GetBindingBuf(int keynum,char * buf,int buflen)198 static void Key_GetBindingBuf( int keynum, char *buf, int buflen ) {
199 	char	*value;
200 
201 	value = Key_GetBinding( keynum );
202 	if ( value ) {
203 		Q_strncpyz( buf, value, buflen );
204 	}
205 	else {
206 		*buf = 0;
207 	}
208 }
209 
Key_KeynumToStringBuf(int keynum,char * buf,int buflen)210 static void Key_KeynumToStringBuf( int keynum, char *buf, int buflen )
211 {
212 	const char *psKeyName = Key_KeynumToString( keynum/*, qtrue */);
213 
214 	// see if there's a more friendly (or localised) name...
215 	//
216 	const char *psKeyNameFriendly = SE_GetString( va("KEYNAMES_KEYNAME_%s",psKeyName) );
217 
218 	Q_strncpyz( buf, (psKeyNameFriendly && psKeyNameFriendly[0]) ? psKeyNameFriendly : psKeyName, buflen );
219 }
220 
CL_SE_GetLanguageName(const int languageIndex,char * buffer)221 static void CL_SE_GetLanguageName( const int languageIndex, char *buffer ) {
222 	Q_strncpyz( buffer, SE_GetLanguageName( languageIndex ), 128 );
223 }
224 
CL_SE_GetStringTextString(const char * text,char * buffer,int bufferLength)225 static qboolean CL_SE_GetStringTextString( const char *text, char *buffer, int bufferLength ) {
226 	assert( text && buffer );
227 	Q_strncpyz( buffer, SE_GetString( text ), bufferLength );
228 	return qtrue;
229 }
230 
CL_R_ShaderNameFromIndex(char * name,int index)231 static void CL_R_ShaderNameFromIndex( char *name, int index ) {
232 	const char *retMem = re->ShaderNameFromIndex( index );
233 	if ( retMem )
234 		strcpy( name, retMem );
235 	else
236 		name[0] = '\0';
237 }
238 
CL_G2API_ListModelSurfaces(void * ghlInfo)239 static void CL_G2API_ListModelSurfaces( void *ghlInfo ) {
240 	if ( !ghlInfo ) {
241 		return;
242 	}
243 
244 	re->G2API_ListSurfaces( (CGhoul2Info *)ghlInfo );
245 }
246 
CL_G2API_ListModelBones(void * ghlInfo,int frame)247 static void CL_G2API_ListModelBones( void *ghlInfo, int frame ) {
248 	if ( !ghlInfo ) {
249 		return;
250 	}
251 
252 	re->G2API_ListBones( (CGhoul2Info *)ghlInfo, frame );
253 }
254 
CL_G2API_SetGhoul2ModelIndexes(void * ghoul2,qhandle_t * modelList,qhandle_t * skinList)255 static void CL_G2API_SetGhoul2ModelIndexes( void *ghoul2, qhandle_t *modelList, qhandle_t *skinList ) {
256 	if ( !ghoul2 ) {
257 		return;
258 	}
259 
260 	re->G2API_SetGhoul2ModelIndexes( *((CGhoul2Info_v *)ghoul2), modelList, skinList );
261 }
262 
CL_G2API_HaveWeGhoul2Models(void * ghoul2)263 static qboolean CL_G2API_HaveWeGhoul2Models( void *ghoul2) {
264 	if ( !ghoul2 ) {
265 		return qfalse;
266 	}
267 
268 	return re->G2API_HaveWeGhoul2Models( *((CGhoul2Info_v *)ghoul2) );
269 }
270 
CL_G2API_GetBoltMatrix(void * ghoul2,const int modelIndex,const int boltIndex,mdxaBone_t * matrix,const vec3_t angles,const vec3_t position,const int frameNum,qhandle_t * modelList,vec3_t scale)271 static qboolean CL_G2API_GetBoltMatrix( void *ghoul2, const int modelIndex, const int boltIndex, mdxaBone_t *matrix, const vec3_t angles, const vec3_t position, const int frameNum, qhandle_t *modelList, vec3_t scale ) {
272 	if ( !ghoul2 ) {
273 		return qfalse;
274 
275 	}
276 	return re->G2API_GetBoltMatrix( *((CGhoul2Info_v *)ghoul2), modelIndex, boltIndex, matrix, angles, position, frameNum, modelList, scale );
277 }
278 
CL_G2API_GetBoltMatrix_NoReconstruct(void * ghoul2,const int modelIndex,const int boltIndex,mdxaBone_t * matrix,const vec3_t angles,const vec3_t position,const int frameNum,qhandle_t * modelList,vec3_t scale)279 static qboolean CL_G2API_GetBoltMatrix_NoReconstruct( void *ghoul2, const int modelIndex, const int boltIndex, mdxaBone_t *matrix, const vec3_t angles, const vec3_t position, const int frameNum, qhandle_t *modelList, vec3_t scale ) {
280 	if ( !ghoul2 ) {
281 		return qfalse;
282 	}
283 
284 	re->G2API_BoltMatrixReconstruction( qfalse );
285 	return re->G2API_GetBoltMatrix( *((CGhoul2Info_v *)ghoul2), modelIndex, boltIndex, matrix, angles, position, frameNum, modelList, scale );
286 }
287 
CL_G2API_GetBoltMatrix_NoRecNoRot(void * ghoul2,const int modelIndex,const int boltIndex,mdxaBone_t * matrix,const vec3_t angles,const vec3_t position,const int frameNum,qhandle_t * modelList,vec3_t scale)288 static qboolean CL_G2API_GetBoltMatrix_NoRecNoRot( void *ghoul2, const int modelIndex, const int boltIndex, mdxaBone_t *matrix, const vec3_t angles, const vec3_t position, const int frameNum, qhandle_t *modelList, vec3_t scale ) {
289 	if ( !ghoul2 ) {
290 		return qfalse;
291 	}
292 
293 	re->G2API_BoltMatrixReconstruction( qfalse );
294 	re->G2API_BoltMatrixSPMethod( qtrue );
295 	return re->G2API_GetBoltMatrix( *((CGhoul2Info_v *)ghoul2), modelIndex, boltIndex, matrix, angles, position, frameNum, modelList, scale );
296 }
297 
CL_G2API_InitGhoul2Model(void ** ghoul2Ptr,const char * fileName,int modelIndex,qhandle_t customSkin,qhandle_t customShader,int modelFlags,int lodBias)298 static int CL_G2API_InitGhoul2Model( void **ghoul2Ptr, const char *fileName, int modelIndex, qhandle_t customSkin, qhandle_t customShader, int modelFlags, int lodBias ) {
299 	if ( !ghoul2Ptr ) {
300 		return 0;
301 	}
302 
303 #ifdef _FULL_G2_LEAK_CHECKING
304 		g_G2AllocServer = 0;
305 #endif
306 	return re->G2API_InitGhoul2Model( (CGhoul2Info_v **)ghoul2Ptr, fileName, modelIndex, customSkin, customShader, modelFlags, lodBias );
307 }
308 
CL_G2API_SetSkin(void * ghoul2,int modelIndex,qhandle_t customSkin,qhandle_t renderSkin)309 static qboolean CL_G2API_SetSkin( void *ghoul2, int modelIndex, qhandle_t customSkin, qhandle_t renderSkin ) {
310 	if ( !ghoul2 ) {
311 		return qfalse;
312 	}
313 
314 	CGhoul2Info_v &g2 = *((CGhoul2Info_v *)ghoul2);
315 	return re->G2API_SetSkin( g2, modelIndex, customSkin, renderSkin );
316 }
317 
CL_G2API_CollisionDetect(CollisionRecord_t * collRecMap,void * ghoul2,const vec3_t angles,const vec3_t position,int frameNumber,int entNum,vec3_t rayStart,vec3_t rayEnd,vec3_t scale,int traceFlags,int useLod,float fRadius)318 static void CL_G2API_CollisionDetect(
319 	CollisionRecord_t *collRecMap,
320 	void* ghoul2,
321 	const vec3_t angles,
322 	const vec3_t position,
323 	int frameNumber,
324 	int entNum,
325 	vec3_t rayStart,
326 	vec3_t rayEnd,
327 	vec3_t scale,
328 	int traceFlags,
329 	int useLod,
330 	float fRadius )
331 {
332 	if ( !ghoul2 ) {
333 		return;
334 	}
335 
336 	re->G2API_CollisionDetect(
337 		collRecMap,
338 		*((CGhoul2Info_v *)ghoul2),
339 		angles,
340 		position,
341 		frameNumber,
342 		entNum,
343 		rayStart,
344 		rayEnd,
345 		scale,
346 		G2VertSpaceClient,
347 		traceFlags,
348 		useLod,
349 		fRadius);
350 }
351 
CL_G2API_CollisionDetectCache(CollisionRecord_t * collRecMap,void * ghoul2,const vec3_t angles,const vec3_t position,int frameNumber,int entNum,vec3_t rayStart,vec3_t rayEnd,vec3_t scale,int traceFlags,int useLod,float fRadius)352 static void CL_G2API_CollisionDetectCache(
353 	CollisionRecord_t *collRecMap,
354 	void* ghoul2,
355 	const vec3_t angles,
356 	const vec3_t position,
357 	int frameNumber,
358 	int entNum,
359 	vec3_t rayStart,
360 	vec3_t rayEnd,
361 	vec3_t scale,
362 	int traceFlags,
363 	int useLod,
364 	float fRadius)
365 {
366 	if ( !ghoul2 ) {
367 		return;
368 	}
369 
370 	re->G2API_CollisionDetectCache(
371 		collRecMap,
372 		*((CGhoul2Info_v *)ghoul2),
373 		angles,
374 		position,
375 		frameNumber,
376 		entNum,
377 		rayStart,
378 		rayEnd,
379 		scale,
380 		G2VertSpaceClient,
381 		traceFlags,
382 		useLod,
383 		fRadius);
384 }
385 
CL_G2API_CleanGhoul2Models(void ** ghoul2Ptr)386 static void CL_G2API_CleanGhoul2Models( void **ghoul2Ptr ) {
387 	if ( !ghoul2Ptr ) {
388 		return;
389 	}
390 
391 #ifdef _FULL_G2_LEAK_CHECKING
392 		g_G2AllocServer = 0;
393 #endif
394 	re->G2API_CleanGhoul2Models( (CGhoul2Info_v **)ghoul2Ptr );
395 }
396 
CL_G2API_SetBoneAngles(void * ghoul2,int modelIndex,const char * boneName,const vec3_t angles,const int flags,const int up,const int right,const int forward,qhandle_t * modelList,int blendTime,int currentTime)397 static qboolean CL_G2API_SetBoneAngles(
398 	void *ghoul2,
399 	int modelIndex,
400 	const char *boneName,
401 	const vec3_t angles,
402 	const int flags,
403 	const int up,
404 	const int right,
405 	const int forward,
406 	qhandle_t *modelList,
407 	int blendTime ,
408 	int currentTime)
409 {
410 	if ( !ghoul2 ) {
411 		return qfalse;
412 	}
413 
414 	return re->G2API_SetBoneAngles(
415 		*((CGhoul2Info_v *)ghoul2),
416 		modelIndex,
417 		boneName,
418 		angles,
419 		flags,
420 		(const Eorientations)up,
421 		(const Eorientations)right,
422 		(const Eorientations)forward,
423 		modelList,
424 		blendTime,
425 		currentTime);
426 }
427 
CL_G2API_SetBoneAnim(void * ghoul2,const int modelIndex,const char * boneName,const int startFrame,const int endFrame,const int flags,const float animSpeed,const int currentTime,const float setFrame,const int blendTime)428 static qboolean CL_G2API_SetBoneAnim(
429 	void *ghoul2,
430 	const int modelIndex,
431 	const char *boneName,
432 	const int startFrame,
433 	const int endFrame,
434 	const int flags,
435 	const float animSpeed,
436 	const int currentTime,
437 	const float setFrame,
438 	const int blendTime)
439 {
440 	if ( !ghoul2 ) {
441 		return qfalse;
442 	}
443 
444 	return re->G2API_SetBoneAnim(
445 		*((CGhoul2Info_v *)ghoul2),
446 		modelIndex,
447 		boneName,
448 		startFrame,
449 		endFrame,
450 		flags,
451 		animSpeed,
452 		currentTime,
453 		setFrame,
454 		blendTime);
455 }
456 
CL_G2API_GetBoneAnim(void * ghoul2,const char * boneName,const int currentTime,float * currentFrame,int * startFrame,int * endFrame,int * flags,float * animSpeed,int * modelList,const int modelIndex)457 static qboolean CL_G2API_GetBoneAnim(
458 	void *ghoul2,
459 	const char *boneName,
460 	const int currentTime,
461 	float *currentFrame,
462 	int *startFrame,
463 	int *endFrame,
464 	int *flags,
465 	float *animSpeed,
466 	int *modelList,
467 	const int modelIndex)
468 {
469 	if ( !ghoul2 ) {
470 		return qfalse;
471 	}
472 
473 	CGhoul2Info_v &g2 = *((CGhoul2Info_v *)ghoul2);
474 	return re->G2API_GetBoneAnim(
475 		g2,
476 		modelIndex,
477 		boneName,
478 		currentTime,
479 		currentFrame,
480 		startFrame,
481 		endFrame,
482 		flags,
483 		animSpeed,
484 		modelList);
485 }
486 
CL_G2API_GetBoneFrame(void * ghoul2,const char * boneName,const int currentTime,float * currentFrame,int * modelList,const int modelIndex)487 static qboolean CL_G2API_GetBoneFrame(
488 	void *ghoul2,
489 	const char *boneName,
490 	const int currentTime,
491 	float *currentFrame,
492 	int *modelList,
493 	const int modelIndex)
494 {
495 	if ( !ghoul2 ) {
496 		return qfalse;
497 	}
498 
499 	CGhoul2Info_v &g2 = *((CGhoul2Info_v *)ghoul2);
500 	int iDontCare1 = 0, iDontCare2 = 0, iDontCare3 = 0;
501 	float fDontCare1 = 0;
502 
503 	return re->G2API_GetBoneAnim(
504 		g2,
505 		modelIndex,
506 		boneName,
507 		currentTime,
508 		currentFrame,
509 		&iDontCare1,
510 		&iDontCare2,
511 		&iDontCare3,
512 		&fDontCare1,
513 		modelList);
514 }
515 
CL_G2API_GetGLAName(void * ghoul2,int modelIndex,char * fillBuf)516 static void CL_G2API_GetGLAName( void *ghoul2, int modelIndex, char *fillBuf ) {
517 	if ( !ghoul2 )
518 	{
519 		fillBuf[0] = '\0';
520 		return;
521 	}
522 
523 	char *tmp = re->G2API_GetGLAName( *((CGhoul2Info_v *)ghoul2), modelIndex );
524 	if ( tmp )
525 		strcpy( fillBuf, tmp );
526 	else
527 		fillBuf[0] = '\0';
528 }
529 
CL_G2API_CopyGhoul2Instance(void * g2From,void * g2To,int modelIndex)530 static int CL_G2API_CopyGhoul2Instance( void *g2From, void *g2To, int modelIndex ) {
531 	if ( !g2From || !g2To ) {
532 		return 0;
533 	}
534 
535 	return re->G2API_CopyGhoul2Instance( *((CGhoul2Info_v *)g2From), *((CGhoul2Info_v *)g2To), modelIndex );
536 }
537 
CL_G2API_CopySpecificGhoul2Model(void * g2From,int modelFrom,void * g2To,int modelTo)538 static void CL_G2API_CopySpecificGhoul2Model( void *g2From, int modelFrom, void *g2To, int modelTo ) {
539 	if ( !g2From || !g2To ) {
540 		return;
541 	}
542 
543 	re->G2API_CopySpecificG2Model( *((CGhoul2Info_v *)g2From), modelFrom, *((CGhoul2Info_v *)g2To), modelTo );
544 }
545 
CL_G2API_DuplicateGhoul2Instance(void * g2From,void ** g2To)546 static void CL_G2API_DuplicateGhoul2Instance( void *g2From, void **g2To ) {
547 	if ( !g2From || !g2To ) {
548 		return;
549 	}
550 
551 #ifdef _FULL_G2_LEAK_CHECKING
552 		g_G2AllocServer = 0;
553 #endif
554 	re->G2API_DuplicateGhoul2Instance( *((CGhoul2Info_v *)g2From), (CGhoul2Info_v **)g2To );
555 }
556 
CL_G2API_HasGhoul2ModelOnIndex(void * ghlInfo,int modelIndex)557 static qboolean CL_G2API_HasGhoul2ModelOnIndex( void *ghlInfo, int modelIndex ) {
558 	if ( !ghlInfo ) {
559 		return qfalse;
560 	}
561 
562 	return re->G2API_HasGhoul2ModelOnIndex( (CGhoul2Info_v **)ghlInfo, modelIndex );
563 }
564 
CL_G2API_RemoveGhoul2Model(void * ghlInfo,int modelIndex)565 static qboolean CL_G2API_RemoveGhoul2Model( void *ghlInfo, int modelIndex ) {
566 	if ( !ghlInfo ) {
567 		return qfalse;
568 	}
569 
570 #ifdef _FULL_G2_LEAK_CHECKING
571 		g_G2AllocServer = 0;
572 #endif
573 	return re->G2API_RemoveGhoul2Model( (CGhoul2Info_v **)ghlInfo, modelIndex );
574 }
575 
CL_G2API_AddBolt(void * ghoul2,int modelIndex,const char * boneName)576 static int CL_G2API_AddBolt( void *ghoul2, int modelIndex, const char *boneName ) {
577 	if ( !ghoul2 ) {
578 		return -1;
579 	}
580 
581 	return re->G2API_AddBolt( *((CGhoul2Info_v *)ghoul2), modelIndex, boneName );
582 }
583 
CL_G2API_SetBoltInfo(void * ghoul2,int modelIndex,int boltInfo)584 static void CL_G2API_SetBoltInfo( void *ghoul2, int modelIndex, int boltInfo ) {
585 	if ( !ghoul2 ) {
586 		return;
587 	}
588 
589 	re->G2API_SetBoltInfo( *((CGhoul2Info_v *)ghoul2), modelIndex, boltInfo );
590 }
591 
CL_G2API_SetRootSurface(void * ghoul2,const int modelIndex,const char * surfaceName)592 static qboolean CL_G2API_SetRootSurface( void *ghoul2, const int modelIndex, const char *surfaceName ) {
593 	if ( !ghoul2 ) {
594 		return qfalse;
595 	}
596 
597 	return re->G2API_SetRootSurface( *((CGhoul2Info_v *)ghoul2), modelIndex, surfaceName );
598 }
599 
CL_G2API_SetSurfaceOnOff(void * ghoul2,const char * surfaceName,const int flags)600 static qboolean CL_G2API_SetSurfaceOnOff( void *ghoul2, const char *surfaceName, const int flags ) {
601 	if ( !ghoul2 ) {
602 		return qfalse;
603 	}
604 
605 	return re->G2API_SetSurfaceOnOff( *((CGhoul2Info_v *)ghoul2), surfaceName, flags );
606 }
607 
CL_G2API_SetNewOrigin(void * ghoul2,const int boltIndex)608 static qboolean CL_G2API_SetNewOrigin( void *ghoul2, const int boltIndex ) {
609 	if ( !ghoul2 ) {
610 		return qfalse;
611 	}
612 
613 	return re->G2API_SetNewOrigin( *((CGhoul2Info_v *)ghoul2), boltIndex );
614 }
615 
CL_G2API_GetTime(void)616 static int CL_G2API_GetTime( void ) {
617 	return re->G2API_GetTime( 0 );
618 }
619 
CL_G2API_SetTime(int time,int clock)620 static void CL_G2API_SetTime( int time, int clock ) {
621 	re->G2API_SetTime( time, clock );
622 }
623 
CL_G2API_SetRagDoll(void * ghoul2,sharedRagDollParams_t * params)624 static void CL_G2API_SetRagDoll( void *ghoul2, sharedRagDollParams_t *params ) {
625 	if ( !ghoul2 ) {
626 		return;
627 	}
628 
629 	CRagDollParams rdParams;
630 
631 	if ( !params ) {
632 		re->G2API_ResetRagDoll( *((CGhoul2Info_v *)ghoul2) );
633 		return;
634 	}
635 
636 	VectorCopy( params->angles, rdParams.angles );
637 	VectorCopy( params->position, rdParams.position );
638 	VectorCopy( params->scale, rdParams.scale );
639 	VectorCopy( params->pelvisAnglesOffset, rdParams.pelvisAnglesOffset );
640 	VectorCopy( params->pelvisPositionOffset, rdParams.pelvisPositionOffset );
641 
642 	rdParams.fImpactStrength = params->fImpactStrength;
643 	rdParams.fShotStrength = params->fShotStrength;
644 	rdParams.me = params->me;
645 
646 	rdParams.startFrame = params->startFrame;
647 	rdParams.endFrame = params->endFrame;
648 
649 	rdParams.collisionType = params->collisionType;
650 	rdParams.CallRagDollBegin = params->CallRagDollBegin;
651 
652 	rdParams.RagPhase = (CRagDollParams::ERagPhase)params->RagPhase;
653 	rdParams.effectorsToTurnOff = (CRagDollParams::ERagEffector)params->effectorsToTurnOff;
654 
655 	re->G2API_SetRagDoll( *((CGhoul2Info_v *)ghoul2), &rdParams );
656 }
657 
CL_G2API_AnimateG2Models(void * ghoul2,int time,sharedRagDollUpdateParams_t * params)658 static void CL_G2API_AnimateG2Models( void *ghoul2, int time, sharedRagDollUpdateParams_t *params ) {
659 	if ( !ghoul2 ) {
660 		return;
661 	}
662 
663 	CRagDollUpdateParams rduParams;
664 
665 	if ( !params )
666 		return;
667 
668 	VectorCopy( params->angles, rduParams.angles );
669 	VectorCopy( params->position, rduParams.position );
670 	VectorCopy( params->scale, rduParams.scale );
671 	VectorCopy( params->velocity, rduParams.velocity );
672 
673 	rduParams.me = params->me;
674 	rduParams.settleFrame = params->settleFrame;
675 
676 	re->G2API_AnimateG2ModelsRag( *((CGhoul2Info_v *)ghoul2), time, &rduParams );
677 }
678 
CL_G2API_SetBoneIKState(void * ghoul2,int time,const char * boneName,int ikState,sharedSetBoneIKStateParams_t * params)679 static qboolean CL_G2API_SetBoneIKState( void *ghoul2, int time, const char *boneName, int ikState, sharedSetBoneIKStateParams_t *params ) {
680 	if ( !ghoul2 ) {
681 		return qfalse;
682 	}
683 
684 	return re->G2API_SetBoneIKState( *((CGhoul2Info_v *)ghoul2), time, boneName, ikState, params );
685 }
686 
CL_G2API_IKMove(void * ghoul2,int time,sharedIKMoveParams_t * params)687 static qboolean CL_G2API_IKMove( void *ghoul2, int time, sharedIKMoveParams_t *params ) {
688 	if ( !ghoul2 ) {
689 		return qfalse;
690 	}
691 
692 	return re->G2API_IKMove( *((CGhoul2Info_v *)ghoul2), time, params );
693 }
694 
CL_G2API_GetSurfaceName(void * ghoul2,int surfNumber,int modelIndex,char * fillBuf)695 static void CL_G2API_GetSurfaceName( void *ghoul2, int surfNumber, int modelIndex, char *fillBuf ) {
696 	if ( !ghoul2 ) {
697 		return;
698 	}
699 
700 	CGhoul2Info_v &g2 = *((CGhoul2Info_v *)ghoul2);
701 	char *tmp = re->G2API_GetSurfaceName( g2, modelIndex, surfNumber );
702 	strcpy( fillBuf, tmp );
703 }
704 
CL_G2API_AttachG2Model(void * ghoul2From,int modelIndexFrom,void * ghoul2To,int toBoltIndex,int toModel)705 static qboolean CL_G2API_AttachG2Model( void *ghoul2From, int modelIndexFrom, void *ghoul2To, int toBoltIndex, int toModel ) {
706 	if ( !ghoul2From || !ghoul2To ) {
707 		return qfalse;
708 	}
709 
710 	CGhoul2Info_v *g2From = ((CGhoul2Info_v *)ghoul2From);
711 	CGhoul2Info_v *g2To = ((CGhoul2Info_v *)ghoul2To);
712 
713 	return re->G2API_AttachG2Model(*g2From, modelIndexFrom, *g2To, toBoltIndex, toModel);
714 }
715 
CL_Key_SetCatcher(int catcher)716 static void CL_Key_SetCatcher( int catcher ) {
717 	// Don't allow the ui module to close the console
718 	Key_SetCatcher( catcher | ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) );
719 }
720 
UIVM_Cvar_Set(const char * var_name,const char * value)721 static void UIVM_Cvar_Set( const char *var_name, const char *value ) {
722 	Cvar_VM_Set( var_name, value, VM_UI );
723 }
724 
UIVM_Cvar_SetValue(const char * var_name,float value)725 static void UIVM_Cvar_SetValue( const char *var_name, float value ) {
726 	Cvar_VM_SetValue( var_name, value, VM_UI );
727 }
728 
CL_AddUICommand(const char * cmdName)729 static void CL_AddUICommand( const char *cmdName ) {
730 	Cmd_AddCommand( cmdName, NULL );
731 }
732 
UIVM_Cmd_RemoveCommand(const char * cmd_name)733 static void UIVM_Cmd_RemoveCommand( const char *cmd_name ) {
734 	Cmd_VM_RemoveCommand( cmd_name, VM_UI );
735 }
736 
737 // legacy syscall
738 
CL_UISystemCalls(intptr_t * args)739 intptr_t CL_UISystemCalls( intptr_t *args ) {
740 	switch ( args[0] ) {
741 		//rww - alright, DO NOT EVER add a GAME/CGAME/UI generic call without adding a trap to match, and
742 		//all of these traps must be shared and have cases in sv_game, cl_cgame, and cl_ui. They must also
743 		//all be in the same order, and start at 100.
744 	case TRAP_MEMSET:
745 		Com_Memset( VMA(1), args[2], args[3] );
746 		return 0;
747 
748 	case TRAP_MEMCPY:
749 		Com_Memcpy( VMA(1), VMA(2), args[3] );
750 		return 0;
751 
752 	case TRAP_STRNCPY:
753 		strncpy( (char *)VMA(1), (const char *)VMA(2), args[3] );
754 		return args[1];
755 
756 	case TRAP_SIN:
757 		return FloatAsInt( sin( VMF(1) ) );
758 
759 	case TRAP_COS:
760 		return FloatAsInt( cos( VMF(1) ) );
761 
762 	case TRAP_ATAN2:
763 		return FloatAsInt( atan2( VMF(1), VMF(2) ) );
764 
765 	case TRAP_SQRT:
766 		return FloatAsInt( sqrt( VMF(1) ) );
767 
768 	case TRAP_MATRIXMULTIPLY:
769 		MatrixMultiply( (vec3_t *)VMA(1), (vec3_t *)VMA(2), (vec3_t *)VMA(3) );
770 		return 0;
771 
772 	case TRAP_ANGLEVECTORS:
773 		AngleVectors( (const float *)VMA(1), (float *)VMA(2), (float *)VMA(3), (float *)VMA(4) );
774 		return 0;
775 
776 	case TRAP_PERPENDICULARVECTOR:
777 		PerpendicularVector( (float *)VMA(1), (const float *)VMA(2) );
778 		return 0;
779 
780 	case TRAP_FLOOR:
781 		return FloatAsInt( floor( VMF(1) ) );
782 
783 	case TRAP_CEIL:
784 		return FloatAsInt( ceil( VMF(1) ) );
785 
786 	case TRAP_TESTPRINTINT:
787 		return 0;
788 
789 	case TRAP_TESTPRINTFLOAT:
790 		return 0;
791 
792 	case TRAP_ACOS:
793 		return FloatAsInt( Q_acos( VMF(1) ) );
794 
795 	case TRAP_ASIN:
796 		return FloatAsInt( Q_asin( VMF(1) ) );
797 
798 	case UI_ERROR:
799 		Com_Error( ERR_DROP, "%s", VMA(1) );
800 		return 0;
801 
802 	case UI_PRINT:
803 		Com_Printf( "%s", VMA(1) );
804 		return 0;
805 
806 	case UI_MILLISECONDS:
807 		return Sys_Milliseconds();
808 
809 	case UI_CVAR_REGISTER:
810 		Cvar_Register( (vmCvar_t *)VMA(1), (const char *)VMA(2), (const char *)VMA(3), args[4] );
811 		return 0;
812 
813 	case UI_CVAR_UPDATE:
814 		Cvar_Update( (vmCvar_t *)VMA(1) );
815 		return 0;
816 
817 	case UI_CVAR_SET:
818 		Cvar_VM_Set( (const char *)VMA(1), (const char *)VMA(2), VM_UI );
819 		return 0;
820 
821 	case UI_CVAR_VARIABLEVALUE:
822 		return FloatAsInt( Cvar_VariableValue( (const char *)VMA(1) ) );
823 
824 	case UI_CVAR_VARIABLESTRINGBUFFER:
825 		Cvar_VariableStringBuffer( (const char *)VMA(1), (char *)VMA(2), args[3] );
826 		return 0;
827 
828 	case UI_CVAR_SETVALUE:
829 		Cvar_VM_SetValue( (const char *)VMA(1), VMF(2), VM_UI );
830 		return 0;
831 
832 	case UI_CVAR_RESET:
833 		Cvar_Reset( (const char *)VMA(1) );
834 		return 0;
835 
836 	case UI_CVAR_CREATE:
837 		Cvar_Get( (const char *)VMA(1), (const char *)VMA(2), args[3] );
838 		return 0;
839 
840 	case UI_CVAR_INFOSTRINGBUFFER:
841 		Cvar_InfoStringBuffer( args[1], (char *)VMA(2), args[3] );
842 		return 0;
843 
844 	case UI_ARGC:
845 		return Cmd_Argc();
846 
847 	case UI_ARGV:
848 		Cmd_ArgvBuffer( args[1], (char *)VMA(2), args[3] );
849 		return 0;
850 
851 	case UI_CMD_EXECUTETEXT:
852 		Cbuf_ExecuteText( args[1], (const char *)VMA(2) );
853 		return 0;
854 
855 	case UI_FS_FOPENFILE:
856 		return FS_FOpenFileByMode( (const char *)VMA(1), (int *)VMA(2), (fsMode_t)args[3] );
857 
858 	case UI_FS_READ:
859 		FS_Read( VMA(1), args[2], args[3] );
860 		return 0;
861 
862 	case UI_FS_WRITE:
863 		FS_Write( VMA(1), args[2], args[3] );
864 		return 0;
865 
866 	case UI_FS_FCLOSEFILE:
867 		FS_FCloseFile( args[1] );
868 		return 0;
869 
870 	case UI_FS_GETFILELIST:
871 		return FS_GetFileList( (const char *)VMA(1), (const char *)VMA(2), (char *)VMA(3), args[4] );
872 
873 	case UI_R_REGISTERMODEL:
874 		return re->RegisterModel( (const char *)VMA(1) );
875 
876 	case UI_R_REGISTERSKIN:
877 		return re->RegisterSkin( (const char *)VMA(1) );
878 
879 	case UI_R_REGISTERSHADERNOMIP:
880 		return re->RegisterShaderNoMip( (const char *)VMA(1) );
881 
882 	case UI_R_SHADERNAMEFROMINDEX:
883 		CL_R_ShaderNameFromIndex( (char *)VMA(1), args[2] );
884 		return 0;
885 
886 	case UI_R_CLEARSCENE:
887 		re->ClearScene();
888 		return 0;
889 
890 	case UI_R_ADDREFENTITYTOSCENE:
891 		re->AddRefEntityToScene( (const refEntity_t *)VMA(1) );
892 		return 0;
893 
894 	case UI_R_ADDPOLYTOSCENE:
895 		re->AddPolyToScene( args[1], args[2], (const polyVert_t *)VMA(3), 1 );
896 		return 0;
897 
898 	case UI_R_ADDLIGHTTOSCENE:
899 		re->AddLightToScene( (const float *)VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) );
900 		return 0;
901 
902 	case UI_R_RENDERSCENE:
903 		re->RenderScene( (const refdef_t *)VMA(1) );
904 		return 0;
905 
906 	case UI_R_SETCOLOR:
907 		re->SetColor( (const float *)VMA(1) );
908 		return 0;
909 
910 	case UI_R_DRAWSTRETCHPIC:
911 		re->DrawStretchPic( VMF(1), VMF(2), VMF(3), VMF(4), VMF(5), VMF(6), VMF(7), VMF(8), args[9] );
912 		return 0;
913 
914 	case UI_R_MODELBOUNDS:
915 		re->ModelBounds( args[1], (float *)VMA(2), (float *)VMA(3) );
916 		return 0;
917 
918 	case UI_UPDATESCREEN:
919 		SCR_UpdateScreen();
920 		return 0;
921 
922 	case UI_CM_LERPTAG:
923 		re->LerpTag( (orientation_t *)VMA(1), args[2], args[3], args[4], VMF(5), (const char *)VMA(6) );
924 		return 0;
925 
926 	case UI_S_REGISTERSOUND:
927 		return S_RegisterSound( (const char *)VMA(1) );
928 
929 	case UI_S_STARTLOCALSOUND:
930 		S_StartLocalSound( args[1], args[2] );
931 		return 0;
932 
933 	case UI_KEY_KEYNUMTOSTRINGBUF:
934 		Key_KeynumToStringBuf( args[1], (char *)VMA(2), args[3] );
935 		return 0;
936 
937 	case UI_KEY_GETBINDINGBUF:
938 		Key_GetBindingBuf( args[1], (char *)VMA(2), args[3] );
939 		return 0;
940 
941 	case UI_KEY_SETBINDING:
942 		Key_SetBinding( args[1], (const char *)VMA(2) );
943 		return 0;
944 
945 	case UI_KEY_ISDOWN:
946 		return Key_IsDown( args[1] );
947 
948 	case UI_KEY_GETOVERSTRIKEMODE:
949 		return Key_GetOverstrikeMode();
950 
951 	case UI_KEY_SETOVERSTRIKEMODE:
952 		Key_SetOverstrikeMode( (qboolean)args[1] );
953 		return 0;
954 
955 	case UI_KEY_CLEARSTATES:
956 		Key_ClearStates();
957 		return 0;
958 
959 	case UI_KEY_GETCATCHER:
960 		return Key_GetCatcher();
961 
962 	case UI_KEY_SETCATCHER:
963 		CL_Key_SetCatcher( args[1] );
964 		return 0;
965 
966 	case UI_GETCLIPBOARDDATA:
967 		GetClipboardData( (char *)VMA(1), args[2] );
968 		return 0;
969 
970 	case UI_GETCLIENTSTATE:
971 		CL_GetClientState( (uiClientState_t *)VMA(1) );
972 		return 0;
973 
974 	case UI_GETGLCONFIG:
975 		CL_GetGlconfig( (glconfig_t *)VMA(1) );
976 		return 0;
977 
978 	case UI_GETCONFIGSTRING:
979 		return GetConfigString( args[1], (char *)VMA(2), args[3] );
980 
981 	case UI_LAN_LOADCACHEDSERVERS:
982 		LAN_LoadCachedServers();
983 		return 0;
984 
985 	case UI_LAN_SAVECACHEDSERVERS:
986 		LAN_SaveServersToCache();
987 		return 0;
988 
989 	case UI_LAN_ADDSERVER:
990 		return LAN_AddServer(args[1], (const char *)VMA(2), (const char *)VMA(3));
991 
992 	case UI_LAN_REMOVESERVER:
993 		LAN_RemoveServer(args[1], (const char *)VMA(2));
994 		return 0;
995 
996 	case UI_LAN_GETPINGQUEUECOUNT:
997 		return LAN_GetPingQueueCount();
998 
999 	case UI_LAN_CLEARPING:
1000 		LAN_ClearPing( args[1] );
1001 		return 0;
1002 
1003 	case UI_LAN_GETPING:
1004 		LAN_GetPing( args[1], (char *)VMA(2), args[3], (int *)VMA(4) );
1005 		return 0;
1006 
1007 	case UI_LAN_GETPINGINFO:
1008 		LAN_GetPingInfo( args[1], (char *)VMA(2), args[3] );
1009 		return 0;
1010 
1011 	case UI_LAN_GETSERVERCOUNT:
1012 		return LAN_GetServerCount(args[1]);
1013 
1014 	case UI_LAN_GETSERVERADDRESSSTRING:
1015 		LAN_GetServerAddressString( args[1], args[2], (char *)VMA(3), args[4] );
1016 		return 0;
1017 
1018 	case UI_LAN_GETSERVERINFO:
1019 		LAN_GetServerInfo( args[1], args[2], (char *)VMA(3), args[4] );
1020 		return 0;
1021 
1022 	case UI_LAN_GETSERVERPING:
1023 		return LAN_GetServerPing( args[1], args[2] );
1024 
1025 	case UI_LAN_MARKSERVERVISIBLE:
1026 		LAN_MarkServerVisible( args[1], args[2], (qboolean)args[3] );
1027 		return 0;
1028 
1029 	case UI_LAN_SERVERISVISIBLE:
1030 		return LAN_ServerIsVisible( args[1], args[2] );
1031 
1032 	case UI_LAN_UPDATEVISIBLEPINGS:
1033 		return LAN_UpdateVisiblePings( args[1] );
1034 
1035 	case UI_LAN_RESETPINGS:
1036 		LAN_ResetPings( args[1] );
1037 		return 0;
1038 
1039 	case UI_LAN_SERVERSTATUS:
1040 		return LAN_GetServerStatus( (char *)VMA(1), (char *)VMA(2), args[3] );
1041 
1042 	case UI_LAN_COMPARESERVERS:
1043 		return LAN_CompareServers( args[1], args[2], args[3], args[4], args[5] );
1044 
1045 	case UI_MEMORY_REMAINING:
1046 		return Hunk_MemoryRemaining();
1047 
1048 	case UI_R_REGISTERFONT:
1049 		return re->RegisterFont( (const char *)VMA(1) );
1050 
1051 	case UI_R_FONT_STRLENPIXELS:
1052 		return re->Font_StrLenPixels( (const char *)VMA(1), args[2], VMF(3) );
1053 
1054 	case UI_R_FONT_STRLENCHARS:
1055 		return re->Font_StrLenChars( (const char *)VMA(1) );
1056 
1057 	case UI_R_FONT_STRHEIGHTPIXELS:
1058 		return re->Font_HeightPixels( args[1], VMF(2) );
1059 
1060 	case UI_R_FONT_DRAWSTRING:
1061 		re->Font_DrawString( args[1], args[2], (const char *)VMA(3), (const float *) VMA(4), args[5], args[6], VMF(7) );
1062 		return 0;
1063 
1064 	case UI_LANGUAGE_ISASIAN:
1065 		return re->Language_IsAsian();
1066 
1067 	case UI_LANGUAGE_USESSPACES:
1068 		return re->Language_UsesSpaces();
1069 
1070 	case UI_ANYLANGUAGE_READCHARFROMSTRING:
1071 		return re->AnyLanguage_ReadCharFromString( (const char *)VMA(1), (int *) VMA(2), (qboolean *) VMA(3) );
1072 
1073 	case UI_PC_ADD_GLOBAL_DEFINE:
1074 		return botlib_export->PC_AddGlobalDefine( (char *)VMA(1) );
1075 
1076 	case UI_PC_LOAD_SOURCE:
1077 		return botlib_export->PC_LoadSourceHandle( (const char *)VMA(1) );
1078 
1079 	case UI_PC_FREE_SOURCE:
1080 		return botlib_export->PC_FreeSourceHandle( args[1] );
1081 
1082 	case UI_PC_READ_TOKEN:
1083 		return botlib_export->PC_ReadTokenHandle( args[1], (struct pc_token_s *)VMA(2) );
1084 
1085 	case UI_PC_SOURCE_FILE_AND_LINE:
1086 		return botlib_export->PC_SourceFileAndLine( args[1], (char *)VMA(2), (int *)VMA(3) );
1087 
1088 	case UI_PC_LOAD_GLOBAL_DEFINES:
1089 		return botlib_export->PC_LoadGlobalDefines ( (char *)VMA(1) );
1090 
1091 	case UI_PC_REMOVE_ALL_GLOBAL_DEFINES:
1092 		botlib_export->PC_RemoveAllGlobalDefines ( );
1093 		return 0;
1094 
1095 	case UI_S_STOPBACKGROUNDTRACK:
1096 		S_StopBackgroundTrack();
1097 		return 0;
1098 
1099 	case UI_S_STARTBACKGROUNDTRACK:
1100 		S_StartBackgroundTrack( (const char *)VMA(1), (const char *)VMA(2), qfalse );
1101 		return 0;
1102 
1103 	case UI_REAL_TIME:
1104 		return Com_RealTime( (struct qtime_s *)VMA(1) );
1105 
1106 	case UI_CIN_PLAYCINEMATIC:
1107 		Com_DPrintf("UI_CIN_PlayCinematic\n");
1108 		return CIN_PlayCinematic((const char *)VMA(1), args[2], args[3], args[4], args[5], args[6]);
1109 
1110 	case UI_CIN_STOPCINEMATIC:
1111 		return CIN_StopCinematic(args[1]);
1112 
1113 	case UI_CIN_RUNCINEMATIC:
1114 		return CIN_RunCinematic(args[1]);
1115 
1116 	case UI_CIN_DRAWCINEMATIC:
1117 		CIN_DrawCinematic(args[1]);
1118 		return 0;
1119 
1120 	case UI_CIN_SETEXTENTS:
1121 		CIN_SetExtents(args[1], args[2], args[3], args[4], args[5]);
1122 		return 0;
1123 
1124 	case UI_R_REMAP_SHADER:
1125 		re->RemapShader( (const char *)VMA(1), (const char *)VMA(2), (const char *)VMA(3) );
1126 		return 0;
1127 
1128 	case UI_SP_GETNUMLANGUAGES:
1129 		return SE_GetNumLanguages();
1130 
1131 	case UI_SP_GETLANGUAGENAME:
1132 		CL_SE_GetLanguageName( args[1], (char *)VMA(2) );
1133 		return 0;
1134 
1135 	case UI_SP_GETSTRINGTEXTSTRING:
1136 		return CL_SE_GetStringTextString( (const char *)VMA(1), (char *)VMA(2), args[3] );
1137 
1138 	case UI_G2_LISTSURFACES:
1139 		CL_G2API_ListModelSurfaces( VMA(1) );
1140 		return 0;
1141 
1142 	case UI_G2_LISTBONES:
1143 		CL_G2API_ListModelBones( VMA(1), args[2]);
1144 		return 0;
1145 
1146 	case UI_G2_HAVEWEGHOULMODELS:
1147 		return CL_G2API_HaveWeGhoul2Models( VMA(1) );
1148 
1149 	case UI_G2_SETMODELS:
1150 		CL_G2API_SetGhoul2ModelIndexes( VMA(1),(qhandle_t *)VMA(2),(qhandle_t *)VMA(3));
1151 		return 0;
1152 
1153 	case UI_G2_GETBOLT:
1154 		return CL_G2API_GetBoltMatrix(VMA(1), args[2], args[3], (mdxaBone_t *)VMA(4), (const float *)VMA(5),(const float *)VMA(6), args[7], (qhandle_t *)VMA(8), (float *)VMA(9));
1155 
1156 	case UI_G2_GETBOLT_NOREC:
1157 		return CL_G2API_GetBoltMatrix_NoReconstruct(VMA(1), args[2], args[3], (mdxaBone_t *)VMA(4), (const float *)VMA(5),(const float *)VMA(6), args[7], (qhandle_t *)VMA(8), (float *)VMA(9));
1158 
1159 	case UI_G2_GETBOLT_NOREC_NOROT:
1160 		return CL_G2API_GetBoltMatrix_NoRecNoRot(VMA(1), args[2], args[3], (mdxaBone_t *)VMA(4), (const float *)VMA(5),(const float *)VMA(6), args[7], (qhandle_t *)VMA(8), (float *)VMA(9));
1161 
1162 	case UI_G2_INITGHOUL2MODEL:
1163 #ifdef _FULL_G2_LEAK_CHECKING
1164 		g_G2AllocServer = 0;
1165 #endif
1166 		return CL_G2API_InitGhoul2Model((void **)VMA(1), (const char *)VMA(2), args[3], (qhandle_t) args[4], (qhandle_t) args[5], args[6], args[7]);
1167 
1168 	case UI_G2_COLLISIONDETECT:
1169 	case UI_G2_COLLISIONDETECTCACHE:
1170 		return 0; //not supported for ui
1171 
1172 	case UI_G2_ANGLEOVERRIDE:
1173 		return CL_G2API_SetBoneAngles(VMA(1), args[2], (const char *)VMA(3), (float *)VMA(4), args[5], (const Eorientations) args[6], (const Eorientations) args[7], (const Eorientations) args[8], (qhandle_t *)VMA(9), args[10], args[11] );
1174 
1175 	case UI_G2_CLEANMODELS:
1176 #ifdef _FULL_G2_LEAK_CHECKING
1177 		g_G2AllocServer = 0;
1178 #endif
1179 		CL_G2API_CleanGhoul2Models((void **)VMA(1));
1180 		return 0;
1181 
1182 	case UI_G2_PLAYANIM:
1183 		return CL_G2API_SetBoneAnim(VMA(1), args[2], (const char *)VMA(3), args[4], args[5], args[6], VMF(7), args[8], VMF(9), args[10]);
1184 
1185 	case UI_G2_GETBONEANIM:
1186 		return CL_G2API_GetBoneAnim(VMA(1), (const char*)VMA(2), args[3], (float *)VMA(4), (int *)VMA(5), (int *)VMA(6), (int *)VMA(7), (float *)VMA(8), (int *)VMA(9), args[10]);
1187 
1188 	case UI_G2_GETBONEFRAME:
1189 		return CL_G2API_GetBoneFrame(VMA(1), (const char*)VMA(2), args[3], (float *)VMA(4), (int *)VMA(5), args[6]);
1190 
1191 	case UI_G2_GETGLANAME:
1192 		CL_G2API_GetGLAName( VMA(1), args[2], (char *)VMA(3) );
1193 		return 0;
1194 
1195 	case UI_G2_COPYGHOUL2INSTANCE:
1196 		return (int)CL_G2API_CopyGhoul2Instance(VMA(1), VMA(2), args[3]);
1197 
1198 	case UI_G2_COPYSPECIFICGHOUL2MODEL:
1199 		CL_G2API_CopySpecificGhoul2Model(VMA(1), args[2], VMA(3), args[4]);
1200 		return 0;
1201 
1202 	case UI_G2_DUPLICATEGHOUL2INSTANCE:
1203 #ifdef _FULL_G2_LEAK_CHECKING
1204 		g_G2AllocServer = 0;
1205 #endif
1206 		CL_G2API_DuplicateGhoul2Instance(VMA(1), (void **)VMA(2));
1207 		return 0;
1208 
1209 	case UI_G2_HASGHOUL2MODELONINDEX:
1210 		return (int)CL_G2API_HasGhoul2ModelOnIndex(VMA(1), args[2]);
1211 
1212 	case UI_G2_REMOVEGHOUL2MODEL:
1213 #ifdef _FULL_G2_LEAK_CHECKING
1214 		g_G2AllocServer = 0;
1215 #endif
1216 		return (int)CL_G2API_RemoveGhoul2Model(VMA(1), args[2]);
1217 
1218 	case UI_G2_ADDBOLT:
1219 		return CL_G2API_AddBolt(VMA(1), args[2], (const char *)VMA(3));
1220 
1221 	case UI_G2_SETBOLTON:
1222 		CL_G2API_SetBoltInfo(VMA(1), args[2], args[3]);
1223 		return 0;
1224 
1225 	case UI_G2_SETROOTSURFACE:
1226 		return CL_G2API_SetRootSurface(VMA(1), args[2], (const char *)VMA(3));
1227 
1228 	case UI_G2_SETSURFACEONOFF:
1229 		return CL_G2API_SetSurfaceOnOff(VMA(1), (const char *)VMA(2), args[3]);
1230 
1231 	case UI_G2_SETNEWORIGIN:
1232 		return CL_G2API_SetNewOrigin(VMA(1), args[2]);
1233 
1234 	case UI_G2_GETTIME:
1235 		return CL_G2API_GetTime();
1236 
1237 	case UI_G2_SETTIME:
1238 		CL_G2API_SetTime(args[1], args[2]);
1239 		return 0;
1240 
1241 	case UI_G2_SETRAGDOLL:
1242 		return 0; //not supported for ui
1243 		break;
1244 
1245 	case UI_G2_ANIMATEG2MODELS:
1246 		return 0; //not supported for ui
1247 		break;
1248 
1249 	case UI_G2_SETBONEIKSTATE:
1250 		return CL_G2API_SetBoneIKState(VMA(1), args[2], (const char *)VMA(3), args[4], (sharedSetBoneIKStateParams_t *)VMA(5));
1251 
1252 	case UI_G2_IKMOVE:
1253 		return CL_G2API_IKMove(VMA(1), args[2], (sharedIKMoveParams_t *)VMA(3));
1254 
1255 	case UI_G2_GETSURFACENAME:
1256 		CL_G2API_GetSurfaceName( (void *)args[1], args[2], args[3], (char *)VMA( 4 ) );
1257 		return 0;
1258 
1259 	case UI_G2_SETSKIN:
1260 		return CL_G2API_SetSkin(VMA(1), args[2], args[3], args[4]);
1261 
1262 	case UI_G2_ATTACHG2MODEL:
1263 		return CL_G2API_AttachG2Model(VMA(1), args[2], VMA(3), args[4], args[5]);
1264 
1265 	default:
1266 		Com_Error( ERR_DROP, "Bad UI system trap: %ld", (long int) args[0] );
1267 
1268 	}
1269 
1270 	return 0;
1271 }
1272 
CL_BindUI(void)1273 void CL_BindUI( void ) {
1274 	static uiImport_t uii;
1275 	uiExport_t		*ret;
1276 	GetUIAPI_t		GetUIAPI;
1277 	char			dllName[MAX_OSPATH] = "ui" ARCH_STRING DLL_EXT;
1278 
1279 	memset( &uii, 0, sizeof( uii ) );
1280 
1281 	uivm = VM_Create( VM_UI );
1282 	if ( uivm && !uivm->isLegacy ) {
1283 		uii.Print								= Com_Printf;
1284 		uii.Error								= Com_Error;
1285 		uii.Milliseconds						= CL_Milliseconds;
1286 		uii.RealTime							= Com_RealTime;
1287 		uii.MemoryRemaining						= Hunk_MemoryRemaining;
1288 
1289 		uii.Cvar_Create							= CL_Cvar_Get;
1290 		uii.Cvar_InfoStringBuffer				= Cvar_InfoStringBuffer;
1291 		uii.Cvar_Register						= Cvar_Register;
1292 		uii.Cvar_Reset							= Cvar_Reset;
1293 		uii.Cvar_Set							= UIVM_Cvar_Set;
1294 		uii.Cvar_SetValue						= UIVM_Cvar_SetValue;
1295 		uii.Cvar_Update							= Cvar_Update;
1296 		uii.Cvar_VariableStringBuffer			= Cvar_VariableStringBuffer;
1297 		uii.Cvar_VariableValue					= Cvar_VariableValue;
1298 
1299 		uii.Cmd_Argc							= Cmd_Argc;
1300 		uii.Cmd_Argv							= Cmd_ArgvBuffer;
1301 		uii.Cmd_ExecuteText						= Cbuf_ExecuteText;
1302 
1303 		uii.FS_Close							= FS_FCloseFile;
1304 		uii.FS_GetFileList						= FS_GetFileList;
1305 		uii.FS_Open								= FS_FOpenFileByMode;
1306 		uii.FS_Read								= FS_Read;
1307 		uii.FS_Write							= FS_Write;
1308 
1309 		uii.GetClientState						= CL_GetClientState;
1310 		uii.GetClipboardData					= GetClipboardData;
1311 		uii.GetConfigString						= GetConfigString;
1312 		uii.GetGlconfig							= CL_GetGlconfig;
1313 		uii.UpdateScreen						= SCR_UpdateScreen;
1314 
1315 		uii.Key_ClearStates						= Key_ClearStates;
1316 		uii.Key_GetBindingBuf					= Key_GetBindingBuf;
1317 		uii.Key_IsDown							= Key_IsDown;
1318 		uii.Key_KeynumToStringBuf				= Key_KeynumToStringBuf;
1319 		uii.Key_SetBinding						= Key_SetBinding;
1320 		uii.Key_GetCatcher						= Key_GetCatcher;
1321 		uii.Key_GetOverstrikeMode				= Key_GetOverstrikeMode;
1322 		uii.Key_SetCatcher						= CL_Key_SetCatcher;
1323 		uii.Key_SetOverstrikeMode				= Key_SetOverstrikeMode;
1324 
1325 		uii.PC_AddGlobalDefine					= botlib_export->PC_AddGlobalDefine;
1326 		uii.PC_FreeSource						= botlib_export->PC_FreeSourceHandle;
1327 		uii.PC_LoadGlobalDefines				= botlib_export->PC_LoadGlobalDefines;
1328 		uii.PC_LoadSource						= botlib_export->PC_LoadSourceHandle;
1329 		uii.PC_ReadToken						= botlib_export->PC_ReadTokenHandle;
1330 		uii.PC_RemoveAllGlobalDefines			= botlib_export->PC_RemoveAllGlobalDefines;
1331 		uii.PC_SourceFileAndLine				= botlib_export->PC_SourceFileAndLine;
1332 
1333 		uii.CIN_DrawCinematic					= CIN_DrawCinematic;
1334 		uii.CIN_PlayCinematic					= CIN_PlayCinematic;
1335 		uii.CIN_RunCinematic					= CIN_RunCinematic;
1336 		uii.CIN_SetExtents						= CIN_SetExtents;
1337 		uii.CIN_StopCinematic					= CIN_StopCinematic;
1338 
1339 		uii.LAN_AddServer						= LAN_AddServer;
1340 		uii.LAN_ClearPing						= LAN_ClearPing;
1341 		uii.LAN_CompareServers					= LAN_CompareServers;
1342 		uii.LAN_GetPing							= LAN_GetPing;
1343 		uii.LAN_GetPingInfo						= LAN_GetPingInfo;
1344 		uii.LAN_GetPingQueueCount				= LAN_GetPingQueueCount;
1345 		uii.LAN_GetServerAddressString			= LAN_GetServerAddressString;
1346 		uii.LAN_GetServerCount					= LAN_GetServerCount;
1347 		uii.LAN_GetServerInfo					= LAN_GetServerInfo;
1348 		uii.LAN_GetServerPing					= LAN_GetServerPing;
1349 		uii.LAN_LoadCachedServers				= LAN_LoadCachedServers;
1350 		uii.LAN_MarkServerVisible				= LAN_MarkServerVisible;
1351 		uii.LAN_RemoveServer					= LAN_RemoveServer;
1352 		uii.LAN_ResetPings						= LAN_ResetPings;
1353 		uii.LAN_SaveCachedServers				= LAN_SaveServersToCache;
1354 		uii.LAN_ServerIsVisible					= LAN_ServerIsVisible;
1355 		uii.LAN_ServerStatus					= LAN_GetServerStatus;
1356 		uii.LAN_UpdateVisiblePings				= LAN_UpdateVisiblePings;
1357 
1358 		uii.S_StartBackgroundTrack				= S_StartBackgroundTrack;
1359 		uii.S_StartLocalSound					= S_StartLocalSound;
1360 		uii.S_StopBackgroundTrack				= S_StopBackgroundTrack;
1361 		uii.S_RegisterSound						= S_RegisterSound;
1362 
1363 		uii.SE_GetLanguageName					= CL_SE_GetLanguageName;
1364 		uii.SE_GetNumLanguages					= SE_GetNumLanguages;
1365 		uii.SE_GetStringTextString				= CL_SE_GetStringTextString;
1366 
1367 		uii.R_Language_IsAsian					= re->Language_IsAsian;
1368 		uii.R_Language_UsesSpaces				= re->Language_UsesSpaces;
1369 		uii.R_AnyLanguage_ReadCharFromString	= re->AnyLanguage_ReadCharFromString;
1370 
1371 		uii.R_AddLightToScene					= re->AddLightToScene;
1372 		uii.R_AddPolysToScene					= re->AddPolyToScene;
1373 		uii.R_AddRefEntityToScene				= re->AddRefEntityToScene;
1374 		uii.R_ClearScene						= re->ClearScene;
1375 		uii.R_DrawStretchPic					= re->DrawStretchPic;
1376 		uii.R_Font_DrawString					= re->Font_DrawString;
1377 		uii.R_Font_HeightPixels					= re->Font_HeightPixels;
1378 		uii.R_Font_StrLenChars					= re->Font_StrLenChars;
1379 		uii.R_Font_StrLenPixels					= re->Font_StrLenPixels;
1380 		uii.R_LerpTag							= re->LerpTag;
1381 		uii.R_ModelBounds						= re->ModelBounds;
1382 		uii.R_RegisterFont						= re->RegisterFont;
1383 		uii.R_RegisterModel						= re->RegisterModel;
1384 		uii.R_RegisterShaderNoMip				= re->RegisterShaderNoMip;
1385 		uii.R_RegisterSkin						= re->RegisterSkin;
1386 		uii.R_RemapShader						= re->RemapShader;
1387 		uii.R_RenderScene						= re->RenderScene;
1388 		uii.R_SetColor							= re->SetColor;
1389 		uii.R_ShaderNameFromIndex				= CL_R_ShaderNameFromIndex;
1390 
1391 		uii.G2_ListModelSurfaces				= CL_G2API_ListModelSurfaces;
1392 		uii.G2_ListModelBones					= CL_G2API_ListModelBones;
1393 		uii.G2_SetGhoul2ModelIndexes			= CL_G2API_SetGhoul2ModelIndexes;
1394 		uii.G2_HaveWeGhoul2Models				= CL_G2API_HaveWeGhoul2Models;
1395 		uii.G2API_GetBoltMatrix					= CL_G2API_GetBoltMatrix;
1396 		uii.G2API_GetBoltMatrix_NoReconstruct	= CL_G2API_GetBoltMatrix_NoReconstruct;
1397 		uii.G2API_GetBoltMatrix_NoRecNoRot		= CL_G2API_GetBoltMatrix_NoRecNoRot;
1398 		uii.G2API_InitGhoul2Model				= CL_G2API_InitGhoul2Model;
1399 		uii.G2API_SetSkin						= CL_G2API_SetSkin;
1400 		uii.G2API_CollisionDetect				= CL_G2API_CollisionDetect;
1401 		uii.G2API_CollisionDetectCache			= CL_G2API_CollisionDetectCache;
1402 		uii.G2API_CleanGhoul2Models				= CL_G2API_CleanGhoul2Models;
1403 		uii.G2API_SetBoneAngles					= CL_G2API_SetBoneAngles;
1404 		uii.G2API_SetBoneAnim					= CL_G2API_SetBoneAnim;
1405 		uii.G2API_GetBoneAnim					= CL_G2API_GetBoneAnim;
1406 		uii.G2API_GetBoneFrame					= CL_G2API_GetBoneFrame;
1407 		uii.G2API_GetGLAName					= CL_G2API_GetGLAName;
1408 		uii.G2API_CopyGhoul2Instance			= CL_G2API_CopyGhoul2Instance;
1409 		uii.G2API_CopySpecificGhoul2Model		= CL_G2API_CopySpecificGhoul2Model;
1410 		uii.G2API_DuplicateGhoul2Instance		= CL_G2API_DuplicateGhoul2Instance;
1411 		uii.G2API_HasGhoul2ModelOnIndex			= CL_G2API_HasGhoul2ModelOnIndex;
1412 		uii.G2API_RemoveGhoul2Model				= CL_G2API_RemoveGhoul2Model;
1413 		uii.G2API_AddBolt						= CL_G2API_AddBolt;
1414 		uii.G2API_SetBoltInfo					= CL_G2API_SetBoltInfo;
1415 		uii.G2API_SetRootSurface				= CL_G2API_SetRootSurface;
1416 		uii.G2API_SetSurfaceOnOff				= CL_G2API_SetSurfaceOnOff;
1417 		uii.G2API_SetNewOrigin					= CL_G2API_SetNewOrigin;
1418 		uii.G2API_GetTime						= CL_G2API_GetTime;
1419 		uii.G2API_SetTime						= CL_G2API_SetTime;
1420 		uii.G2API_SetRagDoll					= CL_G2API_SetRagDoll;
1421 		uii.G2API_AnimateG2Models				= CL_G2API_AnimateG2Models;
1422 		uii.G2API_SetBoneIKState				= CL_G2API_SetBoneIKState;
1423 		uii.G2API_IKMove						= CL_G2API_IKMove;
1424 		uii.G2API_GetSurfaceName				= CL_G2API_GetSurfaceName;
1425 		uii.G2API_AttachG2Model					= CL_G2API_AttachG2Model;
1426 
1427 		uii.ext.R_Font_StrLenPixels				= re->ext.Font_StrLenPixels;
1428 		uii.ext.AddCommand						= CL_AddUICommand;
1429 		uii.ext.RemoveCommand					= UIVM_Cmd_RemoveCommand;
1430 
1431 		GetUIAPI = (GetUIAPI_t)uivm->GetModuleAPI;
1432 		ret = GetUIAPI( UI_API_VERSION, &uii );
1433 		if ( !ret ) {
1434 			//free VM?
1435 			cls.uiStarted = qfalse;
1436 			Com_Error( ERR_FATAL, "GetGameAPI failed on %s", dllName );
1437 		}
1438 		uie = ret;
1439 
1440 		return;
1441 	}
1442 
1443 	// fall back to legacy syscall/vm_call api
1444 	uivm = VM_CreateLegacy( VM_UI, CL_UISystemCalls );
1445 	if ( !uivm ) {
1446 		cls.uiStarted = qfalse;
1447 		Com_Error( ERR_DROP, "VM_CreateLegacy on ui failed" );
1448 	}
1449 }
1450 
CL_UnbindUI(void)1451 void CL_UnbindUI( void ) {
1452 	UIVM_Shutdown();
1453 	VM_Free( uivm );
1454 	uivm = NULL;
1455 }
1456