mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-29 16:09:13 +00:00
Add SDL_storage
This commit is contained in:
parent
4fc749443f
commit
744227e6ab
16 changed files with 1035 additions and 0 deletions
|
@ -494,6 +494,7 @@ sdl_glob_sources(
|
||||||
"${SDL3_SOURCE_DIR}/src/render/*/*.c"
|
"${SDL3_SOURCE_DIR}/src/render/*/*.c"
|
||||||
"${SDL3_SOURCE_DIR}/src/sensor/*.c"
|
"${SDL3_SOURCE_DIR}/src/sensor/*.c"
|
||||||
"${SDL3_SOURCE_DIR}/src/stdlib/*.c"
|
"${SDL3_SOURCE_DIR}/src/stdlib/*.c"
|
||||||
|
"${SDL3_SOURCE_DIR}/src/storage/*.c"
|
||||||
"${SDL3_SOURCE_DIR}/src/thread/*.c"
|
"${SDL3_SOURCE_DIR}/src/thread/*.c"
|
||||||
"${SDL3_SOURCE_DIR}/src/timer/*.c"
|
"${SDL3_SOURCE_DIR}/src/timer/*.c"
|
||||||
"${SDL3_SOURCE_DIR}/src/video/*.c"
|
"${SDL3_SOURCE_DIR}/src/video/*.c"
|
||||||
|
@ -1753,6 +1754,14 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
|
||||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/unix/*.c")
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/unix/*.c")
|
||||||
set(HAVE_SDL_FILESYSTEM TRUE)
|
set(HAVE_SDL_FILESYSTEM TRUE)
|
||||||
|
|
||||||
|
set(SDL_STORAGE_GENERIC 1)
|
||||||
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c")
|
||||||
|
if(LINUX)
|
||||||
|
set(SDL_STORAGE_STEAM 1)
|
||||||
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/steam/*.c")
|
||||||
|
endif()
|
||||||
|
set(HAVE_SDL_STORAGE 1)
|
||||||
|
|
||||||
set(SDL_TIMER_UNIX 1)
|
set(SDL_TIMER_UNIX 1)
|
||||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c")
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/timer/unix/*.c")
|
||||||
set(HAVE_SDL_TIMERS TRUE)
|
set(HAVE_SDL_TIMERS TRUE)
|
||||||
|
@ -1972,6 +1981,14 @@ elseif(WINDOWS)
|
||||||
endif()
|
endif()
|
||||||
set(HAVE_SDL_FILESYSTEM TRUE)
|
set(HAVE_SDL_FILESYSTEM TRUE)
|
||||||
|
|
||||||
|
set(SDL_STORAGE_GENERIC 1)
|
||||||
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c")
|
||||||
|
if(NOT WINDOWS_STORE)
|
||||||
|
set(SDL_STORAGE_STEAM 1)
|
||||||
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/steam/*.c")
|
||||||
|
endif()
|
||||||
|
set(HAVE_SDL_STORAGE 1)
|
||||||
|
|
||||||
# Libraries for Win32 native and MinGW
|
# Libraries for Win32 native and MinGW
|
||||||
if(NOT WINDOWS_STORE)
|
if(NOT WINDOWS_STORE)
|
||||||
sdl_link_dependency(base LIBS kernel32 user32 gdi32 winmm imm32 ole32 oleaut32 version uuid advapi32 setupapi shell32)
|
sdl_link_dependency(base LIBS kernel32 user32 gdi32 winmm imm32 ole32 oleaut32 version uuid advapi32 setupapi shell32)
|
||||||
|
@ -2204,6 +2221,15 @@ elseif(APPLE)
|
||||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/cocoa/*.m")
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/cocoa/*.m")
|
||||||
set(HAVE_SDL_FILESYSTEM TRUE)
|
set(HAVE_SDL_FILESYSTEM TRUE)
|
||||||
|
|
||||||
|
# TODO: SDL_STORAGE_ICLOUD
|
||||||
|
set(SDL_STORAGE_GENERIC 1)
|
||||||
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c")
|
||||||
|
if(DARWIN OR MACOSX)
|
||||||
|
set(SDL_STORAGE_STEAM 1)
|
||||||
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/steam/*.c")
|
||||||
|
endif()
|
||||||
|
set(HAVE_SDL_STORAGE 1)
|
||||||
|
|
||||||
if(SDL_SENSOR)
|
if(SDL_SENSOR)
|
||||||
if(IOS OR VISIONOS)
|
if(IOS OR VISIONOS)
|
||||||
set(SDL_SENSOR_COREMOTION 1)
|
set(SDL_SENSOR_COREMOTION 1)
|
||||||
|
@ -2820,6 +2846,10 @@ if(NOT HAVE_SDL_FILESYSTEM)
|
||||||
set(SDL_FILESYSTEM_DUMMY 1)
|
set(SDL_FILESYSTEM_DUMMY 1)
|
||||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/*.c")
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/dummy/*.c")
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT HAVE_SDL_STORAGE)
|
||||||
|
set(SDL_STORAGE_GENERIC 1)
|
||||||
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c")
|
||||||
|
endif()
|
||||||
if(NOT HAVE_SDL_LOCALE)
|
if(NOT HAVE_SDL_LOCALE)
|
||||||
set(SDL_LOCALE_DUMMY 1)
|
set(SDL_LOCALE_DUMMY 1)
|
||||||
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/dummy/*.c")
|
sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/dummy/*.c")
|
||||||
|
|
|
@ -368,6 +368,7 @@
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_scancode.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_scancode.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_sensor.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_sensor.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_stdinc.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_stdinc.h" />
|
||||||
|
<ClInclude Include="..\..\include\SDL3\SDL_storage.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_surface.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_surface.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_system.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_system.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_test.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_test.h" />
|
||||||
|
@ -778,6 +779,8 @@
|
||||||
<ClCompile Include="..\..\src\stdlib\SDL_stdlib.c" />
|
<ClCompile Include="..\..\src\stdlib\SDL_stdlib.c" />
|
||||||
<ClCompile Include="..\..\src\stdlib\SDL_string.c" />
|
<ClCompile Include="..\..\src\stdlib\SDL_string.c" />
|
||||||
<ClCompile Include="..\..\src\stdlib\SDL_strtokr.c" />
|
<ClCompile Include="..\..\src\stdlib\SDL_strtokr.c" />
|
||||||
|
<ClCompile Include="..\..\src\storage\generic\SDL_genericstorage.c" />
|
||||||
|
<ClCompile Include="..\..\src\storage\SDL_storage.c" />
|
||||||
<ClCompile Include="..\..\src\thread\generic\SDL_syscond.c" />
|
<ClCompile Include="..\..\src\thread\generic\SDL_syscond.c" />
|
||||||
<ClCompile Include="..\..\src\thread\generic\SDL_sysrwlock.c" />
|
<ClCompile Include="..\..\src\thread\generic\SDL_sysrwlock.c" />
|
||||||
<ClCompile Include="..\..\src\thread\SDL_thread.c" />
|
<ClCompile Include="..\..\src\thread\SDL_thread.c" />
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
<ClInclude Include="..\include\SDL3\SDL_scancode.h" />
|
<ClInclude Include="..\include\SDL3\SDL_scancode.h" />
|
||||||
<ClInclude Include="..\include\SDL3\SDL_sensor.h" />
|
<ClInclude Include="..\include\SDL3\SDL_sensor.h" />
|
||||||
<ClInclude Include="..\include\SDL3\SDL_stdinc.h" />
|
<ClInclude Include="..\include\SDL3\SDL_stdinc.h" />
|
||||||
|
<ClInclude Include="..\include\SDL3\SDL_storage.h" />
|
||||||
<ClInclude Include="..\include\SDL3\SDL_surface.h" />
|
<ClInclude Include="..\include\SDL3\SDL_surface.h" />
|
||||||
<ClInclude Include="..\include\SDL3\SDL_system.h" />
|
<ClInclude Include="..\include\SDL3\SDL_system.h" />
|
||||||
<ClInclude Include="..\include\SDL3\SDL_thread.h" />
|
<ClInclude Include="..\include\SDL3\SDL_thread.h" />
|
||||||
|
@ -439,6 +440,8 @@
|
||||||
<ClCompile Include="..\src\stdlib\SDL_stdlib.c" />
|
<ClCompile Include="..\src\stdlib\SDL_stdlib.c" />
|
||||||
<ClCompile Include="..\src\stdlib\SDL_string.c" />
|
<ClCompile Include="..\src\stdlib\SDL_string.c" />
|
||||||
<ClCompile Include="..\src\stdlib\SDL_strtokr.c" />
|
<ClCompile Include="..\src\stdlib\SDL_strtokr.c" />
|
||||||
|
<ClCompile Include="..\src\storage\generic\SDL_genericstorage.c" />
|
||||||
|
<ClCompile Include="..\src\storage\SDL_storage.c" />
|
||||||
<ClCompile Include="..\src\thread\generic\SDL_syssem.c" />
|
<ClCompile Include="..\src\thread\generic\SDL_syssem.c" />
|
||||||
<ClCompile Include="..\src\thread\SDL_thread.c" />
|
<ClCompile Include="..\src\thread\SDL_thread.c" />
|
||||||
<ClCompile Include="..\src\thread\stdcpp\SDL_syscond.cpp">
|
<ClCompile Include="..\src\thread\stdcpp\SDL_syscond.cpp">
|
||||||
|
|
|
@ -291,6 +291,7 @@
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_scancode.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_scancode.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_sensor.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_sensor.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_stdinc.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_stdinc.h" />
|
||||||
|
<ClInclude Include="..\..\include\SDL3\SDL_storage.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_surface.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_surface.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_system.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_system.h" />
|
||||||
<ClInclude Include="..\..\include\SDL3\SDL_test.h" />
|
<ClInclude Include="..\..\include\SDL3\SDL_test.h" />
|
||||||
|
@ -635,6 +636,9 @@
|
||||||
<ClCompile Include="..\..\src\stdlib\SDL_stdlib.c" />
|
<ClCompile Include="..\..\src\stdlib\SDL_stdlib.c" />
|
||||||
<ClCompile Include="..\..\src\stdlib\SDL_string.c" />
|
<ClCompile Include="..\..\src\stdlib\SDL_string.c" />
|
||||||
<ClCompile Include="..\..\src\stdlib\SDL_strtokr.c" />
|
<ClCompile Include="..\..\src\stdlib\SDL_strtokr.c" />
|
||||||
|
<ClCompile Include="..\..\src\storage\generic\SDL_genericstorage.c" />
|
||||||
|
<ClCompile Include="..\..\src\storage\steam\SDL_steamstorage.c" />
|
||||||
|
<ClCompile Include="..\..\src\storage\SDL_storage.c" />
|
||||||
<ClCompile Include="..\..\src\thread\generic\SDL_syscond.c" />
|
<ClCompile Include="..\..\src\thread\generic\SDL_syscond.c" />
|
||||||
<ClCompile Include="..\..\src\thread\generic\SDL_sysrwlock.c" />
|
<ClCompile Include="..\..\src\thread\generic\SDL_sysrwlock.c" />
|
||||||
<ClCompile Include="..\..\src\thread\SDL_thread.c" />
|
<ClCompile Include="..\..\src\thread\SDL_thread.c" />
|
||||||
|
|
|
@ -71,6 +71,7 @@
|
||||||
#include <SDL3/SDL_iostream.h>
|
#include <SDL3/SDL_iostream.h>
|
||||||
#include <SDL3/SDL_scancode.h>
|
#include <SDL3/SDL_scancode.h>
|
||||||
#include <SDL3/SDL_sensor.h>
|
#include <SDL3/SDL_sensor.h>
|
||||||
|
#include <SDL3/SDL_storage.h>
|
||||||
#include <SDL3/SDL_surface.h>
|
#include <SDL3/SDL_surface.h>
|
||||||
#include <SDL3/SDL_system.h>
|
#include <SDL3/SDL_system.h>
|
||||||
#include <SDL3/SDL_thread.h>
|
#include <SDL3/SDL_thread.h>
|
||||||
|
|
|
@ -1904,6 +1904,24 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT"
|
#define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variable that specifies a backend to use for title storage.
|
||||||
|
*
|
||||||
|
* By default, SDL will try all available storage backends in a reasonable order until it finds one that can work, but this hint allows the app or user to force a specific target, such as "pc" if, say, you are on Steam but want to avoid SteamRemoteStorage for title data.
|
||||||
|
*
|
||||||
|
* This hint should be set before SDL is initialized.
|
||||||
|
*/
|
||||||
|
#define SDL_HINT_STORAGE_TITLE_DRIVER "SDL_STORAGE_TITLE_DRIVER"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variable that specifies a backend to use for user storage.
|
||||||
|
*
|
||||||
|
* By default, SDL will try all available storage backends in a reasonable order until it finds one that can work, but this hint allows the app or user to force a specific target, such as "pc" if, say, you are on Steam but want to avoid SteamRemoteStorage for user data.
|
||||||
|
*
|
||||||
|
* This hint should be set before SDL is initialized.
|
||||||
|
*/
|
||||||
|
#define SDL_HINT_STORAGE_USER_DRIVER "SDL_STORAGE_USER_DRIVER"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime.
|
* Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime.
|
||||||
*
|
*
|
||||||
|
|
276
include/SDL3/SDL_storage.h
Normal file
276
include/SDL3/SDL_storage.h
Normal file
|
@ -0,0 +1,276 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file SDL_storage.h
|
||||||
|
*
|
||||||
|
* Include file for storage container SDL API functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_storage_h_
|
||||||
|
#define SDL_storage_h_
|
||||||
|
|
||||||
|
#include <SDL3/SDL_stdinc.h>
|
||||||
|
#include <SDL3/SDL_mutex.h>
|
||||||
|
#include <SDL3/SDL_properties.h>
|
||||||
|
|
||||||
|
#include <SDL3/SDL_begin_code.h>
|
||||||
|
|
||||||
|
/* Set up for C function definitions, even when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* !!! FIXME: Don't let this ship without async R/W support!!! */
|
||||||
|
|
||||||
|
typedef struct SDL_StorageInterface
|
||||||
|
{
|
||||||
|
int (SDLCALL *close)(void *userdata);
|
||||||
|
|
||||||
|
SDL_bool (SDLCALL *ready)(void *userdata);
|
||||||
|
|
||||||
|
int (SDLCALL *fileSize)(void *userdata, const char *path, Uint64 *length);
|
||||||
|
|
||||||
|
int (SDLCALL *readFile)(void *userdata, const char *path, void *destination, Uint64 length);
|
||||||
|
|
||||||
|
int (SDLCALL *writeFile)(void *userdata, const char *path, const void *source, Uint64 length);
|
||||||
|
|
||||||
|
Uint64 (SDLCALL *spaceRemaining)(void *userdata);
|
||||||
|
} SDL_StorageInterface;
|
||||||
|
|
||||||
|
typedef struct SDL_Storage SDL_Storage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens up a read-only container for the application's filesystem.
|
||||||
|
*
|
||||||
|
* \param override a path to override the backend's default title root
|
||||||
|
* \param props a property list that may contain backend-specific information
|
||||||
|
* \returns a title storage container on success or NULL on failure; call
|
||||||
|
* SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenUserStorage
|
||||||
|
* \sa SDL_OpenStorage
|
||||||
|
* \sa SDL_TitleStorageReady
|
||||||
|
* \sa SDL_CloseStorage
|
||||||
|
* \sa SDL_StorageReady
|
||||||
|
* \sa SDL_StorageFileSize
|
||||||
|
* \sa SDL_StorageReadFile
|
||||||
|
* \sa SDL_StorageWriteFile
|
||||||
|
* \sa SDL_StorageSpaceRemaining
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenTitleStorage(const char *override, SDL_PropertiesID props);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens up a container for a user's unique read/write filesystem.
|
||||||
|
*
|
||||||
|
* While title storage can generally be kept open throughout runtime, user
|
||||||
|
* storage should only be opened when the client is ready to read/write files.
|
||||||
|
* This allows the backend to properly batch R/W operations and flush them when
|
||||||
|
* the container has been closed; ensuring safe and optimal save I/O.
|
||||||
|
*
|
||||||
|
* \param org the name of your organization
|
||||||
|
* \param app the name of your application
|
||||||
|
* \param props a property list that may contain backend-specific information
|
||||||
|
* \returns a user storage container on success or NULL on failure; call
|
||||||
|
* SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenTitleStorage
|
||||||
|
* \sa SDL_OpenStorage
|
||||||
|
* \sa SDL_CloseStorage
|
||||||
|
* \sa SDL_StorageReady
|
||||||
|
* \sa SDL_StorageFileSize
|
||||||
|
* \sa SDL_StorageReadFile
|
||||||
|
* \sa SDL_StorageWriteFile
|
||||||
|
* \sa SDL_StorageSpaceRemaining
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenUserStorage(const char *org, const char *app, SDL_PropertiesID props);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens up a container using a client-provided storage interface.
|
||||||
|
*
|
||||||
|
* Applications do not need to use this function unless they are providing
|
||||||
|
* their own SDL_Storage implementation. If you just need an
|
||||||
|
* SDL_Storage, you should use the built-in implementations in SDL,
|
||||||
|
* like SDL_OpenTitleStorage() or SDL_OpenUserStorage().
|
||||||
|
*
|
||||||
|
* \param iface the function table to be used by this container
|
||||||
|
* \param userdata the pointer that will be passed to the store interface
|
||||||
|
* \returns a storage container on success or NULL on failure; call
|
||||||
|
* SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenTitleStorage
|
||||||
|
* \sa SDL_OpenUserStorage
|
||||||
|
* \sa SDL_CloseStorage
|
||||||
|
* \sa SDL_StorageReady
|
||||||
|
* \sa SDL_StorageFileSize
|
||||||
|
* \sa SDL_StorageReadFile
|
||||||
|
* \sa SDL_StorageWriteFile
|
||||||
|
* \sa SDL_StorageSpaceRemaining
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenStorage(const SDL_StorageInterface *iface, void *userdata);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes and frees a storage container.
|
||||||
|
*
|
||||||
|
* \param storage a storage container to close
|
||||||
|
* \returns 0 if the container was freed with no errors, a negative value
|
||||||
|
* otherwise; call SDL_GetError() for more information. Even if the
|
||||||
|
* function returns an error, the container data will be freed; the
|
||||||
|
* error is only for informational purposes.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenTitleStorage
|
||||||
|
* \sa SDL_OpenUserStorage
|
||||||
|
* \sa SDL_OpenStorage
|
||||||
|
* \sa SDL_StorageReady
|
||||||
|
* \sa SDL_StorageFileSize
|
||||||
|
* \sa SDL_StorageReadFile
|
||||||
|
* \sa SDL_StorageWriteFile
|
||||||
|
* \sa SDL_StorageSpaceRemaining
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL SDL_CloseStorage(SDL_Storage *storage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the storage container is ready to use.
|
||||||
|
*
|
||||||
|
* This function should be called in regular intervals until it returns
|
||||||
|
* SDL_TRUE - however, it is not recommended to spinwait on this call, as
|
||||||
|
* the backend may depend on a synchronous message loop.
|
||||||
|
*
|
||||||
|
* \param storage a storage container to query
|
||||||
|
* \returns SDL_TRUE if the container is ready, SDL_FALSE otherwise
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenTitleStorage
|
||||||
|
* \sa SDL_OpenUserStorage
|
||||||
|
* \sa SDL_OpenStorage
|
||||||
|
* \sa SDL_CloseStorage
|
||||||
|
* \sa SDL_StorageFileSize
|
||||||
|
* \sa SDL_StorageReadFile
|
||||||
|
* \sa SDL_StorageWriteFile
|
||||||
|
* \sa SDL_StorageSpaceRemaining
|
||||||
|
*/
|
||||||
|
extern DECLSPEC SDL_bool SDLCALL SDL_StorageReady(SDL_Storage *storage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query the size of a file within a storage container.
|
||||||
|
*
|
||||||
|
* \param storage a storage container to query
|
||||||
|
* \param path the relative path of the file to query
|
||||||
|
* \param length a pointer to be filled with the file's length
|
||||||
|
* \returns 0 if the file could be queried, a negative value otherwise; call
|
||||||
|
* SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenTitleStorage
|
||||||
|
* \sa SDL_OpenUserStorage
|
||||||
|
* \sa SDL_OpenStorage
|
||||||
|
* \sa SDL_CloseStorage
|
||||||
|
* \sa SDL_StorageReady
|
||||||
|
* \sa SDL_StorageReadFile
|
||||||
|
* \sa SDL_StorageWriteFile
|
||||||
|
* \sa SDL_StorageSpaceRemaining
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL SDL_StorageFileSize(SDL_Storage *storage, const char *path, Uint64 *length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously read a file from a storage container into a client-provided buffer.
|
||||||
|
*
|
||||||
|
* \param storage a storage container to read from
|
||||||
|
* \param path the relative path of the file to read
|
||||||
|
* \param destination a client-provided buffer to read the file into
|
||||||
|
* \param length the length of the destination buffer
|
||||||
|
* \returns 0 if the file was read, a negative value otherwise; call
|
||||||
|
* SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenTitleStorage
|
||||||
|
* \sa SDL_OpenUserStorage
|
||||||
|
* \sa SDL_OpenStorage
|
||||||
|
* \sa SDL_CloseStorage
|
||||||
|
* \sa SDL_StorageReady
|
||||||
|
* \sa SDL_StorageFileSize
|
||||||
|
* \sa SDL_StorageWriteFile
|
||||||
|
* \sa SDL_StorageSpaceRemaining
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDLCALL SDL_StorageReadFile(SDL_Storage *storage, const char *path, void *destination, Uint64 length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously write a file from client memory into a storage container.
|
||||||
|
*
|
||||||
|
* \param storage a storage container to write to
|
||||||
|
* \param path the relative path of the file to write
|
||||||
|
* \param source a client-provided buffer to write from
|
||||||
|
* \param length the length of the source buffer
|
||||||
|
* \returns 0 if the file was written, a negative value otherwise; call
|
||||||
|
* SDL_GetError() for more information.
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenTitleStorage
|
||||||
|
* \sa SDL_OpenUserStorage
|
||||||
|
* \sa SDL_OpenStorage
|
||||||
|
* \sa SDL_CloseStorage
|
||||||
|
* \sa SDL_StorageReady
|
||||||
|
* \sa SDL_StorageFileSize
|
||||||
|
* \sa SDL_StorageReadFile
|
||||||
|
* \sa SDL_StorageSpaceRemaining
|
||||||
|
*/
|
||||||
|
extern DECLSPEC int SDL_StorageWriteFile(SDL_Storage *storage, const char *path, const void *source, Uint64 length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries the remaining space in a storage container.
|
||||||
|
*
|
||||||
|
* \param storage a storage container to query
|
||||||
|
* \returns the amount of remaining space, in bytes
|
||||||
|
*
|
||||||
|
* \since This function is available since SDL 3.0.0.
|
||||||
|
*
|
||||||
|
* \sa SDL_OpenTitleStorage
|
||||||
|
* \sa SDL_OpenUserStorage
|
||||||
|
* \sa SDL_OpenStorage
|
||||||
|
* \sa SDL_CloseStorage
|
||||||
|
* \sa SDL_StorageReady
|
||||||
|
* \sa SDL_StorageFileSize
|
||||||
|
* \sa SDL_StorageReadFile
|
||||||
|
* \sa SDL_StorageReadFileAsync
|
||||||
|
* \sa SDL_StorageWriteFile
|
||||||
|
* \sa SDL_StorageWriteFileAsync
|
||||||
|
*/
|
||||||
|
extern DECLSPEC Uint64 SDLCALL SDL_StorageSpaceRemaining(SDL_Storage *storage);
|
||||||
|
|
||||||
|
/* Ends C function definitions when using C++ */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#include <SDL3/SDL_close_code.h>
|
||||||
|
|
||||||
|
#endif /* SDL_storage_h_ */
|
|
@ -465,6 +465,10 @@
|
||||||
#cmakedefine SDL_FILESYSTEM_PS2 @SDL_FILESYSTEM_PS2@
|
#cmakedefine SDL_FILESYSTEM_PS2 @SDL_FILESYSTEM_PS2@
|
||||||
#cmakedefine SDL_FILESYSTEM_N3DS @SDL_FILESYSTEM_N3DS@
|
#cmakedefine SDL_FILESYSTEM_N3DS @SDL_FILESYSTEM_N3DS@
|
||||||
|
|
||||||
|
/* Enable system storage support */
|
||||||
|
#cmakedefine SDL_STORAGE_GENERIC @SDL_STORAGE_GENERIC@
|
||||||
|
#cmakedefine SDL_STORAGE_STEAM @SDL_STORAGE_STEAM@
|
||||||
|
|
||||||
/* Enable camera subsystem */
|
/* Enable camera subsystem */
|
||||||
#cmakedefine SDL_CAMERA_DRIVER_DUMMY @SDL_CAMERA_DRIVER_DUMMY@
|
#cmakedefine SDL_CAMERA_DRIVER_DUMMY @SDL_CAMERA_DRIVER_DUMMY@
|
||||||
/* !!! FIXME: for later cmakedefine SDL_CAMERA_DRIVER_DISK @SDL_CAMERA_DRIVER_DISK@ */
|
/* !!! FIXME: for later cmakedefine SDL_CAMERA_DRIVER_DISK @SDL_CAMERA_DRIVER_DISK@ */
|
||||||
|
|
|
@ -979,6 +979,14 @@ SDL3_0.0.0 {
|
||||||
SDL_OpenIO;
|
SDL_OpenIO;
|
||||||
SDL_CloseIO;
|
SDL_CloseIO;
|
||||||
SDL_GetIOStatus;
|
SDL_GetIOStatus;
|
||||||
|
SDL_OpenTitleStorage;
|
||||||
|
SDL_OpenUserStorage;
|
||||||
|
SDL_OpenStorage;
|
||||||
|
SDL_CloseStorage;
|
||||||
|
SDL_StorageReady;
|
||||||
|
SDL_StorageFileSize;
|
||||||
|
SDL_StorageReadFile;
|
||||||
|
SDL_StorageSpaceRemaining;
|
||||||
# extra symbols go here (don't modify this line)
|
# extra symbols go here (don't modify this line)
|
||||||
local: *;
|
local: *;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1004,3 +1004,11 @@
|
||||||
#define SDL_OpenIO SDL_OpenIO_REAL
|
#define SDL_OpenIO SDL_OpenIO_REAL
|
||||||
#define SDL_CloseIO SDL_CloseIO_REAL
|
#define SDL_CloseIO SDL_CloseIO_REAL
|
||||||
#define SDL_GetIOStatus SDL_GetIOStatus_REAL
|
#define SDL_GetIOStatus SDL_GetIOStatus_REAL
|
||||||
|
#define SDL_OpenTitleStorage SDL_OpenTitleStorage_REAL
|
||||||
|
#define SDL_OpenUserStorage SDL_OpenUserStorage_REAL
|
||||||
|
#define SDL_OpenStorage SDL_OpenStorage_REAL
|
||||||
|
#define SDL_CloseStorage SDL_CloseStorage_REAL
|
||||||
|
#define SDL_StorageReady SDL_StorageReady_REAL
|
||||||
|
#define SDL_StorageFileSize SDL_StorageFileSize_REAL
|
||||||
|
#define SDL_StorageReadFile SDL_StorageReadFile_REAL
|
||||||
|
#define SDL_StorageSpaceRemaining SDL_StorageSpaceRemaining_REAL
|
||||||
|
|
|
@ -1029,3 +1029,11 @@ SDL_DYNAPI_PROC(void,SDL_ShowOpenFolderDialog,(SDL_DialogFileCallback a, void *b
|
||||||
SDL_DYNAPI_PROC(SDL_IOStream*,SDL_OpenIO,(const SDL_IOStreamInterface *a, void *b),(a,b),return)
|
SDL_DYNAPI_PROC(SDL_IOStream*,SDL_OpenIO,(const SDL_IOStreamInterface *a, void *b),(a,b),return)
|
||||||
SDL_DYNAPI_PROC(int,SDL_CloseIO,(SDL_IOStream *a),(a),return)
|
SDL_DYNAPI_PROC(int,SDL_CloseIO,(SDL_IOStream *a),(a),return)
|
||||||
SDL_DYNAPI_PROC(SDL_IOStatus,SDL_GetIOStatus,(SDL_IOStream *a),(a),return)
|
SDL_DYNAPI_PROC(SDL_IOStatus,SDL_GetIOStatus,(SDL_IOStream *a),(a),return)
|
||||||
|
SDL_DYNAPI_PROC(SDL_Storage*,SDL_OpenTitleStorage,(const char *a, SDL_PropertiesID b),(a,b),return)
|
||||||
|
SDL_DYNAPI_PROC(SDL_Storage*,SDL_OpenUserStorage,(const char *a, const char *b, SDL_PropertiesID c),(a,b,c),return)
|
||||||
|
SDL_DYNAPI_PROC(SDL_Storage*,SDL_OpenStorage,(const SDL_StorageInterface *a, void *b),(a,b),return)
|
||||||
|
SDL_DYNAPI_PROC(int,SDL_CloseStorage,(SDL_Storage *a),(a),return)
|
||||||
|
SDL_DYNAPI_PROC(SDL_bool,SDL_StorageReady,(SDL_Storage *a),(a),return)
|
||||||
|
SDL_DYNAPI_PROC(int,SDL_StorageFileSize,(SDL_Storage *a, const char *b, Uint64 *c),(a,b,c),return)
|
||||||
|
SDL_DYNAPI_PROC(int,SDL_StorageReadFile,(SDL_Storage *a, const char *b, void *c, Uint64 d),(a,b,c,d),return)
|
||||||
|
SDL_DYNAPI_PROC(Uint64,SDL_StorageSpaceRemaining,(SDL_Storage *a),(a),return)
|
||||||
|
|
222
src/storage/SDL_storage.c
Normal file
222
src/storage/SDL_storage.c
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
|
#include "SDL_sysstorage.h"
|
||||||
|
|
||||||
|
/* Available title storage drivers */
|
||||||
|
static TitleStorageBootStrap *titlebootstrap[] = {
|
||||||
|
&GENERIC_titlebootstrap,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Available user storage drivers */
|
||||||
|
static UserStorageBootStrap *userbootstrap[] = {
|
||||||
|
#ifdef SDL_STORAGE_STEAM
|
||||||
|
&STEAM_userbootstrap,
|
||||||
|
#endif
|
||||||
|
&GENERIC_userbootstrap,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SDL_Storage
|
||||||
|
{
|
||||||
|
SDL_StorageInterface iface;
|
||||||
|
void *userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CHECK_STORAGE_MAGIC() \
|
||||||
|
if (!storage) { \
|
||||||
|
return SDL_SetError("Invalid storage container"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_STORAGE_MAGIC_RET(retval) \
|
||||||
|
if (!storage) { \
|
||||||
|
SDL_SetError("Invalid storage container"); \
|
||||||
|
return retval; \
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Storage *SDL_OpenTitleStorage(const char *override, SDL_PropertiesID props)
|
||||||
|
{
|
||||||
|
SDL_Storage *storage = NULL;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* Select the proper storage driver */
|
||||||
|
const char *driver_name = SDL_GetHint(SDL_HINT_STORAGE_TITLE_DRIVER);
|
||||||
|
if (driver_name && *driver_name != 0) {
|
||||||
|
const char *driver_attempt = driver_name;
|
||||||
|
while (driver_attempt && *driver_attempt != 0 && !storage) {
|
||||||
|
const char *driver_attempt_end = SDL_strchr(driver_attempt, ',');
|
||||||
|
size_t driver_attempt_len = (driver_attempt_end) ? (driver_attempt_end - driver_attempt)
|
||||||
|
: SDL_strlen(driver_attempt);
|
||||||
|
|
||||||
|
for (i = 0; titlebootstrap[i]; ++i) {
|
||||||
|
if ((driver_attempt_len == SDL_strlen(titlebootstrap[i]->name)) &&
|
||||||
|
(SDL_strncasecmp(titlebootstrap[i]->name, driver_attempt, driver_attempt_len) == 0)) {
|
||||||
|
storage = titlebootstrap[i]->create(override, props);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
driver_attempt = (driver_attempt_end) ? (driver_attempt_end + 1) : NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; titlebootstrap[i]; ++i) {
|
||||||
|
storage = titlebootstrap[i]->create(override, props);
|
||||||
|
if (storage) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!storage) {
|
||||||
|
if (driver_name) {
|
||||||
|
SDL_SetError("%s not available", driver_name);
|
||||||
|
} else {
|
||||||
|
SDL_SetError("No available title storage driver");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Storage *SDL_OpenUserStorage(const char *org, const char *app, SDL_PropertiesID props)
|
||||||
|
{
|
||||||
|
SDL_Storage *storage = NULL;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* Select the proper storage driver */
|
||||||
|
const char *driver_name = SDL_GetHint(SDL_HINT_STORAGE_USER_DRIVER);
|
||||||
|
if (driver_name && *driver_name != 0) {
|
||||||
|
const char *driver_attempt = driver_name;
|
||||||
|
while (driver_attempt && *driver_attempt != 0 && !storage) {
|
||||||
|
const char *driver_attempt_end = SDL_strchr(driver_attempt, ',');
|
||||||
|
size_t driver_attempt_len = (driver_attempt_end) ? (driver_attempt_end - driver_attempt)
|
||||||
|
: SDL_strlen(driver_attempt);
|
||||||
|
|
||||||
|
for (i = 0; userbootstrap[i]; ++i) {
|
||||||
|
if ((driver_attempt_len == SDL_strlen(userbootstrap[i]->name)) &&
|
||||||
|
(SDL_strncasecmp(userbootstrap[i]->name, driver_attempt, driver_attempt_len) == 0)) {
|
||||||
|
storage = userbootstrap[i]->create(org, app, props);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
driver_attempt = (driver_attempt_end) ? (driver_attempt_end + 1) : NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; userbootstrap[i]; ++i) {
|
||||||
|
storage = userbootstrap[i]->create(org, app, props);
|
||||||
|
if (storage) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!storage) {
|
||||||
|
if (driver_name) {
|
||||||
|
SDL_SetError("%s not available", driver_name);
|
||||||
|
} else {
|
||||||
|
SDL_SetError("No available user storage driver");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Storage *SDL_OpenStorage(const SDL_StorageInterface *iface, void *userdata)
|
||||||
|
{
|
||||||
|
SDL_Storage *storage;
|
||||||
|
|
||||||
|
if (iface->close == NULL || iface->ready == NULL || iface->fileSize == NULL) {
|
||||||
|
SDL_SetError("iface is missing required callbacks");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((iface->writeFile != NULL) != (iface->spaceRemaining != NULL)) {
|
||||||
|
SDL_SetError("Writeable containers must have both writeFile and spaceRemaining");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
storage = (SDL_Storage*) SDL_malloc(sizeof(SDL_Storage));
|
||||||
|
if (storage == NULL) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_memcpy(&storage->iface, iface, sizeof(SDL_StorageInterface));
|
||||||
|
storage->userdata = userdata;
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SDL_CloseStorage(SDL_Storage *storage)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
CHECK_STORAGE_MAGIC()
|
||||||
|
|
||||||
|
retval = storage->iface.close(storage->userdata);
|
||||||
|
SDL_free(storage);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_bool SDL_StorageReady(SDL_Storage *storage)
|
||||||
|
{
|
||||||
|
CHECK_STORAGE_MAGIC_RET(SDL_FALSE)
|
||||||
|
|
||||||
|
return storage->iface.ready(storage->userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SDL_StorageFileSize(SDL_Storage *storage, const char *path, Uint64 *length)
|
||||||
|
{
|
||||||
|
CHECK_STORAGE_MAGIC()
|
||||||
|
|
||||||
|
return storage->iface.fileSize(storage->userdata, path, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SDL_StorageReadFile(SDL_Storage *storage, const char *path, void *destination, Uint64 length)
|
||||||
|
{
|
||||||
|
CHECK_STORAGE_MAGIC()
|
||||||
|
|
||||||
|
if (storage->iface.readFile == NULL) {
|
||||||
|
return SDL_SetError("Storage container does not have read capability");
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage->iface.readFile(storage->userdata, path, destination, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SDL_StorageWriteFile(SDL_Storage *storage, const char *path, const void *source, Uint64 length)
|
||||||
|
{
|
||||||
|
CHECK_STORAGE_MAGIC()
|
||||||
|
|
||||||
|
if (storage->iface.writeFile == NULL) {
|
||||||
|
return SDL_SetError("Storage container does not have write capability");
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage->iface.writeFile(storage->userdata, path, source, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint64 SDL_StorageSpaceRemaining(SDL_Storage *storage)
|
||||||
|
{
|
||||||
|
CHECK_STORAGE_MAGIC_RET(0)
|
||||||
|
|
||||||
|
if (storage->iface.spaceRemaining == NULL) {
|
||||||
|
SDL_SetError("Storage container does not have write capability");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage->iface.spaceRemaining(storage->userdata);
|
||||||
|
}
|
49
src/storage/SDL_sysstorage.h
Normal file
49
src/storage/SDL_sysstorage.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SDL_sysstorage_h_
|
||||||
|
#define SDL_sysstorage_h_
|
||||||
|
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
|
typedef struct TitleStorageBootStrap
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const char *desc;
|
||||||
|
SDL_Storage *(*create)(const char*, SDL_PropertiesID);
|
||||||
|
} TitleStorageBootStrap;
|
||||||
|
|
||||||
|
typedef struct UserStorageBootStrap
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
const char *desc;
|
||||||
|
SDL_Storage *(*create)(const char*, const char*, SDL_PropertiesID);
|
||||||
|
} UserStorageBootStrap;
|
||||||
|
|
||||||
|
/* Not all of these are available in a given build. Use #ifdefs, etc. */
|
||||||
|
|
||||||
|
extern TitleStorageBootStrap GENERIC_titlebootstrap;
|
||||||
|
/* Steam does not have title storage APIs */
|
||||||
|
|
||||||
|
extern UserStorageBootStrap GENERIC_userbootstrap;
|
||||||
|
extern UserStorageBootStrap STEAM_userbootstrap;
|
||||||
|
|
||||||
|
#endif /* SDL_sysstorage_h_ */
|
188
src/storage/generic/SDL_genericstorage.c
Normal file
188
src/storage/generic/SDL_genericstorage.c
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
|
#include "../SDL_sysstorage.h"
|
||||||
|
|
||||||
|
static char *GENERIC_INTERNAL_CreateFullPath(const char *base, const char *relative)
|
||||||
|
{
|
||||||
|
size_t fulllen = SDL_strlen(base) + SDL_strlen(relative) + 1;
|
||||||
|
char *result = (char*) SDL_malloc(fulllen);
|
||||||
|
if (result != NULL) {
|
||||||
|
SDL_snprintf(result, fulllen, "%s%s", base, relative);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GENERIC_StorageClose(void *userdata)
|
||||||
|
{
|
||||||
|
SDL_free(userdata);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_bool GENERIC_StorageReady(void *userdata)
|
||||||
|
{
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GENERIC_StorageFileSize(void *userdata, const char *path, Uint64 *length)
|
||||||
|
{
|
||||||
|
SDL_IOStream *stream;
|
||||||
|
Sint64 result;
|
||||||
|
|
||||||
|
char *fullpath = GENERIC_INTERNAL_CreateFullPath((char*) userdata, path);
|
||||||
|
if (fullpath == NULL) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
stream = SDL_IOFromFile(fullpath, "rb");
|
||||||
|
SDL_free(fullpath);
|
||||||
|
|
||||||
|
result = SDL_SizeIO(stream);
|
||||||
|
SDL_CloseIO(stream);
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Should SDL_SizeIO use u64 now...? */
|
||||||
|
*length = (Uint64) result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GENERIC_StorageReadFile(void *userdata, const char *path, void *destination, Uint64 length)
|
||||||
|
{
|
||||||
|
SDL_IOStream *stream;
|
||||||
|
char *fullpath;
|
||||||
|
int fullread;
|
||||||
|
|
||||||
|
if (length > SDL_SIZE_MAX) {
|
||||||
|
return SDL_SetError("Read size exceeds SDL_SIZE_MAX");
|
||||||
|
}
|
||||||
|
|
||||||
|
fullpath = GENERIC_INTERNAL_CreateFullPath((char*) userdata, path);
|
||||||
|
if (fullpath == NULL) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
stream = SDL_IOFromFile(fullpath, "rb");
|
||||||
|
SDL_free(fullpath);
|
||||||
|
|
||||||
|
/* FIXME: Should SDL_ReadIO use u64 now...? */
|
||||||
|
fullread = (SDL_ReadIO(stream, destination, (size_t) length) == length);
|
||||||
|
SDL_CloseIO(stream);
|
||||||
|
return fullread - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GENERIC_StorageWriteFile(void *userdata, const char *path, const void *source, Uint64 length)
|
||||||
|
{
|
||||||
|
/* TODO: Recursively create subdirectories with SDL_mkdir */
|
||||||
|
SDL_IOStream *stream;
|
||||||
|
char *fullpath;
|
||||||
|
int fullwrite;
|
||||||
|
|
||||||
|
if (length > SDL_SIZE_MAX) {
|
||||||
|
return SDL_SetError("Write size exceeds SDL_SIZE_MAX");
|
||||||
|
}
|
||||||
|
|
||||||
|
fullpath = GENERIC_INTERNAL_CreateFullPath((char*) userdata, path);
|
||||||
|
if (fullpath == NULL) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
stream = SDL_IOFromFile(fullpath, "wb");
|
||||||
|
SDL_free(fullpath);
|
||||||
|
|
||||||
|
/* FIXME: Should SDL_WriteIO use u64 now...? */
|
||||||
|
fullwrite = (SDL_WriteIO(stream, source, (size_t) length) == length);
|
||||||
|
SDL_CloseIO(stream);
|
||||||
|
return fullwrite - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Uint64 GENERIC_StorageSpaceRemaining(void *userdata)
|
||||||
|
{
|
||||||
|
/* TODO: There's totally a way to query a folder root's quota... */
|
||||||
|
return SDL_MAX_UINT64;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const SDL_StorageInterface GENERIC_title_iface = {
|
||||||
|
GENERIC_StorageClose,
|
||||||
|
GENERIC_StorageReady,
|
||||||
|
GENERIC_StorageFileSize,
|
||||||
|
GENERIC_StorageReadFile,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static SDL_Storage *GENERIC_Title_Create(const char *override, SDL_PropertiesID props)
|
||||||
|
{
|
||||||
|
SDL_Storage *result;
|
||||||
|
|
||||||
|
char *basepath;
|
||||||
|
if (override != NULL) {
|
||||||
|
basepath = SDL_strdup(override);
|
||||||
|
} else {
|
||||||
|
basepath = SDL_GetBasePath();
|
||||||
|
}
|
||||||
|
if (basepath == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = SDL_OpenStorage(&GENERIC_title_iface, basepath);
|
||||||
|
if (result == NULL) {
|
||||||
|
SDL_free(basepath);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TitleStorageBootStrap GENERIC_titlebootstrap = {
|
||||||
|
"generic",
|
||||||
|
"SDL generic title storage driver",
|
||||||
|
GENERIC_Title_Create
|
||||||
|
};
|
||||||
|
|
||||||
|
static const SDL_StorageInterface GENERIC_user_iface = {
|
||||||
|
GENERIC_StorageClose,
|
||||||
|
GENERIC_StorageReady,
|
||||||
|
GENERIC_StorageFileSize,
|
||||||
|
GENERIC_StorageReadFile,
|
||||||
|
GENERIC_StorageWriteFile,
|
||||||
|
GENERIC_StorageSpaceRemaining
|
||||||
|
};
|
||||||
|
|
||||||
|
static SDL_Storage *GENERIC_User_Create(const char *org, const char *app, SDL_PropertiesID props)
|
||||||
|
{
|
||||||
|
SDL_Storage *result;
|
||||||
|
|
||||||
|
char *prefpath = SDL_GetPrefPath(org, app);
|
||||||
|
if (prefpath == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = SDL_OpenStorage(&GENERIC_user_iface, prefpath);
|
||||||
|
if (result == NULL) {
|
||||||
|
SDL_free(prefpath);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserStorageBootStrap GENERIC_userbootstrap = {
|
||||||
|
"generic",
|
||||||
|
"SDL generic user storage driver",
|
||||||
|
GENERIC_User_Create
|
||||||
|
};
|
199
src/storage/steam/SDL_steamstorage.c
Normal file
199
src/storage/steam/SDL_steamstorage.c
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
|
#include "../SDL_sysstorage.h"
|
||||||
|
|
||||||
|
#include <stdbool.h> /* Needed by Steamworks */
|
||||||
|
|
||||||
|
// !!! FIXME: Async API can use SteamRemoteStorage_ReadFileAsync
|
||||||
|
// !!! FIXME: Async API can use SteamRemoteStorage_WriteFileAsync
|
||||||
|
|
||||||
|
#define STEAM_PROC(ret, func, parms) \
|
||||||
|
typedef ret (*steamfntype_##func) parms;
|
||||||
|
#include "SDL_steamstorage_proc.h"
|
||||||
|
|
||||||
|
typedef struct STEAM_RemoteStorage
|
||||||
|
{
|
||||||
|
void *libsteam_api;
|
||||||
|
#define STEAM_PROC(ret, func, parms) \
|
||||||
|
steamfntype_##func func;
|
||||||
|
#include "SDL_steamstorage_proc.h"
|
||||||
|
} STEAM_RemoteStorage;
|
||||||
|
|
||||||
|
static int STEAM_UserStorageClose(void *userdata)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
STEAM_RemoteStorage *steam = (STEAM_RemoteStorage*) userdata;
|
||||||
|
void *steamremotestorage = steam->SteamAPI_SteamRemoteStorage_v016();
|
||||||
|
if (steamremotestorage == NULL) {
|
||||||
|
result = SDL_SetError("SteamRemoteStorage unavailable");
|
||||||
|
} else if (!steam->SteamAPI_ISteamRemoteStorage_EndFileWriteBatch(steamremotestorage)) {
|
||||||
|
result = SDL_SetError("SteamRemoteStorage()->EndFileWriteBatch() failed");
|
||||||
|
}
|
||||||
|
SDL_UnloadObject(steam->libsteam_api);
|
||||||
|
SDL_free(steam);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SDL_bool STEAM_UserStorageReady(void *userdata)
|
||||||
|
{
|
||||||
|
return SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int STEAM_UserStorageFileSize(void *userdata, const char *path, Uint64 *length)
|
||||||
|
{
|
||||||
|
STEAM_RemoteStorage *steam = (STEAM_RemoteStorage*) userdata;
|
||||||
|
void *steamremotestorage = steam->SteamAPI_SteamRemoteStorage_v016();
|
||||||
|
if (steamremotestorage == NULL) {
|
||||||
|
return SDL_SetError("SteamRemoteStorage unavailable");
|
||||||
|
}
|
||||||
|
*length = steam->SteamAPI_ISteamRemoteStorage_GetFileSize(steamremotestorage, path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int STEAM_UserStorageReadFile(void *userdata, const char *path, void *destination, Uint64 length)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
STEAM_RemoteStorage *steam = (STEAM_RemoteStorage*) userdata;
|
||||||
|
void *steamremotestorage = steam->SteamAPI_SteamRemoteStorage_v016();
|
||||||
|
if (steamremotestorage == NULL) {
|
||||||
|
return SDL_SetError("SteamRemoteStorage unavailable");
|
||||||
|
}
|
||||||
|
if (length > SDL_MAX_SINT32) {
|
||||||
|
return SDL_SetError("SteamRemoteStorage only supports INT32_MAX read size");
|
||||||
|
}
|
||||||
|
retval = steam->SteamAPI_ISteamRemoteStorage_FileRead(steamremotestorage, path, destination, (Sint32) length) == length;
|
||||||
|
return retval - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int STEAM_UserStorageWriteFile(void *userdata, const char *path, const void *source, Uint64 length)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
STEAM_RemoteStorage *steam = (STEAM_RemoteStorage*) userdata;
|
||||||
|
void *steamremotestorage = steam->SteamAPI_SteamRemoteStorage_v016();
|
||||||
|
if (steamremotestorage == NULL) {
|
||||||
|
return SDL_SetError("SteamRemoteStorage unavailable");
|
||||||
|
}
|
||||||
|
if (length > SDL_MAX_SINT32) {
|
||||||
|
return SDL_SetError("SteamRemoteStorage only supports INT32_MAX write size");
|
||||||
|
}
|
||||||
|
retval = steam->SteamAPI_ISteamRemoteStorage_FileWrite(steamremotestorage, path, source, (Sint32) length) == length;
|
||||||
|
return retval - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Uint64 STEAM_UserStorageSpaceRemaining(void *userdata)
|
||||||
|
{
|
||||||
|
Uint64 total, remaining;
|
||||||
|
STEAM_RemoteStorage *steam = (STEAM_RemoteStorage*) userdata;
|
||||||
|
void *steamremotestorage = steam->SteamAPI_SteamRemoteStorage_v016();
|
||||||
|
if (steamremotestorage == NULL) {
|
||||||
|
SDL_SetError("SteamRemoteStorage unavailable");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!steam->SteamAPI_ISteamRemoteStorage_GetQuota(steamremotestorage, &total, &remaining)) {
|
||||||
|
SDL_SetError("SteamRemoteStorage()->GetQuota failed");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const SDL_StorageInterface STEAM_user_iface = {
|
||||||
|
STEAM_UserStorageClose,
|
||||||
|
STEAM_UserStorageReady,
|
||||||
|
STEAM_UserStorageFileSize,
|
||||||
|
STEAM_UserStorageReadFile,
|
||||||
|
STEAM_UserStorageWriteFile,
|
||||||
|
STEAM_UserStorageSpaceRemaining
|
||||||
|
};
|
||||||
|
|
||||||
|
static SDL_Storage *STEAM_User_Create(const char *org, const char *app, SDL_PropertiesID props)
|
||||||
|
{
|
||||||
|
SDL_Storage *result;
|
||||||
|
STEAM_RemoteStorage *steam;
|
||||||
|
void *steamremotestorage;
|
||||||
|
|
||||||
|
steam = (STEAM_RemoteStorage*) SDL_malloc(sizeof(STEAM_RemoteStorage));
|
||||||
|
if (steam == NULL) {
|
||||||
|
SDL_OutOfMemory();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
steam->libsteam_api = SDL_LoadObject(
|
||||||
|
#if defined(_WIN64)
|
||||||
|
"steam_api64.dll"
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
"steam_api.dll"
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
"libsteam_api.dylib"
|
||||||
|
#else
|
||||||
|
"libsteam_api.so"
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
if (steam->libsteam_api == NULL) {
|
||||||
|
SDL_free(steam);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STEAM_PROC(ret, func, parms) \
|
||||||
|
steam->func = (steamfntype_##func) SDL_LoadFunction(steam->libsteam_api, #func); \
|
||||||
|
if (steam->func == NULL) { \
|
||||||
|
SDL_SetError("Could not load function " #func); \
|
||||||
|
goto steamfail; \
|
||||||
|
}
|
||||||
|
#include "SDL_steamstorage_proc.h"
|
||||||
|
|
||||||
|
steamremotestorage = steam->SteamAPI_SteamRemoteStorage_v016();
|
||||||
|
if (steamremotestorage == NULL) {
|
||||||
|
SDL_SetError("SteamRemoteStorage unavailable");
|
||||||
|
goto steamfail;
|
||||||
|
}
|
||||||
|
if (!steam->SteamAPI_ISteamRemoteStorage_IsCloudEnabledForAccount(steamremotestorage)) {
|
||||||
|
SDL_SetError("Steam cloud is disabled for this user");
|
||||||
|
goto steamfail;
|
||||||
|
}
|
||||||
|
if (!steam->SteamAPI_ISteamRemoteStorage_IsCloudEnabledForApp(steamremotestorage)) {
|
||||||
|
SDL_SetError("Steam cloud is disabled for this application");
|
||||||
|
goto steamfail;
|
||||||
|
}
|
||||||
|
if (!steam->SteamAPI_ISteamRemoteStorage_BeginFileWriteBatch(steamremotestorage)) {
|
||||||
|
SDL_SetError("SteamRemoteStorage()->BeginFileWriteBatch failed");
|
||||||
|
goto steamfail;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = SDL_OpenStorage(&STEAM_user_iface, steam);
|
||||||
|
if (result == NULL) {
|
||||||
|
goto steamfail;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
steamfail:
|
||||||
|
SDL_UnloadObject(steam->libsteam_api);
|
||||||
|
SDL_free(steam);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserStorageBootStrap STEAM_userbootstrap = {
|
||||||
|
"steam",
|
||||||
|
"SDL Steam user storage driver",
|
||||||
|
STEAM_User_Create
|
||||||
|
};
|
14
src/storage/steam/SDL_steamstorage_proc.h
Normal file
14
src/storage/steam/SDL_steamstorage_proc.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
STEAM_PROC(void*, SteamAPI_SteamRemoteStorage_v016, (void))
|
||||||
|
|
||||||
|
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_IsCloudEnabledForAccount, (void*))
|
||||||
|
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_IsCloudEnabledForApp, (void*))
|
||||||
|
|
||||||
|
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_BeginFileWriteBatch, (void*))
|
||||||
|
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_EndFileWriteBatch, (void*))
|
||||||
|
|
||||||
|
STEAM_PROC(Sint32, SteamAPI_ISteamRemoteStorage_GetFileSize, (void*, const char*))
|
||||||
|
STEAM_PROC(Sint32, SteamAPI_ISteamRemoteStorage_FileRead, (void*, const char*, void*, Sint32))
|
||||||
|
STEAM_PROC(Sint32, SteamAPI_ISteamRemoteStorage_FileWrite, (void*, const char*, const void*, Sint32))
|
||||||
|
STEAM_PROC(bool, SteamAPI_ISteamRemoteStorage_GetQuota, (void*, Uint64*, Uint64*))
|
||||||
|
|
||||||
|
#undef STEAM_PROC
|
Loading…
Add table
Add a link
Reference in a new issue