Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8557 maxcodehac 1
// ID_CA.C
2
 
3
// this has been customized for WOLF
4
 
5
/*
6
=============================================================================
7
 
8
Id Software Caching Manager
9
---------------------------
10
 
11
Must be started BEFORE the memory manager, because it needs to get the headers
12
loaded into the data segment
13
 
14
=============================================================================
15
*/
16
 
17
#include 
18
#if defined _WIN32
19
    #include 
20
#elif defined _arch_dreamcast
21
    #include 
22
#else
23
//  #include 
24
    #include 
25
#endif
26
 
27
#include "wl_def.h"
28
#pragma hdrstop
29
 
30
#define THREEBYTEGRSTARTS
31
 
32
/*
33
=============================================================================
34
 
35
                             LOCAL CONSTANTS
36
 
37
=============================================================================
38
*/
39
 
40
typedef struct
41
{
42
    word bit0,bit1;       // 0-255 is a character, > is a pointer to a node
43
} huffnode;
44
 
45
 
46
typedef struct
47
{
48
    word RLEWtag;
49
    int32_t headeroffsets[100];
50
} mapfiletype;
51
 
52
 
53
/*
54
=============================================================================
55
 
56
                             GLOBAL VARIABLES
57
 
58
=============================================================================
59
*/
60
 
61
#define BUFFERSIZE 0x1000
62
static int32_t bufferseg[BUFFERSIZE/4];
63
 
64
int     mapon;
65
 
66
word    *mapsegs[MAPPLANES];
67
static maptype* mapheaderseg[NUMMAPS];
68
byte    *audiosegs[NUMSNDCHUNKS];
69
byte    *grsegs[NUMCHUNKS];
70
 
71
word    RLEWtag;
72
 
73
int     numEpisodesMissing = 0;
74
 
75
/*
76
=============================================================================
77
 
78
                             LOCAL VARIABLES
79
 
80
=============================================================================
81
*/
82
 
83
char extension[5]; // Need a string, not constant to change cache files
84
char graphext[5];
85
char audioext[5];
86
static const char gheadname[] = "vgahead.";
87
static const char gfilename[] = "vgagraph.";
88
static const char gdictname[] = "vgadict.";
89
static const char mheadname[] = "maphead.";
90
static const char mfilename[] = "maptemp.";
91
static const char aheadname[] = "audiohed.";
92
static const char afilename[] = "audiot.";
93
 
94
void CA_CannotOpen(const char *string);
95
 
96
static int32_t  grstarts[NUMCHUNKS + 1];
97
static int32_t* audiostarts; // array of offsets in audio / audiot
98
 
99
#ifdef GRHEADERLINKED
100
huffnode *grhuffman;
101
#else
102
huffnode grhuffman[255];
103
#endif
104
 
105
int    grhandle = -1;               // handle to EGAGRAPH
106
int    maphandle = -1;              // handle to MAPTEMP / GAMEMAPS
107
int    audiohandle = -1;            // handle to AUDIOT / AUDIO
108
 
109
int32_t   chunkcomplen,chunkexplen;
110
 
111
SDMode oldsoundmode;
112
 
113
 
114
static int32_t GRFILEPOS(const size_t idx)
115
{
116
	assert(idx < lengthof(grstarts));
117
	return grstarts[idx];
118
}
119
 
120
/*
121
=============================================================================
122
 
123
                            LOW LEVEL ROUTINES
124
 
125
=============================================================================
126
*/
127
 
128
/*
129
============================
130
=
131
= CAL_GetGrChunkLength
132
=
133
= Gets the length of an explicit length chunk (not tiles)
134
= The file pointer is positioned so the compressed data can be read in next.
135
=
136
============================
137
*/
138
 
139
void CAL_GetGrChunkLength (int chunk)
140
{
141
    lseek(grhandle,GRFILEPOS(chunk),SEEK_SET);
142
    read(grhandle,&chunkexplen,sizeof(chunkexplen));
143
    chunkcomplen = GRFILEPOS(chunk+1)-GRFILEPOS(chunk)-4;
144
}
145
 
