Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * HOG support routines for PhysicsFS.
  3.  *
  4.  * This driver handles Descent I/II HOG archives.
  5.  *
  6.  * The format is very simple:
  7.  *
  8.  *   The file always starts with the 3-byte signature "DHF" (Descent
  9.  *   HOG file). After that the files of a HOG are just attached after
  10.  *   another, divided by a 17 bytes header, which specifies the name
  11.  *   and length (in bytes) of the forthcoming file! So you just read
  12.  *   the header with its information of how big the following file is,
  13.  *   and then skip exact that number of bytes to get to the next file
  14.  *   in that HOG.
  15.  *
  16.  *    char sig[3] = {'D', 'H', 'F'}; // "DHF"=Descent HOG File
  17.  *
  18.  *    struct {
  19.  *     char file_name[13]; // Filename, padded to 13 bytes with 0s
  20.  *     int file_size; // filesize in bytes
  21.  *     char data[file_size]; // The file data
  22.  *    } FILE_STRUCT; // Repeated until the end of the file.
  23.  *
  24.  * (That info is from http://www.descent2.com/ddn/specs/hog/)
  25.  *
  26.  * Please see the file LICENSE.txt in the source's root directory.
  27.  *
  28.  *  This file written by Bradley Bell.
  29.  *  Based on grp.c by Ryan C. Gordon.
  30.  */
  31.  
  32. #define __PHYSICSFS_INTERNAL__
  33. #include "physfs_internal.h"
  34.  
  35. #if PHYSFS_SUPPORTS_HOG
  36.  
  37. static int hogLoadEntries(PHYSFS_Io *io, void *arc)
  38. {
  39.     const PHYSFS_uint64 iolen = io->length(io);
  40.     PHYSFS_uint32 pos = 3;
  41.  
  42.     while (pos < iolen)
  43.     {
  44.         PHYSFS_uint32 size;
  45.         char name[13];
  46.  
  47.         BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 13), 0);
  48.         BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &size, 4), 0);
  49.         name[12] = '\0';  /* just in case. */
  50.         pos += 13 + 4;
  51.  
  52.         size = PHYSFS_swapULE32(size);
  53.         BAIL_IF_ERRPASS(!UNPK_addEntry(arc, name, 0, -1, -1, pos, size), 0);
  54.         pos += size;
  55.  
  56.         /* skip over entry */
  57.         BAIL_IF_ERRPASS(!io->seek(io, pos), 0);
  58.     } /* while */
  59.  
  60.     return 1;
  61. } /* hogLoadEntries */
  62.  
  63.  
  64. static void *HOG_openArchive(PHYSFS_Io *io, const char *name,
  65.                              int forWriting, int *claimed)
  66. {
  67.     PHYSFS_uint8 buf[3];
  68.     void *unpkarc = NULL;
  69.  
  70.     assert(io != NULL);  /* shouldn't ever happen. */
  71.     BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
  72.     BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, buf, 3), NULL);
  73.     BAIL_IF(memcmp(buf, "DHF", 3) != 0, PHYSFS_ERR_UNSUPPORTED, NULL);
  74.  
  75.     *claimed = 1;
  76.  
  77.     unpkarc = UNPK_openArchive(io);
  78.     BAIL_IF_ERRPASS(!unpkarc, NULL);
  79.  
  80.     if (!hogLoadEntries(io, unpkarc))
  81.     {
  82.         UNPK_abandonArchive(unpkarc);
  83.         return NULL;
  84.     } /* if */
  85.  
  86.     return unpkarc;
  87. } /* HOG_openArchive */
  88.  
  89.  
  90. const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
  91. {
  92.     CURRENT_PHYSFS_ARCHIVER_API_VERSION,
  93.     {
  94.         "HOG",
  95.         "Descent I/II HOG file format",
  96.         "Bradley Bell <btb@icculus.org>",
  97.         "https://icculus.org/physfs/",
  98.         0,  /* supportsSymlinks */
  99.     },
  100.     HOG_openArchive,
  101.     UNPK_enumerate,
  102.     UNPK_openRead,
  103.     UNPK_openWrite,
  104.     UNPK_openAppend,
  105.     UNPK_remove,
  106.     UNPK_mkdir,
  107.     UNPK_stat,
  108.     UNPK_closeArchive
  109. };
  110.  
  111. #endif  /* defined PHYSFS_SUPPORTS_HOG */
  112.  
  113. /* end of physfs_archiver_hog.c ... */
  114.  
  115.