diff --git a/CMakeLists.txt b/CMakeLists.txt index ce2b796c..2c795f23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,7 @@ set(PHYSFS_SRCS src/physfs_archiver_iso9660.c src/physfs_archiver_vdf.c src/physfs_archiver_lec3d.c + src/physfs_archiver_pod.c src/physfs_version.rc ${PHYSFS_CPP_SRCS} ${PHYSFS_M_SRCS} @@ -176,6 +177,11 @@ if(NOT PHYSFS_ARCHIVE_LECARCHIVES) add_definitions(-DPHYSFS_SUPPORTS_LECARCHIVES=0) endif() +option(PHYSFS_ARCHIVE_POD "Enable Terminal Reality POD Archive support" TRUE) +if(NOT PHYSFS_ARCHIVE_POD) + add_definitions(-DPHYSFS_SUPPORTS_POD=0) +endif() + option(PHYSFS_BUILD_STATIC "Build static library" TRUE) if(PHYSFS_BUILD_STATIC) @@ -413,6 +419,7 @@ message_bool_option("SLB support" PHYSFS_ARCHIVE_SLB) message_bool_option("VDF support" PHYSFS_ARCHIVE_VDF) message_bool_option("ISO9660 support" PHYSFS_ARCHIVE_ISO9660) message_bool_option("GOB/LAB/LFD support" PHYSFS_ARCHIVE_LECARCHIVES) +message_bool_option("POD support" PHYSFS_ARCHIVE_POD) message_bool_option("Build static library" PHYSFS_BUILD_STATIC) message_bool_option("Build shared library" PHYSFS_BUILD_SHARED) message_bool_option("Build stdio test program" PHYSFS_BUILD_TEST) diff --git a/src/Makefile.os2 b/src/Makefile.os2 index 323dfbd4..0883f2aa 100644 --- a/src/Makefile.os2 +++ b/src/Makefile.os2 @@ -27,7 +27,8 @@ SRCS = physfs.c & physfs_archiver_iso9660.c & physfs_archiver_csm.c & physfs_archiver_vdf.c & - physfs_archiver_lec3d.c + physfs_archiver_lec3d.c & + physfs_archiver_pod.c OBJS = $(SRCS:.c=.obj) diff --git a/src/physfs.c b/src/physfs.c index 8d2b9bbf..88e6bd00 100644 --- a/src/physfs.c +++ b/src/physfs.c @@ -1205,6 +1205,9 @@ static int initStaticArchivers(void) REGISTER_STATIC_ARCHIVER(LFD) REGISTER_STATIC_ARCHIVER(LAB) #endif + #if PHYSFS_SUPPORTS_POD + REGISTER_STATIC_ARCHIVER(POD) + #endif #undef REGISTER_STATIC_ARCHIVER diff --git a/src/physfs_archiver_pod.c b/src/physfs_archiver_pod.c new file mode 100644 index 00000000..e737c04b --- /dev/null +++ b/src/physfs_archiver_pod.c @@ -0,0 +1,136 @@ +/* + * POD support routines for PhysicsFS. + * + * This driver handles Terminal Velocity POD archives. + * + * The POD format is as follows: + * + * While there is no known signature, the file starts with an + * unsigned 32-bit integer with the file count, followed by + * an 80-character, null-padded string with a description of + * the pod file. The file entries follow, and are as such: + * + * struct { + * char file_path[32]; // Full file path, IE: "ART\VGA.ACT" + * uint32_t file_size; // filesize in bytes + * uint32_t offset; // The offset of the data. + * } fileEntry_t; // Once per file. The file data itself is at offset after all entries. + * + * (This info is from: https://moddingwiki.shikadi.net/wiki/POD_Format) + * + * There are other POD file formats, but they haven't been implemented yet. + * + * Please see the file LICENSE.txt in the source's root directory. + * + * This file written by Jordon Moss. + */ + +#define __PHYSICSFS_INTERNAL__ +#include "physfs_internal.h" + +#if PHYSFS_SUPPORTS_POD + +static int readui32(PHYSFS_Io *io, PHYSFS_uint32 *val) +{ + PHYSFS_uint32 v; + BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0); + *val = PHYSFS_swapULE32(v); + return 1; +} /* readui32 */ + +static void replaceChar(char* str, char oldChar, char newChar) +{ + int i = 0; + while (str[i] != '\0') + { // Iterate until the null terminator is found + if (str[i] == oldChar) + { + str[i] = newChar; // Replace the character + } + i++; + } +} + +static int pod1LoadEntries(PHYSFS_Io *io, void *arc) +{ + PHYSFS_uint32 numfiles; + PHYSFS_uint32 i; + + BAIL_IF_ERRPASS(!readui32(io, &numfiles), 0); + BAIL_IF_ERRPASS(!io->seek(io, 84), 0); /* skip past description */ + + for (i = 0; i < numfiles; i++) { + char name[33]; + PHYSFS_uint32 size; + PHYSFS_uint32 offset; + BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 32), 0); + BAIL_IF_ERRPASS(!readui32(io, &size), 0); + BAIL_IF_ERRPASS(!readui32(io, &offset), 0); + name[32] = '\0'; /* just in case */ + + replaceChar(name, '\\', '/'); + + BAIL_IF_ERRPASS(!UNPK_addEntry(arc, name, 0, -1, -1, offset, size), 0); + } + + return 1; +} /* pod1LoadEntries */ + + +static void *POD_openArchive(PHYSFS_Io *io, const char *name, + int forWriting, int *claimed) +{ + void *unpkarc = NULL; + PHYSFS_uint32 dummy; + char description[80]; + + assert(io != NULL); /* shouldn't ever happen. */ + BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL); + + BAIL_IF_ERRPASS(!readui32(io, &dummy), 0); + BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, description, 80), NULL); + if ((description[0] == 0) || (description[79] != 0)) // Check if we're lacking a description or last char isn't a null terminator. + return NULL; + + io->seek(io, 0); + + *claimed = 1; + + unpkarc = UNPK_openArchive(io, 0, 1); + BAIL_IF_ERRPASS(!unpkarc, NULL); + + if (!(pod1LoadEntries(io, unpkarc))) + { + UNPK_abandonArchive(unpkarc); + return NULL; + } /* if */ + + return unpkarc; +} /* POD_openArchive */ + + +const PHYSFS_Archiver __PHYSFS_Archiver_POD = +{ + CURRENT_PHYSFS_ARCHIVER_API_VERSION, + { + "POD", + "Terminal Reality POD file format", + "Jordon Moss ", + "https://icculus.org/physfs/", + 0, /* supportsSymlinks */ + }, + POD_openArchive, + UNPK_enumerate, + UNPK_openRead, + UNPK_openWrite, + UNPK_openAppend, + UNPK_remove, + UNPK_mkdir, + UNPK_stat, + UNPK_closeArchive +}; + +#endif /* defined PHYSFS_SUPPORTS_POD */ + +/* end of physfs_archiver_pod.c ... */ + diff --git a/src/physfs_internal.h b/src/physfs_internal.h index 9e9dbefe..dabf203c 100644 --- a/src/physfs_internal.h +++ b/src/physfs_internal.h @@ -95,6 +95,7 @@ extern const PHYSFS_Archiver __PHYSFS_Archiver_VDF; extern const PHYSFS_Archiver __PHYSFS_Archiver_GOB; extern const PHYSFS_Archiver __PHYSFS_Archiver_LFD; extern const PHYSFS_Archiver __PHYSFS_Archiver_LAB; +extern const PHYSFS_Archiver __PHYSFS_Archiver_POD; /* a real C99-compliant snprintf() is in Visual Studio 2015, but just use this everywhere for binary compatibility. */ @@ -227,6 +228,9 @@ void __PHYSFS_smallFree(void *ptr); #ifndef PHYSFS_SUPPORTS_LECARCHIVES #define PHYSFS_SUPPORTS_LECARCHIVES PHYSFS_SUPPORTS_DEFAULT #endif +#ifndef PHYSFS_SUPPORTS_POD +#define PHYSFS_SUPPORTS_POD PHYSFS_SUPPORTS_DEFAULT +#endif #if PHYSFS_SUPPORTS_7Z