Subversion Repositories Kolibri OS

Rev

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