146
 
147
/*
148
==========================
149
=
150
= CA_WriteFile
151
=
152
= Writes a file from a memory buffer
153
=
154
==========================
155
*/
156
 
157
boolean CA_WriteFile (const char *filename, void *ptr, int32_t length)
158
{
159
    const int handle = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644);
160
    if (handle == -1)
161
        return false;
162
 
163
    if (!write (handle,ptr,length))
164
    {
165
        close (handle);
166
        return false;
167
    }
168
    close (handle);
169
    return true;
170
}
171
 
172
 
173
 
174
/*
175
==========================
176
=
177
= CA_LoadFile
178
=
179
= Allocate space for and load a file
180
=
181
==========================
182
*/
183
 
184
boolean CA_LoadFile (const char *filename, memptr *ptr)
185
{
186
    int32_t size;
187
 
188
    const int handle = open(filename, O_RDONLY | O_BINARY);
189
    if (handle == -1)
190
        return false;
191
 
192
    size = lseek(handle, 0, SEEK_END);
193
    lseek(handle, 0, SEEK_SET);
194
    *ptr=malloc(size);
195
    CHECKMALLOCRESULT(*ptr);
196
    if (!read (handle,*ptr,size))
197
    {
198
        close (handle);
199
        return false;
200
    }
201
    close (handle);
202
    return true;
203
}
204
 
205
/*
206
============================================================================
207
 
208
                COMPRESSION routines, see JHUFF.C for more
209
 
210
============================================================================
211
*/
212
 
213
static void CAL_HuffExpand(byte *source, byte *dest, int32_t length, huffnode *hufftable)
214
{
215
    byte *end;
216
    huffnode *headptr, *huffptr;
217
 
218
    if(!length || !dest)
219
    {
220
        Quit("length or dest is null!");
221
        return;
222
    }
223
 
224
    headptr = hufftable+254;        // head node is always node 254
225
 
226
    int written = 0;
227
 
228
    end=dest+length;
229
 
230
    byte val = *source++;
231
    byte mask = 1;
232
    word nodeval;
233
    huffptr = headptr;
234
    while(1)
235
    {
236
        if(!(val & mask))
237
            nodeval = huffptr->bit0;
238
        else
239
            nodeval = huffptr->bit1;
240
        if(mask==0x80)
241
        {
242
            val = *source++;
243
            mask = 1;
244
        }
245
        else mask <<= 1;
246
 
247
        if(nodeval<256)
248
        {
249
            *dest++ = (byte) nodeval;
250
            written++;
251
            huffptr = headptr;
252
            if(dest>=end) break;
253
        }
254
        else
255
        {
256
            huffptr = hufftable + (nodeval - 256);
257
        }
258
    }
259
}
260
 
261
/*
262
======================
263
=
264
= CAL_CarmackExpand
265
=
266
= Length is the length of the EXPANDED data
267
=
268
======================
269
*/
270
 
271
#define NEARTAG 0xa7
272
#define FARTAG  0xa8
273
 
274
void CAL_CarmackExpand (byte *source, word *dest, int length)
275
{
276
    word ch,chhigh,count,offset;
277
    byte *inptr;
278
    word *copyptr, *outptr;
279
 
280
    length/=2;
281
 
282
    inptr = (byte *) source;
283
    outptr = dest;
284
 
285
    while (length>0)
286
    {
287
        ch = READWORD(inptr);
288
        chhigh = ch>>8;
289
        if (chhigh == NEARTAG)
290
        {
291
            count = ch&0xff;
292
            if (!count)
293
            {                               // have to insert a word containing the tag byte
294
                ch |= *inptr++;
295
                *outptr++ = ch;
296
                length--;
297
            }
298
            else
299
            {
300
                offset = *inptr++;
301
                copyptr = outptr - offset;
302
                length -= count;
303
                if(length<0) return;
304
                while (count--)
305
                    *outptr++ = *copyptr++;
306
            }
307
        }
308
        else if (chhigh == FARTAG)
309
        {
310
            count = ch&0xff;
311
            if (!count)
312
            {                               // have to insert a word containing the tag byte
313
                ch |= *inptr++;
314
                *outptr++ = ch;
315
                length --;
316
            }
317
            else
318
            {
319
                offset = READWORD(inptr);
320
                copyptr = dest + offset;
321
                length -= count;
322
                if(length<0) return;
323
                while (count--)
324
                    *outptr++ = *copyptr++;
325
            }
326
        }
327
        else
328
        {
329
            *outptr++ = ch;
330
            length --;
331
        }
332
    }
333
}
334
 
