un-screw steamshim on Windows again

This commit is contained in:
Zorua 2022-09-24 03:00:21 -04:00
parent 6007c45c8a
commit 748aff99cc

View file

@ -1,469 +1,456 @@
#ifdef _WIN32 #ifdef _WIN32
#define WIN32_LEAN_AND_MEAN 1 #define WIN32_LEAN_AND_MEAN 1
#include <windows.h> #include <windows.h>
#include <process.h> #include <stdio.h>
#include <io.h> #include <process.h>
#include <errno.h> typedef HANDLE PipeType;
typedef int PipeType; #define NULLPIPE NULL
#define NULLPIPE 0 typedef unsigned __int8 uint8;
typedef unsigned __int8 uint8; typedef __int32 int32;
typedef __int32 int32; typedef unsigned __int64 uint64;
typedef unsigned __int64 uint64; #else
#else #include <stdio.h>
#include <stdio.h> #include <string.h>
#include <string.h> #include <stdint.h>
#include <stdint.h> #include <unistd.h>
#include <unistd.h> #include <errno.h>
#include <errno.h> #include <poll.h>
#include <poll.h> #include <signal.h>
#include <signal.h> typedef uint8_t uint8;
typedef uint8_t uint8; typedef int32_t int32;
typedef int32_t int32; typedef uint64_t uint64;
typedef uint64_t uint64; typedef int PipeType;
typedef int PipeType; #define NULLPIPE -1
#define NULLPIPE -1 #endif
#endif #include <stdlib.h>
#include <stdlib.h>
#include "steamshim_child.h"
#include "steamshim_child.h"
#ifdef STEAMSHIM_DEBUG
#ifdef STEAMSHIM_DEBUG #define dbgpipe printf
#define dbgpipe printf #else
#else static inline void dbgpipe(const char *fmt, ...) {
static inline void dbgpipe(const char *fmt, ...) { (void)fmt;
(void)fmt; }
} #endif
#endif
static int writePipe(PipeType fd, const void *buf, const unsigned int _len);
static int writePipe(PipeType fd, const void *buf, const unsigned int _len); static int readPipe(PipeType fd, void *buf, const unsigned int _len);
static int readPipe(PipeType fd, void *buf, const unsigned int _len); static void closePipe(PipeType fd);
static void closePipe(PipeType fd); static char *getEnvVar(const char *key, char *buf, const size_t buflen);
static char *getEnvVar(const char *key, char *buf, const size_t buflen); static int pipeReady(PipeType fd);
static int pipeReady(PipeType fd);
#ifdef _WIN32
#ifdef _WIN32
static int pipeReady(PipeType fd)
static int pipeReady(PipeType fd) {
{ DWORD avail = 0;
return 1; return (PeekNamedPipe(fd, NULL, 0, NULL, &avail, NULL) && (avail > 0));
DWORD avail = 0; } /* pipeReady */
return (PeekNamedPipe(fd, NULL, 0, NULL, &avail, NULL) && (avail > 0));
} /* pipeReady */ static int writePipe(PipeType fd, const void *buf, const unsigned int _len) {
const DWORD len = (DWORD)_len;
static int writePipe(PipeType fd, const void *buf, const unsigned int _len) DWORD bw = 0;
{ return ((WriteFile(fd, buf, len, &bw, NULL) != 0) && (bw == len));
const ssize_t len = (ssize_t) _len; } // writePipe
ssize_t bw;
while (((bw = _write(fd, buf, len)) == -1) && (errno == EINTR)) { /*spin*/ } static int readPipe(PipeType fd, void *buf, const unsigned int _len) {
return (bw == len); const DWORD len = (DWORD)_len;
} /* writePipe */ DWORD br = 0;
return ReadFile(fd, buf, len, &br, NULL) ? (int)br : -1;
static int readPipe(PipeType fd, void *buf, const unsigned int _len) } // readPipe
{
const ssize_t len = (ssize_t) _len; static void closePipe(PipeType fd)
ssize_t br; {
while (((br = _read(fd, buf, len)) == 0)) { /*spin*/ } CloseHandle(fd);
return (int) br; } /* closePipe */
} /* readPipe */
static char *getEnvVar(const char *key, char *buf, const size_t buflen)
static void closePipe(PipeType fd) {
{ const DWORD rc = GetEnvironmentVariableA(key, buf, buflen);
_close(fd); /* rc doesn't count null char, hence "<". */
} /* closePipe */ return ((rc > 0) && (rc < buflen)) ? buf : NULL;
} /* getEnvVar */
static char *getEnvVar(const char *key, char *buf, const size_t buflen)
{ #else
const DWORD rc = GetEnvironmentVariableA(key, buf, buflen);
/* rc doesn't count null char, hence "<". */ static int pipeReady(PipeType fd)
return ((rc > 0) && (rc < buflen)) ? buf : NULL; {
} /* getEnvVar */ int rc;
struct pollfd pfd = { fd, POLLIN | POLLERR | POLLHUP, 0 };
#else while (((rc = poll(&pfd, 1, 0)) == -1) && (errno == EINTR)) { /*spin*/ }
return (rc == 1);
static int pipeReady(PipeType fd) } /* pipeReady */
{
int rc; static int writePipe(PipeType fd, const void *buf, const unsigned int _len)
struct pollfd pfd = { fd, POLLIN | POLLERR | POLLHUP, 0 }; {
while (((rc = poll(&pfd, 1, 0)) == -1) && (errno == EINTR)) { /*spin*/ } const ssize_t len = (ssize_t) _len;
return (rc == 1); ssize_t bw;
} /* pipeReady */ while (((bw = write(fd, buf, len)) == -1) && (errno == EINTR)) { /*spin*/ }
return (bw == len);
static int writePipe(PipeType fd, const void *buf, const unsigned int _len) } /* writePipe */
{
const ssize_t len = (ssize_t) _len; static int readPipe(PipeType fd, void *buf, const unsigned int _len)
ssize_t bw; {
while (((bw = write(fd, buf, len)) == -1) && (errno == EINTR)) { /*spin*/ } const ssize_t len = (ssize_t) _len;
return (bw == len); ssize_t br;
} /* writePipe */ while (((br = read(fd, buf, len)) == -1) && (errno == EINTR)) { /*spin*/ }
return (int) br;
static int readPipe(PipeType fd, void *buf, const unsigned int _len) } /* readPipe */
{
const ssize_t len = (ssize_t) _len; static void closePipe(PipeType fd)
ssize_t br; {
while (((br = read(fd, buf, len)) == -1) && (errno == EINTR)) { /*spin*/ } close(fd);
return (int) br; } /* closePipe */
} /* readPipe */
static char *getEnvVar(const char *key, char *buf, const size_t buflen)
static void closePipe(PipeType fd) {
{ const char *envr = getenv(key);
close(fd); if (!envr || (strlen(envr) >= buflen))
} /* closePipe */ return NULL;
strcpy(buf, envr);
static char *getEnvVar(const char *key, char *buf, const size_t buflen) return buf;
{ } /* getEnvVar */
const char *envr = getenv(key);
if (!envr || (strlen(envr) >= buflen)) #endif
return NULL;
strcpy(buf, envr);
return buf; static PipeType GPipeRead = NULLPIPE;
} /* getEnvVar */ static PipeType GPipeWrite = NULLPIPE;
#endif typedef enum ShimCmd
{
SHIMCMD_BYE,
static PipeType GPipeRead = NULLPIPE; SHIMCMD_PUMP,
static PipeType GPipeWrite = NULLPIPE; SHIMCMD_REQUESTSTATS,
SHIMCMD_STORESTATS,
typedef enum ShimCmd SHIMCMD_SETACHIEVEMENT,
{ SHIMCMD_GETACHIEVEMENT,
SHIMCMD_BYE, SHIMCMD_RESETSTATS,
SHIMCMD_PUMP, SHIMCMD_SETSTATI,
SHIMCMD_REQUESTSTATS, SHIMCMD_GETSTATI,
SHIMCMD_STORESTATS, SHIMCMD_SETSTATF,
SHIMCMD_SETACHIEVEMENT, SHIMCMD_GETSTATF,
SHIMCMD_GETACHIEVEMENT, SHIMCMD_GETPERSONANAME,
SHIMCMD_RESETSTATS, SHIMCMD_GETCURRENTGAMELANGUAGE,
SHIMCMD_SETSTATI, } ShimCmd;
SHIMCMD_GETSTATI,
SHIMCMD_SETSTATF, static int write1ByteCmd(const uint8 b1)
SHIMCMD_GETSTATF, {
SHIMCMD_GETPERSONANAME, const uint8 buf[] = { 1, b1 };
SHIMCMD_GETCURRENTGAMELANGUAGE, return writePipe(GPipeWrite, buf, sizeof (buf));
} ShimCmd; } /* write1ByteCmd */
static int write1ByteCmd(const uint8 b1) static int write2ByteCmd(const uint8 b1, const uint8 b2)
{ {
const uint8 buf[] = { 1, b1 }; const uint8 buf[] = { 2, b1, b2 };
return writePipe(GPipeWrite, buf, sizeof (buf)); return writePipe(GPipeWrite, buf, sizeof (buf));
} /* write1ByteCmd */ } /* write2ByteCmd */
static int write2ByteCmd(const uint8 b1, const uint8 b2) static inline int writeBye(void)
{ {
const uint8 buf[] = { 2, b1, b2 }; dbgpipe("Child sending SHIMCMD_BYE().\n");
return writePipe(GPipeWrite, buf, sizeof (buf)); return write1ByteCmd(SHIMCMD_BYE);
} /* write2ByteCmd */ } // writeBye
static inline int writeBye(void) static int initPipes(void)
{ {
dbgpipe("Child sending SHIMCMD_BYE().\n"); char buf[64];
return write1ByteCmd(SHIMCMD_BYE);
} // writeBye if (!getEnvVar("STEAMSHIM_READHANDLE", buf, sizeof (buf)))
return 0;
static int initPipes(void) GPipeRead = (PipeType) strtoull(buf, 0, 10);
{
char buf[64]; if (!getEnvVar("STEAMSHIM_WRITEHANDLE", buf, sizeof (buf)))
return 0;
if (!getEnvVar("STEAMSHIM_READHANDLE", buf, sizeof (buf))) GPipeWrite = (PipeType) strtoull(buf, 0, 10);
return 0;
GPipeRead = (PipeType) strtoull(buf, 0, 10); return ((GPipeRead != NULLPIPE) && (GPipeWrite != NULLPIPE));
} /* initPipes */
if (!getEnvVar("STEAMSHIM_WRITEHANDLE", buf, sizeof (buf)))
return 0;
GPipeWrite = (PipeType) strtoull(buf, 0, 10); int STEAMSHIM_init(void)
{
return ((GPipeRead != NULLPIPE) && (GPipeWrite != NULLPIPE)); dbgpipe("Child init start.\n");
} /* initPipes */ if (!initPipes())
{
dbgpipe("Child init failed.\n");
int STEAMSHIM_init(void) return 0;
{ } /* if */
dbgpipe("Child init start.\n");
if (!initPipes()) #ifndef _WIN32
{ signal(SIGPIPE, SIG_IGN);
dbgpipe("Child init failed.\n"); #endif
return 0;
} /* if */ dbgpipe("Child init success!\n");
return 1;
#ifndef _WIN32 } /* STEAMSHIM_init */
signal(SIGPIPE, SIG_IGN);
#endif void STEAMSHIM_deinit(void)
{
dbgpipe("Child init success!\n"); dbgpipe("Child deinit.\n");
return 1; if (GPipeWrite != NULLPIPE)
} /* STEAMSHIM_init */ {
writeBye();
void STEAMSHIM_deinit(void) closePipe(GPipeWrite);
{ } /* if */
dbgpipe("Child deinit.\n");
if (GPipeWrite != NULLPIPE) if (GPipeRead != NULLPIPE)
{ closePipe(GPipeRead);
writeBye();
closePipe(GPipeWrite); GPipeRead = GPipeWrite = NULLPIPE;
} /* if */
#ifndef _WIN32
if (GPipeRead != NULLPIPE) signal(SIGPIPE, SIG_DFL);
closePipe(GPipeRead); #endif
} /* STEAMSHIM_deinit */
GPipeRead = GPipeWrite = NULLPIPE;
static inline int isAlive(void)
#ifndef _WIN32 {
signal(SIGPIPE, SIG_DFL); return ((GPipeRead != NULLPIPE) && (GPipeWrite != NULLPIPE));
#endif } /* isAlive */
} /* STEAMSHIM_deinit */
static inline int isDead(void)
static inline int isAlive(void) {
{ return !isAlive();
return ((GPipeRead != NULLPIPE) && (GPipeWrite != NULLPIPE)); } /* isDead */
} /* isAlive */
int STEAMSHIM_alive(void)
static inline int isDead(void) {
{ return isAlive();
return !isAlive(); } /* STEAMSHIM_alive */
} /* isDead */
static const STEAMSHIM_Event *processEvent(const uint8 *buf, size_t buflen)
int STEAMSHIM_alive(void) {
{ static STEAMSHIM_Event event;
return isAlive(); const STEAMSHIM_EventType type = (STEAMSHIM_EventType) *(buf++);
} /* STEAMSHIM_alive */ buflen--;
static const STEAMSHIM_Event *processEvent(const uint8 *buf, size_t buflen) memset(&event, '\0', sizeof (event));
{ event.type = type;
static STEAMSHIM_Event event; event.okay = 1;
const STEAMSHIM_EventType type = (STEAMSHIM_EventType) *(buf++);
buflen--; #ifdef STEAMSHIM_DEBUG
if (0) {}
memset(&event, '\0', sizeof (event)); #define PRINTGOTEVENT(x) else if (type == x) printf("Child got " #x ".\n")
event.type = type; PRINTGOTEVENT(SHIMEVENT_BYE);
event.okay = 1; PRINTGOTEVENT(SHIMEVENT_STATSRECEIVED);
PRINTGOTEVENT(SHIMEVENT_STATSSTORED);
#ifdef STEAMSHIM_DEBUG PRINTGOTEVENT(SHIMEVENT_SETACHIEVEMENT);
if (0) {} PRINTGOTEVENT(SHIMEVENT_GETACHIEVEMENT);
#define PRINTGOTEVENT(x) else if (type == x) printf("Child got " #x ".\n") PRINTGOTEVENT(SHIMEVENT_RESETSTATS);
PRINTGOTEVENT(SHIMEVENT_BYE); PRINTGOTEVENT(SHIMEVENT_SETSTATI);
PRINTGOTEVENT(SHIMEVENT_STATSRECEIVED); PRINTGOTEVENT(SHIMEVENT_GETSTATI);
PRINTGOTEVENT(SHIMEVENT_STATSSTORED); PRINTGOTEVENT(SHIMEVENT_SETSTATF);
PRINTGOTEVENT(SHIMEVENT_SETACHIEVEMENT); PRINTGOTEVENT(SHIMEVENT_GETSTATF);
PRINTGOTEVENT(SHIMEVENT_GETACHIEVEMENT); PRINTGOTEVENT(SHIMEVENT_GETPERSONANAME);
PRINTGOTEVENT(SHIMEVENT_RESETSTATS); PRINTGOTEVENT(SHIMEVENT_GETCURRENTGAMELANGUAGE);
PRINTGOTEVENT(SHIMEVENT_SETSTATI); #undef PRINTGOTEVENT
PRINTGOTEVENT(SHIMEVENT_GETSTATI); else printf("Child got unknown shimevent %d.\n", (int) type);
PRINTGOTEVENT(SHIMEVENT_SETSTATF); #endif
PRINTGOTEVENT(SHIMEVENT_GETSTATF);
PRINTGOTEVENT(SHIMEVENT_GETPERSONANAME); switch (type)
PRINTGOTEVENT(SHIMEVENT_GETCURRENTGAMELANGUAGE); {
#undef PRINTGOTEVENT case SHIMEVENT_BYE:
else printf("Child got unknown shimevent %d.\n", (int) type); break;
#endif
case SHIMEVENT_STATSRECEIVED:
switch (type) case SHIMEVENT_STATSSTORED:
{ if (!buflen) return NULL;
case SHIMEVENT_BYE: event.okay = *(buf++) ? 1 : 0;
break; break;
case SHIMEVENT_STATSRECEIVED: case SHIMEVENT_SETACHIEVEMENT:
case SHIMEVENT_STATSSTORED: if (buflen < 3) return NULL;
if (!buflen) return NULL; event.ivalue = *(buf++) ? 1 : 0;
event.okay = *(buf++) ? 1 : 0; event.okay = *(buf++) ? 1 : 0;
break; strcpy(event.name, (const char *) buf);
break;
case SHIMEVENT_SETACHIEVEMENT:
if (buflen < 3) return NULL; case SHIMEVENT_GETACHIEVEMENT:
event.ivalue = *(buf++) ? 1 : 0; if (buflen < 10) return NULL;
event.okay = *(buf++) ? 1 : 0; event.ivalue = (int) *(buf++);
strcpy(event.name, (const char *) buf); if (event.ivalue == 2)
break; event.ivalue = event.okay = 0;
event.epochsecs = (long long unsigned) *((uint64 *) buf);
case SHIMEVENT_GETACHIEVEMENT: buf += sizeof (uint64);
if (buflen < 10) return NULL; strcpy(event.name, (const char *) buf);
event.ivalue = (int) *(buf++); break;
if (event.ivalue == 2)
event.ivalue = event.okay = 0; case SHIMEVENT_RESETSTATS:
event.epochsecs = (long long unsigned) *((uint64 *) buf); if (buflen != 2) return NULL;
buf += sizeof (uint64); event.ivalue = *(buf++) ? 1 : 0;
strcpy(event.name, (const char *) buf); event.okay = *(buf++) ? 1 : 0;
break; break;
case SHIMEVENT_RESETSTATS: case SHIMEVENT_SETSTATI:
if (buflen != 2) return NULL; case SHIMEVENT_GETSTATI:
event.ivalue = *(buf++) ? 1 : 0; event.okay = *(buf++) ? 1 : 0;
event.okay = *(buf++) ? 1 : 0; event.ivalue = (int) *((int32 *) buf);
break; buf += sizeof (int32);
strcpy(event.name, (const char *) buf);
case SHIMEVENT_SETSTATI: break;
case SHIMEVENT_GETSTATI:
event.okay = *(buf++) ? 1 : 0; case SHIMEVENT_SETSTATF:
event.ivalue = (int) *((int32 *) buf); case SHIMEVENT_GETSTATF:
buf += sizeof (int32); event.okay = *(buf++) ? 1 : 0;
strcpy(event.name, (const char *) buf); event.fvalue = (int) *((float *) buf);
break; buf += sizeof (float);
strcpy(event.name, (const char *) buf);
case SHIMEVENT_SETSTATF: break;
case SHIMEVENT_GETSTATF:
event.okay = *(buf++) ? 1 : 0; case SHIMEVENT_GETPERSONANAME:
event.fvalue = (int) *((float *) buf); case SHIMEVENT_GETCURRENTGAMELANGUAGE:
buf += sizeof (float); strcpy(event.name, (const char *) buf);
strcpy(event.name, (const char *) buf); break;
break;
default: /* uh oh */
case SHIMEVENT_GETPERSONANAME: return NULL;
case SHIMEVENT_GETCURRENTGAMELANGUAGE: } /* switch */
strcpy(event.name, (const char *) buf);
break; return &event;
} /* processEvent */
default: /* uh oh */
return NULL; const STEAMSHIM_Event *STEAMSHIM_pump(void)
} /* switch */ {
static uint8 buf[256];
return &event; static int br = 0;
} /* processEvent */ int evlen = (br > 0) ? ((int) buf[0]) : 0;
const STEAMSHIM_Event *STEAMSHIM_pump(void) if (isDead())
{ return NULL;
static uint8 buf[256];
static int br = 0; if (br <= evlen) /* we have an incomplete commmand. Try to read more. */
int evlen = (br > 0) ? ((int) buf[0]) : 0; {
if (pipeReady(GPipeRead))
if (isDead()) {
return NULL; const int morebr = readPipe(GPipeRead, buf + br, sizeof (buf) - br);
if (morebr > 0)
if (br <= evlen) /* we have an incomplete commmand. Try to read more. */ br += morebr;
{ else /* uh oh */
if (pipeReady(GPipeRead)) {
{ dbgpipe("Child readPipe failed! Shutting down.\n");
const int morebr = readPipe(GPipeRead, buf + br, sizeof (buf) - br); STEAMSHIM_deinit(); /* kill it all. */
if (morebr > 0) } /* else */
br += morebr; } /* if */
else /* uh oh */ } /* if */
{
dbgpipe("Child readPipe failed! Shutting down.\n"); if (evlen && (br > evlen))
STEAMSHIM_deinit(); /* kill it all. */ {
} /* else */ const STEAMSHIM_Event *retval = processEvent(buf+1, evlen);
} /* if */ br -= evlen + 1;
} /* if */ if (br > 0)
memmove(buf, buf+evlen+1, br);
if (evlen && (br > evlen)) return retval;
{ } /* if */
const STEAMSHIM_Event *retval = processEvent(buf+1, evlen);
br -= evlen + 1; return NULL;
if (br > 0) } /* STEAMSHIM_pump */
memmove(buf, buf+evlen+1, br);
return retval; void STEAMSHIM_requestStats(void)
} /* if */ {
if (isDead()) return;
/* Run Steam event loop. */ dbgpipe("Child sending SHIMCMD_REQUESTSTATS().\n");
if (br == 0) write1ByteCmd(SHIMCMD_REQUESTSTATS);
{ } /* STEAMSHIM_requestStats */
dbgpipe("Child sending SHIMCMD_PUMP().\n");
write1ByteCmd(SHIMCMD_PUMP); void STEAMSHIM_storeStats(void)
} /* if */ {
if (isDead()) return;
return NULL; dbgpipe("Child sending SHIMCMD_STORESTATS().\n");
} /* STEAMSHIM_pump */ write1ByteCmd(SHIMCMD_STORESTATS);
} /* STEAMSHIM_storeStats */
void STEAMSHIM_requestStats(void)
{ void STEAMSHIM_setAchievement(const char *name, const int enable)
if (isDead()) return; {
dbgpipe("Child sending SHIMCMD_REQUESTSTATS().\n"); uint8 buf[256];
write1ByteCmd(SHIMCMD_REQUESTSTATS); uint8 *ptr = buf+1;
} /* STEAMSHIM_requestStats */ if (isDead()) return;
dbgpipe("Child sending SHIMCMD_SETACHIEVEMENT('%s', %senable).\n", name, enable ? "" : "!");
void STEAMSHIM_storeStats(void) *(ptr++) = (uint8) SHIMCMD_SETACHIEVEMENT;
{ *(ptr++) = enable ? 1 : 0;
if (isDead()) return; strcpy((char *) ptr, name);
dbgpipe("Child sending SHIMCMD_STORESTATS().\n"); ptr += strlen(name) + 1;
write1ByteCmd(SHIMCMD_STORESTATS); buf[0] = (uint8) ((ptr-1) - buf);
} /* STEAMSHIM_storeStats */ writePipe(GPipeWrite, buf, buf[0] + 1);
} /* STEAMSHIM_setAchievement */
void STEAMSHIM_setAchievement(const char *name, const int enable)
{ void STEAMSHIM_getAchievement(const char *name)
uint8 buf[256]; {
uint8 *ptr = buf+1; uint8 buf[256];
if (isDead()) return; uint8 *ptr = buf+1;
dbgpipe("Child sending SHIMCMD_SETACHIEVEMENT('%s', %senable).\n", name, enable ? "" : "!"); if (isDead()) return;
*(ptr++) = (uint8) SHIMCMD_SETACHIEVEMENT; dbgpipe("Child sending SHIMCMD_GETACHIEVEMENT('%s').\n", name);
*(ptr++) = enable ? 1 : 0; *(ptr++) = (uint8) SHIMCMD_GETACHIEVEMENT;
strcpy((char *) ptr, name); strcpy((char *) ptr, name);
ptr += strlen(name) + 1; ptr += strlen(name) + 1;
buf[0] = (uint8) ((ptr-1) - buf); buf[0] = (uint8) ((ptr-1) - buf);
writePipe(GPipeWrite, buf, buf[0] + 1); writePipe(GPipeWrite, buf, buf[0] + 1);
} /* STEAMSHIM_setAchievement */ } /* STEAMSHIM_getAchievement */
void STEAMSHIM_getAchievement(const char *name) void STEAMSHIM_resetStats(const int bAlsoAchievements)
{ {
uint8 buf[256]; if (isDead()) return;
uint8 *ptr = buf+1; dbgpipe("Child sending SHIMCMD_RESETSTATS(%salsoAchievements).\n", bAlsoAchievements ? "" : "!");
if (isDead()) return; write2ByteCmd(SHIMCMD_RESETSTATS, bAlsoAchievements ? 1 : 0);
dbgpipe("Child sending SHIMCMD_GETACHIEVEMENT('%s').\n", name); } /* STEAMSHIM_resetStats */
*(ptr++) = (uint8) SHIMCMD_GETACHIEVEMENT;
strcpy((char *) ptr, name); static void writeStatThing(const ShimCmd cmd, const char *name, const void *val, const size_t vallen)
ptr += strlen(name) + 1; {
buf[0] = (uint8) ((ptr-1) - buf); uint8 buf[256];
writePipe(GPipeWrite, buf, buf[0] + 1); uint8 *ptr = buf+1;
} /* STEAMSHIM_getAchievement */ if (isDead()) return;
*(ptr++) = (uint8) cmd;
void STEAMSHIM_resetStats(const int bAlsoAchievements) if (vallen)
{ {
if (isDead()) return; memcpy(ptr, val, vallen);
dbgpipe("Child sending SHIMCMD_RESETSTATS(%salsoAchievements).\n", bAlsoAchievements ? "" : "!"); ptr += vallen;
write2ByteCmd(SHIMCMD_RESETSTATS, bAlsoAchievements ? 1 : 0); } /* if */
} /* STEAMSHIM_resetStats */ strcpy((char *) ptr, name);
ptr += strlen(name) + 1;
static void writeStatThing(const ShimCmd cmd, const char *name, const void *val, const size_t vallen) buf[0] = (uint8) ((ptr-1) - buf);
{ writePipe(GPipeWrite, buf, buf[0] + 1);
uint8 buf[256]; } /* writeStatThing */
uint8 *ptr = buf+1;
if (isDead()) return; void STEAMSHIM_setStatI(const char *name, const int _val)
*(ptr++) = (uint8) cmd; {
if (vallen) const int32 val = (int32) _val;
{ dbgpipe("Child sending SHIMCMD_SETSTATI('%s', val %d).\n", name, val);
memcpy(ptr, val, vallen); writeStatThing(SHIMCMD_SETSTATI, name, &val, sizeof (val));
ptr += vallen; } /* STEAMSHIM_setStatI */
} /* if */
strcpy((char *) ptr, name); void STEAMSHIM_getStatI(const char *name)
ptr += strlen(name) + 1; {
buf[0] = (uint8) ((ptr-1) - buf); dbgpipe("Child sending SHIMCMD_GETSTATI('%s').\n", name);
writePipe(GPipeWrite, buf, buf[0] + 1); writeStatThing(SHIMCMD_GETSTATI, name, NULL, 0);
} /* writeStatThing */ } /* STEAMSHIM_getStatI */
void STEAMSHIM_setStatI(const char *name, const int _val) void STEAMSHIM_setStatF(const char *name, const float val)
{ {
const int32 val = (int32) _val; dbgpipe("Child sending SHIMCMD_SETSTATF('%s', val %f).\n", name, val);
dbgpipe("Child sending SHIMCMD_SETSTATI('%s', val %d).\n", name, val); writeStatThing(SHIMCMD_SETSTATF, name, &val, sizeof (val));
writeStatThing(SHIMCMD_SETSTATI, name, &val, sizeof (val)); } /* STEAMSHIM_setStatF */
} /* STEAMSHIM_setStatI */
void STEAMSHIM_getStatF(const char *name)
void STEAMSHIM_getStatI(const char *name) {
{ dbgpipe("Child sending SHIMCMD_GETSTATF('%s').\n", name);
dbgpipe("Child sending SHIMCMD_GETSTATI('%s').\n", name); writeStatThing(SHIMCMD_GETSTATF, name, NULL, 0);
writeStatThing(SHIMCMD_GETSTATI, name, NULL, 0); } /* STEAMSHIM_getStatF */
} /* STEAMSHIM_getStatI */
void STEAMSHIM_getPersonaName()
void STEAMSHIM_setStatF(const char *name, const float val) {
{ if (isDead()) return;
dbgpipe("Child sending SHIMCMD_SETSTATF('%s', val %f).\n", name, val); dbgpipe("Child sending SHIMCMD_GETPERSONANAME().\n");
writeStatThing(SHIMCMD_SETSTATF, name, &val, sizeof (val)); write1ByteCmd(SHIMCMD_GETPERSONANAME);
} /* STEAMSHIM_setStatF */ } /* STEAMSHIM_getPersonaName */
void STEAMSHIM_getStatF(const char *name) void STEAMSHIM_getCurrentGameLanguage()
{ {
dbgpipe("Child sending SHIMCMD_GETSTATF('%s').\n", name); if (isDead()) return;
writeStatThing(SHIMCMD_GETSTATF, name, NULL, 0); dbgpipe("Child sending SHIMCMD_GETCURRENTGAMELANGUAGE().\n");
} /* STEAMSHIM_getStatF */ write1ByteCmd(SHIMCMD_GETCURRENTGAMELANGUAGE);
} /* STEAMSHIM_getCurrentGameLanguage */
void STEAMSHIM_getPersonaName()
{ /* end of steamshim_child.c ... */
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 ... */