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