home *** CD-ROM | disk | FTP | other *** search
/ 100 af Verdens Bedste Spil / 100Spil.iso / dos / wolf3d / source / wolfsrc.1 / ID_CA.C < prev    next >
C/C++ Source or Header  |  1993-02-04  |  34KB  |  1,768 lines

  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 "ID_HEADS.H"
  18. #pragma hdrstop
  19.  
  20. #pragma warn -pro
  21. #pragma warn -use
  22.  
  23. #define THREEBYTEGRSTARTS
  24.  
  25. /*
  26. =============================================================================
  27.  
  28.                          LOCAL CONSTANTS
  29.  
  30. =============================================================================
  31. */
  32.  
  33. typedef struct
  34. {
  35.   unsigned bit0,bit1;    // 0-255 is a character, > is a pointer to a node
  36. } huffnode;
  37.  
  38.  
  39. typedef struct
  40. {
  41.     unsigned    RLEWtag;
  42.     long        headeroffsets[100];
  43.     byte        tileinfo[];
  44. } mapfiletype;
  45.  
  46.  
  47. /*
  48. =============================================================================
  49.  
  50.                          GLOBAL VARIABLES
  51.  
  52. =============================================================================
  53. */
  54.  
  55. byte         _seg    *tinf;
  56. int            mapon;
  57.  
  58. unsigned    _seg    *mapsegs[MAPPLANES];
  59. maptype        _seg    *mapheaderseg[NUMMAPS];
  60. byte        _seg    *audiosegs[NUMSNDCHUNKS];
  61. void        _seg    *grsegs[NUMCHUNKS];
  62.  
  63. byte        far    grneeded[NUMCHUNKS];
  64. byte        ca_levelbit,ca_levelnum;
  65.  
  66. int            profilehandle,debughandle;
  67.  
  68. char        audioname[13]="AUDIO.";
  69.  
  70. /*
  71. =============================================================================
  72.  
  73.                          LOCAL VARIABLES
  74.  
  75. =============================================================================
  76. */
  77.  
  78. extern    long    far    CGAhead;
  79. extern    long    far    EGAhead;
  80. extern    byte    CGAdict;
  81. extern    byte    EGAdict;
  82. extern    byte    far    maphead;
  83. extern    byte    mapdict;
  84. extern    byte    far    audiohead;
  85. extern    byte    audiodict;
  86.  
  87.  
  88. char extension[5],    // Need a string, not constant to change cache files
  89.      gheadname[10]=GREXT"HEAD.",
  90.      gfilename[10]=GREXT"GRAPH.",
  91.      gdictname[10]=GREXT"DICT.",
  92.      mheadname[10]="MAPHEAD.",
  93.      mfilename[10]="MAPTEMP.",
  94.      aheadname[10]="AUDIOHED.",
  95.      afilename[10]="AUDIOT.";
  96.  
  97. void CA_CannotOpen(char *string);
  98.  
  99. long        _seg *grstarts;    // array of offsets in egagraph, -1 for sparse
  100. long        _seg *audiostarts;    // array of offsets in audio / audiot
  101.  
  102. #ifdef GRHEADERLINKED
  103. huffnode    *grhuffman;
  104. #else
  105. huffnode    grhuffman[255];
  106. #endif
  107.  
  108. #ifdef AUDIOHEADERLINKED
  109. huffnode    *audiohuffman;
  110. #else
  111. huffnode    audiohuffman[255];
  112. #endif
  113.  
  114.  
  115. int            grhandle;        // handle to EGAGRAPH
  116. int            maphandle;        // handle to MAPTEMP / GAMEMAPS
  117. int            audiohandle;    // handle to AUDIOT / AUDIO
  118.  
  119. long        chunkcomplen,chunkexplen;
  120.  
  121. SDMode        oldsoundmode;
  122.  
  123.  
  124.  
  125. void    CAL_CarmackExpand (unsigned far *source, unsigned far *dest,
  126.         unsigned length);
  127.  
  128.  
  129. #ifdef THREEBYTEGRSTARTS
  130. #define FILEPOSSIZE    3
  131. //#define    GRFILEPOS(c) (*(long far *)(((byte far *)grstarts)+(c)*3)&0xffffff)
  132. long GRFILEPOS(int c)
  133. {
  134.     long value;
  135.     int    offset;
  136.  
  137.     offset = c*3;
  138.  
  139.     value = *(long far *)(((byte far *)grstarts)+offset);
  140.  
  141.     value &= 0x00ffffffl;
  142.  
  143.     if (value == 0xffffffl)
  144.         value = -1;
  145.  
  146.     return value;
  147. };
  148. #else
  149. #define FILEPOSSIZE    4
  150. #define    GRFILEPOS(c) (grstarts[c])
  151. #endif
  152.  
  153. /*
  154. =============================================================================
  155.  
  156.                        LOW LEVEL ROUTINES
  157.  
  158. =============================================================================
  159. */
  160.  
  161. /*
  162. ============================
  163. =
  164. = CA_OpenDebug / CA_CloseDebug
  165. =
  166. = Opens a binary file with the handle "debughandle"
  167. =
  168. ============================
  169. */
  170.  
  171. void CA_OpenDebug (void)
  172. {
  173.     unlink ("DEBUG.TXT");
  174.     debughandle = open("DEBUG.TXT", O_CREAT | O_WRONLY | O_TEXT);
  175. }
  176.  
  177. void CA_CloseDebug (void)
  178. {
  179.     close (debughandle);
  180. }
  181.  
  182.  
  183.  
  184. /*
  185. ============================
  186. =
  187. = CAL_GetGrChunkLength
  188. =
  189. = Gets the length of an explicit length chunk (not tiles)
  190. = The file pointer is positioned so the compressed data can be read in next.
  191. =
  192. ============================
  193. */
  194.  
  195. void CAL_GetGrChunkLength (int chunk)
  196. {
  197.     lseek(grhandle,GRFILEPOS(chunk),SEEK_SET);
  198.     read(grhandle,&chunkexplen,sizeof(chunkexplen));
  199.     chunkcomplen = GRFILEPOS(chunk+1)-GRFILEPOS(chunk)-4;
  200. }
  201.  
  202.  
  203. /*
  204. ==========================
  205. =
  206. = CA_FarRead
  207. =
  208. = Read from a file to a far pointer
  209. =
  210. ==========================
  211. */
  212.  
  213. boolean CA_FarRead (int handle, byte far *dest, long length)
  214. {
  215.     if (length>0xffffl)
  216.         Quit ("CA_FarRead doesn't support 64K reads yet!");
  217.  
  218. asm        push    ds
  219. asm        mov    bx,[handle]
  220. asm        mov    cx,[WORD PTR length]
  221. asm        mov    dx,[WORD PTR dest]
  222. asm        mov    ds,[WORD PTR dest+2]
  223. asm        mov    ah,0x3f                // READ w/handle
  224. asm        int    21h
  225. asm        pop    ds
  226. asm        jnc    good
  227.     errno = _AX;
  228.     return    false;
  229. good:
  230. asm        cmp    ax,[WORD PTR length]
  231. asm        je    done
  232.     errno = EINVFMT;            // user manager knows this is bad read
  233.     return    false;
  234. done:
  235.     return    true;
  236. }
  237.  
  238.  
  239. /*
  240. ==========================
  241. =
  242. = CA_SegWrite
  243. =
  244. = Write from a file to a far pointer
  245. =
  246. ==========================
  247. */
  248.  
  249. boolean CA_FarWrite (int handle, byte far *source, long length)
  250. {
  251.     if (length>0xffffl)
  252.         Quit ("CA_FarWrite doesn't support 64K reads yet!");
  253.  
  254. asm        push    ds
  255. asm        mov    bx,[handle]
  256. asm        mov    cx,[WORD PTR length]
  257. asm        mov    dx,[WORD PTR source]
  258. asm        mov    ds,[WORD PTR source+2]
  259. asm        mov    ah,0x40            // WRITE w/handle
  260. asm        int    21h
  261. asm        pop    ds
  262. asm        jnc    good
  263.     errno = _AX;
  264.     return    false;
  265. good:
  266. asm        cmp    ax,[WORD PTR length]
  267. asm        je    done
  268.     errno = ENOMEM;                // user manager knows this is bad write
  269.     return    false;
  270.  
  271. done:
  272.     return    true;
  273. }
  274.  
  275.  
  276. /*
  277. ==========================
  278. =
  279. = CA_ReadFile
  280. =
  281. = Reads a file into an allready allocated buffer
  282. =
  283. ==========================
  284. */
  285.  
  286. boolean CA_ReadFile (char *filename, memptr *ptr)
  287. {
  288.     int handle;
  289.     long size;
  290.  
  291.     if ((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)
  292.         return false;
  293.  
  294.     size = filelength (handle);
  295.     if (!CA_FarRead (handle,*ptr,size))
  296.     {
  297.         close (handle);
  298.         return false;
  299.     }
  300.     close (handle);
  301.     return true;
  302. }
  303.  
  304.  
  305. /*
  306. ==========================
  307. =
  308. = CA_WriteFile
  309. =
  310. = Writes a file from a memory buffer
  311. =
  312. ==========================
  313. */
  314.  
  315. boolean CA_WriteFile (char *filename, void far *ptr, long length)
  316. {
  317.     int handle;
  318.     long size;
  319.  
  320.     handle = open(filename,O_CREAT | O_BINARY | O_WRONLY,
  321.                 S_IREAD | S_IWRITE | S_IFREG);
  322.  
  323.     if (handle == -1)
  324.         return false;
  325.  
  326.     if (!CA_FarWrite (handle,ptr,length))
  327.     {
  328.         close (handle);
  329.         return false;
  330.     }
  331.     close (handle);
  332.     return true;
  333. }
  334.  
  335.  
  336.  
  337. /*
  338. ==========================
  339. =
  340. = CA_LoadFile
  341. =
  342. = Allocate space for and load a file
  343. =
  344. ==========================
  345. */
  346.  
  347. boolean CA_LoadFile (char *filename, memptr *ptr)
  348. {
  349.     int handle;
  350.     long size;
  351.  
  352.     if ((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)
  353.         return false;
  354.  
  355.     size = filelength (handle);
  356.     MM_GetPtr (ptr,size);
  357.     if (!CA_FarRead (handle,*ptr,size))
  358.     {
  359.         close (handle);
  360.         return false;
  361.     }
  362.     close (handle);
  363.     return true;
  364. }
  365.  
  366. /*
  367. ============================================================================
  368.  
  369.         COMPRESSION routines, see JHUFF.C for more
  370.  
  371. ============================================================================
  372. */
  373.  
  374.  
  375.  
  376. /*
  377. ===============
  378. =
  379. = CAL_OptimizeNodes
  380. =
  381. = Goes through a huffman table and changes the 256-511 node numbers to the
  382. = actular address of the node.  Must be called before CAL_HuffExpand
  383. =
  384. ===============
  385. */
  386.  
  387. void CAL_OptimizeNodes (huffnode *table)
  388. {
  389.   huffnode *node;
  390.   int i;
  391.  
  392.   node = table;
  393.  
  394.   for (i=0;i<255;i++)
  395.   {
  396.     if (node->bit0 >= 256)
  397.       node->bit0 = (unsigned)(table+(node->bit0-256));
  398.     if (node->bit1 >= 256)
  399.       node->bit1 = (unsigned)(table+(node->bit1-256));
  400.     node++;
  401.   }
  402. }
  403.  
  404.  
  405.  
  406. /*
  407. ======================
  408. =
  409. = CAL_HuffExpand
  410. =
  411. = Length is the length of the EXPANDED data
  412. = If screenhack, the data is decompressed in four planes directly
  413. = to the screen
  414. =
  415. ======================
  416. */
  417.  
  418. void CAL_HuffExpand (byte huge *source, byte huge *dest,
  419.   long length,huffnode *hufftable, boolean screenhack)
  420. {
  421. //  unsigned bit,byte,node,code;
  422.   unsigned sourceseg,sourceoff,destseg,destoff,endoff;
  423.   huffnode *headptr;
  424.   byte        mapmask;
  425. //  huffnode *nodeon;
  426.  
  427.   headptr = hufftable+254;    // head node is allways node 254
  428.  
  429.   source++;    // normalize
  430.   source--;
  431.   dest++;
  432.   dest--;
  433.  
  434.   if (screenhack)
  435.   {
  436.     mapmask = 1;
  437. asm    mov    dx,SC_INDEX
  438. asm    mov    ax,SC_MAPMASK + 256
  439. asm    out    dx,ax
  440.     length >>= 2;
  441.   }
  442.  
  443.   sourceseg = FP_SEG(source);
  444.   sourceoff = FP_OFF(source);
  445.   destseg = FP_SEG(dest);
  446.   destoff = FP_OFF(dest);
  447.   endoff = destoff+length;
  448.  
  449. //
  450. // ds:si source
  451. // es:di dest
  452. // ss:bx node pointer
  453. //
  454.  
  455.     if (length <0xfff0)
  456.     {
  457.  
  458. //--------------------------
  459. // expand less than 64k of data
  460. //--------------------------
  461.  
  462. asm mov    bx,[headptr]
  463.  
  464. asm    mov    si,[sourceoff]
  465. asm    mov    di,[destoff]
  466. asm    mov    es,[destseg]
  467. asm    mov    ds,[sourceseg]
  468. asm    mov    ax,[endoff]
  469.  
  470. asm    mov    ch,[si]                // load first byte
  471. asm    inc    si
  472. asm    mov    cl,1
  473.  
  474. expandshort:
  475. asm    test    ch,cl            // bit set?
  476. asm    jnz    bit1short
  477. asm    mov    dx,[ss:bx]            // take bit0 path from node
  478. asm    shl    cl,1                // advance to next bit position
  479. asm    jc    newbyteshort
  480. asm    jnc    sourceupshort
  481.  
  482. bit1short:
  483. asm    mov    dx,[ss:bx+2]        // take bit1 path
  484. asm    shl    cl,1                // advance to next bit position
  485. asm    jnc    sourceupshort
  486.  
  487. newbyteshort:
  488. asm    mov    ch,[si]                // load next byte
  489. asm    inc    si
  490. asm    mov    cl,1                // back to first bit
  491.  
  492. sourceupshort:
  493. asm    or    dh,dh                // if dx<256 its a byte, else move node
  494. asm    jz    storebyteshort
  495. asm    mov    bx,dx                // next node = (huffnode *)code
  496. asm    jmp    expandshort
  497.  
  498. storebyteshort:
  499. asm    mov    [es:di],dl
  500. asm    inc    di                    // write a decopmpressed byte out
  501. asm    mov    bx,[headptr]        // back to the head node for next bit
  502.  
  503. asm    cmp    di,ax                // done?
  504. asm    jne    expandshort
  505.  
  506. //
  507. // perform screenhack if needed
  508. //
  509. asm    test    [screenhack],1
  510. asm    jz    notscreen
  511. asm    shl    [mapmask],1
  512. asm    mov    ah,[mapmask]
  513. asm    cmp    ah,16
  514. asm    je    notscreen            // all four planes done
  515. asm    mov    dx,SC_INDEX
  516. asm    mov    al,SC_MAPMASK
  517. asm    out    dx,ax
  518. asm    mov    di,[destoff]
  519. asm    mov    ax,[endoff]
  520. asm    jmp    expandshort
  521.  
  522. notscreen:;
  523.     }
  524.     else
  525.     {
  526.  
  527. //--------------------------
  528. // expand more than 64k of data
  529. //--------------------------
  530.  
  531.   length--;
  532.  
  533. asm mov    bx,[headptr]
  534. asm    mov    cl,1
  535.  
  536. asm    mov    si,[sourceoff]
  537. asm    mov    di,[destoff]
  538. asm    mov    es,[destseg]
  539. asm    mov    ds,[sourceseg]
  540.  
  541. asm    lodsb            // load first byte
  542.  
  543. expand:
  544. asm    test    al,cl        // bit set?
  545. asm    jnz    bit1
  546. asm    mov    dx,[ss:bx]    // take bit0 path from node
  547. asm    jmp    gotcode
  548. bit1:
  549. asm    mov    dx,[ss:bx+2]    // take bit1 path
  550.  
  551. gotcode:
  552. asm    shl    cl,1        // advance to next bit position
  553. asm    jnc    sourceup
  554. asm    lodsb
  555. asm    cmp    si,0x10        // normalize ds:si
  556. asm      jb    sinorm
  557. asm    mov    cx,ds
  558. asm    inc    cx
  559. asm    mov    ds,cx
  560. asm    xor    si,si
  561. sinorm:
  562. asm    mov    cl,1        // back to first bit
  563.  
  564. sourceup:
  565. asm    or    dh,dh        // if dx<256 its a byte, else move node
  566. asm    jz    storebyte
  567. asm    mov    bx,dx        // next node = (huffnode *)code
  568. asm    jmp    expand
  569.  
  570. storebyte:
  571. asm    mov    [es:di],dl
  572. asm    inc    di        // write a decopmpressed byte out
  573. asm    mov    bx,[headptr]    // back to the head node for next bit
  574.  
  575. asm    cmp    di,0x10        // normalize es:di
  576. asm      jb    dinorm
  577. asm    mov    dx,es
  578. asm    inc    dx
  579. asm    mov    es,dx
  580. asm    xor    di,di
  581. dinorm:
  582.  
  583. asm    sub    [WORD PTR ss:length],1
  584. asm    jnc    expand
  585. asm      dec    [WORD PTR ss:length+2]
  586. asm    jns    expand        // when length = ffff ffff, done
  587.  
  588.     }
  589.  
  590. asm    mov    ax,ss
  591. asm    mov    ds,ax
  592.  
  593. }
  594.  
  595.  
  596. /*
  597. ======================
  598. =
  599. = CAL_CarmackExpand
  600. =
  601. = Length is the length of the EXPANDED data
  602. =
  603. ======================
  604. */
  605.  
  606. #define NEARTAG    0xa7
  607. #define FARTAG    0xa8
  608.  
  609. void CAL_CarmackExpand (unsigned far *source, unsigned far *dest, unsigned length)
  610. {
  611.     unsigned    ch,chhigh,count,offset;
  612.     unsigned    far *copyptr, far *inptr, far *outptr;
  613.  
  614.     length/=2;
  615.  
  616.     inptr = source;
  617.     outptr = dest;
  618.  
  619.     while (length)
  620.     {
  621.         ch = *inptr++;
  622.         chhigh = ch>>8;
  623.         if (chhigh == NEARTAG)
  624.         {
  625.             count = ch&0xff;
  626.             if (!count)
  627.             {                // have to insert a word containing the tag byte
  628.                 ch |= *((unsigned char far *)inptr)++;
  629.                 *outptr++ = ch;
  630.                 length--;
  631.             }
  632.             else
  633.             {
  634.                 offset = *((unsigned char far *)inptr)++;
  635.                 copyptr = outptr - offset;
  636.                 length -= count;
  637.                 while (count--)
  638.                     *outptr++ = *copyptr++;
  639.             }
  640.         }
  641.         else if (chhigh == FARTAG)
  642.         {
  643.             count = ch&0xff;
  644.             if (!count)
  645.             {                // have to insert a word containing the tag byte
  646.                 ch |= *((unsigned char far *)inptr)++;
  647.                 *outptr++ = ch;
  648.                 length --;
  649.             }
  650.             else
  651.             {
  652.                 offset = *inptr++;
  653.                 copyptr = dest + offset;
  654.                 length -= count;
  655.                 while (count--)
  656.                     *outptr++ = *copyptr++;
  657.             }
  658.         }
  659.         else
  660.         {
  661.             *outptr++ = ch;
  662.             length --;
  663.         }
  664.     }
  665. }
  666.  
  667.  
  668.  
  669. /*
  670. ======================
  671. =
  672. = CA_RLEWcompress
  673. =
  674. ======================
  675. */
  676.  
  677. long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest,
  678.   unsigned rlewtag)
  679. {
  680.   long complength;
  681.   unsigned value,count,i;
  682.   unsigned huge *start,huge *end;
  683.  
  684.   start = dest;
  685.  
  686.   end = source + (length+1)/2;
  687.  
  688. //
  689. // compress it
  690. //
  691.   do
  692.   {
  693.     count = 1;
  694.     value = *source++;
  695.     while (*source == value && source<end)
  696.     {
  697.       count++;
  698.       source++;
  699.     }
  700.     if (count>3 || value == rlewtag)
  701.     {
  702.     //
  703.     // send a tag / count / value string
  704.     //
  705.       *dest++ = rlewtag;
  706.       *dest++ = count;
  707.       *dest++ = value;
  708.     }
  709.     else
  710.     {
  711.     //
  712.     // send word without compressing
  713.     //
  714.       for (i=1;i<=count;i++)
  715.     *dest++ = value;
  716.     }
  717.  
  718.   } while (source<end);
  719.  
  720.   complength = 2*(dest-start);
  721.   return complength;
  722. }
  723.  
  724.  
  725. /*
  726. ======================
  727. =
  728. = CA_RLEWexpand
  729. = length is EXPANDED length
  730. =
  731. ======================
  732. */
  733.  
  734. void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,
  735.   unsigned rlewtag)
  736. {
  737. //  unsigned value,count,i;
  738.   unsigned huge *end;
  739.   unsigned sourceseg,sourceoff,destseg,destoff,endseg,endoff;
  740.  
  741.  
  742. //
  743. // expand it
  744. //
  745. #if 0
  746.   do
  747.   {
  748.     value = *source++;
  749.     if (value != rlewtag)
  750.     //
  751.     // uncompressed
  752.     //
  753.       *dest++=value;
  754.     else
  755.     {
  756.     //
  757.     // compressed string
  758.     //
  759.       count = *source++;
  760.       value = *source++;
  761.       for (i=1;i<=count;i++)
  762.     *dest++ = value;
  763.     }
  764.   } while (dest<end);
  765. #endif
  766.  
  767.   end = dest + (length)/2;
  768.   sourceseg = FP_SEG(source);
  769.   sourceoff = FP_OFF(source);
  770.   destseg = FP_SEG(dest);
  771.   destoff = FP_OFF(dest);
  772.   endseg = FP_SEG(end);
  773.   endoff = FP_OFF(end);
  774.  
  775.  
  776. //
  777. // ax = source value
  778. // bx = tag value
  779. // cx = repeat counts
  780. // dx = scratch
  781. //
  782. // NOTE: A repeat count that produces 0xfff0 bytes can blow this!
  783. //
  784.  
  785. asm    mov    bx,rlewtag
  786. asm    mov    si,sourceoff
  787. asm    mov    di,destoff
  788. asm    mov    es,destseg
  789. asm    mov    ds,sourceseg
  790.  
  791. expand:
  792. asm    lodsw
  793. asm    cmp    ax,bx
  794. asm    je    repeat
  795. asm    stosw
  796. asm    jmp    next
  797.  
  798. repeat:
  799. asm    lodsw
  800. asm    mov    cx,ax        // repeat count
  801. asm    lodsw            // repeat value
  802. asm    rep stosw
  803.  
  804. next:
  805.  
  806. asm    cmp    si,0x10        // normalize ds:si
  807. asm      jb    sinorm
  808. asm    mov    ax,si
  809. asm    shr    ax,1
  810. asm    shr    ax,1
  811. asm    shr    ax,1
  812. asm    shr    ax,1
  813. asm    mov    dx,ds
  814. asm    add    dx,ax
  815. asm    mov    ds,dx
  816. asm    and    si,0xf
  817. sinorm:
  818. asm    cmp    di,0x10        // normalize es:di
  819. asm      jb    dinorm
  820. asm    mov    ax,di
  821. asm    shr    ax,1
  822. asm    shr    ax,1
  823. asm    shr    ax,1
  824. asm    shr    ax,1
  825. asm    mov    dx,es
  826. asm    add    dx,ax
  827. asm    mov    es,dx
  828. asm    and    di,0xf
  829. dinorm:
  830.  
  831. asm    cmp     di,ss:endoff
  832. asm    jne    expand
  833. asm    mov    ax,es
  834. asm    cmp    ax,ss:endseg
  835. asm    jb    expand
  836.  
  837. asm    mov    ax,ss
  838. asm    mov    ds,ax
  839.  
  840. }
  841.  
  842.  
  843.  
  844. /*
  845. =============================================================================
  846.  
  847.                      CACHE MANAGER ROUTINES
  848.  
  849. =============================================================================
  850. */
  851.  
  852.  
  853. /*
  854. ======================
  855. =
  856. = CAL_SetupGrFile
  857. =
  858. ======================
  859. */
  860.  
  861. void CAL_SetupGrFile (void)
  862. {
  863.     char fname[13];
  864.     int handle;
  865.     memptr compseg;
  866.  
  867. #ifdef GRHEADERLINKED
  868.  
  869.     grhuffman = (huffnode *)&EGAdict;
  870.     grstarts = (long _seg *)FP_SEG(&EGAhead);
  871.  
  872.     CAL_OptimizeNodes (grhuffman);
  873.  
  874. #else
  875.  
  876. //
  877. // load ???dict.ext (huffman dictionary for graphics files)
  878. //
  879.  
  880.     strcpy(fname,gdictname);
  881.     strcat(fname,extension);
  882.  
  883.     if ((handle = open(fname,
  884.          O_RDONLY | O_BINARY, S_IREAD)) == -1)
  885.         CA_CannotOpen(fname);
  886.  
  887.     read(handle, &grhuffman, sizeof(grhuffman));
  888.     close(handle);
  889.     CAL_OptimizeNodes (grhuffman);
  890. //
  891. // load the data offsets from ???head.ext
  892. //
  893.     MM_GetPtr (&(memptr)grstarts,(NUMCHUNKS+1)*FILEPOSSIZE);
  894.  
  895.     strcpy(fname,gheadname);
  896.     strcat(fname,extension);
  897.  
  898.     if ((handle = open(fname,
  899.          O_RDONLY | O_BINARY, S_IREAD)) == -1)
  900.         CA_CannotOpen(fname);
  901.  
  902.     CA_FarRead(handle, (memptr)grstarts, (NUMCHUNKS+1)*FILEPOSSIZE);
  903.  
  904.     close(handle);
  905.  
  906.  
  907. #endif
  908.  
  909. //
  910. // Open the graphics file, leaving it open until the game is finished
  911. //
  912.     strcpy(fname,gfilename);
  913.     strcat(fname,extension);
  914.  
  915.     grhandle = open(fname, O_RDONLY | O_BINARY);
  916.     if (grhandle == -1)
  917.         CA_CannotOpen(fname);
  918.  
  919.  
  920. //
  921. // load the pic and sprite headers into the arrays in the data segment
  922. //
  923.     MM_GetPtr(&(memptr)pictable,NUMPICS*sizeof(pictabletype));
  924.     CAL_GetGrChunkLength(STRUCTPIC);        // position file pointer
  925.     MM_GetPtr(&compseg,chunkcomplen);
  926.     CA_FarRead (grhandle,compseg,chunkcomplen);
  927.     CAL_HuffExpand (compseg, (byte huge *)pictable,NUMPICS*sizeof(pictabletype),grhuffman,false);
  928.     MM_FreePtr(&compseg);
  929. }
  930.  
  931. //==========================================================================
  932.  
  933.  
  934. /*
  935. ======================
  936. =
  937. = CAL_SetupMapFile
  938. =
  939. ======================
  940. */
  941.  
  942. void CAL_SetupMapFile (void)
  943. {
  944.     int    i;
  945.     int handle;
  946.     long length,pos;
  947.     char fname[13];
  948.  
  949. //
  950. // load maphead.ext (offsets and tileinfo for map file)
  951. //
  952. #ifndef MAPHEADERLINKED
  953.     strcpy(fname,mheadname);
  954.     strcat(fname,extension);
  955.  
  956.     if ((handle = open(fname,
  957.          O_RDONLY | O_BINARY, S_IREAD)) == -1)
  958.         CA_CannotOpen(fname);
  959.  
  960.     length = filelength(handle);
  961.     MM_GetPtr (&(memptr)tinf,length);
  962.     CA_FarRead(handle, tinf, length);
  963.     close(handle);
  964. #else
  965.  
  966.     tinf = (byte _seg *)FP_SEG(&maphead);
  967.  
  968. #endif
  969.  
  970. //
  971. // open the data file
  972. //
  973. #ifdef CARMACIZED
  974.     strcpy(fname,"GAMEMAPS.");
  975.     strcat(fname,extension);
  976.  
  977.     if ((maphandle = open(fname,
  978.          O_RDONLY | O_BINARY, S_IREAD)) == -1)
  979.         CA_CannotOpen(fname);
  980. #else
  981.     strcpy(fname,mfilename);
  982.     strcat(fname,extension);
  983.  
  984.     if ((maphandle = open(fname,
  985.          O_RDONLY | O_BINARY, S_IREAD)) == -1)
  986.         CA_CannotOpen(fname);
  987. #endif
  988.  
  989. //
  990. // load all map header
  991. //
  992.     for (i=0;i<NUMMAPS;i++)
  993.     {
  994.         pos = ((mapfiletype    _seg *)tinf)->headeroffsets[i];
  995.         if (pos<0)                        // $FFFFFFFF start is a sparse map
  996.             continue;
  997.  
  998.         MM_GetPtr(&(memptr)mapheaderseg[i],sizeof(maptype));
  999.         MM_SetLock(&(memptr)mapheaderseg[i],true);
  1000.         lseek(maphandle,pos,SEEK_SET);
  1001.         CA_FarRead (maphandle,(memptr)mapheaderseg[i],sizeof(maptype));
  1002.     }
  1003.  
  1004. //
  1005. // allocate space for 3 64*64 planes
  1006. //
  1007.     for (i=0;i<MAPPLANES;i++)
  1008.     {
  1009.         MM_GetPtr (&(memptr)mapsegs[i],64*64*2);
  1010.         MM_SetLock (&(memptr)mapsegs[i],true);
  1011.     }
  1012. }
  1013.  
  1014.  
  1015. //==========================================================================
  1016.  
  1017.  
  1018. /*
  1019. ======================
  1020. =
  1021. = CAL_SetupAudioFile
  1022. =
  1023. ======================
  1024. */
  1025.  
  1026. void CAL_SetupAudioFile (void)
  1027. {
  1028.     int handle;
  1029.     long length;
  1030.     char fname[13];
  1031.  
  1032. //
  1033. // load maphead.ext (offsets and tileinfo for map file)
  1034. //
  1035. #ifndef AUDIOHEADERLINKED
  1036.     strcpy(fname,aheadname);
  1037.     strcat(fname,extension);
  1038.  
  1039.     if ((handle = open(fname,
  1040.          O_RDONLY | O_BINARY, S_IREAD)) == -1)
  1041.         CA_CannotOpen(fname);
  1042.  
  1043.     length = filelength(handle);
  1044.     MM_GetPtr (&(memptr)audiostarts,length);
  1045.     CA_FarRead(handle, (byte far *)audiostarts, length);
  1046.     close(handle);
  1047. #else
  1048.     audiohuffman = (huffnode *)&audiodict;
  1049.     CAL_OptimizeNodes (audiohuffman);
  1050.     audiostarts = (long _seg *)FP_SEG(&audiohead);
  1051. #endif
  1052.  
  1053. //
  1054. // open the data file
  1055. //
  1056. #ifndef AUDIOHEADERLINKED
  1057.     strcpy(fname,afilename);
  1058.     strcat(fname,extension);
  1059.  
  1060.     if ((audiohandle = open(fname,
  1061.          O_RDONLY | O_BINARY, S_IREAD)) == -1)
  1062.         CA_CannotOpen(fname);
  1063. #else
  1064.     if ((audiohandle = open("AUDIO."EXTENSION,
  1065.          O_RDONLY | O_BINARY, S_IREAD)) == -1)
  1066.         Quit ("Can't open AUDIO."EXTENSION"!");
  1067. #endif
  1068. }
  1069.  
  1070. //==========================================================================
  1071.  
  1072.  
  1073. /*
  1074. ======================
  1075. =
  1076. = CA_Startup
  1077. =
  1078. = Open all files and load in headers
  1079. =
  1080. ======================
  1081. */
  1082.  
  1083. void CA_Startup (void)
  1084. {
  1085. #ifdef PROFILE
  1086.     unlink ("PROFILE.TXT");
  1087.     profilehandle = open("PROFILE.TXT", O_CREAT | O_WRONLY | O_TEXT);
  1088. #endif
  1089.  
  1090.     CAL_SetupMapFile ();
  1091.     CAL_SetupGrFile ();
  1092.     CAL_SetupAudioFile ();
  1093.  
  1094.     mapon = -1;
  1095.     ca_levelbit = 1;
  1096.     ca_levelnum = 0;
  1097.  
  1098. }
  1099.  
  1100. //==========================================================================
  1101.  
  1102.  
  1103. /*
  1104. ======================
  1105. =
  1106. = CA_Shutdown
  1107. =
  1108. = Closes all files
  1109. =
  1110. ======================
  1111. */
  1112.  
  1113. void CA_Shutdown (void)
  1114. {
  1115. #ifdef PROFILE
  1116.     close (profilehandle);
  1117. #endif
  1118.  
  1119.     close (maphandle);
  1120.     close (grhandle);
  1121.     close (audiohandle);
  1122. }
  1123.  
  1124. //===========================================================================
  1125.  
  1126. /*
  1127. ======================
  1128. =
  1129. = CA_CacheAudioChunk
  1130. =
  1131. ======================
  1132. */
  1133.  
  1134. void CA_CacheAudioChunk (int chunk)
  1135. {
  1136.     long    pos,compressed;
  1137. #ifdef AUDIOHEADERLINKED
  1138.     long    expanded;
  1139.     memptr    bigbufferseg;
  1140.     byte    far *source;
  1141. #endif
  1142.  
  1143.     if (audiosegs[chunk])
  1144.     {
  1145.         MM_SetPurge (&(memptr)audiosegs[chunk],0);
  1146.         return;                            // allready in memory
  1147.     }
  1148.  
  1149. //
  1150. // load the chunk into a buffer, either the miscbuffer if it fits, or allocate
  1151. // a larger buffer
  1152. //
  1153.     pos = audiostarts[chunk];
  1154.     compressed = audiostarts[chunk+1]-pos;
  1155.  
  1156.     lseek(audiohandle,pos,SEEK_SET);
  1157.  
  1158. #ifndef AUDIOHEADERLINKED
  1159.  
  1160.     MM_GetPtr (&(memptr)audiosegs[chunk],compressed);
  1161.     if (mmerror)
  1162.         return;
  1163.  
  1164.     CA_FarRead(audiohandle,audiosegs[chunk],compressed);
  1165.  
  1166. #else
  1167.  
  1168.     if (compressed<=BUFFERSIZE)
  1169.     {
  1170.         CA_FarRead(audiohandle,bufferseg,compressed);
  1171.         source = bufferseg;
  1172.     }
  1173.     else
  1174.     {
  1175.         MM_GetPtr(&bigbufferseg,compressed);
  1176.         if (mmerror)
  1177.             return;
  1178.         MM_SetLock (&bigbufferseg,true);
  1179.         CA_FarRead(audiohandle,bigbufferseg,compressed);
  1180.         source = bigbufferseg;
  1181.     }
  1182.  
  1183.     expanded = *(long far *)source;
  1184.     source += 4;            // skip over length
  1185.     MM_GetPtr (&(memptr)audiosegs[chunk],expanded);
  1186.     if (mmerror)
  1187.         goto done;
  1188.     CAL_HuffExpand (source,audiosegs[chunk],expanded,audiohuffman,false);
  1189.  
  1190. done:
  1191.     if (compressed>BUFFERSIZE)
  1192.         MM_FreePtr(&bigbufferseg);
  1193. #endif
  1194. }
  1195.  
  1196. //===========================================================================
  1197.  
  1198. /*
  1199. ======================
  1200. =
  1201. = CA_LoadAllSounds
  1202. =
  1203. = Purges all sounds, then loads all new ones (mode switch)
  1204. =
  1205. ======================
  1206. */
  1207.  
  1208. void CA_LoadAllSounds (void)
  1209. {
  1210.     unsigned    start,i;
  1211.  
  1212.     switch (oldsoundmode)
  1213.     {
  1214.     case sdm_Off:
  1215.         goto cachein;
  1216.     case sdm_PC:
  1217.         start = STARTPCSOUNDS;
  1218.         break;
  1219.     case sdm_AdLib:
  1220.         start = STARTADLIBSOUNDS;
  1221.         break;
  1222.     }
  1223.  
  1224.     for (i=0;i<NUMSOUNDS;i++,start++)
  1225.         if (audiosegs[start])
  1226.             MM_SetPurge (&(memptr)audiosegs[start],3);        // make purgable
  1227.  
  1228. cachein:
  1229.  
  1230.     switch (SoundMode)
  1231.     {
  1232.     case sdm_Off:
  1233.         return;
  1234.     case sdm_PC:
  1235.         start = STARTPCSOUNDS;
  1236.         break;
  1237.     case sdm_AdLib:
  1238.         start = STARTADLIBSOUNDS;
  1239.         break;
  1240.     }
  1241.  
  1242.     for (i=0;i<NUMSOUNDS;i++,start++)
  1243.         CA_CacheAudioChunk (start);
  1244.  
  1245.     oldsoundmode = SoundMode;
  1246. }
  1247.  
  1248. //===========================================================================
  1249.  
  1250.  
  1251. /*
  1252. ======================
  1253. =
  1254. = CAL_ExpandGrChunk
  1255. =
  1256. = Does whatever is needed with a pointer to a compressed chunk
  1257. =
  1258. ======================
  1259. */
  1260.  
  1261. void CAL_ExpandGrChunk (int chunk, byte far *source)
  1262. {
  1263.     long    expanded;
  1264.  
  1265.  
  1266.     if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)
  1267.     {
  1268.     //
  1269.     // expanded sizes of tile8/16/32 are implicit
  1270.     //
  1271.  
  1272. #define BLOCK        64
  1273. #define MASKBLOCK    128
  1274.  
  1275.         if (chunk<STARTTILE8M)            // tile 8s are all in one chunk!
  1276.             expanded = BLOCK*NUMTILE8;
  1277.         else if (chunk<STARTTILE16)
  1278.             expanded = MASKBLOCK*NUMTILE8M;
  1279.         else if (chunk<STARTTILE16M)    // all other tiles are one/chunk
  1280.             expanded = BLOCK*4;
  1281.         else if (chunk<STARTTILE32)
  1282.             expanded = MASKBLOCK*4;
  1283.         else if (chunk<STARTTILE32M)
  1284.             expanded = BLOCK*16;
  1285.         else
  1286.             expanded = MASKBLOCK*16;
  1287.     }
  1288.     else
  1289.     {
  1290.     //
  1291.     // everything else has an explicit size longword
  1292.     //
  1293.         expanded = *(long far *)source;
  1294.         source += 4;            // skip over length
  1295.     }
  1296.  
  1297. //
  1298. // allocate final space, decompress it, and free bigbuffer
  1299. // Sprites need to have shifts made and various other junk
  1300. //
  1301.     MM_GetPtr (&grsegs[chunk],expanded);
  1302.     if (mmerror)
  1303.         return;
  1304.     CAL_HuffExpand (source,grsegs[chunk],expanded,grhuffman,false);
  1305. }
  1306.  
  1307.  
  1308. /*
  1309. ======================
  1310. =
  1311. = CA_CacheGrChunk
  1312. =
  1313. = Makes sure a given chunk is in memory, loadiing it if needed
  1314. =
  1315. ======================
  1316. */
  1317.  
  1318. void CA_CacheGrChunk (int chunk)
  1319. {
  1320.     long    pos,compressed;
  1321.     memptr    bigbufferseg;
  1322.     byte    far *source;
  1323.     int        next;
  1324.  
  1325.     grneeded[chunk] |= ca_levelbit;        // make sure it doesn't get removed
  1326.     if (grsegs[chunk])
  1327.     {
  1328.         MM_SetPurge (&grsegs[chunk],0);
  1329.         return;                            // allready in memory
  1330.     }
  1331.  
  1332. //
  1333. // load the chunk into a buffer, either the miscbuffer if it fits, or allocate
  1334. // a larger buffer
  1335. //
  1336.     pos = GRFILEPOS(chunk);
  1337.     if (pos<0)                            // $FFFFFFFF start is a sparse tile
  1338.       return;
  1339.  
  1340.     next = chunk +1;
  1341.     while (GRFILEPOS(next) == -1)        // skip past any sparse tiles
  1342.         next++;
  1343.  
  1344.     compressed = GRFILEPOS(next)-pos;
  1345.  
  1346.     lseek(grhandle,pos,SEEK_SET);
  1347.  
  1348.     if (compressed<=BUFFERSIZE)
  1349.     {
  1350.         CA_FarRead(grhandle,bufferseg,compressed);
  1351.         source = bufferseg;
  1352.     }
  1353.     else
  1354.     {
  1355.         MM_GetPtr(&bigbufferseg,compressed);
  1356.         MM_SetLock (&bigbufferseg,true);
  1357.         CA_FarRead(grhandle,bigbufferseg,compressed);
  1358.         source = bigbufferseg;
  1359.     }
  1360.  
  1361.     CAL_ExpandGrChunk (chunk,source);
  1362.  
  1363.     if (compressed>BUFFERSIZE)
  1364.         MM_FreePtr(&bigbufferseg);
  1365. }
  1366.  
  1367.  
  1368.  
  1369. //==========================================================================
  1370.  
  1371. /*
  1372. ======================
  1373. =
  1374. = CA_CacheScreen
  1375. =
  1376. = Decompresses a chunk from disk straight onto the screen
  1377. =
  1378. ======================
  1379. */
  1380.  
  1381. void CA_CacheScreen (int chunk)
  1382. {
  1383.     long    pos,compressed,expanded;
  1384.     memptr    bigbufferseg;
  1385.     byte    far *source;
  1386.     int        next;
  1387.  
  1388. //
  1389. // load the chunk into a buffer
  1390. //
  1391.     pos = GRFILEPOS(chunk);
  1392.     next = chunk +1;
  1393.     while (GRFILEPOS(next) == -1)        // skip past any sparse tiles
  1394.         next++;
  1395.     compressed = GRFILEPOS(next)-pos;
  1396.  
  1397.     lseek(grhandle,pos,SEEK_SET);
  1398.  
  1399.     MM_GetPtr(&bigbufferseg,compressed);
  1400.     MM_SetLock (&bigbufferseg,true);
  1401.     CA_FarRead(grhandle,bigbufferseg,compressed);
  1402.     source = bigbufferseg;
  1403.  
  1404.     expanded = *(long far *)source;
  1405.     source += 4;            // skip over length
  1406.  
  1407. //
  1408. // allocate final space, decompress it, and free bigbuffer
  1409. // Sprites need to have shifts made and various other junk
  1410. //
  1411.     CAL_HuffExpand (source,MK_FP(SCREENSEG,bufferofs),expanded,grhuffman,true);
  1412.     VW_MarkUpdateBlock (0,0,319,199);
  1413.     MM_FreePtr(&bigbufferseg);
  1414. }
  1415.  
  1416. //==========================================================================
  1417.  
  1418. /*
  1419. ======================
  1420. =
  1421. = CA_CacheMap
  1422. =
  1423. = WOLF: This is specialized for a 64*64 map size
  1424. =
  1425. ======================
  1426. */
  1427.  
  1428. void CA_CacheMap (int mapnum)
  1429. {
  1430.     long    pos,compressed;
  1431.     int        plane;
  1432.     memptr    *dest,bigbufferseg;
  1433.     unsigned    size;
  1434.     unsigned    far    *source;
  1435. #ifdef CARMACIZED
  1436.     memptr    buffer2seg;
  1437.     long    expanded;
  1438. #endif
  1439.  
  1440.     mapon = mapnum;
  1441.  
  1442. //
  1443. // load the planes into the allready allocated buffers
  1444. //
  1445.     size = 64*64*2;
  1446.  
  1447.     for (plane = 0; plane<MAPPLANES; plane++)
  1448.     {
  1449.         pos = mapheaderseg[mapnum]->planestart[plane];
  1450.         compressed = mapheaderseg[mapnum]->planelength[plane];
  1451.  
  1452.         dest = &(memptr)mapsegs[plane];
  1453.  
  1454.         lseek(maphandle,pos,SEEK_SET);
  1455.         if (compressed<=BUFFERSIZE)
  1456.             source = bufferseg;
  1457.         else
  1458.         {
  1459.             MM_GetPtr(&bigbufferseg,compressed);
  1460.             MM_SetLock (&bigbufferseg,true);
  1461.             source = bigbufferseg;
  1462.         }
  1463.  
  1464.         CA_FarRead(maphandle,(byte far *)source,compressed);
  1465. #ifdef CARMACIZED
  1466.         //
  1467.         // unhuffman, then unRLEW
  1468.         // The huffman'd chunk has a two byte expanded length first
  1469.         // The resulting RLEW chunk also does, even though it's not really
  1470.         // needed
  1471.         //
  1472.         expanded = *source;
  1473.         source++;
  1474.         MM_GetPtr (&buffer2seg,expanded);
  1475.         CAL_CarmackExpand (source, (unsigned far *)buffer2seg,expanded);
  1476.         CA_RLEWexpand (((unsigned far *)buffer2seg)+1,*dest,size,
  1477.         ((mapfiletype _seg *)tinf)->RLEWtag);
  1478.         MM_FreePtr (&buffer2seg);
  1479.  
  1480. #else
  1481.         //
  1482.         // unRLEW, skipping expanded length
  1483.         //
  1484.         CA_RLEWexpand (source+1, *dest,size,
  1485.         ((mapfiletype _seg *)tinf)->RLEWtag);
  1486. #endif
  1487.  
  1488.         if (compressed>BUFFERSIZE)
  1489.             MM_FreePtr(&bigbufferseg);
  1490.     }
  1491. }
  1492.  
  1493. //===========================================================================
  1494.  
  1495. /*
  1496. ======================
  1497. =
  1498. = CA_UpLevel
  1499. =
  1500. = Goes up a bit level in the needed lists and clears it out.
  1501. = Everything is made purgable
  1502. =
  1503. ======================
  1504. */
  1505.  
  1506. void CA_UpLevel (void)
  1507. {
  1508.     int    i;
  1509.  
  1510.     if (ca_levelnum==7)
  1511.         Quit ("CA_UpLevel: Up past level 7!");
  1512.  
  1513.     for (i=0;i<NUMCHUNKS;i++)
  1514.         if (grsegs[i])
  1515.             MM_SetPurge (&(memptr)grsegs[i],3);
  1516.     ca_levelbit<<=1;
  1517.     ca_levelnum++;
  1518. }
  1519.  
  1520. //===========================================================================
  1521.  
  1522. /*
  1523. ======================
  1524. =
  1525. = CA_DownLevel
  1526. =
  1527. = Goes down a bit level in the needed lists and recaches
  1528. = everything from the lower level
  1529. =
  1530. ======================
  1531. */
  1532.  
  1533. void CA_DownLevel (void)
  1534. {
  1535.     if (!ca_levelnum)
  1536.         Quit ("CA_DownLevel: Down past level 0!");
  1537.     ca_levelbit>>=1;
  1538.     ca_levelnum--;
  1539.     CA_CacheMarks();
  1540. }
  1541.  
  1542. //===========================================================================
  1543.  
  1544. /*
  1545. ======================
  1546. =
  1547. = CA_ClearMarks
  1548. =
  1549. = Clears out all the marks at the current level
  1550. =
  1551. ======================
  1552. */
  1553.  
  1554. void CA_ClearMarks (void)
  1555. {
  1556.     int i;
  1557.  
  1558.     for (i=0;i<NUMCHUNKS;i++)
  1559.         grneeded[i]&=~ca_levelbit;
  1560. }
  1561.  
  1562.  
  1563. //===========================================================================
  1564.  
  1565. /*
  1566. ======================
  1567. =
  1568. = CA_ClearAllMarks
  1569. =
  1570. = Clears out all the marks on all the levels
  1571. =
  1572. ======================
  1573. */
  1574.  
  1575. void CA_ClearAllMarks (void)
  1576. {
  1577.     _fmemset (grneeded,0,sizeof(grneeded));
  1578.     ca_levelbit = 1;
  1579.     ca_levelnum = 0;
  1580. }
  1581.  
  1582.  
  1583. //===========================================================================
  1584.  
  1585.  
  1586. /*
  1587. ======================
  1588. =
  1589. = CA_FreeGraphics
  1590. =
  1591. ======================
  1592. */
  1593.  
  1594.  
  1595. void CA_SetGrPurge (void)
  1596. {
  1597.     int i;
  1598.  
  1599. //
  1600. // free graphics
  1601. //
  1602.     CA_ClearMarks ();
  1603.  
  1604.     for (i=0;i<NUMCHUNKS;i++)
  1605.         if (grsegs[i])
  1606.             MM_SetPurge (&(memptr)grsegs[i],3);
  1607. }
  1608.  
  1609.  
  1610.  
  1611. /*
  1612. ======================
  1613. =
  1614. = CA_SetAllPurge
  1615. =
  1616. = Make everything possible purgable
  1617. =
  1618. ======================
  1619. */
  1620.  
  1621. void CA_SetAllPurge (void)
  1622. {
  1623.     int i;
  1624.  
  1625.  
  1626. //
  1627. // free sounds
  1628. //
  1629.     for (i=0;i<NUMSNDCHUNKS;i++)
  1630.         if (audiosegs[i])
  1631.             MM_SetPurge (&(memptr)audiosegs[i],3);
  1632.  
  1633. //
  1634. // free graphics
  1635. //
  1636.     CA_SetGrPurge ();
  1637. }
  1638.  
  1639.  
  1640. //===========================================================================
  1641.  
  1642. /*
  1643. ======================
  1644. =
  1645. = CA_CacheMarks
  1646. =
  1647. ======================
  1648. */
  1649. #define MAXEMPTYREAD    1024
  1650.  
  1651. void CA_CacheMarks (void)
  1652. {
  1653.     int     i,next,numcache;
  1654.     long    pos,endpos,nextpos,nextendpos,compressed;
  1655.     long    bufferstart,bufferend;    // file position of general buffer
  1656.     byte    far *source;
  1657.     memptr    bigbufferseg;
  1658.  
  1659.     numcache = 0;
  1660. //
  1661. // go through and make everything not needed purgable
  1662. //
  1663.     for (i=0;i<NUMCHUNKS;i++)
  1664.         if (grneeded[i]&ca_levelbit)
  1665.         {
  1666.             if (grsegs[i])                    // its allready in memory, make
  1667.                 MM_SetPurge(&grsegs[i],0);    // sure it stays there!
  1668.             else
  1669.                 numcache++;
  1670.         }
  1671.         else
  1672.         {
  1673.             if (grsegs[i])                    // not needed, so make it purgeable
  1674.                 MM_SetPurge(&grsegs[i],3);
  1675.         }
  1676.  
  1677.     if (!numcache)            // nothing to cache!
  1678.         return;
  1679.  
  1680.  
  1681. //
  1682. // go through and load in anything still needed
  1683. //
  1684.     bufferstart = bufferend = 0;        // nothing good in buffer now
  1685.  
  1686.     for (i=0;i<NUMCHUNKS;i++)
  1687.         if ( (grneeded[i]&ca_levelbit) && !grsegs[i])
  1688.         {
  1689.             pos = GRFILEPOS(i);
  1690.             if (pos<0)
  1691.                 continue;
  1692.  
  1693.             next = i +1;
  1694.             while (GRFILEPOS(next) == -1)        // skip past any sparse tiles
  1695.                 next++;
  1696.  
  1697.             compressed = GRFILEPOS(next)-pos;
  1698.             endpos = pos+compressed;
  1699.  
  1700.             if (compressed<=BUFFERSIZE)
  1701.             {
  1702.                 if (bufferstart<=pos
  1703.                 && bufferend>= endpos)
  1704.                 {
  1705.                 // data is allready in buffer
  1706.                     source = (byte _seg *)bufferseg+(pos-bufferstart);
  1707.                 }
  1708.                 else
  1709.                 {
  1710.                 // load buffer with a new block from disk
  1711.                 // try to get as many of the needed blocks in as possible
  1712.                     while ( next < NUMCHUNKS )
  1713.                     {
  1714.                         while (next < NUMCHUNKS &&
  1715.                         !(grneeded[next]&ca_levelbit && !grsegs[next]))
  1716.                             next++;
  1717.                         if (next == NUMCHUNKS)
  1718.                             continue;
  1719.  
  1720.                         nextpos = GRFILEPOS(next);
  1721.                         while (GRFILEPOS(++next) == -1)    // skip past any sparse tiles
  1722.                             ;
  1723.                         nextendpos = GRFILEPOS(next);
  1724.                         if (nextpos - endpos <= MAXEMPTYREAD
  1725.                         && nextendpos-pos <= BUFFERSIZE)
  1726.                             endpos = nextendpos;
  1727.                         else
  1728.                             next = NUMCHUNKS;            // read pos to posend
  1729.                     }
  1730.  
  1731.                     lseek(grhandle,pos,SEEK_SET);
  1732.                     CA_FarRead(grhandle,bufferseg,endpos-pos);
  1733.                     bufferstart = pos;
  1734.                     bufferend = endpos;
  1735.                     source = bufferseg;
  1736.                 }
  1737.             }
  1738.             else
  1739.             {
  1740.             // big chunk, allocate temporary buffer
  1741.                 MM_GetPtr(&bigbufferseg,compressed);
  1742.                 if (mmerror)
  1743.                     return;
  1744.                 MM_SetLock (&bigbufferseg,true);
  1745.                 lseek(grhandle,pos,SEEK_SET);
  1746.                 CA_FarRead(grhandle,bigbufferseg,compressed);
  1747.                 source = bigbufferseg;
  1748.             }
  1749.  
  1750.             CAL_ExpandGrChunk (i,source);
  1751.             if (mmerror)
  1752.                 return;
  1753.  
  1754.             if (compressed>BUFFERSIZE)
  1755.                 MM_FreePtr(&bigbufferseg);
  1756.  
  1757.         }
  1758. }
  1759.  
  1760. void CA_CannotOpen(char *string)
  1761. {
  1762.  char str[30];
  1763.  
  1764.  strcpy(str,"Can't open ");
  1765.  strcat(str,string);
  1766.  strcat(str,"!\n");
  1767.  Quit (str);
  1768. }