Skip to content

Commit

Permalink
Fix VM_Call/syscall argument expansion on 64-bit (#99)
Browse files Browse the repository at this point in the history
Every argument needs to be cast to intptr_t to ensure the memory is correctly aligned for va_arg as it reads everything as intptr_t to support both x86 and x64 correctly.
  • Loading branch information
Aciz authored Jul 22, 2024
1 parent ca39dd8 commit 191fd55
Show file tree
Hide file tree
Showing 19 changed files with 495 additions and 425 deletions.
318 changes: 159 additions & 159 deletions src/cgame/cg_syscalls.c

Large diffs are not rendered by default.

35 changes: 22 additions & 13 deletions src/client/cl_cgame.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ static void CL_SetClientLerpOrigin( float x, float y, float z ) {

qboolean CL_CGameCheckKeyExec( int key ) {
if ( cgvm ) {
return VM_Call( cgvm, 1, CG_CHECKEXECKEY, key );
return VM_Call( cgvm, CG_CHECKEXECKEY, key );
} else {
return qfalse;
}
Expand Down Expand Up @@ -421,7 +421,7 @@ static qboolean CL_GetServerCommand( int serverCommandNumber ) {
if ( !strcmp( cmd, "popup" ) ) { // direct server to client popup request, bypassing cgame
// trap_UI_Popup(Cmd_Argv(1));
// if ( cls.state == CA_ACTIVE && !clc.demoplaying ) {
// VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_CLIPBOARD);
// VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_CLIPBOARD);
// Menus_OpenByName(Cmd_Argv(1));
// }
return qfalse;
Expand Down Expand Up @@ -542,7 +542,7 @@ void CL_CGameBinaryMessageReceived( const char *buf, int buflen, int serverTime
// TODO error instead or is this sufficient?
if ( !cgvm )
return;
VM_Call( cgvm, 3, CG_MESSAGERECEIVED, buf, buflen, serverTime );
VM_Call( cgvm, CG_MESSAGERECEIVED, buf, buflen, serverTime );
}

/*
Expand Down Expand Up @@ -584,7 +584,7 @@ void CL_ShutdownCGame( void ) {
return;
}

VM_Call( cgvm, 0, CG_SHUTDOWN );
VM_Call( cgvm, CG_SHUTDOWN );
VM_Free( cgvm );
cgvm = NULL;
Cmd_UnregisterModule( MODULE_CGAME );
Expand Down Expand Up @@ -1094,7 +1094,7 @@ static intptr_t CL_CgameSystemCalls( intptr_t *args ) {
case CG_INGAME_POPUP:
if ( cls.state == CA_ACTIVE && !clc.demoplaying ) {
if ( uivm ) { // Gordon: can be called as the system is shutting down
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, args[1] );
VM_Call( uivm, UI_SET_ACTIVE_MENU, args[1] );
}
}
return 0;
Expand Down Expand Up @@ -1197,14 +1197,23 @@ CL_DllSyscall
*/
static intptr_t QDECL CL_DllSyscall( intptr_t arg, ... ) {
#if !id386 || defined __clang__
intptr_t args[12]; // max.count for cgame
intptr_t args[13]; // max.count for cgame + VM_CALL_END
va_list ap;
int i;
size_t len = ARRAY_LEN(args);

args[0] = arg;
va_start( ap, arg );
for (i = 1; i < ARRAY_LEN( args ); i++ )
args[ i ] = va_arg( ap, intptr_t );

for (i = 1; i < len; i++) {
args[i] = va_arg(ap, intptr_t);

if (VM_CALL_END == (int)args[i]) {
args[i] = 0;
break;
}
}

va_end( ap );

return CL_CgameSystemCalls( args );
Expand Down Expand Up @@ -1345,10 +1354,10 @@ void CL_InitCGame( void ) {
// otherwise server commands sent just before a gamestate are dropped
//bani - added clc.demoplaying, since some mods need this at init time, and drawactiveframe is too late for them
if ( currentGameMod == GAMEMOD_LEGACY ) {
VM_Call( cgvm, 7, CG_INIT, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum, clc.demoplaying, qtrue, NULL, com_legacyVersion->integer );
VM_Call( cgvm, CG_INIT, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum, clc.demoplaying, qtrue, NULL, com_legacyVersion->integer );
}
else {
VM_Call( cgvm, 4, CG_INIT, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum, clc.demoplaying );
VM_Call( cgvm, CG_INIT, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum, clc.demoplaying );
}

// reset any CVAR_CHEAT cvars registered by cgame
Expand Down Expand Up @@ -1398,7 +1407,7 @@ qboolean CL_GameCommand( void ) {
return qfalse;
}

bRes = (qboolean)VM_Call( cgvm, 0, CG_CONSOLE_COMMAND );
bRes = (qboolean)VM_Call( cgvm, CG_CONSOLE_COMMAND );

Cbuf_NestedReset();

Expand All @@ -1412,7 +1421,7 @@ CL_CGameRendering
=====================
*/
void CL_CGameRendering( stereoFrame_t stereo ) {
VM_Call( cgvm, 3, CG_DRAW_ACTIVE_FRAME, cl.serverTime, stereo, clc.demoplaying );
VM_Call( cgvm, CG_DRAW_ACTIVE_FRAME, cl.serverTime, stereo, clc.demoplaying );
#ifdef _DEBUG
VM_Debug( 0 );
#endif
Expand Down Expand Up @@ -1714,7 +1723,7 @@ qboolean CL_GetTag( int clientNum, char *tagname, orientation_t *orientation ) {
return qfalse;
}

return VM_Call( cgvm, 3, CG_GET_TAG, clientNum, tagname, orientation );
return VM_Call( cgvm, CG_GET_TAG, clientNum, tagname, orientation );
}

qboolean CL_CgameRunning( void ) {
Expand Down
2 changes: 1 addition & 1 deletion src/client/cl_cin.c
Original file line number Diff line number Diff line change
Expand Up @@ -1502,7 +1502,7 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi
if ( cinTable[currentHandle].alterGameState ) {
// close the menu
if ( uivm ) {
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_NONE );
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NONE );
}
} else {
cinTable[currentHandle].playonwalls = cl_inGameVideo->integer;
Expand Down
4 changes: 2 additions & 2 deletions src/client/cl_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -436,15 +436,15 @@ void CL_MouseEvent( int dx, int dy /*, int time*/ ) {
cl.mouseDx[cl.mouseIndex] += dx;
cl.mouseDy[cl.mouseIndex] += dy;
} else {
VM_Call( uivm, 2, UI_MOUSE_EVENT, dx, dy );
VM_Call( uivm, UI_MOUSE_EVENT, dx, dy );
}

} else if ( Key_GetCatcher() & KEYCATCH_CGAME ) {
if ( cl_bypassMouseInput->integer == 1 ) {
cl.mouseDx[cl.mouseIndex] += dx;
cl.mouseDy[cl.mouseIndex] += dy;
} else {
VM_Call( cgvm, 2, CG_MOUSE_EVENT, dx, dy );
VM_Call( cgvm, CG_MOUSE_EVENT, dx, dy );
}
} else {
cl.mouseDx[cl.mouseIndex] += dx;
Expand Down
28 changes: 14 additions & 14 deletions src/client/cl_keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,13 +681,13 @@ static void CL_KeyDownEvent( int key, unsigned time )
// escape always gets out of CGAME stuff
if (Key_GetCatcher( ) & KEYCATCH_CGAME) {
Key_SetCatcher( Key_GetCatcher( ) & ~KEYCATCH_CGAME );
VM_Call( cgvm, 1, CG_EVENT_HANDLING, CGAME_EVENT_NONE );
VM_Call( cgvm, CG_EVENT_HANDLING, CGAME_EVENT_NONE );
return;
}

if ( !( Key_GetCatcher( ) & KEYCATCH_UI ) ) {
if ( cls.state == CA_ACTIVE && !clc.demoplaying ) {
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_INGAME );
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_INGAME );
}
else if ( cls.state != CA_DISCONNECTED ) {
#if 0
Expand All @@ -702,12 +702,12 @@ static void CL_KeyDownEvent( int key, unsigned time )
CL_FlushMemory();
}
#endif
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
}
return;
}

VM_Call( uivm, 2, UI_KEY_EVENT, key, qtrue );
VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
return;
}

Expand All @@ -730,12 +730,12 @@ static void CL_KeyDownEvent( int key, unsigned time )
Console_Key( key );
}
} else if ( (Key_GetCatcher() & KEYCATCH_UI) && uivm && !bypassMenu ) {
if ( !onlybinds || VM_Call( uivm, 0, UI_WANTSBINDKEYS ) ) {
VM_Call( uivm, 2, UI_KEY_EVENT, key, qtrue );
if ( !onlybinds || VM_Call( uivm, UI_WANTSBINDKEYS ) ) {
VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
}
} else if ( (Key_GetCatcher() & KEYCATCH_CGAME) && cgvm && !bypassMenu ) {
if ( !onlybinds || VM_Call( cgvm, 0, CG_WANTSBINDKEYS ) ) {
VM_Call( cgvm, 2, CG_KEY_EVENT, key, qtrue );
if ( !onlybinds || VM_Call( cgvm, CG_WANTSBINDKEYS ) ) {
VM_Call( cgvm, CG_KEY_EVENT, key, qtrue );
}
} else if ( Key_GetCatcher() & KEYCATCH_MESSAGE ) {
if ( !onlybinds ) {
Expand Down Expand Up @@ -799,12 +799,12 @@ static void CL_KeyUpEvent( int key, unsigned time )
}

if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
if ( !onlybinds || VM_Call( uivm, 0, UI_WANTSBINDKEYS ) ) {
VM_Call( uivm, 2, UI_KEY_EVENT, key, qfalse );
if ( !onlybinds || VM_Call( uivm, UI_WANTSBINDKEYS ) ) {
VM_Call( uivm, UI_KEY_EVENT, key, qfalse );
}
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) {
if ( !onlybinds || VM_Call( cgvm, 0, CG_WANTSBINDKEYS ) ) {
VM_Call( cgvm, 2, CG_KEY_EVENT, key, qfalse );
if ( !onlybinds || VM_Call( cgvm, CG_WANTSBINDKEYS ) ) {
VM_Call( cgvm, CG_KEY_EVENT, key, qfalse );
}
}
}
Expand Down Expand Up @@ -847,11 +847,11 @@ void CL_CharEvent( int key )
}
else if ( Key_GetCatcher( ) & KEYCATCH_UI )
{
VM_Call( uivm, 2, UI_KEY_EVENT, key | K_CHAR_FLAG, qtrue );
VM_Call( uivm, UI_KEY_EVENT, key | K_CHAR_FLAG, qtrue );
}
else if ( Key_GetCatcher( ) & KEYCATCH_CGAME )
{
VM_Call( cgvm, 2, CG_KEY_EVENT, key | K_CHAR_FLAG, qtrue );
VM_Call( cgvm, CG_KEY_EVENT, key | K_CHAR_FLAG, qtrue );
}
else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE )
{
Expand Down
10 changes: 5 additions & 5 deletions src/client/cl_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1429,7 +1429,7 @@ qboolean CL_Disconnect( qboolean showMainMenu ) {
Key_ClearStates();

if ( uivm && showMainMenu ) {
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_NONE );
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NONE );
}

// Remove pure paks
Expand Down Expand Up @@ -1616,7 +1616,7 @@ void CL_Disconnect_f( void ) {
CL_FlushMemory();
}
if ( uivm ) {
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
}
}
}
Expand Down Expand Up @@ -3116,7 +3116,7 @@ static void CL_CheckTimeout( void ) {
CL_FlushMemory();
}
if ( uivm ) {
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
}
return;
}
Expand Down Expand Up @@ -3335,12 +3335,12 @@ void CL_Frame( int msec, int realMsec ) {
if ( cls.cddialog ) {
// bring up the cd error dialog if needed
cls.cddialog = qfalse;
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_NEED_CD );
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_NEED_CD );
} else if ( cls.state == CA_DISCONNECTED && !( Key_GetCatcher( ) & KEYCATCH_UI )
&& !com_sv_running->integer && uivm ) {
// if disconnected, bring up the menu
S_StopAllSounds();
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
}

