ID_CA.C 42 KB

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