Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
298 serge 1
// Emacs style mode select   -*- C++ -*-
2
//-----------------------------------------------------------------------------
3
//
4
// $Id:$
5
//
6
// Copyright (C) 1993-1996 by id Software, Inc.
7
//
8
// This source is available for distribution and/or modification
9
// only under the terms of the DOOM Source Code License as
10
// published by id Software. All rights reserved.
11
//
12
// The source is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15
// for more details.
16
//
17
// $Log:$
18
//
19
// DESCRIPTION:
333 serge 20
//      Handles WAD file header, directory, lump I/O.
298 serge 21
//
22
//-----------------------------------------------------------------------------
23
 
24
 
25
static const char
26
rcsid[] = "$Id: w_wad.c,v 1.5 1997/02/03 16:47:57 b1 Exp $";
27
 
28
 
29
#include 
30
#include 
31
#include 
32
#include 
33
 
34
#include "m_swap.h"
35
#include "doomtype.h"
36
#include "i_system.h"
37
#include "z_zone.h"
38
#include "w_wad.h"
39
 
40
#include 
41
 
42
 
333 serge 43
extern char *main_file;
44
 
45
size_t FileSize(FILE *handle);
46
 
550 serge 47
//int _stdcall read_file (char *name, void *buff,
48
//                        size_t offset, size_t count, size_t *reads);
333 serge 49
 
50
 
51
 
298 serge 52
//
53
// GLOBALS
54
//
55
 
56
// Location of each lump on disk.
333 serge 57
lumpinfo_t*             lumpinfo;
58
int                     numlumps;
298 serge 59
 
333 serge 60
void**                  lumpcache;
298 serge 61
 
62
void
63
ExtractFileBase
333 serge 64
( char*         path,
65
  char*         dest )
298 serge 66
{
333 serge 67
    char*       src;
68
    int         length;
298 serge 69
 
70
    src = path + strlen(path) - 1;
71
 
72
    // back up until a \ or the start
73
    while (src != path
333 serge 74
           && *(src-1) != '\\'
75
           && *(src-1) != '/')
298 serge 76
    {
333 serge 77
        src--;
298 serge 78
    }
79
 
80
    // copy up to eight characters
81
    memset (dest,0,8);
82
    length = 0;
83
 
84
    while (*src && *src != '.')
85
    {
333 serge 86
        if (++length == 9)
87
            I_Error ("Filename base of %s >8 chars",path);
298 serge 88
 
333 serge 89
        *dest++ = toupper((int)*src++);
298 serge 90
    }
91
}
92
 
93
 
94
 
95
 
96
 
97
//
98
// LUMP BASED ROUTINES.
99
//
100
 
101
//
102
// W_AddFile
103
// All files are optional, but at least one file must be
104
//  found (PWAD, if all required lumps are present).
105
// Files with a .wad extension are wadlink files
106
//  with multiple lumps.
107
// Other files are single lumps with the base filename
108
//  for the lump name.
109
//
110
// If filename starts with a tilde, the file is handled
111
//  specially to allow map reloads.
112
// But: the reload feature is a fragile hack...
113
 
114
 
333 serge 115
int             reloadlump;
116
char*   reloadname;
298 serge 117
 
118
 