335
/*
336
======================
337
=
338
= CA_RLEWcompress
339
=
340
======================
341
*/
342
 
343
int32_t CA_RLEWCompress (word *source, int32_t length, word *dest, word rlewtag)
344
{
345
    word value,count;
346
    unsigned i;
347
    word *start,*end;
348
 
349
    start = dest;
350
 
351
    end = source + (length+1)/2;
352
 
353
    //
354
    // compress it
355
    //
356
    do
357
    {
358
        count = 1;
359
        value = *source++;
360
        while (*source == value && source
361
        {
362
            count++;
363
            source++;
364
        }
365
        if (count>3 || value == rlewtag)
366
        {
367
            //
368
            // send a tag / count / value string
369
            //
370
            *dest++ = rlewtag;
371
            *dest++ = count;
372
            *dest++ = value;
373
        }
374
        else
375
        {
376
            //
377
            // send word without compressing
378
            //
379
            for (i=1;i<=count;i++)
380
                *dest++ = value;
381
        }
382
 
383
    } while (source
384
 
385
    return (int32_t)(2*(dest-start));
386
}
387
 
388
 
389
/*
390
======================
391
=
392
= CA_RLEWexpand
393
= length is EXPANDED length
394
=
395
======================
396
*/
397
 
398
void CA_RLEWexpand (word *source, word *dest, int32_t length, word rlewtag)
399
{
400
    word value,count,i;
401
    word *end=dest+length/2;
402
 
403
//
404
// expand it
405
//
406
    do
407
    {
408
        value = *source++;
409
        if (value != rlewtag)
410
            //
411
            // uncompressed
412
            //
413
            *dest++=value;
414
        else
415
        {
416
            //
417
            // compressed string
418
            //
419
            count = *source++;
420
            value = *source++;
421
            for (i=1;i<=count;i++)
422
                *dest++ = value;
423
        }
424
    } while (dest
425
}
426
 
427
 
428
 
429
/*
430
=============================================================================
431
 
432
                                         CACHE MANAGER ROUTINES
433
 
434
=============================================================================
435
*/
436
 
437
 
438
/*
439
======================
440
=
441
= CAL_SetupGrFile
442
=
443
======================
444
*/
445
 
446
void CAL_SetupGrFile (void)
447
{
448
    char fname[13];
449
    int handle;
450
    byte *compseg;
451
 
452
#ifdef GRHEADERLINKED
453
 
454
    grhuffman = (huffnode *)&EGAdict;
455
    grstarts = (int32_t _seg *)FP_SEG(&EGAhead);
456
 
457
#else
458
 
459
//
460
// load ???dict.ext (huffman dictionary for graphics files)
461
//
462
 
463
    strcpy(fname,gdictname);
464
    strcat(fname,graphext);
465
 
466
    handle = open(fname, O_RDONLY | O_BINARY);
467
    if (handle == -1)
468
        CA_CannotOpen(fname);
469
 
470
    read(handle, grhuffman, sizeof(grhuffman));
471
    close(handle);
472
 
473
    // load the data offsets from ???head.ext
474
    strcpy(fname,gheadname);
475
    strcat(fname,graphext);
476
 
477
    handle = open(fname, O_RDONLY | O_BINARY);
478
    if (handle == -1)
479
        CA_CannotOpen(fname);
480
 
481
    long headersize = lseek(handle, 0, SEEK_END);
482
    lseek(handle, 0, SEEK_SET);
483
 
484
#ifndef APOGEE_1_0
485
	int expectedsize = lengthof(grstarts) - numEpisodesMissing;
486
#else
487
	int expectedsize = lengthof(grstarts);
488
#endif
489
 
490
    if(!param_ignorenumchunks && headersize / 3 != (long) expectedsize)
491
        Quit("Wolf4SDL was not compiled for these data files:\n"
492
            "%s contains a wrong number of offsets (%i instead of %i)!\n\n"
493
            "Please check whether you are using the right executable!\n"
494
            "(For mod developers: perhaps you forgot to update NUMCHUNKS?)",
495
            fname, headersize / 3, expectedsize);
496
 
497
    byte data[lengthof(grstarts) * 3];
498
    read(handle, data, sizeof(data));
499
    close(handle);
500
 
501
    const byte* d = data;
502
    for (int32_t* i = grstarts; i != endof(grstarts); ++i)
503
    {
504
        const int32_t val = d[0] | d[1] << 8 | d[2] << 16;
505
        *i = (val == 0x00FFFFFF ? -1 : val);
506
        d += 3;
507
    }
508
#endif
509
 
510
//
511
// Open the graphics file, leaving it open until the game is finished
512
//
513
    strcpy(fname,gfilename);
514
    strcat(fname,graphext);
515
 
516
    grhandle = open(fname, O_RDONLY | O_BINARY);
517
    if (grhandle == -1)
518
        CA_CannotOpen(fname);
519
 
520
 
521
//
522
// load the pic and sprite headers into the arrays in the data segment
523
//
524
    pictable=(pictabletype *) malloc(NUMPICS*sizeof(pictabletype));
525
    CHECKMALLOCRESULT(pictable);
526
    CAL_GetGrChunkLength(STRUCTPIC);                // position file pointer
527
    compseg=(byte *) malloc(chunkcomplen);
528
    CHECKMALLOCRESULT(compseg);
529
    read (grhandle,compseg,chunkcomplen);
530
    CAL_HuffExpand(compseg, (byte*)pictable, NUMPICS * sizeof(pictabletype), grhuffman);
531
    free(compseg);
532
}
533
 
534
//==========================================================================
535
 
536
 
537
/*
538
======================
539
=
540
= CAL_SetupMapFile
541
=
542
======================
543
*/
544
 
545
void CAL_SetupMapFile (void)
546
{
547
    int     i;
548
    int handle;
549
    int32_t length,pos;
550
    char fname[13];
551
 
552
//
553
// load maphead.ext (offsets and tileinfo for map file)
554
//
555
    strcpy(fname,mheadname);
556
    strcat(fname,extension);
557
 
558
    handle = open(fname, O_RDONLY | O_BINARY);
559
    if (handle == -1)
560
        CA_CannotOpen(fname);
561
 
562
    length = NUMMAPS*4+2; // used to be "filelength(handle);"
563
    mapfiletype *tinf=(mapfiletype *) malloc(sizeof(mapfiletype));
564
    CHECKMALLOCRESULT(tinf);
565
    read(handle, tinf, length);
566
    close(handle);
567
 
568
    RLEWtag=tinf->RLEWtag;
569
 
570
//
571
// open the data file
572
//
573
#ifdef CARMACIZED
574
    strcpy(fname, "gamemaps.");
575
    strcat(fname, extension);
576
 
577
    maphandle = open(fname, O_RDONLY | O_BINARY);
578
    if (maphandle == -1)
579
        CA_CannotOpen(fname);
580
#else
581
    strcpy(fname,mfilename);
582
    strcat(fname,extension);
583
 
584
    maphandle = open(fname, O_RDONLY | O_BINARY);
585
    if (maphandle == -1)
586
        CA_CannotOpen(fname);
587
#endif
588
 
589
//
590
// load all map header
591
//
592
    for (i=0;i
593
    {
594
        pos = tinf->headeroffsets[i];
595
        if (pos<0)                          // $FFFFFFFF start is a sparse map
596
            continue;
597
 
598
        mapheaderseg[i]=(maptype *) malloc(sizeof(maptype));
599
        CHECKMALLOCRESULT(mapheaderseg[i]);
600
        lseek(maphandle,pos,SEEK_SET);
601
        read (maphandle,(memptr)mapheaderseg[i],sizeof(maptype));
602
    }
603
 
604
    free(tinf);
605
 
606
//
607
// allocate space for 3 64*64 planes
608
//
609
    for (i=0;i
610
    {
611
        mapsegs[i]=(word *) malloc(maparea*2);
612
        CHECKMALLOCRESULT(mapsegs[i]);
613
    }
614
}
615
 
616
 
617
//==========================================================================
618
 
619
 
620
/*
621
======================
622
=
623
= CAL_SetupAudioFile
624
=
625
======================
626
*/
627
 
628
void CAL_SetupAudioFile (void)
629
{
630
    char fname[13];
631
 
632
//
633
// load audiohed.ext (offsets for audio file)
634
//
635
    strcpy(fname,aheadname);
636
    strcat(fname,audioext);
637
 
638
    void* ptr;
639
    if (!CA_LoadFile(fname, &ptr))
640
        CA_CannotOpen(fname);
641
    audiostarts = (int32_t*)ptr;
642
 
643
//
644
// open the data file
645
//
646
    strcpy(fname,afilename);
647
    strcat(fname,audioext);
648
 
649
    audiohandle = open(fname, O_RDONLY | O_BINARY);
650
    if (audiohandle == -1)
651
        CA_CannotOpen(fname);
652
}
653
 
654
//==========================================================================
655
 
656
 
657
/*
658
======================
659
=
660
= CA_Startup
661
=
662
= Open all files and load in headers
663
=
664
======================
665
*/
666
 
667
void CA_Startup (void)
668
{
669
#ifdef PROFILE
670
    unlink ("PROFILE.TXT");
671
    profilehandle = open("PROFILE.TXT", O_CREAT | O_WRONLY | O_TEXT);
672
#endif
673
 
674
    CAL_SetupMapFile ();
675
    CAL_SetupGrFile ();
676
    CAL_SetupAudioFile ();
677
 
678
    mapon = -1;
679
}
680
 
681
//==========================================================================
682
 
683
 
684
/*
685
======================
686
=
687
= CA_Shutdown
688
=
689
= Closes all files
690
=
691
======================
692
*/
693
 
694
void CA_Shutdown (void)
695
{
696
    int i,start;
697
 
698
    if(maphandle != -1)
699
        close(maphandle);
700
    if(grhandle != -1)
701
        close(grhandle);
702
    if(audiohandle != -1)
703
        close(audiohandle);
704
 
705
    for(i=0; i
706
        UNCACHEGRCHUNK(i);
707
    free(pictable);
708
 
709
    switch(oldsoundmode)
710
    {
711
        case sdm_Off:
712
            return;
713
        case sdm_PC:
714
            start = STARTPCSOUNDS;
715
            break;
716
        case sdm_AdLib:
717
            start = STARTADLIBSOUNDS;
718
            break;
719
    }
720
 
721
    for(i=0; i
722
        UNCACHEAUDIOCHUNK(start);
723
}
724
 
725
//===========================================================================
726
 
727
/*
728
======================
729
=
730
= CA_CacheAudioChunk
731
=
732
======================
733
*/
734
 
735
int32_t CA_CacheAudioChunk (int chunk)
736
{
737
    int32_t pos = audiostarts[chunk];
738
    int32_t size = audiostarts[chunk+1]-pos;
739
 
740
    if (audiosegs[chunk])
741
        return size;                        // already in memory
742
 
743
    audiosegs[chunk]=(byte *) malloc(size);
744
    CHECKMALLOCRESULT(audiosegs[chunk]);
745
 
746
    lseek(audiohandle,pos,SEEK_SET);
747
    read(audiohandle,audiosegs[chunk],size);
748
 
749
    return size;
750
}
751
 
752
void CA_CacheAdlibSoundChunk (int chunk)
753
{
754
    int32_t pos = audiostarts[chunk];
755
    int32_t size = audiostarts[chunk+1]-pos;
756
 
757
    if (audiosegs[chunk])
758
        return;                        // already in memory
759
 
760
    lseek(audiohandle, pos, SEEK_SET);
761
    read(audiohandle, bufferseg, ORIG_ADLIBSOUND_SIZE - 1);   // without data[1]
762
 
763
    AdLibSound *sound = (AdLibSound *) malloc(size + sizeof(AdLibSound) - ORIG_ADLIBSOUND_SIZE);
764
    CHECKMALLOCRESULT(sound);
765
 
766
    byte *ptr = (byte *) bufferseg;
767
    sound->common.length = READLONGWORD(ptr);
768
    sound->common.priority = READWORD(ptr);
769
    sound->inst.mChar = *ptr++;
770
    sound->inst.cChar = *ptr++;
771
    sound->inst.mScale = *ptr++;
772
    sound->inst.cScale = *ptr++;
773
    sound->inst.mAttack = *ptr++;
774
    sound->inst.cAttack = *ptr++;
775
    sound->inst.mSus = *ptr++;
776
    sound->inst.cSus = *ptr++;
777
    sound->inst.mWave = *ptr++;
778
    sound->inst.cWave = *ptr++;
779
    sound->inst.nConn = *ptr++;
780
    sound->inst.voice = *ptr++;
781
    sound->inst.mode = *ptr++;
782
    sound->inst.unused[0] = *ptr++;
783
    sound->inst.unused[1] = *ptr++;
784
    sound->inst.unused[2] = *ptr++;
785
    sound->block = *ptr++;
786
 
787
    read(audiohandle, sound->data, size - ORIG_ADLIBSOUND_SIZE + 1);  // + 1 because of byte data[1]
788
 
789
    audiosegs[chunk]=(byte *) sound;
790
}
791
 
792
//===========================================================================
793
 
794
/*
795
======================
796
=
797
= CA_LoadAllSounds
798
=
799
= Purges all sounds, then loads all new ones (mode switch)
800
=
801
======================
802
*/
803
 
804
void CA_LoadAllSounds (void)
805
{
806
    unsigned start,i;
807
 
808
    switch (oldsoundmode)
809
    {
810
        case sdm_Off:
811
            goto cachein;
812
        case sdm_PC:
813
            start = STARTPCSOUNDS;
814
            break;
815
        case sdm_AdLib:
816
            start = STARTADLIBSOUNDS;
817
            break;
818
    }
819
 
820
    for (i=0;i
821
        UNCACHEAUDIOCHUNK(start);
822
 
823
cachein:
824
 
825
    oldsoundmode = SoundMode;
826
 
827
    switch (SoundMode)
828
    {
829
        case sdm_Off:
830
            start = STARTADLIBSOUNDS;   // needed for priorities...
831
            break;
832
        case sdm_PC:
833
            start = STARTPCSOUNDS;
834
            break;
835
        case sdm_AdLib:
836
            start = STARTADLIBSOUNDS;
837
            break;
838
    }
839
 
840
    if(start == STARTADLIBSOUNDS)
841
    {
842
        for (i=0;i
843
            CA_CacheAdlibSoundChunk(start);
844
    }
845
    else
846
    {
847
        for (i=0;i
848
            CA_CacheAudioChunk(start);
849
    }
850
}
851
 
852
//===========================================================================
853
 
854
 
855
/*
856
======================
857
=
858
= CAL_ExpandGrChunk
859
=
860
= Does whatever is needed with a pointer to a compressed chunk
861
=
862
======================
863
*/
864
 
865
void CAL_ExpandGrChunk (int chunk, int32_t *source)
866
{
867
    int32_t    expanded;
868
 
869
    if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)
870
    {
871
        //
872
        // expanded sizes of tile8/16/32 are implicit
873
        //
874
 
875
#define BLOCK           64
876
#define MASKBLOCK       128
877
 
878
        if (chunk
879
            expanded = BLOCK*NUMTILE8;
880
        else if (chunk
881
            expanded = MASKBLOCK*NUMTILE8M;
882
        else if (chunk
883
            expanded = BLOCK*4;
884
        else if (chunk
885
            expanded = MASKBLOCK*4;
886
        else if (chunk
887
            expanded = BLOCK*16;
888
        else
889
            expanded = MASKBLOCK*16;
890
    }
891
    else
892
    {
893
        //
894
        // everything else has an explicit size longword
895
        //
896
        expanded = *source++;
897
    }
898
 
899
    //
900
    // allocate final space, decompress it, and free bigbuffer
901
    // Sprites need to have shifts made and various other junk
902
    //
903
    grsegs[chunk]=(byte *) malloc(expanded);
904
    CHECKMALLOCRESULT(grsegs[chunk]);
905
    CAL_HuffExpand((byte *) source, grsegs[chunk], expanded, grhuffman);
906
}
907
 
908
 
909
/*
910
======================
911
=
912
= CA_CacheGrChunk
913
=
914
= Makes sure a given chunk is in memory, loadiing it if needed
915
=
916
======================
917
*/
918
 
919
void CA_CacheGrChunk (int chunk)
920
{
921
    int32_t pos,compressed;
922
    int32_t *source;
923
    int  next;
924
 
925
    if (grsegs[chunk])
926
        return;                             // already in memory
927
 
928
//
929
// load the chunk into a buffer, either the miscbuffer if it fits, or allocate
930
// a larger buffer
931
//
932
    pos = GRFILEPOS(chunk);
933
    if (pos<0)                              // $FFFFFFFF start is a sparse tile
934
        return;
935
 
936
    next = chunk +1;
937
    while (GRFILEPOS(next) == -1)           // skip past any sparse tiles
938
        next++;
939
 
940
    compressed = GRFILEPOS(next)-pos;
941
 
942
    lseek(grhandle,pos,SEEK_SET);
943
 
944
    if (compressed<=BUFFERSIZE)
945
    {
946
        read(grhandle,bufferseg,compressed);
947
        source = bufferseg;
948
    }
949
    else
950
    {
951
        source = (int32_t *) malloc(compressed);
952
        CHECKMALLOCRESULT(source);
953
        read(grhandle,source,compressed);
954
    }
955
 
956
    CAL_ExpandGrChunk (chunk,source);
957
 
958
    if (compressed>BUFFERSIZE)
959
        free(source);
960
}
961
 
962
 
963
 
964
//==========================================================================
965
 
966
/*
967
======================
968
=
969
= CA_CacheScreen
970
=
971
= Decompresses a chunk from disk straight onto the screen
972
=
973
======================
974
*/
975
 
976
void CA_CacheScreen (int chunk)
977
{
978
    int32_t    pos,compressed,expanded;
979
    memptr  bigbufferseg;
980
    int32_t    *source;
981
    int             next;
982
    byte *pic, *vbuf;
983
    int x, y, scx, scy;
984
    unsigned i, j;
985
 
986
//
987
// load the chunk into a buffer
988
//
989
    pos = GRFILEPOS(chunk);
990
    next = chunk +1;
991
    while (GRFILEPOS(next) == -1)           // skip past any sparse tiles
992
        next++;
993
    compressed = GRFILEPOS(next)-pos;
994
 
995
    lseek(grhandle,pos,SEEK_SET);
996
 
997
    bigbufferseg=malloc(compressed);
998
    CHECKMALLOCRESULT(bigbufferseg);
999
    read(grhandle,bigbufferseg,compressed);
1000
    source = (int32_t *) bigbufferseg;
1001
 
1002
    expanded = *source++;
1003
 
1004
//
1005
// allocate final space, decompress it, and free bigbuffer
1006
// Sprites need to have shifts made and various other junk
1007
//
1008
    pic = (byte *) malloc(64000);
1009
    CHECKMALLOCRESULT(pic);
1010
    CAL_HuffExpand((byte *) source, pic, expanded, grhuffman);
1011
 
1012
    vbuf = VL_LockSurface(curSurface);
1013
    if(vbuf != NULL)
1014
    {
1015
        for(y = 0, scy = 0; y < 200; y++, scy += scaleFactor)
1016
        {
1017
            for(x = 0, scx = 0; x < 320; x++, scx += scaleFactor)
1018
            {
1019
                byte col = pic[(y * 80 + (x >> 2)) + (x & 3) * 80 * 200];
1020
                for(i = 0; i < scaleFactor; i++)
1021
                    for(j = 0; j < scaleFactor; j++)
1022
                        vbuf[(scy + i) * curPitch + scx + j] = col;
1023
            }
1024
        }
1025
        VL_UnlockSurface(curSurface);
1026
    }
1027
    free(pic);
1028
    free(bigbufferseg);
1029
}
1030
 
1031
//==========================================================================
1032
 
1033
/*
1034
======================
1035
=
1036
= CA_CacheMap
1037
=
1038
= WOLF: This is specialized for a 64*64 map size
1039
=
1040
======================
1041
*/
1042
 
1043
void CA_CacheMap (int mapnum)
1044
{
1045
    int32_t   pos,compressed;
1046
    int       plane;
1047
    word     *dest;
1048
    memptr    bigbufferseg;
1049
    unsigned  size;
1050
    word     *source;
1051
#ifdef CARMACIZED
1052
    word     *buffer2seg;
1053
    int32_t   expanded;
1054
#endif
1055
 
1056
    mapon = mapnum;
1057
 
1058
//
1059
// load the planes into the allready allocated buffers
1060
//
1061
    size = maparea*2;
1062
 
1063
    for (plane = 0; plane
1064
    {
1065
        pos = mapheaderseg[mapnum]->planestart[plane];
1066
        compressed = mapheaderseg[mapnum]->planelength[plane];
1067
 
1068
        dest = mapsegs[plane];
1069
 
1070
        lseek(maphandle,pos,SEEK_SET);
1071
        if (compressed<=BUFFERSIZE)
1072
            source = (word *) bufferseg;
1073
        else
1074
        {
1075
            bigbufferseg=malloc(compressed);
1076
            CHECKMALLOCRESULT(bigbufferseg);
1077
            source = (word *) bigbufferseg;
1078
        }
1079
 
1080
        read(maphandle,source,compressed);
1081
#ifdef CARMACIZED
1082
        //
1083
        // unhuffman, then unRLEW
1084
        // The huffman'd chunk has a two byte expanded length first
1085
        // The resulting RLEW chunk also does, even though it's not really
1086
        // needed
1087
        //
1088
        expanded = *source;
1089
        source++;
1090
        buffer2seg = (word *) malloc(expanded);
1091
        CHECKMALLOCRESULT(buffer2seg);
1092
        CAL_CarmackExpand((byte *) source, buffer2seg,expanded);
1093
        CA_RLEWexpand(buffer2seg+1,dest,size,RLEWtag);
1094
        free(buffer2seg);
1095
 
1096
#else
1097
        //
1098
        // unRLEW, skipping expanded length
1099
        //
1100
        CA_RLEWexpand (source+1,dest,size,RLEWtag);
1101
#endif
1102
 
1103
        if (compressed>BUFFERSIZE)
1104
            free(bigbufferseg);
1105
    }
1106
}
1107
 
1108
//===========================================================================
1109
 
1110
void CA_CannotOpen(const char *string)
1111
{
1112
    char str[30];
1113
 
1114
    strcpy(str,"Can't open ");
1115
    strcat(str,string);
1116
    strcat(str,"!\n");
1117
    Quit (str);
1118
}