KEYFRAME.CPP 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  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: F:\projects\c&c\vcs\code\keyframe.cpv 2.14 16 Oct 1995 16:48:54 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 12000*1024
  48. #define THEATER_BIG_SHAPE_BUFFER_SIZE 1000*1024
  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. char *BigShapeBufferPtr = NULL;
  59. int TotalBigShapes=0;
  60. BOOL ReallocShapeBufferFlag = FALSE;
  61. bool OriginalUseBigShapeBuffer = false;
  62. char *TheaterShapeBufferPtr = NULL;
  63. int TotalTheaterShapes = 0;
  64. #define MAX_SLOTS 1500
  65. #define THEATER_SLOT_START 1000
  66. char **KeyFrameSlots [MAX_SLOTS];
  67. int TotalSlotsUsed=0;
  68. int TheaterSlotsUsed = THEATER_SLOT_START;
  69. typedef struct tShapeHeaderType{
  70. unsigned draw_flags;
  71. char *shape_data;
  72. int shape_buffer; //1 if shape is in theater buffer
  73. } ShapeHeaderType;
  74. static int Length;
  75. void *Get_Shape_Header_Data(void *ptr)
  76. {
  77. if (UseBigShapeBuffer){
  78. ShapeHeaderType *header = (ShapeHeaderType*) ptr;
  79. return ((void*) (header->shape_data + (long)(header->shape_buffer ? TheaterShapeBufferStart : BigShapeBufferStart) ) );
  80. }else{
  81. return (ptr);
  82. }
  83. }
  84. int Get_Last_Frame_Length(void)
  85. {
  86. return(Length);
  87. }
  88. void Reset_Theater_Shapes (void)
  89. {
  90. /*
  91. ** Delete any previously allocated slots
  92. */
  93. for (int i=THEATER_SLOT_START ; i<TheaterSlotsUsed ; i++){
  94. delete [] KeyFrameSlots [i];
  95. }
  96. TheaterShapeBufferPtr = TheaterShapeBufferStart;
  97. TotalTheaterShapes = 0;
  98. TheaterSlotsUsed = THEATER_SLOT_START;
  99. }
  100. void Reallocate_Big_Shape_Buffer(void)
  101. {
  102. if (ReallocShapeBufferFlag){
  103. BigShapeBufferLength += 200 * 1024; //Extra 2 Mb of uncompressed shape space
  104. BigShapeBufferPtr -= (unsigned)BigShapeBufferStart;
  105. Memory_Error = NULL;
  106. BigShapeBufferStart = (char*)Resize_Alloc(BigShapeBufferStart, BigShapeBufferLength);
  107. Memory_Error = &Memory_Error_Handler;
  108. /*
  109. ** If we have run out of memory then disable the uncompressed shapes
  110. ** It may still be possible to continue with compressed shapes
  111. */
  112. if (!BigShapeBufferStart){
  113. UseBigShapeBuffer = false;
  114. return;
  115. }
  116. BigShapeBufferPtr += (unsigned)BigShapeBufferStart;
  117. ReallocShapeBufferFlag = FALSE;
  118. }
  119. }
  120. void Check_Use_Compressed_Shapes (void)
  121. {
  122. MEMORYSTATUS mem_info;
  123. mem_info.dwLength=sizeof(mem_info);
  124. GlobalMemoryStatus(&mem_info);
  125. UseBigShapeBuffer = (mem_info.dwTotalPhys > 16*1024*1024) ? TRUE : FALSE;
  126. OriginalUseBigShapeBuffer = UseBigShapeBuffer;
  127. // UseBigShapeBuffer = false;
  128. }
  129. /***********************************************************************************************
  130. * Disable_Uncompressed_Shapes -- Temporarily turns off shape decompression *
  131. * *
  132. * *
  133. * *
  134. * INPUT: Nothing *
  135. * *
  136. * OUTPUT: Nothing *
  137. * *
  138. * WARNINGS: None *
  139. * *
  140. * HISTORY: *
  141. * 11/19/96 2:37PM ST : Created *
  142. *=============================================================================================*/
  143. void Disable_Uncompressed_Shapes (void)
  144. {
  145. UseBigShapeBuffer = false;
  146. }
  147. /***********************************************************************************************
  148. * Enable_Uncompressed_Shapes -- Restores state of shape decompression before it was disabled *
  149. * *
  150. * *
  151. * *
  152. * INPUT: Nothing *
  153. * *
  154. * OUTPUT: Nothing *
  155. * *
  156. * WARNINGS: None *
  157. * *
  158. * HISTORY: *
  159. * 11/19/96 2:37PM ST : Created *
  160. *=============================================================================================*/
  161. void Enable_Uncompressed_Shapes (void)
  162. {
  163. UseBigShapeBuffer = OriginalUseBigShapeBuffer;
  164. }
  165. #define FIXIT_SCORE_CRASH
  166. unsigned long Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr)
  167. {
  168. #ifdef FIXIT_SCORE_CRASH
  169. char * ptr;
  170. unsigned long offcurr, offdiff;
  171. #else
  172. char * ptr, * lockptr;
  173. unsigned long offcurr, off16, offdiff;
  174. #endif
  175. unsigned long offset[SUBFRAMEOFFS];
  176. KeyFrameHeaderType *keyfr;
  177. unsigned short buffsize, currframe, subframe;
  178. unsigned long length = 0;
  179. char frameflags;
  180. unsigned long return_value;
  181. char *temp_shape_ptr;
  182. //
  183. // valid pointer??
  184. //
  185. Length = 0;
  186. if ( !dataptr || !buffptr ) {
  187. return(0);
  188. }
  189. //
  190. // look at header then check that frame to build is not greater
  191. // than total frames
  192. //
  193. keyfr = (KeyFrameHeaderType *) dataptr;
  194. if ( framenumber >= keyfr->frames ) {
  195. return(0);
  196. }
  197. if (UseBigShapeBuffer){
  198. /*
  199. ** If we havnt yet allocated memory for uncompressed shapes then do so now.
  200. **
  201. */
  202. if (!BigShapeBufferStart){
  203. BigShapeBufferStart = (char*)Alloc(BigShapeBufferLength, MEM_NORMAL);
  204. BigShapeBufferPtr = BigShapeBufferStart;
  205. /*
  206. ** Allocate memory for theater specific uncompressed shapes
  207. */
  208. TheaterShapeBufferStart = (char*) Alloc (TheaterShapeBufferLength, MEM_NORMAL);
  209. TheaterShapeBufferPtr = TheaterShapeBufferStart;
  210. }
  211. /*
  212. ** Track memory usage in uncompressed shape buffers.
  213. */
  214. static bool show_info = true;
  215. if ((Frame & 0xff) == 0){
  216. if (show_info){
  217. char debugstr [128];
  218. sprintf (debugstr, "C&C95 - Big shape buffer is now %d Kb.\n", BigShapeBufferLength / 1024);
  219. CCDebugString (debugstr);
  220. sprintf (debugstr, "C&C95 - %d Kb Used in big shape buffer.\n", (unsigned)((unsigned)BigShapeBufferPtr - (unsigned)BigShapeBufferStart)/1024);
  221. CCDebugString (debugstr);
  222. sprintf (debugstr, "C&C95 - %d Kb Used in theater shape buffer.\n", (unsigned)((unsigned)TheaterShapeBufferPtr - (unsigned)TheaterShapeBufferStart)/1024);
  223. CCDebugString (debugstr);
  224. show_info = false;
  225. }
  226. }else{
  227. show_info = true;
  228. }
  229. /*
  230. ** If we are running out of memory (<128k left) for uncompressed shapes
  231. ** then allocate some more.
  232. */
  233. if (( (unsigned)BigShapeBufferStart + BigShapeBufferLength) - (unsigned)BigShapeBufferPtr < 128*1024){
  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. }