Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ set(PHYSFS_SRCS
src/physfs_platform_dos.c
src/physfs_platform_emscripten.c
src/physfs_platform_posix.c
src/physfs_platform_sdl3.c
src/physfs_platform_unix.c
src/physfs_platform_windows.c
src/physfs_platform_ogc.c
Expand Down Expand Up @@ -193,6 +194,11 @@ if(NOT PHYSFS_ARCHIVE_POD)
add_definitions(-DPHYSFS_SUPPORTS_POD=0)
endif()

option(PHYSFS_PLATFORM_SDL3 "Enable building for the SDL3 file system" FALSE)
if(PHYSFS_PLATFORM_SDL3)
add_definitions(-DPHYSFS_PLATFORM_SDL3=1)
endif()

if(EMSCRIPTEN)
set(PHYSFS_EMSCRIPTEN_STORAGE_PATH "" CACHE STRING "Specify a path for prefdir on Emscripten")
if(NOT PHYSFS_EMSCRIPTEN_STORAGE_PATH STREQUAL "")
Expand Down
251 changes: 251 additions & 0 deletions src/physfs_platform_sdl3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
/*
* SDL3 support routines for PhysicsFS.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* This file written by Rob Loach (@RobLoach).
*/

#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"

#ifdef PHYSFS_PLATFORM_SDL3

#include <SDL3/SDL.h>

/**
* Context for enumeration.
*
* @see __PHYSFS_platformEnumerate()
*/
typedef struct platformEnumerateContext
{
PHYSFS_EnumerateCallback callback;
const char *origdir;
void *callbackdata;
PHYSFS_EnumerateCallbackResult result;
} platformEnumerateContext;

int __PHYSFS_platformInit(const char *argv0)
{
(void)argv0;
return 1; /* always succeed. */
} /* __PHYSFS_platformInit */

void __PHYSFS_platformDeinit(void)
{
/* no-op */
} /* __PHYSFS_platformDeinit */

void *__PHYSFS_platformGetThreadID(void)
{
return (void *)(size_t)SDL_GetCurrentThreadID();
} /* __PHYSFS_platformGetThreadID */

void *__PHYSFS_platformCreateMutex(void)
{
return (void *)SDL_CreateMutex();
} /* __PHYSFS_platformCreateMutex */

void __PHYSFS_platformDestroyMutex(void *mutex)
{
SDL_DestroyMutex((SDL_Mutex *)mutex);
} /* __PHYSFS_platformDestroyMutex */

int __PHYSFS_platformGrabMutex(void *mutex)
{
SDL_LockMutex((SDL_Mutex *)mutex);
return 1;
} /* __PHYSFS_platformGrabMutex */

void __PHYSFS_platformReleaseMutex(void *mutex)
{
SDL_UnlockMutex((SDL_Mutex *)mutex);
} /* __PHYSFS_platformReleaseMutex */

/**
* Not supported by SDL3.
*/
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
{
(void)cb;
(void)data;
} /* __PHYSFS_platformDetectAvailableCDs */

char *__PHYSFS_platformCalcBaseDir(const char *argv0)
{
const char *base = SDL_GetBasePath();
(void)argv0;
BAIL_IF(base == NULL, PHYSFS_ERR_OS_ERROR, NULL);
return __PHYSFS_strdup(base);
} /* __PHYSFS_platformCalcBaseDir */

char *__PHYSFS_platformCalcUserDir(void)
{
const char *home = SDL_GetUserFolder(SDL_FOLDER_HOME);
BAIL_IF(home == NULL, PHYSFS_ERR_OS_ERROR, NULL);
return __PHYSFS_strdup(home);
} /* __PHYSFS_platformCalcUserDir */

char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app)
{
char *out = SDL_GetPrefPath(org, app);
BAIL_IF(out == NULL, PHYSFS_ERR_OS_ERROR, NULL);
/* Unlike SDL_GetBasePath() or SDL_GetUserFolder(), SDL_GetPrefPath() allocates the string for us. */
return out;
} /* __PHYSFS_platformCalcPrefDir */

static SDL_EnumerationResult SDLCALL platformEnumerateCallback(void *userdata,
const char *dirname,
const char *fname)
{
platformEnumerateContext *ctx = (platformEnumerateContext *)userdata;
(void)dirname;

ctx->result = ctx->callback(ctx->callbackdata, ctx->origdir, fname);

switch (ctx->result) {
case PHYSFS_ENUM_OK: return SDL_ENUM_CONTINUE;
case PHYSFS_ENUM_STOP: return SDL_ENUM_SUCCESS;
case PHYSFS_ENUM_ERROR: return SDL_ENUM_FAILURE;
}
return SDL_ENUM_FAILURE;
} /* platformEnumerateCallback */

PHYSFS_EnumerateCallbackResult __PHYSFS_platformEnumerate(const char *dirname,
PHYSFS_EnumerateCallback callback,
const char *origdir,
void *callbackdata)
{
platformEnumerateContext ctx;
ctx.callback = callback;
ctx.origdir = origdir;
ctx.callbackdata = callbackdata;
ctx.result = PHYSFS_ENUM_OK;

BAIL_IF(!SDL_EnumerateDirectory(dirname, platformEnumerateCallback, &ctx),
/* Determine the correct PhysFS error to report. */
ctx.result == PHYSFS_ENUM_ERROR ? PHYSFS_ERR_APP_CALLBACK : PHYSFS_ERR_OS_ERROR,
PHYSFS_ENUM_ERROR);

return ctx.result;
} /* __PHYSFS_platformEnumerate */

