ULTIMA8: Refactor so all Crusader movies get subtitles

Previously there was a bit of duplication, and Weasel and the intro movies
didn't get subtitles.  Cleaned up the code a bit and now all are treated
consistently.
This commit is contained in:
Matthew Duggan 2021-05-08 13:58:54 +09:00
parent 531ed6865b
commit f5c4374888
4 changed files with 80 additions and 96 deletions

View File

@ -28,6 +28,7 @@
#include "ultima/ultima8/filesys/file_system.h" #include "ultima/ultima8/filesys/file_system.h"
#include "ultima/ultima8/graphics/palette_manager.h" #include "ultima/ultima8/graphics/palette_manager.h"
#include "ultima/ultima8/gumps/movie_gump.h" #include "ultima/ultima8/gumps/movie_gump.h"
#include "ultima/ultima8/gumps/gump_notify_process.h"
#include "ultima/ultima8/kernel/object_manager.h" #include "ultima/ultima8/kernel/object_manager.h"
#include "ultima/ultima8/kernel/kernel.h" #include "ultima/ultima8/kernel/kernel.h"
#include "ultima/ultima8/world/world.h" #include "ultima/ultima8/world/world.h"
@ -149,15 +150,13 @@ bool RemorseGame::startInitialUsecode(int saveSlot) {
static ProcId playMovie(const char *movieID, bool fade, bool noScale) { static ProcId playMovie(const char *movieID, bool fade, bool noScale) {
const Std::string filename = Std::string::format("flics/%s.avi", movieID); MovieGump *gump = MovieGump::CruMovieViewer(movieID, 640, 480, nullptr, nullptr);
FileSystem *filesys = FileSystem::get_instance(); if (!gump) {
Common::SeekableReadStream *rs = filesys->ReadFile(filename); pout << "RemorseGame::playIntro: movie " << movieID << " not found." << Std::endl;
if (!rs) {
pout << "RemorseGame::playIntro: movie not found." << Std::endl;
return 0; return 0;
} }
// TODO: Add support for subtitles (.txt file). The format is very simple. gump->CreateNotifier();
return MovieGump::U8MovieViewer(rs, fade, false, noScale); return gump->GetNotifyProcess()->getPid();
} }
ProcId RemorseGame::playIntroMovie(bool fade) { ProcId RemorseGame::playIntroMovie(bool fade) {

View File

@ -40,6 +40,60 @@
namespace Ultima { namespace Ultima {
namespace Ultima8 { namespace Ultima8 {
static Std::string _fixCrusaderMovieName(const Std::string &s) {
/*
HACK! The game comes with movies MVA01.AVI etc, but the usecode mentions both
MVA01 and MVA1. We do a translation here. These are the strings we need to fix:
008E: 0D push string "mva1"
036D: 0D push string "mva3a"
04E3: 0D push string "mva4"
0656: 0D push string "mva5a"
07BD: 0D push string "mva6"
0944: 0D push string "mva7"
0A68: 0D push string "mva8"
0B52: 0D push string "mva9"
*/
if (s.size() == 4)
return Std::string::format("mva0%c", s[3]);
else if (s.equals("mva3a"))
return "mva03a";
else if (s.equals("mva5a"))
return "mva05a";
return s;
}
static Common::SeekableReadStream *_tryLoadCruMovieFile(const Std::string &filename, const char *extn) {
const Std::string path = Std::string::format("flics/%s.%s", filename.c_str(), extn);
FileSystem *filesys = FileSystem::get_instance();
Common::SeekableReadStream *rs = filesys->ReadFile(path);
if (!rs) {
// Try with a "0" in the name
const Std::string adjustedfn = Std::string::format("flics/0%s.%s", filename.c_str(), extn);
rs = filesys->ReadFile(adjustedfn);
if (!rs)
return nullptr;
}
return rs;
}
static Common::SeekableReadStream *_tryLoadCruAVI(const Std::string &filename) {
Common::SeekableReadStream *rs = _tryLoadCruMovieFile(filename, "avi");
if (!rs)
warning("movie %s not found", filename.c_str());
return rs;
}
// Convenience function that tries to open both TXT (No Remorse)
// and IFF (No Regret) subtitle formats.
static Common::SeekableReadStream *_tryLoadCruSubtitle(const Std::string &filename) {
Common::SeekableReadStream *txtfile = _tryLoadCruMovieFile(filename, "txt");
if (txtfile)
return txtfile;
return _tryLoadCruMovieFile(filename, "iff");
}
DEFINE_RUNTIME_CLASSTYPE_CODE(MovieGump) DEFINE_RUNTIME_CLASSTYPE_CODE(MovieGump)
MovieGump::MovieGump() : ModalGump(), _player(nullptr) { MovieGump::MovieGump() : ModalGump(), _player(nullptr) {
@ -134,7 +188,7 @@ bool MovieGump::OnKeyDown(int key, int mod) {
return true; return true;
} }
//static /*static*/
ProcId MovieGump::U8MovieViewer(Common::SeekableReadStream *rs, bool fade, bool introMusicHack, bool noScale) { ProcId MovieGump::U8MovieViewer(Common::SeekableReadStream *rs, bool fade, bool introMusicHack, bool noScale) {
ModalGump *gump; ModalGump *gump;
if (GAME_IS_U8) if (GAME_IS_U8)
@ -156,6 +210,18 @@ ProcId MovieGump::U8MovieViewer(Common::SeekableReadStream *rs, bool fade, bool
} }
} }
/*static*/ MovieGump *MovieGump::CruMovieViewer(const Std::string fname, int x, int y, const byte *pal, Gump *parent) {
Common::SeekableReadStream *rs = _tryLoadCruAVI(fname);
if (!rs)
return nullptr;
MovieGump *gump = new MovieGump(x, y, rs, false, false, pal);
gump->InitGump(parent, true);
gump->setRelativePosition(CENTER);
gump->loadSubtitles(_tryLoadCruSubtitle(fname));
return gump;
}
void MovieGump::loadSubtitles(Common::SeekableReadStream *rs) { void MovieGump::loadSubtitles(Common::SeekableReadStream *rs) {
if (!rs) if (!rs)
return; return;
@ -197,59 +263,6 @@ void MovieGump::saveData(Common::WriteStream *ws) {
} }
static Std::string _fixCrusaderMovieName(const Std::string &s) {
/*
HACK! The game comes with movies MVA01.AVI etc, but the usecode mentions both
MVA01 and MVA1. We do a translation here. These are the strings we need to fix:
008E: 0D push string "mva1"
036D: 0D push string "mva3a"
04E3: 0D push string "mva4"
0656: 0D push string "mva5a"
07BD: 0D push string "mva6"
0944: 0D push string "mva7"
0A68: 0D push string "mva8"
0B52: 0D push string "mva9"
*/
if (s.size() == 4)
return Std::string::format("mva0%c", s[3]);
else if (s.equals("mva3a"))
return "mva03a";
else if (s.equals("mva5a"))
return "mva05a";
return s;
}
static Common::SeekableReadStream *_tryLoadCruMovieFile(const Std::string &filename, const char *extn) {
const Std::string path = Std::string::format("flics/%s.%s", filename.c_str(), extn);
FileSystem *filesys = FileSystem::get_instance();
Common::SeekableReadStream *rs = filesys->ReadFile(path);
if (!rs) {
// Try with a "0" in the name
const Std::string adjustedfn = Std::string::format("flics/0%s.%s", filename.c_str(), extn);
rs = filesys->ReadFile(adjustedfn);
if (!rs)
return nullptr;
}
return rs;
}
static Common::SeekableReadStream *_tryLoadCruAVI(const Std::string &filename) {
Common::SeekableReadStream *rs = _tryLoadCruMovieFile(filename, "avi");
if (!rs)
warning("movie %s not found", filename.c_str());
return rs;
}
// Convenience function that tries to open both TXT (No Remorse)
// and IFF (No Regret) subtitle formats.
static Common::SeekableReadStream *_tryLoadCruSubtitle(const Std::string &filename) {
Common::SeekableReadStream *txtfile = _tryLoadCruMovieFile(filename, "txt");
if (txtfile)
return txtfile;
return _tryLoadCruMovieFile(filename, "iff");
}
uint32 MovieGump::I_playMovieOverlay(const uint8 *args, uint32 MovieGump::I_playMovieOverlay(const uint8 *args,
unsigned int /*argsize*/) { unsigned int /*argsize*/) {
ARG_ITEM_FROM_PTR(item); ARG_ITEM_FROM_PTR(item);
@ -267,13 +280,7 @@ uint32 MovieGump::I_playMovieOverlay(const uint8 *args,
const Palette *pal = palman->getPalette(PaletteManager::Pal_Game); const Palette *pal = palman->getPalette(PaletteManager::Pal_Game);
assert(pal); assert(pal);
Common::SeekableReadStream *rs = _tryLoadCruAVI(name); CruMovieViewer(name, x, y, pal->_palette, nullptr);
if (rs) {
MovieGump *gump = new MovieGump(x, y, rs, false, false, pal->_palette);
gump->InitGump(nullptr, true);
gump->setRelativePosition(CENTER);
gump->loadSubtitles(_tryLoadCruSubtitle(name));
}
} }
return 0; return 0;
@ -286,13 +293,7 @@ uint32 MovieGump::I_playMovieCutscene(const uint8 *args, unsigned int /*argsize*
ARG_UINT16(y); ARG_UINT16(y);
if (item) { if (item) {
Common::SeekableReadStream *rs = _tryLoadCruAVI(name); CruMovieViewer(name, x * 3, y * 3, nullptr, nullptr);
if (rs) {
MovieGump *gump = new MovieGump(x * 3, y * 3, rs, false, false);
gump->InitGump(nullptr, true);
gump->setRelativePosition(CENTER);
gump->loadSubtitles(_tryLoadCruSubtitle(name));
}
} }
return 0; return 0;
@ -312,13 +313,7 @@ uint32 MovieGump::I_playMovieCutsceneAlt(const uint8 *args, unsigned int /*argsi
warning("MovieGump::I_playMovieCutsceneAlt: TODO: This intrinsic should pause and fade the background to grey"); warning("MovieGump::I_playMovieCutsceneAlt: TODO: This intrinsic should pause and fade the background to grey");
if (item) { if (item) {
Common::SeekableReadStream *rs = _tryLoadCruAVI(name); CruMovieViewer(name, x * 3, y * 3, nullptr, nullptr);
if (rs) {
MovieGump *gump = new MovieGump(x * 3, y * 3, rs, false, false);
gump->InitGump(nullptr, true);
gump->setRelativePosition(CENTER);
gump->loadSubtitles(_tryLoadCruSubtitle(name));
}
} }
return 0; return 0;
@ -330,13 +325,7 @@ uint32 MovieGump::I_playMovieCutsceneRegret(const uint8 *args, unsigned int /*ar
warning("MovieGump::I_playMovieCutsceneRegret: TODO: use fade argument %d", fade); warning("MovieGump::I_playMovieCutsceneRegret: TODO: use fade argument %d", fade);
Common::SeekableReadStream *rs = _tryLoadCruAVI(name); CruMovieViewer(name, 640, 480, nullptr, nullptr);
if (rs) {
MovieGump *gump = new MovieGump(640, 480, rs, false, false);
gump->InitGump(nullptr, true);
gump->setRelativePosition(CENTER);
gump->loadSubtitles(_tryLoadCruSubtitle(name));
}
return 0; return 0;
} }

View File

@ -56,6 +56,7 @@ public:
bool OnKeyDown(int key, int mod) override; bool OnKeyDown(int key, int mod) override;
static ProcId U8MovieViewer(Common::SeekableReadStream *rs, bool fade, bool introMusicHack, bool noScale); static ProcId U8MovieViewer(Common::SeekableReadStream *rs, bool fade, bool introMusicHack, bool noScale);
static MovieGump *CruMovieViewer(const Std::string fname, int x, int y, const byte *pal, Gump *parent);
bool loadData(Common::ReadStream *rs); bool loadData(Common::ReadStream *rs);
void saveData(Common::WriteStream *ws) override; void saveData(Common::WriteStream *ws) override;

View File

@ -196,16 +196,11 @@ void WeaselGump::InitGump(Gump *newparent, bool take_focus) {
} }
Gump *WeaselGump::playMovie(const Std::string &filename) { Gump *WeaselGump::playMovie(const Std::string &filename) {
const Std::string path = Std::string::format("flics/%s.avi", filename.c_str()); MovieGump *gump = MovieGump::CruMovieViewer(filename, 600, 450, nullptr, this);
FileSystem *filesys = FileSystem::get_instance(); if (!gump) {
Common::SeekableReadStream *rs = filesys->ReadFile(path);
if (!rs) {
warning("Couldn't load flic %s", filename.c_str()); warning("Couldn't load flic %s", filename.c_str());
return nullptr; return nullptr;
} }
Gump *gump = new MovieGump(600, 450, rs, false, false);
gump->InitGump(this, true);
gump->setRelativePosition(CENTER);
gump->CreateNotifier(); gump->CreateNotifier();
return gump; return gump;
} }