Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 <sys/types.h>
  18. #if defined _WIN32
  19.     #include <io.h>
  20. #elif defined _arch_dreamcast
  21.     #include <unistd.h>
  22. #else
  23. //  #include <sys/uio.h>
  24.     #include <unistd.h>
  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<end)
  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<end);
  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<end);
  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<NUMMAPS;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<MAPPLANES;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<NUMCHUNKS; 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<NUMSOUNDS; i++,start++)
  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<NUMSOUNDS;i++,start++)
  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<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. }
  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<STARTTILE8M)          // tile 8s are all in one chunk!
  879.             expanded = BLOCK*NUMTILE8;
  880.         else if (chunk<STARTTILE16)
  881.             expanded = MASKBLOCK*NUMTILE8M;
  882.         else if (chunk<STARTTILE16M)    // all other tiles are one/chunk
  883.             expanded = BLOCK*4;
  884.         else if (chunk<STARTTILE32)
  885.             expanded = MASKBLOCK*4;
  886.         else if (chunk<STARTTILE32M)
  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<MAPPLANES; 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. }
  1119.