Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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