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 * private functions for mvefile
*/ */
static MVEFILE *_mvefile_alloc(void); static MVEFILE *_mvefile_alloc();
static void _mvefile_free(MVEFILE *movie); static void _mvefile_free(MVEFILE *movie);
static int _mvefile_open(MVEFILE *movie, void *stream); static int _mvefile_open(MVEFILE *movie, void *stream);
static void _mvefile_reset(MVEFILE *movie); static void _mvefile_reset(MVEFILE *movie);
@ -50,7 +50,7 @@ static int _mvefile_fetch_next_chunk(MVEFILE *movie);
/* /*
* private functions for mvestream * private functions for mvestream
*/ */
static MVESTREAM *_mvestream_alloc(void); static MVESTREAM *_mvestream_alloc();
static void _mvestream_free(MVESTREAM *movie); static void _mvestream_free(MVESTREAM *movie);
static int _mvestream_open(MVESTREAM *movie, void *stream); static int _mvestream_open(MVESTREAM *movie, void *stream);
static void _mvestream_reset(MVESTREAM *movie); static void _mvestream_reset(MVESTREAM *movie);
@ -69,7 +69,7 @@ MVEFILE *mvefile_open(void *stream) {
file = _mvefile_alloc(); file = _mvefile_alloc();
if (!_mvefile_open(file, stream)) { if (!_mvefile_open(file, stream)) {
_mvefile_free(file); _mvefile_free(file);
return NULL; return nullptr;
} }
/* initialize the file */ /* initialize the file */
@ -78,7 +78,7 @@ MVEFILE *mvefile_open(void *stream) {
/* verify the file's header */ /* verify the file's header */
if (!_mvefile_read_header(file)) { if (!_mvefile_read_header(file)) {
_mvefile_free(file); _mvefile_free(file);
return NULL; return nullptr;
} }
/* now, prefetch the next chunk */ /* now, prefetch the next chunk */
@ -116,7 +116,7 @@ void mvefile_reset(MVEFILE *file) {
*/ */
int mvefile_get_next_segment_size(MVEFILE *movie) { int mvefile_get_next_segment_size(MVEFILE *movie) {
/* if nothing is cached, fail */ /* 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; return -1;
/* if we don't have enough data to get a segment, fail */ /* 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) { unsigned char mvefile_get_next_segment_major(MVEFILE *movie) {
/* if nothing is cached, fail */ /* 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; return 0xff;
/* if we don't have enough data to get a segment, fail */ /* 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) { unsigned char mvefile_get_next_segment_minor(MVEFILE *movie) {
/* if nothing is cached, fail */ /* 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; return 0xff;
/* if we don't have enough data to get a segment, fail */ /* 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) { unsigned char *mvefile_get_next_segment(MVEFILE *movie) {
/* if nothing is cached, fail */ /* 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 NULL; return nullptr;
/* if we don't have enough data to get a segment, fail */ /* if we don't have enough data to get a segment, fail */
if (movie->cur_fill - movie->next_segment < 4) if (movie->cur_fill - movie->next_segment < 4)
return NULL; return nullptr;
/* otherwise, get the data length */ /* otherwise, get the data length */
return movie->cur_chunk + movie->next_segment + 4; 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) { void mvefile_advance_segment(MVEFILE *movie) {
/* if nothing is cached, fail */ /* 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; return;
/* if we don't have enough data to get a segment, fail */ /* if we don't have enough data to get a segment, fail */
@ -213,7 +213,7 @@ MVESTREAM *mve_open(void *stream) {
/* open */ /* open */
if (!_mvestream_open(movie, stream)) { if (!_mvestream_open(movie, stream)) {
_mvestream_free(movie); _mvestream_free(movie);
return NULL; return nullptr;
} }
return movie; return movie;
@ -254,7 +254,7 @@ int mve_play_next_chunk(MVESTREAM *movie) {
major = mvefile_get_next_segment_major(movie->movie); major = mvefile_get_next_segment_major(movie->movie);
while (major != 0xff) { while (major != 0xff) {
/* check whether to handle the segment */ /* 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); minor = mvefile_get_next_segment_minor(movie->movie);
len = mvefile_get_next_segment_size(movie->movie); len = mvefile_get_next_segment_size(movie->movie);
data = mvefile_get_next_segment(movie->movie); data = mvefile_get_next_segment(movie->movie);
@ -282,10 +282,10 @@ int mve_play_next_chunk(MVESTREAM *movie) {
/* /*
* allocate an MVEFILE * allocate an MVEFILE
*/ */
static MVEFILE *_mvefile_alloc(void) { static MVEFILE *_mvefile_alloc() {
MVEFILE *file = (MVEFILE *)mve_alloc(sizeof(MVEFILE)); MVEFILE *file = (MVEFILE *)mve_alloc(sizeof(MVEFILE));
file->stream = NULL; file->stream = nullptr;
file->cur_chunk = NULL; file->cur_chunk = nullptr;
file->buf_size = 0; file->buf_size = 0;
file->cur_fill = 0; file->cur_fill = 0;
file->next_segment = 0; file->next_segment = 0;
@ -298,12 +298,12 @@ static MVEFILE *_mvefile_alloc(void) {
*/ */
static void _mvefile_free(MVEFILE *movie) { static void _mvefile_free(MVEFILE *movie) {
/* free the stream */ /* free the stream */
movie->stream = NULL; movie->stream = nullptr;
/* free the buffer */ /* free the buffer */
if (movie->cur_chunk) if (movie->cur_chunk)
mve_free(movie->cur_chunk); mve_free(movie->cur_chunk);
movie->cur_chunk = NULL; movie->cur_chunk = nullptr;
/* not strictly necessary */ /* not strictly necessary */
movie->buf_size = 0; movie->buf_size = 0;
@ -329,12 +329,11 @@ static int _mvefile_open(MVEFILE *file, void *stream) {
* allocate an MVEFILE * allocate an MVEFILE
*/ */
static void _mvefile_reset(MVEFILE *file) { static void _mvefile_reset(MVEFILE *file) {
#if 0 fseek((FILE *)file->stream, 0, SEEK_SET);
file->cur_chunk = NULL; file->cur_chunk = nullptr;
file->buf_size = 0; file->buf_size = 0;
file->cur_fill = 0; file->cur_fill = 0;
file->next_segment = 0; file->next_segment = 0;
#endif
} }
/* /*
@ -435,12 +434,12 @@ static unsigned short _mve_get_ushort(unsigned char *data) {
/* /*
* allocate an MVESTREAM * allocate an MVESTREAM
*/ */
static MVESTREAM *_mvestream_alloc(void) { static MVESTREAM *_mvestream_alloc() {
MVESTREAM *movie; MVESTREAM *movie;
/* allocate and zero-initialize everything */ /* allocate and zero-initialize everything */
movie = (MVESTREAM *)mve_alloc(sizeof(MVESTREAM)); movie = (MVESTREAM *)mve_alloc(sizeof(MVESTREAM));
movie->movie = NULL; movie->movie = nullptr;
movie->context = 0; movie->context = 0;
memset(movie->handlers, 0, sizeof(movie->handlers)); memset(movie->handlers, 0, sizeof(movie->handlers));
@ -456,10 +455,10 @@ static void _mvestream_free(MVESTREAM *movie) {
return; return;
if (movie->movie != nullptr) if (movie->movie != nullptr)
mvefile_close(movie->movie); mvefile_close(movie->movie);
movie->movie = NULL; movie->movie = nullptr;
/* clear context and handlers */ /* clear context and handlers */
movie->context = NULL; movie->context = nullptr;
memset(movie->handlers, 0, sizeof(movie->handlers)); memset(movie->handlers, 0, sizeof(movie->handlers));
/* free the struct */ /* free the struct */
@ -472,7 +471,7 @@ static void _mvestream_free(MVESTREAM *movie) {
static int _mvestream_open(MVESTREAM *movie, void *stream) { static int _mvestream_open(MVESTREAM *movie, void *stream) {
movie->movie = mvefile_open(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]; MVESEGMENTHANDLER handlers[32];
} MVESTREAM; } MVESTREAM;
int MVE_rmPrepMovie(void *stream, int x, int y, int track); MVESTREAM* MVE_rmPrepMovie(void *stream, int x, int y, int track);
int MVE_rmStepMovie(); int MVE_rmStepMovie(MVESTREAM *mve);
void MVE_rmHoldMovie(); void MVE_rmHoldMovie();
void MVE_rmEndMovie(); void MVE_rmEndMovie(MVESTREAM *mve);
void MVE_getVideoSpec(MVE_videoSpec *vSpec); 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; return 1;
} }
static MVESTREAM *mve = NULL;
void MVE_ioCallbacks(mve_cb_Read io_read) { mve_read = io_read; } 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) { 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; } void MVE_palCallbacks(mve_cb_SetPalette setpalette) { mve_setpalette = setpalette; }
int MVE_rmPrepMovie(void *src, int x, int y, int track) { MVESTREAM* MVE_rmPrepMovie(void *src, int x, int y, int track) {
if (mve) { MVESTREAM *mve;
mve_reset(mve);
return 0;
}
mve = mve_open(src); mve = mve_open(src);
if (!mve) if (!mve)
return 1; return nullptr;
g_destX = x; g_destX = x;
g_destY = y; g_destY = y;
@ -614,7 +608,7 @@ int MVE_rmPrepMovie(void *src, int x, int y, int track) {
if (mve_audio_enabled) if (mve_audio_enabled)
mve_play_next_chunk(mve); /* audio initialization chunk */ mve_play_next_chunk(mve); /* audio initialization chunk */
return 0; return mve;
} }
void MVE_getVideoSpec(MVE_videoSpec *vSpec) { void MVE_getVideoSpec(MVE_videoSpec *vSpec) {
@ -625,7 +619,7 @@ void MVE_getVideoSpec(MVE_videoSpec *vSpec) {
vSpec->truecolor = g_truecolor; vSpec->truecolor = g_truecolor;
} }
int MVE_rmStepMovie() { int MVE_rmStepMovie(MVESTREAM *mve) {
static int init_timer = 0; static int init_timer = 0;
int cont = 1; int cont = 1;
@ -649,11 +643,7 @@ int MVE_rmStepMovie() {
return 0; return 0;
} }
void MVE_rmEndMovie() { void MVE_rmEndMovie(MVESTREAM *mve) {
#ifdef AUDIO
int i;
#endif
timer_stop(); timer_stop();
timer_created = 0; timer_created = 0;
@ -663,7 +653,7 @@ void MVE_rmEndMovie() {
Mix_CloseAudio(); Mix_CloseAudio();
mve_audio_canplay = 0; 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) if (mve_audio_buffers[i] != NULL)
mve_free(mve_audio_buffers[i]); mve_free(mve_audio_buffers[i]);
memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers)); memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers));
@ -678,14 +668,14 @@ void MVE_rmEndMovie() {
#endif #endif
mve_free(g_vBuffers); mve_free(g_vBuffers);
g_vBuffers = NULL; g_vBuffers = nullptr;
g_pCurMap = NULL; g_pCurMap = nullptr;
g_nMapLength = 0; g_nMapLength = 0;
videobuf_created = 0; videobuf_created = 0;
video_initialized = 0; video_initialized = 0;
mve_close(mve); mve_close(mve);
mve = NULL; mve = nullptr;
} }
void MVE_rmHoldMovie() { timer_started = 0; } void MVE_rmHoldMovie() { timer_started = 0; }

View File

@ -46,7 +46,7 @@
#include "game.h" #include "game.h"
namespace { namespace {
MovieFrameCallback_fp Movie_callback = NULL; MovieFrameCallback_fp Movie_callback = nullptr;
char MovieDir[512]; char MovieDir[512];
char SoundCardName[512]; char SoundCardName[512];
uint16_t CurrentPalette[256]; uint16_t CurrentPalette[256];
@ -336,9 +336,9 @@ int mve_PlayMovie(const char *pMovieName, oeApplication *pApp) {
return MVELIB_INIT_ERROR; return MVELIB_INIT_ERROR;
} }
int result = MVE_rmPrepMovie(hFile, -1, -1, 0); MVESTREAM *mve = MVE_rmPrepMovie(hFile, -1, -1, 0);
if (result != 0) { if (mve == nullptr) {
mprintf(0, "PrepMovie result = %d\n", result); mprintf(0, "Failed to prepMovie %s\n", pMovieName);
fclose(hFile); fclose(hFile);
mve_CloseSound(soundDevice); mve_CloseSound(soundDevice);
return MVELIB_INIT_ERROR; return MVELIB_INIT_ERROR;
@ -346,7 +346,8 @@ int mve_PlayMovie(const char *pMovieName, oeApplication *pApp) {
bool aborted = false; bool aborted = false;
Movie_current_framenum = 0; Movie_current_framenum = 0;
while ((result = MVE_rmStepMovie()) == 0) { int result;
while ((result = MVE_rmStepMovie(mve)) == 0) {
// let the OS do its thing // let the OS do its thing
pApp->defer(); pApp->defer();
@ -376,7 +377,7 @@ int mve_PlayMovie(const char *pMovieName, oeApplication *pApp) {
} }
// cleanup and shutdown // cleanup and shutdown
MVE_rmEndMovie(); MVE_rmEndMovie(mve);
// reset sound // reset sound
mve_CloseSound(soundDevice); 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); BlitToMovieBitmap(buf, bufw, bufh, hicolor, true, texW, texH);
// calculate UVs from texture // calculate UVs from texture
int drawWidth = bufw; unsigned int drawWidth = bufw;
int drawHeight = bufh; unsigned int drawHeight = bufh;
float u = float(drawWidth - 1) / float(texW - 1); float u = float(drawWidth - 1) / float(texW - 1);
float v = float(drawHeight - 1) / float(texH - 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); rend_SetZBufferState(1);
// call our callback // call our callback
if (Movie_callback != NULL) { if (Movie_callback != nullptr) {
Movie_callback(dstx, dsty, Movie_current_framenum); Movie_callback(dstx, dsty, Movie_current_framenum);
} }
++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(); 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 #endif
intptr_t mve_SequenceStart(const char *mvename, void *fhandle, oeApplication *app, bool looping) { 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 #else
real_name = mvename; real_name = mvename;
#endif #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()); mprintf(1, "MOVIE: Unable to open %s\n", real_name.u8string().c_str());
fhandle = nullptr;
return 0; return 0;
} }
@ -542,6 +579,7 @@ intptr_t mve_SequenceStart(const char *mvename, void *fhandle, oeApplication *ap
//MVE_rmFastMode(MVE_RM_NORMAL); //MVE_rmFastMode(MVE_RM_NORMAL);
MVE_memCallbacks(CallbackAlloc, CallbackFree); MVE_memCallbacks(CallbackAlloc, CallbackFree);
MVE_ioCallbacks(CallbackFileRead); MVE_ioCallbacks(CallbackFileRead);
MVE_sfCallbacks(CallbackShowFrameNoFlip);
InitializePalette(); InitializePalette();
Movie_bm_handle = -1; Movie_bm_handle = -1;
Movie_looping = looping; 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) // let the render know we will be copying bitmaps to framebuffer (or something)
rend_SetFrameBufferCopyState(true); rend_SetFrameBufferCopyState(true);
fhandle = hfile; MVESTREAM *mve = MVE_rmPrepMovie(fhandle, -1, -1, 0);
// TODO return (intptr_t)MVE_frOpen(CallbackFileRead, hfile, NULL); if (mve == nullptr) {
return 0; mprintf((0, "Failed to PrepMovie %s\n", mvename));
fclose((FILE *)fhandle);
return MVELIB_INIT_ERROR;
}
return (intptr_t)mve;
#else #else
return 0; return nullptr;
#endif #endif
} }
@ -573,17 +616,8 @@ intptr_t mve_SequenceFrame(intptr_t handle, void *fhandle, bool sequence, int *b
reread_frame: reread_frame:
// get the next frame of data // get the next frame of data
uint8_t *pBuffer = NULL; uint8_t *pBuffer = nullptr;
// TODO err = MVE_frGet((MVE_frStream)handle, &pBuffer, &sw, &sh, &hicolor); err = MVE_rmStepMovie((MVESTREAM *)handle);
// 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);
}
if (err == 0) { if (err == 0) {
// blit to bitmap // blit to bitmap
@ -598,9 +632,7 @@ reread_frame:
} }
if (Movie_looping && err == MVE_ERR_EOF) { if (Movie_looping && err == MVE_ERR_EOF) {
// TODO MVE_frClose((MVE_frStream)handle); mve_reset((MVESTREAM *)handle);
fseek((FILE *)fhandle, 0, SEEK_SET);
// TODO handle = (intptr_t)MVE_frOpen(CallbackFileRead, (FILE *)fhandle, NULL);
sequence = true; sequence = true;
goto reread_frame; goto reread_frame;
} }
@ -616,9 +648,7 @@ bool mve_SequenceClose(intptr_t hMovie, void *hFile) {
if (hMovie == -1) if (hMovie == -1)
return false; return false;
// TODO MVE_frClose((MVE_frStream)hMovie); MVE_rmEndMovie((MVESTREAM *)hMovie);
MVE_rmEndMovie();
fclose((FILE *)hFile);
// free our bitmap // free our bitmap
if (Movie_bm_handle != -1) { if (Movie_bm_handle != -1) {