diff --git a/source/exhumed/src/2d.cpp b/source/exhumed/src/2d.cpp index 9acd38072..e66fe0e8e 100644 --- a/source/exhumed/src/2d.cpp +++ b/source/exhumed/src/2d.cpp @@ -879,5 +879,193 @@ public: RunScreenJob(&job, 1, mycompletion); } +//--------------------------------------------------------------------------- +// +// text overlay +// +//--------------------------------------------------------------------------- + +void TextOverlay::Start(int starttime) +{ + lastclock = starttime; +} + +void TextOverlay::ComputeCinemaText(int nLine) +{ + linecount = 0; + + while (1) + { + if (!strcmp(gString[linecount + nLine], "END")) { + break; + } + + int nWidth = SmallFont->StringWidth(gString[linecount + nLine]); + nLeft[linecount] = 160 - nWidth / 2; + + linecount++; + } + + nCrawlY = 199; + nHeight = linecount * 10; +} + +void TextOverlay::ReadyCinemaText(uint16_t nVal) +{ + line = FindGString("CINEMAS"); + if (line < 0) { + return; + } + + while (nVal) + { + while (strcmp(gString[line], "END")) { + line++; + } + + line++; + nVal--; + } + + ComputeCinemaText(line); +} + +void TextOverlay::DisplayText() +{ + if (nHeight + nCrawlY > 0) + { + double y = nCrawlY; + int i = 0; + + while (i < linecount && y <= 199) + { + if (y >= -10) { + DrawText(twod, SmallFont, CR_UNDEFINED, nLeft[i], y, gString[line + i], DTA_FullscreenScale, FSMode_ScaleToFit43, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, TAG_DONE); + } + + i++; + y += 10; + } + } +} + +bool TextOverlay::AdvanceCinemaText(int totalclock) +{ + if (nHeight + nCrawlY > 0 || CDplaying()) + { + nCrawlY-= (totalclock - lastclock) / 15.; // do proper interpolation. + lastclock = totalclock; + return true; + } + + return false; +} + + + //--------------------------------------------------------------------------- +// +// cinema +// +//--------------------------------------------------------------------------- + +static const char * const cinpalfname[] = { + "3454.pal", + "3452.pal", + "3449.pal", + "3445.pal", + "set.pal", + "3448.pal", + "3446.pal", + "hsc1.pal", + "2972.pal", + "2973.pal", + "2974.pal", + "2975.pal", + "2976.pal", + "heli.pal", + "2978.pal", + "terror.pal" +}; + +extern short nCinemaSeen[30]; + +void uploadCinemaPalettes() +{ + for (int i = 0; i < countof(cinpalfname); i++) + { + uint8_t palette[768] = {}; + auto hFile = fileSystem.OpenFileReader(cinpalfname[i]); + if (hFile.isOpen()) + hFile.Read(palette, 768); + for (auto& c : palette) + c <<= 2; + paletteSetColorTable(ANIMPAL+i, palette, false, true); + } +} + +//--------------------------------------------------------------------------- +// +// cinema +// +//--------------------------------------------------------------------------- + +class DCinema : public DScreenJob +{ + TextOverlay text; + short cinematile; + int currentCinemaPalette; + int edx; + +public: + DCinema(int nVal) : DScreenJob(fadein|fadeout) + { + static const short cinematiles[] = { 3454, 3452, 3449, 3445, 3451, 3448, 3446}; + static const int8_t bxvals[] = { 4, 0, 2, 7, 3, 8, 6 }; + static const int8_t dxvals[] = { 4, -1, 2, -1, 3, 8, 6 }; + + if (nVal < 1 || nVal >7) return; + cinematile = cinematiles[nVal-1]; + currentCinemaPalette = nVal; + edx = dxvals[nVal - 1]; + text.Start(0); + text.ReadyCinemaText(bxvals[nVal - 1]); + } + + int Frame(uint64_t clock, bool skiprequest) override + { + + if (clock == 0) + { + StopAllSounds(); + if (edx != -1) + { + playCDtrack(edx + 2, false); + } + } + + twod->ClearScreen(); + DrawTexture(twod, tileGetTexture(cinematile), 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, TRANSLATION(Translation_BasePalettes, currentCinemaPalette), TAG_DONE); + + text.DisplayText(); + auto cont = text.AdvanceCinemaText(clock * 129 / 1'000'000'000); + int ret = skiprequest ? -1 : cont ? 1 : 0; + + // quit the game if we've finished level 4 and displayed the advert text + if (ISDEMOVER && currentCinemaPalette == 3 && ret != 1) + { + ExitGame(); + } + return ret; + } +}; + +// temporary. +void RunCinemaScene(int num) +{ + JobDesc job = { Create(num) }; + RunScreenJob(&job, 1, [](bool) { gamestate = GS_LEVEL; }); + SyncScreenJob(); +} + END_PS_NS diff --git a/source/exhumed/src/exhumed.cpp b/source/exhumed/src/exhumed.cpp index ea9d164c2..370825ecc 100644 --- a/source/exhumed/src/exhumed.cpp +++ b/source/exhumed/src/exhumed.cpp @@ -2059,7 +2059,6 @@ void DoGameOverScene() NoClip(); overwritesprite(0, 0, kTile3591, 0, 2, kPalNormal, 16); videoNextPage(); - CinemaFadeIn(); PlayGameOverSound(); //WaitAnyKey(3); FadeOut(0); diff --git a/source/exhumed/src/exhumed.h b/source/exhumed/src/exhumed.h index 7d8265702..3544d46fb 100644 --- a/source/exhumed/src/exhumed.h +++ b/source/exhumed/src/exhumed.h @@ -261,6 +261,26 @@ enum { kPalBrite2 }; + +class TextOverlay +{ + double nCrawlY; + short nLeft[50]; + int nHeight; + int linecount; + int line; + int lastclock; + +public: + + void Start(int starttime); + void ComputeCinemaText(int nLine); + void ReadyCinemaText(uint16_t nVal); + void DisplayText(); + bool AdvanceCinemaText(int totalclock); +}; + + extern char g_modDir[BMAX_PATH]; void G_LoadGroupsInDir(const char* dirname); diff --git a/source/exhumed/src/menu.cpp b/source/exhumed/src/menu.cpp index e6abc7ab0..001ab42d3 100644 --- a/source/exhumed/src/menu.cpp +++ b/source/exhumed/src/menu.cpp @@ -58,9 +58,6 @@ short nCinemaSeen[30]; uint8_t energytile[66 * 66] = {0}; -short nLeft[50] = {0}; -int line; - short SavePosition = -1; uint8_t *cur; @@ -87,6 +84,8 @@ enum { kMenuMaxItems }; +void RunCinemaScene(int num); + void ClearCinemaSeen() { @@ -382,270 +381,10 @@ const char *cinpalfname[kMaxCinemaPals] = { "terror.pal" }; -int linecount; -int nextclock; -short nHeight; -short nCrawlY; -short cinematile; -int currentCinemaPalette; - - -void uploadCinemaPalettes() -{ - for (int i = 0; i < countof(cinpalfname); i++) - { - uint8_t palette[768] = {}; - auto hFile = fileSystem.OpenFileReader(cinpalfname[i]); - if (hFile.isOpen()) - hFile.Read(palette, 768); - for (auto& c : palette) - c <<= 2; - paletteSetColorTable(ANIMPAL+i, palette, false, true); - } -} - void CinemaFadeIn() { } -void ComputeCinemaText(int nLine) -{ - linecount = 0; - - while (1) - { - if (!strcmp(gString[linecount + nLine], "END")) { - break; - } - - int nWidth = SmallFont->StringWidth(gString[linecount + nLine]); - nLeft[linecount] = 160 - nWidth / 2; - - linecount++; - } - - nCrawlY = 199; - nHeight = linecount * 10; - - inputState.ClearAllInput(); -} - -void ReadyCinemaText(uint16_t nVal) -{ - line = FindGString("CINEMAS"); - if (line < 0) { - return; - } - - while (nVal) - { - while (strcmp(gString[line], "END")) { - line++; - } - - line++; - nVal--; - } - - ComputeCinemaText(line); -} - -bool AdvanceCinemaText() -{ - bool bDoText = nHeight + nCrawlY > 0; - - if (bDoText || CDplaying()) - { - nextclock = (int)totalclock + 15; // NOTE: Value was 14 in original code but seems a touch too fast now - - if (bDoText) - { - short y = nCrawlY; - int i = 0; - - while (i < linecount && y <= 199) - { - if (y >= -10) { - DrawText(twod, SmallFont, CR_UNDEFINED, nLeft[i], y, gString[line + i], DTA_FullscreenScale, FSMode_ScaleToFit43, DTA_VirtualWidth, 320, DTA_VirtualHeight, 200, TAG_DONE); - } - - i++; - y += 10; - } - - nCrawlY--; - } - - while (1) - { - HandleAsync(); - - if (inputState.CheckAllInput()) - { - break; - } - - if (nextclock <= (int)totalclock) { - return true; - } - } - } - - return false; -} - -void DoCinemaText(short nVal) -{ - ReadyCinemaText(nVal); - - bool bContinue = true; - - while (bContinue) - { - overwritesprite(0, 0, cinematile, 0, 2, kPalNormal, currentCinemaPalette); - - bContinue = AdvanceCinemaText(); - - WaitVBL(); - videoNextPage(); - } -} - -void GoToTheCinema(int nVal) -{ - switch (nVal - 1) - { - default: - return; - - case 0: - { - cinematile = 3454; - break; - } - - case 1: - { - cinematile = 3452; - break; - } - - case 2: - { - cinematile = 3449; - break; - } - - case 3: - { - cinematile = 3445; - break; - } - - case 4: - { - cinematile = 3451; - break; - } - - case 5: - { - cinematile = 3448; - break; - } - - case 6: - { - cinematile = 3446; - break; - } - } - currentCinemaPalette = nVal; - - FadeOut(false); - StopAllSounds(); - NoClip(); - - overwritesprite(0, 0, kMovieTile, 100, 2, kPalNormal, currentCinemaPalette); - videoNextPage(); - -// int386(16, (const union REGS *)&val, (union REGS *)&val) - - overwritesprite(0, 0, cinematile, 0, 2, kPalNormal, currentCinemaPalette); - videoNextPage(); - - CinemaFadeIn(); - inputState.ClearAllInput(); - - int ebx = -1; - int edx = -1; - - switch (nVal - 1) - { - default: - //WaitAnyKey(10); - break; - - case 0: - ebx = 4; - edx = ebx; - break; - - case 1: - ebx = 0; - break; - - case 2: - ebx = 2; - edx = ebx; - break; - - case 3: - ebx = 7; - break; - - case 4: - ebx = 3; - edx = ebx; - break; - - case 5: - ebx = 8; - edx = ebx; - break; - - case 6: - ebx = 6; - edx = ebx; - break; - } - - if (ebx != -1) - { - if (edx != -1) - { - if (CDplaying()) { - fadecdaudio(); - } - - playCDtrack(edx + 2, false); - } - - DoCinemaText(ebx); - } - - FadeOut(true); - - overwritesprite(0, 0, kMovieTile, 100, 2, kPalNormal, currentCinemaPalette); - videoNextPage(); - - GrabPalette(); - - // quit the game if we've finished level 4 and displayed the advert text - if (ISDEMOVER && nVal == 3) { - ExitGame(); - } -} short nBeforeScene[] = { 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -665,7 +404,7 @@ void CheckBeforeScene(int nLevel) { if (!nCinemaSeen[nScene]) { - GoToTheCinema(nScene); + RunCinemaScene(nScene); nCinemaSeen[nScene] = 1; } } @@ -703,7 +442,7 @@ void DoAfterCinemaScene(int nLevel) short nAfterScene[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 7, 0, 0, 0, 0, 6 }; if (nAfterScene[nLevel]) { - GoToTheCinema(nAfterScene[nLevel]); + RunCinemaScene(nAfterScene[nLevel]); } } @@ -718,7 +457,7 @@ void DoFailedFinalScene() playCDtrack(9, false); FadeToWhite(); - GoToTheCinema(4); + RunCinemaScene(4); } int FindGString(const char *str) diff --git a/source/exhumed/src/menu.h b/source/exhumed/src/menu.h index e066818af..25e990818 100644 --- a/source/exhumed/src/menu.h +++ b/source/exhumed/src/menu.h @@ -62,9 +62,6 @@ void DoEnergyTile(); void CinemaFadeIn(); -void ReadyCinemaText(uint16_t nVal); -bool AdvanceCinemaText(); - void DoFailedFinalScene(); void DoLastLevelCinema(); diff --git a/source/exhumed/src/view.cpp b/source/exhumed/src/view.cpp index 05a24ad00..dae89d13d 100644 --- a/source/exhumed/src/view.cpp +++ b/source/exhumed/src/view.cpp @@ -240,6 +240,8 @@ static inline int interpolate16(int a, int b, int smooth) return a + mulscale16(b - a, smooth); } +static TextOverlay subtitleOverlay; + void DrawView(int smoothRatio, bool sceneonly) { int playerX; @@ -435,15 +437,16 @@ void DrawView(int smoothRatio, bool sceneonly) if (bSubTitles) { + subtitleOverlay.Start(totalclock); if (levelnum == 1) - ReadyCinemaText(1); + subtitleOverlay.ReadyCinemaText(1); else - ReadyCinemaText(5); + subtitleOverlay.ReadyCinemaText(5); } } - else + else if (nHeadStage == 6) { - if ((bSubTitles && !AdvanceCinemaText()) || inputState.CheckAllInput()) + if ((bSubTitles && !subtitleOverlay.AdvanceCinemaText(totalclock)) || inputState.CheckAllInput()) { inputState.ClearAllInput(); levelnew = levelnum + 1;