Subversion Repositories eduke32

Rev

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