physfs_archiver_csm.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * CSM support routines for PhysicsFS.
  3. *
  4. * This driver handles Chasm: The Rift engine archives ("CSM.BINs").
  5. * This format (but not this driver) was developed by Action Forms Ltd.
  6. * and published by Megamedia for use with the Chasm: The Rift engine.
  7. * The specs of the format are from http://github.com/Panzerschrek/Chasm-Reverse
  8. * The format of the archive: (from the specs)
  9. *
  10. * A CSM file has three parts:
  11. * (1) a 6 byte header
  12. * (2) a TOC that contains the names, offsets, and
  13. * sizes of all the entries in the CSM.BIN
  14. *
  15. * The header consists of three four-byte parts:
  16. * (a) an ASCII string which must be "CSid"
  17. * (b) a uint16 which is the number of TOC entries in the CSM.BIN
  18. *
  19. * The TOC has one -byte entry for every lump. Each entry consists
  20. * of three parts:
  21. *
  22. * (a) a uint8, the length of the filename
  23. * (b) an 12-byte ASCII string, the name of the entry, padded with zeros.
  24. * (c) a uint32, the size of the entry in bytes
  25. * (d) a uint32, the file offset to the start of the entry
  26. *
  27. *
  28. *
  29. * Please see the file LICENSE.txt in the source's root directory.
  30. *
  31. * This file written by Jon Daniel, based on the WAD archiver by
  32. * Travis Wells.
  33. */
  34. #define __PHYSICSFS_INTERNAL__
  35. #include "physfs_internal.h"
  36. #if PHYSFS_SUPPORTS_CSM
  37. static int csmLoadEntries(PHYSFS_Io *io, const PHYSFS_uint16 count, void *arc)
  38. {
  39. PHYSFS_uint16 i;
  40. for (i = 0; i < count; i++)
  41. {
  42. PHYSFS_uint8 fn_len;
  43. char name[12];
  44. PHYSFS_uint32 size;
  45. PHYSFS_uint32 pos;
  46. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &fn_len, 1), 0);
  47. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 12), 0);
  48. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &size, 4), 0);
  49. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &pos, 4), 0);
  50. if(fn_len > 12) fn_len = 12;
  51. name[fn_len] = '\0'; /* name might not be null-terminated in file. */
  52. size = PHYSFS_swapULE32(size);
  53. pos = PHYSFS_swapULE32(pos);
  54. BAIL_IF_ERRPASS(!UNPK_addEntry(arc, name, 0, -1, -1, pos, size), 0);
  55. } /* for */
  56. return 1;
  57. } /* csmLoadEntries */
  58. static void *CSM_openArchive(PHYSFS_Io *io, const char *name,
  59. int forWriting, int *claimed)
  60. {
  61. PHYSFS_uint8 buf[4];
  62. PHYSFS_uint16 count;
  63. void *unpkarc;
  64. assert(io != NULL); /* shouldn't ever happen. */
  65. BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
  66. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, buf, sizeof (buf)), NULL);
  67. if (memcmp(buf, "CSid", 4) != 0)
  68. BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
  69. *claimed = 1;
  70. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof (count)), NULL);
  71. count = PHYSFS_swapULE16(count);
  72. unpkarc = UNPK_openArchive(io, 0, 1);
  73. BAIL_IF_ERRPASS(!unpkarc, NULL);
  74. if (!csmLoadEntries(io, count, unpkarc))
  75. {
  76. UNPK_abandonArchive(unpkarc);
  77. return NULL;
  78. } /* if */
  79. return unpkarc;
  80. } /* CSM_openArchive */
  81. const PHYSFS_Archiver __PHYSFS_Archiver_CSM =
  82. {
  83. CURRENT_PHYSFS_ARCHIVER_API_VERSION,
  84. {
  85. "BIN",
  86. "Chasm: The Rift engine format",
  87. "Jon Daniel <jondaniel879@gmail.com>",
  88. "http://www.github.com/Panzerschrek/Chasm-Reverse",
  89. 0, /* supportsSymlinks */
  90. },
  91. CSM_openArchive,
  92. UNPK_enumerate,
  93. UNPK_openRead,
  94. UNPK_openWrite,
  95. UNPK_openAppend,
  96. UNPK_remove,
  97. UNPK_mkdir,
  98. UNPK_stat,
  99. UNPK_closeArchive
  100. };
  101. #endif /* defined PHYSFS_SUPPORTS_CSM */
  102. /* end of physfs_archiver_CSM.c ... */