119
void W_AddFile (char *filename)
120
{
333 serge 121
    wadinfo_t           header;
122
    lumpinfo_t*         lump_p;
123
    unsigned            i;
124
    FILE               *handle;
125
    int                 length;
126
    int                 startlump;
127
    filelump_t*         fileinfo;
128
    filelump_t          singleinfo;
129
    int                 storehandle;
130
    int err;
131
    size_t bytes;
298 serge 132
 
133
    // open the file and add to directory
134
 
135
    // handle reload indicator.
136
    if (filename[0] == '~')
137
    {
333 serge 138
        filename++;
139
        reloadname = filename;
140
        reloadlump = numlumps;
298 serge 141
    }
342 serge 142
 
143
    printf("open file %s\n\r",filename);
333 serge 144
 
298 serge 145
    if ( (handle = fopen (filename,"rb")) == NULL)
146
    {
333 serge 147
       printf (" couldn't open %s\n",filename);
148
       return;
298 serge 149
    }
150
 
333 serge 151
    printf (" adding %s\n\r",filename);
298 serge 152
    startlump = numlumps;
333 serge 153
 
154
    if (strnicmp (filename+strlen(filename)-3 , "wad", 3 ) )
298 serge 155
    {
333 serge 156
        // single lump file
157
        fileinfo = &singleinfo;
158
        singleinfo.filepos = 0;
159
        singleinfo.size = FileSize(handle);
160
        ExtractFileBase (filename, singleinfo.name);
161
        numlumps++;
298 serge 162
    }
163
    else
164
    {
333 serge 165
         //WAD file
166
        fread (&header, 1, sizeof(header), handle);
167
 
168
        if (strncmp(header.identification,"IWAD",4))
169
        {
170
            printf("No IWAD id\n");
171
            // Homebrew levels?
172
            if (strncmp(header.identification,"PWAD",4))
173
            {
174
                I_Error ("Wad file %s doesn't have IWAD "
175
                         "or PWAD id\n", filename);
176
            }
177
            printf("WAD magic OK\n");
178
            // ???modifiedgame = true;
179
        }
180
        header.numlumps = LONG(header.numlumps);
181
 
182
        header.infotableofs = LONG(header.infotableofs);
183
 
184
        length = header.numlumps*sizeof(filelump_t);
185
 
186
        fileinfo = alloca(length);
187
        fseek (handle, header.infotableofs, SEEK_SET);
188
        fread (fileinfo, 1, length, handle);
189
        numlumps += header.numlumps;
298 serge 190
    }
191
 
192
 
193
    // Fill in lumpinfo
194
    lumpinfo = realloc (lumpinfo, numlumps*sizeof(lumpinfo_t));
195
 
196
    if (!lumpinfo)
333 serge 197
        I_Error ("Couldn't realloc lumpinfo");
298 serge 198
 
199
    lump_p = &lumpinfo[startlump];
333 serge 200
 
298 serge 201
    storehandle = reloadname ? -1 : (int)handle;
333 serge 202
 
298 serge 203
    for (i=startlump ; i
204
    {
333 serge 205
        lump_p->handle = storehandle;
206
        lump_p->position = LONG(fileinfo->filepos);
207
        lump_p->size = LONG(fileinfo->size);
208
        strncpy (lump_p->name, fileinfo->name, 8);
298 serge 209
    }
333 serge 210
 
298 serge 211
    if (reloadname)
333 serge 212
        fclose (handle);
298 serge 213
}
214
 
215
 
216
 
217
 
218
//
219
// W_Reload
220
// Flushes any of the reloadable lumps in memory
221
//  and reloads the directory.
222
//
223
void W_Reload (void)
224
{
333 serge 225
    wadinfo_t           header;
226
    int                 lumpcount;
227
    lumpinfo_t*         lump_p;
228
    unsigned            i;
229
    FILE                *handle;
230
    int                 length;
231
    filelump_t*         fileinfo;
232
 
298 serge 233
    if (!reloadname)
333 serge 234
        return;
235
 
298 serge 236
    if ( (handle = fopen (reloadname,"rb")) == NULL)
333 serge 237
        I_Error ("W_Reload: couldn't open %s",reloadname);
298 serge 238
 
239
    fread (&header, 1, sizeof(header), handle);
333 serge 240
 
298 serge 241
    lumpcount = LONG(header.numlumps);
242
    header.infotableofs = LONG(header.infotableofs);
243
    length = lumpcount*sizeof(filelump_t);
244
    fileinfo = malloc (length);
245
    fseek (handle, header.infotableofs, SEEK_SET);
246
    fread (fileinfo, 1, length, handle);
247
 
248
    // Fill in lumpinfo
249
    lump_p = &lumpinfo[reloadlump];
333 serge 250
 
298 serge 251
    for (i=reloadlump ;
333 serge 252
         i
253
         i++,lump_p++, fileinfo++)
298 serge 254
    {
333 serge 255
        if (lumpcache[i])
256
            Z_Free (lumpcache[i]);
298 serge 257
 
333 serge 258
        lump_p->position = LONG(fileinfo->filepos);
259
        lump_p->size = LONG(fileinfo->size);
298 serge 260
    }
333 serge 261
 
298 serge 262
    fclose (handle);
263
}
264
 
265
//
266
// W_InitMultipleFiles
267
// Pass a null terminated list of files to use.
268
// All files are optional, but at least one file
269
//  must be found.
270
// Files with a .wad extension are idlink files
271
//  with multiple lumps.
272
// Other files are single lumps with the base filename
273
//  for the lump name.
274
// Lump names can appear multiple times.
275
// The name searcher looks backwards, so a later file
276
//  does override all earlier ones.
277
//
278
void W_InitMultipleFiles (char** filenames)
333 serge 279
{
280
    int         size;
298 serge 281
 
282
    // open all the files, load headers, and count lumps
283
    numlumps = 0;
284
 
285
    // will be realloced as lumps are added
333 serge 286
    lumpinfo = malloc(16384);
298 serge 287
 
288
    for ( ; *filenames ; filenames++)
333 serge 289
        W_AddFile (*filenames);
298 serge 290
 
291
    if (!numlumps)
333 serge 292
        I_Error ("W_InitFiles: no files found");
298 serge 293
 
294
    // set up caching
295
    size = numlumps * sizeof(*lumpcache);
296
    lumpcache = malloc (size);
297
 
298
    if (!lumpcache)
333 serge 299
        I_Error ("Couldn't allocate lumpcache");
298 serge 300
 
301
    memset (lumpcache,0, size);
302
}
303
 
304
 
305
 
306
 
307
//
308
// W_InitFile
309
// Just initialize from a single file.
310
//
311
void W_InitFile (char* filename)
312
{
333 serge 313
    char*       names[2];
298 serge 314
 
315
    names[0] = filename;
316
    names[1] = NULL;
317
    W_InitMultipleFiles (names);
318
}
319
 
320
 
321
 
322
//
323
// W_NumLumps
324
//
325
int W_NumLumps (void)
326
{
327
    return numlumps;
328
}
329
 
330
 
331
 
332
//
333
// W_CheckNumForName
334
// Returns -1 if name not found.
335
//
336
 
337
int W_CheckNumForName (char* name)
338
{
339
    union {
333 serge 340
        char    s[9];
341
        int     x[2];
342
 
298 serge 343
    } name8;
344
 
333 serge 345
    int         v1;
346
    int         v2;
347
    lumpinfo_t* lump_p;
298 serge 348
 
349
    // make the name into two integers for easy compares
350
    strncpy (name8.s,name,8);
351
 
352
    // in case the name was a fill 8 chars
353
    name8.s[8] = 0;
354
 
355
    // case insensitive
333 serge 356
    strupr (name8.s);
298 serge 357
 
358
    v1 = name8.x[0];
359
    v2 = name8.x[1];
360
 
361
 
362
    // scan backwards so patch lump files take precedence
363
    lump_p = lumpinfo + numlumps;
364
 
365
    while (lump_p-- != lumpinfo)
366
    {
333 serge 367
        if ( *(int *)lump_p->name == v1
368
             && *(int *)&lump_p->name[4] == v2)
369
        {
370
            return lump_p - lumpinfo;
371
        }
298 serge 372
    }
373
 
374
    // TFB. Not found.
375
    return -1;
376
}
377
 
378
 
379
 
380
 
381
//
382
// W_GetNumForName
383
// Calls W_CheckNumForName, but bombs out if not found.
384
//
385
int W_GetNumForName (char* name)
386
{
333 serge 387
    int i;
298 serge 388
 
389
    i = W_CheckNumForName (name);
390
 
391
    if (i == -1)
392
      I_Error ("W_GetNumForName: %s not found!", name);
393
 
394
    return i;
395
}
396
 
397
 
398
//
399
// W_LumpLength
400
// Returns the buffer size needed to load the given lump.
401
//
402
int W_LumpLength (int lump)
403
{
404
    if (lump >= numlumps)
333 serge 405
        I_Error ("W_LumpLength: %i >= numlumps",lump);
298 serge 406
 
407
    return lumpinfo[lump].size;
408
}
409
 
410
 
411
 
412
//
413
// W_ReadLump
414
// Loads the lump into the given buffer,
415
//  which must be >= W_LumpLength().
416
//
417
void
418
W_ReadLump
333 serge 419
( int           lump,
420
  void*         dest )
298 serge 421
{
333 serge 422
    int         c;
423
    lumpinfo_t* l;
424
    FILE        *handle;
425
    size_t bytes;
426
 
298 serge 427
    if (lump >= numlumps)
333 serge 428
        I_Error ("W_ReadLump: %i >= numlumps",lump);
298 serge 429
 
430
    l = lumpinfo+lump;
333 serge 431
 
298 serge 432
    // ??? I_BeginRead ();
333 serge 433
 
298 serge 434
    if (l->handle == -1)
435
    {
333 serge 436
        // reloadable file, so use open / read / close
437
        if ( (handle = fopen (reloadname,"rb")) == NULL)
438
            I_Error ("W_ReadLump: couldn't open %s",reloadname);
298 serge 439
    }
440
    else
333 serge 441
        handle = (FILE *)l->handle;
442
 
298 serge 443
    fseek (handle, l->position, SEEK_SET);
444
    c = fread (dest, 1, l->size, handle);
445
    if (c < l->size)
333 serge 446
        I_Error ("W_ReadLump: only read %i of %i on lump %i",
447
                 c,l->size,lump);
298 serge 448
 
449
    if (l->handle == -1)
333 serge 450
        fclose (handle);
451
 
298 serge 452
    // ??? I_EndRead ();
453
}
454
 
455
 
456
 
457
 
458
//
459
// W_CacheLumpNum
460
//
461
void*
462
W_CacheLumpNum
333 serge 463
( int           lump,
464
  int           tag )
298 serge 465
{
333 serge 466
    byte*       ptr;
298 serge 467
 
333 serge 468
    if ((unsigned)lump >= (unsigned)numlumps)
469
        I_Error ("W_CacheLumpNum: %i >= numlumps",lump);
470
 
298 serge 471
    if (!lumpcache[lump])
472
    {
333 serge 473
        // read the lump in
474
 
475
        //printf ("cache miss on lump %i\n",lump);
476
        ptr = Z_Malloc (W_LumpLength (lump), tag, &lumpcache[lump]);
477
        W_ReadLump (lump, lumpcache[lump]);
298 serge 478
    }
479
    else
480
    {
333 serge 481
        //printf ("cache hit on lump %i\n",lump);
482
        Z_ChangeTag (lumpcache[lump],tag);
298 serge 483
    }
333 serge 484
 
298 serge 485
    return lumpcache[lump];
486
}
487
 
488
 
489
 
490
//
491
// W_CacheLumpName
492
//
493
void*
494
W_CacheLumpName
333 serge 495
( char*         name,
496
  int           tag )
298 serge 497
{
498
    return W_CacheLumpNum (W_GetNumForName(name), tag);
499
}
500
 
300 serge 501
#if 0
298 serge 502
 
503
//
504
// W_Profile
505
//
333 serge 506
int             info[2500][10];
507
int             profilecount;
298 serge 508
 
509
void W_Profile (void)
510
{
333 serge 511
    int         i;
512
    memblock_t* block;
513
    void*       ptr;
514
    char        ch;
515
    FILE*       f;
516
    int         j;
517
    char        name[9];
518
 
519
 
298 serge 520
    for (i=0 ; i
333 serge 521
    {
522
        ptr = lumpcache[i];
523
        if (!ptr)
524
        {
525
            ch = ' ';
526
            continue;
527
        }
528
        else
529
        {
530
            block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
531
            if (block->tag < PU_PURGELEVEL)
532
                ch = 'S';
533
            else
534
                ch = 'P';
535
        }
536
        info[i][profilecount] = ch;
298 serge 537
    }
538
    profilecount++;
333 serge 539
 
298 serge 540
    f = fopen ("waddump.txt","w");
541
    name[8] = 0;
542
 
543
    for (i=0 ; i
544
    {
333 serge 545
        memcpy (name,lumpinfo[i].name,8);
298 serge 546
 
333 serge 547
        for (j=0 ; j<8 ; j++)
548
            if (!name[j])
549
                break;
298 serge 550
 
333 serge 551
        for ( ; j<8 ; j++)
552
            name[j] = ' ';
298 serge 553
 
333 serge 554
        //printf ("%s ",name);
298 serge 555
 
333 serge 556
        for (j=0 ; j
557
            fprintf (f,"    %c",info[i][j]);
298 serge 558
 
333 serge 559
        //printf ("\n");
298 serge 560
    }
561
    fclose (f);
562
}
563
 
300 serge 564
#endif
333 serge 565