mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-03-28 14:56:22 +01:00
Use OneShot version of Steamshim
This commit is contained in:
parent
f859c69b02
commit
8b10b72d2a
6 changed files with 158 additions and 45 deletions
|
@ -7,8 +7,8 @@ if [ -n "$1" ]; then
|
|||
mkdir -p "${MESON_INSTALL_PREFIX}/Contents/libs"
|
||||
cp "$1/libsteam_api.dylib" "${MESON_INSTALL_PREFIX}/Contents/libs"
|
||||
install_name_tool -change "@loader_path/libsteam_api.dylib" "@executable_path/../libs/libsteam_api.dylib" $EXE
|
||||
install_name_tool -add_rpath "@executable_path/../libs" ${EXE}_child
|
||||
macpack ${EXE}_child
|
||||
install_name_tool -add_rpath "@executable_path/../libs" ${EXE}_rt
|
||||
macpack ${EXE}_rt
|
||||
else
|
||||
install_name_tool -add_rpath "@executable_path/../libs" ${EXE}
|
||||
macpack ${EXE}
|
||||
|
|
|
@ -160,10 +160,10 @@ endif
|
|||
|
||||
exe_name = meson.project_name()
|
||||
if steamworks == true
|
||||
exe_name = meson.project_name() + '_child'
|
||||
exe_name = meson.project_name() + '_rt'
|
||||
la = ''
|
||||
if build_static == true
|
||||
la = '-static-libgcc -static-libstdc++'
|
||||
la = '-static'
|
||||
endif
|
||||
shim_args = ['-DGAME_LAUNCH_NAME="' + exe_name + '"']
|
||||
if get_option('steam_appid') != ''
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
This is a modified version of Steamshim used in [OneShot](https://github.com/elizagamedev/mkxp-oneshot)
|
||||
which should be compatible with Windows, further modified (not by much, at the moment) for mkxp-z.
|
||||
|
||||
|
||||
## Original Steamshim README:
|
||||
|
||||
```
|
||||
What is this?
|
||||
|
||||
- This is a small piece of code, written in C++, that acts as a bridge between
|
||||
|
@ -62,5 +69,4 @@ Questions? Ask me.
|
|||
|
||||
--ryan.
|
||||
icculus@icculus.org
|
||||
|
||||
|
||||
```
|
|
@ -9,7 +9,6 @@ typedef __int32 int32;
|
|||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
@ -22,14 +21,16 @@ typedef uint64_t uint64;
|
|||
typedef int PipeType;
|
||||
#define NULLPIPE -1
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "steamshim_child.h"
|
||||
|
||||
#define DEBUGPIPE 1
|
||||
#if DEBUGPIPE
|
||||
#ifdef STEAMSHIM_DEBUG
|
||||
#define dbgpipe printf
|
||||
#else
|
||||
static inline void dbgpipe(const char *fmt, ...) {}
|
||||
static inline void dbgpipe(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int writePipe(PipeType fd, const void *buf, const unsigned int _len);
|
||||
|
@ -66,12 +67,11 @@ static void closePipe(PipeType fd)
|
|||
CloseHandle(fd);
|
||||
} /* closePipe */
|
||||
|
||||
static char *getEnvVar(const char *key, char *buf, const size_t _buflen)
|
||||
static char *getEnvVar(const char *key, char *buf, const size_t buflen)
|
||||
{
|
||||
const DWORD buflen = (DWORD) _buflen;
|
||||
const DWORD rc = GetEnvironmentVariableA(key, val, buflen);
|
||||
const DWORD rc = GetEnvironmentVariableA(key, buf, buflen);
|
||||
/* rc doesn't count null char, hence "<". */
|
||||
return ((rc > 0) && (rc < buflen)) ? NULL : buf;
|
||||
return ((rc > 0) && (rc < buflen)) ? buf : NULL;
|
||||
} /* getEnvVar */
|
||||
|
||||
#else
|
||||
|
@ -133,6 +133,8 @@ typedef enum ShimCmd
|
|||
SHIMCMD_GETSTATI,
|
||||
SHIMCMD_SETSTATF,
|
||||
SHIMCMD_GETSTATF,
|
||||
SHIMCMD_GETPERSONANAME,
|
||||
SHIMCMD_GETCURRENTGAMELANGUAGE,
|
||||
} ShimCmd;
|
||||
|
||||
static int write1ByteCmd(const uint8 b1)
|
||||
|
@ -156,22 +158,15 @@ static inline int writeBye(void)
|
|||
static int initPipes(void)
|
||||
{
|
||||
char buf[64];
|
||||
unsigned long long val;
|
||||
|
||||
if (!getEnvVar("STEAMSHIM_READHANDLE", buf, sizeof (buf)))
|
||||
return 0;
|
||||
else if (sscanf(buf, "%llu", &val) != 1)
|
||||
return 0;
|
||||
else
|
||||
GPipeRead = (PipeType) val;
|
||||
GPipeRead = (PipeType) strtoull(buf, 0, 10);
|
||||
|
||||
if (!getEnvVar("STEAMSHIM_WRITEHANDLE", buf, sizeof (buf)))
|
||||
return 0;
|
||||
else if (sscanf(buf, "%llu", &val) != 1)
|
||||
return 0;
|
||||
else
|
||||
GPipeWrite = (PipeType) val;
|
||||
|
||||
GPipeWrite = (PipeType) strtoull(buf, 0, 10);
|
||||
|
||||
return ((GPipeRead != NULLPIPE) && (GPipeWrite != NULLPIPE));
|
||||
} /* initPipes */
|
||||
|
||||
|
@ -185,7 +180,9 @@ int STEAMSHIM_init(void)
|
|||
return 0;
|
||||
} /* if */
|
||||
|
||||
#ifndef _WIN32
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
dbgpipe("Child init success!\n");
|
||||
return 1;
|
||||
|
@ -205,7 +202,9 @@ void STEAMSHIM_deinit(void)
|
|||
|
||||
GPipeRead = GPipeWrite = NULLPIPE;
|
||||
|
||||
#ifndef _WIN32
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
#endif
|
||||
} /* STEAMSHIM_deinit */
|
||||
|
||||
static inline int isAlive(void)
|
||||
|
@ -233,7 +232,7 @@ static const STEAMSHIM_Event *processEvent(const uint8 *buf, size_t buflen)
|
|||
event.type = type;
|
||||
event.okay = 1;
|
||||
|
||||
#if DEBUGPIPE
|
||||
#ifdef STEAMSHIM_DEBUG
|
||||
if (0) {}
|
||||
#define PRINTGOTEVENT(x) else if (type == x) printf("Child got " #x ".\n")
|
||||
PRINTGOTEVENT(SHIMEVENT_BYE);
|
||||
|
@ -246,6 +245,8 @@ static const STEAMSHIM_Event *processEvent(const uint8 *buf, size_t buflen)
|
|||
PRINTGOTEVENT(SHIMEVENT_GETSTATI);
|
||||
PRINTGOTEVENT(SHIMEVENT_SETSTATF);
|
||||
PRINTGOTEVENT(SHIMEVENT_GETSTATF);
|
||||
PRINTGOTEVENT(SHIMEVENT_GETPERSONANAME);
|
||||
PRINTGOTEVENT(SHIMEVENT_GETCURRENTGAMELANGUAGE);
|
||||
#undef PRINTGOTEVENT
|
||||
else printf("Child got unknown shimevent %d.\n", (int) type);
|
||||
#endif
|
||||
|
@ -300,6 +301,11 @@ static const STEAMSHIM_Event *processEvent(const uint8 *buf, size_t buflen)
|
|||
strcpy(event.name, (const char *) buf);
|
||||
break;
|
||||
|
||||
case SHIMEVENT_GETPERSONANAME:
|
||||
case SHIMEVENT_GETCURRENTGAMELANGUAGE:
|
||||
strcpy(event.name, (const char *) buf);
|
||||
break;
|
||||
|
||||
default: /* uh oh */
|
||||
return NULL;
|
||||
} /* switch */
|
||||
|
@ -440,5 +446,18 @@ void STEAMSHIM_getStatF(const char *name)
|
|||
writeStatThing(SHIMCMD_GETSTATF, name, NULL, 0);
|
||||
} /* STEAMSHIM_getStatF */
|
||||
|
||||
/* end of steamshim_child.c ... */
|
||||
void STEAMSHIM_getPersonaName()
|
||||
{
|
||||
if (isDead()) return;
|
||||
dbgpipe("Child sending SHIMCMD_GETPERSONANAME().\n");
|
||||
write1ByteCmd(SHIMCMD_GETPERSONANAME);
|
||||
} /* STEAMSHIM_getPersonaName */
|
||||
|
||||
void STEAMSHIM_getCurrentGameLanguage()
|
||||
{
|
||||
if (isDead()) return;
|
||||
dbgpipe("Child sending SHIMCMD_GETCURRENTGAMELANGUAGE().\n");
|
||||
write1ByteCmd(SHIMCMD_GETCURRENTGAMELANGUAGE);
|
||||
} /* STEAMSHIM_getCurrentGameLanguage */
|
||||
|
||||
/* end of steamshim_child.c ... */
|
||||
|
|
|
@ -17,6 +17,8 @@ typedef enum STEAMSHIM_EventType
|
|||
SHIMEVENT_GETSTATI,
|
||||
SHIMEVENT_SETSTATF,
|
||||
SHIMEVENT_GETSTATF,
|
||||
SHIMEVENT_GETPERSONANAME,
|
||||
SHIMEVENT_GETCURRENTGAMELANGUAGE,
|
||||
} STEAMSHIM_EventType;
|
||||
|
||||
/* not all of these fields make sense in a given event. */
|
||||
|
@ -43,6 +45,8 @@ void STEAMSHIM_setStatI(const char *name, const int _val);
|
|||
void STEAMSHIM_getStatI(const char *name);
|
||||
void STEAMSHIM_setStatF(const char *name, const float val);
|
||||
void STEAMSHIM_getStatF(const char *name);
|
||||
void STEAMSHIM_getPersonaName();
|
||||
void STEAMSHIM_getCurrentGameLanguage();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -51,4 +55,3 @@ void STEAMSHIM_getStatF(const char *name);
|
|||
#endif /* include-once blocker */
|
||||
|
||||
/* end of steamshim_child.h ... */
|
||||
|
||||
|
|
|
@ -1,34 +1,38 @@
|
|||
//#define GAME_LAUNCH_NAME "testapp"
|
||||
#ifndef GAME_LAUNCH_NAME
|
||||
#error Please define your game exe name.
|
||||
#define GAME_LAUNCH_NAME "oneshot"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#define UNICODE
|
||||
#include <windows.h>
|
||||
typedef PROCESS_INFORMATION ProcessType;
|
||||
typedef HANDLE PipeType;
|
||||
#define NULLPIPE NULL
|
||||
#define LLUFMT "%I64u"
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
typedef pid_t ProcessType;
|
||||
typedef int PipeType;
|
||||
#define NULLPIPE -1
|
||||
#define LLUFMT "%llu"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "steam/steam_api.h"
|
||||
|
||||
#define DEBUGPIPE 1
|
||||
#if DEBUGPIPE
|
||||
#ifdef STEAMSHIM_DEBUG
|
||||
#define dbgpipe printf
|
||||
#else
|
||||
static inline void dbgpipe(const char *fmt, ...) {}
|
||||
static inline void dbgpipe(const char *fmt, ...) {
|
||||
(void)fmt;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* platform-specific mainline calls this. */
|
||||
|
@ -100,11 +104,57 @@ static bool setEnvVar(const char *key, const char *val)
|
|||
return (SetEnvironmentVariableA(key, val) != 0);
|
||||
} // setEnvVar
|
||||
|
||||
static bool launchChild(ProcessType *pid);
|
||||
static LPWSTR genCommandLine()
|
||||
{
|
||||
return (CreateProcessW(TEXT(".\\") TEXT(GAME_LAUNCH_NAME) TEXT(".exe"),
|
||||
GetCommandLineW(), NULL, NULL, TRUE, 0, NULL,
|
||||
NULL, NULL, pid) != 0);
|
||||
// Construct a command line with the appropriate filename
|
||||
LPWSTR cmdline = GetCommandLineW();
|
||||
|
||||
// Find the index of the first argument after 0
|
||||
int iFirstArg = -1;
|
||||
bool quote = false;
|
||||
bool whitespace = false;
|
||||
for (int i = 0; cmdline[i]; ++i)
|
||||
{
|
||||
if (cmdline[i] == '"' && (i == 0 || cmdline[i-1] != '\\'))
|
||||
{
|
||||
quote = !quote;
|
||||
whitespace = false;
|
||||
}
|
||||
else if (!quote && (cmdline[i] == ' ' || cmdline[i] == '\t'))
|
||||
{
|
||||
whitespace = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (whitespace)
|
||||
{
|
||||
iFirstArg = i;
|
||||
break;
|
||||
}
|
||||
whitespace = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If it doesn't exist, that must mean there are no arguments,
|
||||
// so just return GAME_LAUNCH_NAME
|
||||
if (iFirstArg == -1)
|
||||
return _wcsdup(TEXT("\".\\" GAME_LAUNCH_NAME ".exe\""));
|
||||
|
||||
// Create the new string
|
||||
// (`".\.exe" ` == +9
|
||||
LPWSTR newcmdline = (LPWSTR)malloc(sizeof(TEXT(GAME_LAUNCH_NAME))
|
||||
+ sizeof(WCHAR) * (wcslen(cmdline) - iFirstArg + 9));
|
||||
wsprintf(newcmdline, TEXT("\".\\" GAME_LAUNCH_NAME ".exe\" %s"), cmdline + iFirstArg);
|
||||
return newcmdline;
|
||||
}
|
||||
|
||||
static bool launchChild(ProcessType *pid)
|
||||
{
|
||||
STARTUPINFOW si;
|
||||
memset(&si, 0, sizeof(si));
|
||||
return CreateProcessW(TEXT(".\\" GAME_LAUNCH_NAME ".exe"),
|
||||
genCommandLine(), NULL, NULL, TRUE, 0, NULL,
|
||||
NULL, &si, pid);
|
||||
} // launchChild
|
||||
|
||||
static int closeProcess(ProcessType *pid)
|
||||
|
@ -154,6 +204,8 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
|
|||
int fds[2];
|
||||
if (pipe(fds) == -1)
|
||||
return 0;
|
||||
fcntl(fds[0], F_SETFL, 0);
|
||||
fcntl(fds[1], F_SETFL, 0);
|
||||
*pPipeParentRead = fds[0];
|
||||
*pPipeChildWrite = fds[1];
|
||||
|
||||
|
@ -164,6 +216,8 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
|
|||
return 0;
|
||||
} // if
|
||||
|
||||
fcntl(fds[0], F_SETFL, 0);
|
||||
fcntl(fds[1], F_SETFL, 0);
|
||||
*pPipeChildRead = fds[0];
|
||||
*pPipeParentWrite = fds[1];
|
||||
|
||||
|
@ -192,11 +246,15 @@ static bool launchChild(ProcessType *pid)
|
|||
return true; // we'll let the pipe fail if this didn't work.
|
||||
|
||||
// we're the child.
|
||||
char buf[350] = {0};
|
||||
#ifdef __APPLE__
|
||||
char buf[300];
|
||||
strncpy(buf, GArgv[0], sizeof(buf));
|
||||
strcat(buf, "_child");
|
||||
strcat(buf, "_rt");
|
||||
GArgv[0] = buf;
|
||||
//GArgv[0] = strdup("./" GAME_LAUNCH_NAME);
|
||||
#else
|
||||
GArgv[0] = strdup("./" GAME_LAUNCH_NAME);
|
||||
#endif
|
||||
dbgpipe("Starting %s\n", GArgv[0]);
|
||||
execvp(GArgv[0], GArgv);
|
||||
// still here? It failed! Terminate, closing child's ends of the pipes.
|
||||
_exit(1);
|
||||
|
@ -229,6 +287,8 @@ class SteamBridge;
|
|||
static ISteamUserStats *GSteamStats = NULL;
|
||||
static ISteamUtils *GSteamUtils = NULL;
|
||||
static ISteamUser *GSteamUser = NULL;
|
||||
static ISteamFriends *GSteamFriends = NULL;
|
||||
static ISteamApps *GSteamApps = NULL;
|
||||
static AppId_t GAppID = 0;
|
||||
static uint64 GUserID = 0;
|
||||
static SteamBridge *GSteamBridge = NULL;
|
||||
|
@ -257,6 +317,8 @@ typedef enum ShimCmd
|
|||
SHIMCMD_GETSTATI,
|
||||
SHIMCMD_SETSTATF,
|
||||
SHIMCMD_GETSTATF,
|
||||
SHIMCMD_GETPERSONANAME,
|
||||
SHIMCMD_GETCURRENTGAMELANGUAGE,
|
||||
} ShimCmd;
|
||||
|
||||
typedef enum ShimEvent
|
||||
|
@ -271,6 +333,8 @@ typedef enum ShimEvent
|
|||
SHIMEVENT_GETSTATI,
|
||||
SHIMEVENT_SETSTATF,
|
||||
SHIMEVENT_GETSTATF,
|
||||
SHIMEVENT_GETPERSONANAME,
|
||||
SHIMEVENT_GETCURRENTGAMELANGUAGE,
|
||||
} ShimEvent;
|
||||
|
||||
static bool write1ByteCmd(PipeType fd, const uint8 b1)
|
||||
|
@ -291,6 +355,14 @@ static bool write3ByteCmd(PipeType fd, const uint8 b1, const uint8 b2, const uin
|
|||
return writePipe(fd, buf, sizeof (buf));
|
||||
} // write3ByteCmd
|
||||
|
||||
static bool writeString(PipeType fd, ShimEvent event, const char *str)
|
||||
{
|
||||
uint8 buf[256];
|
||||
buf[0] = strlen(str) + 2;
|
||||
buf[1] = (uint8) event;
|
||||
strcpy((char *) buf + 2, str);
|
||||
return writePipe(fd, buf, buf[0] + 1);
|
||||
} // writeString
|
||||
|
||||
static inline bool writeBye(PipeType fd)
|
||||
{
|
||||
|
@ -328,7 +400,7 @@ static bool writeAchievementGet(PipeType fd, const char *name, const int status,
|
|||
{
|
||||
uint8 buf[256];
|
||||
uint8 *ptr = buf+1;
|
||||
dbgpipe("Parent sending SHIMEVENT_GETACHIEVEMENT('%s', status %d, time %llu).\n", name, status, (unsigned long long) time);
|
||||
dbgpipe("Parent sending SHIMEVENT_GETACHIEVEMENT('%s', status %d, time " LLUFMT ").\n", name, status, (unsigned long long) time);
|
||||
*(ptr++) = (uint8) SHIMEVENT_GETACHIEVEMENT;
|
||||
*(ptr++) = (uint8) status;
|
||||
memcpy(ptr, &time, sizeof (time));
|
||||
|
@ -414,7 +486,7 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
|
|||
const ShimCmd cmd = (ShimCmd) *(buf++);
|
||||
buflen--;
|
||||
|
||||
#if DEBUGPIPE
|
||||
#if STEAMSHIM_DEBUG
|
||||
if (false) {}
|
||||
#define PRINTGOTCMD(x) else if (cmd == x) printf("Parent got " #x ".\n")
|
||||
PRINTGOTCMD(SHIMCMD_BYE);
|
||||
|
@ -428,6 +500,8 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
|
|||
PRINTGOTCMD(SHIMCMD_GETSTATI);
|
||||
PRINTGOTCMD(SHIMCMD_SETSTATF);
|
||||
PRINTGOTCMD(SHIMCMD_GETSTATF);
|
||||
PRINTGOTCMD(SHIMCMD_GETPERSONANAME);
|
||||
PRINTGOTCMD(SHIMCMD_GETCURRENTGAMELANGUAGE);
|
||||
#undef PRINTGOTCMD
|
||||
else printf("Parent got unknown shimcmd %d.\n", (int) cmd);
|
||||
#endif
|
||||
|
@ -534,6 +608,16 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
|
|||
writeGetStatF(fd, name, 0.0f, false);
|
||||
} // if
|
||||
break;
|
||||
|
||||
case SHIMCMD_GETPERSONANAME:
|
||||
dbgpipe("Parent sending SHIMEVENT_GETPERSONANAME.\n");
|
||||
writeString(fd, SHIMEVENT_GETPERSONANAME, GSteamFriends->GetPersonaName());
|
||||
break;
|
||||
|
||||
case SHIMCMD_GETCURRENTGAMELANGUAGE:
|
||||
dbgpipe("Parent sending SHIMEVENT_GETCURRENTGAMELANGUAGE.\n");
|
||||
writeString(fd, SHIMEVENT_GETCURRENTGAMELANGUAGE, GSteamApps->GetCurrentGameLanguage());
|
||||
break;
|
||||
} // switch
|
||||
|
||||
return true; // keep going.
|
||||
|
@ -580,11 +664,11 @@ static void processCommands(PipeType pipeParentRead, PipeType pipeParentWrite)
|
|||
static bool setEnvironmentVars(PipeType pipeChildRead, PipeType pipeChildWrite)
|
||||
{
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof (buf), "%llu", (unsigned long long) pipeChildRead);
|
||||
snprintf(buf, sizeof (buf), LLUFMT, (unsigned long long) pipeChildRead);
|
||||
if (!setEnvVar("STEAMSHIM_READHANDLE", buf))
|
||||
return false;
|
||||
|
||||
snprintf(buf, sizeof (buf), "%llu", (unsigned long long) pipeChildWrite);
|
||||
snprintf(buf, sizeof (buf), LLUFMT, (unsigned long long) pipeChildWrite);
|
||||
if (!setEnvVar("STEAMSHIM_WRITEHANDLE", buf))
|
||||
return false;
|
||||
|
||||
|
@ -607,6 +691,8 @@ static bool initSteamworks(PipeType fd)
|
|||
GSteamStats = SteamUserStats();
|
||||
GSteamUtils = SteamUtils();
|
||||
GSteamUser = SteamUser();
|
||||
GSteamFriends = SteamFriends();
|
||||
GSteamApps = SteamApps();
|
||||
|
||||
GAppID = GSteamUtils ? GSteamUtils->GetAppID() : 0;
|
||||
GUserID = GSteamUser ? GSteamUser->GetSteamID().ConvertToUint64() : 0;
|
||||
|
@ -675,4 +761,3 @@ static int mainline(void)
|
|||
} // mainline
|
||||
|
||||
// end of steamshim_parent.cpp ...
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue