1 /* |
|
2 * SLB support routines for PhysicsFS. |
|
3 * |
|
4 * This driver handles SLB archives ("slab files"). This uncompressed format |
|
5 * is used in I-War / Independence War and Independence War: Defiance. |
|
6 * |
|
7 * The format begins with four zero bytes (version?), the file count and the |
|
8 * location of the table of contents. Each ToC entry contains a 64-byte buffer |
|
9 * containing a zero-terminated filename, the offset of the data, and its size. |
|
10 * All the filenames begin with the separator character '\'. |
|
11 * |
|
12 * Please see the file LICENSE.txt in the source's root directory. |
|
13 * |
|
14 * This file written by Aleksi Nurmi, based on the GRP archiver by |
|
15 * Ryan C. Gordon. |
|
16 */ |
|
17 |
|
18 #define __PHYSICSFS_INTERNAL__ |
|
19 #include "physfs_internal.h" |
|
20 |
|
21 #if PHYSFS_SUPPORTS_SLB |
|
22 |
|
23 static UNPKentry *slbLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount) |
|
24 { |
|
25 UNPKentry *entries = NULL; |
|
26 UNPKentry *entry = NULL; |
|
27 |
|
28 entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount); |
|
29 BAIL_IF_MACRO(entries == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL); |
|
30 |
|
31 for (entry = entries; fileCount > 0; fileCount--, entry++) |
|
32 { |
|
33 char *ptr; |
|
34 |
|
35 /* don't include the '\' in the beginning */ |
|
36 char backslash; |
|
37 GOTO_IF_MACRO(!__PHYSFS_readAll(io, &backslash, 1), ERRPASS, failed); |
|
38 GOTO_IF_MACRO(backslash != '\\', ERRPASS, failed); |
|
39 |
|
40 /* read the rest of the buffer, 63 bytes */ |
|
41 GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->name, 63), ERRPASS, failed); |
|
42 entry->name[63] = '\0'; /* in case the name lacks the null terminator */ |
|
43 |
|
44 /* convert backslashes */ |
|
45 for (ptr = entry->name; *ptr; ptr++) |
|
46 { |
|
47 if (*ptr == '\\') |
|
48 *ptr = '/'; |
|
49 } /* for */ |
|
50 |
|
51 GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->startPos, 4), |
|
52 ERRPASS, failed); |
|
53 entry->startPos = PHYSFS_swapULE32(entry->startPos); |
|
54 |
|
55 GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->size, 4), ERRPASS, failed); |
|
56 entry->size = PHYSFS_swapULE32(entry->size); |
|
57 } /* for */ |
|
58 |
|
59 return entries; |
|
60 |
|
61 failed: |
|
62 allocator.Free(entries); |
|
63 return NULL; |
|
64 |
|
65 } /* slbLoadEntries */ |
|
66 |
|
67 |
|
68 static void *SLB_openArchive(PHYSFS_Io *io, const char *name, int forWriting) |
|
69 { |
|
70 PHYSFS_uint32 version; |
|
71 PHYSFS_uint32 count = 0; |
|
72 PHYSFS_uint32 tocPos = 0; |
|
73 UNPKentry *entries = NULL; |
|
74 |
|
75 assert(io != NULL); /* shouldn't ever happen. */ |
|
76 |
|
77 BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL); |
|
78 |
|
79 BAIL_IF_MACRO(!__PHYSFS_readAll(io, &version, sizeof(version)), |
|
80 ERRPASS, NULL); |
|
81 version = PHYSFS_swapULE32(version); |
|
82 BAIL_IF_MACRO(version != 0, ERRPASS, NULL); |
|
83 |
|
84 BAIL_IF_MACRO(!__PHYSFS_readAll(io, &count, sizeof(count)), ERRPASS, NULL); |
|
85 count = PHYSFS_swapULE32(count); |
|
86 |
|
87 /* offset of the table of contents */ |
|
88 BAIL_IF_MACRO(!__PHYSFS_readAll(io, &tocPos, sizeof(tocPos)), |
|
89 ERRPASS, NULL); |
|
90 tocPos = PHYSFS_swapULE32(tocPos); |
|
91 |
|
92 /* seek to the table of contents */ |
|
93 BAIL_IF_MACRO(!io->seek(io, tocPos), ERRPASS, NULL); |
|
94 |
|
95 entries = slbLoadEntries(io, count); |
|
96 BAIL_IF_MACRO(!entries, ERRPASS, NULL); |
|
97 |
|
98 return UNPK_openArchive(io, entries, count); |
|
99 } /* SLB_openArchive */ |
|
100 |
|
101 |
|
102 const PHYSFS_Archiver __PHYSFS_Archiver_SLB = |
|
103 { |
|
104 CURRENT_PHYSFS_ARCHIVER_API_VERSION, |
|
105 { |
|
106 "SLB", |
|
107 "I-War / Independence War Slab file", |
|
108 "Aleksi Nurmi <aleksi.nurmi@gmail.com>", |
|
109 "https://bitbucket.org/ahnurmi/", |
|
110 0, /* supportsSymlinks */ |
|
111 }, |
|
112 SLB_openArchive, |
|
113 UNPK_enumerateFiles, |
|
114 UNPK_openRead, |
|
115 UNPK_openWrite, |
|
116 UNPK_openAppend, |
|
117 UNPK_remove, |
|
118 UNPK_mkdir, |
|
119 UNPK_stat, |
|
120 UNPK_closeArchive |
|
121 }; |
|
122 |
|
123 #endif /* defined PHYSFS_SUPPORTS_SLB */ |
|
124 |
|
125 /* end of archiver_slb.c ... */ |
|
126 |
|