bink.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. /*=============================================================================
  2. Name : bink.c
  3. Purpose : routines for playback of Bink files
  4. Created 6/8/1999 by khent
  5. Copyright Relic Entertainment, Inc. All rights reserved.
  6. =============================================================================*/
  7. #include <stdlib.h>
  8. #include "bink.h"
  9. #include "main.h"
  10. #include "file.h"
  11. #include "debug.h"
  12. #include "key.h"
  13. #include "soundevent.h"
  14. #include "dxdraw.h"
  15. #include "utility.h"
  16. #define USE_TIMER 0
  17. #define INCREMENTAL_FRAMES 0
  18. #define BINK_SemaphoreName "BINKSEMAPHORE"
  19. #define SWtype 0
  20. #define GLIDEtype 1
  21. #define D3Dtype 2
  22. #define GLtype 3
  23. HANDLE binkSemaphore;
  24. bool binkDonePlaying = TRUE;
  25. static bool binkIsPaused = FALSE;
  26. static sdword g_RGLtype;
  27. static binkDisplay_proc g_displayProc;
  28. static binkDecodeCallback_proc g_decodeProc;
  29. static binkEndCallback_proc g_endProc;
  30. static sdword g_trackNum;
  31. static sdword g_surfType;
  32. static HBINK bnk = 0;
  33. MMRESULT binkTimerHandle = 0;
  34. static bool decodeTimer;
  35. bool binkPlaying = FALSE;
  36. static bool inDecode = FALSE;
  37. static bool binkStopNow = FALSE;
  38. static bool binkUpdate = FALSE;
  39. static sdword binkDecodeFrameCount;
  40. static sdword binkDisplayFrameCount;
  41. static u32 binkDisplayFlags;
  42. static LARGE_INTEGER binkTimerFrequency;
  43. static LONGLONG binkTimerDivisor;
  44. static LONGLONG binkTimerStart;
  45. static sdword binkTimerFrame;
  46. static uword* binkSurface = NULL;
  47. real32 binkFrameRate = 0.0f;
  48. sdword binkFrameAdd;
  49. extern HDC hGLDeviceContext;
  50. void binkTimeReset(void);
  51. /*-----------------------------------------------------------------------------
  52. Name : binkGetSurface
  53. Description : return the surface that frames are decoded onto
  54. Inputs :
  55. Outputs :
  56. Return : binkSurface (pitch = width*(depth>>3))
  57. ----------------------------------------------------------------------------*/
  58. uword* binkGetSurface(void)
  59. {
  60. return binkSurface;
  61. }
  62. /*-----------------------------------------------------------------------------
  63. Name : binkInit
  64. Description :
  65. Inputs :
  66. Outputs :
  67. Return : TRUE or FALSE (success or failure)
  68. ----------------------------------------------------------------------------*/
  69. bool binkInit(sdword rgltype)
  70. {
  71. sdword size;
  72. g_RGLtype = rgltype;
  73. binkSemaphore = CreateSemaphore(NULL, 1, 1, BINK_SemaphoreName);
  74. dbgAssert(binkSemaphore != NULL);
  75. switch (g_RGLtype)
  76. {
  77. case SWtype:
  78. size = 2;
  79. break;
  80. case -1:
  81. case GLtype:
  82. case D3Dtype:
  83. size = 4;
  84. break;
  85. default:
  86. dbgFatalf(DBG_Loc, "what's this type: %d [binkInit]", g_RGLtype);
  87. }
  88. binkSurface = (uword*)radmalloc(size*640*480);
  89. binkTimeReset();
  90. return TRUE;
  91. }
  92. /*-----------------------------------------------------------------------------
  93. Name : binkCleanup
  94. Description : cleanup after displaying a Bink video file
  95. Inputs :
  96. Outputs :
  97. Return : TRUE or FALSE
  98. ----------------------------------------------------------------------------*/
  99. bool binkCleanup(void)
  100. {
  101. keyClearAll();
  102. CloseHandle(binkSemaphore);
  103. if (binkSurface != NULL)
  104. {
  105. radfree(binkSurface);
  106. binkSurface = NULL;
  107. }
  108. return TRUE;
  109. }
  110. /*-----------------------------------------------------------------------------
  111. Name : binkGetBink
  112. Description : returns the Bink internal structure
  113. Inputs :
  114. Outputs :
  115. Return : bnk
  116. ----------------------------------------------------------------------------*/
  117. HBINK binkGetBink(void)
  118. {
  119. return bnk;
  120. }
  121. /*-----------------------------------------------------------------------------
  122. Name : binkOpen
  123. Description : wrapper for opening a Bink video file
  124. Inputs : filename - name of the Bink video file to open
  125. Outputs :
  126. Return : TRUE or FALSE
  127. ----------------------------------------------------------------------------*/
  128. static bool binkOpen(char* filename)
  129. {
  130. char fullname[1024];
  131. char cdname[1024];
  132. char* dir;
  133. // get CD path
  134. strcpy(cdname,filePathPrepend(filename,FF_CDROM));
  135. dir = getenv("HW_Data");
  136. if (dir == NULL)
  137. {
  138. // set default path
  139. strcpy(fullname, filename);
  140. }
  141. else
  142. {
  143. // set HW_Data path
  144. strcpy(fullname, dir);
  145. strcat(fullname, "\\");
  146. strcat(fullname, filename);
  147. }
  148. BinkSoundUseDirectSound(NULL);
  149. // try default path or HW_Data path
  150. bnk = BinkOpen(fullname, BINKNOTHREADEDIO);
  151. if (!bnk)
  152. {
  153. // try filename alone
  154. bnk = BinkOpen(filename, BINKNOTHREADEDIO);
  155. if (!bnk)
  156. {
  157. // try CD path
  158. bnk = BinkOpen(cdname, BINKNOTHREADEDIO);
  159. if (!bnk)
  160. {
  161. return FALSE;
  162. }
  163. }
  164. }
  165. // BinkSetSoundOnOff(bnk, 0);
  166. binkFrameRate = (real32)bnk->FrameRate / (real32)bnk->FrameRateDiv;
  167. return TRUE;
  168. }
  169. /*-----------------------------------------------------------------------------
  170. Name : binkTimeReset
  171. Description : reset the frame timer
  172. Inputs :
  173. Outputs :
  174. Return :
  175. ----------------------------------------------------------------------------*/
  176. static void binkTimeReset(void)
  177. {
  178. LARGE_INTEGER timer;
  179. QueryPerformanceFrequency(&binkTimerFrequency);
  180. binkTimerDivisor = binkTimerFrequency.QuadPart;
  181. QueryPerformanceCounter(&timer);
  182. binkTimerStart = timer.QuadPart;
  183. binkTimerFrame = 1;
  184. }
  185. /*-----------------------------------------------------------------------------
  186. Name : binkTimeElapsed
  187. Description : calculate amount of time (ms) elapsed since binkTimeReset was called
  188. Inputs :
  189. Outputs :
  190. Return : ms of elapsed time
  191. ----------------------------------------------------------------------------*/
  192. static sdword binkTimeElapsed(void)
  193. {
  194. LARGE_INTEGER timer;
  195. LONGLONG difference;
  196. real32 secs;
  197. QueryPerformanceCounter(&timer);
  198. difference = timer.QuadPart - binkTimerStart;
  199. secs = (real32)difference / (real64)binkTimerDivisor;
  200. return (udword)(secs * 1000.0);
  201. }
  202. /*-----------------------------------------------------------------------------
  203. Name : binkIdealFrame
  204. Description : returns the frame (based on time elapsed) that a video should be currently at
  205. Inputs :
  206. Outputs :
  207. Return : the frame
  208. ----------------------------------------------------------------------------*/
  209. static sdword binkIdealFrame(void)
  210. {
  211. #if INCREMENTAL_FRAMES
  212. binkTimerFrame++;
  213. return (binkTimerFrame + binkFrameAdd);
  214. #else
  215. real32 ms;
  216. sdword frame;
  217. ms = 1000.0f / binkFrameRate;
  218. frame = (sdword)((real32)binkTimeElapsed() / ms);
  219. frame += binkFrameAdd;
  220. return frame;
  221. #endif
  222. }
  223. /*-----------------------------------------------------------------------------
  224. Name : binkUserPaintCallback
  225. Description :
  226. Inputs : psurf - surface pointer or NULL
  227. pitch, x, y - ignored
  228. Outputs : frame is blitted onto binkSurface
  229. Return :
  230. ----------------------------------------------------------------------------*/
  231. static void binkUserPaintCallback(void* psurf, sdword pitch, sdword x, sdword y)
  232. {
  233. WaitForSingleObject(binkSemaphore, INFINITE);
  234. binkDisplayFlags = BINKSURFACECOPYALL;
  235. if (psurf != NULL)
  236. {
  237. BinkCopyToBuffer(bnk, psurf, pitch, 480, x, y, BINKSURFACE565 | binkDisplayFlags);
  238. }
  239. else
  240. {
  241. switch (g_RGLtype)
  242. {
  243. case -1:
  244. if (pitch == 2*640)
  245. {
  246. BinkCopyToBuffer(bnk, binkSurface, pitch, 480, 0, 0,
  247. ((g_surfType == S_RGB565) ? BINKSURFACE565 : BINKSURFACE555) | binkDisplayFlags);
  248. }
  249. else
  250. {
  251. BinkCopyToBuffer(bnk, binkSurface, pitch, 480, 0, 0, BINKSURFACE32 | binkDisplayFlags);
  252. }
  253. break;
  254. case SWtype:
  255. BinkCopyToBuffer(bnk, binkSurface, 2*640, 480, 0, 0,
  256. ((g_surfType == S_RGB565) ? BINKSURFACE565 : BINKSURFACE555) | binkDisplayFlags);
  257. break;
  258. case GLtype:
  259. case D3Dtype:
  260. BinkCopyToBuffer(bnk, binkSurface, 4*640, 480, 0, 0, BINKSURFACE32 | binkDisplayFlags);
  261. break;
  262. default:
  263. dbgFatalf(DBG_Loc, "what's this type: %d [binkUserPaintCallback]", g_RGLtype);
  264. }
  265. }
  266. ReleaseSemaphore(binkSemaphore, 1, NULL);
  267. }
  268. /*-----------------------------------------------------------------------------
  269. Name : binkNextFrame
  270. Description : advance to next frame of the Bink video file
  271. Inputs :
  272. Outputs :
  273. Return :
  274. ----------------------------------------------------------------------------*/
  275. static void binkNextFrame(void)
  276. {
  277. if (WaitForSingleObject(binkSemaphore, 0) == WAIT_FAILED)
  278. {
  279. return;
  280. }
  281. BinkDoFrame(bnk);
  282. binkUpdate = TRUE;
  283. if (bnk->FrameNum == (bnk->Frames - 1))
  284. {
  285. binkStopNow = TRUE;
  286. }
  287. else
  288. {
  289. BinkNextFrame(bnk);
  290. }
  291. ReleaseSemaphore(binkSemaphore, 1, NULL);
  292. }
  293. /*-----------------------------------------------------------------------------
  294. Name : binkReverse
  295. Description : y-flips a given 640x480 image
  296. Inputs : surf - surface to y-flip
  297. pitch - surface pitch
  298. Outputs :
  299. Return :
  300. ----------------------------------------------------------------------------*/
  301. static void binkReverse(ubyte* surf, sdword pitch)
  302. {
  303. ubyte line[4*640];
  304. sdword y, top, bot;
  305. for (y = 0; y < (480/2); y++)
  306. {
  307. top = y;
  308. bot = 479 - y;
  309. memcpy(line, surf + pitch*top, pitch);
  310. memcpy(surf + pitch*top, surf + pitch*bot, pitch);
  311. memcpy(surf + pitch*bot, line, pitch);
  312. }
  313. }
  314. /*-----------------------------------------------------------------------------
  315. Name : binkDisplayWin32
  316. Description : Win32 method of displaying a frame of Bink video
  317. Inputs : callback - fn that blits onto generic surface
  318. depth - bitdepth of display device
  319. Outputs :
  320. Return :
  321. ----------------------------------------------------------------------------*/
  322. void binkDisplayWin32(binkDisplayCallback_proc callback, sdword depth)
  323. {
  324. BITMAPINFOHEADER* pbi;
  325. BITMAPINFO bmi;
  326. BITMAPINFO* pbmi;
  327. HBITMAP hbitmap;
  328. BYTE* pbits;
  329. WORD* pbitmap;
  330. HDC hdc, hdcTemp;
  331. sdword bitsize;
  332. sdword xofs, yofs;
  333. sdword mult;
  334. mult = depth >> 3;
  335. callback(NULL, mult*640, 0, 0);
  336. binkReverse((ubyte*)binkSurface, mult*640);
  337. pbmi = &bmi;
  338. bitsize = mult * 640 * 480;
  339. pbits = (BYTE*)binkSurface;
  340. pbi = (BITMAPINFOHEADER*)pbmi;
  341. pbi->biSize = sizeof(BITMAPINFOHEADER);
  342. pbi->biWidth = 640;
  343. pbi->biHeight = 480;
  344. pbi->biPlanes = 1;
  345. pbi->biBitCount = depth;
  346. pbi->biCompression = BI_RGB;
  347. pbi->biSizeImage = 0;
  348. pbi->biXPelsPerMeter = 0;
  349. pbi->biYPelsPerMeter = 0;
  350. pbi->biClrUsed = 0;
  351. pbi->biClrImportant = 0;
  352. hdc = GetDC(ghMainWindow);
  353. hbitmap = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (VOID**)&pbitmap, 0, 0);
  354. SetDIBits(hdc, hbitmap, 0, 480, pbits, pbmi, DIB_RGB_COLORS);
  355. hdcTemp = CreateCompatibleDC(hdc);
  356. SelectObject(hdcTemp, hbitmap);
  357. if (fullScreen)
  358. {
  359. xofs = yofs = 0;
  360. }
  361. else
  362. {
  363. xofs = (MAIN_WindowWidth - 640) / 2;
  364. yofs = (MAIN_WindowHeight - 480) / 2;
  365. }
  366. BitBlt(hdc, xofs, yofs, 640, 480, hdcTemp, 0, 0, SRCCOPY);
  367. DeleteDC(hdcTemp);
  368. ReleaseDC(ghMainWindow, hdc);
  369. DeleteObject(hbitmap);
  370. }
  371. /*-----------------------------------------------------------------------------
  372. Name : binkDisplay16
  373. Description : Windows-specific 16bit RGB555 frame display
  374. Inputs : ...
  375. Outputs :
  376. Return :
  377. ----------------------------------------------------------------------------*/
  378. void binkDisplay16(binkDisplayCallback_proc callback)
  379. {
  380. binkDisplayWin32(callback, 16);
  381. }
  382. /*-----------------------------------------------------------------------------
  383. Name : binkDisplay32
  384. Description : Windows-specific 32bit frame display
  385. Inputs : ...
  386. Outputs :
  387. Return :
  388. ----------------------------------------------------------------------------*/
  389. void binkDisplay32(binkDisplayCallback_proc callback)
  390. {
  391. binkDisplayWin32(callback, 32);
  392. }
  393. /*-----------------------------------------------------------------------------
  394. Name : binkDecodeSimply
  395. Description : simple frame decoder
  396. Inputs :
  397. Outputs :
  398. Return :
  399. ----------------------------------------------------------------------------*/
  400. static void binkDecodeSimply(void)
  401. {
  402. if (systemActive && !BinkWait(bnk))
  403. {
  404. binkDecodeFrameCount++;
  405. binkNextFrame();
  406. binkUpdate = TRUE;
  407. binkDisplayFlags = BINKSURFACECOPYALL;
  408. if (g_decodeProc != NULL)
  409. {
  410. g_decodeProc(binkDecodeFrameCount);
  411. }
  412. }
  413. }
  414. /*-----------------------------------------------------------------------------
  415. Name : binkDecodeTimerProc
  416. Description : mmtimer callback proc for decoding a frame of Bink video
  417. Inputs : [all ignored]
  418. Outputs :
  419. Return :
  420. ----------------------------------------------------------------------------*/
  421. void CALLBACK binkDecodeTimerProc(UINT uid, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
  422. {
  423. if (!systemActive)
  424. {
  425. binkUpdate = FALSE;
  426. binkStopNow = TRUE;
  427. return;
  428. }
  429. if (inDecode || binkStopNow)
  430. {
  431. if (binkStopNow)
  432. {
  433. binkUpdate = FALSE;
  434. }
  435. return;
  436. }
  437. inDecode = TRUE;
  438. soundEventUpdate();
  439. speechEventUpdate();
  440. if (bnk->FrameNum < 2)
  441. {
  442. binkTimeReset();
  443. binkDecodeSimply();
  444. inDecode = FALSE;
  445. return;
  446. }
  447. if (systemActive)
  448. {
  449. sdword diff, i;
  450. sdword idealFrame = binkIdealFrame();
  451. (void)BinkWait(bnk);
  452. if (idealFrame >= bnk->Frames)
  453. {
  454. idealFrame = bnk->Frames - 1;
  455. binkStopNow = TRUE;
  456. inDecode = FALSE;
  457. binkUpdate = FALSE;
  458. if (binkTimerHandle != 0)
  459. {
  460. (void)timeKillEvent(binkTimerHandle);
  461. binkTimerHandle = 0;
  462. }
  463. return;
  464. }
  465. diff = idealFrame - bnk->FrameNum;
  466. if (diff < 0)
  467. {
  468. diff = 0;
  469. }
  470. binkDisplayFlags = (diff > 1) ? BINKSURFACECOPYALL : 0;
  471. for (i = 0; i < diff; i++)
  472. {
  473. if ((i > 0) && (!(i & 3)))
  474. {
  475. (void)BinkWait(bnk);
  476. }
  477. binkDecodeFrameCount++;
  478. binkNextFrame();
  479. binkUpdate = TRUE;
  480. if (binkStopNow)
  481. {
  482. break;
  483. }
  484. }
  485. if (g_decodeProc != NULL)
  486. {
  487. g_decodeProc(binkDecodeFrameCount);
  488. }
  489. }
  490. if (binkStopNow)
  491. {
  492. binkUpdate = FALSE;
  493. }
  494. inDecode = FALSE;
  495. }
  496. /*-----------------------------------------------------------------------------
  497. Name : binkPlayLoop
  498. Description : playback loop (message handling) for playing Bink video files
  499. Inputs :
  500. Outputs :
  501. Return :
  502. ----------------------------------------------------------------------------*/
  503. static void binkPlayLoop(void)
  504. {
  505. MSG msg;
  506. BOOL gotMsg;
  507. TIMECAPS ptc;
  508. PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  509. timeGetDevCaps((LPTIMECAPS)&ptc, sizeof(TIMECAPS));
  510. #if USE_TIMER
  511. binkTimerHandle = timeSetEvent(ptc.wPeriodMin, 0, binkDecodeTimerProc, 0, TIME_PERIODIC);
  512. #else
  513. binkTimerHandle = 0;
  514. #endif
  515. decodeTimer = (binkTimerHandle == 0) ? FALSE : TRUE;
  516. if (g_trackNum != -1)
  517. {
  518. soundEventPlayMusic(g_trackNum);
  519. }
  520. for (;;)
  521. {
  522. Sleep(0);
  523. if (systemActive)
  524. {
  525. gotMsg = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
  526. }
  527. else
  528. {
  529. gotMsg = GetMessage(&msg, NULL, 0, 0);
  530. }
  531. BinkService(bnk);
  532. if (gotMsg)
  533. {
  534. if (msg.message == WM_QUIT)
  535. {
  536. break;
  537. }
  538. TranslateMessage(&msg);
  539. DispatchMessage(&msg);
  540. }
  541. else if (systemActive && !binkIsPaused)
  542. {
  543. if (binkUpdate)
  544. {
  545. binkUpdate = FALSE;
  546. g_displayProc(binkUserPaintCallback);
  547. binkDisplayFrameCount++;
  548. }
  549. Sleep(0);
  550. if (!decodeTimer)
  551. {
  552. binkDecodeTimerProc(0, 0, 0, 0, 0);
  553. }
  554. }
  555. if (binkStopNow)
  556. {
  557. break;
  558. }
  559. }
  560. if (binkTimerHandle != 0)
  561. {
  562. (void)timeKillEvent(binkTimerHandle);
  563. binkTimerHandle = 0;
  564. }
  565. if (g_trackNum != -1)
  566. {
  567. soundEventStopMusic(0.0f);
  568. }
  569. }
  570. /*-----------------------------------------------------------------------------
  571. Name : binkPlay
  572. Description : playback a Bink video file
  573. Inputs : ...
  574. Outputs :
  575. Return : TRUE or FALSE (success or failure)
  576. ----------------------------------------------------------------------------*/
  577. bool binkPlay(char* filename,
  578. binkDisplay_proc displayProc,
  579. binkDecodeCallback_proc decodeProc,
  580. sdword surfType, bool rev, sdword trackNum)
  581. {
  582. if (!systemActive)
  583. {
  584. return FALSE;
  585. }
  586. g_trackNum = trackNum;
  587. if (trackNum != -1)
  588. {
  589. soundEventUpdate();
  590. speechEventUpdate();
  591. Sleep(150);
  592. soundEventUpdate();
  593. speechEventUpdate();
  594. }
  595. binkStopNow = FALSE;
  596. binkUpdate = FALSE;
  597. binkIsPaused = FALSE;
  598. binkFrameAdd = 0;
  599. if (!binkOpen(filename))
  600. {
  601. return FALSE;
  602. }
  603. binkDecodeFrameCount = 0;
  604. binkDisplayFrameCount = 0;
  605. binkDisplayFlags = BINKSURFACECOPYALL;
  606. binkDonePlaying = FALSE;
  607. binkPlaying = TRUE;
  608. g_surfType = surfType;
  609. if (displayProc == NULL)
  610. {
  611. g_displayProc = (hwGetDepth() > 16) ? binkDisplay32 : binkDisplay16;
  612. }
  613. else
  614. {
  615. g_displayProc = displayProc;
  616. }
  617. g_decodeProc = decodeProc;
  618. binkPlayLoop();
  619. binkPlaying = FALSE;
  620. BinkClose(bnk);
  621. binkDonePlaying = TRUE;
  622. return TRUE;
  623. }
  624. /*-----------------------------------------------------------------------------
  625. Name : binkStop
  626. Description : flag video playback to stop
  627. Inputs :
  628. Outputs :
  629. Return : TRUE or FALSE (currently cannot fail)
  630. ----------------------------------------------------------------------------*/
  631. bool binkStop(void)
  632. {
  633. binkStopNow = TRUE;
  634. if (binkTimerHandle != 0)
  635. {
  636. (void)timeKillEvent(binkTimerHandle);
  637. binkTimerHandle = 0;
  638. }
  639. return TRUE;
  640. }
  641. /*-----------------------------------------------------------------------------
  642. Name : binkPause
  643. Description : un/pause video playback
  644. Inputs : pause - TRUE or FALSE, pause or continue
  645. Outputs :
  646. Return : TRUE or FALSE (currently cannot fail)
  647. ----------------------------------------------------------------------------*/
  648. bool binkPause(bool pause)
  649. {
  650. if (pause)
  651. {
  652. binkIsPaused = TRUE;
  653. }
  654. else
  655. {
  656. binkIsPaused = FALSE;
  657. //reset ideal time
  658. binkTimeReset();
  659. binkFrameAdd = bnk->FrameNum;
  660. }
  661. return TRUE;
  662. }