FileSystem: Add fallback to wrapped SDL_RWops if normal mounting fails
Makes it easy to mount archives on Android residing in "assets/".
This commit is contained in:
		
							parent
							
								
									3411435138
								
							
						
					
					
						commit
						4fb94aaf10
					
				
					 1 changed files with 109 additions and 1 deletions
				
			
		| 
						 | 
					@ -42,6 +42,105 @@
 | 
				
			||||||
#include <iconv.h>
 | 
					#include <iconv.h>
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct SDLRWIoContext
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						SDL_RWops *ops;
 | 
				
			||||||
 | 
						std::string filename;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SDLRWIoContext(const char *filename)
 | 
				
			||||||
 | 
						    : ops(SDL_RWFromFile(filename, "r")),
 | 
				
			||||||
 | 
						      filename(filename)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (!ops)
 | 
				
			||||||
 | 
								throw Exception(Exception::SDLError,
 | 
				
			||||||
 | 
								                "Failed to open file: %s", SDL_GetError());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						~SDLRWIoContext()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							SDL_RWclose(ops);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PHYSFS_Io *createSDLRWIo(const char *filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SDL_RWops *getSDLRWops(PHYSFS_Io *io)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return static_cast<SDLRWIoContext*>(io->opaque)->ops;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PHYSFS_sint64 SDLRWIoRead(struct PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return SDL_RWread(getSDLRWops(io), buf, 1, len);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int SDLRWIoSeek(struct PHYSFS_Io *io, PHYSFS_uint64 offset)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (SDL_RWseek(getSDLRWops(io), offset, RW_SEEK_SET) != -1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PHYSFS_sint64 SDLRWIoTell(struct PHYSFS_Io *io)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return SDL_RWseek(getSDLRWops(io), 0, RW_SEEK_CUR);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PHYSFS_sint64 SDLRWIoLength(struct PHYSFS_Io *io)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return SDL_RWsize(getSDLRWops(io));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct PHYSFS_Io *SDLRWIoDuplicate(struct PHYSFS_Io *io)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						SDLRWIoContext *ctx = static_cast<SDLRWIoContext*>(io->opaque);
 | 
				
			||||||
 | 
						int64_t offset = io->tell(io);
 | 
				
			||||||
 | 
						PHYSFS_Io *dup = createSDLRWIo(ctx->filename.c_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (dup)
 | 
				
			||||||
 | 
							SDLRWIoSeek(dup, offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return dup;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void SDLRWIoDestroy(struct PHYSFS_Io *io)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						delete static_cast<SDLRWIoContext*>(io->opaque);
 | 
				
			||||||
 | 
						delete io;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PHYSFS_Io SDLRWIoTemplate =
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						0, 0, /* version, opaque */
 | 
				
			||||||
 | 
						SDLRWIoRead,
 | 
				
			||||||
 | 
						0, /* write */
 | 
				
			||||||
 | 
						SDLRWIoSeek,
 | 
				
			||||||
 | 
						SDLRWIoTell,
 | 
				
			||||||
 | 
						SDLRWIoLength,
 | 
				
			||||||
 | 
						SDLRWIoDuplicate,
 | 
				
			||||||
 | 
						0, /* flush */
 | 
				
			||||||
 | 
						SDLRWIoDestroy
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static PHYSFS_Io *createSDLRWIo(const char *filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						SDLRWIoContext *ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ctx = new SDLRWIoContext(filename);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						catch (const Exception &e)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Debug() << "Failed mounting" << filename;
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PHYSFS_Io *io = new PHYSFS_Io;
 | 
				
			||||||
 | 
						*io = SDLRWIoTemplate;
 | 
				
			||||||
 | 
						io->opaque = ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return io;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline PHYSFS_File *sdlPHYS(SDL_RWops *ops)
 | 
					static inline PHYSFS_File *sdlPHYS(SDL_RWops *ops)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return static_cast<PHYSFS_File*>(ops->hidden.unknown.data1);
 | 
						return static_cast<PHYSFS_File*>(ops->hidden.unknown.data1);
 | 
				
			||||||
| 
						 | 
					@ -368,7 +467,16 @@ FileSystem::~FileSystem()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void FileSystem::addPath(const char *path)
 | 
					void FileSystem::addPath(const char *path)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	PHYSFS_mount(path, 0, 1);
 | 
						/* Try the normal mount first */
 | 
				
			||||||
 | 
						if (!PHYSFS_mount(path, 0, 1))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							/* If it didn't work, try mounting via a wrapped
 | 
				
			||||||
 | 
							 * SDL_RWops */
 | 
				
			||||||
 | 
							PHYSFS_Io *io = createSDLRWIo(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (io)
 | 
				
			||||||
 | 
								PHYSFS_mountIo(io, path, 0, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __APPLE__
 | 
					#ifdef __APPLE__
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue