diff --git a/src/game.h b/src/game.h index 86a06766..d7e59bbc 100644 --- a/src/game.h +++ b/src/game.h @@ -26,7 +26,7 @@ namespace Game { if (level->level.isTitle() && id != TR::LVL_MAX) playVideo = false; - level->init(playVideo); + level->init(id == TR::LVL_MAX, playVideo); UI::game = level; #if !defined(_OS_PSP) && !defined(_OS_CLOVER) diff --git a/src/gameflow.h b/src/gameflow.h index 734c428b..c8b9d577 100644 --- a/src/gameflow.h +++ b/src/gameflow.h @@ -868,6 +868,31 @@ namespace TR { } } + const char* getGameLogo(Version version) { + if (version & VER_TR1) { + CHECK_FILE("FMV/CORELOGO.FMV"); + CHECK_FILE("FMV/CORE.RPL"); + CHECK_FILE("video/1/CORELOGO.FMV"); + return "video/1/CORE.RPL"; + } + + if (version & VER_TR2) { + CHECK_FILE("FMV/LOGO.FMV"); + CHECK_FILE("FMV/LOGO.RPL"); + CHECK_FILE("video/2/LOGO.FMV"); + return "video/2/LOGO.RPL"; + } + + if (version & VER_TR3) { + CHECK_FILE("FMV/LOGO.FMV"); + CHECK_FILE("fmv/logo.rpl"); + CHECK_FILE("video/3/LOGO.FMV"); + return "video/3/logo.rpl"; + } + + return NULL; + } + const char* getGameVideo(LevelID id) { switch (id) { // TR1 diff --git a/src/inventory.h b/src/inventory.h index 469715aa..246a948b 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -33,7 +33,7 @@ struct OptionItem { uint32 icon; uint8 maxValue; bool bar; - + OptionItem(Type type = TYPE_EMPTY, int title = STR_NOT_IMPLEMENTED, intptr_t offset = 0, uint32 color = 0xFFFFFFFF, int icon = 0, uint8 maxValue = 0, bool bar = false) : type(type), title(StringID(title)), offset(offset), color(color), icon(icon), maxValue(maxValue), bar(bar) {} void setValue(uint8 value, Core::Settings *settings) const { @@ -214,6 +214,9 @@ struct Inventory { Texture *background[2]; Video *video; + bool playLogo; + bool playVideo; + bool active; bool chosen; float phaseRing, phasePage, phaseChoose, phaseSelect; @@ -478,6 +481,14 @@ struct Inventory { new Stream(TR::getGameScreen(inv->game->getLevel()->id), loadTitleBG, inv); } + static void loadLogo(Stream *stream, void *userData) { + Inventory *inv = (Inventory*)userData; + if (stream) + inv->video = new Video(stream); + else + inv->skipVideo(); + } + Inventory(IGame *game) : game(game), active(false), chosen(false), index(0), targetIndex(0), page(PAGE_OPTION), targetPage(PAGE_OPTION), itemsCount(0), playerIndex(0), changeTimer(0.0f), nextLevel(TR::LVL_MAX), lastKey(cMAX) { TR::LevelID id = game->getLevel()->id; @@ -545,10 +556,21 @@ struct Inventory { delete background[i]; } - void init(bool playVideo) { + void startVideo() { new Stream(playVideo ? TR::getGameVideo(game->getLevel()->id) : NULL, loadVideo, this); } + void init(bool playLogo, bool playVideo) { + this->playLogo = playLogo; + this->playVideo = playVideo; + + if (playLogo) { + new Stream(TR::getGameLogo(game->getLevel()->version), loadLogo, this); + return; + } + startVideo(); + } + bool isActive() { return active || phaseRing > 0.0f; } @@ -919,6 +941,16 @@ struct Inventory { void skipVideo() { delete video; video = NULL; + + if (playLogo) { + playLogo = false; + if (playVideo) { + startVideo(); + return; + } + } + playVideo = false; + game->playTrack(0); if (game->getLevel()->isTitle()) { titleTimer = 0.0f; @@ -928,10 +960,17 @@ struct Inventory { } void update() { - if (video && (Input::state[0][cInventory] || Input::state[0][cAction] || Input::state[0][cJump] || - Input::state[1][cInventory] || Input::state[1][cAction] || Input::state[1][cJump] || - Input::down[ikCtrl] || Input::down[ikEnter] || Input::down[ikAlt])) - skipVideo(); + if (titleTimer > 1.0f && ( + Input::state[0][cInventory] || Input::state[0][cAction] || Input::state[0][cJump] || + Input::state[1][cInventory] || Input::state[1][cAction] || Input::state[1][cJump] || + Input::down[ikCtrl] || Input::down[ikEnter] || Input::down[ikAlt])) + { + if (video) { + if (video->time > 0.5f) + skipVideo(); + } else if (titleTimer > 1.0f && titleTimer < 2.5f) + titleTimer = 1.0f; + } if (video) { video->update(); @@ -1555,14 +1594,14 @@ struct Inventory { Texture *tmp = background[0]; float sy = 1.0f; - if (game->getLevel()->version & TR::VER_TR1) + if ((game->getLevel()->version & TR::VER_TR1) && !playLogo) sy = 1.2f; background[0] = video->frameTex[0]; renderTitleBG(1.0f, sy, 255); background[0] = video->frameTex[1]; - renderTitleBG(1.0f, sy, clamp(int((video->time / video->step) * 255), 0, 255)); + renderTitleBG(1.0f, sy, clamp(int((video->stepTimer / video->step) * 255), 0, 255)); background[0] = tmp; diff --git a/src/level.h b/src/level.h index 9ad34868..66907fb2 100644 --- a/src/level.h +++ b/src/level.h @@ -759,8 +759,8 @@ struct Level : IGame { Sound::stopAll(); } - void init(bool playVideo) { - inventory->init(playVideo); + void init(bool playLogo, bool playVideo) { + inventory->init(playLogo, playVideo); } void addPlayer(int index) { diff --git a/src/video.h b/src/video.h index c32a0236..14061be7 100644 --- a/src/video.h +++ b/src/video.h @@ -1099,14 +1099,27 @@ struct Video { int i = 0; while (i < count) { if (xa->pos >= COUNT(xa->buffer)) { - if (aFrames[curAudioFrame].size == 0) + if (aFrames[curAudioFrame].size == 0) { curAudioFrame = (curAudioFrame + 1) % AUDIO_MAX_FRAMES; - if (aFrames[curAudioFrame].size == 0) { - stream->setPos(oldPos); - nextFrame(); - oldPos = stream->pos; - curAudioFrame = aFrameIndex; + if (aFrames[curAudioFrame].size == 0) { + // check next 3 frames for audio frame + stream->setPos(oldPos); + for (int j = 0; j < 3; j++) { + nextFrame(); + curAudioFrame = aFrameIndex; + if (curAudioFrame != -1 && aFrames[curAudioFrame].size != 0) + break; + } + + if (curAudioFrame == -1) { // no audio frames found! + ASSERT(false); + memset(frames, 0, count * sizeof(Sound::Frame)); + return count; + } + + oldPos = stream->pos; + } } } stream->setPos(aFrames[curAudioFrame].pos); @@ -1126,12 +1139,12 @@ struct Video { Decoder *decoder; Texture *frameTex[2]; Color32 *frameData; - float time, step; + float step, stepTimer, time; bool isPlaying; bool needUpdate; Sound::Sample *sample; - Video(Stream *stream) : decoder(NULL), time(0.0f), isPlaying(false) { + Video(Stream *stream) : decoder(NULL), time(0.0f), stepTimer(0.0f), isPlaying(false) { frameTex[0] = frameTex[1] = NULL; if (!stream) return; @@ -1154,7 +1167,8 @@ struct Video { sample = Sound::play(decoder); step = 1.0f / decoder->fps; - time = step; + stepTimer = step; + time = 0.0f; isPlaying = true; } @@ -1171,10 +1185,11 @@ struct Video { void update() { if (!isPlaying) return; - time += Core::deltaTime; - if (time < step) + stepTimer += Core::deltaTime; + if (stepTimer < step) return; - time -= step; + stepTimer -= step; + time += step; #ifdef VIDEO_TEST int t = Core::getTime(); while (decoder->decodeVideo(frameData)) {}