Subversion Repositories Kolibri OS

Rev

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