From a8784ee524ef3729d77b9b59463adc3f859dd433 Mon Sep 17 00:00:00 2001 From: "Azamat H. Hackimov" Date: Sun, 5 May 2024 03:52:52 +0300 Subject: [PATCH] MVE: Implementing frame playing (main menu) Reorganized MVE to use own MVESTREAM pointer for each opened MVE file. --- libmve/mvelib.cpp | 57 ++++++++++++++------------- libmve/mvelib.h | 6 +-- libmve/mveplay.cpp | 30 +++++---------- movie/d3movie.cpp | 96 ++++++++++++++++++++++++++++++---------------- 4 files changed, 104 insertions(+), 85 deletions(-) diff --git a/libmve/mvelib.cpp b/libmve/mvelib.cpp index 7e9b1a5c..0e538584 100644 --- a/libmve/mvelib.cpp +++ b/libmve/mvelib.cpp @@ -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; } /* diff --git a/libmve/mvelib.h b/libmve/mvelib.h index d91278ed..257bf776 100644 --- a/libmve/mvelib.h +++ b/libmve/mvelib.h @@ -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); diff --git a/libmve/mveplay.cpp b/libmve/mveplay.cpp index fd2e2862..c28aef6d 100644 --- a/libmve/mveplay.cpp +++ b/libmve/mveplay.cpp @@ -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; } diff --git a/movie/d3movie.cpp b/movie/d3movie.cpp index 9e0c6a6c..7e80a076 100644 --- a/movie/d3movie.cpp +++ b/movie/d3movie.cpp @@ -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) {