Работа по переписыванию на SDL3 стандартную библеотеку C

This commit is contained in:
DepressedTWM 2026-05-30 10:07:56 -04:00
parent 7763b998a6
commit 78114ba0c9
21 changed files with 193 additions and 332 deletions

View file

@ -234,8 +234,6 @@ void ALStream::openSource(const std::string &filename){
char buf[512];
snprintf(buf, sizeof(buf), "Unable to decode audio stream: %s: %s", filename.c_str(), handler.errorMsg.c_str());
crash(buf, Exception::MEOW, false);
Debug() << buf;
}
}

View file

@ -28,8 +28,7 @@
#include <SDL3/SDL_thread.h>
#include <SDL3/SDL_timer.h>
AudioStream::AudioStream(ALStream::LoopMode loopMode,
const std::string &threadId)
AudioStream::AudioStream(ALStream::LoopMode loopMode, const std::string &threadId)
: extPaused(false),
noResumeStop(false),
stream(loopMode, threadId)

View file

@ -113,8 +113,7 @@ struct AudioStream{
uint32_t startTicks;
} fadeIn;
AudioStream(ALStream::LoopMode loopMode,
const std::string &threadId);
AudioStream(ALStream::LoopMode loopMode, const std::string &threadId);
~AudioStream();
void play(const std::string &filename, int volume, int pitch, float offset = 0);

View file

@ -48,8 +48,7 @@
#define GUARD_MEGA \
{ \
if (p->megaSurface) \
throw Exception(Exception::MKXPError, \
"Operation not supported for mega surfaces"); \
crash("Operation not supported for mega surfaces", Exception::MKXPError, true); \
}
#define OUTLINE_SIZE 1
@ -1034,15 +1033,10 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align){
TEX::bind(p->gl.tex);
if (!subImage){
TEX::uploadSubImage(posRect.x, posRect.y,
posRect.w, posRect.h,
txtSurf->pixels, GL_RGBA);
TEX::uploadSubImage(posRect.x, posRect.y, posRect.w, posRect.h, txtSurf->pixels, GL_RGBA);
}
else{
GLMeta::subRectImageUpload(txtSurf->w, subSrcX, subSrcY,
posRect.x, posRect.y,
posRect.w, posRect.h,
txtSurf, GL_RGBA);
GLMeta::subRectImageUpload(txtSurf->w, subSrcX, subSrcY, posRect.x, posRect.y, posRect.w, posRect.h, txtSurf, GL_RGBA);
GLMeta::subRectImageEnd();
}
}

View file

