Subversion Repositories eduke32

Rev

Rev 3618 | Rev 3661 | 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
{
109
    struct grpfile *grp, *fg;
110
 
111
    for (grp = foundgrps; grp; grp=grp->next)
112
    {
113
        if (grp->crcval == crcval)
114
        {
115
            if (grp == foundgrps)
116
                foundgrps = grp->next;
117
            else fg->next = grp->next;
118
 
119
            Bfree((char *)grp->name);
120
            Bfree(grp);
121
 
122
            break;
123
        }
124
 
125
        fg = grp;
126
    }
127
}
128
 
129
struct grpfile * FindGroup(int32_t crcval)
130
{
131
    struct grpfile *grp;
132
 
133
    for (grp = foundgrps; grp; grp=grp->next)
134
    {
135
        if (grp->crcval == crcval)
136
            return grp;
137
    }
138
 
139
    return NULL;
140
}
141
 
1205 terminx 142
int32_t ScanGroups(void)
241 terminx 143
{
144
    CACHE1D_FIND_REC *srch, *sidx;
145
    struct grpcache *fg, *fgg;
146
    struct grpfile *grp;
147
    char *fn;
148
    struct Bstat st;
1430 terminx 149
#define BUFFER_SIZE (1024 * 1024 * 8)
3176 helixhorne 150
    uint8_t *buf = (uint8_t *)Bmalloc(BUFFER_SIZE);
241 terminx 151
 
1431 terminx 152
    if (!buf)
1430 terminx 153
    {
154
        initprintf("Error allocating %d byte buffer to scan GRPs!\n", BUFFER_SIZE);
155
        return 0;
156
    }
157
 
1643 terminx 158
    initprintf("Searching for game data...\n");
241 terminx 159
 
160
    LoadGroupsCache();
161
 
162
    srch = klistpath("/", "*.grp", CACHE1D_FIND_FILE);
163
 
335 terminx 164
    for (sidx = srch; sidx; sidx = sidx->next)
165
    {
166
        for (fg = grpcache; fg; fg = fg->next)
167
        {
241 terminx 168
            if (!Bstrcmp(fg->name, sidx->name)) break;
169
        }
170
 
335 terminx 171
        if (fg)
172
        {
2726 hendricks2 173
            if (findfrompath(sidx->name, &fn)) continue; // failed to resolve the filename
335 terminx 174
            if (Bstat(fn, &st))
175
            {
1527 terminx 176
                Bfree(fn);
335 terminx 177
                continue;
2726 hendricks2 178
            } // failed to stat the file
1527 terminx 179
            Bfree(fn);
335 terminx 180
            if (fg->size == st.st_size && fg->mtime == st.st_mtime)
181
            {
808 terminx 182
                grp = (struct grpfile *)Bcalloc(1, sizeof(struct grpfile));
1527 terminx 183
                grp->name = Bstrdup(sidx->name);
241 terminx 184
                grp->crcval = fg->crcval;
185
                grp->size = fg->size;
186
                grp->next = foundgrps;
187
                foundgrps = grp;
188
 
808 terminx 189
                fgg = (struct grpcache *)Bcalloc(1, sizeof(struct grpcache));
241 terminx 190
                strcpy(fgg->name, fg->name);
191
                fgg->size = fg->size;
192
                fgg->mtime = fg->mtime;
193
                fgg->crcval = fg->crcval;
194
                fgg->next = usedgrpcache;
195
                usedgrpcache = fgg;
196
                continue;
197
            }
198
        }
199
 
200
        {
1205 terminx 201
            int32_t b, fh;
202
            int32_t crcval;
241 terminx 203
 
204
            fh = openfrompath(sidx->name, BO_RDONLY|BO_BINARY, BS_IREAD);
205
            if (fh < 0) continue;
3171 helixhorne 206
            if (Bfstat(fh, &st)) continue;
241 terminx 207
 
208
            initprintf(" Checksumming %s...", sidx->name);
1205 terminx 209
            crc32init((uint32_t *)&crcval);
335 terminx 210
            do
211
            {
1430 terminx 212
                b = read(fh, buf, BUFFER_SIZE);
1205 terminx 213
                if (b > 0) crc32block((uint32_t *)&crcval, (uint8_t *)buf, b);
335 terminx 214
            }
1430 terminx 215
            while (b == BUFFER_SIZE);
1205 terminx 216
            crc32finish((uint32_t *)&crcval);
241 terminx 217
            close(fh);
218
            initprintf(" Done\n");
219
 
808 terminx 220
            grp = (struct grpfile *)Bcalloc(1, sizeof(struct grpfile));
1527 terminx 221
            grp->name = Bstrdup(sidx->name);
241 terminx 222
            grp->crcval = crcval;
223
            grp->size = st.st_size;
224
            grp->next = foundgrps;
225
            foundgrps = grp;
226
 
808 terminx 227
            fgg = (struct grpcache *)Bcalloc(1, sizeof(struct grpcache));
1221 terminx 228
            Bstrncpy(fgg->name, sidx->name, BMAX_PATH);
241 terminx 229
            fgg->size = st.st_size;
230
            fgg->mtime = st.st_mtime;
231
            fgg->crcval = crcval;
232
            fgg->next = usedgrpcache;
233
            usedgrpcache = fgg;
234
        }
235
    }
236
 
237
    klistfree(srch);
238
    FreeGroupsCache();
239
 
3654 terminx 240
    for (grp = foundgrps; grp; /*grp=grp->next*/)
241
    {
242
        int32_t i;
243
 
244
        for (i = 0; i<NUMGRPFILES; i++) if (grp->crcval == grpfiles[i].crcval) break;
245
        if (i == NUMGRPFILES) continue; // unrecognised grp file
246
 
247
        if (grpfiles[i].dependency)
248
        {
249
            //initprintf("found grp with dep\n");
250
            for (grp = foundgrps; grp; grp=grp->next)
251
                if (grp->crcval == grpfiles[i].dependency) break;
252
 
253
            if (grp == NULL || grp->crcval != grpfiles[i].dependency) // couldn't find dependency
254
            {
255
                //initprintf("removing %s\n", grp->name);
256
                RemoveGroup(grpfiles[i].crcval);
257
                grp = foundgrps;
258
                continue;
259
            }
260
        }
261
 
262
        grp=grp->next;
263
    }
264
 
335 terminx 265
    if (usedgrpcache)
266
    {
1205 terminx 267
        int32_t i = 0;
241 terminx 268
        FILE *fp;
269
        fp = fopen(GRPCACHEFILE, "wt");
335 terminx 270
        if (fp)
271
        {
272
            for (fg = usedgrpcache; fg; fg=fgg)
273
            {
241 terminx 274
                fgg = fg->next;
275
                fprintf(fp, "\"%s\" %d %d %d\n", fg->name, fg->size, fg->mtime, fg->crcval);
1527 terminx 276
                Bfree(fg);
1000 terminx 277
                i++;
241 terminx 278
            }
279
            fclose(fp);
280
        }
1178 terminx 281
//        initprintf("Found %d recognized GRP %s.\n",i,i>1?"files":"file");
2978 helixhorne 282
 
283
        Bfree(buf);
1000 terminx 284
        return 0;
241 terminx 285
    }
1642 terminx 286
 
287
    initprintf("Found no recognized game data!\n");
288
 
2978 helixhorne 289
    Bfree(buf);
241 terminx 290
    return 0;
291
}
292
 
3654 terminx 293
 
241 terminx 294
void FreeGroups(void)
295
{
296
    struct grpfile *fg;
297
 
335 terminx 298
    while (foundgrps)
299
    {
241 terminx 300
        fg = foundgrps->next;
1677 terminx 301
        Bfree((char *)foundgrps->name);
1527 terminx 302
        Bfree(foundgrps);
241 terminx 303
        foundgrps = fg;
304
    }
305
}
306