Unload robot movies on exit
This commit is contained in:
parent
76a7361786
commit
d0d7545ec1
|
@ -73,6 +73,7 @@ constexpr std::integral_constant<uint8_t, 127> MAX_SECRET_LEVELS_PER_MISSION{};
|
|||
#define FULL_MISSION_HOGSIZE 7595079 // v1.1 - 1.2
|
||||
#define FULL_10_MISSION_HOGSIZE 7107354 // v1.0
|
||||
#define MAC_FULL_MISSION_HOGSIZE 7110007 // v1.1 - 1.2
|
||||
#include "movie.h"
|
||||
#endif
|
||||
|
||||
//where the missions go
|
||||
|
@ -132,6 +133,8 @@ public:
|
|||
};
|
||||
|
||||
#if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
|
||||
namespace dsx {
|
||||
|
||||
struct Mission : Mission_path
|
||||
{
|
||||
std::unique_ptr<ubyte[]> secret_level_table; // originating level no for each secret level
|
||||
|
@ -149,6 +152,7 @@ struct Mission : Mission_path
|
|||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
descent_version_type descent_version; // descent 1 or descent 2?
|
||||
std::unique_ptr<d_fname> alternate_ham_file;
|
||||
std::unique_ptr<LoadedMovie> extra_robot_movie;
|
||||
#endif
|
||||
/* Explicitly default move constructor and move operator=
|
||||
*
|
||||
|
@ -203,6 +207,8 @@ extern Mission_ptr Current_mission; // current mission
|
|||
#endif
|
||||
#define PLAYING_BUILTIN_MISSION (Current_mission->builtin_hogsize != 0)
|
||||
#define ANARCHY_ONLY_MISSION (1 == Current_mission->anarchy_only_flag)
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
//values for d1 built-in mission
|
||||
|
|
|
@ -20,10 +20,14 @@
|
|||
|
||||
using namespace dcx;
|
||||
|
||||
namespace {
|
||||
|
||||
static unsigned short *backBuf1, *backBuf2;
|
||||
|
||||
static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, const unsigned char **pData, const unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb);
|
||||
|
||||
}
|
||||
|
||||
void decodeFrame16(unsigned char *pFrame, const unsigned char *pMap, int mapRemain, const unsigned char *pData, int dataRemain)
|
||||
{
|
||||
unsigned short offset;
|
||||
|
@ -86,6 +90,8 @@ void decodeFrame16(unsigned char *pFrame, const unsigned char *pMap, int mapRema
|
|||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static uint16_t GETPIXEL(const unsigned char **buf, int off)
|
||||
{
|
||||
unsigned short val = (*buf)[0+off] | ((*buf)[1+off] << 8);
|
||||
|
@ -104,12 +110,12 @@ struct position_t
|
|||
int x, y;
|
||||
};
|
||||
|
||||
static inline constexpr position_t relClose(int i)
|
||||
static constexpr position_t relClose(int i)
|
||||
{
|
||||
return {(i & 0xf) - 8, (i >> 4) - 8};
|
||||
}
|
||||
|
||||
static inline constexpr position_t relFar0(int i, int sign)
|
||||
static constexpr position_t relFar0(int i, int sign)
|
||||
{
|
||||
return {
|
||||
sign * (8 + (i % 7)),
|
||||
|
@ -117,7 +123,7 @@ static inline constexpr position_t relFar0(int i, int sign)
|
|||
};
|
||||
}
|
||||
|
||||
static inline constexpr position_t relFar56(int i, int sign)
|
||||
static constexpr position_t relFar56(int i, int sign)
|
||||
{
|
||||
return {
|
||||
sign * (-14 + (i - 56) % 29),
|
||||
|
@ -125,7 +131,7 @@ static inline constexpr position_t relFar56(int i, int sign)
|
|||
};
|
||||
}
|
||||
|
||||
static inline constexpr position_t relFar(int i, int sign)
|
||||
static constexpr position_t relFar(int i, int sign)
|
||||
{
|
||||
return (i < 56) ? relFar0(i, sign) : relFar56(i, sign);
|
||||
}
|
||||
|
@ -136,7 +142,7 @@ struct lookup_table_t
|
|||
};
|
||||
|
||||
template <std::size_t... N>
|
||||
static inline constexpr lookup_table_t genLoopkupTable(std::index_sequence<N...>)
|
||||
static constexpr lookup_table_t genLoopkupTable(std::index_sequence<N...>)
|
||||
{
|
||||
return lookup_table_t{
|
||||
{{relClose(N)...}},
|
||||
|
@ -716,3 +722,5 @@ static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, c
|
|||
|
||||
*pFrame = pDstBak+8;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "mvelib.h"
|
||||
#include <memory>
|
||||
|
||||
namespace {
|
||||
|
||||
static const char MVE_HEADER[] = "Interplay MVE File\x1A";
|
||||
constexpr short MVE_HDRCONST1 = 0x001A;
|
||||
constexpr short MVE_HDRCONST2 = 0x0100;
|
||||
|
@ -40,6 +42,8 @@ static int _mvefile_fetch_next_chunk(MVEFILE *movie);
|
|||
static int _mvestream_open(MVESTREAM *movie, void *stream);
|
||||
static void _mvestream_reset(MVESTREAM *movie);
|
||||
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* public MVEFILE functions
|
||||
************************************************************/
|
||||
|
@ -70,6 +74,8 @@ std::unique_ptr<MVEFILE> mvefile_open(void *stream)
|
|||
return file;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
* reset a MVE file
|
||||
*/
|
||||
|
@ -99,6 +105,8 @@ static bool have_segment_header(const MVEFILE *movie)
|
|||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* get the size of the next segment
|
||||
*/
|
||||
|
@ -262,6 +270,8 @@ MVEFILE::~MVEFILE()
|
|||
{
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
* open the file stream in thie object
|
||||
*/
|
||||
|
@ -359,6 +369,8 @@ static uint16_t _mve_get_ushort(const unsigned char *data)
|
|||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate an MVESTREAM
|
||||
*/
|
||||
|
@ -371,6 +383,8 @@ MVESTREAM::~MVESTREAM()
|
|||
{
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/*
|
||||
* open an MVESTREAM object
|
||||
*/
|
||||
|
@ -388,3 +402,5 @@ static void _mvestream_reset(MVESTREAM *movie)
|
|||
{
|
||||
mvefile_reset(movie->movie.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -62,6 +62,9 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
|
||||
#include "compiler-range_for.h"
|
||||
#include "partial_range.h"
|
||||
#include "d_zip.h"
|
||||
|
||||
namespace dsx {
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -88,13 +91,6 @@ constexpr std::array<std::array<char, 8>, 3> movielib_files{{
|
|||
{"intro"}, {"other"}, {"robots"}
|
||||
}};
|
||||
|
||||
struct loaded_movie_t
|
||||
{
|
||||
std::array<char, FILENAME_LEN + 2> filename;
|
||||
};
|
||||
|
||||
static loaded_movie_t extra_robot_movie_mission;
|
||||
|
||||
static RWops_ptr RoboFile;
|
||||
|
||||
// Function Prototypes
|
||||
|
@ -112,6 +108,8 @@ struct movie_pause_window : window
|
|||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *MovieMemoryAllocate(std::size_t size)
|
||||
{
|
||||
return d_malloc(size);
|
||||
|
@ -130,6 +128,7 @@ unsigned int MovieFileRead(void *handle, void *buf, unsigned int count)
|
|||
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
namespace dsx {
|
||||
|
||||
//filename will actually get modified to be either low-res or high-res
|
||||
//returns status. see values in movie.h
|
||||
|
@ -170,6 +169,8 @@ movie_play_status PlayMovie(const char *subtitles, const char *filename, int mus
|
|||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MovieShowFrame(const uint8_t *buf, int dstx, int dsty, int bufw, int bufh, int sw, int sh)
|
||||
{
|
||||
grs_bitmap source_bm;
|
||||
|
@ -243,6 +244,8 @@ void MovieSetPalette(const unsigned char *p, unsigned start, unsigned count)
|
|||
memcpy(&gr_palette[start],p+start*3,count*3);
|
||||
}
|
||||
|
||||
namespace dsx {
|
||||
|
||||
namespace {
|
||||
|
||||
struct movie : window
|
||||
|
@ -443,14 +446,12 @@ int RotateRobot(MVESTREAM_ptr_t &pMovie)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void DeInitRobotMovie(MVESTREAM_ptr_t &pMovie)
|
||||
{
|
||||
pMovie.reset();
|
||||
RoboFile.reset(); // Close Movie File
|
||||
}
|
||||
|
||||
|
||||
int InitRobotMovie(const char *filename, MVESTREAM_ptr_t &pMovie)
|
||||
{
|
||||
if (GameArg.SysNoMovies)
|
||||
|
@ -636,60 +637,60 @@ static void draw_subtitles(const d_subtitle_state &SubtitleState, const int fram
|
|||
}
|
||||
}
|
||||
|
||||
static int init_movie(const char *movielib, char resolution, int required, loaded_movie_t &movie)
|
||||
static int init_movie(const char *movielib, char resolution, int required, LoadedMovie &movie)
|
||||
{
|
||||
snprintf(&movie.filename[0], movie.filename.size(), "%s-%c.mvl", movielib, resolution);
|
||||
std::array<char, PATH_MAX> pathname;
|
||||
auto r = PHYSFSX_addRelToSearchPath(&movie.filename[0], pathname, physfs_search_path::prepend);
|
||||
std::array<char, FILENAME_LEN + 2> filename;
|
||||
snprintf(&filename[0], filename.size(), "%s-%c.mvl", movielib, resolution);
|
||||
auto r = PHYSFSX_addRelToSearchPath(&filename[0], movie.pathname, physfs_search_path::prepend);
|
||||
if (!r)
|
||||
{
|
||||
if (required || CGameArg.DbgVerbose)
|
||||
con_printf(CON_URGENT, "Can't open movielib <%s>: %s", &movie.filename[0], PHYSFS_getLastError());
|
||||
movie.filename[0] = 0;
|
||||
con_printf(required ? CON_URGENT : CON_VERBOSE, "Can't open movielib <%s>: %s", &filename[0], PHYSFS_getLastError());
|
||||
movie.pathname[0] = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static void init_movie(const char *movielib, int required, loaded_movie_t &movie)
|
||||
static int init_movie(const char *movielib, int required, LoadedMovie &movie)
|
||||
{
|
||||
if (!GameArg.GfxSkipHiresMovie)
|
||||
{
|
||||
if (init_movie(movielib, 'h', required, movie))
|
||||
return;
|
||||
if (auto r = init_movie(movielib, 'h', required, movie))
|
||||
return r;
|
||||
}
|
||||
init_movie(movielib, 'l', required, movie);
|
||||
return init_movie(movielib, 'l', required, movie);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//find and initialize the movie libraries
|
||||
void init_movies()
|
||||
std::unique_ptr<BuiltinMovies> init_movies()
|
||||
{
|
||||
if (GameArg.SysNoMovies)
|
||||
return;
|
||||
return nullptr;
|
||||
|
||||
range_for (auto &i, movielib_files)
|
||||
{
|
||||
loaded_movie_t m;
|
||||
init_movie(&i[0], 1, m);
|
||||
}
|
||||
auto r = std::make_unique<BuiltinMovies>();
|
||||
for (auto &&[f, m] : zip(movielib_files, r->movies))
|
||||
init_movie(&f[0], 1, m);
|
||||
return r;
|
||||
}
|
||||
|
||||
void close_extra_robot_movie()
|
||||
LoadedMovie::~LoadedMovie()
|
||||
{
|
||||
const auto movielib = &extra_robot_movie_mission.filename[0];
|
||||
const auto movielib = pathname.data();
|
||||
if (!*movielib)
|
||||
return;
|
||||
if (!PHYSFSX_contfile_close(movielib))
|
||||
{
|
||||
con_printf(CON_URGENT, "Can't close movielib <%s>: %s", movielib, PHYSFS_getLastError());
|
||||
}
|
||||
*movielib = 0;
|
||||
if (!PHYSFS_unmount(movielib))
|
||||
con_printf(CON_URGENT, "Cannot close movielib <%s>: %s", movielib, PHYSFS_getLastError());
|
||||
}
|
||||
|
||||
void init_extra_robot_movie(const char *movielib)
|
||||
std::unique_ptr<LoadedMovie> init_extra_robot_movie(const char *movielib)
|
||||
{
|
||||
if (GameArg.SysNoMovies)
|
||||
return;
|
||||
init_movie(movielib, 0, extra_robot_movie_mission);
|
||||
return nullptr;
|
||||
auto r = std::make_unique<LoadedMovie>();
|
||||
if (!init_movie(movielib, 0, *r))
|
||||
return nullptr;
|
||||
return r;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,8 +25,11 @@ COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <limits.h>
|
||||
#include "d2x-rebirth/libmve/mvelib.h"
|
||||
#include "dsx-ns.h"
|
||||
|
||||
namespace dsx {
|
||||
|
||||
#define MOVIE_ABORT_ON 1
|
||||
#define MOVIE_ABORT_OFF 0
|
||||
|
@ -50,12 +53,25 @@ int InitRobotMovie(const char *filename, MVESTREAM_ptr_t &pMovie);
|
|||
int RotateRobot(MVESTREAM_ptr_t &pMovie);
|
||||
void DeInitRobotMovie(MVESTREAM_ptr_t &pMovie);
|
||||
|
||||
// find and initialize the movie libraries
|
||||
void init_movies();
|
||||
struct LoadedMovie
|
||||
{
|
||||
std::array<char, PATH_MAX> pathname;
|
||||
LoadedMovie()
|
||||
{
|
||||
pathname[0] = 0;
|
||||
}
|
||||
~LoadedMovie();
|
||||
};
|
||||
|
||||
void init_extra_robot_movie(const char *filename);
|
||||
void close_extra_robot_movie();
|
||||
struct BuiltinMovies
|
||||
{
|
||||
std::array<LoadedMovie, 3> movies;
|
||||
};
|
||||
|
||||
// find and initialize the movie libraries
|
||||
std::unique_ptr<BuiltinMovies> init_movies();
|
||||
std::unique_ptr<LoadedMovie> init_extra_robot_movie(const char *filename);
|
||||
|
||||
extern int MovieHires; // specifies whether movies use low or high res
|
||||
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -239,9 +239,11 @@ static const mle *compare_mission_by_pathname(const mission_entry_predicate miss
|
|||
|
||||
}
|
||||
|
||||
Mission_ptr Current_mission; // currently loaded mission
|
||||
|
||||
}
|
||||
|
||||
Mission_ptr Current_mission; // currently loaded mission
|
||||
namespace {
|
||||
|
||||
static bool null_or_space(char c)
|
||||
{
|
||||
|
@ -552,8 +554,13 @@ static bool ml_sort_func(const mle &e0,const mle &e1)
|
|||
return d_stricmp(e0.mission_name,e1.mission_name) < 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//returns 1 if file read ok, else 0
|
||||
namespace dsx {
|
||||
|
||||
namespace {
|
||||
|
||||
static int read_mission_file(mission_list_type &mission_list, mission_candidate_search_path &pathname)
|
||||
{
|
||||
if (const auto mfile = PHYSFSX_openReadBuffered(pathname.data()))
|
||||
|
@ -621,9 +628,7 @@ static int read_mission_file(mission_list_type &mission_list, mission_candidate_
|
|||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace dsx {
|
||||
static void add_d1_builtin_mission_to_list(mission_list_type &mission_list)
|
||||
{
|
||||
int size;
|
||||
|
@ -667,7 +672,6 @@ static void add_d1_builtin_mission_to_list(mission_list_type &mission_list)
|
|||
mission->builtin_hogsize = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
template <std::size_t N1, std::size_t N2>
|
||||
|
@ -716,8 +720,6 @@ static void add_builtin_mission_to_list(mission_list_type &mission_list, d_fname
|
|||
}
|
||||
#endif
|
||||
|
||||
namespace dsx {
|
||||
|
||||
static void add_missions_to_list(mission_list_type &mission_list, mission_candidate_search_path &path, const mission_candidate_search_path::iterator rel_path, const mission_filter_mode mission_filter)
|
||||
{
|
||||
/* rel_path must point within the array `path`.
|
||||
|
@ -798,8 +800,13 @@ static void add_missions_to_list(mission_list_type &mission_list, mission_candid
|
|||
DXX_POISON_MEMORY(std::next(rel_path), path.end(), 0xcc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/* move <mission_name> to <place> on mission list, increment <place> */
|
||||
static void promote (mission_list_type &mission_list, const char *const name, std::size_t &top_place)
|
||||
{
|
||||
|
@ -813,6 +820,8 @@ static void promote (mission_list_type &mission_list, const char *const name, st
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Mission::~Mission()
|
||||
{
|
||||
// May become more complex with the editor
|
||||
|
@ -824,13 +833,13 @@ Mission::~Mission()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//fills in the global list of missions. Returns the number of missions
|
||||
//in the list. If anarchy_mode is set, then also add anarchy-only missions.
|
||||
|
||||
namespace dsx {
|
||||
|
||||
namespace {
|
||||
|
||||
static mission_list_type build_mission_list(const mission_filter_mode mission_filter)
|
||||
{
|
||||
//now search for levels on disk
|
||||
|
@ -872,6 +881,8 @@ static mission_list_type build_mission_list(const mission_filter_mode mission_fi
|
|||
return mission_list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
//values for built-in mission
|
||||
|
||||
|
@ -921,6 +932,8 @@ int load_mission_ham()
|
|||
#endif
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
#define tex ".tex"
|
||||
static void set_briefing_filename(d_fname &f, const char *const v, std::size_t d)
|
||||
{
|
||||
|
@ -955,18 +968,19 @@ static void record_briefing(d_fname &f, std::array<char, PATH_MAX> &buf)
|
|||
}
|
||||
#undef tex
|
||||
|
||||
}
|
||||
|
||||
//loads the specfied mission from the mission list.
|
||||
//build_mission_list() must have been called.
|
||||
//Returns true if mission loaded ok, else false.
|
||||
namespace dsx {
|
||||
|
||||
namespace {
|
||||
|
||||
static const char *load_mission(const mle *const mission)
|
||||
{
|
||||
char *v;
|
||||
|
||||
#if defined(DXX_BUILD_DESCENT_II)
|
||||
close_extra_robot_movie();
|
||||
#endif
|
||||
Current_mission = std::make_unique<Mission>(static_cast<const Mission_path &>(*mission));
|
||||
Current_mission->builtin_hogsize = mission->builtin_hogsize;
|
||||
Current_mission->mission_name.copy_if(mission->mission_name);
|
||||
|
@ -1192,11 +1206,13 @@ static const char *load_mission(const mle *const mission)
|
|||
free_polygon_models(LevelSharedPolygonModelState);
|
||||
|
||||
if (load_mission_ham())
|
||||
init_extra_robot_movie(&*Current_mission->filename);
|
||||
Current_mission->extra_robot_movie = init_extra_robot_movie(&*Current_mission->filename);
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//loads the named mission if exists.
|
||||
//Returns nullptr if mission loaded ok, else error string.
|
||||
const char *load_mission_by_name (const mission_entry_predicate mission_name, const mission_name_type name_match_mode)
|
||||
|
@ -1424,6 +1440,8 @@ window_event_result mission_menu::callback_handler(const d_event &event, window_
|
|||
return window_event_result::ignored;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using mission_menu_create_state_ptr = std::unique_ptr<mission_menu_create_state>;
|
||||
|
||||
static mission_menu_create_state_ptr prepare_mission_menu_state(const mission_list_type &mission_list, const char *const LastMission, const std::size_t extra_strings)
|
||||
|
@ -1457,6 +1475,8 @@ static mission_menu_create_state_ptr prepare_mission_menu_state(const mission_li
|
|||
return p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace dsx {
|
||||
|
||||
int select_mission(const mission_filter_mode mission_filter, const menu_title message, window_event_result (*when_selected)(void))
|
||||
|
|
Loading…
Reference in a new issue