@ -28,7 +28,7 @@
#include <physfs.h>
#include <fstream>
#include <stdint.h>
#include <SDL3/SDL_stdinc.h>
#include <cstdlib>
#include "debugwriter.h"
@ -129,8 +129,7 @@ void Config::read(int argc, char *argv[]){
/* Parse command line options */
try{
po::parsed_options cmdPo =
po::command_line_parser(argc, argv).options(podesc).run();
po::parsed_options cmdPo = po::command_line_parser(argc, argv).options(podesc).run();
po::store(cmdPo, vm);
}
catch (po::error &error){
@ -186,7 +185,7 @@ void Config::read(int argc, char *argv[]){
#ifdef STEAM
/* Override fullscreen config if Big Picture */
if (const char *env = std::getenv("SteamTenfoot")){
if (!strcmp(env, "1"))
if (!SDL_strcmp(env, "1"))
fullscreen = true;
}
#endif

View file

@ -38,7 +38,7 @@
#include "oneshot.h"
#include <string.h>
#include <SDL3/SDL_stdinc.h>
#include <map>
@ -307,8 +307,7 @@ void EventThread::process(RGSSThreadData &rtData){
if (fullscreen){
/* Prevent fullscreen flicker */
strncpy(pendingTitle, rtData.config.windowTitle.c_str(),
sizeof(pendingTitle));
SDL_strlcpy(pendingTitle, rtData.config.windowTitle.c_str(), sizeof(pendingTitle));
break;
}
@ -455,7 +454,7 @@ void EventThread::process(RGSSThreadData &rtData){
case SDL_EVENT_FINGER_UP :
i = event.tfinger.fingerID;
memset(&touchState.fingers[i], 0, sizeof(touchState.fingers[0]));
SDL_memset(&touchState.fingers[i], 0, sizeof(touchState.fingers[0]));
break;
default :
@ -471,10 +470,8 @@ void EventThread::process(RGSSThreadData &rtData){
break;
case REQUEST_MESSAGEBOX :
SDL_ShowSimpleMessageBox(event.user.code,
rtData.config.windowTitle.c_str(),
(const char*) event.user.data1, win);
free(event.user.data1);
SDL_ShowSimpleMessageBox(event.user.code, rtData.config.windowTitle.c_str(), (const char*) event.user.data1, win);
SDL_free(event.user.data1);
msgBoxDone.set();
break;
@ -487,12 +484,12 @@ void EventThread::process(RGSSThreadData &rtData){
if (!fps.sendUpdates)
break;
snprintf(buffer, sizeof(buffer), "%s - %d FPS", rtData.config.windowTitle.c_str(), event.user.code);
SDL_snprintf(buffer, sizeof(buffer), "%s - %d FPS", rtData.config.windowTitle.c_str(), event.user.code);
/* Updating the window title in fullscreen
* mode seems to cause flickering */
if (fullscreen){
strncpy(pendingTitle, buffer, sizeof(pendingTitle));
SDL_strlcpy(pendingTitle, buffer, sizeof(pendingTitle));
break;
}
@ -585,15 +582,15 @@ void EventThread::cleanup(){
while (SDL_PollEvent(&event))
if ((event.type - usrIdStart) == REQUEST_MESSAGEBOX)
free(event.user.data1);
SDL_free(event.user.data1);
}
void EventThread::resetInputStates(){
memset(&keyStates, 0, sizeof(keyStates));
memset(&gcState, 0, sizeof(gcState));
memset(&joyState, 0, sizeof(joyState));
memset(&mouseState.buttons, 0, sizeof(mouseState.buttons));
memset(&touchState, 0, sizeof(touchState));
SDL_memset(&keyStates, 0, sizeof(keyStates));
SDL_memset(&gcState, 0, sizeof(gcState));
SDL_memset(&joyState, 0, sizeof(joyState));
SDL_memset(&mouseState.buttons, 0, sizeof(mouseState.buttons));
SDL_memset(&touchState, 0, sizeof(touchState));
}
void EventThread::setFullscreen(SDL_Window *win, bool mode){

View file

@ -35,8 +35,6 @@
#include <string>
#include <stdint.h>
#include <alc.h>
//typedef struct ALCdevice_struct ALCdevice;
@ -256,11 +254,7 @@ struct RGSSThreadData{
std::string inputText;
int inputTextLimit;
RGSSThreadData(EventThread *ethread,
SDL_Window *window,
ALCdevice *alcDev,
int refreshRate,
const Config& newconf)
RGSSThreadData(EventThread *ethread, SDL_Window *window, ALCdevice *alcDev, int refreshRate, const Config& newconf)
: allowExit(true),
ethread(ethread),
window(window),

View file

@ -33,9 +33,7 @@
#include <physfs.h>
#include <SDL3_sound/SDL_sound.h>
#include <stdio.h>
#include <string.h>
#include <SDL3/SDL_stdinc.h>
#include <algorithm>
#include <vector>
#include <stack>
@ -233,11 +231,11 @@ static int SDL_RWopsCloseFree(void *userdata)
* Returns copied bytes (minus terminating null) */
static size_t strcpySafe(char *dst, const char *src, size_t dstMax, int srcN){
if (srcN < 0)
srcN = strlen(src);
srcN = SDL_strlen(src);
size_t cpyMax = std::min<size_t>(dstMax-1, srcN);
memcpy(dst, src, cpyMax);
SDL_memcpy(dst, src, cpyMax);
dst[cpyMax] = '\0';
return cpyMax;
@ -249,7 +247,7 @@ static size_t strcpySafe(char *dst, const char *src, size_t dstMax, int srcN){
static const char *findExt(const char *filename){
size_t len;
for (len = strlen(filename); len > 0; --len){
for (len = SDL_strlen(filename); len > 0; --len){
if (filename[len] == '/')
return 0;
@ -357,7 +355,7 @@ struct CacheEnumData{
/* Converts in-place */
void toNFC(char *inout){
#ifdef OS_OSX
size_t srcSize = strlen(inout);
size_t srcSize = SDL_strlen(inout);
size_t bufSize = sizeof(buf);
char *bufPtr = buf;
char *inoutPtr = inout;
@ -365,9 +363,7 @@ struct CacheEnumData{
/* Reserve room for null terminator */
--bufSize;
iconv(nfd2nfc,
&inoutPtr, &srcSize,
&bufPtr, &bufSize);
iconv(nfd2nfc, &inoutPtr, &srcSize, &bufPtr, &bufSize);
/* Null-terminate */
*bufPtr = 0;
strcpy(inout, buf);
@ -382,9 +378,9 @@ static PHYSFS_EnumerateCallbackResult cacheEnumCB(void *d, const char *origdir,
char fullPath[512];
if (!*origdir)
snprintf(fullPath, sizeof(fullPath), "%s", fname);
SDL_snprintf(fullPath, sizeof(fullPath), "%s", fname);
else
snprintf(fullPath, sizeof(fullPath), "%s/%s", origdir, fname);
SDL_snprintf(fullPath, sizeof(fullPath), "%s/%s", origdir, fname);
/* Deal with OSX' weird UTF-8 standards */
data.toNFC(fullPath);
@ -448,11 +444,11 @@ static PHYSFS_EnumerateCallbackResult fontSetEnumCB (void *data, const char *dir
lowExt[i] = tolower(ext[i]);
lowExt[i] = '\0';
if (strcmp(lowExt, "ttf") && strcmp(lowExt, "otf") && strcmp(lowExt, "ttc"))
if (SDL_strcmp(lowExt, "ttf") && SDL_strcmp(lowExt, "otf") && SDL_strcmp(lowExt, "ttc"))
return PHYSFS_ENUM_OK;
char filename[512];
snprintf(filename, sizeof(filename), "%s/%s", dir, fname);
SDL_snprintf(filename, sizeof(filename), "%s/%s", dir, fname);
PHYSFS_File *handle = PHYSFS_openRead(filename);
if (!handle)
@ -494,9 +490,7 @@ struct OpenReadEnumData{
* doesn't get changed before we get back into our code */
const char *physfsError;
OpenReadEnumData(FileSystem::OpenHandler &handler,
const char *filename, size_t filenameN,
BoostHash<std::string, std::string> *pathTrans)
OpenReadEnumData(FileSystem::OpenHandler &handler, const char *filename, size_t filenameN, BoostHash<std::string, std::string> *pathTrans)
: handler(handler), filename(filename), filenameN(filenameN),
pathTrans(pathTrans), matchCount(0), stopSearching(false),
physfsError(0)
@ -513,14 +507,14 @@ openReadEnumCB(void *d, const char *dirpath, const char *filename){
return PHYSFS_ENUM_STOP;
/* If there's not even a partial match, continue searching */
if (strncmp(filename, data.filename, data.filenameN) != 0)
if (SDL_strncmp(filename, data.filename, data.filenameN) != 0)
return PHYSFS_ENUM_OK;
if (!*dirpath){
fullPath = filename;
}
else{
snprintf(buffer, sizeof(buffer), "%s/%s", dirpath, filename);
SDL_snprintf(buffer, sizeof(buffer), "%s/%s", dirpath, filename);
fullPath = buffer;
}
@ -587,8 +581,7 @@ void FileSystem::openRead(OpenHandler &handler, const char *filename){
dir = buffer;
}
OpenReadEnumData data(handler, file, len + buffer - delim - !root,
p->havePathCache ? &p->pathCache : 0);
OpenReadEnumData data(handler, file, len + buffer - delim - !root, p->havePathCache ? &p->pathCache : 0);
if (p->havePathCache){
/* Get the list of files contained in this directory

View file

@ -39,7 +39,7 @@ struct GLDebugLoggerPrivate{
void writeTimestamp(){
time(&timestamp);
*stream << "[GLDEBUG | " << ctime(&timestamp) << "]";
*stream << "[GLDEBUG " << ctime(&timestamp) << "]";
}
void writeLine(const char *line){

View file

@ -24,7 +24,7 @@
#include "gl-fun.h"
#include <stdio.h>
#include <SDL3/SDL_stdinc.h>
#include <algorithm>
struct GLDebugLoggerPrivate;
@ -42,7 +42,7 @@ private:
if (gl.StringMarker) \
{ \
char buf[128]; \
int len = snprintf(buf, sizeof(buf), format, ##__VA_ARGS__); \
int len = SDL_snprintf(buf, sizeof(buf), format, ##__VA_ARGS__); \
gl.StringMarker(std::min<size_t>(len, sizeof(buf)), buf); \
}

View file

@ -5,7 +5,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <SDL3/SDL_stdinc.h>
char** strdict = 0;
unsigned int nStr = 0;
@ -35,10 +35,10 @@ const char* findtext(unsigned int msgid, const char* fallback) {
void unloadLocale() {
for (unsigned int i = 0; i < nStr; i++) {
free(strdict[i]);
SDL_free(strdict[i]);
}
free(strdict);
free(currentLocale);
SDL_free(strdict);
SDL_free(currentLocale);
strdict = 0;
nStr = 0;
}
@ -50,16 +50,16 @@ void unloadLanguageMetadata() {
LanguageFontAndSize* ldata = languageMetadata[i];
if (ldata) {
if (ldata->font_name) {
free(ldata->font_name);
SDL_free(ldata->font_name);
}
if (ldata->lang_code) {
free(ldata->lang_code);
SDL_free(ldata->lang_code);
}
free(ldata);
SDL_free(ldata);
}
}
}
free(languageMetadata);
SDL_free(languageMetadata);
}
void loadLanguageMetadata() {
@ -77,27 +77,27 @@ void loadLanguageMetadata() {
int languageMetadataIndex = 0;
while (fgets(line, 1024, fontsFile)) {
char* indexOfEquals = strchr(line, '=');
char* indexOfEquals = SDL_strchr(line, '=');
if (indexOfEquals) {
// splitting the string in place here
indexOfEquals[0] = 0;
char* indexOfFontName = indexOfEquals + 1;
// remove new line from end of font name
char* indexOfNewLine = strchr(indexOfFontName, '\n');
char* indexOfNewLine = SDL_strchr(indexOfFontName, '\n');
if (indexOfNewLine) {
indexOfNewLine[0] = 0;
}
// make new strings for code and font name
char* langCode = (char*)calloc(LANGCODE_SIZE, sizeof(char));
char* langFont = (char*)calloc(LANGFONT_SIZE, sizeof(char));
char* langCode = (char*)SDL_calloc(LANGCODE_SIZE, sizeof(char));
char* langFont = (char*)SDL_calloc(LANGFONT_SIZE, sizeof(char));
strcpy(langCode, line);
strcpy(langFont, indexOfFontName);
SDL_strlcpy(langCode, line, sizeof(line));
SDL_strlcpy(langFont, indexOfFontName, sizeof(indexOfFontName));
// allocate metadata mem
LanguageFontAndSize* metadata = (LanguageFontAndSize*) calloc(1, sizeof(LanguageFontAndSize));
LanguageFontAndSize* metadata = (LanguageFontAndSize*) SDL_calloc(1, sizeof(LanguageFontAndSize));
metadata->font_name = langFont;
metadata->lang_code = langCode;
@ -118,7 +118,7 @@ void loadLanguageMetadata() {
if (fontSizesFile) {
while (fgets(line, 1024, fontSizesFile)) {
int languageMetadataIndex = 0;
char* indexOfEquals = strchr(line, '=');
char* indexOfEquals = SDL_strchr(line, '=');
if (indexOfEquals) {
// splitting the string in place here
indexOfEquals[0] = 0;
@ -135,22 +135,20 @@ void loadLanguageMetadata() {
for (int i = 0; i < MAX_LANGUAGES; i++) {
// search for corresponding langCode in metadata array to populate font size in the appropriate metadata
LanguageFontAndSize* metadata = languageMetadata[i];
if (metadata && strcmp(line, metadata->lang_code) == 0) {
if (metadata && SDL_strcmp(line, metadata->lang_code) == 0) {
metadata->size = fontSize;
break;
}
}
}
}
//fclose(fontSizesFile);
}
}
int getFontSize() {
for (int i = 0; i < MAX_LANGUAGES; i++) {
LanguageFontAndSize* metadata = languageMetadata[i];
if (metadata && strcmp(currentLocale, metadata->lang_code) == 0) {
if (metadata && SDL_strcmp(currentLocale, metadata->lang_code) == 0) {
return metadata->size;
}
}
@ -162,7 +160,7 @@ int getFontSize() {
char* getFontName() {
for (int i = 0; i < MAX_LANGUAGES; i++) {
LanguageFontAndSize* metadata = languageMetadata[i];
if (metadata && strcmp(currentLocale, metadata->lang_code) == 0) {
if (metadata && SDL_strcmp(currentLocale, metadata->lang_code) == 0) {
return metadata->font_name;
}
}
@ -178,21 +176,21 @@ void loadLocale(const char* locale) {
unloadLocale();
currentLocale = (char*) calloc(128, sizeof(char));
strncpy(currentLocale, locale, 128 - 1);
currentLocale = (char*) SDL_calloc(128, sizeof(char));
SDL_strlcpy(currentLocale, locale, 128 - 1);
int dictSize = 100;
// currently there are 52, but 100 should be plenty if we ever do add more
strdict = (char**)malloc(sizeof(char*) * dictSize);
strdict = (char**)SDL_malloc(sizeof(char*) * dictSize);
sprintf(pathbuf, "Languages/internal/%s.po", locale);
locfile = fopen(pathbuf, "r");
if (locfile) {
while (fgets(line, 1024, locfile)) {
if (strncmp("msgstr \"", line, 8) == 0) {
if (SDL_strncmp("msgstr \"", line, 8) == 0) {
char* lineWithoutMsgid = line + 8;
char* endQuoteAddress = strrchr(lineWithoutMsgid, '"');
char* endQuoteAddress = SDL_strrchr(lineWithoutMsgid, '"');
// end string at last quotation mark
if (endQuoteAddress != 0) {
@ -201,10 +199,10 @@ void loadLocale(const char* locale) {
decodeEscapeChars(lineWithoutMsgid);
int lineLen = strlen(lineWithoutMsgid);
int lineLen = SDL_strlen(lineWithoutMsgid);
strdict[nStr] = (char*)malloc(lineLen + 1);
strcpy(strdict[nStr], lineWithoutMsgid);
SDL_strlcpy(strdict[nStr], lineWithoutMsgid, sizeof(lineWithoutMsgid));
nStr++;
}

View file

@ -30,7 +30,7 @@
#include <SDL3/SDL_mouse.h>
#include <vector>
#include <string.h>
#include <SDL3/SDL_stdinc.h>
#include <assert.h>
#define BUTTON_CODE_COUNT 24
@ -113,9 +113,7 @@ struct GcButtonBinding : public Binding{
struct GcAxisBinding : public Binding{
GcAxisBinding() {}
GcAxisBinding(uint8_t source,
AxisDir dir,
Input::ButtonCode target)
GcAxisBinding(uint8_t source, AxisDir dir, Input::ButtonCode target)
: Binding(target),
source(source),
dir(dir)
@ -157,9 +155,7 @@ struct JsButtonBinding : public Binding{
struct JsAxisBinding : public Binding{
JsAxisBinding() {}
JsAxisBinding(uint8_t source,
AxisDir dir,
Input::ButtonCode target)
JsAxisBinding(uint8_t source, AxisDir dir, Input::ButtonCode target)
: Binding(target),
source(source),
dir(dir)
@ -186,9 +182,7 @@ struct JsAxisBinding : public Binding{
struct JsHatBinding : public Binding{
JsHatBinding() {}
JsHatBinding(uint8_t source,
uint8_t pos,
Input::ButtonCode target)
JsHatBinding(uint8_t source, uint8_t pos, Input::ButtonCode target)
: Binding(target),
source(source),
pos(pos)
@ -211,8 +205,7 @@ struct JsHatBinding : public Binding{
struct MsBinding : public Binding{
MsBinding() {}
MsBinding(int buttonIndex,
Input::ButtonCode target)
MsBinding(int buttonIndex, Input::ButtonCode target)
: Binding(target),
index(buttonIndex)
{}
@ -373,7 +366,7 @@ struct InputPrivate {
void clearBuffer(){
const size_t size = sizeof(ButtonState) * BUTTON_CODE_COUNT;
memset(states, 0, size);
SDL_memset(states, 0, size);
}
void checkBindingChange(const RGSSThreadData &rtData){
@ -508,8 +501,7 @@ struct InputPrivate {
updateDir8();
}
void pollBindingPriv(const Binding &b,
Input::ButtonCode &repeatCand){
void pollBindingPriv(const Binding &b, Input::ButtonCode &repeatCand){
if (!b.sourceActive())
return;

View file

@ -24,7 +24,7 @@
#include "config.h"
#include "util.h"
#include <stdio.h>
#include <SDL3/SDL_stdinc.h>
struct KbBindingData{
SDL_Scancode source;
@ -156,7 +156,7 @@ struct Header{
};
static void buildPath(const std::string &dir, char *out, size_t outSize){
snprintf(out, outSize, "%skeybindings.dat", dir.c_str());
SDL_snprintf(out, outSize, "%skeybindings.dat", dir.c_str());
}
static bool writeBindings(const BDescVec &d, const std::string &dir){

View file

@ -27,7 +27,7 @@
#include <SDL3/SDL_scancode.h>
#include <SDL3/SDL_joystick.h>
#include <SDL3/SDL_gamepad.h>
#include <stdint.h>
#include <SDL3/SDL_stdinc.h>
#include <assert.h>
#include <vector>

View file

@ -33,7 +33,7 @@
#else
#include <unistd.h>
#endif
#include <string.h>
#include <SDL3/SDL_stdinc.h>
#include <assert.h>
#include <string>
#include <iostream>
@ -88,7 +88,7 @@ int rgssThreadFun(void *userdata){
glCtx = SDL_GL_CreateContext(win);
if (!glCtx){
snprintf(msg, sizeof msg, "Error creating context: %s", SDL_GetError());
SDL_snprintf(msg, sizeof msg, "Error creating context: %s", SDL_GetError());
crash(msg, Exception::MEOW, false);
rgssThreadError(threadData, std::string(msg));
return 0;
@ -230,7 +230,7 @@ int main(int argc, char *argv[]){
/* initialize SDL first */
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) == false){
snprintf(msg, sizeof msg, "Error initializing SDL: %s", SDL_GetError());
SDL_snprintf(msg, sizeof msg, "Error initializing SDL: %s", SDL_GetError());
crash(msg, Exception::MEOW, false);
return 0;
}
@ -276,7 +276,7 @@ int main(int argc, char *argv[]){
if (!conf.gameFolder.empty()){
if (chdir(conf.gameFolder.c_str()) != 0){
snprintf(msg, sizeof msg, "Unable to switch into gameFolder %s", conf.gameFolder);
SDL_snprintf(msg, sizeof msg, "Unable to switch into gameFolder %s", conf.gameFolder);
crash(msg, Exception::MEOW, false);
return 0;
}
@ -290,13 +290,13 @@ int main(int argc, char *argv[]){
conf.windowTitle = conf.game.title;
if (TTF_Init() == false){
snprintf(msg, sizeof msg, "Error initializing SDL_ttf: %s", SDL_GetError());
SDL_snprintf(msg, sizeof msg, "Error initializing SDL_ttf: %s", SDL_GetError());
crash(msg, Exception::MEOW, false);
SDL_Quit();
}
if (Sound_Init() == false){
snprintf(msg, sizeof msg, "Error initializing SDL_sound: %s", Sound_GetError());
SDL_snprintf(msg, sizeof msg, "Error initializing SDL_sound: %s", Sound_GetError());
crash(msg, Exception::MEOW, false);
TTF_Quit();
SDL_Quit();
@ -316,7 +316,7 @@ int main(int argc, char *argv[]){
SDL_SetWindowFullscreen(win, true);
if (!win){
snprintf(msg, sizeof msg, "Error creating window: %s", SDL_GetError());
SDL_snprintf(msg, sizeof msg, "Error creating window: %s", SDL_GetError());
crash(msg, Exception::MEOW, false);
return 0;
}

View file

@ -13,7 +13,7 @@
#include "config.h"
#include "gl-debug.h"
#include "gl-fun.h"
#include <stdio.h>
#include <SDL3/SDL_stdinc.h>
#include <time.h>
#include <fstream>
#include <ruby.h>
@ -29,7 +29,6 @@
#include "xdg-user-dir-lookup.h"
#endif
SDL_MessageBoxButtonData buttons[] = {
{ SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Yes" },
{ SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 2, "No" }
@ -39,10 +38,9 @@ static inline const char* glGetStringInt(GLenum name){
return (const char*) gl.GetString(name);
}
void crash(const char* reason, Exception::Type t, bool do_exp){
char msg[1024];
snprintf(msg, sizeof msg, "Error occured! Error message: %s\n\n Want to create a crash log? You can share the crash log with the developers and help resolve the issue.", reason);
SDL_snprintf(msg, sizeof msg, "Error occured! Error message: %s\n\n Want to create a crash log? You can share the crash log with the developers and help resolve the issue.", reason);
SDL_MessageBoxData messageboxdata = {
.flags = SDL_MESSAGEBOX_ERROR,
.window = NULL,

View file

@ -42,33 +42,28 @@ static int pipeReady(PipeType fd);
#ifdef _WIN32
static int pipeReady(PipeType fd)
{
static int pipeReady(PipeType fd){
DWORD avail = 0;
return (PeekNamedPipe(fd, NULL, 0, NULL, &avail, NULL) && (avail > 0));
} /* pipeReady */
static int writePipe(PipeType fd, const void *buf, const unsigned int _len)
{
static int writePipe(PipeType fd, const void *buf, const unsigned int _len){
const DWORD len = (DWORD) _len;
DWORD bw = 0;
return ((WriteFile(fd, buf, len, &bw, NULL) != 0) && (bw == len));
} /* writePipe */
static int readPipe(PipeType fd, void *buf, const unsigned int _len)
{
static int readPipe(PipeType fd, void *buf, const unsigned int _len){
const DWORD len = (DWORD) _len;
DWORD br = 0;
return ReadFile(fd, buf, len, &br, NULL) ? (int) br : -1;
} /* readPipe */
static void closePipe(PipeType fd)
{
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 rc = GetEnvironmentVariableA(key, buf, buflen);
/* rc doesn't count null char, hence "<". */
return ((rc > 0) && (rc < buflen)) ? buf : NULL;
@ -76,37 +71,32 @@ static char *getEnvVar(const char *key, char *buf, const size_t buflen)
#else
static int pipeReady(PipeType fd)
{
static int pipeReady(PipeType fd){
int rc;
struct pollfd pfd = { fd, POLLIN | POLLERR | POLLHUP, 0 };
while (((rc = poll(&pfd, 1, 0)) == -1) && (errno == EINTR)) { /*spin*/ }
return (rc == 1);
} /* pipeReady */
static int writePipe(PipeType fd, const void *buf, const unsigned int _len)
{
static int writePipe(PipeType fd, const void *buf, const unsigned int _len){
const ssize_t len = (ssize_t) _len;
ssize_t bw;
while (((bw = write(fd, buf, len)) == -1) && (errno == EINTR)) { /*spin*/ }
return (bw == len);
} /* writePipe */
static int readPipe(PipeType fd, void *buf, const unsigned int _len)
{
static int readPipe(PipeType fd, void *buf, const unsigned int _len){
const ssize_t len = (ssize_t) _len;
ssize_t br;
while (((br = read(fd, buf, len)) == -1) && (errno == EINTR)) { /*spin*/ }
return (int) br;
} /* readPipe */
static void closePipe(PipeType fd)
{
static void closePipe(PipeType fd){
close(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 char *envr = getenv(key);
if (!envr || (strlen(envr) >= buflen))
return NULL;
@ -120,8 +110,7 @@ static char *getEnvVar(const char *key, char *buf, const size_t buflen)
static PipeType GPipeRead = NULLPIPE;
static PipeType GPipeWrite = NULLPIPE;
typedef enum ShimCmd
{
typedef enum ShimCmd{
SHIMCMD_BYE,
SHIMCMD_PUMP,
SHIMCMD_REQUESTSTATS,
@ -137,26 +126,22 @@ typedef enum ShimCmd
SHIMCMD_GETCURRENTGAMELANGUAGE,
} ShimCmd;
static int write1ByteCmd(const uint8 b1)
{
static int write1ByteCmd(const uint8 b1){
const uint8 buf[] = { 1, b1 };
return writePipe(GPipeWrite, buf, sizeof (buf));
} /* write1ByteCmd */
static int write2ByteCmd(const uint8 b1, const uint8 b2)
{
static int write2ByteCmd(const uint8 b1, const uint8 b2){
const uint8 buf[] = { 2, b1, b2 };
return writePipe(GPipeWrite, buf, sizeof (buf));
} /* write2ByteCmd */
static inline int writeBye(void)
{
static inline int writeBye(void){
dbgpipe("Child sending SHIMCMD_BYE().\n");
return write1ByteCmd(SHIMCMD_BYE);
} // writeBye
static int initPipes(void)
{
static int initPipes(void){
char buf[64];
if (!getEnvVar("STEAMSHIM_READHANDLE", buf, sizeof (buf)))
@ -171,11 +156,9 @@ static int initPipes(void)
} /* initPipes */
int STEAMSHIM_init(void)
{
int STEAMSHIM_init(void){
dbgpipe("Child init start.\n");
if (!initPipes())
{
if (!initPipes()){
dbgpipe("Child init failed.\n");
return 0;
} /* if */
@ -188,11 +171,9 @@ int STEAMSHIM_init(void)
return 1;
} /* STEAMSHIM_init */
void STEAMSHIM_deinit(void)
{
void STEAMSHIM_deinit(void){
dbgpipe("Child deinit.\n");
if (GPipeWrite != NULLPIPE)
{
if (GPipeWrite != NULLPIPE){
writeBye();
closePipe(GPipeWrite);
} /* if */
@ -207,23 +188,19 @@ void STEAMSHIM_deinit(void)
#endif
} /* STEAMSHIM_deinit */
static inline int isAlive(void)
{
static inline int isAlive(void){
return ((GPipeRead != NULLPIPE) && (GPipeWrite != NULLPIPE));
} /* isAlive */
static inline int isDead(void)
{
static inline int isDead(void){
return !isAlive();
} /* isDead */
int STEAMSHIM_alive(void)
{
int STEAMSHIM_alive(void){
return isAlive();
} /* STEAMSHIM_alive */
static const STEAMSHIM_Event *processEvent(const uint8 *buf, size_t buflen)
{
static const STEAMSHIM_Event *processEvent(const uint8 *buf, size_t buflen){
static STEAMSHIM_Event event;
const STEAMSHIM_EventType type = (STEAMSHIM_EventType) *(buf++);
buflen--;
@ -313,8 +290,7 @@ static const STEAMSHIM_Event *processEvent(const uint8 *buf, size_t buflen)
return &event;
} /* processEvent */
const STEAMSHIM_Event *STEAMSHIM_pump(void)
{
const STEAMSHIM_Event *STEAMSHIM_pump(void){
static uint8 buf[256];
static int br = 0;
int evlen = (br > 0) ? ((int) buf[0]) : 0;
@ -337,8 +313,7 @@ const STEAMSHIM_Event *STEAMSHIM_pump(void)
} /* if */
} /* if */
if (evlen && (br > evlen))
{
if (evlen && (br > evlen)){
const STEAMSHIM_Event *retval = processEvent(buf+1, evlen);
br -= evlen + 1;
if (br > 0)
@ -347,8 +322,7 @@ const STEAMSHIM_Event *STEAMSHIM_pump(void)
} /* if */
/* Run Steam event loop. */
if (br == 0)
{
if (br == 0){
dbgpipe("Child sending SHIMCMD_PUMP().\n");
write1ByteCmd(SHIMCMD_PUMP);
} /* if */
@ -356,22 +330,19 @@ const STEAMSHIM_Event *STEAMSHIM_pump(void)
return NULL;
} /* STEAMSHIM_pump */
void STEAMSHIM_requestStats(void)
{
void STEAMSHIM_requestStats(void){
if (isDead()) return;
dbgpipe("Child sending SHIMCMD_REQUESTSTATS().\n");
write1ByteCmd(SHIMCMD_REQUESTSTATS);
} /* STEAMSHIM_requestStats */
void STEAMSHIM_storeStats(void)
{
void STEAMSHIM_storeStats(void){
if (isDead()) return;
dbgpipe("Child sending SHIMCMD_STORESTATS().\n");
write1ByteCmd(SHIMCMD_STORESTATS);
} /* STEAMSHIM_storeStats */
void STEAMSHIM_setAchievement(const char *name, const int enable)
{
void STEAMSHIM_setAchievement(const char *name, const int enable){
uint8 buf[256];
uint8 *ptr = buf+1;
if (isDead()) return;
@ -384,8 +355,7 @@ void STEAMSHIM_setAchievement(const char *name, const int enable)
writePipe(GPipeWrite, buf, buf[0] + 1);
} /* STEAMSHIM_setAchievement */
void STEAMSHIM_getAchievement(const char *name)
{
void STEAMSHIM_getAchievement(const char *name){
uint8 buf[256];
uint8 *ptr = buf+1;
if (isDead()) return;
@ -397,15 +367,13 @@ void STEAMSHIM_getAchievement(const char *name)
writePipe(GPipeWrite, buf, buf[0] + 1);
} /* STEAMSHIM_getAchievement */
void STEAMSHIM_resetStats(const int bAlsoAchievements)
{
void STEAMSHIM_resetStats(const int bAlsoAchievements){
if (isDead()) return;
dbgpipe("Child sending SHIMCMD_RESETSTATS(%salsoAchievements).\n", bAlsoAchievements ? "" : "!");
write2ByteCmd(SHIMCMD_RESETSTATS, bAlsoAchievements ? 1 : 0);
} /* STEAMSHIM_resetStats */
static void writeStatThing(const ShimCmd cmd, const char *name, const void *val, const size_t vallen)
{
static void writeStatThing(const ShimCmd cmd, const char *name, const void *val, const size_t vallen){
uint8 buf[256];
uint8 *ptr = buf+1;
if (isDead()) return;
@ -421,40 +389,34 @@ static void writeStatThing(const ShimCmd cmd, const char *name, const void *val,
writePipe(GPipeWrite, buf, buf[0] + 1);
} /* writeStatThing */
void STEAMSHIM_setStatI(const char *name, const int _val)
{
void STEAMSHIM_setStatI(const char *name, const int _val){
const int32 val = (int32) _val;
dbgpipe("Child sending SHIMCMD_SETSTATI('%s', val %d).\n", name, val);
writeStatThing(SHIMCMD_SETSTATI, name, &val, sizeof (val));
} /* STEAMSHIM_setStatI */
void STEAMSHIM_getStatI(const char *name)
{
void STEAMSHIM_getStatI(const char *name){
dbgpipe("Child sending SHIMCMD_GETSTATI('%s').\n", name);
writeStatThing(SHIMCMD_GETSTATI, name, NULL, 0);
} /* STEAMSHIM_getStatI */
void STEAMSHIM_setStatF(const char *name, const float val)
{
void STEAMSHIM_setStatF(const char *name, const float val){
dbgpipe("Child sending SHIMCMD_SETSTATF('%s', val %f).\n", name, val);
writeStatThing(SHIMCMD_SETSTATF, name, &val, sizeof (val));
} /* STEAMSHIM_setStatF */
void STEAMSHIM_getStatF(const char *name)
{
void STEAMSHIM_getStatF(const char *name){
dbgpipe("Child sending SHIMCMD_GETSTATF('%s').\n", name);
writeStatThing(SHIMCMD_GETSTATF, name, NULL, 0);
} /* STEAMSHIM_getStatF */
void STEAMSHIM_getPersonaName()
{
void STEAMSHIM_getPersonaName(){
if (isDead()) return;
dbgpipe("Child sending SHIMCMD_GETPERSONANAME().\n");
write1ByteCmd(SHIMCMD_GETPERSONANAME);
} /* STEAMSHIM_getPersonaName */
void STEAMSHIM_getCurrentGameLanguage()
{
void STEAMSHIM_getCurrentGameLanguage(){
if (isDead()) return;
dbgpipe("Child sending SHIMCMD_GETCURRENTGAMELANGUAGE().\n");
write1ByteCmd(SHIMCMD_GETCURRENTGAMELANGUAGE);

View file

@ -5,8 +5,7 @@
extern "C" {
#endif
typedef enum STEAMSHIM_EventType
{
typedef enum STEAMSHIM_EventType{
SHIMEVENT_BYE,
SHIMEVENT_STATSRECEIVED,
SHIMEVENT_STATSSTORED,
@ -22,8 +21,7 @@ typedef enum STEAMSHIM_EventType
} STEAMSHIM_EventType;
/* not all of these fields make sense in a given event. */
typedef struct STEAMSHIM_Event
{
typedef struct STEAMSHIM_Event{
STEAMSHIM_EventType type;
int okay;
int ivalue;

View file

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8.11)
set(STEAMWORKS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../steamworks" CACHE PATH "Path to Steamworks folder")
set(GAME_LAUNCH_NAME "oneshot" CACHE STRING "Game launch name")
option(DEBUG "Debug mode" OFF)
option(DEBUG "Debug" OFF)
if(DEBUG)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3 -O0 -fno-omit-frame-pointer -ggdb")
@ -17,6 +17,8 @@ include_directories(${STEAMWORKS_PATH}/public)
add_definitions(-DGAME_LAUNCH_NAME="${GAME_LAUNCH_NAME}")
find_package(SDL3 CONFIG)
IF(DEBUG)
add_definitions(-DSTEAMSHIM_DEBUG)
ENDIF()
@ -37,4 +39,4 @@ add_executable(steamshim
)
set_target_properties(steamshim PROPERTIES LINK_FLAGS "-Wl,-rpath,$ORIGIN -no-pie")
target_link_libraries(steamshim ${steamworks})
target_link_libraries(steamshim ${steamworks} SDL3::SDL3)

View file

@ -35,6 +35,8 @@ static inline void dbgpipe(const char *fmt, ...) {
}
#endif
#include <SDL3/SDL_messagebox.h>
/* platform-specific mainline calls this. */
static int mainline(void);
@ -50,29 +52,24 @@ static bool launchChild(ProcessType *pid);
static int closeProcess(ProcessType *pid);
#ifdef _WIN32
static void fail(const char *err)
{
static void fail(const char *err){
MessageBoxA(NULL, err, "ERROR", MB_ICONERROR | MB_OK);
ExitProcess(1);
} // fail
static bool writePipe(PipeType fd, const void *buf, const unsigned int _len)
{
static bool writePipe(PipeType fd, const void *buf, const unsigned int _len){
const DWORD len = (DWORD) _len;
DWORD bw = 0;
return ((WriteFile(fd, buf, len, &bw, NULL) != 0) && (bw == len));
} // writePipe
static int readPipe(PipeType fd, void *buf, const unsigned int _len)
{
static int readPipe(PipeType fd, void *buf, const unsigned int _len){
const DWORD len = (DWORD) _len;
DWORD br = 0;
return ReadFile(fd, buf, len, &br, NULL) ? (int) br : -1;
} // readPipe
static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
PipeType *pPipeChildRead, PipeType *pPipeChildWrite)
{
static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite, PipeType *pPipeChildRead, PipeType *pPipeChildWrite){
SECURITY_ATTRIBUTES pipeAttr;
pipeAttr.nLength = sizeof (pipeAttr);
@ -84,8 +81,7 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
pipeAttr.nLength = sizeof (pipeAttr);
pipeAttr.lpSecurityDescriptor = NULL;
pipeAttr.bInheritHandle = TRUE;
if (!CreatePipe(pPipeChildRead, pPipeParentWrite, &pipeAttr, 0))
{
if (!CreatePipe(pPipeChildRead, pPipeParentWrite, &pipeAttr, 0)){
CloseHandle(*pPipeParentRead);
CloseHandle(*pPipeChildWrite);
return 0;
@ -94,18 +90,15 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
return 1;
} // createPipes
static void closePipe(PipeType fd)
{
static void closePipe(PipeType fd){
CloseHandle(fd);
} // closePipe
static bool setEnvVar(const char *key, const char *val)
{
static bool setEnvVar(const char *key, const char *val){
return (SetEnvironmentVariableA(key, val) != 0);
} // setEnvVar
static LPWSTR genCommandLine()
{
static LPWSTR genCommandLine(){
// Construct a command line with the appropriate filename
LPWSTR cmdline = GetCommandLineW();
@ -113,21 +106,16 @@ static LPWSTR genCommandLine()
int iFirstArg = -1;
bool quote = false;
bool whitespace = false;
for (int i = 0; cmdline[i]; ++i)
{
if (cmdline[i] == '"' && (i == 0 || cmdline[i-1] != '\\'))
{
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'))
{
else if (!quote && (cmdline[i] == ' ' || cmdline[i] == '\t')){
whitespace = true;
}
else
{
if (whitespace)
{
else{
if (whitespace){
iFirstArg = i;
break;
}
@ -148,8 +136,7 @@ static LPWSTR genCommandLine()
return newcmdline;
}
static bool launchChild(ProcessType *pid)
{
static bool launchChild(ProcessType *pid){
STARTUPINFOW si;
memset(&si, 0, sizeof(si));
return CreateProcessW(TEXT(".\\" GAME_LAUNCH_NAME ".exe"),
@ -157,16 +144,13 @@ static bool launchChild(ProcessType *pid)
NULL, &si, pid);
} // launchChild
static int closeProcess(ProcessType *pid)
{
static int closeProcess(ProcessType *pid){
CloseHandle(pid->hProcess);
CloseHandle(pid->hThread);
return 0;
} // closeProcess
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
mainline();
ExitProcess(0);
return 0; // just in case.
@ -175,32 +159,27 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
#else // everyone else that isn't Windows.
static void fail(const char *err)
{
// !!! FIXME: zenity or something.
static void fail(const char *err){
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Steamshim parent error", err, NULL);
fprintf(stderr, "%s\n", err);
_exit(1);
} // fail
static bool writePipe(PipeType fd, const void *buf, const unsigned int _len)
{
static bool writePipe(PipeType fd, const void *buf, const unsigned int _len){
const ssize_t len = (ssize_t) _len;
ssize_t bw;
while (((bw = write(fd, buf, len)) == -1) && (errno == EINTR)) { /*spin*/ }
return (bw == len);
} // writePipe
static int readPipe(PipeType fd, void *buf, const unsigned int _len)
{
static int readPipe(PipeType fd, void *buf, const unsigned int _len){
const ssize_t len = (ssize_t) _len;
ssize_t br;
while (((br = read(fd, buf, len)) == -1) && (errno == EINTR)) { /*spin*/ }
return (int) br;
} // readPipe
static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
PipeType *pPipeChildRead, PipeType *pPipeChildWrite)
{
static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite, PipeType *pPipeChildRead, PipeType *pPipeChildWrite){
int fds[2];
if (pipe(fds) == -1)
return 0;
@ -209,8 +188,7 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
*pPipeParentRead = fds[0];
*pPipeChildWrite = fds[1];
if (pipe(fds) == -1)
{
if (pipe(fds) == -1){
close(*pPipeParentRead);
close(*pPipeChildWrite);
return 0;
@ -224,21 +202,18 @@ static bool createPipes(PipeType *pPipeParentRead, PipeType *pPipeParentWrite,
return 1;
} // createPipes
static void closePipe(PipeType fd)
{
static void closePipe(PipeType fd){
close(fd);
} // closePipe
static bool setEnvVar(const char *key, const char *val)
{
static bool setEnvVar(const char *key, const char *val){
return (setenv(key, val, 1) != -1);
} // setEnvVar
static int GArgc = 0;
static char **GArgv = NULL;
static bool launchChild(ProcessType *pid)
{
static bool launchChild(ProcessType *pid){
*pid = fork();
if (*pid == -1) // failed
return false;
@ -253,8 +228,7 @@ static bool launchChild(ProcessType *pid)
_exit(1);
} // launchChild
static int closeProcess(ProcessType *pid)
{
static int closeProcess(ProcessType *pid){
int rc = 0;
while ((waitpid(*pid, &rc, 0) == -1) && (errno == EINTR)) { /*spin*/ }
if (!WIFEXITED(rc))
@ -262,8 +236,7 @@ static int closeProcess(ProcessType *pid)
return WEXITSTATUS(rc);
} // closeProcess
int main(int argc, char **argv)
{
int main(int argc, char **argv){
signal(SIGPIPE, SIG_IGN);
GArgc = argc;
GArgv = argv;
@ -330,26 +303,22 @@ typedef enum ShimEvent
SHIMEVENT_GETCURRENTGAMELANGUAGE,
} ShimEvent;
static bool write1ByteCmd(PipeType fd, const uint8 b1)
{
static bool write1ByteCmd(PipeType fd, const uint8 b1){
const uint8 buf[] = { 1, b1 };
return writePipe(fd, buf, sizeof (buf));
} // write1ByteCmd
static bool write2ByteCmd(PipeType fd, const uint8 b1, const uint8 b2)
{
static bool write2ByteCmd(PipeType fd, const uint8 b1, const uint8 b2){
const uint8 buf[] = { 2, b1, b2 };
return writePipe(fd, buf, sizeof (buf));
} // write2ByteCmd
static bool write3ByteCmd(PipeType fd, const uint8 b1, const uint8 b2, const uint8 b3)
{
static bool write3ByteCmd(PipeType fd, const uint8 b1, const uint8 b2, const uint8 b3){
const uint8 buf[] = { 3, b1, b2, b3 };
return writePipe(fd, buf, sizeof (buf));
} // write3ByteCmd
static bool writeString(PipeType fd, ShimEvent event, const char *str)
{
static bool writeString(PipeType fd, ShimEvent event, const char *str){
uint8 buf[256];
buf[0] = strlen(str) + 2;
buf[1] = (uint8) event;
@ -357,26 +326,22 @@ static bool writeString(PipeType fd, ShimEvent event, const char *str)
return writePipe(fd, buf, buf[0] + 1);
} // writeString
static inline bool writeBye(PipeType fd)
{
static inline bool writeBye(PipeType fd){
dbgpipe("Parent sending SHIMEVENT_BYE().\n");
return write1ByteCmd(fd, SHIMEVENT_BYE);
} // writeBye
static inline bool writeStatsReceived(PipeType fd, const bool okay)
{
static inline bool writeStatsReceived(PipeType fd, const bool okay){
dbgpipe("Parent sending SHIMEVENT_STATSRECEIVED(%sokay).\n", okay ? "" : "!");
return write2ByteCmd(fd, SHIMEVENT_STATSRECEIVED, okay ? 1 : 0);
} // writeStatsReceived
static inline bool writeStatsStored(PipeType fd, const bool okay)
{
static inline bool writeStatsStored(PipeType fd, const bool okay){
dbgpipe("Parent sending SHIMEVENT_STATSSTORED(%sokay).\n", okay ? "" : "!");
return write2ByteCmd(fd, SHIMEVENT_STATSSTORED, okay ? 1 : 0);
} // writeStatsStored
static bool writeAchievementSet(PipeType fd, const char *name, const bool enable, const bool okay)
{
static bool writeAchievementSet(PipeType fd, const char *name, const bool enable, const bool okay){
uint8 buf[256];
uint8 *ptr = buf+1;
dbgpipe("Parent sending SHIMEVENT_SETACHIEVEMENT('%s', %senable, %sokay).\n", name, enable ? "" : "!", okay ? "" : "!");
@ -389,8 +354,7 @@ static bool writeAchievementSet(PipeType fd, const char *name, const bool enable
return writePipe(fd, buf, buf[0] + 1);
} // writeAchievementSet
static bool writeAchievementGet(PipeType fd, const char *name, const int status, const uint64 time)
{
static bool writeAchievementGet(PipeType fd, const char *name, const int status, const uint64 time){
uint8 buf[256];
uint8 *ptr = buf+1;
dbgpipe("Parent sending SHIMEVENT_GETACHIEVEMENT('%s', status %d, time " LLUFMT ").\n", name, status, (unsigned long long) time);
@ -404,14 +368,12 @@ static bool writeAchievementGet(PipeType fd, const char *name, const int status,
return writePipe(fd, buf, buf[0] + 1);
} // writeAchievementGet
static inline bool writeResetStats(PipeType fd, const bool alsoAch, const bool okay)
{
static inline bool writeResetStats(PipeType fd, const bool alsoAch, const bool okay){
dbgpipe("Parent sending SHIMEVENT_RESETSTATS(%salsoAchievements, %sokay).\n", alsoAch ? "" : "!", okay ? "" : "!");
return write3ByteCmd(fd, SHIMEVENT_RESETSTATS, alsoAch ? 1 : 0, okay ? 1 : 0);
} // writeResetStats
static bool writeStatThing(PipeType fd, const ShimEvent ev, const char *name, const void *val, const size_t vallen, const bool okay)
{
static bool writeStatThing(PipeType fd, const ShimEvent ev, const char *name, const void *val, const size_t vallen, const bool okay){
uint8 buf[256];
uint8 *ptr = buf+1;
*(ptr++) = (uint8) ev;
@ -424,26 +386,22 @@ static bool writeStatThing(PipeType fd, const ShimEvent ev, const char *name, co
return writePipe(fd, buf, buf[0] + 1);
} // writeStatThing
static inline bool writeSetStatI(PipeType fd, const char *name, const int32 val, const bool okay)
{
static inline bool writeSetStatI(PipeType fd, const char *name, const int32 val, const bool okay){
dbgpipe("Parent sending SHIMEVENT_SETSTATI('%s', val %d, %sokay).\n", name, (int) val, okay ? "" : "!");
return writeStatThing(fd, SHIMEVENT_SETSTATI, name, &val, sizeof (val), okay);
} // writeSetStatI
static inline bool writeSetStatF(PipeType fd, const char *name, const float val, const bool okay)
{
static inline bool writeSetStatF(PipeType fd, const char *name, const float val, const bool okay){
dbgpipe("Parent sending SHIMEVENT_SETSTATF('%s', val %f, %sokay).\n", name, val, okay ? "" : "!");
return writeStatThing(fd, SHIMEVENT_SETSTATF, name, &val, sizeof (val), okay);
} // writeSetStatF
static inline bool writeGetStatI(PipeType fd, const char *name, const int32 val, const bool okay)
{
static inline bool writeGetStatI(PipeType fd, const char *name, const int32 val, const bool okay){
dbgpipe("Parent sending SHIMEVENT_GETSTATI('%s', val %d, %sokay).\n", name, (int) val, okay ? "" : "!");
return writeStatThing(fd, SHIMEVENT_GETSTATI, name, &val, sizeof (val), okay);
} // writeGetStatI
static inline bool writeGetStatF(PipeType fd, const char *name, const float val, const bool okay)
{
static inline bool writeGetStatF(PipeType fd, const char *name, const float val, const bool okay){
dbgpipe("Parent sending SHIMEVENT_GETSTATF('%s', val %f, %sokay).\n", name, val, okay ? "" : "!");
return writeStatThing(fd, SHIMEVENT_GETSTATF, name, &val, sizeof (val), okay);
} // writeGetStatF
@ -457,22 +415,19 @@ SteamBridge::SteamBridge(PipeType _fd)
{
} // SteamBridge::SteamBridge
void SteamBridge::OnUserStatsReceived(UserStatsReceived_t *pCallback)
{
void SteamBridge::OnUserStatsReceived(UserStatsReceived_t *pCallback){
if (GAppID != pCallback->m_nGameID) return;
if (GUserID != pCallback->m_steamIDUser.ConvertToUint64()) return;
writeStatsReceived(fd, pCallback->m_eResult == k_EResultOK);
} // SteamBridge::OnUserStatsReceived
void SteamBridge::OnUserStatsStored(UserStatsStored_t *pCallback)
{
void SteamBridge::OnUserStatsStored(UserStatsStored_t *pCallback){
if (GAppID != pCallback->m_nGameID) return;
writeStatsStored(fd, pCallback->m_eResult == k_EResultOK);
} // SteamBridge::OnUserStatsStored
static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
{
static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd){
if (buflen == 0)
return true;
@ -522,8 +477,7 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
break;
case SHIMCMD_SETACHIEVEMENT:
if (buflen >= 2)
{
if (buflen >= 2){
const bool enable = (*(buf++) != 0);
const char *name = (const char *) buf; // !!! FIXME: buffer overflow possible.
if (!GSteamStats)
@ -538,8 +492,7 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
break;
case SHIMCMD_GETACHIEVEMENT:
if (buflen)
{
if (buflen){
const char *name = (const char *) buf; // !!! FIXME: buffer overflow possible.
bool ach = false;
uint32 t = 0;
@ -551,16 +504,14 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
break;
case SHIMCMD_RESETSTATS:
if (buflen)
{
if (buflen){
const bool alsoAch = (*(buf++) != 0);
writeResetStats(fd, alsoAch, (GSteamStats) && (GSteamStats->ResetAllStats(alsoAch)));
} // if
break;
case SHIMCMD_SETSTATI:
if (buflen >= 5)
{
if (buflen >= 5){
const int32 val = *((int32 *) buf);
buf += sizeof (int32);
const char *name = (const char *) buf; // !!! FIXME: buffer overflow possible.
@ -569,8 +520,7 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
break;
case SHIMCMD_GETSTATI:
if (buflen)
{
if (buflen){
const char *name = (const char *) buf; // !!! FIXME: buffer overflow possible.
int32 val = 0;
if ((GSteamStats) && (GSteamStats->GetStat(name, &val)))
@ -581,8 +531,7 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
break;
case SHIMCMD_SETSTATF:
if (buflen >= 5)
{
if (buflen >= 5){
const float val = *((float *) buf);
buf += sizeof (float);
const char *name = (const char *) buf; // !!! FIXME: buffer overflow possible.
@ -591,8 +540,7 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
break;
case SHIMCMD_GETSTATF:
if (buflen)
{
if (buflen){
const char *name = (const char *) buf; // !!! FIXME: buffer overflow possible.
float val = 0;
if ((GSteamStats) && (GSteamStats->GetStat(name, &val)))
@ -616,22 +564,17 @@ static bool processCommand(const uint8 *buf, unsigned int buflen, PipeType fd)
return true; // keep going.
} // processCommand
static void processCommands(PipeType pipeParentRead, PipeType pipeParentWrite)
{
static void processCommands(PipeType pipeParentRead, PipeType pipeParentWrite){
bool quit = false;
uint8 buf[256];
int br;
// this read blocks.
while (!quit && ((br = readPipe(pipeParentRead, buf, sizeof (buf))) > 0))
{
while (br > 0)
{
while (!quit && ((br = readPipe(pipeParentRead, buf, sizeof (buf))) > 0)){
while (br > 0){
const int cmdlen = (int) buf[0];
if ((br-1) >= cmdlen)
{
if (!processCommand(buf+1, cmdlen, pipeParentWrite))
{
if ((br-1) >= cmdlen){
if (!processCommand(buf+1, cmdlen, pipeParentWrite)){
quit = true;
break;
} // if
@ -643,8 +586,7 @@ static void processCommands(PipeType pipeParentRead, PipeType pipeParentWrite)
else // get more data.
{
const int morebr = readPipe(pipeParentRead, buf+br, sizeof (buf) - br);
if (morebr <= 0)
{
if (morebr <= 0){
quit = true; // uhoh.
break;
} // if
@ -654,8 +596,7 @@ static void processCommands(PipeType pipeParentRead, PipeType pipeParentWrite)
} // while
} // processCommands
static bool setEnvironmentVars(PipeType pipeChildRead, PipeType pipeChildWrite)
{
static bool setEnvironmentVars(PipeType pipeChildRead, PipeType pipeChildWrite){
char buf[64];
snprintf(buf, sizeof (buf), LLUFMT, (unsigned long long) pipeChildRead);
if (!setEnvVar("STEAMSHIM_READHANDLE", buf))
@ -668,8 +609,7 @@ static bool setEnvironmentVars(PipeType pipeChildRead, PipeType pipeChildWrite)
return true;
} // setEnvironmentVars
static bool initSteamworks(PipeType fd)
{
static bool initSteamworks(PipeType fd){
// this can fail for many reasons:
// - you forgot a steam_appid.txt in the current working directory.
// - you don't have Steam running
@ -690,8 +630,7 @@ static bool initSteamworks(PipeType fd)
return 1;
} // initSteamworks
static void deinitSteamworks(void)
{
static void deinitSteamworks(void){
SteamAPI_Shutdown();
delete GSteamBridge;
GSteamBridge = NULL;
@ -700,8 +639,7 @@ static void deinitSteamworks(void)
GSteamUser = NULL;
} // deinitSteamworks
static int mainline(void)
{
static int mainline(void){
PipeType pipeParentRead = NULLPIPE;
PipeType pipeParentWrite = NULLPIPE;
PipeType pipeChildRead = NULLPIPE;

View file

@ -1,2 +1,2 @@
#!/bin/bash
#!/bin/sh
curl -s https://raw.githubusercontent.com/mdqinc/SDL_GameControllerDB/refs/heads/master/gamecontrollerdb.txt > assets/gamecontrollerdb.txt