From 713d09f91655a195305bddf08434e17d516dc1b0 Mon Sep 17 00:00:00 2001 From: Jon Daniel Date: Sat, 24 Jun 2023 09:59:27 +0200 Subject: [PATCH] Support CSM.BIN in Chasm: The Rift and add ignores --- .gitignore | 11 +++- CMakeLists.txt | 7 +++ src/physfs.c | 3 + src/physfs.h | 1 + src/physfs_archiver_csm.c | 123 ++++++++++++++++++++++++++++++++++++++ src/physfs_internal.h | 4 ++ 6 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/physfs_archiver_csm.c diff --git a/.gitignore b/.gitignore index 7878ec04..709eee09 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,11 @@ cmake-build - +CMakeFiles/ +CMakeCache.txt +Makefile +test_physfs* +libphysfs.* +install_manifest.txt +cmake_install.cmake +CMakeDoxy* +extras/physfs.pc +Doxyfile diff --git a/CMakeLists.txt b/CMakeLists.txt index e84c7d04..6a5e7c18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,7 @@ set(PHYSFS_SRCS src/physfs_archiver_mvl.c src/physfs_archiver_qpak.c src/physfs_archiver_wad.c + src/physfs_archiver_csm.c src/physfs_archiver_zip.c src/physfs_archiver_slb.c src/physfs_archiver_iso9660.c @@ -124,6 +125,11 @@ if(NOT PHYSFS_ARCHIVE_WAD) add_definitions(-DPHYSFS_SUPPORTS_WAD=0) endif() +option(PHYSFS_ARCHIVE_CSM "Enable Chasm: The Rift CSM.BIN support" TRUE) +if(NOT PHYSFS_ARCHIVE_CSM) + add_definitions(-DPHYSFS_SUPPORTS_CSM=0) +endif() + option(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE) if(NOT PHYSFS_ARCHIVE_HOG) add_definitions(-DPHYSFS_SUPPORTS_HOG=0) @@ -318,6 +324,7 @@ message_bool_option("ZIP support" PHYSFS_ARCHIVE_ZIP) message_bool_option("7zip support" PHYSFS_ARCHIVE_7Z) message_bool_option("GRP support" PHYSFS_ARCHIVE_GRP) message_bool_option("WAD support" PHYSFS_ARCHIVE_WAD) +message_bool_option("CSM support" PHYSFS_ARCHIVE_CSM) message_bool_option("HOG support" PHYSFS_ARCHIVE_HOG) message_bool_option("MVL support" PHYSFS_ARCHIVE_MVL) message_bool_option("QPAK support" PHYSFS_ARCHIVE_QPAK) diff --git a/src/physfs.c b/src/physfs.c index 6476e0a7..a45011d1 100644 --- a/src/physfs.c +++ b/src/physfs.c @@ -1188,6 +1188,9 @@ static int initStaticArchivers(void) #if PHYSFS_SUPPORTS_WAD REGISTER_STATIC_ARCHIVER(WAD); #endif + #if PHYSFS_SUPPORTS_CSM + REGISTER_STATIC_ARCHIVER(CSM); + #endif #if PHYSFS_SUPPORTS_SLB REGISTER_STATIC_ARCHIVER(SLB); #endif diff --git a/src/physfs.h b/src/physfs.h index 3be60c49..f90029cf 100644 --- a/src/physfs.h +++ b/src/physfs.h @@ -148,6 +148,7 @@ * - .HOG (Descent I/II/III HOG file archives) * - .MVL (Descent II movielib archives) * - .WAD (DOOM engine archives) + * - .BIN (Chasm: The Rift engine archives) * - .VDF (Gothic I/II engine archives) * - .SLB (Independence War archives) * diff --git a/src/physfs_archiver_csm.c b/src/physfs_archiver_csm.c new file mode 100644 index 00000000..77f26c36 --- /dev/null +++ b/src/physfs_archiver_csm.c @@ -0,0 +1,123 @@ +/* + * CSM support routines for PhysicsFS. + * + * This driver handles Chasm: The Rift engine archives ("CSM.BINs"). + * This format (but not this driver) was developed by Action Forms Ltd. + * and published by Megamedia for use with the Chasm: The Rift engine. + * The specs of the format are from http://github.com/Panzerschrek/Chasm-Reverse + * The format of the archive: (from the specs) + * + * A CSM file has three parts: + * (1) a 6 byte header + * (2) a TOC that contains the names, offsets, and + * sizes of all the entries in the CSM.BIN + * + * The header consists of three four-byte parts: + * (a) an ASCII string which must be "CSid" + * (b) a uint16 which is the number of TOC entries in the CSM.BIN + * + * The TOC has one -byte entry for every lump. Each entry consists + * of three parts: + * + * (a) a uint8, the length of the filename + * (b) an 12-byte ASCII string, the name of the entry, padded with zeros. + * (c) a uint32, the size of the entry in bytes + * (d) a uint32, the file offset to the start of the entry + * + * + * + * Please see the file LICENSE.txt in the source's root directory. + * + * This file written by Jon Daniel, based on the WAD archiver by + * Travis Wells. + */ + +#define __PHYSICSFS_INTERNAL__ +#include "physfs_internal.h" + +#if PHYSFS_SUPPORTS_CSM + +static int csmLoadEntries(PHYSFS_Io *io, const PHYSFS_uint16 count, void *arc) +{ + PHYSFS_uint16 i; + for (i = 0; i < count; i++) + { + PHYSFS_uint8 fn_len; + char name[12]; + PHYSFS_uint32 size; + PHYSFS_uint32 pos; + + BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &fn_len, 1), 0); + BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 12), 0); + BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &size, 4), 0); + BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &pos, 4), 0); + + if(fn_len > 12) fn_len = 12; + name[fn_len] = '\0'; /* name might not be null-terminated in file. */ + size = PHYSFS_swapULE32(size); + pos = PHYSFS_swapULE32(pos); + BAIL_IF_ERRPASS(!UNPK_addEntry(arc, name, 0, -1, -1, pos, size), 0); + } /* for */ + + return 1; +} /* csmLoadEntries */ + + +static void *CSM_openArchive(PHYSFS_Io *io, const char *name, + int forWriting, int *claimed) +{ + PHYSFS_uint8 buf[4]; + PHYSFS_uint16 count; + void *unpkarc; + + assert(io != NULL); /* shouldn't ever happen. */ + + BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL); + BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, buf, sizeof (buf)), NULL); + if (memcmp(buf, "CSid", 4) != 0) + BAIL(PHYSFS_ERR_UNSUPPORTED, NULL); + + *claimed = 1; + + BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof (count)), NULL); + count = PHYSFS_swapULE16(count); + + + unpkarc = UNPK_openArchive(io, 0, 1); + BAIL_IF_ERRPASS(!unpkarc, NULL); + + if (!csmLoadEntries(io, count, unpkarc)) + { + UNPK_abandonArchive(unpkarc); + return NULL; + } /* if */ + + return unpkarc; +} /* CSM_openArchive */ + + +const PHYSFS_Archiver __PHYSFS_Archiver_CSM = +{ + CURRENT_PHYSFS_ARCHIVER_API_VERSION, + { + "CSM", + "Chasm: The Rift engine format", + "Jon Daniel ", + "http://www.github.com/Panzerschrek/Chasm-Reverse", + 0, /* supportsSymlinks */ + }, + CSM_openArchive, + UNPK_enumerate, + UNPK_openRead, + UNPK_openWrite, + UNPK_openAppend, + UNPK_remove, + UNPK_mkdir, + UNPK_stat, + UNPK_closeArchive +}; + +#endif /* defined PHYSFS_SUPPORTS_CSM */ + +/* end of physfs_archiver_CSM.c ... */ + diff --git a/src/physfs_internal.h b/src/physfs_internal.h index 2200d4d5..b29830ec 100644 --- a/src/physfs_internal.h +++ b/src/physfs_internal.h @@ -88,6 +88,7 @@ extern const PHYSFS_Archiver __PHYSFS_Archiver_QPAK; extern const PHYSFS_Archiver __PHYSFS_Archiver_HOG; extern const PHYSFS_Archiver __PHYSFS_Archiver_MVL; extern const PHYSFS_Archiver __PHYSFS_Archiver_WAD; +extern const PHYSFS_Archiver __PHYSFS_Archiver_CSM; extern const PHYSFS_Archiver __PHYSFS_Archiver_SLB; extern const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660; extern const PHYSFS_Archiver __PHYSFS_Archiver_VDF; @@ -200,6 +201,9 @@ void __PHYSFS_smallFree(void *ptr); #ifndef PHYSFS_SUPPORTS_WAD #define PHYSFS_SUPPORTS_WAD PHYSFS_SUPPORTS_DEFAULT #endif +#ifndef PHYSFS_SUPPORTS_CSM +#define PHYSFS_SUPPORTS_CSM PHYSFS_SUPPORTS_DEFAULT +#endif #ifndef PHYSFS_SUPPORTS_QPAK #define PHYSFS_SUPPORTS_QPAK PHYSFS_SUPPORTS_DEFAULT #endif