Bladeren bron

pod: Add POD archiver.

Jordon Moss 4 maanden geleden
bovenliggende
commit
4e13e765f2
5 gewijzigde bestanden met toevoegingen van 152 en 1 verwijderingen
  1. 7 0
      CMakeLists.txt
  2. 2 1
      src/Makefile.os2
  3. 3 0
      src/physfs.c
  4. 136 0
      src/physfs_archiver_pod.c
  5. 4 0
      src/physfs_internal.h

+ 7 - 0
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)

+ 2 - 1
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)

+ 3 - 0
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
 

+ 136 - 0
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 <mossj32@gmail.com>",
+        "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 ... */
+

+ 4 - 0
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