| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- /*
- * 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 ... */
|