TASK.CPP 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  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. /****************************************************************************
  19. *
  20. * C O N F I D E N T I A L -- W E S T W O O D S T U D I O S
  21. *
  22. *----------------------------------------------------------------------------
  23. *
  24. * PROJECT
  25. * VQA player library. (32-Bit protected mode)
  26. *
  27. * FILE
  28. * task.c
  29. *
  30. * DESCRIPTION
  31. * Loading and drawing delegation
  32. *
  33. * PROGRAMMER
  34. * Bill Randolph
  35. * Denzil E. Long, Jr.
  36. *
  37. * DATE
  38. * July 25, 1995
  39. *
  40. *----------------------------------------------------------------------------
  41. *
  42. * PUBLIC
  43. * VQA_Alloc - Allocate a VQAHandle to use.
  44. * VQA_Free - Free a VQAHandle.
  45. * VQA_Init - Initialize the VQAHandle IO.
  46. * VQA_Play - Play the VQA movie.
  47. * VQA_SetStop - Set the frame the player should stop on.
  48. * VQA_GetInfo - Get VQA movie information.
  49. * VQA_GetStats - Get VQA movie statistics.
  50. * VQA_Version - Get VQA library version number.
  51. * VQA_IDString - Get the VQA player library's ID string.
  52. *
  53. * PRIVATE
  54. * VQA_IO_Task - Loader task for multitasking.
  55. * VQA_Rendering_Task - Drawer task for multitasking.
  56. * User_Update - Page flip routine called by the task interrupt.
  57. *
  58. ****************************************************************************/
  59. #include <stdio.h>
  60. #include <malloc.h>
  61. #include <dos.h>
  62. #include <mem.h>
  63. #include <conio.h>
  64. #include <sys\timeb.h>
  65. #include <vqm32\all.h>
  66. #include "vqaplayp.h"
  67. #include <vqm32\font.h>
  68. /*---------------------------------------------------------------------------
  69. * PRIVATE DECLARATIONS
  70. *-------------------------------------------------------------------------*/
  71. /* Externals */
  72. #ifdef __cplusplus
  73. extern "C" {
  74. #endif
  75. extern int __cdecl Check_Key(void);
  76. extern int __cdecl Get_Key(void);
  77. #ifdef __cplusplus
  78. }
  79. #endif
  80. /****************************************************************************
  81. *
  82. * NAME
  83. * VQA_Alloc - Allocate a VQAHandle to use.
  84. *
  85. * SYNOPSIS
  86. * VQAHandle = VQA_Alloc()
  87. *
  88. * VQAHandle *VQA_Alloc(void);
  89. *
  90. * FUNCTION
  91. * Obtain a VQAHandle. This handle is used by most VQA library functions,
  92. * and contains the current position in the file. This is the only legal
  93. * way to obtain a VQAHandle.
  94. *
  95. * INPUTS
  96. * NONE
  97. *
  98. * RESULT
  99. * VQA - Handle of a VQA.
  100. *
  101. ****************************************************************************/
  102. VQAHandle *VQA_Alloc(void)
  103. {
  104. VQAHandleP *vqa;
  105. if ((vqa = (VQAHandleP *)malloc(sizeof(VQAHandleP))) != NULL) {
  106. memset(vqa, 0, sizeof(VQAHandleP));
  107. }
  108. return ((VQAHandle *)vqa);
  109. }
  110. /****************************************************************************
  111. *
  112. * NAME
  113. * VQA_Free - Free a VQAHandle.
  114. *
  115. * SYNOPSIS
  116. * VQA_Free(VQA)
  117. *
  118. * void VQA_Free(VQAHandle *);
  119. *
  120. * FUNCTION
  121. * Dispose of a VQAHandle. This is the only legal way to dispose of a
  122. * VQAHandle.
  123. *
  124. * INPUTS
  125. * VQA - Pointer to VQAHandle to dispose of.
  126. *
  127. * RESULT
  128. * NONE
  129. *
  130. ****************************************************************************/
  131. void VQA_Free(VQAHandle *vqa)
  132. {
  133. if (vqa) free(vqa);
  134. }
  135. /****************************************************************************
  136. *
  137. * NAME
  138. * VQA_Init - Initialize the VQAHandle IO handler.
  139. *
  140. * SYNOPSIS
  141. * VQA_Init(VQA, IOHandler)
  142. *
  143. * void VQA_Init(VQAHandle *, IOHandler *);
  144. *
  145. * FUNCTION
  146. * Initialize the specified VQAHandle IO with the client provided custom
  147. * IO handler.
  148. *
  149. * INPUTS
  150. * VQA - Pointer to VQAHandle to initialize.
  151. * IOHandler - Pointer to custom file I/O handler function.
  152. *
  153. * RESULT
  154. * NONE
  155. *
  156. ****************************************************************************/
  157. void VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,
  158. void *buffer, long nbytes))
  159. {
  160. ((VQAHandleP *)vqa)->IOHandler = iohandler;
  161. }
  162. /****************************************************************************
  163. *
  164. * NAME
  165. * VQA_Reset - Reset the VQAHandle.
  166. *
  167. * SYNOPSIS
  168. * VQA_Reset(VQA)
  169. *
  170. * void VQA_Reset(VQAHandle *);
  171. *
  172. * FUNCTION
  173. *
  174. * INPUTS
  175. * VQA - VQAHandle to reset.
  176. *
  177. * RESULT
  178. * NONE
  179. *
  180. ****************************************************************************/
  181. void VQA_Reset(VQAHandle *vqa)
  182. {
  183. VQAData *vqabuf;
  184. /* Dereference data members for quick access */
  185. vqabuf = ((VQAHandleP *)vqa)->VQABuf;
  186. vqabuf->Flags = 0;
  187. vqabuf->LoadedFrames = 0;
  188. vqabuf->DrawnFrames = 0;
  189. vqabuf->StartTime = 0;
  190. vqabuf->EndTime = 0;
  191. }
  192. int VQAMovieDone;
  193. /****************************************************************************
  194. *
  195. * NAME
  196. * VQA_Play - Play the VQA movie.
  197. *
  198. * SYNOPSIS
  199. * Error = VQA_Play(VQA, Mode)
  200. *
  201. * long VQA_Play(VQAHandle *, long);
  202. *
  203. * FUNCTION
  204. * Playback the movie associated with the specified VQAHandle.
  205. *
  206. * INPUTS
  207. * VQA - Pointer to handle of movie to play.
  208. * Mode - Playback mode.
  209. * VQAMODE_RUN - Run the movie until completion.
  210. * VQAMODE_WALK - Walk the movie frame by frame.
  211. * VQAMODE_PAUSE - Pause the movie.
  212. * VQAMODE_STOP - Stop the movie (Shutdown).
  213. *
  214. * RESULT
  215. * Error - 0 if successful, or error code.
  216. *
  217. ****************************************************************************/
  218. long VQA_Play(VQAHandle *vqa, long mode)
  219. {
  220. VQAData *vqabuf;
  221. VQAConfig *config;
  222. VQADrawer *drawer;
  223. long rc;
  224. long i;
  225. long key;
  226. #ifdef WIN32
  227. unsigned char *pal;
  228. long palsize;
  229. long slowpal;
  230. VQAFrameNode *curframe;
  231. int setpalette;
  232. #endif //WIN32
  233. #ifdef WIN32
  234. /*
  235. ** Save the process priority level then bump it up
  236. */
  237. DWORD process_priority = GetPriorityClass(GetCurrentProcess());
  238. SetPriorityClass (GetCurrentProcess() , HIGH_PRIORITY_CLASS);
  239. #endif //WIN32
  240. /* Dereference commonly used data members for quick access. */
  241. vqabuf = ((VQAHandleP *)vqa)->VQABuf;
  242. drawer = &vqabuf->Drawer;
  243. config = &((VQAHandleP *)vqa)->Config;
  244. /* One time player priming. */
  245. if (!(vqabuf->Flags & VQADATF_PRIMED)) {
  246. /* Init the Drawer's configuration */
  247. VQA_Configure_Drawer((VQAHandleP *)vqa);
  248. /* If audio enabled & loaded, start playing */
  249. #if(VQAAUDIO_ON)
  250. if ((config->OptionFlags & VQAOPTF_AUDIO) && vqabuf->Audio.IsLoaded[0]) {
  251. VQA_StartAudio((VQAHandleP *)vqa);
  252. }
  253. #endif
  254. /* Initialize the timer */
  255. i = ((vqabuf->Drawer.CurFrame->FrameNum * VQA_TIMETICKS)
  256. / config->DrawRate);
  257. VQA_SetTimer((VQAHandleP *)vqa, i, config->TimerMethod);
  258. vqabuf->StartTime = VQA_GetTime((VQAHandleP *)vqa);
  259. /* Set up the Mono screen */
  260. #if(VQAMONO_ON)
  261. if (config->OptionFlags & VQAOPTF_MONO) {
  262. VQA_InitMono((VQAHandleP *)vqa);
  263. }
  264. #endif
  265. /* Priming is complete. */
  266. vqabuf->Flags |= VQADATF_PRIMED;
  267. }
  268. /* Main Player Loop */
  269. switch (mode) {
  270. case VQAMODE_PAUSE:
  271. if ((vqabuf->Flags & VQADATF_PAUSED) == 0) {
  272. vqabuf->Flags |= VQADATF_PAUSED;
  273. vqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);
  274. /* Stop the audio while the movie is paused. */
  275. #if(VQAAUDIO_ON)
  276. if (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {
  277. VQA_StopAudio((VQAHandleP *)vqa);
  278. }
  279. #endif
  280. }
  281. rc = VQAERR_PAUSED;
  282. break;
  283. case VQAMODE_RUN:
  284. case VQAMODE_WALK:
  285. default:
  286. /* Start up the movie if is it currently paused. */
  287. if (vqabuf->Flags & VQADATF_PAUSED) {
  288. vqabuf->Flags &= ~VQADATF_PAUSED;
  289. /* Start the audio if it was previously on. */
  290. #if(VQAAUDIO_ON)
  291. if (config->OptionFlags & VQAOPTF_AUDIO) {
  292. if (VQA_StartAudio((VQAHandleP *)vqa) != 0){
  293. /* Stop audio, if it's playing. */
  294. VQA_StopAudio((VQAHandleP *)vqa);
  295. #ifdef WIN32
  296. /*
  297. ** Restore the process priority level
  298. */
  299. SetPriorityClass (GetCurrentProcess() , process_priority);
  300. #endif //WIN32
  301. return (VQAERR_EOF);
  302. }
  303. }
  304. #endif
  305. VQA_SetTimer((VQAHandleP *)vqa, vqabuf->EndTime, config->TimerMethod);
  306. }
  307. /* Load, Draw, Load, Draw, Load, Draw ... */
  308. while ((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))
  309. != (VQADATF_DDONE|VQADATF_LDONE)) {
  310. /* Load a frame */
  311. if (!(vqabuf->Flags & VQADATF_LDONE)) {
  312. if ((rc = VQA_LoadFrame(vqa)) == 0) {
  313. vqabuf->LoadedFrames++;
  314. }
  315. else {
  316. if ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {
  317. vqabuf->Flags |= VQADATF_LDONE;
  318. rc = 0;
  319. }
  320. }
  321. }else{
  322. VQAMovieDone++;
  323. }
  324. /* Draw a frame */
  325. if ((config->DrawFlags & VQACFGF_NODRAW) == 0) {
  326. if ((rc = (*(vqabuf->Draw_Frame))(vqa)) == 0) {
  327. vqabuf->DrawnFrames++;
  328. rc = vqabuf->Drawer.LastFrameNum;
  329. #ifdef WIN32never
  330. curframe = drawer->CurFrame;
  331. pal = curframe->Palette;
  332. palsize = curframe->PaletteSize;
  333. slowpal = (config->OptionFlags & VQAOPTF_SLOWPAL) ? 1 : 0;
  334. if ((curframe->Flags & VQAFRMF_PALETTE)
  335. || (drawer->Flags & VQADRWF_SETPAL)) {
  336. setpalette = TRUE;
  337. }else{
  338. setpalette = FALSE;
  339. }
  340. #endif
  341. if (User_Update(vqa)) {
  342. vqabuf->Flags |= (VQADATF_DDONE|VQADATF_LDONE);
  343. }
  344. #ifdef WIN32never
  345. /*
  346. ** Set the palette if neccessary
  347. */
  348. if (setpalette) {
  349. SetPalette(pal, palsize, slowpal);
  350. curframe->Flags &= ~VQAFRMF_PALETTE;
  351. drawer->Flags &= ~VQADRWF_SETPAL;
  352. }
  353. #endif //WIN32
  354. }else {
  355. if (rc==VQAERR_EOF) break;
  356. if ((vqabuf->Flags & VQADATF_LDONE) && (rc == VQAERR_NOBUFFER)) {
  357. vqabuf->Flags |= VQADATF_DDONE;
  358. }
  359. }
  360. } else {
  361. vqabuf->Flags |= VQADATF_DDONE;
  362. drawer->CurFrame->Flags = 0L;
  363. drawer->CurFrame = drawer->CurFrame->Next;
  364. }
  365. /* Update Mono output */
  366. #if(VQAMONO_ON)
  367. if (config->OptionFlags & VQAOPTF_MONO) {
  368. VQA_UpdateMono((VQAHandleP *)vqa);
  369. }
  370. #endif
  371. if (mode == VQAMODE_WALK) {
  372. break;
  373. }
  374. #if(VQASTANDALONE)
  375. else {
  376. /* Do single-stepping check. */
  377. if (config->OptionFlags & VQAOPTF_STEP) {
  378. while ((key = Check_Key()) == 0);
  379. Get_Key();
  380. /* Escape key still quits. */
  381. if (key == 27) {
  382. break;
  383. }
  384. }
  385. /* Check for ESC */
  386. if ((key = Check_Key()) != 0) {
  387. mode = VQAMODE_STOP;
  388. break;
  389. }
  390. }
  391. #endif
  392. }
  393. break;
  394. }
  395. /* If the movie is finished or we are requested to stop then shutdown. */
  396. if (((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))
  397. == (VQADATF_DDONE|VQADATF_LDONE)) || (mode == VQAMODE_STOP)) {
  398. /* Record the end time; must be done before stopping audio, since we're
  399. * getting the elapsed time from the audio DMA position.
  400. */
  401. vqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);
  402. /* Movie is finished. */
  403. rc = VQAERR_EOF;
  404. }
  405. /* Stop audio, if it's playing. */
  406. #if(VQAAUDIO_ON)
  407. if (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {
  408. VQA_StopAudio((VQAHandleP *)vqa);
  409. }
  410. #endif
  411. #ifdef WIN32
  412. /*
  413. ** Restore the process priority level
  414. */
  415. SetPriorityClass (GetCurrentProcess() , process_priority);
  416. #endif //WIN32
  417. return (rc);
  418. }
  419. /****************************************************************************
  420. *
  421. * NAME
  422. * VQA_SetStop - Set the frame the player should stop on.
  423. *
  424. * SYNOPSIS
  425. * OldStop = VQA_SetStop(VQA, Frame)
  426. *
  427. * long = VQA_SetStop(VQAHandle *, long);
  428. *
  429. * FUNCTION
  430. * Set the frame that the player should stop on. This function will only
  431. * work on movies that are already open.
  432. *
  433. * INPUTS
  434. * VQA - VQAHandle of movie to set the stop frame for.
  435. * Frame - Frame number to stop on.
  436. *
  437. * RESULT
  438. * OldStop - Previous stop frame. (-1 = invalid stop frame)
  439. *
  440. ****************************************************************************/
  441. long VQA_SetStop(VQAHandle *vqa, long stop)
  442. {
  443. long oldstop = -1;
  444. VQAHeader *header;
  445. /* Get a local pointer to the header. */
  446. header = &((VQAHandleP *)vqa)->Header;
  447. if ((stop > 0) && (header->Frames >= stop)) {
  448. oldstop = header->Frames;
  449. header->Frames = stop;
  450. }
  451. return (oldstop);
  452. }
  453. /****************************************************************************
  454. *
  455. * NAME
  456. * VQA_GetInfo - Get VQA movie information.
  457. *
  458. * SYNOPSIS
  459. * VQA_GetInfo(VQA, Info)
  460. *
  461. * void VQA_GetInfo(VQAHandle *, VQAInfo *);
  462. *
  463. * FUNCTION
  464. * Retrieve information about the opened movie.
  465. *
  466. * INPUTS
  467. * VQA - Pointer to VQAHandle of opened movie.
  468. * Info - Pointer to VQAInfo structure to fill.
  469. *
  470. * RESULT
  471. * NONE
  472. *
  473. ****************************************************************************/
  474. void VQA_GetInfo(VQAHandle *vqa, VQAInfo *info)
  475. {
  476. VQAHeader *header;
  477. /* Dereference header structure. */
  478. header = &((VQAHandleP *)vqa)->Header;
  479. info->NumFrames = header->Frames;
  480. info->ImageHeight = header->ImageHeight;
  481. info->ImageWidth = header->ImageWidth;
  482. info->ImageBuf = ((VQAHandleP *)vqa)->VQABuf->Drawer.ImageBuf;
  483. }
  484. /****************************************************************************
  485. *
  486. * NAME
  487. * VQA_GetStats - Get VQA movie statistics.
  488. *
  489. * SYNOPSIS
  490. * VQA_GetStats(VQA, Stats)
  491. *
  492. * void VQA_GetStats(VQAHandle *, VQAStatistics *);
  493. *
  494. * FUNCTION
  495. * Retrieve the statistics for the VQA movie.
  496. *
  497. * INPUTS
  498. * VQA - Handle of VQA movie to get statistics for.
  499. * Stats - Pointer to VQAStatistics to fill.
  500. *
  501. * RESULT
  502. * NONE
  503. *
  504. ****************************************************************************/
  505. void VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats)
  506. {
  507. VQAData *vqabuf;
  508. /* Dereference VQAData structure from VQAHandle */
  509. vqabuf = ((VQAHandleP *)vqa)->VQABuf;
  510. stats->MemUsed = vqabuf->MemUsed;
  511. stats->StartTime = vqabuf->StartTime;
  512. stats->EndTime = vqabuf->EndTime;
  513. stats->FramesLoaded = vqabuf->LoadedFrames;
  514. stats->FramesDrawn = vqabuf->DrawnFrames;
  515. stats->FramesSkipped = vqabuf->Drawer.NumSkipped;
  516. stats->MaxFrameSize = vqabuf->Loader.MaxFrameSize;
  517. #if(VQAAUDIO_ON)
  518. stats->SamplesPlayed = vqabuf->Audio.SamplesPlayed;
  519. #else
  520. stats->SamplesPlayed = 0;
  521. #endif
  522. }
  523. /****************************************************************************
  524. *
  525. * NAME
  526. * VQA_Version - Get VQA library version number.
  527. *
  528. * SYNOPSIS
  529. * Version = VQA_Version()
  530. *
  531. * char *VQA_Version(void);
  532. *
  533. * FUNCTION
  534. * Return the version of the VQA player library.
  535. *
  536. * INPUTS
  537. * NONE
  538. *
  539. * RESULT
  540. * Version - Pointer to version number string.
  541. *
  542. ****************************************************************************/
  543. char *VQA_Version(void)
  544. {
  545. return(VQA_VERSION);
  546. }
  547. /****************************************************************************
  548. *
  549. * NAME
  550. * VQA_IDString - Get the VQA player library's ID string.
  551. *
  552. * SYNOPSIS
  553. * IDString = VQA_IDString()
  554. *
  555. * char *VQA_IDString(void);
  556. *
  557. * FUNCTION
  558. * Return the ID string of this VQA player library.
  559. *
  560. * INPUTS
  561. * NONE
  562. *
  563. * RESULT
  564. * IDString - Pointer to ID string.
  565. *
  566. ****************************************************************************/
  567. char *VQA_IDString(void)
  568. {
  569. return (VQA_IDSTRING);
  570. }
  571. /****************************************************************************
  572. *
  573. * NAME
  574. * User_Update - Page flip routine called by the task interrupt.
  575. *
  576. * SYNOPSIS
  577. * User_Update(VQA)
  578. *
  579. * long User_Update(VQAHandle *);
  580. *
  581. * FUNCTION
  582. *
  583. * INPUTS
  584. * VQA - Handle of VQA movie.
  585. *
  586. * RESULT
  587. * NONE
  588. *
  589. ****************************************************************************/
  590. long User_Update(VQAHandle *vqa)
  591. {
  592. VQAData *vqabuf;
  593. long rc = 0;
  594. /* Dereference data members for quicker access. */
  595. vqabuf = ((VQAHandleP *)vqa)->VQABuf;
  596. if (vqabuf->Flags & VQADATF_UPDATE) {
  597. /* Invoke the page flip routine */
  598. rc = (*(vqabuf->Page_Flip))(vqa);
  599. /* Update data for mono output */
  600. vqabuf->Flipper.LastFrameNum = vqabuf->Flipper.CurFrame->FrameNum;
  601. /* Mark the frame as loadable */
  602. vqabuf->Flipper.CurFrame->Flags = 0L;
  603. vqabuf->Flags &= (~VQADATF_UPDATE);
  604. }
  605. return (rc);
  606. }
  607. void VQA_Dummy(void)
  608. {
  609. Set_Font(NULL);
  610. }