Rev 3654 | Rev 3708 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1652 | terminx | 1 | //------------------------------------------------------------------------- |
2 | /* |
||
3 | Copyright (C) 2010 EDuke32 developers and contributors |
||
4 | |||
5 | This file is part of EDuke32. |
||
6 | |||
7 | EDuke32 is free software; you can redistribute it and/or |
||
8 | modify it under the terms of the GNU General Public License version 2 |
||
9 | as published by the Free Software Foundation. |
||
10 | |||
11 | This program is distributed in the hope that it will be useful, |
||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
14 | |||
15 | See the GNU General Public License for more details. |
||
16 | |||
17 | You should have received a copy of the GNU General Public License |
||
18 | along with this program; if not, write to the Free Software |
||
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
20 | */ |
||
21 | //------------------------------------------------------------------------- |
||
22 | |||
241 | terminx | 23 | #include "compat.h" |
24 | #include "baselayer.h" |
||
25 | |||
26 | #include "scriptfile.h" |
||
27 | #include "cache1d.h" |
||
28 | #include "crc32.h" |
||
29 | |||
30 | #include "duke3d.h" |
||
2726 | hendricks2 | 31 | #include "common_game.h" |
241 | terminx | 32 | #include "grpscan.h" |
33 | |||
2543 | helixhorne | 34 | struct grpfile grpfiles[NUMGRPFILES] = |
559 | terminx | 35 | { |
3654 | terminx | 36 | { "Duke Nukem 3D", DUKE13_CRC, 26524524, GAMEFLAG_DUKE, 0, NULL, NULL }, |
37 | { "Duke Nukem 3D (South Korean Censored)", DUKEKR_CRC, 26385383, GAMEFLAG_DUKE, 0, NULL, NULL }, |
||
38 | { "Duke Nukem 3D: Atomic Edition", DUKE15_CRC, 44356548, GAMEFLAG_DUKE, 0, NULL, NULL }, |
||
39 | { "Duke Nukem 3D: Plutonium Pak", DUKEPP_CRC, 44348015, GAMEFLAG_DUKE, 0, NULL, NULL }, |
||
40 | { "Duke Nukem 3D Shareware", DUKESW_CRC, 11035779, GAMEFLAG_DUKE, 0, NULL, NULL }, |
||
41 | { "Duke Nukem 3D Mac Demo", DUKEMD_CRC, 10444391, GAMEFLAG_DUKE, 0, NULL, NULL }, |
||
42 | { "Duke it out in D.C.", DUKEDC_CRC, 8410183 , GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, NULL, NULL }, |
||
43 | { "Duke Caribbean: Life's a Beach", DUKECB_CRC, 22213819, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, NULL, NULL }, |
||
44 | { "Duke: Nuclear Winter", DUKENW_CRC, 16169365, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, "nwinter.con", NULL }, |
||
45 | { "NAM", NAM_CRC, 43448927, GAMEFLAG_NAM, 0, NULL, NULL }, |
||
46 | { "NAPALM", NAPALM_CRC, 44365728, GAMEFLAG_NAM|GAMEFLAG_NAPALM, 0, NULL, NULL }, |
||
47 | { "WWII GI", WW2GI_CRC, 77939508, GAMEFLAG_WW2GI|GAMEFLAG_NAM, 0, NULL, NULL }, |
||
559 | terminx | 48 | }; |
241 | terminx | 49 | struct grpfile *foundgrps = NULL; |
50 | |||
51 | #define GRPCACHEFILE "grpfiles.cache" |
||
335 | terminx | 52 | static struct grpcache |
53 | { |
||
241 | terminx | 54 | struct grpcache *next; |
1205 | terminx | 55 | int32_t size; |
56 | int32_t mtime; |
||
57 | int32_t crcval; |
||
1457 | terminx | 58 | char name[BMAX_PATH]; |
335 | terminx | 59 | } |
60 | *grpcache = NULL, *usedgrpcache = NULL; |
||
241 | terminx | 61 | |
1205 | terminx | 62 | static int32_t LoadGroupsCache(void) |
241 | terminx | 63 | { |
64 | struct grpcache *fg; |
||
65 | |||
1205 | terminx | 66 | int32_t fsize, fmtime, fcrcval; |
241 | terminx | 67 | char *fname; |
68 | |||
69 | scriptfile *script; |
||
70 | |||
71 | script = scriptfile_fromfile(GRPCACHEFILE); |
||
72 | if (!script) return -1; |
||
73 | |||
335 | terminx | 74 | while (!scriptfile_eof(script)) |
75 | { |
||
2726 | hendricks2 | 76 | if (scriptfile_getstring(script, &fname)) break; // filename |
77 | if (scriptfile_getnumber(script, &fsize)) break; // filesize |
||
78 | if (scriptfile_getnumber(script, &fmtime)) break; // modification time |
||
79 | if (scriptfile_getnumber(script, &fcrcval)) break; // crc checksum |
||
241 | terminx | 80 | |
3176 | helixhorne | 81 | fg = (struct grpcache *)Bcalloc(1, sizeof(struct grpcache)); |
241 | terminx | 82 | fg->next = grpcache; |
83 | grpcache = fg; |
||
84 | |||
1221 | terminx | 85 | Bstrncpy(fg->name, fname, BMAX_PATH); |
241 | terminx | 86 | fg->size = fsize; |
87 | fg->mtime = fmtime; |
||
88 | fg->crcval = fcrcval; |
||
89 | } |
||
90 | |||
91 | scriptfile_close(script); |
||
92 | return 0; |
||
93 | } |
||
94 | |||
95 | static void FreeGroupsCache(void) |
||
96 | { |
||
97 | struct grpcache *fg; |
||
98 | |||
335 | terminx | 99 | while (grpcache) |
100 | { |
||
241 | terminx | 101 | fg = grpcache->next; |
1527 | terminx | 102 | Bfree(grpcache); |
241 | terminx | 103 | grpcache = fg; |
104 | } |
||
105 | } |
||
106 | |||
3654 | terminx | 107 | void RemoveGroup(int32_t crcval) |
108 | { |
||
3661 | terminx | 109 | struct grpfile *grp; |
3654 | terminx | 110 | |
111 | for (grp = foundgrps; grp; grp=grp->next) |
||
112 | { |
||
113 | if (grp->crcval == crcval) |
||
114 | { |
||
115 | if (grp == foundgrps) |
||
116 | foundgrps = grp->next; |
||
3661 | terminx | 117 | else |
118 | { |
||
119 | struct grpfile *fg; |
||
3654 | terminx | 120 | |
3661 | terminx | 121 | for (fg = foundgrps; fg; fg=fg->next) |
122 | { |
||
123 | if (fg->next == grp) |
||
124 | { |
||
125 | fg->next = grp->next; |
||
126 | break; |
||
127 | } |
||
128 | } |
||
129 | } |
||
130 | |||
3654 | terminx | 131 | Bfree((char *)grp->name); |
132 | Bfree(grp); |
||
133 | |||
3661 | terminx | 134 | RemoveGroup(crcval); |
135 | |||
3654 | terminx | 136 | break; |
137 | } |
||
138 | } |
||
139 | } |
||
140 | |||
141 | struct grpfile * FindGroup(int32_t crcval) |
||
142 | { |
||
143 | struct grpfile *grp; |
||
144 | |||
145 | for (grp = foundgrps; grp; grp=grp->next) |
||
146 | { |
||
147 | if (grp->crcval == crcval) |
||
148 | return grp; |
||
149 | } |
||
150 | |||
151 | return NULL; |
||
152 | } |
||
153 | |||
1205 | terminx | 154 | int32_t ScanGroups(void) |
241 | terminx | 155 | { |
156 | CACHE1D_FIND_REC *srch, *sidx; |
||
157 | struct grpcache *fg, *fgg; |
||
158 | struct grpfile *grp; |
||
159 | char *fn; |
||
160 | struct Bstat st; |
||
1430 | terminx | 161 | #define BUFFER_SIZE (1024 * 1024 * 8) |
3176 | helixhorne | 162 | uint8_t *buf = (uint8_t *)Bmalloc(BUFFER_SIZE); |
241 | terminx | 163 | |
1431 | terminx | 164 | if (!buf) |
1430 | terminx | 165 | { |
166 | initprintf("Error allocating %d byte buffer to scan GRPs!\n", BUFFER_SIZE); |
||
167 | return 0; |
||
168 | } |
||
169 | |||
1643 | terminx | 170 | initprintf("Searching for game data...\n"); |
241 | terminx | 171 | |
172 | LoadGroupsCache(); |
||
173 | |||
174 | srch = klistpath("/", "*.grp", CACHE1D_FIND_FILE); |
||
175 | |||
335 | terminx | 176 | for (sidx = srch; sidx; sidx = sidx->next) |
177 | { |
||
178 | for (fg = grpcache; fg; fg = fg->next) |
||
179 | { |
||
241 | terminx | 180 | if (!Bstrcmp(fg->name, sidx->name)) break; |
181 | } |
||
182 | |||
335 | terminx | 183 | if (fg) |
184 | { |
||
2726 | hendricks2 | 185 | if (findfrompath(sidx->name, &fn)) continue; // failed to resolve the filename |
335 | terminx | 186 | if (Bstat(fn, &st)) |
187 | { |
||
1527 | terminx | 188 | Bfree(fn); |
335 | terminx | 189 | continue; |
2726 | hendricks2 | 190 | } // failed to stat the file |
1527 | terminx | 191 | Bfree(fn); |
335 | terminx | 192 | if (fg->size == st.st_size && fg->mtime == st.st_mtime) |
193 | { |
||
808 | terminx | 194 | grp = (struct grpfile *)Bcalloc(1, sizeof(struct grpfile)); |
1527 | terminx | 195 | grp->name = Bstrdup(sidx->name); |
241 | terminx | 196 | grp->crcval = fg->crcval; |
197 | grp->size = fg->size; |
||
198 | grp->next = foundgrps; |
||
199 | foundgrps = grp; |
||
200 | |||
808 | terminx | 201 | fgg = (struct grpcache *)Bcalloc(1, sizeof(struct grpcache)); |
241 | terminx | 202 | strcpy(fgg->name, fg->name); |
203 | fgg->size = fg->size; |
||
204 | fgg->mtime = fg->mtime; |
||
205 | fgg->crcval = fg->crcval; |
||
206 | fgg->next = usedgrpcache; |
||
207 | usedgrpcache = fgg; |
||
208 | continue; |
||
209 | } |
||
210 | } |
||
211 | |||
212 | { |
||
1205 | terminx | 213 | int32_t b, fh; |
214 | int32_t crcval; |
||
241 | terminx | 215 | |
216 | fh = openfrompath(sidx->name, BO_RDONLY|BO_BINARY, BS_IREAD); |
||
217 | if (fh < 0) continue; |
||
3171 | helixhorne | 218 | if (Bfstat(fh, &st)) continue; |
241 | terminx | 219 | |
220 | initprintf(" Checksumming %s...", sidx->name); |
||
1205 | terminx | 221 | crc32init((uint32_t *)&crcval); |
335 | terminx | 222 | do |
223 | { |
||
1430 | terminx | 224 | b = read(fh, buf, BUFFER_SIZE); |
1205 | terminx | 225 | if (b > 0) crc32block((uint32_t *)&crcval, (uint8_t *)buf, b); |
335 | terminx | 226 | } |
1430 | terminx | 227 | while (b == BUFFER_SIZE); |
1205 | terminx | 228 | crc32finish((uint32_t *)&crcval); |
241 | terminx | 229 | close(fh); |
230 | initprintf(" Done\n"); |
||
231 | |||
808 | terminx | 232 | grp = (struct grpfile *)Bcalloc(1, sizeof(struct grpfile)); |
1527 | terminx | 233 | grp->name = Bstrdup(sidx->name); |
241 | terminx | 234 | grp->crcval = crcval; |
235 | grp->size = st.st_size; |
||
236 | grp->next = foundgrps; |
||
237 | foundgrps = grp; |
||
238 | |||
808 | terminx | 239 | fgg = (struct grpcache *)Bcalloc(1, sizeof(struct grpcache)); |
1221 | terminx | 240 | Bstrncpy(fgg->name, sidx->name, BMAX_PATH); |
241 | terminx | 241 | fgg->size = st.st_size; |
242 | fgg->mtime = st.st_mtime; |
||
243 | fgg->crcval = crcval; |
||
244 | fgg->next = usedgrpcache; |
||
245 | usedgrpcache = fgg; |
||
246 | } |
||
247 | } |
||
248 | |||
249 | klistfree(srch); |
||
250 | FreeGroupsCache(); |
||
251 | |||
3654 | terminx | 252 | for (grp = foundgrps; grp; /*grp=grp->next*/) |
253 | { |
||
254 | int32_t i; |
||
255 | |||
256 | for (i = 0; i<NUMGRPFILES; i++) if (grp->crcval == grpfiles[i].crcval) break; |
||
3661 | terminx | 257 | if (i == NUMGRPFILES) { grp=grp->next; continue; } // unrecognised grp file |
3654 | terminx | 258 | |
259 | if (grpfiles[i].dependency) |
||
260 | { |
||
261 | //initprintf("found grp with dep\n"); |
||
262 | for (grp = foundgrps; grp; grp=grp->next) |
||
263 | if (grp->crcval == grpfiles[i].dependency) break; |
||
264 | |||
265 | if (grp == NULL || grp->crcval != grpfiles[i].dependency) // couldn't find dependency |
||
266 | { |
||
267 | //initprintf("removing %s\n", grp->name); |
||
268 | RemoveGroup(grpfiles[i].crcval); |
||
269 | grp = foundgrps; |
||
270 | continue; |
||
271 | } |
||
272 | } |
||
273 | |||
274 | grp=grp->next; |
||
275 | } |
||
276 | |||
335 | terminx | 277 | if (usedgrpcache) |
278 | { |
||
1205 | terminx | 279 | int32_t i = 0; |
241 | terminx | 280 | FILE *fp; |
281 | fp = fopen(GRPCACHEFILE, "wt"); |
||
335 | terminx | 282 | if (fp) |
283 | { |
||
284 | for (fg = usedgrpcache; fg; fg=fgg) |
||
285 | { |
||
241 | terminx | 286 | fgg = fg->next; |
287 | fprintf(fp, "\"%s\" %d %d %d\n", fg->name, fg->size, fg->mtime, fg->crcval); |
||
1527 | terminx | 288 | Bfree(fg); |
1000 | terminx | 289 | i++; |
241 | terminx | 290 | } |
291 | fclose(fp); |
||
292 | } |
||
1178 | terminx | 293 | // initprintf("Found %d recognized GRP %s.\n",i,i>1?"files":"file"); |
2978 | helixhorne | 294 | |
295 | Bfree(buf); |
||
1000 | terminx | 296 | return 0; |
241 | terminx | 297 | } |
1642 | terminx | 298 | |
299 | initprintf("Found no recognized game data!\n"); |
||
300 | |||
2978 | helixhorne | 301 | Bfree(buf); |
241 | terminx | 302 | return 0; |
303 | } |
||
304 | |||
3654 | terminx | 305 | |
241 | terminx | 306 | void FreeGroups(void) |
307 | { |
||
308 | struct grpfile *fg; |
||
309 | |||
335 | terminx | 310 | while (foundgrps) |
311 | { |
||
241 | terminx | 312 | fg = foundgrps->next; |
1677 | terminx | 313 | Bfree((char *)foundgrps->name); |
1527 | terminx | 314 | Bfree(foundgrps); |
241 | terminx | 315 | foundgrps = fg; |
316 | } |
||
317 | } |
||
318 |