wolf_gfx.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708
  1. /*
  2. Copyright (C) 2004 Michael Liebscher
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. /*
  16. * wolf_gfx.c: Decode Wolfenstein3-D GFX data.
  17. *
  18. * Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
  19. * Date: 2004
  20. *
  21. * Acknowledgement:
  22. * This code was derived from Wolfenstein3-D, and was originally
  23. * written by Id Software, Inc.
  24. *
  25. */
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include "wolf_def.h"
  30. #include "../loaders/tga.h"
  31. #include "../hq2x.h"
  32. #include "../string/com_string.h"
  33. #include "../filesys/file.h"
  34. #include "../../../common/common_utils.h"
  35. #include "../../../common/arch.h"
  36. #include "../memory/memory.h"
  37. extern char gamepal[];
  38. #define FILEPOSSIZE 3
  39. #define GFXHEADFNAME "VGAHEAD"
  40. #define GFXFNAME "VGAGRAPH"
  41. #define GFXDICTFNAME "VGADICT"
  42. #define FONTWIDTH 256
  43. #define FONTHEIGHT 128
  44. typedef struct
  45. {
  46. short height;
  47. short location[ 256 ];
  48. char width[ 256 ];
  49. } fontstruct;
  50. typedef struct
  51. {
  52. // 0-255 is a character, > is a pointer to a node
  53. W16 bit0, bit1;
  54. } huffnode;
  55. typedef struct
  56. {
  57. W16 width, height;
  58. } pictabletype;
  59. pictabletype *pictable;
  60. huffnode grhuffman[ 255 ];
  61. FILE *grhandle;
  62. SW32 *grstarts; // array of offsets in vgagraph, -1 for sparse
  63. void *grsegs[ NUMCHUNKS ];
  64. /*
  65. -----------------------------------------------------------------------------
  66. Function: GRFILEPOS() -Calculate graphic file position.
  67. Parameters: chunk -[in] Chunk number to calculate file offset.
  68. Returns: File offset value or -1 for sparse tile.
  69. Notes: See 'wl6_name.h' for valid chunk numbers for SOD and WL6.
  70. grstarts must be allocated and initialized before call.
  71. Uses global variable grstarts.
  72. -----------------------------------------------------------------------------
  73. */
  74. PRIVATE SW32 GRFILEPOS( W32 c )
  75. {
  76. SW32 value;
  77. W32 offset;
  78. offset = c * 3;
  79. value = *(PW32)( ( (PW8)grstarts ) + offset );
  80. value &= 0x00ffffffl;
  81. if( value == 0xffffffl )
  82. {
  83. value = -1;
  84. }
  85. return value;
  86. };
  87. /*
  88. -----------------------------------------------------------------------------
  89. Function: CAL_GetGrChunkLength() -Calculate length of compressed graphic
  90. chunk.
  91. Parameters: chunk -[in] Chunk number to calculate file offset.
  92. Returns: The length of the compressed graphic chunk.
  93. Notes: Gets the length of an explicit length chunk (not tiles).
  94. The file pointer is positioned so the compressed data
  95. can be read in next.
  96. -----------------------------------------------------------------------------
  97. */
  98. PRIVATE SW32 CAL_GetGrChunkLength( W32 chunk )
  99. {
  100. fseek( grhandle, GRFILEPOS( chunk ) + sizeof( W32 ), SEEK_SET );
  101. return ( GRFILEPOS( chunk + 1 ) - GRFILEPOS( chunk ) - 4 );
  102. }
  103. /*
  104. -----------------------------------------------------------------------------
  105. Function: CAL_HuffExpand() -Expand compressed data.
  106. Parameters: source -[in] Pointer to compressed data.
  107. destination -[out] Pointer to hold decompressed data.
  108. length -[in] Length of expanded data.
  109. hufftable -[in] Huffman dictionary data.
  110. Returns: Nothing.
  111. Notes: Uses classic Huffman node tree (not optimized).
  112. -----------------------------------------------------------------------------
  113. */
  114. PRIVATE void CAL_HuffExpand( const W8 *source,
  115. W8 *destination,
  116. W32 length,
  117. huffnode *hufftable )
  118. {
  119. W32 bx; // node pointer
  120. W32 dx;
  121. W32 ch; // high order of CX
  122. W32 cl; // low order of CX
  123. const W8 *si; // Source Index
  124. W8 *di; // Destination Index
  125. bx = 254; // head node is always node 254
  126. si = source;
  127. di = destination;
  128. ch = *si; // load first byte
  129. si++;
  130. cl = 1;
  131. do
  132. {
  133. if( (ch & cl) & 0xff ) // bit set?
  134. dx = hufftable[ bx ].bit1; // take bit1 path from node
  135. else
  136. dx = hufftable[ bx ].bit0; // take bit0 path from node
  137. cl <<= 1; // advance to next bit position
  138. if( cl & 0x100 )
  139. {
  140. ch = *si; // load next byte
  141. si++;
  142. cl = 1; // back to first bit
  143. }
  144. if( (cl & 0x100) == 0 )
  145. {
  146. if( dx < 256 )
  147. {
  148. *di = (W8)(dx & 0xff); // write a decompressed byte out
  149. di++;
  150. bx = 254; // back to the head node for next bit
  151. length--;
  152. }
  153. else
  154. {
  155. bx = dx - 256; // next node = (huffnode *)code
  156. }
  157. }
  158. } while( length );
  159. }
  160. /*
  161. -----------------------------------------------------------------------------
  162. Function: CAL_SetupGrFile() -Initialize graphic files and arrays.
  163. Parameters: extension -[in] Pointer to a null-terminated string that
  164. specifies the file extension.
  165. (must be in '.XXX' format).
  166. Returns: 1 on success, 0 otherwise.
  167. Notes:
  168. Uses global variables grhandle and pictable.
  169. 1. Open vgadict.XXX, read huffman dictionary data.
  170. 2. Open vgahead.XXX, read data offsets.
  171. 3. Open vgagraph.XXX, read pic and sprite header, expand data.
  172. -----------------------------------------------------------------------------
  173. */
  174. PRIVATE W8 CAL_SetupGrFile( const char *extension )
  175. {
  176. void *compseg;
  177. FILE *handle;
  178. char filename[ 16 ];
  179. SW32 chunkcomplen; // chunk compressed length
  180. //
  181. // load vgadict.ext (huffman dictionary for graphics files)
  182. //
  183. cs_strlcpy( filename, GFXDICTFNAME, sizeof( filename ) );
  184. cs_strlcat( filename, extension, sizeof( filename ) );
  185. if( ( handle = fopen( cs_strupr( filename ), "rb" ) ) == NULL )
  186. {
  187. if( ( handle = fopen( cs_strlwr( filename ), "rb" ) ) == NULL )
  188. {
  189. printf( "Could not open file (%s) for read!\n", filename );
  190. return 0;
  191. }
  192. }
  193. fread( grhuffman, sizeof( grhuffman ), 1, handle );
  194. fclose( handle );
  195. //
  196. // Open then load the data offsets from vgahead.ext
  197. //
  198. cs_strlcpy( filename, GFXHEADFNAME, sizeof( filename ) );
  199. cs_strlcat( filename, extension, sizeof( filename ) );
  200. if( (handle = fopen( cs_strupr( filename ), "rb" )) == NULL )
  201. {
  202. if( (handle = fopen( cs_strlwr( filename ), "rb" )) == NULL )
  203. {
  204. printf( "Could not open file (%s) for read!\n", filename );
  205. return 0;
  206. }
  207. }
  208. grstarts = MM_MALLOC( (NUMCHUNKS+1) * FILEPOSSIZE );
  209. if( grstarts == NULL )
  210. {
  211. return 0;
  212. }
  213. fread( grstarts, sizeof( long ), (NUMCHUNKS+1) * FILEPOSSIZE, handle );
  214. fclose( handle );
  215. //
  216. // Open the graphics file 'vgagraph.XXX'.
  217. //
  218. cs_strlcpy( filename, GFXFNAME, sizeof( filename ) );
  219. cs_strlcat( filename, extension, sizeof( filename ) );
  220. if( ( grhandle = fopen( cs_strupr( filename ), "rb" ) ) == NULL )
  221. {
  222. if( ( grhandle = fopen( cs_strlwr( filename ), "rb" ) ) == NULL )
  223. {
  224. printf( "Could not open file (%s) for read!\n", filename );
  225. return 0;
  226. }
  227. }
  228. //
  229. // load the pic and sprite headers into the arrays.
  230. //
  231. pictable = MM_MALLOC( NUMPICS * sizeof( pictabletype ) );
  232. if( pictable == NULL )
  233. {
  234. return 0;
  235. }
  236. chunkcomplen = CAL_GetGrChunkLength( STRUCTPIC ); // position file pointer
  237. compseg = MM_MALLOC( chunkcomplen );
  238. if( compseg == NULL )
  239. {
  240. return 0;
  241. }
  242. fread( compseg, chunkcomplen, 1, grhandle );
  243. CAL_HuffExpand( compseg, (PW8)pictable,
  244. NUMPICS * sizeof( pictabletype ),
  245. grhuffman );
  246. MM_FREE( compseg );
  247. return 1;
  248. }
  249. /*
  250. -----------------------------------------------------------------------------
  251. Function: CAL_Shutdown() -Shutdown module.
  252. Parameters: Nothing.
  253. Returns: Nothing.
  254. Notes: Frees grstarts, pictable and grsegs data. Closes grhandle file handle.
  255. -----------------------------------------------------------------------------
  256. */
  257. PUBLIC void CAL_Shutdown( void )
  258. {
  259. W32 i;
  260. if( grstarts )
  261. {
  262. MM_FREE( grstarts );
  263. }
  264. if( pictable )
  265. {
  266. MM_FREE( pictable );
  267. }
  268. if( grhandle )
  269. {
  270. fclose( grhandle );
  271. }
  272. for( i = 0; i < NUMCHUNKS; ++i )
  273. {
  274. if( grsegs[ i ] )
  275. {
  276. MM_FREE( grsegs[ i ] );
  277. }
  278. }
  279. }
  280. /*
  281. -----------------------------------------------------------------------------
  282. Function: CAL_ExpandGrChunk() -Expand compressed graphic chunk.
  283. Parameters: chunk -[in] Chunk number to expand.
  284. source -[in] Pointer to compressed data.
  285. version -[in] extension version.
  286. 1 -WL6
  287. 2 -SOD
  288. Returns: Nothing.
  289. Notes:
  290. -----------------------------------------------------------------------------
  291. */
  292. PRIVATE void CAL_ExpandGrChunk( W32 chunk, const W8 *source, W16 version )
  293. {
  294. W32 expanded;
  295. W16 offset = 0;
  296. if( version & SOD_PAK )
  297. offset = SOD_STARTDIFF;
  298. if( chunk >= ( STARTTILE8 + offset ) &&
  299. chunk < ( STARTEXTERNS + offset ) )
  300. {
  301. //
  302. // expanded sizes of tile8/16/32 are implicit
  303. //
  304. #define BLOCK 64
  305. #define MASKBLOCK 128
  306. if( chunk < (STARTTILE8M + offset) ) // tile 8s are all in one chunk!
  307. expanded = BLOCK * NUMTILE8;
  308. else if( chunk < (STARTTILE16 + offset) )
  309. expanded = MASKBLOCK * NUMTILE8M;
  310. else if( chunk < (STARTTILE16M + offset) ) // all other tiles are one/chunk
  311. expanded = BLOCK << 2;
  312. else if( chunk < (STARTTILE32 + offset) )
  313. expanded = MASKBLOCK << 2;
  314. else if( chunk < (STARTTILE32M + offset) )
  315. expanded = BLOCK << 4;
  316. else
  317. expanded = MASKBLOCK << 4;
  318. }
  319. else
  320. {
  321. //
  322. // everything else has an explicit size longword
  323. //
  324. expanded = *(PW32)source;
  325. source += 4; // skip over length
  326. }
  327. //
  328. // allocate final space and decompress it.
  329. // Sprites need to have shifts made and various other junk.
  330. //
  331. grsegs[ chunk ] = MM_MALLOC( expanded );
  332. if( grsegs[ chunk ] == NULL )
  333. {
  334. return;
  335. }
  336. CAL_HuffExpand( source, grsegs[ chunk ], expanded, grhuffman );
  337. }
  338. /*
  339. -----------------------------------------------------------------------------
  340. Function: CA_CacheGrChunk() -Cache graphic chunk.
  341. Parameters: chunk -[in] Chunk number to cache.
  342. version -[in] extension version.
  343. 1 -WL6
  344. 2 -SOD
  345. Returns: Nothing.
  346. Notes: Makes sure a given chunk is in memory, loading it if needed.
  347. -----------------------------------------------------------------------------
  348. */
  349. PRIVATE void CA_CacheGrChunk( W32 chunk, W16 version )
  350. {
  351. SW32 pos;
  352. W32 compressed;
  353. void *buffer;
  354. W32 next;
  355. if( grsegs[ chunk ] )
  356. {
  357. return; // already in memory
  358. }
  359. //
  360. // load the chunk into a buffer
  361. //
  362. pos = GRFILEPOS( chunk );
  363. if( pos < 0 ) // $FFFFFFFF start is a sparse tile
  364. {
  365. return;
  366. }
  367. next = chunk + 1;
  368. while( GRFILEPOS( next ) == -1 ) // skip past any sparse tiles
  369. {
  370. next++;
  371. }
  372. compressed = GRFILEPOS( next ) - pos;
  373. fseek( grhandle, pos, SEEK_SET );
  374. buffer = MM_MALLOC( compressed );
  375. if( buffer == NULL )
  376. {
  377. return;
  378. }
  379. fread( buffer, 1, compressed, grhandle );
  380. CAL_ExpandGrChunk( chunk, buffer, version );
  381. MM_FREE( buffer );
  382. }
  383. /*
  384. -----------------------------------------------------------------------------
  385. Function: RGB32toRGB24() -Convert image from 32bits to 24bits.
  386. Parameters: src -[in] Buffer to convert from.
  387. dest -[in/out] Buffer to convert to.
  388. size -[in] Size of src buffer.
  389. Returns: Nothing.
  390. Notes: src and dest can point to the same memory block.
  391. -----------------------------------------------------------------------------
  392. */
  393. PUBLIC void RGB32toRGB24( const W8 *src, W8 *dest, size_t size )
  394. {
  395. size_t i;
  396. size_t npixels = size >> 2;
  397. for( i = 0 ; i < npixels ; ++i )
  398. {
  399. dest[ i * 3 + 0 ] = src[ i * 4 + 0 ];
  400. dest[ i * 3 + 1 ] = src[ i * 4 + 1 ];
  401. dest[ i * 3 + 2 ] = src[ i * 4 + 2 ];
  402. }
  403. }
  404. /*
  405. -----------------------------------------------------------------------------
  406. Function: MergePics() -Merge image inside another image.
  407. Parameters: src -[in] Source image to copy from.
  408. dest -[in] Destination image to copy to.
  409. width -[in] Width of source image.
  410. height -[in] Height of source image.
  411. bpp -[in] Bytes per pixel of images.
  412. totalwidth -[in] -Total width (in pixels) of destination image.
  413. x_offset -[in] X offset (in pixels) in destination image.
  414. y_offset -[in] Y offset (in pixels) in destination image.
  415. Returns: Nothing.
  416. Notes:
  417. -----------------------------------------------------------------------------
  418. */
  419. PRIVATE void MergePics( const W8 *src, W8 *dest, W16 width, W16 height, W16 bpp, W16 totalwidth,
  420. W32 x_offset,
  421. W32 y_offset )
  422. {
  423. W16 x, y;
  424. W8 *dptr;
  425. dptr = dest + (y_offset * totalwidth * bpp) + (x_offset * bpp);
  426. for( y = 0 ; y < height ; ++y )
  427. {
  428. for( x = 0 ; x < width ; ++x )
  429. {
  430. dptr[ 0 ] = src[ 0 ];
  431. dptr[ 1 ] = src[ 1 ];
  432. src += bpp;
  433. dptr += bpp;
  434. }
  435. dptr += (totalwidth * bpp) - width * bpp;
  436. }
  437. }
  438. PRIVATE void MergeImages( W8 *src, W16 src_bpp, W16 src_totalwidth, W16 src_region_width, W16 src_region_height, W32 src_x_offset, W32 src_y_offset,
  439. W8 *dest, W16 dest_bpp, W16 dest_totalwidth, W16 dest_region_width, W16 dest_region_height, W32 dest_x_offset, W32 dest_y_offset )
  440. {
  441. W16 x, y;
  442. W8 *dptr;
  443. W8 *sptr;
  444. dptr = dest + (dest_y_offset * dest_totalwidth * dest_bpp) + (dest_x_offset * dest_bpp);
  445. sptr = src + (src_y_offset * src_totalwidth * src_bpp) + (src_x_offset * src_bpp);
  446. for( y = 0 ; y < src_region_height ; ++y )
  447. {
  448. for( x = 0 ; x < src_region_width ; ++x )
  449. {
  450. dptr[ 0 ] = sptr[ 0 ];
  451. dptr[ 1 ] = sptr[ 1 ];
  452. sptr += src_bpp;
  453. dptr += dest_bpp;
  454. }
  455. dptr += (dest_totalwidth * dest_bpp) - dest_region_width * dest_bpp;
  456. sptr += (src_totalwidth * src_bpp) - src_region_width * src_bpp;
  457. }
  458. }
  459. /*
  460. -----------------------------------------------------------------------------
  461. Function: SavePic() -Save graphic lump in targa image format.
  462. Parameters: chunk -[in] Chunk number to save.
  463. version -[in] extension version.
  464. 1 -WL6
  465. 2 -SOD
  466. Returns: Nothing.
  467. Notes:
  468. -----------------------------------------------------------------------------
  469. */
  470. PRIVATE void SavePic( W32 chunknum, W16 version, W8 *buffer, W8 *buffer2 )
  471. {
  472. W16 i;
  473. W16 temp;
  474. char filename[32];
  475. char *fname;
  476. W8 *ptr;
  477. W8 *pic;
  478. W32 picnum;
  479. W16 width, height;
  480. W16 linewidth, plane, sx, sy;
  481. W8 r,g,b;
  482. W16 rgb;
  483. W8 *tpalette = gamepal;
  484. static W16 offset = 0;
  485. if( ( (chunknum == WL1_N_BLANKPIC ||
  486. chunknum == WL1_NOKEYPIC ) && (version & WL1_PAK) ) )
  487. {
  488. return;
  489. }
  490. if( ( (chunknum == N_BLANKPIC ||
  491. chunknum == NOKEYPIC ) && (version & WL6_PAK) ) )
  492. {
  493. return;
  494. }
  495. if( ( (chunknum == SDM_N_BLANKPIC ||
  496. chunknum == SDM_NOKEYPIC ) && (version & SDM_PAK) ) )
  497. {
  498. return;
  499. }
  500. if( ( (chunknum == SOD_N_BLANKPIC ||
  501. chunknum == SOD_NOKEYPIC ) && (version & SOD_PAK) ) )
  502. {
  503. return;
  504. }
  505. // Spear used multiple palettes, so
  506. // pull out the one we need.
  507. if( version & SDM_PAK )
  508. {
  509. switch( chunknum )
  510. {
  511. case SDM_TITLE1PIC:
  512. case SDM_TITLE2PIC:
  513. CA_CacheGrChunk( SDM_TITLEPALETTE, version );
  514. tpalette = grsegs[ SDM_TITLEPALETTE ];
  515. break;
  516. default:
  517. tpalette = gamepal;
  518. break;
  519. }
  520. }
  521. if( version & SOD_PAK )
  522. {
  523. switch( chunknum )
  524. {
  525. case SOD_IDGUYS1PIC:
  526. case SOD_IDGUYS2PIC:
  527. CA_CacheGrChunk( SOD_IDGUYSPALETTE, version );
  528. tpalette = grsegs[ SOD_IDGUYSPALETTE ];
  529. break;
  530. case SOD_TITLE1PIC:
  531. case SOD_TITLE2PIC:
  532. CA_CacheGrChunk( SOD_TITLEPALETTE, version );
  533. tpalette = grsegs[ SOD_TITLEPALETTE ];
  534. break;
  535. case SOD_ENDSCREEN11PIC:
  536. CA_CacheGrChunk( SOD_END1PALETTE, version );
  537. tpalette = grsegs[ SOD_END1PALETTE ];
  538. break;
  539. case SOD_ENDSCREEN12PIC:
  540. CA_CacheGrChunk( SOD_END2PALETTE, version );
  541. tpalette = grsegs[ SOD_END2PALETTE ];
  542. break;
  543. case SOD_ENDSCREEN3PIC:
  544. CA_CacheGrChunk( SOD_END3PALETTE, version );
  545. tpalette = grsegs[ SOD_END3PALETTE ];
  546. break;
  547. case SOD_ENDSCREEN4PIC:
  548. CA_CacheGrChunk( SOD_END4PALETTE, version );
  549. tpalette = grsegs[ SOD_END4PALETTE ];
  550. break;
  551. case SOD_ENDSCREEN5PIC:
  552. CA_CacheGrChunk( SOD_END5PALETTE, version );
  553. tpalette = grsegs[ SOD_END5PALETTE ];
  554. break;
  555. case SOD_ENDSCREEN6PIC:
  556. CA_CacheGrChunk( SOD_END6PALETTE, version );
  557. tpalette = grsegs[ SOD_END6PALETTE ];
  558. break;
  559. case SOD_ENDSCREEN7PIC:
  560. CA_CacheGrChunk( SOD_END7PALETTE, version );
  561. tpalette = grsegs[ SOD_END7PALETTE ];
  562. break;
  563. case SOD_ENDSCREEN8PIC:
  564. CA_CacheGrChunk( SOD_END8PALETTE, version );
  565. tpalette = grsegs[ SOD_END8PALETTE ];
  566. break;
  567. case SOD_ENDSCREEN9PIC:
  568. CA_CacheGrChunk( SOD_END9PALETTE, version );
  569. tpalette = grsegs[ SOD_END9PALETTE ];
  570. break;
  571. default:
  572. tpalette = gamepal;
  573. break;
  574. } // End switch chunknum
  575. } // End if version & SOD_PAK
  576. STATUSBARHACK:
  577. picnum = chunknum - STARTPICS;
  578. pic = grsegs[ chunknum ];
  579. width = pictable[ picnum ].width;
  580. height= pictable[ picnum ].height;
  581. linewidth = width / 4;
  582. for( i = 0; i < ( width * height ); ++i, pic++ )
  583. {
  584. plane = i / ( (width * height) / 4 );
  585. sx = ( ( i % ( linewidth ) ) * 4 ) + plane;
  586. sy = ( ( i / linewidth ) % height );
  587. ptr = buffer + ( (sx*2) + (sy * width)*2);
  588. temp = (*pic) * 3;
  589. r = tpalette[ temp ] >> 1;
  590. g = tpalette[ temp+1 ];
  591. b = tpalette[ temp+2 ] >> 1;
  592. rgb = (b << 11) | (g << 5) | r;
  593. ptr[ 0 ] = rgb & 0xff;
  594. ptr[ 1 ] = rgb >> 8;
  595. }
  596. //
  597. // Hacks to reassemble images
  598. //
  599. if( version & WL1_PAK )
  600. {
  601. if( chunknum == WL1_STATUSBARPIC )
  602. {
  603. memcpy( buffer2, buffer, width * height * 2 ); // Save Status bar pic
  604. CA_CacheGrChunk( WL1_NOKEYPIC, version ); // cache NOKEYPIC
  605. chunknum = WL1_NOKEYPIC;
  606. goto STATUSBARHACK;
  607. }
  608. else if( chunknum == WL1_H_BOTTOMINFOPIC )
  609. {
  610. MergeImages( buffer, 2, 304, 91, 16, 24, 4,
  611. buffer2, 2, 91, 91, 16, 0, 0 );
  612. MergeImages( buffer, 2, 304, 91, 16, 192, 4,
  613. buffer2, 2, 91, 91, 16, 0, 16 );
  614. hq2x_32( buffer2, buffer, 91, 16, (91*2)*4 );
  615. RGB32toRGB24( buffer, buffer, 182*32*4 );
  616. cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, "PLAQUE_PAGE" );
  617. WriteTGA( filename, 24, 182, 32, buffer, 0, 0 );
  618. hq2x_32( buffer2 + (16 * 91 * 2), buffer, 91, 16, (91*2)*4 );
  619. RGB32toRGB24( buffer, buffer, 182*32*4 );
  620. cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, "PLAQUE_BLANK" );
  621. WriteTGA( filename, 24, 182, 32, buffer, 0, 1 );
  622. return;
  623. }
  624. else if( chunknum == WL1_NOKEYPIC )
  625. {
  626. chunknum = WL1_STATUSBARPIC;
  627. MergePics( buffer, buffer2, width, height, 2, 320, 240, 4 );
  628. MergePics( buffer, buffer2, width, height, 2, 320, 240, 4+height );
  629. memcpy( buffer, buffer2, 320 * 40 * 2 );
  630. width = 320;
  631. height = 40;
  632. }
  633. else if( chunknum == WL1_L_COLONPIC )
  634. {
  635. memset( buffer2, 0, 256*64*2 );
  636. MergePics( buffer, buffer2, width, height, 2, 256, 160, 16 );
  637. return;
  638. }
  639. else if( chunknum == WL1_L_EXPOINTPIC )
  640. {
  641. MergePics( buffer, buffer2, width, height, 2, 256, 16, 0 );
  642. return;
  643. }
  644. else if( chunknum == WL1_L_APOSTROPHEPIC )
  645. {
  646. W16 i;
  647. MergePics( buffer, buffer2, width, height, 2, 256, 112, 0 );
  648. memcpy( buffer, buffer2, 256 * 64 * 2 );
  649. for( i = 0 ; i < 256 * 64 * 2 ; i += 2 )
  650. {
  651. if( buffer[ i ] == 0 && buffer[ i + 1 ] == 0 )
  652. {
  653. buffer[ i + 1 ] = 66;
  654. }
  655. }
  656. offset = 0;
  657. width = 256;
  658. height = 64;
  659. }
  660. else if( chunknum == WL1_L_PERCENTPIC )
  661. {
  662. offset = 16; // this is for L_APIC...
  663. MergePics( buffer, buffer2, width, height, 2, 256, 80, 0 );
  664. return;
  665. }
  666. else if( chunknum >= WL1_L_NUM0PIC && chunknum <= WL1_L_NUM9PIC )
  667. {
  668. MergePics( buffer, buffer2, width, height, 2, 256, offset, 16 );
  669. offset += width;
  670. return;
  671. }
  672. else if( chunknum >= WL1_N_0PIC && chunknum < WL1_N_9PIC )
  673. {
  674. MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
  675. offset += width + 1;
  676. return;
  677. }
  678. else if( chunknum == WL1_N_9PIC )
  679. {
  680. W32 i;
  681. MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
  682. memcpy( buffer, buffer2, 90 * height * 2 );
  683. for( i = 0 ; i < 90 * 16 * 2 ; i += 2 )
  684. {
  685. if( ! (i % 9) && i != 0 )
  686. {
  687. buffer[ i - 2 ] = 0;
  688. buffer[ i - 1 ] = 160;
  689. }
  690. }
  691. width = 90;
  692. offset = 0;
  693. }
  694. else if( chunknum >= WL1_L_APIC && chunknum <= WL1_L_ZPIC )
  695. {
  696. static W32 yoffset = 32;
  697. MergePics( buffer, buffer2, width, height, 2, 256, offset, yoffset );
  698. offset += width;
  699. if( offset >= 256 )
  700. {
  701. offset = 0;
  702. yoffset += 16;
  703. }
  704. return;
  705. }
  706. else if( chunknum == WL1_FACE5CPIC )
  707. {
  708. // hmmm... Why is this one messed up?
  709. MergeImages( buffer, 2, 24, 18, height-2, 8, 2,
  710. buffer2, 2, 24, 18, height-2, 0, 0 );
  711. MergeImages( buffer, 2, 24, 8, height-3, 0, 3,
  712. buffer2, 2, 24, 8, height-2, 16, 0 );
  713. MergeImages( buffer, 2, 24, 18, 2, 9, 0,
  714. buffer2, 2, 24, 18, 2, 0, height-2 );
  715. MergeImages( buffer, 2, 24, 7, 3, 1, 0,
  716. buffer2, 2, 24, 7, 3, 16, height-3 );
  717. memcpy( buffer, buffer2, 24 * 32 * 2 );
  718. buffer[ (30 * 24 * 2) + (3 * 2) ] = 73;
  719. buffer[ (30 * 24 * 2) + (3 * 2) + 1 ] = 74;
  720. buffer[ (31 * 24 * 2) + (3 * 2) ] = 73;
  721. buffer[ (31 * 24 * 2) + (3 * 2) + 1 ] = 74;
  722. buffer[ (29 * 24 * 2) + (23 * 2) ] = 73;
  723. buffer[ (29 * 24 * 2) + (23 * 2) + 1 ] = 74;
  724. buffer[ (30 * 24 * 2) + (23 * 2) ] = 73;
  725. buffer[ (30 * 24 * 2) + (23 * 2) + 1 ] = 74;
  726. buffer[ (31 * 24 * 2) + (23 * 2) ] = 73;
  727. buffer[ (31 * 24 * 2) + (23 * 2) + 1 ] = 74;
  728. buffer[ (29 * 24 * 2) + (19 * 2) ] = 255;
  729. buffer[ (29 * 24 * 2) + (19 * 2) + 1 ] = 100;
  730. buffer[ (30 * 24 * 2) + (19 * 2) ] = 63;
  731. buffer[ (30 * 24 * 2) + (19 * 2) + 1 ] = 117;
  732. buffer[ (31 * 24 * 2) + (19 * 2) ] = 52;
  733. buffer[ (31 * 24 * 2) + (19 * 2) + 1 ] = 59;
  734. buffer[ (30 * 24 * 2) + (7 * 2) ] = 19;
  735. buffer[ (30 * 24 * 2) + (7 * 2) + 1 ] = 59;
  736. buffer[ (31 * 24 * 2) + (7 * 2) ] = 19;
  737. buffer[ (31 * 24 * 2) + (7 * 2) + 1 ] = 59;
  738. buffer[ (30 * 24 * 2) + (11 * 2) ] = 91;
  739. buffer[ (30 * 24 * 2) + (11 * 2) + 1 ] = 84;
  740. buffer[ (31 * 24 * 2) + (11 * 2) ] = 190;
  741. buffer[ (31 * 24 * 2) + (11 * 2) + 1 ] = 92;
  742. buffer[ (30 * 24 * 2) + (15 * 2) ] = 249;
  743. buffer[ (30 * 24 * 2) + (15 * 2) + 1 ] = 75;
  744. buffer[ (31 * 24 * 2) + (15 * 2) ] = 190;
  745. buffer[ (31 * 24 * 2) + (15 * 2) + 1 ] = 92;
  746. }
  747. }
  748. else if( version & WL6_PAK )
  749. {
  750. if( chunknum == STATUSBARPIC )
  751. {
  752. memcpy( buffer2, buffer, width * height * 2 ); // Save Status bar pic
  753. CA_CacheGrChunk( NOKEYPIC, version ); // cache NOKEYPIC
  754. chunknum = NOKEYPIC;
  755. goto STATUSBARHACK;
  756. }
  757. else if( chunknum == H_BOTTOMINFOPIC )
  758. {
  759. MergeImages( buffer, 2, 304, 91, 16, 24, 4,
  760. buffer2, 2, 91, 91, 16, 0, 0 );
  761. MergeImages( buffer, 2, 304, 91, 16, 192, 4,
  762. buffer2, 2, 91, 91, 16, 0, 16 );
  763. hq2x_32( buffer2, buffer, 91, 16, (91*2)*4 );
  764. RGB32toRGB24( buffer, buffer, 182*32*4 );
  765. cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, "PLAQUE_PAGE" );
  766. WriteTGA( filename, 24, 182, 32, buffer, 0, 0 );
  767. hq2x_32( buffer2 + (16 * 91 * 2), buffer, 91, 16, (91*2)*4 );
  768. RGB32toRGB24( buffer, buffer, 182*32*4 );
  769. cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, "PLAQUE_BLANK" );
  770. WriteTGA( filename, 24, 182, 32, buffer, 0, 1 );
  771. return;
  772. }
  773. else if( chunknum == NOKEYPIC )
  774. {
  775. chunknum = STATUSBARPIC;
  776. MergePics( buffer, buffer2, width, height, 2, 320, 240, 4 );
  777. MergePics( buffer, buffer2, width, height, 2, 320, 240, 4+height );
  778. memcpy( buffer, buffer2, 320 * 40 * 2 );
  779. width = 320;
  780. height = 40;
  781. }
  782. else if( chunknum == L_COLONPIC )
  783. {
  784. memset( buffer2, 0, 256*64*2 );
  785. MergePics( buffer, buffer2, width, height, 2, 256, 160, 16 );
  786. return;
  787. }
  788. else if( chunknum == L_EXPOINTPIC )
  789. {
  790. MergePics( buffer, buffer2, width, height, 2, 256, 16, 0 );
  791. return;
  792. }
  793. else if( chunknum == L_APOSTROPHEPIC )
  794. {
  795. W16 i;
  796. MergePics( buffer, buffer2, width, height, 2, 256, 112, 0 );
  797. memcpy( buffer, buffer2, 256 * 64 * 2 );
  798. for( i = 0 ; i < 256 * 64 * 2 ; i += 2 )
  799. {
  800. if( buffer[ i ] == 0 && buffer[ i + 1 ] == 0 )
  801. {
  802. buffer[ i + 1 ] = 66;
  803. }
  804. }
  805. offset = 0;
  806. width = 256;
  807. height = 64;
  808. }
  809. else if( chunknum == L_PERCENTPIC )
  810. {
  811. offset = 16; // this is for L_APIC...
  812. MergePics( buffer, buffer2, width, height, 2, 256, 80, 0 );
  813. return;
  814. }
  815. else if( chunknum >= L_NUM0PIC && chunknum <= L_NUM9PIC )
  816. {
  817. MergePics( buffer, buffer2, width, height, 2, 256, offset, 16 );
  818. offset += width;
  819. return;
  820. }
  821. else if( chunknum >= N_0PIC && chunknum < N_9PIC )
  822. {
  823. MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
  824. offset += width + 1;
  825. return;
  826. }
  827. else if( chunknum == N_9PIC )
  828. {
  829. W32 i;
  830. MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
  831. memcpy( buffer, buffer2, 90 * height * 2 );
  832. for( i = 0 ; i < 90 * 16 * 2 ; i += 2 )
  833. {
  834. if( ! (i % 9) && i != 0 )
  835. {
  836. buffer[ i - 2 ] = 0;
  837. buffer[ i - 1 ] = 160;
  838. }
  839. }
  840. width = 90;
  841. offset = 0;
  842. }
  843. else if( chunknum >= L_APIC && chunknum <= L_ZPIC )
  844. {
  845. static W32 yoffset = 32;
  846. MergePics( buffer, buffer2, width, height, 2, 256, offset, yoffset );
  847. offset += width;
  848. if( offset >= 256 )
  849. {
  850. offset = 0;
  851. yoffset += 16;
  852. }
  853. return;
  854. }
  855. }
  856. else if( version & SDM_PAK )
  857. {
  858. if( chunknum == SDM_STATUSBARPIC )
  859. {
  860. memcpy( buffer2, buffer, width * height * 2 ); // Save Status bar pic
  861. CA_CacheGrChunk( SDM_NOKEYPIC, version ); // cache SOD_NOKEYPIC
  862. chunknum = SDM_NOKEYPIC;
  863. goto STATUSBARHACK;
  864. }
  865. else if( chunknum == SDM_NOKEYPIC )
  866. {
  867. chunknum = SDM_STATUSBARPIC;
  868. MergePics( buffer, buffer2, width, height, 2, 320, 240, 4 );
  869. MergePics( buffer, buffer2, width, height, 2, 320, 240, 4+height );
  870. memcpy( buffer, buffer2, 320 * 40 * 2 );
  871. width = 320;
  872. height = 40;
  873. }
  874. else if( chunknum == SDM_L_COLONPIC )
  875. {
  876. memset( buffer2, 0, 256*64*2 );
  877. MergePics( buffer, buffer2, width, height, 2, 256, 160, 16 );
  878. return;
  879. }
  880. else if( chunknum == SDM_L_EXPOINTPIC )
  881. {
  882. MergePics( buffer, buffer2, width, height, 2, 256, 16, 0 );
  883. return;
  884. }
  885. else if( chunknum == SDM_L_APOSTROPHEPIC )
  886. {
  887. W16 i;
  888. MergePics( buffer, buffer2, width, height, 2, 256, 112, 0 );
  889. memcpy( buffer, buffer2, 256 * 64 * 2 );
  890. for( i = 0 ; i < 256 * 64 * 2 ; i += 2 )
  891. {
  892. if( buffer[ i ] == 0 && buffer[ i + 1 ] == 0 )
  893. {
  894. buffer[ i + 1 ] = 66;
  895. }
  896. }
  897. offset = 0;
  898. width = 256;
  899. height = 64;
  900. }
  901. else if( chunknum == SDM_L_PERCENTPIC )
  902. {
  903. offset = 16; // this is for L_APIC...
  904. MergePics( buffer, buffer2, width, height, 2, 256, 80, 0 );
  905. return;
  906. }
  907. else if( chunknum >= SDM_L_NUM0PIC && chunknum <= SDM_L_NUM9PIC )
  908. {
  909. MergePics( buffer, buffer2, width, height, 2, 256, offset, 16 );
  910. offset += width;
  911. return;
  912. }
  913. else if( chunknum >= SDM_N_0PIC && chunknum < SDM_N_9PIC )
  914. {
  915. MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
  916. offset += width + 1;
  917. return;
  918. }
  919. else if( chunknum == SDM_N_9PIC )
  920. {
  921. W32 i;
  922. MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
  923. memcpy( buffer, buffer2, 90 * height * 2 );
  924. for( i = 0 ; i < 90 * 16 * 2 ; i += 2 )
  925. {
  926. if( ! (i % 9) && i != 0 )
  927. {
  928. buffer[ i - 2 ] = 0;
  929. buffer[ i - 1 ] = 160;
  930. }
  931. }
  932. width = 90;
  933. offset = 0;
  934. }
  935. else if( chunknum >= SDM_L_APIC && chunknum <= SDM_L_ZPIC )
  936. {
  937. static W32 yoffset = 32;
  938. MergePics( buffer, buffer2, width, height, 2, 256, offset, yoffset );
  939. offset += width;
  940. if( offset >= 256 )
  941. {
  942. offset = 0;
  943. yoffset += 16;
  944. }
  945. return;
  946. }
  947. else if( chunknum == SDM_TITLE1PIC )
  948. {
  949. memcpy( buffer2+offset, buffer, (width*height*2) );
  950. offset += width*height*2;
  951. return;
  952. }
  953. else if( chunknum == SDM_TITLE2PIC )
  954. {
  955. memcpy( buffer2+offset, buffer, (width*height*2) );
  956. memcpy( buffer, buffer2, 320*200*2 );
  957. height = 200;
  958. offset = 0;
  959. }
  960. }
  961. else if( version & SOD_PAK )
  962. {
  963. if( chunknum == SOD_STATUSBARPIC )
  964. {
  965. memcpy( buffer2, buffer, width * height * 2 ); // Save Status bar pic
  966. CA_CacheGrChunk( SOD_NOKEYPIC, version ); // cache SOD_NOKEYPIC
  967. chunknum = SOD_NOKEYPIC;
  968. goto STATUSBARHACK;
  969. }
  970. else if( chunknum == SOD_NOKEYPIC )
  971. {
  972. chunknum = SOD_STATUSBARPIC;
  973. MergePics( buffer, buffer2, width, height, 2, 320, 240, 4 );
  974. MergePics( buffer, buffer2, width, height, 2, 320, 240, 4+height );
  975. memcpy( buffer, buffer2, 320 * 40 * 2 );
  976. width = 320;
  977. height = 40;
  978. }
  979. else if( chunknum == SOD_L_COLONPIC )
  980. {
  981. memset( buffer2, 0, 256*64*2 );
  982. MergePics( buffer, buffer2, width, height, 2, 256, 160, 16 );
  983. return;
  984. }
  985. else if( chunknum == SOD_L_EXPOINTPIC )
  986. {
  987. MergePics( buffer, buffer2, width, height, 2, 256, 16, 0 );
  988. return;
  989. }
  990. else if( chunknum == SOD_L_APOSTROPHEPIC )
  991. {
  992. W16 i;
  993. MergePics( buffer, buffer2, width, height, 2, 256, 112, 0 );
  994. memcpy( buffer, buffer2, 256 * 64 * 2 );
  995. for( i = 0 ; i < 256 * 64 * 2 ; i += 2 )
  996. {
  997. if( buffer[ i ] == 0 && buffer[ i + 1 ] == 0 )
  998. {
  999. buffer[ i + 1 ] = 66;
  1000. }
  1001. }
  1002. offset = 0;
  1003. width = 256;
  1004. height = 64;
  1005. }
  1006. else if( chunknum == SOD_L_PERCENTPIC )
  1007. {
  1008. offset = 16; // this is for L_APIC...
  1009. MergePics( buffer, buffer2, width, height, 2, 256, 80, 0 );
  1010. return;
  1011. }
  1012. else if( chunknum >= SOD_L_NUM0PIC && chunknum <= SOD_L_NUM9PIC )
  1013. {
  1014. MergePics( buffer, buffer2, width, height, 2, 256, offset, 16 );
  1015. offset += width;
  1016. return;
  1017. }
  1018. else if( chunknum >= SOD_N_0PIC && chunknum < SOD_N_9PIC )
  1019. {
  1020. MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
  1021. offset += width + 1;
  1022. return;
  1023. }
  1024. else if( chunknum == SOD_N_9PIC )
  1025. {
  1026. W32 i;
  1027. MergePics( buffer, buffer2, width, height, 2, 90, offset, 0 );
  1028. memcpy( buffer, buffer2, 90 * height * 2 );
  1029. for( i = 0 ; i < 90 * 16 * 2 ; i += 2 )
  1030. {
  1031. if( ! (i % 9) && i != 0 )
  1032. {
  1033. buffer[ i - 2 ] = 0;
  1034. buffer[ i - 1 ] = 160;
  1035. }
  1036. }
  1037. width = 90;
  1038. offset = 0;
  1039. }
  1040. else if( chunknum >= SOD_L_APIC && chunknum <= SOD_L_ZPIC )
  1041. {
  1042. static W32 yoffset = 32;
  1043. MergePics( buffer, buffer2, width, height, 2, 256, offset, yoffset );
  1044. offset += width;
  1045. if( offset >= 256 )
  1046. {
  1047. offset = 0;
  1048. yoffset += 16;
  1049. }
  1050. return;
  1051. }
  1052. else if( chunknum == SOD_IDGUYS1PIC )
  1053. {
  1054. memcpy( buffer2+offset, buffer, (width*height*2) );
  1055. offset += width*height*2;
  1056. return;
  1057. }
  1058. else if( chunknum == SOD_IDGUYS2PIC )
  1059. {
  1060. memcpy( buffer2+offset, buffer, (width*height*2) );
  1061. memcpy( buffer, buffer2, 320*200*2 );
  1062. height = 200;
  1063. offset = 0;
  1064. }
  1065. else if( chunknum == SOD_TITLE1PIC )
  1066. {
  1067. memcpy( buffer2+offset, buffer, (width*height*2) );
  1068. offset += width*height*2;
  1069. return;
  1070. }
  1071. else if( chunknum == SOD_TITLE2PIC )
  1072. {
  1073. memcpy( buffer2+offset, buffer, (width*height*2) );
  1074. memcpy( buffer, buffer2, 320*200*2 );
  1075. height = 200;
  1076. offset = 0;
  1077. }
  1078. }
  1079. //
  1080. // End of images hacks
  1081. //
  1082. if( version & WL1_PAK )
  1083. {
  1084. fname = GetLumpFileName_WL1( chunknum );
  1085. }
  1086. else if( version & WL6_PAK )
  1087. {
  1088. fname = GetLumpFileName_WL6( chunknum );
  1089. }
  1090. else if( version & SDM_PAK )
  1091. {
  1092. fname = GetLumpFileName_SDM( chunknum );
  1093. }
  1094. else if( version & SOD_PAK )
  1095. {
  1096. fname = GetLumpFileName_SOD( chunknum );
  1097. }
  1098. else
  1099. {
  1100. printf( "Unknown file extension!\n" );
  1101. return;
  1102. }
  1103. if( fname == NULL )
  1104. {
  1105. printf( "File name not found for item: (%d)\n", chunknum );
  1106. return;
  1107. }
  1108. cs_snprintf( filename, sizeof( filename ), "%s/%s.tga", LGFXDIR, fname );
  1109. hq2x_32( buffer, buffer2, width, height, (width*2)*4 );
  1110. // Get rid of alpha channel
  1111. RGB32toRGB24( buffer2, buffer2, (width*2)*(height*2)*4 );
  1112. WriteTGA( filename, 24, (width*2), (height*2), buffer2, 0, 1 );
  1113. return;
  1114. }
  1115. /*
  1116. -----------------------------------------------------------------------------
  1117. Function: Fontline() -Extract and save font.
  1118. Parameters: fontnumber -[in] font to save.
  1119. version -[in] extension version.
  1120. 1 -WL6
  1121. 2 -SOD
  1122. Returns: Nothing.
  1123. Notes: Font must be cached in grsegs[] before calling.
  1124. -----------------------------------------------------------------------------
  1125. */
  1126. PRIVATE void Fontline( W32 fontnumber, W16 version )
  1127. {
  1128. fontstruct *font;
  1129. W16 i;
  1130. W16 x, y;
  1131. W16 px, py;
  1132. W8 *buffer;
  1133. W8 *source;
  1134. W8 *ptr;
  1135. char filename[ 256 ];
  1136. font = (fontstruct *)grsegs[ fontnumber ];
  1137. buffer = MM_MALLOC( FONTWIDTH * FONTHEIGHT * 4 );
  1138. if( buffer == NULL )
  1139. return;
  1140. ptr = buffer;
  1141. for( x = 0; x < FONTWIDTH; ++x )
  1142. {
  1143. for( y = 0; y < FONTHEIGHT; ++y, ptr += 4 )
  1144. {
  1145. ptr[ 0 ] = ptr[ 1 ] = ptr[ 2 ] = 0xFF;
  1146. ptr[ 3 ] = 0x00;
  1147. }
  1148. }
  1149. px = py = 0;
  1150. for( i = 0; i < 256; ++i )
  1151. {
  1152. if( ! font->width[ i ] )
  1153. continue;
  1154. if( px + font->width[ i ] > FONTWIDTH-1 )
  1155. {
  1156. py += font->height;
  1157. px = 0;
  1158. }
  1159. source = ((PW8) font) + font->location[ i ];
  1160. ptr = buffer + (py * FONTWIDTH + px) * 4;
  1161. for( y = 0; y < font->height; ++y, ptr += FONTWIDTH * 4 )
  1162. {
  1163. for( x = 0; x < font->width[ i ]; ++x )
  1164. {
  1165. if( *source++ )
  1166. {
  1167. ptr[ x * 4 + 3 ] = 0xFF;
  1168. }
  1169. }
  1170. }
  1171. px += 16;
  1172. } // end for i = 0; i < 256; ++i
  1173. cs_snprintf( filename, sizeof( filename ), "%s/font%d.tga", LGFXDIR, fontnumber );
  1174. WriteTGA( filename, 32, FONTWIDTH, FONTHEIGHT, buffer, 0, 1 );
  1175. MM_FREE( buffer );
  1176. }
  1177. PRIVATE void DecodeText( W16 version )
  1178. {
  1179. char *text;
  1180. int artnum;
  1181. int endextern;
  1182. int i;
  1183. int length;
  1184. FILE *fhandle;
  1185. int limit;
  1186. limit = 6;
  1187. if( version & SOD_PAK )
  1188. {
  1189. endextern = 168;
  1190. fhandle = fopen( "sod.txt", "wb" );
  1191. if( ! fhandle )
  1192. {
  1193. return;
  1194. }
  1195. limit = 1;
  1196. }
  1197. else if( version & WL6_PAK )
  1198. {
  1199. endextern = 143;
  1200. fhandle = fopen( "wl6.txt", "wb" );
  1201. if( ! fhandle )
  1202. {
  1203. return;
  1204. }
  1205. }
  1206. else
  1207. {
  1208. return;
  1209. }
  1210. for( i = 0 ; i < limit ; ++i )
  1211. {
  1212. artnum = endextern + i;
  1213. CA_CacheGrChunk( artnum, version );
  1214. text = (char *)grsegs[ artnum ];
  1215. length = strlen( text );
  1216. fwrite( text, sizeof( W8 ), length, fhandle );
  1217. fprintf( fhandle, "\n\n" );
  1218. MM_FREE( grsegs[ artnum ] );
  1219. }
  1220. fclose( fhandle );
  1221. }
  1222. /*
  1223. -----------------------------------------------------------------------------
  1224. Function: LumpExtractor() -Extract Lump gfx from Wolf3D and SOD data files.
  1225. Parameters: fextension -[in] String holding file extension
  1226. (must be in '.XXX' format).
  1227. limit -[in] max
  1228. version -[in] extension version.
  1229. 1 -WL6
  1230. 2 -SOD
  1231. Returns: Nothing.
  1232. Notes:
  1233. -----------------------------------------------------------------------------
  1234. */
  1235. PUBLIC _boolean LumpExtractor( const char *fextension, W32 limit, W16 version )
  1236. {
  1237. W32 i;
  1238. W8 *buffer, *buffer2;
  1239. if( ! fextension || ! *fextension )
  1240. {
  1241. printf( "Invalid file extension passed into LumpExtractor!\n" );
  1242. return false;
  1243. }
  1244. //
  1245. // Setup
  1246. //
  1247. if( 0 == FS_Mkdir( LGFXDIR ) )
  1248. {
  1249. printf( "[%s] Could not create directory (%s)!\n", "wolf_gfx.c", LGFXDIR );
  1250. return false;
  1251. }
  1252. if( ! CAL_SetupGrFile( fextension ) )
  1253. {
  1254. CAL_Shutdown();
  1255. return false;
  1256. }
  1257. //
  1258. // Allocate buffers
  1259. //
  1260. buffer = MM_MALLOC( 320 * 416 * 2 );
  1261. if( buffer == NULL )
  1262. {
  1263. CAL_Shutdown();
  1264. return false;
  1265. }
  1266. buffer2 = MM_MALLOC( 640 * 400 * 4 );
  1267. if( buffer2 == NULL )
  1268. {
  1269. MM_FREE( buffer );
  1270. CAL_Shutdown();
  1271. return false;
  1272. }
  1273. //
  1274. // Decode GFX data
  1275. //
  1276. printf( "Decoding GFX Data...\n" );
  1277. // (void)DecodeText( version );
  1278. for( i = STARTFONT; i < STARTPICS; ++i )
  1279. {
  1280. CA_CacheGrChunk( i, version );
  1281. Fontline( i, version );
  1282. }
  1283. for( i = STARTPICS; i < limit+1; ++i )
  1284. {
  1285. CA_CacheGrChunk( i, version );
  1286. SavePic( i, version, buffer, buffer2 );
  1287. }
  1288. //
  1289. // Shutdown
  1290. //
  1291. MM_FREE( buffer2 );
  1292. MM_FREE( buffer );
  1293. CAL_Shutdown();
  1294. return true;
  1295. }