int __PHYSFS_platformMkDir(const char *path)
{
BAIL_IF(!SDL_CreateDirectory(path), PHYSFS_ERR_OS_ERROR, 0);
return 1;
} /* __PHYSFS_platformMkDir */

int __PHYSFS_platformDelete(const char *path)
{
BAIL_IF(!SDL_RemovePath(path), PHYSFS_ERR_OS_ERROR, 0);
return 1;
} /* __PHYSFS_platformDelete */

int __PHYSFS_platformStat(const char *fn, PHYSFS_Stat *stat, const int follow)
{
SDL_PathInfo info;
(void)follow;

BAIL_IF(!SDL_GetPathInfo(fn, &info), PHYSFS_ERR_NOT_FOUND, 0);

switch (info.type) {
case SDL_PATHTYPE_FILE:
stat->filetype = PHYSFS_FILETYPE_REGULAR;
stat->filesize = (PHYSFS_sint64)info.size;
break;
case SDL_PATHTYPE_DIRECTORY:
stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
stat->filesize = 0;
break;
case SDL_PATHTYPE_OTHER:
stat->filetype = PHYSFS_FILETYPE_OTHER;
stat->filesize = -1;
break;
case SDL_PATHTYPE_NONE:
default:
BAIL(PHYSFS_ERR_NOT_FOUND, 0);
}

stat->accesstime = (PHYSFS_sint64)(info.access_time / SDL_NS_PER_SECOND);
stat->createtime = (PHYSFS_sint64)(info.create_time / SDL_NS_PER_SECOND);
stat->modtime = (PHYSFS_sint64)(info.modify_time / SDL_NS_PER_SECOND);
stat->readonly = 0;
return 1;
} /* __PHYSFS_platformStat */

static void *doOpen(const char *filename, const char* mode)
{
SDL_IOStream *io = SDL_IOFromFile(filename, mode);
BAIL_IF(io == NULL, PHYSFS_ERR_OS_ERROR, NULL);
return io;
} /* doOpen */

void *__PHYSFS_platformOpenRead(const char *filename)
{
return doOpen(filename, "rb");
} /* __PHYSFS_platformOpenRead */

void *__PHYSFS_platformOpenWrite(const char *filename)
{
return doOpen(filename, "wb");
} /* __PHYSFS_platformOpenWrite */

void *__PHYSFS_platformOpenAppend(const char *filename)
{
return doOpen(filename, "ab");
} /* __PHYSFS_platformOpenAppend */

PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len)
{
SDL_IOStream *io = (SDL_IOStream *)opaque;
size_t size = (size_t)len;
size_t rc = SDL_ReadIO(io, buf, size);
BAIL_IF(rc < size && SDL_GetIOStatus(io) == SDL_IO_STATUS_ERROR, PHYSFS_ERR_IO, -1);
return (PHYSFS_sint64)rc;
} /* __PHYSFS_platformRead */

PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buf, PHYSFS_uint64 len)
{
SDL_IOStream *io = (SDL_IOStream *)opaque;
size_t size = (size_t)len;
size_t rc = SDL_WriteIO(io, buf, size);
BAIL_IF(rc < size && SDL_GetIOStatus(io) == SDL_IO_STATUS_ERROR, PHYSFS_ERR_IO, -1);
return (PHYSFS_sint64)rc;
} /* __PHYSFS_platformWrite */

int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos)
{
BAIL_IF(SDL_SeekIO((SDL_IOStream *)opaque, (Sint64)pos, SDL_IO_SEEK_SET) < 0, PHYSFS_ERR_IO, 0);
return 1;
} /* __PHYSFS_platformSeek */

PHYSFS_sint64 __PHYSFS_platformTell(void *opaque)
{
Sint64 pos = SDL_TellIO((SDL_IOStream *)opaque);
BAIL_IF(pos < 0, PHYSFS_ERR_IO, -1);
return (PHYSFS_sint64)pos;
} /* __PHYSFS_platformTell */

PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
{
Sint64 size = SDL_GetIOSize((SDL_IOStream *)opaque);
BAIL_IF(size < 0, PHYSFS_ERR_IO, -1);
return (PHYSFS_sint64)size;
} /* __PHYSFS_platformFileLength */

int __PHYSFS_platformFlush(void *opaque)
{
BAIL_IF(!SDL_FlushIO((SDL_IOStream *)opaque), PHYSFS_ERR_IO, 0);
return 1;
} /* __PHYSFS_platformFlush */

void __PHYSFS_platformClose(void *opaque)
{
if (!SDL_CloseIO((SDL_IOStream *)opaque)) {
SDL_ClearError();
}
} /* __PHYSFS_platformClose */

#endif
4 changes: 3 additions & 1 deletion src/physfs_platforms.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
* PHYSFS_PLATFORM_UNIX on that system.
*/

#if defined(TARGET_EXTENSION) && (defined(TARGET_PLAYDATE) || defined(TARGET_SIMULATOR))
#if defined(PHYSFS_PLATFORM_SDL3)
#define PHYSFS_NO_CDROM_SUPPORT 1
#elif defined(TARGET_EXTENSION) && (defined(TARGET_PLAYDATE) || defined(TARGET_SIMULATOR))
# define PHYSFS_PLATFORM_PLAYDATE 1
# define PHYSFS_NO_CRUNTIME_MALLOC 1
#elif (defined __EMSCRIPTEN__)
Expand Down
Loading