mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-16 14:50:17 +00:00
ULTIMA8: Add Crusader subtitle support
This commit is contained in:
parent
5b5f134be7
commit
72e8f4de0b
@ -124,5 +124,9 @@ void AVIPlayer::run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AVIPlayer::getFrameNo() const {
|
||||||
|
return _decoder->getCurFrame();
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Ultima8
|
} // End of namespace Ultima8
|
||||||
} // End of namespace Ultima
|
} // End of namespace Ultima
|
||||||
|
@ -53,6 +53,8 @@ public:
|
|||||||
return _playing;
|
return _playing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getFrameNo() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool _playing;
|
bool _playing;
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "ultima/ultima8/world/get_object.h"
|
#include "ultima/ultima8/world/get_object.h"
|
||||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||||
#include "ultima/ultima8/gumps/cru_status_gump.h"
|
#include "ultima/ultima8/gumps/cru_status_gump.h"
|
||||||
|
#include "ultima/ultima8/gumps/widgets/text_widget.h"
|
||||||
|
|
||||||
#include "ultima/ultima8/filesys/file_system.h"
|
#include "ultima/ultima8/filesys/file_system.h"
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ MovieGump::MovieGump() : ModalGump(), _player(nullptr) {
|
|||||||
MovieGump::MovieGump(int width, int height, Common::SeekableReadStream *rs,
|
MovieGump::MovieGump(int width, int height, Common::SeekableReadStream *rs,
|
||||||
bool introMusicHack, bool noScale, const byte *overridePal,
|
bool introMusicHack, bool noScale, const byte *overridePal,
|
||||||
uint32 flags, int32 layer)
|
uint32 flags, int32 layer)
|
||||||
: ModalGump(50, 50, width, height, 0, flags, layer) {
|
: ModalGump(50, 50, width, height, 0, flags, layer), _subtitleWidget(0) {
|
||||||
uint32 stream_id = rs->readUint32BE();
|
uint32 stream_id = rs->readUint32BE();
|
||||||
rs->seek(-4, SEEK_CUR);
|
rs->seek(-4, SEEK_CUR);
|
||||||
if (stream_id == 0x52494646) {// 'RIFF' - crusader AVIs
|
if (stream_id == 0x52494646) {// 'RIFF' - crusader AVIs
|
||||||
@ -93,6 +94,24 @@ void MovieGump::run() {
|
|||||||
ModalGump::run();
|
ModalGump::run();
|
||||||
|
|
||||||
_player->run();
|
_player->run();
|
||||||
|
|
||||||
|
AVIPlayer *aviplayer = dynamic_cast<AVIPlayer *>(_player);
|
||||||
|
if (aviplayer) {
|
||||||
|
const int frameno = aviplayer->getFrameNo();
|
||||||
|
if (_subtitles.contains(frameno)) {
|
||||||
|
TextWidget *subtitle = dynamic_cast<TextWidget *>(getGump(_subtitleWidget));
|
||||||
|
if (subtitle)
|
||||||
|
subtitle->Close();
|
||||||
|
// Create a new TextWidget
|
||||||
|
TextWidget *widget = new TextWidget(0, 0, _subtitles[frameno], true, 4, 640, 10);
|
||||||
|
widget->InitGump(this);
|
||||||
|
widget->setRelativePosition(BOTTOM_CENTER, 0, -10);
|
||||||
|
// Subtitles should be white.
|
||||||
|
widget->setBlendColour(0xffffffff);
|
||||||
|
_subtitleWidget = widget->getObjId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!_player->isPlaying()) {
|
if (!_player->isPlaying()) {
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
@ -137,6 +156,36 @@ ProcId MovieGump::U8MovieViewer(Common::SeekableReadStream *rs, bool fade, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MovieGump::loadSubtitles(Common::SeekableReadStream *rs) {
|
||||||
|
const uint32 id = rs->readUint32BE();
|
||||||
|
rs->seek(0);
|
||||||
|
|
||||||
|
if (id == 0x464F524D) { // 'FORM'
|
||||||
|
loadIFFSubs(rs);
|
||||||
|
} else {
|
||||||
|
loadTXTSubs(rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovieGump::loadTXTSubs(Common::SeekableReadStream *rs) {
|
||||||
|
int frameno = 0;
|
||||||
|
Common::String subtitles;
|
||||||
|
while (!rs->eos()) {
|
||||||
|
Common::String line = rs->readLine();
|
||||||
|
if (line.hasPrefix("@frame ")) {
|
||||||
|
frameno = atoi(line.c_str() + 7);
|
||||||
|
subtitles += '\n';
|
||||||
|
} else {
|
||||||
|
_subtitles[frameno] = line;
|
||||||
|
subtitles += line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovieGump::loadIFFSubs(Common::SeekableReadStream *rs) {
|
||||||
|
warning("TODO: load IFF subtitle data");
|
||||||
|
}
|
||||||
|
|
||||||
bool MovieGump::loadData(Common::ReadStream *rs) {
|
bool MovieGump::loadData(Common::ReadStream *rs) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -168,22 +217,36 @@ static Std::string _fixCrusaderMovieName(const Std::string &s) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Common::SeekableReadStream *_tryLoadCruMovie(const Std::string &filename) {
|
static Common::SeekableReadStream *_tryLoadCruMovieFile(const Std::string &filename, const char *extn) {
|
||||||
const Std::string path = Std::string::format("flics/%s.avi", filename.c_str());
|
const Std::string path = Std::string::format("flics/%s.%s", filename.c_str(), extn);
|
||||||
FileSystem *filesys = FileSystem::get_instance();
|
FileSystem *filesys = FileSystem::get_instance();
|
||||||
Common::SeekableReadStream *rs = filesys->ReadFile(path);
|
Common::SeekableReadStream *rs = filesys->ReadFile(path);
|
||||||
if (!rs) {
|
if (!rs) {
|
||||||
// Try with a "0" in the name
|
// Try with a "0" in the name
|
||||||
const Std::string adjustedfn = Std::string::format("flics/0%s.avi", filename.c_str());
|
const Std::string adjustedfn = Std::string::format("flics/0%s.%s", filename.c_str(), extn);
|
||||||
rs = filesys->ReadFile(adjustedfn);
|
rs = filesys->ReadFile(adjustedfn);
|
||||||
if (!rs) {
|
if (!rs)
|
||||||
warning("movie %s not found", filename.c_str());
|
return nullptr;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return rs;
|
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);
|
||||||
@ -201,11 +264,12 @@ 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 = _tryLoadCruMovie(name);
|
Common::SeekableReadStream *rs = _tryLoadCruAVI(name);
|
||||||
if (rs) {
|
if (rs) {
|
||||||
Gump *gump = new MovieGump(x, y, rs, false, false, pal->_palette);
|
MovieGump *gump = new MovieGump(x, y, rs, false, false, pal->_palette);
|
||||||
gump->InitGump(nullptr, true);
|
gump->InitGump(nullptr, true);
|
||||||
gump->setRelativePosition(CENTER);
|
gump->setRelativePosition(CENTER);
|
||||||
|
gump->loadSubtitles(_tryLoadCruSubtitle(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,11 +283,12 @@ uint32 MovieGump::I_playMovieCutscene(const uint8 *args, unsigned int /*argsize*
|
|||||||
ARG_UINT16(y);
|
ARG_UINT16(y);
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
Common::SeekableReadStream *rs = _tryLoadCruMovie(name);
|
Common::SeekableReadStream *rs = _tryLoadCruAVI(name);
|
||||||
if (rs) {
|
if (rs) {
|
||||||
Gump *gump = new MovieGump(x * 3, y * 3, rs, false, false);
|
MovieGump *gump = new MovieGump(x * 3, y * 3, rs, false, false);
|
||||||
gump->InitGump(nullptr, true);
|
gump->InitGump(nullptr, true);
|
||||||
gump->setRelativePosition(CENTER);
|
gump->setRelativePosition(CENTER);
|
||||||
|
gump->loadSubtitles(_tryLoadCruSubtitle(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,11 +304,12 @@ 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 = _tryLoadCruMovie(name);
|
Common::SeekableReadStream *rs = _tryLoadCruAVI(name);
|
||||||
if (rs) {
|
if (rs) {
|
||||||
Gump *gump = new MovieGump(x * 3, y * 3, rs, false, false);
|
MovieGump *gump = new MovieGump(x * 3, y * 3, rs, false, false);
|
||||||
gump->InitGump(nullptr, true);
|
gump->InitGump(nullptr, true);
|
||||||
gump->setRelativePosition(CENTER);
|
gump->setRelativePosition(CENTER);
|
||||||
|
gump->loadSubtitles(_tryLoadCruSubtitle(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,11 +322,12 @@ 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 = _tryLoadCruMovie(name);
|
Common::SeekableReadStream *rs = _tryLoadCruAVI(name);
|
||||||
if (rs) {
|
if (rs) {
|
||||||
Gump *gump = new MovieGump(640, 480, rs, false, false);
|
MovieGump *gump = new MovieGump(640, 480, rs, false, false);
|
||||||
gump->InitGump(nullptr, true);
|
gump->InitGump(nullptr, true);
|
||||||
gump->setRelativePosition(CENTER);
|
gump->setRelativePosition(CENTER);
|
||||||
|
gump->loadSubtitles(_tryLoadCruSubtitle(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -67,6 +67,19 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
MoviePlayer *_player;
|
MoviePlayer *_player;
|
||||||
|
|
||||||
|
// Load subtitles with format detection
|
||||||
|
void loadSubtitles(Common::SeekableReadStream *rs);
|
||||||
|
|
||||||
|
// Load subtitles from a txt file (No Remorse format)
|
||||||
|
void loadTXTSubs(Common::SeekableReadStream *rs);
|
||||||
|
|
||||||
|
// Load subtitles from a iff file (No Regret format)
|
||||||
|
void loadIFFSubs(Common::SeekableReadStream *rs);
|
||||||
|
|
||||||
|
Common::HashMap<int, Common::String> _subtitles;
|
||||||
|
uint16 _subtitleWidget;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Ultima8
|
} // End of namespace Ultima8
|
||||||
|
Loading…
Reference in New Issue
Block a user