LOADER.CPP 75 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832
  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. * loader.c
  29. *
  30. * DESCRIPTION
  31. * Stream loading and pre-processing.
  32. *
  33. * PROGRAMMER
  34. * Bill Randolph
  35. * Denzil E. Long, Jr.
  36. *
  37. * DATE
  38. * August 21, 1995
  39. *
  40. *----------------------------------------------------------------------------
  41. *
  42. * PUBLIC
  43. * VQA_Open - Open a VQA file to play.
  44. * VQA_Close - Close an opened VQA file.
  45. * VQA_LoadFrame - Load the next video frame from the VQA data stream.
  46. * VQA_SeekFrame - Position the movie stream to the specified frame.
  47. *
  48. * PRIVATE
  49. * AllocBuffers - Allocates the numerous VQA play buffers
  50. * FreeBuffers - Frees the VQA play buffers
  51. * PrimeBuffers - Pre-Load the internal buffers.
  52. * Load_FINF - Loads the Frame Info Table.
  53. * Load_VQHD - Loads a VQA Header.
  54. * Load_CBF0 - Loads a full, uncompressed codebook
  55. * Load_CBFZ - Loads a full, compressed codebook
  56. * Load_CBP0 - Loads a partial uncompressed codebook
  57. * Load_CBPZ - Loads a partial compressed codebook
  58. * Load_CPL0 - Loads an uncompressed palette
  59. * Load_CPLZ - Loads a compressed palette
  60. * Load_VPT0 - Loads uncompressed pointers
  61. * Load_VPTZ - Loads compressed pointers
  62. * Load_VQF - Loads a VQ Frame chunk
  63. * Load_SND0 - Loads an uncompressed sound chunk
  64. * Load_SND1 - Loads a compressed sound chunk
  65. * Load_AudFrame - Loads blocks from separate audio file, if needed.
  66. *
  67. ****************************************************************************/
  68. #include <stdio.h>
  69. #include <fcntl.h>
  70. #include <io.h>
  71. #include <malloc.h>
  72. #include <mem.h>
  73. #include <dos.h>
  74. #include "vq.h"
  75. #include "vqaplayp.h"
  76. #include <vqm32\all.h>
  77. /*---------------------------------------------------------------------------
  78. * PRIVATE DECLARATIONS
  79. *-------------------------------------------------------------------------*/
  80. static VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config);
  81. static void FreeBuffers(VQAData *vqa, VQAConfig *config, VQAHeader *header);
  82. static long PrimeBuffers(VQAHandle *vqa);
  83. static long Load_VQF(VQAHandleP *vqap, unsigned long iffsize);
  84. static long Load_FINF(VQAHandleP *vqap, unsigned long iffsize);
  85. static long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize);
  86. static long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize);
  87. static long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize);
  88. static long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize);
  89. static long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize);
  90. static long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize);
  91. static long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize);
  92. static long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize);
  93. static long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize);
  94. #if(VQAAUDIO_ON)
  95. static long Load_SND0(VQAHandleP *vqap, unsigned long iffsize);
  96. static long Load_SND1(VQAHandleP *vqap, unsigned long iffsize);
  97. static long Load_SND2(VQAHandleP *vqap, unsigned long iffsize);
  98. #if(VQAVOC_ON)
  99. static void Load_AudFrame(VQAHandleP *vqap);
  100. #endif /* VQAVOC_ON */
  101. #endif /* VQAAUDIO_ON */
  102. /****************************************************************************
  103. *
  104. * NAME
  105. * VQA_Open - Open a VQA file to play.
  106. *
  107. * SYNOPSIS
  108. * Error = VQA_Open(VQA, Name, Config)
  109. *
  110. * long VQA_Open(VQAHandle *, char *, VQAConfig *);
  111. *
  112. * FUNCTION
  113. * - Open a VQA file for reading.
  114. * - Validate that it is an IFF file, of the VQA type.
  115. * - Read the VQA header.
  116. * - Open a VOC file for playback, if requested.
  117. * - Set the Loader's frame rate, if the caller's Config structure's
  118. * FrameRate is set to -1
  119. * - Set the Drawer's frame rate, if the caller's Config structure's
  120. * DrawRate is set to -1
  121. *
  122. * INPUTS
  123. * VQA - Pointer to initialized handle. Obtained by VQA_Alloc().
  124. * Name - Pointer to name of VQA file to open.
  125. * Config - Pointer to initialized VQA configuration structure.
  126. *
  127. * RESULT
  128. * Error - 0 if successful, or VQAERR_ error code.
  129. *
  130. ****************************************************************************/
  131. #define OPEN_VQHD (1<<0)
  132. #define OPEN_FINF (1<<1)
  133. #define OPEN_CAPTIONS (1<<2)
  134. #define OPEN_EVA (1<<3)
  135. long VQA_Open(VQAHandle *vqa, char const *filename, VQAConfig *config)
  136. {
  137. VQAHandleP *vqap;
  138. VQAHeader *header;
  139. ChunkHeader chunk;
  140. long max_frm_size;
  141. long i;
  142. long done;
  143. long found;
  144. char *ptr;
  145. /* Dereference commonly used data members for quicker access. */
  146. vqap = (VQAHandleP *)vqa;
  147. header = &vqap->Header;
  148. /*-------------------------------------------------------------------------
  149. * VERIFY VALIDITY OF VQA FILE.
  150. *-----------------------------------------------------------------------*/
  151. /* Open the file. */
  152. if (vqap->IOHandler(vqa, VQACMD_OPEN, (void *)filename, 0)) {
  153. return (VQAERR_OPEN);
  154. }
  155. /* Read the file ID & Size */
  156. if (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 8)) {
  157. VQA_Close(vqa);
  158. return (VQAERR_READ);
  159. }
  160. /* Verify an IFF FORM */
  161. if ((chunk.id != ID_FORM) || (chunk.size == 0)) {
  162. VQA_Close(vqa);
  163. return (VQAERR_NOTVQA);
  164. }
  165. /* Read in WVQA ID */
  166. if (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 4)) {
  167. VQA_Close(vqa);
  168. return (VQAERR_READ);
  169. }
  170. /* Verify VQA */
  171. if (chunk.id != ID_WVQA) {
  172. VQA_Close(vqa);
  173. return (VQAERR_NOTVQA);
  174. }
  175. /*-------------------------------------------------------------------------
  176. * INITIALIZE THE PLAYERS CONFIGURATION
  177. *-----------------------------------------------------------------------*/
  178. /* Use the clients configuration if they provided one. */
  179. if (config != NULL) {
  180. memcpy(&vqap->Config, config, sizeof(VQAConfig));
  181. } else {
  182. VQA_DefaultConfig(&vqap->Config);
  183. }
  184. /* Use the internal configuration structure from now on. */
  185. config = &vqap->Config;
  186. /*-------------------------------------------------------------------------
  187. * PROCESS THE PRE-FRAME CHUNKS (VQHD, CAP, FINF, ETC...)
  188. *-----------------------------------------------------------------------*/
  189. found = 0;
  190. done = 0;
  191. while (!done) {
  192. if (vqap->IOHandler(vqa, VQACMD_READ, &chunk, 8)) {
  193. VQA_Close(vqa);
  194. return (VQAERR_READ);
  195. }
  196. chunk.size = REVERSE_LONG(chunk.size);
  197. switch (chunk.id) {
  198. /*---------------------------------------------------------------------
  199. * READ IN THE VQA HEADER.
  200. *-------------------------------------------------------------------*/
  201. case ID_VQHD:
  202. if (chunk.size != sizeof(VQAHeader)) {
  203. VQA_Close(vqa);
  204. return (VQAERR_NOTVQA);
  205. }
  206. /* Read the header data. */
  207. if (vqap->IOHandler(vqa, VQACMD_READ, header, PADSIZE(chunk.size))) {
  208. VQA_Close(vqa);
  209. return (VQAERR_READ);
  210. }
  211. /*-------------------------------------------------------------------
  212. * SETUP THE CONFIGURATION FROM THE HEADER.
  213. *-----------------------------------------------------------------*/
  214. if (config->ImageWidth == -1) {
  215. config->ImageWidth = header->ImageWidth;
  216. }
  217. if (config->ImageHeight == -1) {
  218. config->ImageHeight = header->ImageHeight;
  219. }
  220. /* If Loaders frame rate is -1 then use the value from the header. */
  221. if (config->FrameRate == -1) {
  222. config->FrameRate = header->FPS;
  223. }
  224. /* If Drawers frame rate is -1 then use the value from the header,
  225. * which will result in a "variable" frame rate.
  226. */
  227. if (config->DrawRate == -1) {
  228. config->DrawRate = header->FPS;
  229. }
  230. /* Finally, if the DrawRate was set to -1 or 0 (ie MaxRate contained
  231. * bogus values), set it to the header value.
  232. */
  233. if ((config->DrawRate == -1) || (config->DrawRate == 0)) {
  234. config->DrawRate = header->FPS;
  235. }
  236. #if(VQAAUDIO_ON)
  237. /* If an alternate audio track is not available then turn it off.
  238. * This enables the primary audio track to be played.
  239. */
  240. if ((header->Version > VQAHD_VER1)
  241. && !(header->Flags & VQAHDF_ALTAUDIO)) {
  242. config->OptionFlags &= ~VQAOPTF_ALTAUDIO;
  243. }
  244. #endif
  245. /*-------------------------------------------------------------------
  246. * ALLOCATE THE BUFFERS THAT WE NEED TO PLAY THE VQA.
  247. *-----------------------------------------------------------------*/
  248. if ((vqap->VQABuf = AllocBuffers(header, config)) == NULL) {
  249. VQA_Close(vqa);
  250. return (VQAERR_NOMEM);
  251. }
  252. found |= OPEN_VQHD;
  253. break;
  254. /*---------------------------------------------------------------------
  255. * READ IN AND OPEN THE CAPTIONS STREAM.
  256. *-------------------------------------------------------------------*/
  257. case ID_CAP0:
  258. if ((config->CapFont != NULL)
  259. && (config->OptionFlags & VQAOPTF_CAPTIONS)) {
  260. short size = 0;
  261. /* Get uncompressed size of captions. */
  262. if (vqap->IOHandler(vqa, VQACMD_READ, &size, sizeof(short))) {
  263. VQA_Close(vqa);
  264. return (VQAERR_READ);
  265. }
  266. /* Allocate buffer for captions. */
  267. i = size + 50;
  268. if ((ptr = (char *)malloc(i)) == NULL) {
  269. VQA_Close(vqa);
  270. return (VQAERR_NOMEM);
  271. }
  272. /* Read in the captions chunk. */
  273. i -= PADSIZE(chunk.size);
  274. if (vqap->IOHandler(vqa, VQACMD_READ, (ptr + i),
  275. PADSIZE(chunk.size - sizeof(short)))) {
  276. free(ptr);
  277. VQA_Close(vqa);
  278. return (VQAERR_READ);
  279. }
  280. /* Decompress the captions. */
  281. LCW_Uncompress((ptr + i), ptr, size);
  282. vqap->Caption = OpenCaptions(ptr, config->CapFont);
  283. if (vqap->Caption == NULL) {
  284. VQA_Close(vqa);
  285. return (VQAERR_NOMEM);
  286. }
  287. found |= OPEN_CAPTIONS;
  288. } else {
  289. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  290. PADSIZE(chunk.size))) {
  291. VQA_Close(vqa);
  292. return (VQAERR_SEEK);
  293. }
  294. }
  295. break;
  296. case ID_EVA0:
  297. if ((config->EVAFont != NULL)
  298. && (config->OptionFlags & VQAOPTF_EVA)) {
  299. short size = 0;
  300. /* Get uncompressed size of captions. */
  301. if (vqap->IOHandler(vqa, VQACMD_READ, &size, sizeof(short))) {
  302. VQA_Close(vqa);
  303. return (VQAERR_READ);
  304. }
  305. /* Allocate buffer for captions. */
  306. i = size + 50;
  307. if ((ptr = (char *)malloc(i)) == NULL) {
  308. VQA_Close(vqa);
  309. return (VQAERR_NOMEM);
  310. }
  311. /* Read in the captions chunk. */
  312. i -= PADSIZE(chunk.size);
  313. if (vqap->IOHandler(vqa, VQACMD_READ, (ptr + i),
  314. PADSIZE(chunk.size - sizeof(short)))) {
  315. free (ptr);
  316. VQA_Close(vqa);
  317. return (VQAERR_READ);
  318. }
  319. /* Decompress the captions. */
  320. LCW_Uncompress((ptr + i), ptr, size);
  321. vqap->EVA = OpenCaptions(ptr, config->EVAFont);
  322. if (vqap->EVA == NULL) {
  323. VQA_Close(vqa);
  324. return (VQAERR_NOMEM);
  325. }
  326. found |= OPEN_EVA;
  327. } else {
  328. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  329. PADSIZE(chunk.size))) {
  330. VQA_Close(vqa);
  331. return (VQAERR_SEEK);
  332. }
  333. }
  334. break;
  335. /*---------------------------------------------------------------------
  336. * READ FRAME INFORMATION
  337. *-------------------------------------------------------------------*/
  338. case ID_FINF:
  339. if (Load_FINF(vqap, chunk.size)) {
  340. VQA_Close(vqa);
  341. return (VQAERR_READ);
  342. }
  343. done = 1;
  344. break;
  345. default:
  346. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  347. PADSIZE(chunk.size))) {
  348. VQA_Close(vqa);
  349. return (VQAERR_SEEK);
  350. }
  351. break;
  352. }
  353. }
  354. /*-------------------------------------------------------------------------
  355. * INITIALIZE THE VIDEO SYSTEM IF WE ARE REQUIRED TO HANDLE THAT.
  356. *-----------------------------------------------------------------------*/
  357. #if(VQAVIDEO_ON)
  358. if ((vqap->VQABuf->Drawer.Display = SetVideoMode(config->Vmode)) == 0) {
  359. VQA_Close(vqa);
  360. return (VQAERR_VIDEO);
  361. }
  362. /* Set the VBIBit polarity. */
  363. vqap->VQABuf->VBIBit = GetVBIBit();
  364. #else
  365. if (config->VBIBit == -1) {
  366. config->VBIBit = TestVBIBit();
  367. }
  368. vqap->VQABuf->VBIBit = config->VBIBit;
  369. if (found & (OPEN_CAPTIONS|OPEN_EVA)) {
  370. SetDAC(251,255,255,255); /* White */
  371. SetDAC(252,255,000,000); /* Red */
  372. SetDAC(253,000,255,000); /* Green */
  373. SetDAC(254,255,255,255);
  374. SetDAC(255,255,000,255); /* Cycle */
  375. }
  376. #endif /* VQAVIDEO_ON */
  377. /*-------------------------------------------------------------------------
  378. * AUDIO TRACK OVERRIDE FROM EXTERNAL FILE (.VOC)
  379. *-----------------------------------------------------------------------*/
  380. /* Open VOC file if one is requested. */
  381. #if(VQAVOC_ON && VQAAUDIO_ON)
  382. if (config->VocFile != NULL) {
  383. vqap->vocfh = open(config->VocFile, (O_RDONLY|O_BINARY));
  384. } else {
  385. vqap->vocfh = -1;
  386. }
  387. /* Make sure we won't try to play audio. */
  388. if ((vqap->vocfh == -1) && ((header->Flags & VQAHDF_AUDIO) == 0)) {
  389. config->OptionFlags &= (~VQAOPTF_AUDIO);
  390. }
  391. #else /* VQAVOC_ON */
  392. /* If the movie does not contain an audio track make sure we won't try
  393. * to play one.
  394. */
  395. if (((header->Flags & VQAHDF_AUDIO) == 0)) {
  396. config->OptionFlags &= (~VQAOPTF_AUDIO);
  397. }
  398. #endif /* VQAVOC_ON */
  399. /*-------------------------------------------------------------------------
  400. * INITIALIZE THE AUDIO PLAYBACK/TIMING SYSTEM.
  401. *-----------------------------------------------------------------------*/
  402. #if(VQAAUDIO_ON)
  403. if (config->OptionFlags & VQAOPTF_AUDIO) {
  404. VQAAudio *audio;
  405. /* Dereference for quick access. */
  406. audio = &vqap->VQABuf->Audio;
  407. /* Open HMI audio resource for playback. */
  408. if (VQA_OpenAudio(vqap)) {
  409. VQA_Close(vqa);
  410. return (VQAERR_AUDIO);
  411. }
  412. /* Initialize ADPCM information structure for audio stream. */
  413. sosCODECInitStream(&audio->ADPCM_Info);
  414. if (header->Version == VQAHD_VER1) {
  415. audio->ADPCM_Info.wBitSize = 8;
  416. audio->ADPCM_Info.dwUnCompSize = (22050L/header->FPS) * header->Frames;
  417. audio->ADPCM_Info.wChannels = 1;
  418. } else {
  419. audio->ADPCM_Info.wBitSize = audio->BitsPerSample;
  420. audio->ADPCM_Info.dwUnCompSize = (((audio->SampleRate / header->FPS)
  421. * (audio->BitsPerSample >> 3)) * audio->Channels) * header->Frames;
  422. audio->ADPCM_Info.wChannels = audio->Channels;
  423. }
  424. audio->ADPCM_Info.dwCompSize = audio->ADPCM_Info.dwUnCompSize
  425. / (audio->ADPCM_Info.wBitSize / 4);
  426. }
  427. /* Turn off audio if the HMI DigiHandle is invalid. */
  428. if (config->DigiHandle == -1) {
  429. config->OptionFlags &= ~VQAOPTF_AUDIO;
  430. }
  431. /* Setup the timer interrupt if the client requests it for the timing
  432. * source.
  433. */
  434. if (!(config->OptionFlags & VQAOPTF_AUDIO)
  435. || (config->TimerMethod == VQA_TMETHOD_INT)) {
  436. /* Start HMI timer system for timing. */
  437. if (VQA_StartTimerInt(vqap, (config->OptionFlags & VQAOPTF_HMIINIT))) {
  438. VQA_Close(vqa);
  439. return (VQAERR_AUDIO);
  440. }
  441. }
  442. #endif /* VQAAUDIO_ON */
  443. /*-------------------------------------------------------------------------
  444. * PRIME THE BUFFERS BY PRE-LOADING THEM WITH FRAME DATA.
  445. *-----------------------------------------------------------------------*/
  446. if (PrimeBuffers(vqa) != 0) {
  447. VQA_Close(vqa);
  448. return (VQAERR_READ);
  449. }
  450. return (0);
  451. }
  452. /****************************************************************************
  453. *
  454. * NAME
  455. * VQA_Close - Close an opened VQA file.
  456. *
  457. * SYNOPSIS
  458. * VQA_Close(VQA)
  459. *
  460. * void VQA_Close(VQAHandle *);
  461. *
  462. * FUNCTION
  463. * Close the file that was opened with VQA_Open().
  464. *
  465. * INPUTS
  466. * VQA - Pointer VQAHandle to close.
  467. *
  468. * RESULT
  469. * NONE
  470. *
  471. ****************************************************************************/
  472. void VQA_Close(VQAHandle *vqa)
  473. {
  474. long (*iohandler)(VQAHandle *, long, void *, long);
  475. /* Restore video mode to text. */
  476. #if(VQAVIDEO_ON)
  477. SetVideoMode(TEXT);
  478. #endif /* VQAVIDEO_ON */
  479. /* Shutdown audio/timing system. */
  480. #if(VQAAUDIO_ON)
  481. if (((VQAHandleP *)vqa)->Config.OptionFlags & VQAOPTF_AUDIO) {
  482. VQA_CloseAudio((VQAHandleP *)vqa);
  483. } else {
  484. VQA_StopTimerInt((VQAHandleP *)vqa);
  485. }
  486. #endif /* VQAAUDIO_ON */
  487. /* Free captions. */
  488. if (((VQAHandleP *)vqa)->Caption != NULL) {
  489. if (((VQAHandleP *)vqa)->Caption->Buffer != NULL) {
  490. free(((VQAHandleP *)vqa)->Caption->Buffer);
  491. }
  492. CloseCaptions(((VQAHandleP *)vqa)->Caption);
  493. }
  494. /* Free EVA. */
  495. if (((VQAHandleP *)vqa)->EVA != NULL) {
  496. if (((VQAHandleP *)vqa)->EVA->Buffer != NULL) {
  497. free(((VQAHandleP *)vqa)->EVA->Buffer);
  498. }
  499. CloseCaptions(((VQAHandleP *)vqa)->EVA);
  500. }
  501. /* Free memory */
  502. if (((VQAHandleP *)vqa)->VQABuf != NULL) {
  503. FreeBuffers(((VQAHandleP *)vqa)->VQABuf, &((VQAHandleP *)vqa)->Config,
  504. &((VQAHandleP *)vqa)->Header);
  505. }
  506. /* Close the VOC override file if one was opened */
  507. #if(VQAVOC_ON && VQAAUDIO_ON)
  508. if (((VQAHandleP *)vqa)->vocfh != -1) {
  509. close(((VQAHandleP *)vqa)->vocfh);
  510. }
  511. #endif /* VQAVOC_ON */
  512. /* Close the VQA file */
  513. ((VQAHandleP *)vqa)->IOHandler(vqa, VQACMD_CLOSE, NULL, 0);
  514. /* Reset the VQAHandle */
  515. iohandler = ((VQAHandleP *)vqa)->IOHandler;
  516. memset(vqa, 0, sizeof(VQAHandleP));
  517. ((VQAHandleP *)vqa)->IOHandler = iohandler;
  518. }
  519. /****************************************************************************
  520. *
  521. * NAME
  522. * VQA_LoadFrame - Load the next video frame from the VQA data stream.
  523. *
  524. * SYNOPSIS
  525. * Error = VQA_LoadFrame(VQA)
  526. *
  527. * long VQA_LoadFrame(VQAHandle *);
  528. *
  529. * FUNCTION
  530. * The codebook is split up such that the last frame of every group gets
  531. * a new, complete codebook, ready for the next group. The first codebook
  532. * in the VQA is a full codebook, and goes with the first frame's data.
  533. * Partial codebooks are stored per frame after that, and they add up to
  534. * a full codebook just before the first frame for the next group is read.
  535. *
  536. * (Currently, this routine can read either the older non-frame-grouped
  537. * VQA file format, or the new frame-chunk format. For the older format,
  538. * it's assumed that the last chunk in a frame is the pointer data.)
  539. *
  540. * This routine also does a sort of "cooperative multitasking". If the
  541. * Loader hits a "wait state" where it has to wait on the audio to finish
  542. * playing before it can continue to load, it sets a "sleep" flag and
  543. * just returns. The sleep flag is checked on entry to see if it needs
  544. * to jump to the proper execution point. This may improve performance on
  545. * some platforms, but it also allows the Loader to be called regardless
  546. * of the size of the buffers; if the buffers fill up or the audio fails
  547. * to play, the Loader won't just get stuck.
  548. *
  549. * INPUTS
  550. * VQA - Pointer to VQAHandle structure.
  551. *
  552. * RESULT
  553. * Error - 0 if successful or VQAERR_??? error code.
  554. *
  555. ****************************************************************************/
  556. long VQA_LoadFrame(VQAHandle *vqa)
  557. {
  558. VQAHandleP *vqap;
  559. VQAData *vqabuf;
  560. VQALoader *loader;
  561. VQAFrameNode *curframe;
  562. ChunkHeader *chunk;
  563. unsigned long iffsize;
  564. long frame_loaded = 0;
  565. /* Dereference commonly used data members for quicker access. */
  566. vqap = (VQAHandleP *)vqa;
  567. vqabuf = vqap->VQABuf;
  568. loader = &vqabuf->Loader;
  569. curframe = loader->CurFrame;
  570. chunk = &loader->CurChunkHdr;
  571. /* We have reached the end of the file if we loaded all the frames. */
  572. if (loader->CurFrameNum >= vqap->Header.Frames) {
  573. return (VQAERR_EOF);
  574. }
  575. /* If we're reading audio from a VOC file then service that requirement. */
  576. #if(VQAVOC_ON && VQAAUDIO_ON)
  577. if (vqap->vocfh != -1) {
  578. Load_AudFrame(vqap);
  579. }
  580. #endif /* VQAAUDIO_ON & VQAVOC_ON */
  581. /* If no buffer is available for loading then return. This allows the
  582. * drawer to service one of the buffers more readily. (We'll wait for one
  583. * to free up).
  584. */
  585. if (curframe->Flags & VQAFRMF_LOADED) {
  586. loader->WaitsOnDrawer++;
  587. return (VQAERR_NOBUFFER);
  588. }
  589. /* If we're not sleeping, initialize */
  590. if (!(vqabuf->Flags & VQADATF_LSLEEP)) {
  591. frame_loaded = 0;
  592. loader->FrameSize = 0;
  593. /* Initialize the codebook ptr for the frame we're about to load:
  594. * (This frame's codebook is the last full codebook; we have to init it
  595. * now, because if we're on the last frame in a group, we'll get a new
  596. * FullCB pointer.)
  597. */
  598. curframe->Codebook = loader->FullCB;
  599. }
  600. /*-------------------------------------------------------------------------
  601. * THE MAIN LOADER LOOP
  602. *-----------------------------------------------------------------------*/
  603. while (frame_loaded == 0) {
  604. /* Read new chunk, only if we're not sleeping */
  605. if (!(vqabuf->Flags & VQADATF_LSLEEP)) {
  606. /* Read chunk ID */
  607. if (vqap->IOHandler(vqa, VQACMD_READ, chunk, 8)) {
  608. return (VQAERR_EOF);
  609. }
  610. iffsize = REVERSE_LONG(chunk->size);
  611. loader->FrameSize += iffsize;
  612. }
  613. /* Handle each chunk type */
  614. switch (chunk->id) {
  615. /* VQ Normal Frame */
  616. case ID_VQFR:
  617. if (Load_VQF(vqap, iffsize)) {
  618. return (VQAERR_READ);
  619. }
  620. frame_loaded = 1;
  621. break;
  622. /* VQ Key Frame */
  623. case ID_VQFK:
  624. if (Load_VQF(vqap, iffsize)) {
  625. return (VQAERR_READ);
  626. }
  627. /* Flag this frame as being key. */
  628. curframe->Flags |= VQAFRMF_KEY;
  629. frame_loaded = 1;
  630. break;
  631. /* Full uncompressed codebook */
  632. case ID_CBF0:
  633. if (Load_CBF0(vqap, iffsize)) {
  634. return (VQAERR_READ);
  635. }
  636. break;
  637. /* Full compressed codebook */
  638. case ID_CBFZ:
  639. if (Load_CBFZ(vqap, iffsize)) {
  640. return (VQAERR_READ);
  641. }
  642. break;
  643. /* Partial uncompressed codebook */
  644. case ID_CBP0:
  645. if (Load_CBP0(vqap, iffsize)) {
  646. return (VQAERR_READ);
  647. }
  648. break;
  649. /* Partial compressed codebook */
  650. case ID_CBPZ:
  651. if (Load_CBPZ(vqap, iffsize)) {
  652. return (VQAERR_READ);
  653. }
  654. break;
  655. /* Uncompressed palette */
  656. case ID_CPL0:
  657. if (Load_CPL0(vqap, iffsize)) {
  658. return (VQAERR_READ);
  659. }
  660. /* Flag this frame as having a palette. */
  661. curframe->Flags |= VQAFRMF_PALETTE;
  662. break;
  663. /* Compressed palette */
  664. case ID_CPLZ:
  665. if (Load_CPLZ(vqap, iffsize)) {
  666. return (VQAERR_READ);
  667. }
  668. /* Flag this frame as having a palette. */
  669. curframe->Flags |= VQAFRMF_PALETTE;
  670. break;
  671. /* Uncompressed pointer data */
  672. case ID_VPT0:
  673. if (Load_VPT0(vqap, iffsize)) {
  674. return (VQAERR_READ);
  675. }
  676. frame_loaded = 1;
  677. break;
  678. /* Compressed pointer data */
  679. case ID_VPTZ:
  680. case ID_VPTD:
  681. if (Load_VPTZ(vqap, iffsize)) {
  682. return (VQAERR_READ);
  683. }
  684. frame_loaded = 1;
  685. break;
  686. /* Pointer data Key (Must draw) */
  687. case ID_VPTK:
  688. if (Load_VPTZ(vqap, iffsize)) {
  689. return (VQAERR_READ);
  690. }
  691. /* Flag this frame as being key. */
  692. curframe->Flags |= VQAFRMF_KEY;
  693. frame_loaded = 1;
  694. break;
  695. /* Uncompressed audio frame.
  696. *
  697. * - Make sure the sound load buffer (Audio.TempBuf) is empty; if not
  698. * go into a sleep state.
  699. * - Load the data into TempBuf.
  700. */
  701. #if(VQAAUDIO_ON)
  702. case ID_SND0:
  703. if (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {
  704. /* Move the last audio frame to the play buffer. */
  705. if (CopyAudio(vqap) == VQAERR_SLEEPING) {
  706. vqabuf->Flags |= VQADATF_LSLEEP;
  707. return (VQAERR_SLEEPING);
  708. } else {
  709. vqabuf->Flags &= (~VQADATF_LSLEEP);
  710. }
  711. /* Load an uncompressed audio frame. */
  712. if (Load_SND0(vqap, iffsize) != 0) {
  713. return (VQAERR_READ);
  714. }
  715. } else {
  716. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  717. PADSIZE(iffsize))) {
  718. return (VQAERR_SEEK);
  719. }
  720. }
  721. break;
  722. case ID_SNA0:
  723. if (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {
  724. /* Move the last audio frame to the play buffer. */
  725. if (CopyAudio(vqap) == VQAERR_SLEEPING) {
  726. vqabuf->Flags |= VQADATF_LSLEEP;
  727. return (VQAERR_SLEEPING);
  728. } else {
  729. vqabuf->Flags &= (~VQADATF_LSLEEP);
  730. }
  731. /* Load an uncompressed audio frame. */
  732. if (Load_SND0(vqap, iffsize) != 0) {
  733. return (VQAERR_READ);
  734. }
  735. } else {
  736. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  737. PADSIZE(iffsize))) {
  738. return (VQAERR_SEEK);
  739. }
  740. }
  741. break;
  742. /* Compressed audio frame.
  743. *
  744. * - Make sure the sound load buffer (Audio.TempBuf) is empty; if not
  745. * go into a sleep state.
  746. * - Load the data into TempBuf.
  747. */
  748. case ID_SND1:
  749. if (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {
  750. /* Move the last audio frame to the play buffer. */
  751. if (CopyAudio(vqap) == VQAERR_SLEEPING) {
  752. vqabuf->Flags |= VQADATF_LSLEEP;
  753. return (VQAERR_SLEEPING);
  754. } else {
  755. vqabuf->Flags &= (~VQADATF_LSLEEP);
  756. }
  757. /* Load a compressed audio frame. */
  758. if (Load_SND1(vqap, iffsize) != 0) {
  759. return (VQAERR_READ);
  760. }
  761. } else {
  762. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  763. PADSIZE(iffsize))) {
  764. return (VQAERR_SEEK);
  765. }
  766. }
  767. break;
  768. case ID_SNA1:
  769. if (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {
  770. /* Move the last audio frame to the play buffer. */
  771. if (CopyAudio(vqap) == VQAERR_SLEEPING) {
  772. vqabuf->Flags |= VQADATF_LSLEEP;
  773. return (VQAERR_SLEEPING);
  774. } else {
  775. vqabuf->Flags &= (~VQADATF_LSLEEP);
  776. }
  777. /* Load a compressed audio frame. */
  778. if (Load_SND1(vqap, iffsize) != 0) {
  779. return (VQAERR_READ);
  780. }
  781. } else {
  782. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  783. PADSIZE(iffsize))) {
  784. return (VQAERR_SEEK);
  785. }
  786. }
  787. break;
  788. /* HMI ADPCM compressed audio frame.
  789. *
  790. * - Make sure the sound load buffer (Audio.TempBuf) is empty; if not
  791. * go into a sleep state.
  792. * - Load the data into TempBuf.
  793. */
  794. case ID_SND2:
  795. if (!(vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO)) {
  796. /* Move the last audio frame to the play buffer. */
  797. if (CopyAudio(vqap) == VQAERR_SLEEPING) {
  798. vqabuf->Flags |= VQADATF_LSLEEP;
  799. return (VQAERR_SLEEPING);
  800. } else {
  801. vqabuf->Flags &= (~VQADATF_LSLEEP);
  802. }
  803. /* Load a compressed audio frame. */
  804. if (Load_SND2(vqap, iffsize) != 0) {
  805. return (VQAERR_READ);
  806. }
  807. } else {
  808. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  809. PADSIZE(iffsize))) {
  810. return (VQAERR_SEEK);
  811. }
  812. }
  813. break;
  814. case ID_SNA2:
  815. if (vqap->Config.OptionFlags & VQAOPTF_ALTAUDIO) {
  816. /* Move the last audio frame to the play buffer. */
  817. if (CopyAudio(vqap) == VQAERR_SLEEPING) {
  818. vqabuf->Flags |= VQADATF_LSLEEP;
  819. return (VQAERR_SLEEPING);
  820. } else {
  821. vqabuf->Flags &= (~VQADATF_LSLEEP);
  822. }
  823. /* Load a compressed audio frame. */
  824. if (Load_SND2(vqap, iffsize) != 0) {
  825. return (VQAERR_READ);
  826. }
  827. } else {
  828. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  829. PADSIZE(iffsize))) {
  830. return (VQAERR_SEEK);
  831. }
  832. }
  833. break;
  834. #endif
  835. /* Skip any unknown chunks. */
  836. default:
  837. if (vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_CUR,
  838. PADSIZE(iffsize))) {
  839. return (VQAERR_SEEK);
  840. }
  841. break;
  842. }
  843. }
  844. /* Update maximum frame size stat. */
  845. if ((loader->CurFrameNum>0) && (loader->FrameSize>loader->MaxFrameSize)) {
  846. loader->MaxFrameSize = loader->FrameSize;
  847. }
  848. /*-------------------------------------------------------------------------
  849. * SET UP THE FRAME FOR DRAWING.
  850. *-----------------------------------------------------------------------*/
  851. /* Set the frame # */
  852. curframe->FrameNum = loader->CurFrameNum;
  853. loader->CurFrameNum++;
  854. /* Update data for mono output */
  855. loader->LastFrameNum = loader->CurFrameNum;
  856. /* Loader is finished with this frame; tell Drawer to draw it */
  857. curframe->Flags |= VQAFRMF_LOADED;
  858. loader->CurFrame = curframe->Next;
  859. return (0);
  860. }
  861. /****************************************************************************
  862. *
  863. * NAME
  864. * VQA_SeekFrame - Position the movie stream to the specified frame.
  865. *
  866. * SYNOPSIS
  867. * Frame = VQA_SeekFrame(VQA, Frame, FromWhere)
  868. *
  869. * long VQA_SeekFrame(VQAHandle *, long, long);
  870. *
  871. * FUNCTION
  872. * This function sets the movie stream to the new frame specified by
  873. * the 'offset' parameter. 'FromWhere' is a symbolic constant that is used
  874. * to specify from where in the stream offset should be applied.
  875. *
  876. * INPUTS
  877. * VQA - Pointer to VQAHandle of movie to seek into.
  878. * Frame - Frame to seek to.
  879. * FromWhere - Relative position indicator.
  880. *
  881. * RESULT
  882. * Frame - New frame position or -1 if error.
  883. *
  884. ****************************************************************************/
  885. long VQA_SeekFrame(VQAHandle *vqa, long framenum, long fromwhere)
  886. {
  887. VQAHandleP *vqap;
  888. VQAData *vqabuf;
  889. VQALoader *loader;
  890. VQAHeader *header;
  891. VQAFrameNode *frame;
  892. long group;
  893. long i;
  894. long rc = VQAERR_SLEEPING;
  895. #if(VQAAUDIO_ON)
  896. VQAConfig *config;
  897. VQAAudio *audio;
  898. long audio_on;
  899. #endif
  900. /* Dereference commonly used data members for quick access. */
  901. vqap = (VQAHandleP *)vqa;
  902. vqabuf = vqap->VQABuf;
  903. loader = &vqabuf->Loader;
  904. header = &vqap->Header;
  905. #if(VQAAUDIO_ON)
  906. config = &vqap->Config;
  907. #endif
  908. fromwhere = fromwhere;
  909. #if(VQAAUDIO_ON)
  910. audio = &vqabuf->Audio;
  911. /* Stop audio playback. */
  912. audio_on = (audio->Flags & VQAAUDF_ISPLAYING);
  913. VQA_StopAudio(vqap);
  914. #endif
  915. /* Make sure the requested frame is valid and the frame information
  916. * array is allocated before continuing.
  917. */
  918. if ((framenum < header->Frames) && (vqabuf->Foff != NULL)) {
  919. /* Get the current frame. */
  920. frame = loader->CurFrame;
  921. /* Find and load the most recent palette. */
  922. for (i = framenum; i >= 0; i--) {
  923. if (vqabuf->Foff[i] & VQAFINF_PAL) {
  924. /* Seek to the palette frame. */
  925. rc = vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_SET,
  926. VQAFRAME_OFFSET(vqabuf->Foff[i]));
  927. if (!rc) {
  928. /* Fool the loader into thinking this frame is empty. */
  929. loader->NumPartialCB = 0;
  930. loader->PartialCBSize = 0;
  931. loader->FullCB = vqabuf->CBData;
  932. loader->CurCB = vqabuf->CBData;
  933. loader->CurFrameNum = 0;
  934. frame->Flags = 0;
  935. /* Load the frame with the palette. */
  936. if (VQA_LoadFrame(vqa) == 0) {
  937. /* Decompress the palette if neccessary.*/
  938. if (frame->Flags & VQAFRMF_PALCOMP) {
  939. frame->PaletteSize = LCW_Uncompress((char *)frame->Palette
  940. + frame->PalOffset, (char *)frame->Palette,
  941. vqabuf->Max_Pal_Size);
  942. }
  943. SetPalette(frame->Palette, frame->PaletteSize, 0);
  944. }
  945. } else {
  946. rc = VQAERR_SEEK;
  947. }
  948. break;
  949. }
  950. }
  951. if (!rc) {
  952. /* Compute the starting group frame of the requested frame. */
  953. group = (framenum / header->Groupsize);
  954. group = (group * header->Groupsize);
  955. /* The codebook for the group we want to goto is found in the previous
  956. * group, with the exception of the very first group.
  957. */
  958. if (group >= header->Groupsize) {
  959. group -= header->Groupsize;
  960. }
  961. /* Seek to the start of the group containing the partial codebooks for
  962. * the target frame.
  963. */
  964. if (!vqap->IOHandler(vqa, VQACMD_SEEK, (void *)SEEK_SET,
  965. VQAFRAME_OFFSET(vqabuf->Foff[group]))) {
  966. /* Throw away any audio frames that were loaded. */
  967. #if(VQAAUDIO_ON)
  968. if ((config->OptionFlags & VQAOPTF_AUDIO)
  969. && (audio->Buffer != NULL)) {
  970. memset(audio->IsLoaded, 0, audio->NumAudBlocks * sizeof(short));
  971. memset(audio->Buffer, 0, config->AudioBufSize);
  972. /* Position the audio buffer to 1/2 second. */
  973. audio->AudBufPos = (long)(((audio->SampleRate * audio->Channels)
  974. * (audio->BitsPerSample >> 3)) / 2);
  975. /* Mark 1/2 second of the audio buffer as loaded. */
  976. for (i = 0; i < (audio->AudBufPos / config->HMIBufSize); i++) {
  977. audio->IsLoaded[i] = 1;
  978. }
  979. }
  980. #endif
  981. /* Force the loader to the desired frame. */
  982. loader->NumPartialCB = 0;
  983. loader->PartialCBSize = 0;
  984. loader->FullCB = vqabuf->CBData;
  985. loader->CurCB = vqabuf->CBData;
  986. loader->CurFrameNum = group;
  987. /* Load frames up to the target frame collecting partial codebooks
  988. * along the way.
  989. */
  990. for (i = 0; i < (framenum - group); i++) {
  991. /* Fool the loader into thinking the frame has been drawn. */
  992. loader->CurFrame->Flags = 0;
  993. #if(VQAAUDIO_ON)
  994. audio->TempBufLen = 0;
  995. #endif
  996. /* Load the frame. */
  997. if ((rc = VQA_LoadFrame(vqa)) != 0) {
  998. if ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {
  999. break;
  1000. } else {
  1001. rc = 0;
  1002. }
  1003. }
  1004. }
  1005. /* If everything is okay, then re-prime the buffers. */
  1006. if (!rc) {
  1007. /* Mark all the frames except the current one as empty. */
  1008. loader->CurFrame->Flags = 0;
  1009. frame = loader->CurFrame->Next;
  1010. while (frame != loader->CurFrame) {
  1011. frame->Flags = 0;
  1012. frame = frame->Next;
  1013. }
  1014. /* Set the drawer to the current frame and the loader
  1015. * to the next.
  1016. */
  1017. vqabuf->Drawer.CurFrame = loader->CurFrame;
  1018. /* Prime the buffers for the new position. */
  1019. rc = PrimeBuffers(vqa);
  1020. /* An end of file is not considered and error. */
  1021. if ((rc == 0) || (rc == VQAERR_EOF)) {
  1022. rc = framenum;
  1023. }
  1024. }
  1025. } else {
  1026. rc = VQAERR_SEEK;
  1027. }
  1028. }
  1029. }
  1030. /* Restart audio playback. */
  1031. #if(VQAAUDIO_ON)
  1032. if (audio_on) {
  1033. VQA_StartAudio(vqap);
  1034. }
  1035. #endif
  1036. return (rc);
  1037. }
  1038. /****************************************************************************
  1039. *
  1040. * NAME
  1041. * AllocBuffers - Allocate VQA play buffers.
  1042. *
  1043. * SYNOPSIS
  1044. * VQAData = AllocBuffers(Header, Config)
  1045. *
  1046. * VQAData *AllocBuffers(VQAHeader *, VQAConfig *);
  1047. *
  1048. * FUNCTION
  1049. * For those structures that contain buffer pointers (codebook nodes,
  1050. * frame buffer nodes), enough memory is allocated for both the structure
  1051. * and its associated buffers, then the buffer pointers are pointed to
  1052. * the appropriate offset from the structure pointer. This allows us
  1053. * to perform only one malloc & free for each node.
  1054. *
  1055. * Buffers allocated:
  1056. * - vqa
  1057. * - vqa->CBData (list)
  1058. * - vqa->FrameData (list)
  1059. * - vqa->Drawer.ImageBuf
  1060. * - vqa->Audio.Buffer
  1061. * - vqa->Audio.IsLoaded
  1062. * - vqa->Foff
  1063. *
  1064. * INPUTS
  1065. * Header - Pointer to VQAHeader structure.
  1066. * Config - Pointer to VQA configuration structure.
  1067. *
  1068. * RESULT
  1069. * VQAData - Pointer to initialized VQAData structure.
  1070. *
  1071. ****************************************************************************/
  1072. static VQAData *AllocBuffers(VQAHeader *header, VQAConfig *config)
  1073. {
  1074. VQAData *vqa;
  1075. VQACBNode *cbnode;
  1076. VQACBNode *this_cb;
  1077. VQAFrameNode *framenode;
  1078. VQAFrameNode *this_frame;
  1079. long i;
  1080. /* Check the configuration for valid values. */
  1081. if ((config->NumCBBufs == 0) || (config->NumFrameBufs == 0)) {
  1082. return (NULL);
  1083. }
  1084. /* Allocate the master structure */
  1085. if ((vqa = (VQAData *)malloc(sizeof(VQAData))) == NULL) {
  1086. return (NULL);
  1087. }
  1088. /*-------------------------------------------------------------------------
  1089. * INITIALIZE THE VQA DATA STRUCTURES.
  1090. *
  1091. * Pointers are set to NULL initially, and filled in as the buffers are
  1092. * allocated. The Max buffer sizes are computed with 1K of padding,
  1093. * and'd with 0xFFFC to make the size divisible by 4, to ensure DWORD
  1094. * alignment.
  1095. *-----------------------------------------------------------------------*/
  1096. DPMI_Lock(vqa, sizeof(VQAData));
  1097. memset(vqa, 0, sizeof(VQAData));
  1098. vqa->MemUsed = sizeof(VQAData);
  1099. vqa->Drawer.LastTime = (-VQA_TIMETICKS);
  1100. /* Set maximum codebook size. */
  1101. vqa->Max_CB_Size = ((header->CBentries) * header->BlockWidth
  1102. * header->BlockHeight + 250) & 0xFFFC;
  1103. /* Set maximum palette size. */
  1104. vqa->Max_Pal_Size = (768 + 1024) & 0xFFFC;
  1105. /* Set maximum vector pointers size. */
  1106. vqa->Max_Ptr_Size = ((header->ImageWidth / header->BlockWidth)
  1107. * (header->ImageHeight / header->BlockHeight)
  1108. * sizeof(short) + 1024) & 0xFFFC;
  1109. /* Set the frame number of the frame containing the last codebook. */
  1110. vqa->Loader.LastCBFrame = (((header->Frames - 1) / header->Groupsize)
  1111. * header->Groupsize);
  1112. /*-------------------------------------------------------------------------
  1113. * ALLOCATE THE CODEBOOK BUFFERS.
  1114. *-----------------------------------------------------------------------*/
  1115. for (i = 0; i < config->NumCBBufs; i++) {
  1116. /* Allocate a codebook node. */
  1117. cbnode = (VQACBNode *)malloc((sizeof(VQACBNode) + vqa->Max_CB_Size));
  1118. /* If failure then clean up and exit. */
  1119. if (cbnode == NULL) {
  1120. FreeBuffers(vqa, config, header);
  1121. return (NULL);
  1122. }
  1123. /* Lock the buffer to prevent page swapping. */
  1124. DPMI_Lock(cbnode, (sizeof(VQACBNode) + vqa->Max_CB_Size));
  1125. /* Keep count of the memory usage. */
  1126. vqa->MemUsed += (long)(sizeof(VQACBNode) + vqa->Max_CB_Size);
  1127. /* Initialize the node */
  1128. memset(cbnode, 0, sizeof(VQACBNode));
  1129. cbnode->Buffer = (unsigned char *)cbnode + sizeof(VQACBNode);
  1130. /* Install the node */
  1131. if (i == 0) {
  1132. vqa->CBData = cbnode;
  1133. this_cb = cbnode;
  1134. } else {
  1135. this_cb->Next = cbnode;
  1136. this_cb = cbnode;
  1137. }
  1138. }
  1139. /* Make the list circular */
  1140. cbnode->Next = vqa->CBData;
  1141. /* Install the Codebook list */
  1142. vqa->Loader.CurCB = vqa->CBData;
  1143. vqa->Loader.FullCB = vqa->CBData;
  1144. /*-------------------------------------------------------------------------
  1145. * ALLOCATE THE FRAME BUFFERS.
  1146. *-----------------------------------------------------------------------*/
  1147. for (i = 0; i < config->NumFrameBufs; i++) {
  1148. /* Allocate a pointer node */
  1149. framenode = (VQAFrameNode *)malloc((sizeof(VQAFrameNode)
  1150. + vqa->Max_Ptr_Size + vqa->Max_Pal_Size));
  1151. /* If failure then clean up and exit. */
  1152. if (framenode == NULL) {
  1153. FreeBuffers(vqa, config, header);
  1154. return (NULL);
  1155. }
  1156. /* Lock the buffer to prevent page swapping. */
  1157. DPMI_Lock(framenode, sizeof(VQAFrameNode) + vqa->Max_Ptr_Size
  1158. + vqa->Max_Pal_Size);
  1159. /* Keep count of the memory usage. */
  1160. vqa->MemUsed += (long)(sizeof(VQAFrameNode) + vqa->Max_Ptr_Size
  1161. + vqa->Max_Pal_Size);
  1162. /* Initialize the node */
  1163. memset(framenode, 0, sizeof(VQAFrameNode));
  1164. framenode->Pointers = (unsigned char *)framenode + sizeof(VQAFrameNode);
  1165. framenode->Palette = (unsigned char *)framenode + sizeof(VQAFrameNode)
  1166. + vqa->Max_Ptr_Size;
  1167. framenode->Codebook = vqa->CBData;
  1168. /* Install the node */
  1169. if (i == 0) {
  1170. vqa->FrameData = framenode;
  1171. this_frame = framenode;
  1172. } else {
  1173. this_frame->Next = framenode;
  1174. this_frame = framenode;
  1175. }
  1176. }
  1177. /* Make the list circular */
  1178. framenode->Next = vqa->FrameData;
  1179. /* Install the Frame Buffer list */
  1180. vqa->Loader.CurFrame = vqa->FrameData;
  1181. vqa->Drawer.CurFrame = vqa->FrameData;
  1182. vqa->Flipper.CurFrame = vqa->FrameData;
  1183. /*-------------------------------------------------------------------------
  1184. * ALLOCATE THE IMAGE BUFFERS IF ONE IS NOT ALREADY PROVIDED.
  1185. *-----------------------------------------------------------------------*/
  1186. if (config->ImageBuf == NULL) {
  1187. /* Allocate our own buffer. */
  1188. if (config->DrawFlags & VQACFGF_BUFFER) {
  1189. vqa->Drawer.ImageBuf = (unsigned char *)malloc((header->ImageWidth
  1190. * header->ImageHeight));
  1191. /* If the allocation failed we must free up and exit. */
  1192. if (vqa->Drawer.ImageBuf == NULL) {
  1193. FreeBuffers(vqa, config, header);
  1194. return (NULL);
  1195. }
  1196. /* Lock to prevent page swapping. */
  1197. DPMI_Lock(vqa->Drawer.ImageBuf,header->ImageWidth*header->ImageHeight);
  1198. /* Plugin image buffer information. */
  1199. vqa->Drawer.ImageWidth = header->ImageWidth;
  1200. vqa->Drawer.ImageHeight = header->ImageHeight;
  1201. vqa->MemUsed += (long)(header->ImageWidth * header->ImageHeight);
  1202. } else {
  1203. vqa->Drawer.ImageWidth = config->ImageWidth;
  1204. vqa->Drawer.ImageHeight = config->ImageHeight;
  1205. }
  1206. } else {
  1207. /* Use caller provided buffer */
  1208. vqa->Drawer.ImageBuf = config->ImageBuf;
  1209. vqa->Drawer.ImageWidth = config->ImageWidth;
  1210. vqa->Drawer.ImageHeight = config->ImageHeight;
  1211. }
  1212. /*-------------------------------------------------------------------------
  1213. * ALLOCATE AND INITIALIZE AUDIO BUFFERS AND STRUCTURES.
  1214. *-----------------------------------------------------------------------*/
  1215. #if(VQAAUDIO_ON)
  1216. if ((header->Flags & VQAHDF_AUDIO)
  1217. && (config->OptionFlags & VQAOPTF_AUDIO)) {
  1218. /* Dereference audio structure for quick access. */
  1219. VQAAudio *audio = &vqa->Audio;
  1220. /* Version 1 VQA's only supported 22050 8 bit mono audio. */
  1221. if (header->Version < VQAHD_VER2) {
  1222. audio->SampleRate = 22050U;
  1223. audio->Channels = 1;
  1224. audio->BitsPerSample = 8;
  1225. audio->BytesPerSec = 22050;
  1226. } else {
  1227. if ((config->OptionFlags & VQAOPTF_ALTAUDIO)
  1228. && (header->Flags & VQAHDF_ALTAUDIO)) {
  1229. audio->SampleRate = header->AltSampleRate;
  1230. audio->Channels = header->AltChannels;
  1231. audio->BitsPerSample = header->AltBitsPerSample;
  1232. } else {
  1233. audio->SampleRate = header->SampleRate;
  1234. audio->Channels = header->Channels;
  1235. audio->BitsPerSample = header->BitsPerSample;
  1236. }
  1237. audio->BytesPerSec = ((audio->SampleRate * audio->Channels)
  1238. * (audio->BitsPerSample >> 3));
  1239. }
  1240. /* Adjust the HMI buffer to accomodate the amount of data. */
  1241. #if(0)
  1242. config->HMIBufSize *= (audio->SampleRate / 22050);
  1243. config->HMIBufSize *= audio->Channels * (audio->BitsPerSample >> 3);
  1244. #endif
  1245. /* The default audio buffer size should be large enough to hold
  1246. * 1.5 seconds of data.
  1247. */
  1248. if (config->AudioBufSize == -1) {
  1249. /* Compute the number of HMI buffers that will completly fit into
  1250. * 1.5 seconds of audio data.
  1251. */
  1252. i = ((audio->BytesPerSec+(audio->BytesPerSec/2))/config->HMIBufSize);
  1253. config->AudioBufSize = (config->HMIBufSize * i);
  1254. }
  1255. /* Do not allocate anything if the audio buffer is zero length. */
  1256. if (config->AudioBufSize > 0) {
  1257. /* Allocate an audio buffer if the user did not provide one.
  1258. * Otherwise, use the user supplied buffer.
  1259. */
  1260. if (config->AudioBuf == NULL) {
  1261. audio->Buffer = (unsigned char *)malloc(config->AudioBufSize);
  1262. /* If failure then clean up and exit. */
  1263. if (audio->Buffer == NULL) {
  1264. FreeBuffers(vqa, config, header);
  1265. return (NULL);
  1266. }
  1267. DPMI_Lock(audio->Buffer, config->AudioBufSize);
  1268. /* Add audio buffer size to memory usage. */
  1269. vqa->MemUsed += config->AudioBufSize;
  1270. } else {
  1271. audio->Buffer = config->AudioBuf;
  1272. }
  1273. /* Allocate IsLoaded flags */
  1274. audio->NumAudBlocks = (config->AudioBufSize / config->HMIBufSize);
  1275. audio->IsLoaded = (short *)malloc(audio->NumAudBlocks * sizeof(short));
  1276. /* If failure then clean up and exit. */
  1277. if (audio->IsLoaded == NULL) {
  1278. FreeBuffers(vqa, config, header);
  1279. return (NULL);
  1280. }
  1281. /* Lock to prevent page swapping. */
  1282. DPMI_Lock(audio->IsLoaded, audio->NumAudBlocks * sizeof(short));
  1283. /* Add IsLoaded flags array to memory usage. */
  1284. vqa->MemUsed += (audio->NumAudBlocks * sizeof(short));
  1285. /* Initialize audio IsLoaded flags to false. */
  1286. memset(audio->IsLoaded, 0, audio->NumAudBlocks * sizeof(short));
  1287. /* Allocate temporary staging buffer for the audio frames. */
  1288. audio->TempBufSize = ((audio->BytesPerSec / header->FPS) * 2) + 100;
  1289. audio->TempBuf = (unsigned char *)malloc(audio->TempBufSize);
  1290. if (audio->TempBuf == NULL) {
  1291. FreeBuffers(vqa, config, header);
  1292. return (NULL);
  1293. }
  1294. /* Lock to prevent page swapping. */
  1295. DPMI_Lock(audio->TempBuf, audio->TempBufSize);
  1296. /* Add temporary buffer size to memory usage. */
  1297. vqa->MemUsed += audio->TempBufSize;
  1298. }
  1299. }
  1300. #endif /* VQAAUDIO_ON */
  1301. /*-------------------------------------------------------------------------
  1302. * ALLOCATE THE FRAME INFORMATION TABLE IF REQUESTED.
  1303. *-----------------------------------------------------------------------*/
  1304. vqa->Foff = (long *)malloc(header->Frames * sizeof(long));
  1305. if (vqa->Foff == NULL) {
  1306. FreeBuffers(vqa, config, header);
  1307. return (NULL);
  1308. }
  1309. /* Lock to prevent page swapping. */
  1310. DPMI_Lock(vqa->Foff, header->Frames * sizeof(long));
  1311. /* Keep a running total of memory usage. */
  1312. vqa->MemUsed += (header->Frames * sizeof(long));
  1313. return (vqa);
  1314. }
  1315. /****************************************************************************
  1316. *
  1317. * NAME
  1318. * FreeBuffers - Free VQA play buffers.
  1319. *
  1320. * SYNOPSIS
  1321. * FreeBuffers(VQAData, Config, Header)
  1322. *
  1323. * void FreeBuffers(VQAData *, VQAConfig *, VQAHeader *);
  1324. *
  1325. * FUNCTION
  1326. * Free the buffers allocated by AllocBuffers().
  1327. *
  1328. * INPUTS
  1329. * VQAData - Pointer to VQAData structure.
  1330. * Config - Pointer to configuration structure.
  1331. * Header - Pointer to movie header structure.
  1332. *
  1333. * RESULT
  1334. * NONE
  1335. *
  1336. ****************************************************************************/
  1337. static void FreeBuffers(VQAData *vqa, VQAConfig *config, VQAHeader *header)
  1338. {
  1339. VQACBNode *cb_this,
  1340. *cb_next;
  1341. VQAFrameNode *frame_this,
  1342. *frame_next;
  1343. long i;
  1344. /*-------------------------------------------------------------------------
  1345. * FREE THE FRAME INFORMATION TABLE.
  1346. *-----------------------------------------------------------------------*/
  1347. if (vqa->Foff) {
  1348. DPMI_Unlock(vqa->Foff, header->Frames * sizeof(long));
  1349. free(vqa->Foff);
  1350. }
  1351. /*-------------------------------------------------------------------------
  1352. * FREE THE AUDIO BUFFERS.
  1353. *-----------------------------------------------------------------------*/
  1354. #if(VQAAUDIO_ON)
  1355. if ((config->AudioBuf == NULL) && (vqa->Audio.Buffer)) {
  1356. DPMI_Unlock(vqa->Audio.Buffer, config->AudioBufSize);
  1357. free(vqa->Audio.Buffer);
  1358. }
  1359. /* Free the audio segments loaded flag array. */
  1360. if (vqa->Audio.IsLoaded) {
  1361. DPMI_Unlock(vqa->Audio.IsLoaded,vqa->Audio.NumAudBlocks * sizeof(short));
  1362. free(vqa->Audio.IsLoaded);
  1363. }
  1364. /* Free the temporary audio buffer. */
  1365. if (vqa->Audio.TempBuf) {
  1366. DPMI_Unlock(vqa->Audio.TempBuf, vqa->Audio.TempBufSize);
  1367. free(vqa->Audio.TempBuf);
  1368. }
  1369. #endif /* VQAAUDIO_ON */
  1370. /*-------------------------------------------------------------------------
  1371. * FREE THE IMAGE BUFFER ONLY IF WE ALLOCATED IT.
  1372. *-----------------------------------------------------------------------*/
  1373. if ((config->ImageBuf == NULL) && vqa->Drawer.ImageBuf) {
  1374. DPMI_Unlock(vqa->Drawer.ImageBuf,header->ImageWidth*header->ImageHeight);
  1375. free(vqa->Drawer.ImageBuf);
  1376. }
  1377. /*-------------------------------------------------------------------------
  1378. * FREE THE FRAME BUFFERS.
  1379. *-----------------------------------------------------------------------*/
  1380. frame_this = vqa->FrameData;
  1381. for (i = 0; i < config->NumFrameBufs; i++) {
  1382. if (frame_this) {
  1383. frame_next = frame_this->Next;
  1384. DPMI_Unlock(frame_this, sizeof(VQAFrameNode) + vqa->Max_Ptr_Size
  1385. + vqa->Max_Pal_Size);
  1386. free(frame_this);
  1387. frame_this = frame_next;
  1388. } else {
  1389. break;
  1390. }
  1391. }
  1392. /*-------------------------------------------------------------------------
  1393. * FREE THE CODEBOOK BUFFERS.
  1394. *-----------------------------------------------------------------------*/
  1395. cb_this = vqa->CBData;
  1396. for (i = 0; i < config->NumCBBufs; i++) {
  1397. if (cb_this) {
  1398. cb_next = cb_this->Next;
  1399. DPMI_Unlock(cb_this, sizeof(VQACBNode) + vqa->Max_CB_Size);
  1400. free(cb_this);
  1401. cb_this = cb_next;
  1402. } else {
  1403. break;
  1404. }
  1405. }
  1406. /*-------------------------------------------------------------------------
  1407. * FREE THE VQA DATA STRUCTURES.
  1408. *-----------------------------------------------------------------------*/
  1409. DPMI_Unlock(vqa, sizeof(VQAData));
  1410. free(vqa);
  1411. }
  1412. /****************************************************************************
  1413. *
  1414. * NAME
  1415. * PrimeBuffers - Pre-Load the internal buffers.
  1416. *
  1417. * SYNOPSIS
  1418. * Error = PrimeBuffers(VQA)
  1419. *
  1420. * long = PrimeBuffers(VQAHandle *);
  1421. *
  1422. * FUNCTION
  1423. * Pre-load the internal buffers in order to give the player some slack
  1424. * in the playback of large frames.
  1425. *
  1426. * INPUTS
  1427. * VQA - Pointer to VQAHandle structure.
  1428. *
  1429. * RESULT
  1430. * Error - 0 if successful, or VQAERR_??? error code.
  1431. *
  1432. ****************************************************************************/
  1433. long PrimeBuffers(VQAHandle *vqa)
  1434. {
  1435. VQAData *vqabuf;
  1436. VQAConfig *config;
  1437. long rc;
  1438. long i;
  1439. /* Dereference commonly used data members for quick access. */
  1440. vqabuf = ((VQAHandleP *)vqa)->VQABuf;
  1441. config = &((VQAHandleP *)vqa)->Config;
  1442. /* Pre-load the buffers */
  1443. for (i = 0; i < config->NumFrameBufs; i++) {
  1444. if ((rc = VQA_LoadFrame(vqa)) == 0) {
  1445. vqabuf->LoadedFrames++;
  1446. }
  1447. else if ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {
  1448. return (rc);
  1449. }
  1450. }
  1451. return (0);
  1452. }
  1453. /****************************************************************************
  1454. *
  1455. * NAME
  1456. * Load_VQF - Loads a VQ Frame chunk.
  1457. *
  1458. * SYNOPSIS
  1459. * Error = Load_VQF(VQA, Iffsize)
  1460. *
  1461. * long Load_VQF(VQAHandleP *, unsigned long);
  1462. *
  1463. * FUNCTION
  1464. * The VQ Frame Chunk contains a set of other chunks (codebooks,
  1465. * palettes, pointers). This routine reads the frame's chunk size,
  1466. * then loops until it's read that many bytes.
  1467. *
  1468. * INPUTS
  1469. * VQA - Pointer to private VQA handle.
  1470. * Iffsize - Size of IFF chunk.
  1471. *
  1472. * RESULT
  1473. * Error - 0 if successful or VQAERR_??? error code.
  1474. *
  1475. ****************************************************************************/
  1476. static long Load_VQF(VQAHandleP *vqap, unsigned long frame_iffsize)
  1477. {
  1478. VQAData *vqabuf;
  1479. VQAFrameNode *curframe;
  1480. ChunkHeader *chunk;
  1481. unsigned long iffsize;
  1482. unsigned long framesize;
  1483. unsigned long bytes_loaded = 0;
  1484. /* Dereference commonly used data members for quicker access. */
  1485. vqabuf = vqap->VQABuf;
  1486. curframe = vqabuf->Loader.CurFrame;
  1487. chunk = &vqabuf->Loader.CurChunkHdr;
  1488. framesize = PADSIZE(frame_iffsize);
  1489. /*-------------------------------------------------------------------------
  1490. * FRAME LOADING LOOP.
  1491. *-----------------------------------------------------------------------*/
  1492. while (bytes_loaded < framesize) {
  1493. /* Read chunk ID */
  1494. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, chunk, 8)) {
  1495. return (VQAERR_EOF);
  1496. }
  1497. iffsize = REVERSE_LONG(chunk->size);
  1498. bytes_loaded += 8;
  1499. bytes_loaded += PADSIZE(iffsize);
  1500. /* Handle each chunk type */
  1501. switch (chunk->id) {
  1502. /* Full uncompressed codebook */
  1503. case ID_CBF0:
  1504. if (Load_CBF0(vqap, iffsize)) {
  1505. return (VQAERR_READ);
  1506. }
  1507. break;
  1508. /* Full compressed codebook */
  1509. case ID_CBFZ:
  1510. if (Load_CBFZ(vqap, iffsize)) {
  1511. return (VQAERR_READ);
  1512. }
  1513. break;
  1514. /* Partial uncompressed codebook */
  1515. case ID_CBP0:
  1516. if (Load_CBP0(vqap, iffsize)) {
  1517. return (VQAERR_READ);
  1518. }
  1519. break;
  1520. /* Partial compressed codebook */
  1521. case ID_CBPZ:
  1522. if (Load_CBPZ(vqap, iffsize)) {
  1523. return (VQAERR_READ);
  1524. }
  1525. break;
  1526. /* Uncompressed palette */
  1527. case ID_CPL0:
  1528. if (Load_CPL0(vqap, iffsize)) {
  1529. return (VQAERR_READ);
  1530. }
  1531. /* Flag this frame as having a palette. */
  1532. curframe->Flags |= VQAFRMF_PALETTE;
  1533. break;
  1534. /* Compressed palette */
  1535. case ID_CPLZ:
  1536. if (Load_CPLZ(vqap, iffsize)) {
  1537. return (VQAERR_READ);
  1538. }
  1539. /* Flag this frame as having a palette. */
  1540. curframe->Flags |= VQAFRMF_PALETTE;
  1541. break;
  1542. /* Uncompressed pointer data */
  1543. case ID_VPT0:
  1544. if (Load_VPT0(vqap, iffsize)) {
  1545. return (VQAERR_READ);
  1546. }
  1547. break;
  1548. /* Compressed pointer data */
  1549. case ID_VPTZ:
  1550. case ID_VPTD:
  1551. if (Load_VPTZ(vqap, iffsize)) {
  1552. return (VQAERR_READ);
  1553. }
  1554. break;
  1555. /* Compressed pointer data */
  1556. case ID_VPTK:
  1557. if (Load_VPTZ(vqap, iffsize)) {
  1558. return (VQAERR_READ);
  1559. }
  1560. /* Flag this frame as being key. */
  1561. curframe->Flags |= VQAFRMF_KEY;
  1562. break;
  1563. /* An unknown chunk in the video frame is an error. */
  1564. default:
  1565. return (VQAERR_READ);
  1566. }
  1567. }
  1568. return (0);
  1569. }
  1570. /****************************************************************************
  1571. *
  1572. * NAME
  1573. * Load_FINF - Load Frame Info chunk.
  1574. *
  1575. * SYNOPSIS
  1576. * Error = Load_FINF(VQA, Iffsize)
  1577. *
  1578. * long Load_FINF(VQAHandleP *, unsigned long);
  1579. *
  1580. * FUNCTION
  1581. * Load FINF chunk if buffer available, otherwise skip it.
  1582. *
  1583. * INPUTS
  1584. * VQA - Pointer to private VQA handle.
  1585. * Iffsize - Size of IFF chunk.
  1586. *
  1587. * RESULT
  1588. * Error - 0 if successful or VQAERR_??? error code.
  1589. *
  1590. ****************************************************************************/
  1591. static long Load_FINF(VQAHandleP *vqap, unsigned long iffsize)
  1592. {
  1593. VQAData *vqabuf;
  1594. /* Dereference commonly used data members for quicker access. */
  1595. vqabuf = vqap->VQABuf;
  1596. /* Load the frame information table if we need to, otherwise we will
  1597. * skip it.
  1598. */
  1599. if (vqabuf->Foff != NULL) {
  1600. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, vqabuf->Foff,
  1601. PADSIZE(iffsize))) {
  1602. return (VQAERR_READ);
  1603. }
  1604. } else {
  1605. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,
  1606. PADSIZE(iffsize))) {
  1607. return (VQAERR_SEEK);
  1608. }
  1609. }
  1610. return (0);
  1611. }
  1612. /****************************************************************************
  1613. *
  1614. * NAME
  1615. * Load_VQHD - Load VQA header chunk.
  1616. *
  1617. * SYNOPSIS
  1618. * Error = Load_VQHD(VQA, Iffsize)
  1619. *
  1620. * long Load_VQHD(VQAHandleP *, unsigned long);
  1621. *
  1622. * FUNCTION
  1623. *
  1624. * INPUTS
  1625. * VQA - Pointer to private VQA handle.
  1626. * Iffsize - Size of IFF chunk.
  1627. *
  1628. * RESULT
  1629. * Error - 0 if successful or VQAERR_??? error code.
  1630. *
  1631. ****************************************************************************/
  1632. static long Load_VQHD(VQAHandleP *vqap, unsigned long iffsize)
  1633. {
  1634. /* Read the header */
  1635. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, &vqap->Header,
  1636. PADSIZE(iffsize))) {
  1637. return (VQAERR_READ);
  1638. }
  1639. /* Reconfigure the Drawer for the new settings */
  1640. VQA_Configure_Drawer(vqap);
  1641. return (0);
  1642. }
  1643. /****************************************************************************
  1644. *
  1645. * NAME
  1646. * Load_CBF0 - Load full uncompressed codebook.
  1647. *
  1648. * SYNOPSIS
  1649. * Error = Load_CBF0(VQA, Iffsize)
  1650. *
  1651. * long Load_CBF0(VQAHandleP *, unsigned long);
  1652. *
  1653. * FUNCTION
  1654. *
  1655. * INPUTS
  1656. * VQA - Pointer to private VQA handle.
  1657. * Iffsize - Size of IFF chunk.
  1658. *
  1659. * RESULT
  1660. * Error - 0 if successful or VQAERR_??? error code.
  1661. *
  1662. ****************************************************************************/
  1663. static long Load_CBF0(VQAHandleP *vqap, unsigned long iffsize)
  1664. {
  1665. VQALoader *loader;
  1666. VQACBNode *curcb;
  1667. /* Dereference commonly used data members for quicker access. */
  1668. loader = &vqap->VQABuf->Loader;
  1669. curcb = loader->CurCB;
  1670. /* Read into the start of the buffer */
  1671. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curcb->Buffer,
  1672. PADSIZE(iffsize))) {
  1673. return (VQAERR_READ);
  1674. }
  1675. /* Reset the partial codebook counter. */
  1676. loader->NumPartialCB = 0;
  1677. /* Flag this codebook as uncompressed. */
  1678. curcb->Flags &= (~VQACBF_CBCOMP);
  1679. curcb->CBOffset = 0;
  1680. /* Clock pointers to next CB Buffer. */
  1681. loader->FullCB = curcb;
  1682. loader->FullCB->Flags &= (~VQACBF_DOWNLOADED);
  1683. loader->CurCB = curcb->Next;
  1684. return (0);
  1685. }
  1686. /****************************************************************************
  1687. *
  1688. * NAME
  1689. * Load_CBFZ - Load full compressed codebook.
  1690. *
  1691. * SYNOPSIS
  1692. * Error = Load_CBFZ(VQA, Iffsize)
  1693. *
  1694. * long Load_CBFZ(VQAHandleP *, unsigned long);
  1695. *
  1696. * FUNCTION
  1697. *
  1698. * INPUTS
  1699. * VQA - Pointer to private VQA handle.
  1700. * Iffsize - Size of IFF chunk.
  1701. *
  1702. * RESULT
  1703. * Error - 0 if successful or VQAERR_??? error code.
  1704. *
  1705. ****************************************************************************/
  1706. static long Load_CBFZ(VQAHandleP *vqap, unsigned long iffsize)
  1707. {
  1708. VQALoader *loader;
  1709. VQACBNode *curcb;
  1710. void *buffer;
  1711. unsigned long padsize;
  1712. unsigned long lcwoffset;
  1713. /* Dereference commonly used data members for quicker access. */
  1714. loader = &vqap->VQABuf->Loader;
  1715. curcb = loader->CurCB;
  1716. padsize = PADSIZE(iffsize);
  1717. /* Load the codebook into the end of the buffer. */
  1718. lcwoffset = vqap->VQABuf->Max_CB_Size - padsize;
  1719. buffer = curcb->Buffer + lcwoffset;
  1720. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {
  1721. return (VQAERR_READ);
  1722. }
  1723. /* Reset the partial codebook counter. */
  1724. loader->NumPartialCB = 0;
  1725. /* Flag this codebook as compressed */
  1726. curcb->Flags |= VQACBF_CBCOMP;
  1727. curcb->CBOffset = lcwoffset;
  1728. /* Clock pointers to next CB Buffer */
  1729. loader->FullCB = curcb;
  1730. loader->FullCB->Flags &= (~VQACBF_DOWNLOADED);
  1731. loader->CurCB = curcb->Next;
  1732. return (0);
  1733. }
  1734. /****************************************************************************
  1735. *
  1736. * NAME
  1737. * Load_CBP0 - Load partial uncompressed codebook.
  1738. *
  1739. * SYNOPSIS
  1740. * Error = Load_CBP0(VQA, Iffsize)
  1741. *
  1742. * long Load_CBP0(VQAHandleP *, unsigned long);
  1743. *
  1744. * FUNCTION
  1745. *
  1746. * INPUTS
  1747. * VQA - Pointer to private VQA handle.
  1748. * Iffsize - Size of IFF chunk.
  1749. *
  1750. * RESULT
  1751. * Error - 0 if successful or VQA_??? error code.
  1752. *
  1753. ****************************************************************************/
  1754. static long Load_CBP0(VQAHandleP *vqap, unsigned long iffsize)
  1755. {
  1756. VQAData *vqabuf;
  1757. VQALoader *loader;
  1758. VQACBNode *curcb;
  1759. void *buffer;
  1760. /* Dereference commonly used data members for quicker access. */
  1761. vqabuf = vqap->VQABuf;
  1762. loader = &vqabuf->Loader;
  1763. curcb = loader->CurCB;
  1764. /*-------------------------------------------------------------------------
  1765. * ASSEMBLY PARTIAL CODEBOOKS.
  1766. *-----------------------------------------------------------------------*/
  1767. /* Read the partial codebook into the next position in the buffer. */
  1768. buffer = curcb->Buffer + loader->PartialCBSize;
  1769. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer,
  1770. PADSIZE(iffsize))) {
  1771. return (VQAERR_READ);
  1772. }
  1773. /* Accumulate the partial codebook values. */
  1774. loader->PartialCBSize += iffsize;
  1775. loader->NumPartialCB++;
  1776. /*-------------------------------------------------------------------------
  1777. * PROCESS FULL CODEBOOK.
  1778. *-----------------------------------------------------------------------*/
  1779. if (loader->NumPartialCB == vqap->Header.Groupsize) {
  1780. /* Reset the codebook accumulator values */
  1781. loader->NumPartialCB = 0;
  1782. loader->PartialCBSize = 0;
  1783. /* Flag this codebook as uncompressed */
  1784. curcb->Flags &= (~VQACBF_CBCOMP);
  1785. curcb->CBOffset = 0;
  1786. /* Go to the next codebook buffer */
  1787. loader->FullCB = curcb;
  1788. loader->FullCB->Flags &= (~VQACBF_DOWNLOADED);
  1789. loader->CurCB = curcb->Next;
  1790. }
  1791. return (0);
  1792. }
  1793. /****************************************************************************
  1794. *
  1795. * NAME
  1796. * Load_CBPZ - Load partial compressed codebook.
  1797. *
  1798. * SYNOPSIS
  1799. * Error = Load_CBPZ(VQA, Iffsize)
  1800. *
  1801. * long Load_CBPZ(VQAHandleP *, unsigned long);
  1802. *
  1803. * FUNCTION
  1804. *
  1805. * INPUTS
  1806. * VQA - Pointer to private VQA handle.
  1807. * Iffsize - Size of IFF chunk.
  1808. *
  1809. * RESULT
  1810. * Error - 0 if successful or VQAERR_??? error code.
  1811. *
  1812. ****************************************************************************/
  1813. static long Load_CBPZ(VQAHandleP *vqap, unsigned long iffsize)
  1814. {
  1815. VQAData *vqabuf;
  1816. VQALoader *loader;
  1817. VQACBNode *curcb;
  1818. void *buffer;
  1819. unsigned long padsize;
  1820. /* Dereference commonly used data members for quicker access */
  1821. vqabuf = vqap->VQABuf;
  1822. loader = &vqabuf->Loader;
  1823. curcb = loader->CurCB;
  1824. padsize = PADSIZE(iffsize);
  1825. /* Attempt to compute the LCW offset into the codebook buffer by
  1826. * multiplying the size of this chunk by the # frames/group, and adding
  1827. * a small fudge factor on, then subtracting that from the CB buffer size.
  1828. */
  1829. if (loader->PartialCBSize == 0) {
  1830. curcb->CBOffset = (vqabuf->Max_CB_Size
  1831. - (padsize * vqap->Header.Groupsize + 100));
  1832. }
  1833. /*-------------------------------------------------------------------------
  1834. * ASSEMBLE PARTIAL CODEBOOKS.
  1835. *-----------------------------------------------------------------------*/
  1836. /* Read the partial codebook into the next position in the buffer. */
  1837. buffer = ((curcb->Buffer + curcb->CBOffset) + loader->PartialCBSize);
  1838. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {
  1839. return (VQAERR_READ);
  1840. }
  1841. /* Accumulate partial codebook values */
  1842. loader->PartialCBSize += iffsize;
  1843. loader->NumPartialCB++;
  1844. /*-------------------------------------------------------------------------
  1845. * PROCESS FULL CODEBOOK.
  1846. *-----------------------------------------------------------------------*/
  1847. if (loader->NumPartialCB == vqap->Header.Groupsize) {
  1848. /* Reset the codebook accumulator values. */
  1849. loader->NumPartialCB = 0;
  1850. loader->PartialCBSize = 0;
  1851. /* Flag this codebook as compressed. */
  1852. curcb->Flags |= VQACBF_CBCOMP;
  1853. /* Go to the next codebook buffer */
  1854. loader->FullCB = curcb;
  1855. loader->FullCB->Flags &= (~VQACBF_DOWNLOADED);
  1856. loader->CurCB = curcb->Next;
  1857. }
  1858. return (0);
  1859. }
  1860. /****************************************************************************
  1861. *
  1862. * NAME
  1863. * Load_CPL0 - Load an uncompressed palette.
  1864. *
  1865. * SYNOPSIS
  1866. * Error = Load_CPL0(VQA, Iffsize)
  1867. *
  1868. * long Load_CPL0(VQAHandleP *, unsigned long);
  1869. *
  1870. * FUNCTION
  1871. *
  1872. * INPUTS
  1873. * VQA - Pointer to private VQA handle.
  1874. * Iffsize - Size of IFF chunk.
  1875. *
  1876. * RESULT
  1877. * Error - 0 if successful or VQAERR_??? error code.
  1878. *
  1879. ****************************************************************************/
  1880. static long Load_CPL0(VQAHandleP *vqap, unsigned long iffsize)
  1881. {
  1882. VQAFrameNode *curframe;
  1883. /* Dereference commonly used data members for quicker access. */
  1884. curframe = vqap->VQABuf->Loader.CurFrame;
  1885. /* Read the palette into the palette buffer */
  1886. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Palette,
  1887. PADSIZE(iffsize))) {
  1888. return (VQAERR_READ);
  1889. }
  1890. /* Flag the palette as uncompressed. */
  1891. curframe->Flags &= ~VQAFRMF_PALCOMP;
  1892. curframe->PalOffset = 0;
  1893. curframe->PaletteSize = iffsize;
  1894. return (0);
  1895. }
  1896. /****************************************************************************
  1897. *
  1898. * NAME
  1899. * Load_CPLZ - Load compressed palette.
  1900. *
  1901. * SYNOPSIS
  1902. * Error = Load_CPLZ(VQA, Iffsize)
  1903. *
  1904. * long Load_CPLZ(VQAHandleP *, unsigned long);
  1905. *
  1906. * FUNCTION
  1907. *
  1908. * INPUTS
  1909. * VQA - Pointer to private VQA handle.
  1910. * Iffsize - Size of IFF chunk.
  1911. *
  1912. * RESULT
  1913. * Error - 0 if successful or VQAERR_??? error code.
  1914. *
  1915. ****************************************************************************/
  1916. static long Load_CPLZ(VQAHandleP *vqap, unsigned long iffsize)
  1917. {
  1918. VQAFrameNode *curframe;
  1919. void *buffer;
  1920. unsigned long padsize;
  1921. unsigned long lcwoffset;
  1922. /* Dereference commonly used data members for quicker access. */
  1923. curframe = vqap->VQABuf->Loader.CurFrame;
  1924. padsize = PADSIZE(iffsize);
  1925. /* Read the palette into the end of the palette buffer. */
  1926. lcwoffset = vqap->VQABuf->Max_Pal_Size - padsize;
  1927. buffer = curframe->Palette + lcwoffset;
  1928. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {
  1929. return (VQAERR_READ);
  1930. }
  1931. /* Flag this palette as compressed. */
  1932. curframe->Flags |= VQAFRMF_PALCOMP;
  1933. curframe->PalOffset = lcwoffset;
  1934. curframe->PaletteSize = iffsize;
  1935. return (0);
  1936. }
  1937. /****************************************************************************
  1938. *
  1939. * NAME
  1940. * Load_VPT0 - Load uncompressed pointers.
  1941. *
  1942. * SYNOPSIS
  1943. * Error = Load_VPT0(VQA, Iffsize)
  1944. *
  1945. * long Load_VPT0(VQAHandleP *, unsigned long);
  1946. *
  1947. * FUNCTION
  1948. *
  1949. * INPUTS
  1950. * VQA - Pointer to private VQA handle.
  1951. * Iffsize - Size of IFF chunk.
  1952. *
  1953. * RESULT
  1954. * Error - 0 if successful or VQAERR_??? error code.
  1955. *
  1956. ****************************************************************************/
  1957. static long Load_VPT0(VQAHandleP *vqap, unsigned long iffsize)
  1958. {
  1959. VQAFrameNode *curframe;
  1960. /* Dereference commonly used data members for quicker access. */
  1961. curframe = vqap->VQABuf->Loader.CurFrame;
  1962. /* Read the pointers into start of the pointer buffer. */
  1963. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, curframe->Pointers,
  1964. PADSIZE(iffsize))) {
  1965. return (VQAERR_READ);
  1966. }
  1967. /* Flag this frame as uncompressed */
  1968. curframe->Flags &= ~VQAFRMF_PTRCOMP;
  1969. curframe->PtrOffset = 0;
  1970. return (0);
  1971. }
  1972. /****************************************************************************
  1973. *
  1974. * NAME
  1975. * Load_VPTZ - Load compressed pointers.
  1976. *
  1977. * SYNOPSIS
  1978. * Error = Load_VPTZ(VQA, Iffsize)
  1979. *
  1980. * long Load_VPTZ(VQAHandleP *, unsigned long);
  1981. *
  1982. * FUNCTION
  1983. *
  1984. * INPUTS
  1985. * VQA - Pointer to private VQA handle.
  1986. * Iffsize - Size of IFF chunk.
  1987. *
  1988. * RESULT
  1989. * Error - 0 if successful or VQAERR_??? error code.
  1990. *
  1991. ****************************************************************************/
  1992. static long Load_VPTZ(VQAHandleP *vqap, unsigned long iffsize)
  1993. {
  1994. VQAFrameNode *curframe;
  1995. void *buffer;
  1996. unsigned long padsize;
  1997. unsigned long lcwoffset;
  1998. /* Dereference commonly used data members for quicker access. */
  1999. curframe = vqap->VQABuf->Loader.CurFrame;
  2000. padsize = PADSIZE(iffsize);
  2001. lcwoffset = vqap->VQABuf->Max_Ptr_Size - padsize;
  2002. /* Read the pointers into end of the pointer buffer. */
  2003. buffer = curframe->Pointers + lcwoffset;
  2004. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, buffer, padsize)) {
  2005. return (VQAERR_READ);
  2006. }
  2007. /* Flag this frame as compressed. */
  2008. curframe->Flags |= VQAFRMF_PTRCOMP;
  2009. curframe->PtrOffset = lcwoffset;
  2010. return (0);
  2011. }
  2012. #if(VQAAUDIO_ON)
  2013. /****************************************************************************
  2014. *
  2015. * NAME
  2016. * Load_SND0 - Load uncompressed sound chunk.
  2017. *
  2018. * SYNOPSIS
  2019. * Error = Load_SND0(VQA, Iffsize)
  2020. *
  2021. * long Load_SND0(VQAHandleP *, unsigned long);
  2022. *
  2023. * FUNCTION
  2024. * This routine normally loads the chunk into the TempBuf, unless the
  2025. * chunk is larger than the temp buffer size, in which case it puts it
  2026. * directly into the audio buffer itself. This assumes that the only
  2027. * such chunk will be the first audio chunk!
  2028. *
  2029. * INPUTS
  2030. * VQA - Pointer to private VQA handle.
  2031. * Iffsize - Size of IFF chunk.
  2032. *
  2033. * RESULT
  2034. * Error - 0 if successful or VQAERR_??? error code.
  2035. *
  2036. ****************************************************************************/
  2037. static long Load_SND0(VQAHandleP *vqap, unsigned long iffsize)
  2038. {
  2039. VQAData *vqabuf;
  2040. VQALoader *loader;
  2041. VQAAudio *audio;
  2042. VQAConfig *config;
  2043. unsigned long padsize;
  2044. long i;
  2045. /* Dereference commonly used data members for quicker access. */
  2046. vqabuf = vqap->VQABuf;
  2047. loader = &vqabuf->Loader;
  2048. audio = &vqabuf->Audio;
  2049. config = &vqap->Config;
  2050. padsize = PADSIZE(iffsize);
  2051. /* If sound is disabled, or if we're playing from a VOC file, or if
  2052. * there's no Audio Buffer, just skip the chunk.
  2053. */
  2054. #if(VQAVOC_ON && VQAAUDIO_ON)
  2055. if (((config->OptionFlags & VQAOPTF_AUDIO) == 0)
  2056. || (vqap->vocfh != -1) || (audio->Buffer == NULL)) {
  2057. #else /* VQAVOC_ON */
  2058. if (((config->OptionFlags & VQAOPTF_AUDIO) == 0)
  2059. || (audio->Buffer == NULL)) {
  2060. #endif /* VQAVOC_ON */
  2061. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,
  2062. padsize)) {
  2063. return (VQAERR_SEEK);
  2064. } else {
  2065. return (0);
  2066. }
  2067. }
  2068. /* Read large startup chunk directly into AudioBuf */
  2069. if ((padsize > audio->TempBufSize) && (audio->AudBufPos == 0)) {
  2070. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,
  2071. padsize)) {
  2072. return (VQAERR_READ);
  2073. }
  2074. audio->AudBufPos += iffsize;
  2075. /* Flag the audio frame flags as loaded for the initial audio frame. */
  2076. for (i = 0; i < (iffsize / config->HMIBufSize); i++) {
  2077. audio->IsLoaded[i] = 1;
  2078. }
  2079. return (0);
  2080. } else {
  2081. /* Read data into TempBuf */
  2082. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,
  2083. padsize)) {
  2084. return (VQAERR_READ);
  2085. }
  2086. }
  2087. /* Set the TempBufLen */
  2088. audio->TempBufLen = iffsize;
  2089. return (0);
  2090. }
  2091. /****************************************************************************
  2092. *
  2093. * NAME
  2094. * Load_SND1 - Load compressed sound chunk.
  2095. *
  2096. * SYNOPSIS
  2097. * Error = Load_SND1(VQA, Iffsize)
  2098. *
  2099. * long Load_SND1(VQAHandleP *, unsigned long);
  2100. *
  2101. * FUNCTION
  2102. * This routine normally loads the chunk into the TempBuf, unless the
  2103. * chunk is larger than the temp buffer size, in which case it puts it
  2104. * directly into the audio buffer itself. This assumes that the only
  2105. * such chunk will be the first audio chunk!
  2106. *
  2107. * INPUTS
  2108. * VQA - Pointer to private VQA handle.
  2109. * Iffsize - Size of IFF chunk.
  2110. *
  2111. * RESULT
  2112. * Error - 0 if successful or VQAERR_??? error code.
  2113. *
  2114. ****************************************************************************/
  2115. static long Load_SND1(VQAHandleP *vqap, unsigned long iffsize)
  2116. {
  2117. VQAData *vqabuf;
  2118. VQALoader *loader;
  2119. VQAAudio *audio;
  2120. VQAConfig *config;
  2121. unsigned char *loadbuf;
  2122. unsigned long padsize;
  2123. ZAPHeader zap;
  2124. long i;
  2125. /* Dereference commonly used data members for quicker access. */
  2126. vqabuf = vqap->VQABuf;
  2127. loader = &vqabuf->Loader;
  2128. audio = &vqabuf->Audio;
  2129. config = &vqap->Config;
  2130. padsize = PADSIZE(iffsize);
  2131. /* If sound is disabled, or if we're playing from a VOC file, or if
  2132. * there's no Audio Buffer, just skip the chunk
  2133. */
  2134. #if(VQAVOC_ON && VQAAUDIO_ON)
  2135. if (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)
  2136. || (audio->Buffer == NULL)) {
  2137. #else
  2138. if (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {
  2139. #endif /* VQAVOC_ON */
  2140. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,
  2141. padsize)) {
  2142. return (VQAERR_SEEK);
  2143. } else {
  2144. return (0);
  2145. }
  2146. }
  2147. /* Read the ZAP audio frame header. */
  2148. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, &zap,
  2149. sizeof(ZAPHeader))) {
  2150. return (VQAERR_READ);
  2151. }
  2152. /* Adjust chunk size */
  2153. padsize -= sizeof(ZAPHeader);
  2154. /* Read large startup chunk directly into AudioBuf */
  2155. if ((zap.UnCompSize > audio->TempBufSize) && (audio->AudBufPos == 0)) {
  2156. /* Load RAW uncompressed data. */
  2157. if (zap.UnCompSize == zap.CompSize) {
  2158. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->Buffer,
  2159. padsize)) {
  2160. return (VQAERR_READ);
  2161. }
  2162. } else {
  2163. /* Load compressed data into the end of the buffer. */
  2164. loadbuf = (audio->Buffer + config->AudioBufSize) - padsize;
  2165. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf,
  2166. padsize)) {
  2167. return (VQAERR_READ);
  2168. }
  2169. /* Uncompress the audio frame. */
  2170. AudioUnzap(loadbuf, audio->Buffer, zap.UnCompSize);
  2171. }
  2172. /* Set buffer positions & flags */
  2173. audio->AudBufPos += zap.UnCompSize;
  2174. for (i = 0; i < (zap.UnCompSize / config->HMIBufSize); i++) {
  2175. audio->IsLoaded[i] = 1;
  2176. }
  2177. return (0);
  2178. }
  2179. /* Load an audio frame. */
  2180. if (zap.UnCompSize == zap.CompSize) {
  2181. /* If the frame is uncompressed the load it in directly. */
  2182. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, audio->TempBuf,
  2183. padsize)) {
  2184. return (VQAERR_READ);
  2185. }
  2186. } else {
  2187. /* Load the audio frame into the end of the buffer. */
  2188. loadbuf = ((audio->TempBuf + audio->TempBufSize) - padsize);
  2189. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {
  2190. return (VQAERR_READ);
  2191. }
  2192. /* Uncompress the audio frame. */
  2193. AudioUnzap(loadbuf, audio->TempBuf, zap.UnCompSize);
  2194. }
  2195. /* Set the TempBufLen */
  2196. audio->TempBufLen = zap.UnCompSize;
  2197. return (0);
  2198. }
  2199. /****************************************************************************
  2200. *
  2201. * NAME
  2202. * Load_SND2 - Load ADPCM compressed sound chunk.
  2203. *
  2204. * SYNOPSIS
  2205. * Error = Load_SND2(VQA, Iffsize)
  2206. *
  2207. * long Load_SND2(VQAHandleP *, unsigned long);
  2208. *
  2209. * FUNCTION
  2210. * This routine normally loads the chunk into the TempBuf, unless the
  2211. * chunk is larger than the temp buffer size, in which case it puts it
  2212. * directly into the audio buffer itself. This assumes that the only
  2213. * such chunk will be the first audio chunk!
  2214. *
  2215. * INPUTS
  2216. * VQA - Pointer to private VQA handle.
  2217. * Iffsize - Size of IFF chunk.
  2218. *
  2219. * RESULT
  2220. * Error - 0 if successful or VQAERR_??? error code.
  2221. *
  2222. ****************************************************************************/
  2223. static long Load_SND2(VQAHandleP *vqap, unsigned long iffsize)
  2224. {
  2225. VQAData *vqabuf;
  2226. VQALoader *loader;
  2227. VQAAudio *audio;
  2228. VQAConfig *config;
  2229. unsigned char *loadbuf;
  2230. unsigned long padsize;
  2231. unsigned long uncomp_size;
  2232. long i;
  2233. /* Dereference commonly used data members for quicker access. */
  2234. vqabuf = vqap->VQABuf;
  2235. loader = &vqabuf->Loader;
  2236. audio = &vqabuf->Audio;
  2237. config = &vqap->Config;
  2238. padsize = PADSIZE(iffsize);
  2239. /* If sound is disabled, or if we're playing from a VOC file, or if
  2240. * there's no Audio Buffer, just skip the chunk
  2241. */
  2242. #if(VQAVOC_ON && VQAAUDIO_ON)
  2243. if (((config->OptionFlags & VQAOPTF_AUDIO) == 0) || (vqap->vocfh != -1)
  2244. || (audio->Buffer == NULL)) {
  2245. #else /* VQAVOC_ON */
  2246. if (((config->OptionFlags & VQAOPTF_AUDIO)==0) || (audio->Buffer==NULL)) {
  2247. #endif /* VQAVOC_ON */
  2248. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_SEEK, (void *)SEEK_CUR,
  2249. padsize)) {
  2250. return (VQAERR_SEEK);
  2251. } else {
  2252. return (0);
  2253. }
  2254. }
  2255. uncomp_size = iffsize * (audio->BitsPerSample / 4);
  2256. /* Read large startup chunk directly into AudioBuf */
  2257. if ((uncomp_size > audio->TempBufSize) && (audio->AudBufPos == 0)) {
  2258. /* Load compressed data into the end of the buffer. */
  2259. loadbuf = (audio->Buffer + config->AudioBufSize) - padsize;
  2260. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {
  2261. return (VQAERR_READ);
  2262. }
  2263. /* Uncompress the audio frame. */
  2264. audio->ADPCM_Info.lpSource = (char *)loadbuf;
  2265. audio->ADPCM_Info.lpDest = (char *)audio->Buffer;
  2266. sosCODECDecompressData(&audio->ADPCM_Info, uncomp_size);
  2267. /* Set buffer positions & flags */
  2268. audio->AudBufPos += uncomp_size;
  2269. for (i = 0; i < (uncomp_size / config->HMIBufSize); i++) {
  2270. audio->IsLoaded[i] = 1;
  2271. }
  2272. return (0);
  2273. }
  2274. /* Load an audio frame. */
  2275. loadbuf = ((audio->TempBuf + audio->TempBufSize) - padsize);
  2276. if (vqap->IOHandler((VQAHandle *)vqap, VQACMD_READ, loadbuf, padsize)) {
  2277. return (VQAERR_READ);
  2278. }
  2279. /* Uncompress the audio frame. */
  2280. audio->ADPCM_Info.lpSource = (char *)loadbuf;
  2281. audio->ADPCM_Info.lpDest = (char *)audio->TempBuf;
  2282. sosCODECDecompressData(&audio->ADPCM_Info, uncomp_size);
  2283. /* Set the TempBufLen */
  2284. audio->TempBufLen = uncomp_size;
  2285. return (0);
  2286. }
  2287. #if(VQAVOC_ON)
  2288. /****************************************************************************
  2289. *
  2290. * NAME
  2291. * Load_AudFrame - Loads blocks from seperate VOC file.
  2292. *
  2293. * SYNOPSIS
  2294. * Load_AudFrame(VQA)
  2295. *
  2296. * void Load_AudFrame(VQAHandleP *);
  2297. *
  2298. * FUNCTION
  2299. *
  2300. * INPUTS
  2301. * VQA - Pointer to private VQA handle.
  2302. *
  2303. * RESULT
  2304. * NONE
  2305. *
  2306. ****************************************************************************/
  2307. static void Load_AudFrame(VQAHandleP *vqap)
  2308. {
  2309. VQAData *vqabuf;
  2310. VQALoader *loader;
  2311. VQAAudio *audio;
  2312. VQAConfig *config;
  2313. static long lastplayblock = -1;
  2314. static long myblock = 0;
  2315. static long firsttime = 1;
  2316. long numblocks;
  2317. long i;
  2318. /* Dereference commonly used data members for quicker access. */
  2319. vqabuf = vqap->VQABuf;
  2320. loader = &vqabuf->Loader;
  2321. audio = &vqabuf->Audio;
  2322. config = &vqap->Config;
  2323. /* Do nothing if no buffer */
  2324. if (audio->Buffer == NULL) {
  2325. return;
  2326. }
  2327. /* If this is the first time we're called, pre-load the 1st 'n' audio
  2328. * blocks, where 'n' is half the total audio buffer size; this way, we'll
  2329. * always stay ahead of HMI.
  2330. */
  2331. if (firsttime) {
  2332. numblocks = (audio->NumAudBlocks / 2);
  2333. read(vqap->vocfh, audio->Buffer, config->HMIBufSize * numblocks);
  2334. audio->AudBufPos += config->HMIBufSize * numblocks;
  2335. if (audio->AudBufPos >= config->AudioBufSize) {
  2336. audio->AudBufPos = 0;
  2337. }
  2338. for (i = 0; i < numblocks; i++) {
  2339. audio->IsLoaded[i] = 1;
  2340. }
  2341. myblock += numblocks;
  2342. if (myblock >= audio->NumAudBlocks) {
  2343. myblock = 0;
  2344. }
  2345. firsttime = 0;
  2346. }
  2347. /* If HMI's block has changed, load the next block & mark it as loaded */
  2348. if (audio->PlayPosition / config->HMIBufSize != lastplayblock) {
  2349. /* update HMI's last known block position */
  2350. lastplayblock = audio->PlayPosition / config->HMIBufSize;
  2351. /* read the VOC data */
  2352. read(vqap->vocfh, (audio->Buffer + myblock * config->HMIBufSize),
  2353. config->HMIBufSize);
  2354. audio->AudBufPos += config->HMIBufSize;
  2355. if (audio->AudBufPos >= config->AudioBufSize) {
  2356. audio->AudBufPos = 0;
  2357. }
  2358. /* set the IsLoaded flags */
  2359. audio->IsLoaded[myblock] = 1;
  2360. /* increment my block counter */
  2361. myblock++;
  2362. if (myblock >= audio->NumAudBlocks) {
  2363. myblock = 0;
  2364. }
  2365. }
  2366. }
  2367. #endif /* VQAVOC_ON */
  2368. #endif /* VQAAUDIO_ON */