aviRecord = CL_VideoRecording();
Expand Down
16 changes: 8 additions & 8 deletions src/client/cl_scrn.c
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ static void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {

re.BeginFrame( stereoFrame );

uiFullscreen = (uivm && VM_Call( uivm, 0, UI_IS_FULLSCREEN ));
uiFullscreen = (uivm && VM_Call( uivm, UI_IS_FULLSCREEN ));

// wide aspect ratio screens need to have the sides cleared
// unless they are displaying game renderings
Expand Down Expand Up @@ -556,20 +556,20 @@ static void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
case CA_DISCONNECTED:
// force menu up
S_StopAllSounds();
VM_Call( uivm, 1, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN );
break;
case CA_CONNECTING:
case CA_CHALLENGING:
case CA_CONNECTED:
// connecting clients will only show the connection dialog
// refresh to update the time
VM_Call( uivm, 1, UI_REFRESH, cls.realtime );
VM_Call( uivm, 1, UI_DRAW_CONNECT_SCREEN, qfalse );
VM_Call( uivm, UI_REFRESH, cls.realtime );
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qfalse );
break;
// // Ridah, if the cgame is valid, fall through to there
// if (!cls.cgameStarted || !com_sv_running->integer) {
// // connecting clients will only show the connection dialog
// VM_Call( uivm, 1, UI_DRAW_CONNECT_SCREEN, qfalse );
// VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qfalse );
// break;
// }
case CA_LOADING:
Expand All @@ -581,8 +581,8 @@ static void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {
// also draw the connection information, so it doesn't
// flash away too briefly on local or lan games
// refresh to update the time
VM_Call( uivm, 1, UI_REFRESH, cls.realtime );
VM_Call( uivm, 1, UI_DRAW_CONNECT_SCREEN, qtrue );
VM_Call( uivm, UI_REFRESH, cls.realtime );
VM_Call( uivm, UI_DRAW_CONNECT_SCREEN, qtrue );
break;
case CA_ACTIVE:
// always supply STEREO_CENTER as vieworg offset is now done by the engine.
Expand All @@ -597,7 +597,7 @@ static void SCR_DrawScreenField( stereoFrame_t stereoFrame ) {

// the menu draws next
if ( (Key_GetCatcher( ) & KEYCATCH_UI) && uivm ) {
VM_Call( uivm, 1, UI_REFRESH, cls.realtime );
VM_Call( uivm, UI_REFRESH, cls.realtime );
}

// console draws next
Expand Down
33 changes: 21 additions & 12 deletions src/client/cl_ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,15 +1331,24 @@ UI_DllSyscall
*/
static intptr_t QDECL UI_DllSyscall( intptr_t arg, ... ) {
#if !id386 || defined __clang__
intptr_t args[11]; // max.count for UI
intptr_t args[12]; // max.count for UI + VM_CALL_END
va_list ap;
int i;
size_t len = ARRAY_LEN(args);

args[0] = arg;
va_start( ap, arg );
for (i = 1; i < ARRAY_LEN( args ); i++ )
args[ i ] = va_arg( ap, intptr_t );
va_end( ap );
va_start(ap, arg);

for (i = 1; i < len; i++) {
args[i] = va_arg(ap, intptr_t);

if (VM_CALL_END == (int)args[i]) {
args[i] = 0;
break;
}
}

va_end(ap);

return CL_UISystemCalls( args );
#else
Expand All @@ -1359,7 +1368,7 @@ void CL_ShutdownUI( void ) {
if ( !uivm ) {
return;
}
VM_Call( uivm, 0, UI_SHUTDOWN );
VM_Call( uivm, UI_SHUTDOWN );
VM_Free( uivm );
uivm = NULL;
Cmd_UnregisterModule( MODULE_UI );
Expand Down Expand Up @@ -1397,7 +1406,7 @@ void CL_InitUI( void ) {
}

// sanity check
v = VM_Call( uivm, 0, UI_GETAPIVERSION );
v = VM_Call( uivm, UI_GETAPIVERSION );
if ( v != UI_API_VERSION ) {
// Free uivm now, so UI_SHUTDOWN doesn't get called later.
VM_Free( uivm );
Expand All @@ -1409,24 +1418,24 @@ void CL_InitUI( void ) {
else {
// init for this gamestate
if ( currentGameMod == GAMEMOD_LEGACY || currentGameMod == GAMEMOD_ETJUMP )
VM_Call( uivm, 3, UI_INIT, ( cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE ), qtrue, com_legacyVersion->integer );
VM_Call( uivm, UI_INIT, ( cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE ), qtrue, com_legacyVersion->integer );
else
VM_Call( uivm, 1, UI_INIT, ( cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE ) );
VM_Call( uivm, UI_INIT, ( cls.state >= CA_AUTHORIZING && cls.state < CA_ACTIVE ) );
}
}


qboolean UI_usesUniqueCDKey() {
if ( uivm ) {
return ( VM_Call( uivm, 0, UI_HASUNIQUECDKEY ) == qtrue );
return ( VM_Call( uivm, UI_HASUNIQUECDKEY ) == qtrue );
} else {
return qfalse;
}
}

qboolean UI_checkKeyExec( int key ) {
if ( uivm ) {
return VM_Call( uivm, 1, UI_CHECKEXECKEY, key );
return VM_Call( uivm, UI_CHECKEXECKEY, key );
} else {
return qfalse;
}
Expand All @@ -1444,5 +1453,5 @@ qboolean UI_GameCommand( void ) {
return qfalse;
}

return VM_Call( uivm, 1, UI_CONSOLE_COMMAND, cls.realtime );
return VM_Call( uivm, UI_CONSOLE_COMMAND, cls.realtime );
}
Loading

0 comments on commit 191fd55

Please sign in to comment.