WSA.CPP 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153
  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: g:/library/source/rcs/./wsa.c 1.16 1994/05/20 15:35:27 joe_bostic Exp $ */
  15. /***************************************************************************
  16. ** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S **
  17. ***************************************************************************
  18. * *
  19. * Project Name : Library Animation System *
  20. * *
  21. * File Name : WSA.C *
  22. * *
  23. * Programmer : Michael Legg *
  24. * *
  25. * Start Date : November 20, 1991 *
  26. * *
  27. *-------------------------------------------------------------------------*
  28. * There are many different ways that the user can use the WSA library *
  29. * module. The options are as follows : *
  30. * *
  31. * System Allocation vs User Buffer - The user may request that the *
  32. * system allocate the needed buffer from the heap or the user may *
  33. * pass his own buffer in for the animator to use. *
  34. * *
  35. * Resident vs File based - If there is enough RAM, the user may put the *
  36. * entire animation into RAM for fastest animations. If there is *
  37. * not enouph RAM, the system will automatically make it so each *
  38. * frame will be read off disk when needed. *
  39. * *
  40. * Direct to Page vs Use of a user buffer -- Noramally Direct to page *
  41. * is the best method both in speed and in RAM need to hold anim. *
  42. * One may want to use the write to user buffer method if they *
  43. * are using the animation in a non sequencial order. *
  44. * *
  45. *-------------------------------------------------------------------------*
  46. * Functions: *
  47. * Animate_Frame -- Displays a frame of a given animation *
  48. * Get_Animation_Frame_Count -- Return Number of frames in an animation. *
  49. * Get_Animation_X -- Gets the x from an animation *
  50. * Get_Animation_Y -- Gets the y from an animation *
  51. * Get_Animation_Width -- Gets the width from an animation *
  52. * Get_Animation_Height -- The height of the animation we are processing *
  53. * Apply_Delta -- Copies frame into delta buffer, then applies to target *
  54. * Close_Animation -- Close the animation, freeing the space if necessary*
  55. * Get_File_Frame_Offset -- Get offset of a delta frame from animate file*
  56. * Get_Resident_Frame_Offset -- Gets frame offset of animate file in RAM *
  57. * Open_Animation -- Opens an animation file and reads into buffer *
  58. *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  59. #include <wwstd.h>
  60. #include "wsa.h"
  61. #include <wwmem.h>
  62. #include <file.h>
  63. #include <misc.h>
  64. #include <iff.h>
  65. //#include <mem.h>
  66. #include <string.h>
  67. //
  68. // WSA animation header allocation type.
  69. // If we need more then 8 flags for the flags variable, we can combine
  70. // USER_ALLOCATED with SYS_ALLOCATED and combine FILE with RESIDENT.
  71. //
  72. #define WSA_USER_ALLOCATED 0x01
  73. #define WSA_SYS_ALLOCATED 0x02
  74. #define WSA_FILE 0x04
  75. #define WSA_RESIDENT 0x08
  76. #define WSA_TARGET_IN_BUFFER 0x10
  77. #define WSA_LINEAR_ONLY 0x20
  78. #define WSA_FRAME_0_ON_PAGE 0x40
  79. #define WSA_AMIGA_ANIMATION 0x80
  80. #define WSA_PALETTE_PRESENT 0x100
  81. #define WSA_FRAME_0_IS_DELTA 0x200
  82. // These are used to call Apply_XOR_Delta_To_Page_Or_Viewport() to setup flags parameter. If
  83. // These change, make sure and change their values in lp_asm.asm.
  84. #define DO_XOR 0x0
  85. #define DO_COPY 0x01
  86. #define TO_VIEWPORT 0x0
  87. #define TO_PAGE 0x02
  88. typedef struct {
  89. unsigned short current_frame;
  90. unsigned short total_frames;
  91. unsigned short pixel_x;
  92. unsigned short pixel_y;
  93. unsigned short pixel_width;
  94. unsigned short pixel_height;
  95. unsigned short largest_frame_size;
  96. char *delta_buffer;
  97. char *file_buffer;
  98. char file_name[ 13 ];
  99. short flags;
  100. // New fields that animate does not know about below this point. SEE EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT
  101. short file_handle;
  102. unsigned long anim_mem_size;
  103. } SysAnimHeaderType;
  104. // NOTE:"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE
  105. // UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING
  106. // IT TO THE FILE. THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.
  107. #define EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT (sizeof(short) + sizeof(unsigned long))
  108. //
  109. // Header structure for the file.
  110. // NOTE: The 'total_frames' field is used to differentiate between Amiga and IBM
  111. // animations. Amiga animations have the HIGH bit set.
  112. //
  113. typedef struct {
  114. unsigned short total_frames;
  115. unsigned short pixel_x;
  116. unsigned short pixel_y;
  117. unsigned short pixel_width;
  118. unsigned short pixel_height;
  119. unsigned short largest_frame_size;
  120. short flags;
  121. unsigned long frame0_offset;
  122. unsigned long frame0_end;
  123. /* unsigned long data_seek_offset, unsigned short frame_size ... */
  124. } WSA_FileHeaderType;
  125. #define WSA_FILE_HEADER_SIZE ( sizeof(WSA_FileHeaderType) - (2 * sizeof(unsigned long)) )
  126. /*=========================================================================*/
  127. /* The following PRIVATE functions are in this file: */
  128. /*=========================================================================*/
  129. PRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame );
  130. PRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust);
  131. PRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w);
  132. /*= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
  133. /***************************************************************************
  134. * OPEN_ANIMATION -- Opens an animation file and reads into buffer *
  135. * *
  136. * INPUT: char *file_name of animation sequence file. *
  137. * char *user_buffer pointer if one exists (NULL ok) *
  138. * unsigned long user_buffer_size if known (NULL ok) *
  139. * WSAOpenType user_flags - flags on how to open. *
  140. * unsigned char *palette - pointer to palette space for return (NULL ok) *
  141. * *
  142. * OUTPUT: void *pointer to animation data. Must be used for all *
  143. * other WSA calls. *
  144. * *
  145. * WARNINGS: May return NULL, please check. *
  146. * *
  147. * HISTORY: *
  148. * 11/26/1991 SB : Created. *
  149. *=========================================================================*/
  150. void * __cdecl Open_Animation(char const *file_name, char *user_buffer, long user_buffer_size, WSAOpenType user_flags, unsigned char *palette)
  151. {
  152. int fh, anim_flags;
  153. int palette_adjust;
  154. unsigned int offsets_size;
  155. unsigned int frame0_size;
  156. long target_buffer_size, delta_buffer_size, file_buffer_size;
  157. long max_buffer_size, min_buffer_size;
  158. char *sys_anim_header_buffer;
  159. char *target_buffer;
  160. char *delta_buffer, *delta_back;
  161. SysAnimHeaderType *sys_header;
  162. WSA_FileHeaderType file_header;
  163. /*======================================================================*/
  164. /* Open the file to get the header information */
  165. /*======================================================================*/
  166. anim_flags = 0;
  167. fh = Open_File(file_name, READ);
  168. Read_File(fh, (char *) &file_header, sizeof(WSA_FileHeaderType));
  169. /*======================================================================*/
  170. /* If the file has an attached palette then if we have a valid palette */
  171. /* pointer we need to read it in. */
  172. /*======================================================================*/
  173. if (file_header.flags & 1) {
  174. anim_flags |= WSA_PALETTE_PRESENT;
  175. palette_adjust = 768;
  176. if (palette != NULL) {
  177. Seek_File(fh, sizeof(unsigned long) * (file_header.total_frames), SEEK_CUR);
  178. Read_File(fh, palette, 768L);
  179. }
  180. } else {
  181. palette_adjust = 0;
  182. }
  183. // Check for flag from ANIMATE indicating that this animation was
  184. // created from a .LBM and a .ANM. These means that the first
  185. // frame is a XOR Delta from a picture, not black.
  186. if (file_header.flags & 2) {
  187. anim_flags |= WSA_FRAME_0_IS_DELTA;
  188. }
  189. // Get the total file size minus the size of the first frame and the size
  190. // of the file header. These will not be read in to save even more space.
  191. file_buffer_size = Seek_File(fh, 0L, SEEK_END);
  192. if (file_header.frame0_offset) {
  193. long tlong;
  194. tlong = file_header.frame0_end - file_header.frame0_offset;
  195. frame0_size = (unsigned short) tlong;
  196. }
  197. else {
  198. anim_flags |= WSA_FRAME_0_ON_PAGE;
  199. frame0_size = 0;
  200. }
  201. file_buffer_size -= palette_adjust + frame0_size + WSA_FILE_HEADER_SIZE;
  202. // We need to determine the buffer sizes required for the animation. At a
  203. // minimum, we need a target buffer for the uncompressed frame and a delta
  204. // buffer for the delta data. We may be able to make the file resident,
  205. // so we will determine the file size.
  206. //
  207. // If the target buffer is in the user buffer
  208. // Then figure its size
  209. // and set the allocation flag
  210. // Else size is zero.
  211. //
  212. if (user_flags & WSA_OPEN_DIRECT) {
  213. target_buffer_size = 0L;
  214. }
  215. else {
  216. anim_flags |= WSA_TARGET_IN_BUFFER;
  217. target_buffer_size = (unsigned long) file_header.pixel_width * file_header.pixel_height;
  218. }
  219. // NOTE:"THIS IS A BAD THING. SINCE sizeof(SysAnimHeaderType) CHANGED, THE ANIMATE.EXE
  220. // UTILITY DID NOT KNOW I UPDATED IT, IT ADDS IT TO largest_frame_size BEFORE SAVING
  221. // IT TO THE FILE. THIS MEANS I HAVE TO ADD THESE charS ON NOW FOR IT TO WORK.
  222. delta_buffer_size = (unsigned long) file_header.largest_frame_size + EXTRA_charS_ANIMATE_NOT_KNOW_ABOUT;
  223. min_buffer_size = target_buffer_size + delta_buffer_size;
  224. max_buffer_size = min_buffer_size + file_buffer_size;
  225. // check to see if buffer size is big enough for at least min required
  226. if (user_buffer && (user_buffer_size < min_buffer_size)) {
  227. Close_File(fh);
  228. return(NULL);
  229. }
  230. // A buffer was not passed in, so do allocations
  231. if (user_buffer == NULL) {
  232. // If the user wants it from the disk, then let us give it to him,
  233. // otherwise, try to give a max allocation he can have.
  234. if (user_flags & WSA_OPEN_FROM_DISK) {
  235. user_buffer_size = min_buffer_size;
  236. }
  237. // else no buffer size, then try max configuration.
  238. else if (!user_buffer_size) {
  239. user_buffer_size = max_buffer_size;
  240. }
  241. // else if buffer specified is less then max needed, give min.
  242. else if (user_buffer_size < max_buffer_size) {
  243. user_buffer_size = min_buffer_size;
  244. }
  245. // otherwise we only want to alloc what we need.
  246. else {
  247. user_buffer_size = max_buffer_size;
  248. }
  249. // Check to see if enough RAM available for buffer_size.
  250. if (user_buffer_size > Ram_Free(MEM_NORMAL)) {
  251. // If not enough room for even the min, return no buffer.
  252. if (min_buffer_size > Ram_Free(MEM_NORMAL)) {
  253. Close_File(fh);
  254. return(NULL);
  255. }
  256. // Else make buffer size the min and allocate it.
  257. user_buffer_size = min_buffer_size;
  258. }
  259. // allocate buffer needed
  260. user_buffer = (char *) Alloc(user_buffer_size, MEM_CLEAR);
  261. anim_flags |= WSA_SYS_ALLOCATED;
  262. }
  263. else {
  264. // Check to see if the user_buffer_size should be min or max.
  265. if ((user_flags & WSA_OPEN_FROM_DISK) || (user_buffer_size < max_buffer_size)) {
  266. user_buffer_size = min_buffer_size;
  267. }
  268. else {
  269. user_buffer_size = max_buffer_size;
  270. }
  271. anim_flags |= WSA_USER_ALLOCATED;
  272. }
  273. // Set the pointers to the RAM buffers
  274. sys_anim_header_buffer = user_buffer;
  275. target_buffer = (char *) Add_Long_To_Pointer(sys_anim_header_buffer, sizeof(SysAnimHeaderType));
  276. delta_buffer = (char *) Add_Long_To_Pointer(target_buffer, target_buffer_size);
  277. // Clear target buffer if it is in the user buffer.
  278. if (target_buffer_size) {
  279. memset( target_buffer, 0, (unsigned short) target_buffer_size );
  280. }
  281. // Poke data into the system animation header (start of user_buffer)
  282. // current_frame is set to total_frames so that Animate_Frame() knows that
  283. // it needs to clear the target buffer.
  284. sys_header = ( SysAnimHeaderType * ) sys_anim_header_buffer;
  285. sys_header -> current_frame =
  286. sys_header -> total_frames = file_header.total_frames;
  287. sys_header -> pixel_x = file_header.pixel_x;
  288. sys_header -> pixel_y = file_header.pixel_y;
  289. sys_header -> pixel_width = file_header.pixel_width;
  290. sys_header -> pixel_height = file_header.pixel_height;
  291. sys_header -> anim_mem_size = user_buffer_size;
  292. sys_header -> delta_buffer = delta_buffer;
  293. sys_header -> largest_frame_size =
  294. (unsigned short) (delta_buffer_size - sizeof(SysAnimHeaderType));
  295. strcpy(sys_header->file_name, file_name);
  296. // Figure how much room the frame offsets take up in the file.
  297. // Add 2 - one for the wrap around and one for the final end offset.
  298. offsets_size = (file_header.total_frames + 2) << 2;
  299. // Can the user_buffer_size handle the maximum case buffer?
  300. if ( user_buffer_size == max_buffer_size) {
  301. //
  302. // set the file buffer pointer,
  303. // Skip over the header information.
  304. // Read in the offsets.
  305. // Skip over the first frame.
  306. // Read in remaining frames.
  307. //
  308. sys_header->file_buffer = (char *)Add_Long_To_Pointer(delta_buffer,sys_header->largest_frame_size);
  309. Seek_File( fh, WSA_FILE_HEADER_SIZE, SEEK_SET);
  310. Read_File( fh, sys_header->file_buffer, offsets_size);
  311. Seek_File( fh, frame0_size + palette_adjust, SEEK_CUR);
  312. Read_File( fh, sys_header->file_buffer + offsets_size,
  313. file_buffer_size - offsets_size);
  314. //
  315. // Find out if there is an ending value for the last frame.
  316. // If there is not, then this animation will not be able to
  317. // loop back to the beginning.
  318. //
  319. if (Get_Resident_Frame_Offset( sys_header->file_buffer, sys_header->total_frames + 1))
  320. anim_flags |= WSA_RESIDENT;
  321. else
  322. anim_flags |= WSA_LINEAR_ONLY | WSA_RESIDENT;
  323. }
  324. else { // buffer cannot handle max_size of buffer
  325. if(Get_File_Frame_Offset( fh, sys_header->total_frames + 1, palette_adjust))
  326. anim_flags |= WSA_FILE;
  327. else
  328. anim_flags |= WSA_LINEAR_ONLY | WSA_FILE;
  329. ////
  330. sys_header->file_buffer = NULL;
  331. }
  332. // Figure where to back load frame 0 into the delta buffer.
  333. delta_back = (char *)Add_Long_To_Pointer(delta_buffer,
  334. sys_header->largest_frame_size - frame0_size);
  335. // Read the first frame into the delta buffer and uncompress it.
  336. // Then close it.
  337. Seek_File( fh, WSA_FILE_HEADER_SIZE + offsets_size + palette_adjust, SEEK_SET);
  338. Read_File( fh, delta_back, frame0_size);
  339. // We do not use the file handle when it is in RAM.
  340. if (anim_flags & WSA_RESIDENT) {
  341. sys_header -> file_handle = (short) -1;
  342. Close_File(fh);
  343. }
  344. else {
  345. sys_header -> file_handle = (short)fh;
  346. }
  347. LCW_Uncompress(delta_back, delta_buffer, sys_header->largest_frame_size);
  348. // Finally set the flags,
  349. sys_header->flags = (short)anim_flags;
  350. // return valid handle
  351. return( user_buffer );
  352. }
  353. /***************************************************************************
  354. * CLOSE_ANIMATION -- Close the animation, freeing the space if necessary. *
  355. * *
  356. * INPUT: void *handle to the animation data buffer *
  357. * *
  358. * OUTPUT: none *
  359. * *
  360. * WARNINGS: handle MUST have been returned by Open_Animation *
  361. * *
  362. * HISTORY: *
  363. * 11/23/1991 ML : Created. *
  364. *=========================================================================*/
  365. void __cdecl Close_Animation( void *handle )
  366. {
  367. SysAnimHeaderType *sys_header;
  368. // Assign our local system header pointer to the beginning of the handle space
  369. sys_header = (SysAnimHeaderType *) handle;
  370. // Close the WSA file in it was disk based.
  371. if (sys_header->flags & WSA_FILE) {
  372. Close_File(sys_header->file_handle);
  373. }
  374. // Check to see if the buffer was allocated OR the programmer provided the buffer
  375. if (handle && sys_header->flags & WSA_SYS_ALLOCATED) {
  376. Free(handle);
  377. }
  378. }
  379. /***************************************************************************
  380. * ANIMATE_FRAME -- Displays a frame of a given animation *
  381. * *
  382. * INPUT: void *handle to the animation. *
  383. * int frame_number wanted to be displayed *
  384. * int x_pixel position of left side of animation on page *
  385. * int y_pixel position of top of animation on page *
  386. * *
  387. * OUTPUT: BOOL if successfull or not. *
  388. * *
  389. * WARNINGS: *
  390. * *
  391. * HISTORY: *
  392. * 11/27/1991 SB : Created. *
  393. *=========================================================================*/
  394. //#pragma off (unreferenced)
  395. BOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,
  396. int frame_number, int x_pixel, int y_pixel,
  397. WSAType flags_and_prio, void *magic_cols, void *magic)
  398. {
  399. SysAnimHeaderType *sys_header; // fix up the void pointer past in.
  400. int curr_frame; // current frame we are on.
  401. int total_frames; // number of frames in anim.
  402. int distance; // distance to desired frame.
  403. int search_dir; // direcion to search for desired frame.
  404. int search_frames; // How many frames to search.
  405. int loop; // Just a loop varible.
  406. char *frame_buffer; // our destination.
  407. BOOL direct_to_dest; // are we going directly to the destination?
  408. int dest_width; // the width of the destination buffer or page.
  409. // Assign local pointer to the beginning of the buffer where the system information
  410. // resides
  411. sys_header = (SysAnimHeaderType *)handle;
  412. // Get the total number of frames
  413. total_frames = sys_header->total_frames;
  414. // Are the animation handle and the frame number valid?
  415. if (!handle || (total_frames <= frame_number)) {
  416. return FALSE;
  417. }
  418. if (view.Lock()!=TRUE) return (FALSE);
  419. // Decide if we are going to a page or a viewport (part of a buffer).
  420. dest_width = view.Get_Width() + view.Get_XAdd() + view.Get_Pitch();
  421. //
  422. // adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.
  423. //
  424. x_pixel += (short)sys_header->pixel_x;
  425. y_pixel += (short)sys_header->pixel_y;
  426. //
  427. // Check to see if we are using a buffer inside of the animation buffer or if
  428. // it is being drawn directly to the destination page or buffer.
  429. //
  430. if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
  431. // Get a pointer to the frame in animation buffer.
  432. frame_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));
  433. direct_to_dest = FALSE;
  434. }
  435. else {
  436. frame_buffer = (char *)view.Get_Offset();
  437. frame_buffer += (y_pixel * dest_width) + x_pixel;
  438. direct_to_dest = TRUE;
  439. }
  440. //
  441. // If current_frame is equal to tatal_frames, then no animations have taken place
  442. // so must uncompress frame 0 in delta buffer to the frame_buffer/page if it
  443. // exists.
  444. //
  445. if (sys_header->current_frame == total_frames) {
  446. // Call apply delta telling it wether to copy or to xor depending on if the
  447. // target is a page or a buffer.
  448. if (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {
  449. if (direct_to_dest) {
  450. // The last parameter says weather to copy or to XOR. If the
  451. // first frame is a DELTA, then it must be XOR'd. A TRUE is
  452. // copy while FALSE is XOR.
  453. Apply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,
  454. sys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,
  455. (sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);
  456. }
  457. else {
  458. Apply_XOR_Delta(frame_buffer, sys_header->delta_buffer);
  459. }
  460. }
  461. sys_header->current_frame = 0;
  462. }
  463. //
  464. // Get the current frame
  465. // If no looping aloud, are the trying to do it anyways?
  466. //
  467. curr_frame = sys_header->current_frame;
  468. #if (FALSE)
  469. // This is commented out since we will let them loop even though they should
  470. // not - it will be slower.
  471. if ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {
  472. view.Unlock();
  473. return FALSE;
  474. }
  475. #endif
  476. // Get absoulte distance from our current frame to the target frame
  477. distance = ABS(curr_frame - frame_number);
  478. // Assume we are searching right
  479. search_dir = 1;
  480. // Calculate the number of frames to search if we go right and wrap
  481. if (frame_number > curr_frame) {
  482. search_frames = total_frames - frame_number + curr_frame;
  483. // Is going right faster than going backwards?
  484. // Or are they trying to loop when the should not?
  485. if ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {
  486. search_dir = -1; // No, so go left
  487. }
  488. else {
  489. search_frames = distance;
  490. }
  491. }
  492. else {
  493. search_frames = total_frames - curr_frame + frame_number;
  494. // Is going right faster than going backwards?
  495. // Or are they trying to loop when the should not?
  496. if ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {
  497. search_dir = -1; // No, so go left
  498. search_frames = distance;
  499. }
  500. }
  501. // Take care of the case when we are searching right (possibly right)
  502. if (search_dir > 0) {
  503. for (loop = 0; loop < search_frames; loop++) {
  504. // Move the logical frame number ordinally right
  505. curr_frame += search_dir;
  506. Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
  507. // Adjust the current frame number, taking into consideration that we could
  508. // have wrapped
  509. if (curr_frame == total_frames) {
  510. curr_frame = 0;
  511. }
  512. }
  513. }
  514. else {
  515. for (loop = 0; loop < search_frames; loop++) {
  516. // If we are going backwards and we are on frame 0, the delta to get
  517. // to the last frame is the n + 1 delta (wrap delta)
  518. if (curr_frame == 0) {
  519. curr_frame = total_frames;
  520. }
  521. Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
  522. curr_frame += search_dir;
  523. }
  524. }
  525. sys_header->current_frame = (short)frame_number;
  526. // If we did this all in a hidden buffer, then copy it to the desired page or viewport.
  527. if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
  528. #if TRUE
  529. Buffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);
  530. #else
  531. int flags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;
  532. int pri = flags_and_prio & 0x00FF;
  533. Buffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,
  534. sys_header->pixel_height, 0, flags, frame_buffer, pri,
  535. magic_cols, magic);
  536. #endif
  537. }
  538. view.Unlock();
  539. return TRUE;
  540. }
  541. /***************************************************************************
  542. * ANIMATE_FRAME -- Displays a frame of a given animation *
  543. * *
  544. * INPUT: void *handle to the animation. *
  545. * int frame_number wanted to be displayed *
  546. * int x_pixel position of left side of animation on page *
  547. * int y_pixel position of top of animation on page *
  548. * *
  549. * OUTPUT: BOOL if successfull or not. *
  550. * *
  551. * WARNINGS: *
  552. * *
  553. * HISTORY: *
  554. * 11/27/1991 SB : Created. *
  555. *=========================================================================*/
  556. //#pragma argsused
  557. #ifdef cuts
  558. BOOL __cdecl Animate_Frame(void *handle, GraphicViewPortClass& view,
  559. int frame_number, int x_pixel, int y_pixel,
  560. WSAType flags_and_prio, void *magic_cols, void *magic)
  561. {
  562. SysAnimHeaderType *sys_header; // fix up the void pointer past in.
  563. int curr_frame; // current frame we are on.
  564. int total_frames; // number of frames in anim.
  565. int distance; // distance to desired frame.
  566. int search_dir; // direcion to search for desired frame.
  567. int search_frames; // How many frames to search.
  568. int loop; // Just a loop varible.
  569. char *frame_buffer; // our destination.
  570. BOOL direct_to_dest; // are we going directly to the destination?
  571. int dest_width; // the width of the destination buffer or page.
  572. // Assign local pointer to the beginning of the buffer where the system information
  573. // resides
  574. sys_header = (SysAnimHeaderType *)handle;
  575. // Get the total number of frames
  576. total_frames = sys_header->total_frames;
  577. // Are the animation handle and the frame number valid?
  578. if (!handle || (total_frames <= frame_number)) {
  579. return FALSE;
  580. }
  581. // Decide if we are going to a page or a viewport (part of a buffer).
  582. dest_width = view.Get_Width() + view.Get_XAdd();
  583. //
  584. // adjust x_pixel and y_pixel by system pixel_x and pixel_y respectively.
  585. //
  586. x_pixel += (short)sys_header->pixel_x;
  587. y_pixel += (short)sys_header->pixel_y;
  588. //
  589. // Check to see if we are using a buffer inside of the animation buffer or if
  590. // it is being drawn directly to the destination page or buffer.
  591. //
  592. if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
  593. // Get a pointer to the frame in animation buffer.
  594. frame_buffer = (char *)Add_Long_To_Pointer(sys_header, sizeof(SysAnimHeaderType));
  595. direct_to_dest = FALSE;
  596. }
  597. else {
  598. frame_buffer = (char *)view.Get_Offset();
  599. frame_buffer += (y_pixel * dest_width) + x_pixel;
  600. direct_to_dest = TRUE;
  601. }
  602. //
  603. // If current_frame is equal to tatal_frames, then no animations have taken place
  604. // so must uncompress frame 0 in delta buffer to the frame_buffer/page if it
  605. // exists.
  606. //
  607. if (sys_header->current_frame == total_frames) {
  608. // Call apply delta telling it wether to copy or to xor depending on if the
  609. // target is a page or a buffer.
  610. if (!(sys_header->flags & WSA_FRAME_0_ON_PAGE)) {
  611. if (direct_to_dest) {
  612. // The last parameter says weather to copy or to XOR. If the
  613. // first frame is a DELTA, then it must be XOR'd. A TRUE is
  614. // copy while FALSE is XOR.
  615. Apply_XOR_Delta_To_Page_Or_Viewport(frame_buffer, sys_header->delta_buffer,
  616. sys_header->pixel_width, dest_width, //dest_width - sys_header->pixel_width,
  617. (sys_header->flags & WSA_FRAME_0_IS_DELTA)? DO_XOR : DO_COPY);
  618. }
  619. else {
  620. Apply_XOR_Delta(frame_buffer, sys_header->delta_buffer);
  621. }
  622. }
  623. sys_header->current_frame = 0;
  624. }
  625. //
  626. // Get the current frame
  627. // If no looping aloud, are the trying to do it anyways?
  628. //
  629. curr_frame = sys_header->current_frame;
  630. #if (FALSE)
  631. // This is commented out since we will let them loop even though they should
  632. // not - it will be slower.
  633. if ( (sys_header->flags & WSA_LINEAR_ONLY) && (frame_number < cur_frame) ) {
  634. return FALSE;
  635. }
  636. #endif
  637. // Get absoulte distance from our current frame to the target frame
  638. distance = ABS(curr_frame - frame_number);
  639. // Assume we are searching right
  640. search_dir = 1;
  641. // Calculate the number of frames to search if we go right and wrap
  642. if (frame_number > curr_frame) {
  643. search_frames = total_frames - frame_number + curr_frame;
  644. // Is going right faster than going backwards?
  645. // Or are they trying to loop when the should not?
  646. if ((search_frames < distance) && !(sys_header->flags & WSA_LINEAR_ONLY)) {
  647. search_dir = -1; // No, so go left
  648. }
  649. else {
  650. search_frames = distance;
  651. }
  652. }
  653. else {
  654. search_frames = total_frames - curr_frame + frame_number;
  655. // Is going right faster than going backwards?
  656. // Or are they trying to loop when the should not?
  657. if ((search_frames >= distance) || (sys_header->flags & WSA_LINEAR_ONLY)) {
  658. search_dir = -1; // No, so go left
  659. search_frames = distance;
  660. }
  661. }
  662. // Take care of the case when we are searching right (possibly right)
  663. if (search_dir > 0) {
  664. for (loop = 0; loop < search_frames; loop++) {
  665. // Move the logical frame number ordinally right
  666. curr_frame += search_dir;
  667. Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
  668. // Adjust the current frame number, taking into consideration that we could
  669. // have wrapped
  670. if (curr_frame == total_frames) {
  671. curr_frame = 0;
  672. }
  673. }
  674. }
  675. else {
  676. for (loop = 0; loop < search_frames; loop++) {
  677. // If we are going backwards and we are on frame 0, the delta to get
  678. // to the last frame is the n + 1 delta (wrap delta)
  679. if (curr_frame == 0) {
  680. curr_frame = total_frames;
  681. }
  682. Apply_Delta(sys_header, curr_frame, frame_buffer, dest_width);
  683. curr_frame += search_dir;
  684. }
  685. }
  686. sys_header->current_frame = frame_number;
  687. // If we did this all in a hidden buffer, then copy it to the desired page or viewport.
  688. if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
  689. #if TRUE
  690. Buffer_To_Page(x_pixel, y_pixel, sys_header->pixel_width, sys_header->pixel_height, frame_buffer, view);
  691. #else
  692. int flags = ((unsigned short)flags_and_prio & 0xFF00u) >> 12u;
  693. int pri = flags_and_prio & 0x00FF;
  694. Buffer_Bitblit_To_LogicPage(x_pixel, y_pixel, sys_header->pixel_width,
  695. sys_header->pixel_height, 0, flags, frame_buffer, pri,
  696. magic_cols, magic);
  697. #endif
  698. }
  699. return TRUE;
  700. }
  701. #endif
  702. /***************************************************************************
  703. * ANIMATE_FRAME_COUNT -- Return Number of frames in an animation. *
  704. * *
  705. * INPUT: void *handle to the animation. *
  706. * *
  707. * OUTPUT: int number of frames in animation. *
  708. * *
  709. * WARNINGS: *
  710. * *
  711. * HISTORY: *
  712. * 12/05/1991 SB : Created. *
  713. *=========================================================================*/
  714. int __cdecl Get_Animation_Frame_Count(void *handle)
  715. {
  716. SysAnimHeaderType *sys_header;
  717. if (!handle) {
  718. return FALSE;
  719. }
  720. sys_header = (SysAnimHeaderType *) handle;
  721. return((short)sys_header->total_frames);
  722. }
  723. /***************************************************************************
  724. * GET_ANIM_X -- Gets the x from an animation *
  725. * *
  726. * *
  727. * INPUT: void * to the animation that we are processing *
  728. * *
  729. * OUTPUT: int the x of the animation we are processing *
  730. * *
  731. * WARNINGS: *
  732. * *
  733. * HISTORY: *
  734. * 07/03/1992 DRD : Created. *
  735. *=========================================================================*/
  736. int __cdecl Get_Animation_X(void const *handle)
  737. {
  738. SysAnimHeaderType const *sys_header;
  739. if (!handle) {
  740. return FALSE;
  741. }
  742. sys_header = (SysAnimHeaderType *) handle;
  743. return(sys_header->pixel_x);
  744. }
  745. /***************************************************************************
  746. * GET_ANIM_Y -- Gets the y from an animation *
  747. * *
  748. * *
  749. * INPUT: void * to the animation that we are processing *
  750. * *
  751. * OUTPUT: int the y of the animation we are processing *
  752. * *
  753. * WARNINGS: *
  754. * *
  755. * HISTORY: *
  756. * 10/14/1992 PWG : Created. *
  757. *=========================================================================*/
  758. int __cdecl Get_Animation_Y(void const *handle)
  759. {
  760. SysAnimHeaderType const *sys_header;
  761. if (!handle) {
  762. return FALSE;
  763. }
  764. sys_header = (SysAnimHeaderType *) handle;
  765. return(sys_header->pixel_y);
  766. }
  767. /***************************************************************************
  768. * GET_ANIM_WIDTH -- Gets the width from an animation *
  769. * *
  770. * *
  771. * INPUT: void * to the animation that we are processing *
  772. * *
  773. * OUTPUT: int the width of the animation we are processing *
  774. * *
  775. * WARNINGS: *
  776. * *
  777. * HISTORY: *
  778. * 10/14/1992 PWG : Created. *
  779. *=========================================================================*/
  780. int __cdecl Get_Animation_Width(void const *handle)
  781. {
  782. SysAnimHeaderType const *sys_header;
  783. if (!handle) {
  784. return FALSE;
  785. }
  786. sys_header = (SysAnimHeaderType *) handle;
  787. return(sys_header->pixel_width);
  788. }
  789. /***************************************************************************
  790. * GET_ANIM_HEIGHT -- The height of the animation we are processing *
  791. * *
  792. * INPUT: void * to the animation that we are processing *
  793. * *
  794. * OUTPUT: int the height of the animation we are processing *
  795. * *
  796. * HISTORY: *
  797. * 10/14/1992 PWG : Created. *
  798. *=========================================================================*/
  799. int __cdecl Get_Animation_Height(void const *handle)
  800. {
  801. SysAnimHeaderType const *sys_header;
  802. if (!handle) {
  803. return FALSE;
  804. }
  805. sys_header = (SysAnimHeaderType *) handle;
  806. return(sys_header->pixel_height);
  807. }
  808. /***************************************************************************
  809. * GET_ANIM_PALETTE -- Returns true if the anim had an attached palette *
  810. * *
  811. * INPUT: void * to the animation that we are processing *
  812. * *
  813. * OUTPUT: int True if the animation has a set palette. False if the *
  814. * animation does not. *
  815. * *
  816. * HISTORY: *
  817. * 10/14/1992 PWG : Created. *
  818. *=========================================================================*/
  819. int __cdecl Get_Animation_Palette(void const *handle)
  820. {
  821. SysAnimHeaderType const *sys_header;
  822. if (!handle) {
  823. return FALSE;
  824. }
  825. sys_header = (SysAnimHeaderType *) handle;
  826. return(sys_header->flags & WSA_PALETTE_PRESENT);
  827. }
  828. /***************************************************************************
  829. * GET_ANIMATION_SIZE -- Return the amount of memory the animation is using*
  830. * *
  831. * *
  832. * INPUT: void * to the animation that we are processing *
  833. * *
  834. * OUTPUT: unsigned long number of byte used by animation. *
  835. * *
  836. * WARNINGS: *
  837. * *
  838. * HISTORY: *
  839. * 05/23/1994 SKB : Created. *
  840. *=========================================================================*/
  841. unsigned long __cdecl Get_Animation_Size(void const *handle)
  842. {
  843. SysAnimHeaderType const *sys_header;
  844. if (!handle) {
  845. return FALSE;
  846. }
  847. sys_header = (SysAnimHeaderType *) handle;
  848. return(sys_header->anim_mem_size);
  849. }
  850. /* :::::::::::::::::::::::::::: PRIVATE FUNCTIONS :::::::::::::::::::::::::::::: */
  851. /***************************************************************************
  852. * GET_RESIDENT_FRAME_OFFSET -- Gets frame offset of animate file in RAM *
  853. * *
  854. * INPUT: char *file_buffer in RAM of animation file. *
  855. * int frame number that we need the offset of. *
  856. * *
  857. * OUTPUT: int offset of frame requested. *
  858. * *
  859. * WARNINGS: *
  860. * *
  861. * HISTORY: *
  862. * 11/26/1991 SB : Created. *
  863. *=========================================================================*/
  864. PRIVATE unsigned long Get_Resident_Frame_Offset( char *file_buffer, int frame )
  865. {
  866. unsigned long frame0_size;
  867. unsigned long *lptr;
  868. // If there is a frame 0, the calculate its size.
  869. lptr = (unsigned long *) file_buffer;
  870. if (*lptr) {
  871. frame0_size = lptr[1] - *lptr;
  872. } else {
  873. frame0_size = 0;
  874. }
  875. // Return the offset into RAM for the frame.
  876. lptr += frame;
  877. if (*lptr)
  878. return (*lptr - (frame0_size + WSA_FILE_HEADER_SIZE));
  879. else
  880. return (0L);
  881. }
  882. /***************************************************************************
  883. * GET_FILE_FRAME_OFFSET -- Get offset of a delta frame from animate file. *
  884. * *
  885. * INPUT: int file_handle of animation file. *
  886. * int frame number that we need the offset of. *
  887. * *
  888. * OUTPUT: int offset of frame requested. *
  889. * *
  890. * WARNINGS: *
  891. * *
  892. * HISTORY: *
  893. * 11/26/1991 SB : Created. *
  894. *=========================================================================*/
  895. PRIVATE unsigned long Get_File_Frame_Offset( int file_handle, int frame, int palette_adjust)
  896. {
  897. unsigned long offset;
  898. Seek_File(file_handle, (frame << 2) + WSA_FILE_HEADER_SIZE, SEEK_SET);
  899. if (Read_File(file_handle, (char *) &offset, sizeof(unsigned long)) != sizeof(unsigned long)) {
  900. offset = 0L;
  901. }
  902. offset += palette_adjust;
  903. return( offset );
  904. }
  905. /***************************************************************************
  906. * APPLY_DELTA -- Copies frame into delta buffer, then applies to target *
  907. * *
  908. * INPUT: SysAnimHeaderType *sys_header - pointer to animation buffer.*
  909. * int curr_frame - frame to put into target buffer. *
  910. * *
  911. * OUTPUT: BOOL - Return wether or not it worked. *
  912. * *
  913. * WARNINGS: *
  914. * *
  915. * HISTORY: *
  916. * 11/26/1991 SB : Created. *
  917. *=========================================================================*/
  918. PRIVATE BOOL Apply_Delta(SysAnimHeaderType *sys_header, int curr_frame, char *dest_ptr, int dest_w)
  919. {
  920. char *data_ptr, *delta_back;
  921. int file_handle, palette_adjust;
  922. unsigned long frame_data_size, frame_offset;
  923. palette_adjust = ((sys_header->flags & WSA_PALETTE_PRESENT) ? 768 : 0);
  924. delta_back = sys_header->delta_buffer;
  925. if (sys_header->flags & WSA_RESIDENT) {
  926. // Get offset of the given frame in the resident file
  927. // Get the size of the frame <- (frame+1 offset) - (offset)
  928. // Point at the delta data
  929. // figure offset to load data into end of delta buffer
  930. // copy it into buffer
  931. frame_offset = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame);
  932. frame_data_size = Get_Resident_Frame_Offset(sys_header->file_buffer, curr_frame + 1) - frame_offset;
  933. data_ptr = (char *)Add_Long_To_Pointer(sys_header->file_buffer, frame_offset);
  934. delta_back = (char *)Add_Long_To_Pointer(delta_back,
  935. sys_header->largest_frame_size - frame_data_size);
  936. Mem_Copy( data_ptr, delta_back, frame_data_size );
  937. } else if (sys_header -> flags & WSA_FILE) {
  938. // Open up file because not file not in RAM.
  939. // Get offset of the given frame in the file on disk
  940. // Get the size of the frame <- (frame+1 offset) - (offset)
  941. // Return if Get_.._offset() failed. -- need error handling????
  942. // Seek to delta data.
  943. // figure offset to load data into end of delta buffer
  944. // Read it into buffer -- Return if correct amount not read.-- errors??
  945. file_handle = sys_header->file_handle;
  946. Seek_File(file_handle, 0L, SEEK_SET);
  947. frame_offset = Get_File_Frame_Offset(file_handle, curr_frame, palette_adjust);
  948. frame_data_size = Get_File_Frame_Offset(file_handle, curr_frame + 1, palette_adjust) - frame_offset;
  949. if (!frame_offset || !frame_data_size) {
  950. return(FALSE);
  951. }
  952. Seek_File(file_handle, frame_offset, SEEK_SET);
  953. delta_back = (char *)Add_Long_To_Pointer(delta_back, sys_header->largest_frame_size - frame_data_size);
  954. if (Read_File(file_handle, delta_back, frame_data_size) != frame_data_size) {
  955. return(FALSE);
  956. }
  957. }
  958. // Uncompress data at end of delta buffer to the beginning of delta buffer.
  959. // Find start of target buffer.
  960. // Apply the XOR delta.
  961. LCW_Uncompress(delta_back, sys_header->delta_buffer, sys_header->largest_frame_size);
  962. if (sys_header->flags & WSA_TARGET_IN_BUFFER) {
  963. Apply_XOR_Delta(dest_ptr, sys_header->delta_buffer);
  964. }
  965. else {
  966. Apply_XOR_Delta_To_Page_Or_Viewport(dest_ptr, sys_header->delta_buffer,
  967. sys_header->pixel_width, dest_w, DO_XOR);
  968. }
  969. return(TRUE);
  970. }