WSA.CPP 45 KB

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