45 #if (defined PHYSFS_SUPPORTS_WAD) |
45 #if (defined PHYSFS_SUPPORTS_WAD) |
46 |
46 |
47 #define __PHYSICSFS_INTERNAL__ |
47 #define __PHYSICSFS_INTERNAL__ |
48 #include "physfs_internal.h" |
48 #include "physfs_internal.h" |
49 |
49 |
50 static inline int readAll(PHYSFS_Io *io, void *buf, const PHYSFS_uint64 len) |
|
51 { |
|
52 return (io->read(io, buf, len) == len); |
|
53 } /* readAll */ |
|
54 |
|
55 |
|
56 static UNPKentry *wadLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount) |
50 static UNPKentry *wadLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount) |
57 { |
51 { |
58 PHYSFS_uint32 directoryOffset; |
52 PHYSFS_uint32 directoryOffset; |
59 UNPKentry *entries = NULL; |
53 UNPKentry *entries = NULL; |
60 UNPKentry *entry = NULL; |
54 UNPKentry *entry = NULL; |
61 |
55 |
62 BAIL_IF_MACRO(!readAll(io, &directoryOffset, 4), NULL, 0); |
56 BAIL_IF_MACRO(!__PHYSFS_readAll(io, &directoryOffset, 4), NULL, 0); |
63 directoryOffset = PHYSFS_swapULE32(directoryOffset); |
57 directoryOffset = PHYSFS_swapULE32(directoryOffset); |
64 |
58 |
65 BAIL_IF_MACRO(!io->seek(io, directoryOffset), NULL, 0); |
59 BAIL_IF_MACRO(!io->seek(io, directoryOffset), NULL, 0); |
66 |
60 |
67 entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount); |
61 entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount); |
68 BAIL_IF_MACRO(entries == NULL, ERR_OUT_OF_MEMORY, NULL); |
62 BAIL_IF_MACRO(entries == NULL, ERR_OUT_OF_MEMORY, NULL); |
69 |
63 |
70 for (entry = entries; fileCount > 0; fileCount--, entry++) |
64 for (entry = entries; fileCount > 0; fileCount--, entry++) |
71 { |
65 { |
72 GOTO_IF_MACRO(!readAll(io, &entry->startPos, 4), NULL, wadLoad_failed); |
66 GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->startPos, 4), NULL, failed); |
73 GOTO_IF_MACRO(!readAll(io, &entry->size, 4), NULL, wadLoad_failed); |
67 GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->size, 4), NULL, failed); |
74 GOTO_IF_MACRO(!readAll(io, &entry->name, 8), NULL, wadLoad_failed); |
68 GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->name, 8), NULL, failed); |
75 |
69 |
76 entry->name[8] = '\0'; /* name might not be null-terminated in file. */ |
70 entry->name[8] = '\0'; /* name might not be null-terminated in file. */ |
77 entry->size = PHYSFS_swapULE32(entry->size); |
71 entry->size = PHYSFS_swapULE32(entry->size); |
78 entry->startPos = PHYSFS_swapULE32(entry->startPos); |
72 entry->startPos = PHYSFS_swapULE32(entry->startPos); |
79 } /* for */ |
73 } /* for */ |
80 |
74 |
81 return entries; |
75 return entries; |
82 |
76 |
83 wadLoad_failed: |
77 failed: |
84 allocator.Free(entries); |
78 allocator.Free(entries); |
85 return NULL; |
79 return NULL; |
86 } /* wadLoadEntries */ |
80 } /* wadLoadEntries */ |
87 |
81 |
88 |
82 |
89 static void *WAD_openArchive(PHYSFS_Io *io, const char *name, int forWriting) |
83 static void *WAD_openArchive(PHYSFS_Io *io, const char *name, int forWriting) |
90 { |
84 { |
91 PHYSFS_uint8 buf[4]; |
85 PHYSFS_uint8 buf[4]; |
92 UNPKentry *entries = NULL; |
86 UNPKentry *entries = NULL; |
93 PHYSFS_uint32 entryCount = 0; |
87 PHYSFS_uint32 count = 0; |
94 |
88 |
95 assert(io != NULL); /* shouldn't ever happen. */ |
89 assert(io != NULL); /* shouldn't ever happen. */ |
96 |
90 |
97 BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0); |
91 BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0); |
98 BAIL_IF_MACRO(!readAll(io, buf, sizeof (buf)), NULL, NULL); |
92 BAIL_IF_MACRO(!__PHYSFS_readAll(io, buf, sizeof (buf)), NULL, NULL); |
99 if ((memcmp(buf, "IWAD", 4) != 0) && (memcmp(buf, "PWAD", 4) != 0)) |
93 if ((memcmp(buf, "IWAD", 4) != 0) && (memcmp(buf, "PWAD", 4) != 0)) |
100 BAIL_MACRO(ERR_NOT_AN_ARCHIVE, NULL); |
94 BAIL_MACRO(ERR_NOT_AN_ARCHIVE, NULL); |
101 |
95 |
102 BAIL_IF_MACRO(!readAll(io, &entryCount, sizeof (entryCount)), NULL, NULL); |
96 BAIL_IF_MACRO(!__PHYSFS_readAll(io, &count, sizeof (count)), NULL, NULL); |
103 entryCount = PHYSFS_swapULE32(entryCount); |
97 count = PHYSFS_swapULE32(count); |
104 |
98 |
105 entries = wadLoadEntries(io, entryCount); |
99 entries = wadLoadEntries(io, count); |
106 BAIL_IF_MACRO(entries == NULL, NULL, NULL); |
100 BAIL_IF_MACRO(entries == NULL, NULL, NULL); |
107 return UNPK_openArchive(io, entries, entryCount); |
101 return UNPK_openArchive(io, entries, count); |
108 } /* WAD_openArchive */ |
102 } /* WAD_openArchive */ |
109 |
103 |
110 |
104 |
111 const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_WAD = |
105 const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_WAD = |
112 { |
106 { |