2KEYFRAM.CPP 21 KB

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