| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /****************************************************************************
- *
- * 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
- *
- *----------------------------------------------------------------------------
- *
- * PROJECT
- * VQA player library. (32-Bit protected mode)
- *
- * FILE
- * task.c
- *
- * DESCRIPTION
- * Loading and drawing delegation
- *
- * PROGRAMMER
- * Bill Randolph
- * Denzil E. Long, Jr.
- *
- * DATE
- * July 25, 1995
- *
- *----------------------------------------------------------------------------
- *
- * PUBLIC
- * VQA_Alloc - Allocate a VQAHandle to use.
- * VQA_Free - Free a VQAHandle.
- * VQA_Init - Initialize the VQAHandle IO.
- * VQA_Play - Play the VQA movie.
- * VQA_GetInfo - Get VQA movie information.
- * VQA_GetStats - Get VQA movie statistics.
- * VQA_Version - Get VQA library version number.
- * VQA_IDString - Get the VQA player library's ID string.
- *
- * PRIVATE
- * VQA_IO_Task - Loader task for multitasking.
- * VQA_Rendering_Task - Drawer task for multitasking.
- * User_Update - Page flip routine called by the task interrupt.
- *
- ****************************************************************************/
- #include <stdio.h>
- #include <malloc.h>
- #include <dos.h>
- #include <mem.h>
- #include <conio.h>
- #include <sys\timeb.h>
- #include <vqm32\all.h>
- #include "vqaplayp.h"
- /*---------------------------------------------------------------------------
- * PRIVATE DECLARATIONS
- *-------------------------------------------------------------------------*/
- /* Externals */
- #ifdef __cplusplus
- extern "C" {
- #endif
- extern int cdecl Check_Key(void);
- extern int cdecl Get_Key(void);
- #ifdef __cplusplus
- }
- #endif
- /****************************************************************************
- *
- * NAME
- * VQA_Alloc - Allocate a VQAHandle to use.
- *
- * SYNOPSIS
- * VQAHandle = VQA_Alloc()
- *
- * VQAHandle *VQA_Alloc(void);
- *
- * FUNCTION
- * Obtain a VQAHandle. This handle is used by most VQA library functions,
- * and contains the current position in the file. This is the only legal
- * way to obtain a VQAHandle.
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * VQA - Handle of a VQA.
- *
- ****************************************************************************/
- VQAHandle *VQA_Alloc(void)
- {
- VQAHandleP *vqa;
- if ((vqa = (VQAHandleP *)malloc(sizeof(VQAHandleP))) != NULL) {
- memset(vqa, 0, sizeof(VQAHandleP));
- }
- return ((VQAHandle *)vqa);
- }
- /****************************************************************************
- *
- * NAME
- * VQA_Free - Free a VQAHandle.
- *
- * SYNOPSIS
- * VQA_Free(VQA)
- *
- * void VQA_Free(VQAHandle *);
- *
- * FUNCTION
- * Dispose of a VQAHandle. This is the only legal way to dispose of a
- * VQAHandle.
- *
- * INPUTS
- * VQA - Pointer to VQAHandle to dispose of.
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- void VQA_Free(VQAHandle *vqa)
- {
- if (vqa) free(vqa);
- }
- /****************************************************************************
- *
- * NAME
- * VQA_Init - Initialize the VQAHandle IO handler.
- *
- * SYNOPSIS
- * VQA_Init(VQA, IOHandler)
- *
- * void VQA_Init(VQAHandle *, IOHandler *);
- *
- * FUNCTION
- * Initialize the specified VQAHandle IO with the client provided custom
- * IO handler.
- *
- * INPUTS
- * VQA - Pointer to VQAHandle to initialize.
- * IOHandler - Pointer to custom file I/O handler function.
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- void VQA_Init(VQAHandle *vqa, long(*iohandler)(VQAHandle *vqa, long action,
- void *buffer, long nbytes))
- {
- ((VQAHandleP *)vqa)->IOHandler = iohandler;
- }
- /****************************************************************************
- *
- * NAME
- * VQA_Play - Play the VQA movie.
- *
- * SYNOPSIS
- * Error = VQA_Play(VQA, Mode)
- *
- * long VQA_Play(VQAHandle *, long);
- *
- * FUNCTION
- * Playback the movie associated with the specified VQAHandle.
- *
- * INPUTS
- * VQA - Pointer to handle of movie to play.
- * Mode - Playback mode.
- * VQAMODE_RUN - Run the movie until completion.
- * VQAMODE_WALK - Walk the movie frame by frame.
- * VQAMODE_PAUSE - Pause the movie.
- * VQAMODE_STOP - Stop the movie (Shutdown).
- *
- * RESULT
- * Error - 0 if successful, or error code.
- *
- ****************************************************************************/
- long VQA_Play(VQAHandle *vqa, long mode)
- {
- VQAData *vqabuf;
- VQAConfig *config;
- VQADrawer *drawer;
- long rc;
- long i;
- long key;
- /* Dereference commonly used data members for quick access. */
- vqabuf = ((VQAHandleP *)vqa)->VQABuf;
- drawer = &vqabuf->Drawer;
- config = &((VQAHandleP *)vqa)->Config;
- /* One time player priming. */
- if (!(vqabuf->Flags & VQADATF_PRIMED)) {
- /* Init the Drawer's configuration */
- VQA_Configure_Drawer((VQAHandleP *)vqa);
- /* If audio enabled & loaded, start playing */
- #if(VQAAUDIO_ON)
- if ((config->OptionFlags & VQAOPTF_AUDIO) && vqabuf->Audio.IsLoaded[0]) {
- VQA_StartAudio((VQAHandleP *)vqa);
- }
- #endif
- /* Initialize the timer */
- i = ((vqabuf->Drawer.CurFrame->FrameNum * VQA_TIMETICKS)
- / config->DrawRate);
- VQA_SetTimer((VQAHandleP *)vqa, i, config->TimerMethod);
- vqabuf->StartTime = VQA_GetTime((VQAHandleP *)vqa);
- /* Set up the Mono screen */
- #if(VQAMONO_ON)
- if (config->OptionFlags & VQAOPTF_MONO) {
- VQA_InitMono((VQAHandleP *)vqa);
- }
- #endif
- /* Priming is complete. */
- vqabuf->Flags |= VQADATF_PRIMED;
- }
- /* Main Player Loop */
- switch (mode) {
- case VQAMODE_PAUSE:
- if ((vqabuf->Flags & VQADATF_PAUSED) == 0) {
- vqabuf->Flags |= VQADATF_PAUSED;
- vqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);
- /* Stop the audio while the movie is paused. */
- #if(VQAAUDIO_ON)
- if (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {
- VQA_StopAudio((VQAHandleP *)vqa);
- }
- #endif
- }
- rc = VQAERR_PAUSED;
- break;
- case VQAMODE_RUN:
- case VQAMODE_WALK:
- default:
- /* Start up the movie if is it currently paused. */
- if (vqabuf->Flags & VQADATF_PAUSED) {
- vqabuf->Flags &= ~VQADATF_PAUSED;
-
- /* Start the audio if it was previously on. */
- #if(VQAAUDIO_ON)
- if (config->OptionFlags & VQAOPTF_AUDIO) {
- VQA_StartAudio((VQAHandleP *)vqa);
- }
- #endif
- VQA_SetTimer((VQAHandleP *)vqa, vqabuf->EndTime, config->TimerMethod);
- }
-
- /* Load, Draw, Load, Draw, Load, Draw ... */
- while ((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))
- != (VQADATF_DDONE|VQADATF_LDONE)) {
- /* Load a frame */
- if (!(vqabuf->Flags & VQADATF_LDONE)) {
- if ((rc = VQA_LoadFrame(vqa)) == 0) {
- vqabuf->LoadedFrames++;
- }
- else if ((rc != VQAERR_NOBUFFER) && (rc != VQAERR_SLEEPING)) {
- vqabuf->Flags |= VQADATF_LDONE;
- rc = 0;
- }
- }
- /* Draw a frame */
- if ((config->DrawFlags & VQACFGF_NODRAW) == 0) {
- if ((rc = (*(vqabuf->Draw_Frame))(vqa)) == 0) {
- vqabuf->DrawnFrames++;
- if (User_Update(vqa)) {
- vqabuf->Flags |= (VQADATF_DDONE|VQADATF_LDONE);
- }
- }
- else if ((vqabuf->Flags & VQADATF_LDONE)
- && (rc == VQAERR_NOBUFFER)) {
- vqabuf->Flags |= VQADATF_DDONE;
- }
- } else {
- vqabuf->Flags |= VQADATF_DDONE;
- drawer->CurFrame->Flags = 0L;
- drawer->CurFrame = drawer->CurFrame->Next;
- }
- /* Update Mono output */
- #if(VQAMONO_ON)
- if (config->OptionFlags & VQAOPTF_MONO) {
- VQA_UpdateMono((VQAHandleP *)vqa);
- }
- #endif
- if (mode == VQAMODE_WALK) {
- break;
- }
- #if(VQASTANDALONE)
- else {
- /* Do single-stepping check. */
- if (config->OptionFlags & VQAOPTF_STEP) {
- while ((key = Check_Key()) == 0);
- Get_Key();
- /* Escape key still quits. */
- if (key == 27) {
- break;
- }
- }
- /* Check for ESC */
- if ((key = Check_Key()) != 0) {
- mode = VQAMODE_STOP;
- break;
- }
- }
- #endif
- }
- break;
- }
- /* If the movie is finished or we are requested to stop then shutdown. */
- if (((vqabuf->Flags & (VQADATF_DDONE|VQADATF_LDONE))
- == (VQADATF_DDONE|VQADATF_LDONE)) || (mode == VQAMODE_STOP)) {
- /* Record the end time; must be done before stopping audio, since we're
- * getting the elapsed time from the audio DMA position.
- */
- vqabuf->EndTime = VQA_GetTime((VQAHandleP *)vqa);
- /* Stop audio, if it's playing. */
- #if(VQAAUDIO_ON)
- if (vqabuf->Audio.Flags & VQAAUDF_ISPLAYING) {
- VQA_StopAudio((VQAHandleP *)vqa);
- }
- #endif
- /* Movie is finished. */
- rc = VQAERR_EOF;
- }
- return (rc);
- }
- /****************************************************************************
- *
- * NAME
- * VQA_GetInfo - Get VQA movie information.
- *
- * SYNOPSIS
- * VQA_GetInfo(VQA, Info)
- *
- * void VQA_GetInfo(VQAHandle *, VQAInfo *);
- *
- * FUNCTION
- * Retrieve information about the opened movie.
- *
- * INPUTS
- * VQA - Pointer to VQAHandle of opened movie.
- * Info - Pointer to VQAInfo structure to fill.
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- void VQA_GetInfo(VQAHandle *vqa, VQAInfo *info)
- {
- VQAHeader *header;
- /* Dereference header structure. */
- header = &((VQAHandleP *)vqa)->Header;
- info->NumFrames = header->Frames;
- info->ImageHeight = header->ImageHeight;
- info->ImageWidth = header->ImageWidth;
- info->ImageBuf = ((VQAHandleP *)vqa)->VQABuf->Drawer.ImageBuf;
- }
- /****************************************************************************
- *
- * NAME
- * VQA_GetStats - Get VQA movie statistics.
- *
- * SYNOPSIS
- * VQA_GetStats(VQA, Stats)
- *
- * void VQA_GetStats(VQAHandle *, VQAStatistics *);
- *
- * FUNCTION
- * Retrieve the statistics for the VQA movie.
- *
- * INPUTS
- * VQA - Handle of VQA movie to get statistics for.
- * Stats - Pointer to VQAStatistics to fill.
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- void VQA_GetStats(VQAHandle *vqa, VQAStatistics *stats)
- {
- VQAData *vqabuf;
- /* Dereference VQAData structure from VQAHandle */
- vqabuf = ((VQAHandleP *)vqa)->VQABuf;
- stats->MemUsed = vqabuf->MemUsed;
- stats->StartTime = vqabuf->StartTime;
- stats->EndTime = vqabuf->EndTime;
- stats->FramesLoaded = vqabuf->LoadedFrames;
- stats->FramesDrawn = vqabuf->DrawnFrames;
- stats->FramesSkipped = vqabuf->Drawer.NumSkipped;
- stats->MaxFrameSize = vqabuf->Loader.MaxFrameSize;
- #if(VQAAUDIO_ON)
- stats->SamplesPlayed = vqabuf->Audio.SamplesPlayed;
- #else
- stats->SamplesPlayed = 0;
- #endif
- }
- /****************************************************************************
- *
- * NAME
- * VQA_Version - Get VQA library version number.
- *
- * SYNOPSIS
- * Version = VQA_Version()
- *
- * char *VQA_Version(void);
- *
- * FUNCTION
- * Return the version of the VQA player library.
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * Version - Pointer to version number string.
- *
- ****************************************************************************/
- char *VQA_Version(void)
- {
- return(VQA_VERSION);
- }
- /****************************************************************************
- *
- * NAME
- * VQA_IDString - Get the VQA player library's ID string.
- *
- * SYNOPSIS
- * IDString = VQA_IDString()
- *
- * char *VQA_IDString(void);
- *
- * FUNCTION
- * Return the ID string of this VQA player library.
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * IDString - Pointer to ID string.
- *
- ****************************************************************************/
- char *VQA_IDString(void)
- {
- return (VQA_IDSTRING);
- }
- /****************************************************************************
- *
- * NAME
- * User_Update - Page flip routine called by the task interrupt.
- *
- * SYNOPSIS
- * User_Update(VQA)
- *
- * long User_Update(VQAHandle *);
- *
- * FUNCTION
- *
- * INPUTS
- * VQA - Handle of VQA movie.
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- long User_Update(VQAHandle *vqa)
- {
- VQAData *vqabuf;
- long rc = 0;
- /* Dereference data members for quicker access. */
- vqabuf = ((VQAHandleP *)vqa)->VQABuf;
- if (vqabuf->Flags & VQADATF_UPDATE) {
- /* Invoke the page flip routine */
- rc = (*(vqabuf->Page_Flip))(vqa);
- /* Update data for mono output */
- vqabuf->Flipper.LastFrameNum = vqabuf->Flipper.CurFrame->FrameNum;
- /* Mark the frame as loadable */
- vqabuf->Flipper.CurFrame->Flags = 0L;
- vqabuf->Flags &= (~VQADATF_UPDATE);
- }
- return (rc);
- }
|