2KEYFRAM.CPP 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /CounterStrike/2KEYFRAM.CPP 1 3/03/97 10:24a Joe_bostic $ */
  15. /***********************************************************************************************
  16. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : KEYFRAME.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : 06/25/95 *
  26. * *
  27. * Last Update : June 25, 1995 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * Get_Build_Frame_Count -- Fetches the number of frames in data block. *
  32. * Get_Build_Frame_Width -- Fetches the width of the shape image. *
  33. * Get_Build_Frame_Height -- Fetches the height of the shape image. *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "function.h"
  36. #define SUBFRAMEOFFS 7 // 3 1/2 frame offsets loaded (2 offsets/frame)
  37. #define Apply_Delta(buffer, delta) Apply_XOR_Delta((char*)(buffer), (char*)(delta))
  38. typedef struct {
  39. unsigned short frames;
  40. unsigned short x;
  41. unsigned short y;
  42. unsigned short width;
  43. unsigned short height;
  44. unsigned short largest_frame_size;
  45. short flags;
  46. } KeyFrameHeaderType;
  47. #define INITIAL_BIG_SHAPE_BUFFER_SIZE 8000000
  48. #define THEATER_BIG_SHAPE_BUFFER_SIZE 4000000
  49. #define UNCOMPRESS_MAGIC_NUMBER 56789
  50. unsigned BigShapeBufferLength = INITIAL_BIG_SHAPE_BUFFER_SIZE;
  51. unsigned TheaterShapeBufferLength = THEATER_BIG_SHAPE_BUFFER_SIZE;
  52. extern "C"{
  53. char *BigShapeBufferStart = NULL;
  54. char *TheaterShapeBufferStart = NULL;
  55. BOOL UseBigShapeBuffer = FALSE;
  56. bool IsTheaterShape = false;
  57. }
  58. #ifdef FIXIT_SCORE_CRASH
  59. /*
  60. ** Global required to fix the score screen crash bug by allowing disabling of uncompressed shapes.
  61. */
  62. bool OriginalUseBigShapeBuffer = false;
  63. #endif //FIXIT
  64. char *BigShapeBufferPtr = NULL;
  65. int TotalBigShapes=0;
  66. BOOL ReallocShapeBufferFlag = FALSE;
  67. char *TheaterShapeBufferPtr = NULL;
  68. int TotalTheaterShapes = 0;
  69. #define MAX_SLOTS 1500
  70. #define THEATER_SLOT_START 1000
  71. char **KeyFrameSlots [MAX_SLOTS];
  72. int TotalSlotsUsed=0;
  73. int TheaterSlotsUsed = THEATER_SLOT_START;
  74. typedef struct tShapeHeaderType{
  75. unsigned draw_flags;
  76. char *shape_data;
  77. int shape_buffer; //1 if shape is in theater buffer
  78. } ShapeHeaderType;
  79. static int Length;
  80. void *Get_Shape_Header_Data(void *ptr)
  81. {
  82. if (UseBigShapeBuffer) {
  83. ShapeHeaderType *header = (ShapeHeaderType*) ptr;
  84. return ((void*) (header->shape_data + (long)(header->shape_buffer ? TheaterShapeBufferStart : BigShapeBufferStart) ) );
  85. } else {
  86. return (ptr);
  87. }
  88. }
  89. int Get_Last_Frame_Length(void)
  90. {
  91. return(Length);
  92. }
  93. void Reset_Theater_Shapes (void)
  94. {
  95. /*
  96. ** Delete any previously allocated slots
  97. */
  98. for (int i=THEATER_SLOT_START ; i<TheaterSlotsUsed ; i++) {
  99. delete [] KeyFrameSlots [i];
  100. }
  101. TheaterShapeBufferPtr = TheaterShapeBufferStart;
  102. TotalTheaterShapes = 0;
  103. TheaterSlotsUsed = THEATER_SLOT_START;
  104. }
  105. void Reallocate_Big_Shape_Buffer(void)
  106. {
  107. if (ReallocShapeBufferFlag) {
  108. BigShapeBufferLength += 2000000; //Extra 2 Mb of uncompressed shape space
  109. BigShapeBufferPtr -= (unsigned)BigShapeBufferStart;
  110. Memory_Error = NULL;
  111. BigShapeBufferStart = (char*)Resize_Alloc(BigShapeBufferStart, BigShapeBufferLength);
  112. Memory_Error = &Memory_Error_Handler;
  113. /*
  114. ** If we have run out of memory then disable the uncompressed shapes
  115. ** It may still be possible to continue with compressed shapes
  116. */
  117. if (!BigShapeBufferStart) {
  118. UseBigShapeBuffer = false;
  119. return;
  120. }
  121. BigShapeBufferPtr += (unsigned)BigShapeBufferStart;
  122. ReallocShapeBufferFlag = FALSE;
  123. }
  124. }
  125. //#ifdef FIXIT_SCORE_CRASH
  126. /***********************************************************************************************
  127. * Disable_Uncompressed_Shapes -- Temporarily turns off shape decompression *
  128. * *
  129. * *
  130. * *
  131. * INPUT: Nothing *
  132. * *
  133. * OUTPUT: Nothing *
  134. * *
  135. * WARNINGS: None *
  136. * *
  137. * HISTORY: *
  138. * 11/19/96 2:37PM ST : Created *
  139. *=============================================================================================*/
  140. void Disable_Uncompressed_Shapes (void)
  141. {
  142. UseBigShapeBuffer = false;
  143. }
  144. /***********************************************************************************************
  145. * Enable_Uncompressed_Shapes -- Restores state of shape decompression before it was disabled *
  146. * *
  147. * *
  148. * *
  149. * INPUT: Nothing *
  150. * *
  151. * OUTPUT: Nothing *
  152. * *
  153. * WARNINGS: None *
  154. * *
  155. * HISTORY: *
  156. * 11/19/96 2:37PM ST : Created *
  157. *=============================================================================================*/
  158. void Enable_Uncompressed_Shapes (void)
  159. {
  160. UseBigShapeBuffer = OriginalUseBigShapeBuffer;
  161. }
  162. //#endif //FIXIT
  163. void Check_Use_Compressed_Shapes (void)
  164. {
  165. #if (1) // Uncompressed shapes enabled for performance reasons. We don't need to worry about memory.
  166. // Uncompressed shapes don't seem to work in RA for rotated/scaled objects so wherever scale/rotate is used,
  167. // we will need to disable it (like in Techno_Draw_Object). ST - 11/6/2019 2:09PM
  168. UseBigShapeBuffer = true;
  169. OriginalUseBigShapeBuffer = true;
  170. #else
  171. MEMORYSTATUS mem_info;
  172. mem_info.dwLength=sizeof(mem_info);
  173. GlobalMemoryStatus(&mem_info);
  174. UseBigShapeBuffer = (mem_info.dwTotalPhys > 16*1024*1024) ? TRUE : FALSE;
  175. #ifdef FIXIT_SCORE_CRASH
  176. /*
  177. ** Keep track of our original decision about whether to use cached shapes.
  178. ** This is needed for the score screen crash fix.
  179. */
  180. OriginalUseBigShapeBuffer = UseBigShapeBuffer;
  181. #endif //FIXIT
  182. #endif
  183. }
  184. unsigned long Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr)
  185. {
  186. #ifdef FIXIT_SCORE_CRASH
  187. char *ptr;
  188. unsigned long offcurr, offdiff;
  189. #else
  190. char *ptr, *lockptr;//, *uncomp_ptr;
  191. unsigned long offcurr, off16, offdiff;
  192. #endif
  193. unsigned long offset[SUBFRAMEOFFS];
  194. KeyFrameHeaderType *keyfr;
  195. unsigned short buffsize, currframe, subframe;
  196. unsigned long length = 0;
  197. char frameflags;
  198. unsigned long return_value;
  199. char *temp_shape_ptr;
  200. //
  201. // valid pointer??
  202. //
  203. Length = 0;
  204. if ( !dataptr || !buffptr ) {
  205. return(0);
  206. }
  207. //
  208. // look at header then check that frame to build is not greater
  209. // than total frames
  210. //
  211. keyfr = (KeyFrameHeaderType *) dataptr;
  212. if ( framenumber >= keyfr->frames ) {
  213. return(0);
  214. }
  215. if (UseBigShapeBuffer) {
  216. /*
  217. ** If we havnt yet allocated memory for uncompressed shapes then do so now.
  218. **
  219. */
  220. if (!BigShapeBufferStart) {
  221. BigShapeBufferStart = (char*)Alloc(BigShapeBufferLength, MEM_NORMAL);
  222. BigShapeBufferPtr = BigShapeBufferStart;
  223. /*
  224. ** Allocate memory for theater specific uncompressed shapes
  225. */
  226. TheaterShapeBufferStart = (char*) Alloc (TheaterShapeBufferLength, MEM_NORMAL);
  227. TheaterShapeBufferPtr = TheaterShapeBufferStart;
  228. }
  229. /*
  230. ** If we are running out of memory (<10k left) for uncompressed shapes
  231. ** then allocate some more.
  232. */
  233. if (( (unsigned)BigShapeBufferStart + BigShapeBufferLength) - (unsigned)BigShapeBufferPtr < 128000) {
  234. ReallocShapeBufferFlag = TRUE;
  235. }
  236. /*
  237. ** If this animation was not previously uncompressed then
  238. ** allocate memory to keep the pointers to the uncompressed data
  239. ** for these animation frames
  240. */
  241. if (keyfr->x != UNCOMPRESS_MAGIC_NUMBER) {
  242. keyfr->x = UNCOMPRESS_MAGIC_NUMBER;
  243. if (IsTheaterShape) {
  244. keyfr->y = TheaterSlotsUsed;
  245. TheaterSlotsUsed++;
  246. } else {
  247. keyfr->y = TotalSlotsUsed;
  248. TotalSlotsUsed++;
  249. }
  250. /*
  251. ** Allocate and clear the memory for the shape info
  252. */
  253. KeyFrameSlots[keyfr->y]= new char *[keyfr->frames];
  254. memset (KeyFrameSlots[keyfr->y] , 0 , keyfr->frames*4);
  255. }
  256. /*
  257. ** If this frame was previously uncompressed then just return
  258. ** a pointer to the raw data
  259. */
  260. if (*(KeyFrameSlots[keyfr->y]+framenumber)) {
  261. if (IsTheaterShape) {
  262. return ((unsigned long)TheaterShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));
  263. } else {
  264. return ((unsigned long)BigShapeBufferStart + (unsigned long)*(KeyFrameSlots[keyfr->y]+framenumber));
  265. }
  266. }
  267. }
  268. // calc buff size
  269. buffsize = keyfr->width * keyfr->height;
  270. // get offset into data
  271. ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)framenumber << 3) + sizeof(KeyFrameHeaderType)) );
  272. Mem_Copy( ptr, &offset[0], 12L );
  273. frameflags = (char)(offset[0] >> 24);
  274. if ( (frameflags & KF_KEYFRAME) ) {
  275. ptr = (char *)Add_Long_To_Pointer( dataptr, (offset[0] & 0x00FFFFFFL) );
  276. if (keyfr->flags & 1 ) {
  277. ptr = (char *)Add_Long_To_Pointer( ptr, 768L );
  278. }
  279. length = LCW_Uncompress( ptr, buffptr, buffsize );
  280. } else { // key delta or delta
  281. if ( (frameflags & KF_DELTA) ) {
  282. currframe = (unsigned short)offset[1];
  283. ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)currframe << 3) + sizeof(KeyFrameHeaderType)) );
  284. Mem_Copy( ptr, &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );
  285. }
  286. // key frame
  287. offcurr = offset[1] & 0x00FFFFFFL;
  288. // key delta
  289. offdiff = (offset[0] & 0x00FFFFFFL) - offcurr;
  290. ptr = (char *)Add_Long_To_Pointer( dataptr, offcurr );
  291. if (keyfr->flags & 1 ) {
  292. ptr = (char *)Add_Long_To_Pointer( ptr, 768L );
  293. }
  294. #ifndef FIXIT_SCORE_CRASH
  295. off16 = (unsigned long)lockptr & 0x00003FFFL;
  296. #endif
  297. length = LCW_Uncompress( ptr, buffptr, buffsize );
  298. if (length > buffsize) {
  299. return(0);
  300. }
  301. #ifndef FIXIT_SCORE_CRASH
  302. if ( ((offset[2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {
  303. ptr = (char *)Add_Long_To_Pointer( ptr, offdiff );
  304. off16 = (unsigned long)ptr & 0x00003FFFL;
  305. offcurr += offdiff;
  306. offdiff = 0;
  307. }
  308. #endif
  309. length = buffsize;
  310. Apply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));
  311. if ( (frameflags & KF_DELTA) ) {
  312. // adjust to delta after the keydelta
  313. currframe++;
  314. subframe = 2;
  315. while (currframe <= framenumber) {
  316. offdiff = (offset[subframe] & 0x00FFFFFFL) - offcurr;
  317. #ifndef FIXIT_SCORE_CRASH
  318. if ( ((offset[subframe+2] & 0x00FFFFFFL) - offcurr) >= (0x00010000L - off16) ) {
  319. ptr = (char *)Add_Long_To_Pointer( ptr, offdiff );
  320. off16 = (unsigned long)lockptr & 0x00003FFFL;
  321. offcurr += offdiff;
  322. offdiff = 0;
  323. }
  324. #endif
  325. length = buffsize;
  326. Apply_Delta(buffptr, Add_Long_To_Pointer(ptr, offdiff));
  327. currframe++;
  328. subframe += 2;
  329. if ( subframe >= (SUBFRAMEOFFS - 1) &&
  330. currframe <= framenumber ) {
  331. Mem_Copy( Add_Long_To_Pointer( dataptr,
  332. (((unsigned long)currframe << 3) +
  333. sizeof(KeyFrameHeaderType)) ),
  334. &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) );
  335. subframe = 0;
  336. }
  337. }
  338. }
  339. }
  340. if (UseBigShapeBuffer) {
  341. /*
  342. ** Save the uncompressed shape data so we dont have to uncompress it
  343. ** again next time its drawn.
  344. ** We keep a space free before the raw shape data so we can add line
  345. ** header info before the shape is drawn for the first time
  346. */
  347. if (IsTheaterShape) {
  348. /*
  349. ** Shape is a theater specific shape
  350. */
  351. return_value = (unsigned long) TheaterShapeBufferPtr;
  352. temp_shape_ptr = TheaterShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);
  353. /*
  354. ** align the actual shape data
  355. */
  356. if (3 & (unsigned)temp_shape_ptr) {
  357. temp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);
  358. }
  359. memcpy (temp_shape_ptr , buffptr , length);
  360. ((ShapeHeaderType *)TheaterShapeBufferPtr)->draw_flags = -1; //Flag that headers need to be generated
  361. ((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)TheaterShapeBufferStart; //pointer to old raw shape data
  362. ((ShapeHeaderType *)TheaterShapeBufferPtr)->shape_buffer = 1; //Theater buffer
  363. *(KeyFrameSlots[keyfr->y]+framenumber) = TheaterShapeBufferPtr - (unsigned)TheaterShapeBufferStart;
  364. TheaterShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);
  365. /*
  366. ** Align the next shape
  367. */
  368. if (3 & (unsigned)TheaterShapeBufferPtr) {
  369. TheaterShapeBufferPtr = (char *)((unsigned)(TheaterShapeBufferPtr + 3) & 0xfffffffc);
  370. }
  371. Length = length;
  372. return (return_value);
  373. } else {
  374. return_value=(unsigned long)BigShapeBufferPtr;
  375. temp_shape_ptr = BigShapeBufferPtr + keyfr->height+sizeof(ShapeHeaderType);
  376. /*
  377. ** align the actual shape data
  378. */
  379. if (3 & (unsigned)temp_shape_ptr) {
  380. temp_shape_ptr = (char *) ((unsigned)(temp_shape_ptr + 3) & 0xfffffffc);
  381. }
  382. memcpy (temp_shape_ptr , buffptr , length);
  383. ((ShapeHeaderType *)BigShapeBufferPtr)->draw_flags = -1; //Flag that headers need to be generated
  384. ((ShapeHeaderType *)BigShapeBufferPtr)->shape_data = temp_shape_ptr - (unsigned)BigShapeBufferStart; //pointer to old raw shape data
  385. ((ShapeHeaderType *)BigShapeBufferPtr)->shape_buffer = 0; //Normal Big Shape Buffer
  386. *(KeyFrameSlots[keyfr->y]+framenumber) = BigShapeBufferPtr - (unsigned)BigShapeBufferStart;
  387. BigShapeBufferPtr = (char*)(length + (unsigned)temp_shape_ptr);
  388. // Align the next shape
  389. if (3 & (unsigned)BigShapeBufferPtr) {
  390. BigShapeBufferPtr = (char *)((unsigned)(BigShapeBufferPtr + 3) & 0xfffffffc);
  391. }
  392. Length = length;
  393. return (return_value);
  394. }
  395. } else {
  396. return ((unsigned long)buffptr);
  397. }
  398. }
  399. /***********************************************************************************************
  400. * Get_Build_Frame_Count -- Fetches the number of frames in data block. *
  401. * *
  402. * Use this routine to determine the number of shapes within the data block. *
  403. * *
  404. * INPUT: dataptr -- Pointer to the keyframe shape data block. *
  405. * *
  406. * OUTPUT: Returns with the number of shapes in the data block. *
  407. * *
  408. * WARNINGS: none *
  409. * *
  410. * HISTORY: *
  411. * 06/25/1995 JLB : Commented. *
  412. *=============================================================================================*/
  413. unsigned short Get_Build_Frame_Count(void const *dataptr)
  414. {
  415. if (dataptr) {
  416. return(((KeyFrameHeaderType const *)dataptr)->frames);
  417. }
  418. return(0);
  419. }
  420. unsigned short Get_Build_Frame_X(void const *dataptr)
  421. {
  422. if (dataptr) {
  423. return(((KeyFrameHeaderType const *)dataptr)->x);
  424. }
  425. return(0);
  426. }
  427. unsigned short Get_Build_Frame_Y(void const *dataptr)
  428. {
  429. if (dataptr) {
  430. return(((KeyFrameHeaderType const *)dataptr)->y);
  431. }
  432. return(0);
  433. }
  434. /***********************************************************************************************
  435. * Get_Build_Frame_Width -- Fetches the width of the shape image. *
  436. * *
  437. * Use this routine to fetch the width of the shapes within the keyframe shape data block. *
  438. * All shapes within the block have the same width. *
  439. * *
  440. * INPUT: dataptr -- Pointer to the keyframe shape data block. *
  441. * *
  442. * OUTPUT: Returns with the width of the shapes in the block -- expressed in pixels. *
  443. * *
  444. * WARNINGS: none *
  445. * *
  446. * HISTORY: *
  447. * 06/25/1995 JLB : Commented *
  448. *=============================================================================================*/
  449. unsigned short Get_Build_Frame_Width(void const *dataptr)
  450. {
  451. if (dataptr) {
  452. return(((KeyFrameHeaderType const *)dataptr)->width);
  453. }
  454. return(0);
  455. }
  456. /***********************************************************************************************
  457. * Get_Build_Frame_Height -- Fetches the height of the shape image. *
  458. * *
  459. * Use this routine to fetch the height of the shapes within the keyframe shape data block. *
  460. * All shapes within the block have the same height. *
  461. * *
  462. * INPUT: dataptr -- Pointer to the keyframe shape data block. *
  463. * *
  464. * OUTPUT: Returns with the height of the shapes in the block -- expressed in pixels. *
  465. * *
  466. * WARNINGS: none *
  467. * *
  468. * HISTORY: *
  469. * 06/25/1995 JLB : Commented *
  470. *=============================================================================================*/
  471. unsigned short Get_Build_Frame_Height(void const *dataptr)
  472. {
  473. if (dataptr) {
  474. return(((KeyFrameHeaderType const *)dataptr)->height);
  475. }
  476. return(0);
  477. }
  478. bool Get_Build_Frame_Palette(void const * dataptr, void * palette)
  479. {
  480. if (dataptr && (((KeyFrameHeaderType const *)dataptr)->flags & 1)) {
  481. char const * ptr = (char const *)Add_Long_To_Pointer( dataptr,
  482. ( (( (long)sizeof(unsigned long) << 1) *
  483. ((KeyFrameHeaderType *) dataptr)->frames ) +
  484. 16 + sizeof(KeyFrameHeaderType) ) );
  485. memcpy(palette, ptr, 768L);
  486. return(true);
  487. }
  488. return(false);
  489. }