MVE: Implementing frame playing (main menu)

Reorganized MVE to use own MVESTREAM pointer for each opened MVE file.
This commit is contained in:
Azamat H. Hackimov 2024-05-05 03:52:52 +03:00
parent 99ec2e3a5e
commit a8784ee524
4 changed files with 104 additions and 85 deletions

View File

@ -39,7 +39,7 @@ static unsigned short _mve_get_ushort(unsigned char *data);
/*
* private functions for mvefile
*/
static MVEFILE *_mvefile_alloc(void);
static MVEFILE *_mvefile_alloc();
static void _mvefile_free(MVEFILE *movie);
static int _mvefile_open(MVEFILE *movie, void *stream);
static void _mvefile_reset(MVEFILE *movie);
@ -50,7 +50,7 @@ static int _mvefile_fetch_next_chunk(MVEFILE *movie);
/*
* private functions for mvestream
*/
static MVESTREAM *_mvestream_alloc(void);
static MVESTREAM *_mvestream_alloc();
static void _mvestream_free(MVESTREAM *movie);
static int _mvestream_open(MVESTREAM *movie, void *stream);
static void _mvestream_reset(MVESTREAM *movie);
@ -69,7 +69,7 @@ MVEFILE *mvefile_open(void *stream) {
file = _mvefile_alloc();
if (!_mvefile_open(file, stream)) {
_mvefile_free(file);
return NULL;
return nullptr;
}
/* initialize the file */
@ -78,7 +78,7 @@ MVEFILE *mvefile_open(void *stream) {
/* verify the file's header */
if (!_mvefile_read_header(file)) {
_mvefile_free(file);
return NULL;
return nullptr;
}
/* now, prefetch the next chunk */
@ -116,7 +116,7 @@ void mvefile_reset(MVEFILE *file) {
*/
int mvefile_get_next_segment_size(MVEFILE *movie) {
/* if nothing is cached, fail */
if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill)
if (movie->cur_chunk == nullptr || movie->next_segment >= movie->cur_fill)
return -1;
/* if we don't have enough data to get a segment, fail */
@ -132,7 +132,7 @@ int mvefile_get_next_segment_size(MVEFILE *movie) {
*/
unsigned char mvefile_get_next_segment_major(MVEFILE *movie) {
/* if nothing is cached, fail */
if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill)
if (movie->cur_chunk == nullptr || movie->next_segment >= movie->cur_fill)
return 0xff;
/* if we don't have enough data to get a segment, fail */
@ -149,7 +149,7 @@ unsigned char mvefile_get_next_segment_major(MVEFILE *movie) {
*/
unsigned char mvefile_get_next_segment_minor(MVEFILE *movie) {
/* if nothing is cached, fail */
if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill)
if (movie->cur_chunk == nullptr || movie->next_segment >= movie->cur_fill)
return 0xff;
/* if we don't have enough data to get a segment, fail */
@ -165,12 +165,12 @@ unsigned char mvefile_get_next_segment_minor(MVEFILE *movie) {
*/
unsigned char *mvefile_get_next_segment(MVEFILE *movie) {
/* if nothing is cached, fail */
if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill)
return NULL;
if (movie->cur_chunk == nullptr || movie->next_segment >= movie->cur_fill)
return nullptr;
/* if we don't have enough data to get a segment, fail */
if (movie->cur_fill - movie->next_segment < 4)
return NULL;
return nullptr;
/* otherwise, get the data length */
return movie->cur_chunk + movie->next_segment + 4;
@ -181,7 +181,7 @@ unsigned char *mvefile_get_next_segment(MVEFILE *movie) {
*/
void mvefile_advance_segment(MVEFILE *movie) {
/* if nothing is cached, fail */
if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill)
if (movie->cur_chunk == nullptr || movie->next_segment >= movie->cur_fill)
return;
/* if we don't have enough data to get a segment, fail */
@ -213,7 +213,7 @@ MVESTREAM *mve_open(void *stream) {
/* open */
if (!_mvestream_open(movie, stream)) {
_mvestream_free(movie);
return NULL;
return nullptr;
}
return movie;
@ -254,7 +254,7 @@ int mve_play_next_chunk(MVESTREAM *movie) {
major = mvefile_get_next_segment_major(movie->movie);
while (major != 0xff) {
/* check whether to handle the segment */
if (major < 32 && movie->handlers[major] != NULL) {
if (major < 32 && movie->handlers[major] != nullptr) {
minor = mvefile_get_next_segment_minor(movie->movie);
len = mvefile_get_next_segment_size(movie->movie);
data = mvefile_get_next_segment(movie->movie);
@ -282,10 +282,10 @@ int mve_play_next_chunk(MVESTREAM *movie) {
/*
* allocate an MVEFILE
*/
static MVEFILE *_mvefile_alloc(void) {
static MVEFILE *_mvefile_alloc() {
MVEFILE *file = (MVEFILE *)mve_alloc(sizeof(MVEFILE));
file->stream = NULL;
file->cur_chunk = NULL;
file->stream = nullptr;
file->cur_chunk = nullptr;
file->buf_size = 0;
file->cur_fill = 0;
file->next_segment = 0;
@ -298,12 +298,12 @@ static MVEFILE *_mvefile_alloc(void) {
*/
static void _mvefile_free(MVEFILE *movie) {
/* free the stream */
movie->stream = NULL;
movie->stream = nullptr;
/* free the buffer */
if (movie->cur_chunk)
mve_free(movie->cur_chunk);
movie->cur_chunk = NULL;
movie->cur_chunk = nullptr;
/* not strictly necessary */
movie->buf_size = 0;
@ -329,12 +329,11 @@ static int _mvefile_open(MVEFILE *file, void *stream) {
* allocate an MVEFILE
*/
static void _mvefile_reset(MVEFILE *file) {
#if 0
file->cur_chunk = NULL;
file->buf_size = 0;
file->cur_fill = 0;
file->next_segment = 0;
#endif
fseek((FILE *)file->stream, 0, SEEK_SET);
file->cur_chunk = nullptr;
file->buf_size = 0;
file->cur_fill = 0;
file->next_segment = 0;
}
/*
@ -435,12 +434,12 @@ static unsigned short _mve_get_ushort(unsigned char *data) {
/*
* allocate an MVESTREAM
*/
static MVESTREAM *_mvestream_alloc(void) {
static MVESTREAM *_mvestream_alloc() {
MVESTREAM *movie;
/* allocate and zero-initialize everything */
movie = (MVESTREAM *)mve_alloc(sizeof(MVESTREAM));
movie->movie = NULL;
movie->movie = nullptr;
movie->context = 0;
memset(movie->handlers, 0, sizeof(movie->handlers));
@ -456,10 +455,10 @@ static void _mvestream_free(MVESTREAM *movie) {
return;
if (movie->movie != nullptr)
mvefile_close(movie->movie);
movie->movie = NULL;
movie->movie = nullptr;
/* clear context and handlers */
movie->context = NULL;
movie->context = nullptr;
memset(movie->handlers, 0, sizeof(movie->handlers));
/* free the struct */
@ -472,7 +471,7 @@ static void _mvestream_free(MVESTREAM *movie) {
static int _mvestream_open(MVESTREAM *movie, void *stream) {
movie->movie = mvefile_open(stream);
return (movie->movie == NULL) ? 0 : 1;
return (movie->movie == nullptr) ? 0 : 1;
}
/*

View File

@ -70,10 +70,10 @@ typedef struct MVESTREAM {
MVESEGMENTHANDLER handlers[32];
} MVESTREAM;
int MVE_rmPrepMovie(void *stream, int x, int y, int track);
int MVE_rmStepMovie();
MVESTREAM* MVE_rmPrepMovie(void *stream, int x, int y, int track);
int MVE_rmStepMovie(MVESTREAM *mve);
void MVE_rmHoldMovie();
void MVE_rmEndMovie();
void MVE_rmEndMovie(MVESTREAM *mve);
void MVE_getVideoSpec(MVE_videoSpec *vSpec);

View File

@ -561,8 +561,6 @@ static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned
return 1;
}
static MVESTREAM *mve = NULL;
void MVE_ioCallbacks(mve_cb_Read io_read) { mve_read = io_read; }
void MVE_memCallbacks(mve_cb_Alloc mem_alloc, mve_cb_Free mem_free) {
@ -574,16 +572,12 @@ void MVE_sfCallbacks(mve_cb_ShowFrame showframe) { mve_showframe = showframe; }
void MVE_palCallbacks(mve_cb_SetPalette setpalette) { mve_setpalette = setpalette; }
int MVE_rmPrepMovie(void *src, int x, int y, int track) {
if (mve) {
mve_reset(mve);
return 0;
}
MVESTREAM* MVE_rmPrepMovie(void *src, int x, int y, int track) {
MVESTREAM *mve;
mve = mve_open(src);
if (!mve)
return 1;
return nullptr;
g_destX = x;
g_destY = y;
@ -614,7 +608,7 @@ int MVE_rmPrepMovie(void *src, int x, int y, int track) {
if (mve_audio_enabled)
mve_play_next_chunk(mve); /* audio initialization chunk */
return 0;
return mve;
}
void MVE_getVideoSpec(MVE_videoSpec *vSpec) {
@ -625,7 +619,7 @@ void MVE_getVideoSpec(MVE_videoSpec *vSpec) {
vSpec->truecolor = g_truecolor;
}
int MVE_rmStepMovie() {
int MVE_rmStepMovie(MVESTREAM *mve) {
static int init_timer = 0;
int cont = 1;
@ -649,11 +643,7 @@ int MVE_rmStepMovie() {
return 0;
}
void MVE_rmEndMovie() {
#ifdef AUDIO
int i;
#endif
void MVE_rmEndMovie(MVESTREAM *mve) {
timer_stop();
timer_created = 0;
@ -663,7 +653,7 @@ void MVE_rmEndMovie() {
Mix_CloseAudio();
mve_audio_canplay = 0;
}
for (i = 0; i < TOTAL_AUDIO_BUFFERS; i++)
for (int i = 0; i < TOTAL_AUDIO_BUFFERS; i++)
if (mve_audio_buffers[i] != NULL)
mve_free(mve_audio_buffers[i]);
memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
@ -678,14 +668,14 @@ void MVE_rmEndMovie() {
#endif
mve_free(g_vBuffers);
g_vBuffers = NULL;
g_pCurMap = NULL;
g_vBuffers = nullptr;
g_pCurMap = nullptr;
g_nMapLength = 0;
videobuf_created = 0;
video_initialized = 0;
mve_close(mve);
mve = NULL;
mve = nullptr;
}
void MVE_rmHoldMovie() { timer_started = 0; }

View File

@ -46,7 +46,7 @@
#include "game.h"
namespace {
MovieFrameCallback_fp Movie_callback = NULL;
MovieFrameCallback_fp Movie_callback = nullptr;
char MovieDir[512];
char SoundCardName[512];
uint16_t CurrentPalette[256];
@ -336,9 +336,9 @@ int mve_PlayMovie(const char *pMovieName, oeApplication *pApp) {
return MVELIB_INIT_ERROR;
}
int result = MVE_rmPrepMovie(hFile, -1, -1, 0);
if (result != 0) {
mprintf(0, "PrepMovie result = %d\n", result);
MVESTREAM *mve = MVE_rmPrepMovie(hFile, -1, -1, 0);
if (mve == nullptr) {
mprintf(0, "Failed to prepMovie %s\n", pMovieName);
fclose(hFile);
mve_CloseSound(soundDevice);
return MVELIB_INIT_ERROR;
@ -346,7 +346,8 @@ int mve_PlayMovie(const char *pMovieName, oeApplication *pApp) {
bool aborted = false;
Movie_current_framenum = 0;
while ((result = MVE_rmStepMovie()) == 0) {
int result;
while ((result = MVE_rmStepMovie(mve)) == 0) {
// let the OS do its thing
pApp->defer();
@ -376,7 +377,7 @@ int mve_PlayMovie(const char *pMovieName, oeApplication *pApp) {
}
// cleanup and shutdown
MVE_rmEndMovie();
MVE_rmEndMovie(mve);
// reset sound
mve_CloseSound(soundDevice);
@ -484,8 +485,8 @@ void CallbackShowFrame(uint8_t *buf, uint32_t bufw, uint32_t bufh, uint32_t sx,
BlitToMovieBitmap(buf, bufw, bufh, hicolor, true, texW, texH);
// calculate UVs from texture
int drawWidth = bufw;
int drawHeight = bufh;
unsigned int drawWidth = bufw;
unsigned int drawHeight = bufh;
float u = float(drawWidth - 1) / float(texW - 1);
float v = float(drawHeight - 1) / float(texH - 1);
@ -505,7 +506,7 @@ void CallbackShowFrame(uint8_t *buf, uint32_t bufw, uint32_t bufh, uint32_t sx,
rend_SetZBufferState(1);
// call our callback
if (Movie_callback != NULL) {
if (Movie_callback != nullptr) {
Movie_callback(dstx, dsty, Movie_current_framenum);
}
++Movie_current_framenum;
@ -514,6 +515,43 @@ void CallbackShowFrame(uint8_t *buf, uint32_t bufw, uint32_t bufh, uint32_t sx,
rend_Flip();
}
// This callback is same as CallbackShowFrame() but don't flip renderer at end, so there no flickering
void CallbackShowFrameNoFlip(unsigned char *buf, unsigned int bufw, unsigned int bufh, unsigned int sx, unsigned int sy,
unsigned int w, unsigned int h, unsigned int dstx, unsigned int dsty, unsigned int hicolor) {
// prepare our bitmap
int texW, texH;
BlitToMovieBitmap(buf, bufw, bufh, hicolor, true, texW, texH);
// calculate UVs from texture
unsigned int drawWidth = bufw;
unsigned int drawHeight = bufh;
float u = float(drawWidth - 1) / float(texW - 1);
float v = float(drawHeight - 1) / float(texH - 1);
StartFrame(0, 0, 640, 480, false);
rend_ClearScreen(GR_BLACK);
rend_SetAlphaType(AT_CONSTANT);
rend_SetAlphaValue(255);
rend_SetLighting(LS_NONE);
rend_SetColorModel(CM_MONO);
rend_SetOverlayType(OT_NONE);
rend_SetWrapType(WT_CLAMP);
rend_SetFiltering(0);
rend_SetZBufferState(0);
rend_DrawScaledBitmap(dstx, dsty, dstx + drawWidth, dsty + drawHeight, Movie_bm_handle, 0.0f, 0.0f, u, v);
rend_SetFiltering(1);
rend_SetZBufferState(1);
// call our callback
if (Movie_callback != nullptr) {
Movie_callback(dstx, dsty, Movie_current_framenum);
}
++Movie_current_framenum;
EndFrame();
}
#endif
intptr_t mve_SequenceStart(const char *mvename, void *fhandle, oeApplication *app, bool looping) {
@ -530,11 +568,10 @@ intptr_t mve_SequenceStart(const char *mvename, void *fhandle, oeApplication *ap
#else
real_name = mvename;
#endif
FILE *hfile = fopen(real_name.u8string().c_str(), "rb");
fhandle = fopen(real_name.u8string().c_str(), "rb");
if (hfile == nullptr) {
if (fhandle == nullptr) {
mprintf(1, "MOVIE: Unable to open %s\n", real_name.u8string().c_str());
fhandle = nullptr;
return 0;
}
@ -542,6 +579,7 @@ intptr_t mve_SequenceStart(const char *mvename, void *fhandle, oeApplication *ap
//MVE_rmFastMode(MVE_RM_NORMAL);
MVE_memCallbacks(CallbackAlloc, CallbackFree);
MVE_ioCallbacks(CallbackFileRead);
MVE_sfCallbacks(CallbackShowFrameNoFlip);
InitializePalette();
Movie_bm_handle = -1;
Movie_looping = looping;
@ -549,11 +587,16 @@ intptr_t mve_SequenceStart(const char *mvename, void *fhandle, oeApplication *ap
// let the render know we will be copying bitmaps to framebuffer (or something)
rend_SetFrameBufferCopyState(true);
fhandle = hfile;
// TODO return (intptr_t)MVE_frOpen(CallbackFileRead, hfile, NULL);
return 0;
MVESTREAM *mve = MVE_rmPrepMovie(fhandle, -1, -1, 0);
if (mve == nullptr) {
mprintf((0, "Failed to PrepMovie %s\n", mvename));
fclose((FILE *)fhandle);
return MVELIB_INIT_ERROR;
}
return (intptr_t)mve;
#else
return 0;
return nullptr;
#endif
}
@ -573,17 +616,8 @@ intptr_t mve_SequenceFrame(intptr_t handle, void *fhandle, bool sequence, int *b
reread_frame:
// get the next frame of data
uint8_t *pBuffer = NULL;
// TODO err = MVE_frGet((MVE_frStream)handle, &pBuffer, &sw, &sh, &hicolor);
// refresh our palette
{
uint32_t palstart = 0;
uint32_t palcount = 0;
uint8_t *pal = NULL;
// TODO MVE_frPal((MVE_frStream)handle, &pal, &palstart, &palcount);
CallbackSetPalette(pal, palstart, palcount);
}
uint8_t *pBuffer = nullptr;
err = MVE_rmStepMovie((MVESTREAM *)handle);
if (err == 0) {
// blit to bitmap
@ -598,9 +632,7 @@ reread_frame:
}
if (Movie_looping && err == MVE_ERR_EOF) {
// TODO MVE_frClose((MVE_frStream)handle);
fseek((FILE *)fhandle, 0, SEEK_SET);
// TODO handle = (intptr_t)MVE_frOpen(CallbackFileRead, (FILE *)fhandle, NULL);
mve_reset((MVESTREAM *)handle);
sequence = true;
goto reread_frame;
}
@ -616,9 +648,7 @@ bool mve_SequenceClose(intptr_t hMovie, void *hFile) {
if (hMovie == -1)
return false;
// TODO MVE_frClose((MVE_frStream)hMovie);
MVE_rmEndMovie();
fclose((FILE *)hFile);
MVE_rmEndMovie((MVESTREAM *)hMovie);
// free our bitmap
if (Movie_bm_handle != -1) {