diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp index a06afd3ef2..80abd9dc44 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -25,7 +25,6 @@ # include # include # include -# include # include # include # include diff --git a/src/openrct2-ui/windows/TitleExit.cpp b/src/openrct2-ui/windows/TitleExit.cpp index 0c56d4ab6e..8f08fe9280 100644 --- a/src/openrct2-ui/windows/TitleExit.cpp +++ b/src/openrct2-ui/windows/TitleExit.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -38,9 +37,6 @@ static Widget _titleExitWidgets[] = { void OnMouseUp(WidgetIndex widgetIndex) override { - if (gIntroState != IntroState::None) - return; - switch (widgetIndex) { case WIDX_EXIT: diff --git a/src/openrct2-ui/windows/TitleOptions.cpp b/src/openrct2-ui/windows/TitleOptions.cpp index 07a359e3e7..cbde63d877 100644 --- a/src/openrct2-ui/windows/TitleOptions.cpp +++ b/src/openrct2-ui/windows/TitleOptions.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index fe82237c51..ceabc0b150 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -19,7 +19,6 @@ #include "GameState.h" #include "GameStateSnapshots.h" #include "Input.h" -#include "Intro.h" #include "OpenRCT2.h" #include "ParkImporter.h" #include "PlatformEnvironment.h" @@ -67,6 +66,7 @@ #include "scenario/Scenario.h" #include "scenario/ScenarioRepository.h" #include "scenes/game/GameScene.h" +#include "scenes/intro/IntroScene.h" #include "scenes/title/TitleScene.h" #include "scenes/title/TitleSequenceManager.h" #include "scripting/HookEngine.h" @@ -124,6 +124,7 @@ namespace OpenRCT2 #endif // Scenes + std::unique_ptr _introScene; std::unique_ptr _titleScene; std::unique_ptr _gameScene; IScene* _activeScene = nullptr; @@ -174,6 +175,7 @@ namespace OpenRCT2 #ifndef DISABLE_NETWORK , _network(*this) #endif + , _introScene(std::make_unique(*this)) , _titleScene(std::make_unique(*this)) , _gameScene(std::make_unique(*this)) , _painter(std::make_unique(uiContext)) @@ -317,8 +319,7 @@ namespace OpenRCT2 IScene* GetIntroScene() override { - // TODO: Implement me. - return nullptr; + return _introScene.get(); } IScene* GetTitleScene() override @@ -917,7 +918,6 @@ namespace OpenRCT2 }); } - gIntroState = IntroState::None; if (gOpenRCT2Headless) { // NONE or OPEN are the only allowed actions for headless mode @@ -937,8 +937,7 @@ namespace OpenRCT2 switch (gOpenRCT2StartupAction) { case StartupAction::Intro: - gIntroState = IntroState::PublisherBegin; - SetActiveScene(GetTitleScene()); + SetActiveScene(GetIntroScene()); break; case StartupAction::Title: SetActiveScene(GetTitleScene()); diff --git a/src/openrct2/Intro.cpp b/src/openrct2/Intro.cpp deleted file mode 100644 index 3fb9106a88..0000000000 --- a/src/openrct2/Intro.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2024 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#include "Intro.h" - -#include "Context.h" -#include "audio/AudioChannel.h" -#include "audio/AudioMixer.h" -#include "audio/audio.h" -#include "drawing/Drawing.h" -#include "sprites.h" - -#include - -using namespace OpenRCT2::Audio; - -static constexpr PaletteIndex kBackgroundColourDark = PALETTE_INDEX_10; -static constexpr PaletteIndex kBackgroundColourLogo = PALETTE_INDEX_245; -static constexpr PaletteIndex kBorderColourPublisher = PALETTE_INDEX_129; - -constexpr int32_t PALETTE_G1_IDX_DEVELOPER = 23217; -constexpr int32_t PALETTE_G1_IDX_LOGO = 23224; - -IntroState gIntroState; - -// Used mainly for timing but also for Y coordinate and fading. -static int32_t _introStateCounter; - -static std::shared_ptr _soundChannel = nullptr; -static bool _chainLiftFinished; - -static void ScreenIntroProcessMouseInput(); -static void ScreenIntroProcessKeyboardInput(); -static void ScreenIntroSkipPart(); -static void ScreenIntroDrawLogo(DrawPixelInfo& dpi); - -// rct2: 0x0068E966 -void IntroUpdate() -{ - ScreenIntroProcessMouseInput(); - ScreenIntroProcessKeyboardInput(); - - switch (gIntroState) - { - case IntroState::Disclaimer1: - case IntroState::Disclaimer2: - // Originally used for the disclaimer text - gIntroState = IntroState::PublisherBegin; - [[fallthrough]]; - case IntroState::PublisherBegin: - LoadPalette(); - - // Set the Y for the Infogrames logo - _introStateCounter = -580; - - // Play the chain lift sound - _soundChannel = CreateAudioChannel(SoundId::LiftBM, true); - _chainLiftFinished = false; - gIntroState = IntroState::PublisherScroll; - break; - case IntroState::PublisherScroll: - // Move the Infogrames logo down - _introStateCounter += 5; - - // Check if logo is off the screen...ish - if (_introStateCounter > ContextGetHeight() - 120) - { - _introStateCounter = -116; - gIntroState = IntroState::DeveloperBegin; - } - - break; - case IntroState::DeveloperBegin: - // Set the Y for the Chris Sawyer logo - _introStateCounter = -116; - - gIntroState = IntroState::DeveloperScroll; - break; - case IntroState::DeveloperScroll: - _introStateCounter += 5; - - // Check if logo is almost scrolled to the bottom - if (!_chainLiftFinished && _introStateCounter >= ContextGetHeight() + 40 - 421) - { - _chainLiftFinished = true; - - // Stop the chain lift sound - if (_soundChannel != nullptr) - { - _soundChannel->Stop(); - _soundChannel = nullptr; - } - - // Play the track friction sound - _soundChannel = CreateAudioChannel(SoundId::TrackFrictionBM, true, kMixerVolumeMax, 0.25f, 0.75); - } - - // Check if logo is off the screen...ish - if (_introStateCounter >= ContextGetHeight() + 40) - { - // Stop the track friction sound - if (_soundChannel != nullptr) - { - _soundChannel->Stop(); - _soundChannel = nullptr; - } - - // Play long peep scream sound - _soundChannel = CreateAudioChannel(SoundId::Scream1); - - gIntroState = IntroState::LogoFadeIn; - _introStateCounter = 0; - } - break; - case IntroState::LogoFadeIn: - // Fade in, add 4 / 256 to fading - _introStateCounter += 0x400; - if (_introStateCounter > 0xFF00) - { - gIntroState = IntroState::LogoWait; - _introStateCounter = 0; - } - break; - case IntroState::LogoWait: - // Wait 80 game ticks - _introStateCounter++; - if (_introStateCounter >= 80) - { - // Set fading to 256 - _introStateCounter = 0xFF00; - - gIntroState = IntroState::LogoFadeOut; - } - break; - case IntroState::LogoFadeOut: - // Fade out, subtract 4 / 256 from fading - _introStateCounter -= 0x400; - if (_introStateCounter < 0) - { - gIntroState = IntroState::Clear; - } - break; - case IntroState::Clear: - // Stop any playing sound - if (_soundChannel != nullptr) - { - _soundChannel->Stop(); - _soundChannel = nullptr; - } - - // Move to next part - gIntroState = IntroState::Finish; - _introStateCounter = 0; - break; - case IntroState::Finish: - gIntroState = IntroState::None; - LoadPalette(); - OpenRCT2::Audio::PlayTitleMusic(); - break; - default: - break; - } -} - -void IntroDraw(DrawPixelInfo& dpi) -{ - int32_t screenWidth = ContextGetWidth(); - - switch (gIntroState) - { - case IntroState::Disclaimer1: - case IntroState::Disclaimer2: - break; - case IntroState::PublisherBegin: - GfxClear(dpi, kBackgroundColourDark); - break; - case IntroState::PublisherScroll: - GfxClear(dpi, kBackgroundColourDark); - - // Draw a white rectangle for the logo background (gives a bit of white margin) - GfxFillRect( - dpi, - { { (screenWidth / 2) - 320 + 50, _introStateCounter + 50 }, - { (screenWidth / 2) - 320 + 50 + 540, _introStateCounter + 50 + 425 } }, - kBorderColourPublisher); - - // Draw Infogrames logo - GfxDrawSprite(dpi, ImageId(SPR_INTRO_INFOGRAMES_00), { (screenWidth / 2) - 320 + 69, _introStateCounter + 69 }); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_INFOGRAMES_10), { (screenWidth / 2) - 320 + 319, _introStateCounter + 69 }); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_INFOGRAMES_01), { (screenWidth / 2) - 320 + 69, _introStateCounter + 319 }); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_INFOGRAMES_11), { (screenWidth / 2) - 320 + 319, _introStateCounter + 319 }); - break; - case IntroState::DeveloperBegin: - GfxClear(dpi, kBackgroundColourDark); - GfxTransposePalette(PALETTE_G1_IDX_DEVELOPER, 255); - break; - case IntroState::DeveloperScroll: - GfxClear(dpi, kBackgroundColourDark); - - // Draw Chris Sawyer logo - GfxDrawSprite(dpi, ImageId(SPR_INTRO_CHRIS_SAWYER_00), { (screenWidth / 2) - 320 + 70, _introStateCounter }); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_CHRIS_SAWYER_10), { (screenWidth / 2) - 320 + 320, _introStateCounter }); - break; - case IntroState::LogoFadeIn: - if (_introStateCounter <= 0xFF00) - { - GfxTransposePalette(PALETTE_G1_IDX_LOGO, (_introStateCounter >> 8) & 0xFF); - } - else - { - GfxTransposePalette(PALETTE_G1_IDX_LOGO, 255); - } - ScreenIntroDrawLogo(dpi); - break; - case IntroState::LogoWait: - ScreenIntroDrawLogo(dpi); - break; - case IntroState::LogoFadeOut: - if (_introStateCounter >= 0) - { - GfxTransposePalette(PALETTE_G1_IDX_LOGO, (_introStateCounter >> 8) & 0xFF); - } - else - { - GfxTransposePalette(PALETTE_G1_IDX_LOGO, 0); - } - ScreenIntroDrawLogo(dpi); - break; - case IntroState::Clear: - GfxClear(dpi, kBackgroundColourDark); - break; - default: - break; - } -} - -static void ScreenIntroProcessMouseInput() -{ - if (ContextGetCursorState()->any == CURSOR_PRESSED) - { - ScreenIntroSkipPart(); - } -} - -/** - * - * rct2: 0x006E3AEC - */ -static void ScreenIntroProcessKeyboardInput() -{ - const uint8_t* keys = ContextGetKeysState(); - for (int i = 0; i < 256; i++) - { - if (keys[i] != 0) - { - ScreenIntroSkipPart(); - break; - } - } -} - -static void ScreenIntroSkipPart() -{ - switch (gIntroState) - { - case IntroState::None: - break; - case IntroState::Disclaimer2: - gIntroState = IntroState::PublisherBegin; - break; - default: - gIntroState = IntroState::Clear; - break; - } -} - -static void ScreenIntroDrawLogo(DrawPixelInfo& dpi) -{ - int32_t screenWidth = ContextGetWidth(); - int32_t imageWidth = 640; - int32_t imageX = (screenWidth - imageWidth) / 2; - - DrawingEngineInvalidateImage(SPR_INTRO_LOGO_00); - DrawingEngineInvalidateImage(SPR_INTRO_LOGO_10); - DrawingEngineInvalidateImage(SPR_INTRO_LOGO_20); - DrawingEngineInvalidateImage(SPR_INTRO_LOGO_01); - DrawingEngineInvalidateImage(SPR_INTRO_LOGO_11); - DrawingEngineInvalidateImage(SPR_INTRO_LOGO_21); - - GfxClear(dpi, kBackgroundColourLogo); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_00), { imageX + 0, 0 }); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_10), { imageX + 220, 0 }); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_20), { imageX + 440, 0 }); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_01), { imageX + 0, 240 }); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_11), { imageX + 220, 240 }); - GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_21), { imageX + 440, 240 }); -} diff --git a/src/openrct2/Intro.h b/src/openrct2/Intro.h deleted file mode 100644 index 3fb8f90d21..0000000000 --- a/src/openrct2/Intro.h +++ /dev/null @@ -1,35 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2024 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#pragma once - -#include "common.h" - -struct DrawPixelInfo; - -enum class IntroState : uint8_t -{ - None, - PublisherBegin, - PublisherScroll, - DeveloperBegin, - DeveloperScroll, - LogoFadeIn, - LogoWait, - LogoFadeOut, - Disclaimer1, - Disclaimer2, - Clear = 254, - Finish = 255, -}; - -extern IntroState gIntroState; - -void IntroUpdate(); -void IntroDraw(DrawPixelInfo& dpi); diff --git a/src/openrct2/audio/Audio.cpp b/src/openrct2/audio/Audio.cpp index fbac597e0c..753c469532 100644 --- a/src/openrct2/audio/Audio.cpp +++ b/src/openrct2/audio/Audio.cpp @@ -10,7 +10,6 @@ #include "audio.h" #include "../Context.h" -#include "../Intro.h" #include "../OpenRCT2.h" #include "../PlatformEnvironment.h" #include "../config/Config.h" @@ -26,6 +25,7 @@ #include "../object/ObjectManager.h" #include "../ride/Ride.h" #include "../ride/RideAudio.h" +#include "../scenes/intro/IntroScene.h" #include "../ui/UiContext.h" #include "../util/Util.h" #include "../world/Climate.h" @@ -294,7 +294,7 @@ namespace OpenRCT2::Audio void PlayTitleMusic() { - if (gGameSoundsOff || !(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) || gIntroState != IntroState::None) + if (gGameSoundsOff || !(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) || IntroIsPlaying()) { StopTitleMusic(); return; diff --git a/src/openrct2/drawing/X8DrawingEngine.cpp b/src/openrct2/drawing/X8DrawingEngine.cpp index 5af091d8ab..ca0ef40a26 100644 --- a/src/openrct2/drawing/X8DrawingEngine.cpp +++ b/src/openrct2/drawing/X8DrawingEngine.cpp @@ -10,12 +10,12 @@ #include "X8DrawingEngine.h" #include "../Context.h" -#include "../Intro.h" #include "../config/Config.h" #include "../core/Numerics.hpp" #include "../interface/Screenshot.h" #include "../interface/Viewport.h" #include "../interface/Window.h" +#include "../scenes/intro/IntroScene.h" #include "../ui/UiContext.h" #include "../util/Util.h" #include "Drawing.h" @@ -184,7 +184,7 @@ void X8DrawingEngine::Invalidate(int32_t left, int32_t top, int32_t right, int32 void X8DrawingEngine::BeginDraw() { - if (gIntroState == IntroState::None) + if (!IntroIsPlaying()) { // HACK we need to re-configure the bits if light fx has been enabled / disabled if (_lastLightFXenabled != (gConfigGeneral.EnableLightFx != 0)) @@ -837,4 +837,4 @@ void X8DrawingContext::DrawTTFBitmap( else DrawTTFBitmapInternal(dpi, fgColor, surface, x, y, 0); #endif // NO_TTF -} \ No newline at end of file +} diff --git a/src/openrct2/interface/Screenshot.cpp b/src/openrct2/interface/Screenshot.cpp index 36c5e5025d..b3214d9161 100644 --- a/src/openrct2/interface/Screenshot.cpp +++ b/src/openrct2/interface/Screenshot.cpp @@ -12,7 +12,6 @@ #include "../Context.h" #include "../Game.h" #include "../GameState.h" -#include "../Intro.h" #include "../OpenRCT2.h" #include "../PlatformEnvironment.h" #include "../actions/CheatSetAction.h" @@ -490,7 +489,6 @@ int32_t CommandLineForScreenshot(const char** argv, int32_t argc, ScreenshotOpti throw std::runtime_error("Failed to load park."); } - gIntroState = IntroState::None; gScreenFlags = SCREEN_FLAGS_PLAYING; Viewport viewport{}; diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index ca3b0e6ce1..b3184b2c57 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -275,7 +275,6 @@ - @@ -512,6 +511,7 @@ + @@ -793,7 +793,6 @@ - @@ -1003,6 +1002,7 @@ + diff --git a/src/openrct2/paint/Painter.cpp b/src/openrct2/paint/Painter.cpp index e8d5b210c3..d24813d1af 100644 --- a/src/openrct2/paint/Painter.cpp +++ b/src/openrct2/paint/Painter.cpp @@ -11,7 +11,6 @@ #include "../Game.h" #include "../GameState.h" -#include "../Intro.h" #include "../OpenRCT2.h" #include "../ReplayManager.h" #include "../config/Config.h" @@ -24,6 +23,7 @@ #include "../localisation/Language.h" #include "../paint/Paint.h" #include "../profiling/Profiling.h" +#include "../scenes/intro/IntroScene.h" #include "../scenes/title/TitleScene.h" #include "../ui/UiContext.h" #include "../world/TileInspector.h" @@ -43,7 +43,8 @@ void Painter::Paint(IDrawingEngine& de) PROFILED_FUNCTION(); auto dpi = de.GetDrawingPixelInfo(); - if (gIntroState != IntroState::None) + + if (IntroIsPlaying()) { IntroDraw(*dpi); } diff --git a/src/openrct2/scenes/game/GameScene.h b/src/openrct2/scenes/game/GameScene.h index 7cf4bcd35c..c0b39ca89c 100644 --- a/src/openrct2/scenes/game/GameScene.h +++ b/src/openrct2/scenes/game/GameScene.h @@ -10,7 +10,6 @@ #pragma once #include "../../common.h" -#include "../../drawing/Drawing.h" #include "../Scene.h" namespace OpenRCT2 diff --git a/src/openrct2/scenes/intro/IntroScene.cpp b/src/openrct2/scenes/intro/IntroScene.cpp new file mode 100644 index 0000000000..82d0a1cb40 --- /dev/null +++ b/src/openrct2/scenes/intro/IntroScene.cpp @@ -0,0 +1,326 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "IntroScene.h" + +#include "../../Context.h" +#include "../../audio/AudioChannel.h" +#include "../../audio/AudioMixer.h" +#include "../../audio/audio.h" +#include "../../drawing/Drawing.h" +#include "../../sprites.h" + +#include + +using OpenRCT2::Audio::SoundId; + +namespace OpenRCT2 +{ + static constexpr PaletteIndex kBackgroundColourDark = PALETTE_INDEX_10; + static constexpr PaletteIndex kBackgroundColourLogo = PALETTE_INDEX_245; + static constexpr PaletteIndex kBorderColourPublisher = PALETTE_INDEX_129; + + constexpr int32_t PALETTE_G1_IDX_DEVELOPER = 23217; + constexpr int32_t PALETTE_G1_IDX_LOGO = 23224; + + static IntroState _introState; + + // Used mainly for timing but also for Y coordinate and fading. + static int32_t _introStateCounter; + + static std::shared_ptr _soundChannel = nullptr; + static bool _chainLiftFinished; + + bool IntroIsPlaying() + { + return _introState != IntroState::None; + } + + void IntroScene::Load() + { + _introState = IntroState::PublisherBegin; + } + + void IntroScene::Stop() + { + _introState = IntroState::None; + LoadPalette(); + } + + static void ScreenIntroProcessMouseInput(); + static void ScreenIntroProcessKeyboardInput(); + static void ScreenIntroSkipPart(); + static void ScreenIntroDrawLogo(DrawPixelInfo& dpi); + + // rct2: 0x0068E966 + void IntroScene::Tick() + { + ScreenIntroProcessMouseInput(); + ScreenIntroProcessKeyboardInput(); + + switch (_introState) + { + case IntroState::Disclaimer1: + case IntroState::Disclaimer2: + // Originally used for the disclaimer text + _introState = IntroState::PublisherBegin; + [[fallthrough]]; + case IntroState::PublisherBegin: + LoadPalette(); + + // Set the Y for the Infogrames logo + _introStateCounter = -580; + + // Play the chain lift sound + _soundChannel = Audio::CreateAudioChannel(SoundId::LiftBM, true); + _chainLiftFinished = false; + _introState = IntroState::PublisherScroll; + break; + case IntroState::PublisherScroll: + // Move the Infogrames logo down + _introStateCounter += 5; + + // Check if logo is off the screen...ish + if (_introStateCounter > ContextGetHeight() - 120) + { + _introStateCounter = -116; + _introState = IntroState::DeveloperBegin; + } + + break; + case IntroState::DeveloperBegin: + // Set the Y for the Chris Sawyer logo + _introStateCounter = -116; + + _introState = IntroState::DeveloperScroll; + break; + case IntroState::DeveloperScroll: + _introStateCounter += 5; + + // Check if logo is almost scrolled to the bottom + if (!_chainLiftFinished && _introStateCounter >= ContextGetHeight() + 40 - 421) + { + _chainLiftFinished = true; + + // Stop the chain lift sound + if (_soundChannel != nullptr) + { + _soundChannel->Stop(); + _soundChannel = nullptr; + } + + // Play the track friction sound + _soundChannel = Audio::CreateAudioChannel( + SoundId::TrackFrictionBM, true, Audio::kMixerVolumeMax, 0.25f, 0.75); + } + + // Check if logo is off the screen...ish + if (_introStateCounter >= ContextGetHeight() + 40) + { + // Stop the track friction sound + if (_soundChannel != nullptr) + { + _soundChannel->Stop(); + _soundChannel = nullptr; + } + + // Play long peep scream sound + _soundChannel = Audio::CreateAudioChannel(SoundId::Scream1); + + _introState = IntroState::LogoFadeIn; + _introStateCounter = 0; + } + break; + case IntroState::LogoFadeIn: + // Fade in, add 4 / 256 to fading + _introStateCounter += 0x400; + if (_introStateCounter > 0xFF00) + { + _introState = IntroState::LogoWait; + _introStateCounter = 0; + } + break; + case IntroState::LogoWait: + // Wait 80 game ticks + _introStateCounter++; + if (_introStateCounter >= 80) + { + // Set fading to 256 + _introStateCounter = 0xFF00; + + _introState = IntroState::LogoFadeOut; + } + break; + case IntroState::LogoFadeOut: + // Fade out, subtract 4 / 256 from fading + _introStateCounter -= 0x400; + if (_introStateCounter < 0) + { + _introState = IntroState::Clear; + } + break; + case IntroState::Clear: + // Stop any playing sound + if (_soundChannel != nullptr) + { + _soundChannel->Stop(); + _soundChannel = nullptr; + } + + // Move to next part + _introState = IntroState::Finish; + _introStateCounter = 0; + break; + case IntroState::Finish: + { + auto& context = GetContext(); + context.SetActiveScene(context.GetTitleScene()); + } + default: + break; + } + } + + void IntroDraw(DrawPixelInfo& dpi) + { + int32_t screenWidth = ContextGetWidth(); + + switch (_introState) + { + case IntroState::Disclaimer1: + case IntroState::Disclaimer2: + break; + case IntroState::PublisherBegin: + GfxClear(dpi, kBackgroundColourDark); + break; + case IntroState::PublisherScroll: + GfxClear(dpi, kBackgroundColourDark); + + // Draw a white rectangle for the logo background (gives a bit of white margin) + GfxFillRect( + dpi, + { { (screenWidth / 2) - 320 + 50, _introStateCounter + 50 }, + { (screenWidth / 2) - 320 + 50 + 540, _introStateCounter + 50 + 425 } }, + kBorderColourPublisher); + + // Draw Infogrames logo + GfxDrawSprite(dpi, ImageId(SPR_INTRO_INFOGRAMES_00), { (screenWidth / 2) - 320 + 69, _introStateCounter + 69 }); + GfxDrawSprite( + dpi, ImageId(SPR_INTRO_INFOGRAMES_10), { (screenWidth / 2) - 320 + 319, _introStateCounter + 69 }); + GfxDrawSprite( + dpi, ImageId(SPR_INTRO_INFOGRAMES_01), { (screenWidth / 2) - 320 + 69, _introStateCounter + 319 }); + GfxDrawSprite( + dpi, ImageId(SPR_INTRO_INFOGRAMES_11), { (screenWidth / 2) - 320 + 319, _introStateCounter + 319 }); + break; + case IntroState::DeveloperBegin: + GfxClear(dpi, kBackgroundColourDark); + GfxTransposePalette(PALETTE_G1_IDX_DEVELOPER, 255); + break; + case IntroState::DeveloperScroll: + GfxClear(dpi, kBackgroundColourDark); + + // Draw Chris Sawyer logo + GfxDrawSprite(dpi, ImageId(SPR_INTRO_CHRIS_SAWYER_00), { (screenWidth / 2) - 320 + 70, _introStateCounter }); + GfxDrawSprite(dpi, ImageId(SPR_INTRO_CHRIS_SAWYER_10), { (screenWidth / 2) - 320 + 320, _introStateCounter }); + break; + case IntroState::LogoFadeIn: + if (_introStateCounter <= 0xFF00) + { + GfxTransposePalette(PALETTE_G1_IDX_LOGO, (_introStateCounter >> 8) & 0xFF); + } + else + { + GfxTransposePalette(PALETTE_G1_IDX_LOGO, 255); + } + ScreenIntroDrawLogo(dpi); + break; + case IntroState::LogoWait: + ScreenIntroDrawLogo(dpi); + break; + case IntroState::LogoFadeOut: + if (_introStateCounter >= 0) + { + GfxTransposePalette(PALETTE_G1_IDX_LOGO, (_introStateCounter >> 8) & 0xFF); + } + else + { + GfxTransposePalette(PALETTE_G1_IDX_LOGO, 0); + } + ScreenIntroDrawLogo(dpi); + break; + case IntroState::Clear: + GfxClear(dpi, kBackgroundColourDark); + break; + default: + break; + } + } + + static void ScreenIntroProcessMouseInput() + { + if (ContextGetCursorState()->any == CURSOR_PRESSED) + { + ScreenIntroSkipPart(); + } + } + + /** + * + * rct2: 0x006E3AEC + */ + static void ScreenIntroProcessKeyboardInput() + { + const uint8_t* keys = ContextGetKeysState(); + for (int i = 0; i < 256; i++) + { + if (keys[i] != 0) + { + ScreenIntroSkipPart(); + break; + } + } + } + + static void ScreenIntroSkipPart() + { + switch (_introState) + { + case IntroState::None: + break; + case IntroState::Disclaimer2: + _introState = IntroState::PublisherBegin; + break; + default: + _introState = IntroState::Clear; + break; + } + } + + static void ScreenIntroDrawLogo(DrawPixelInfo& dpi) + { + int32_t screenWidth = ContextGetWidth(); + int32_t imageWidth = 640; + int32_t imageX = (screenWidth - imageWidth) / 2; + + DrawingEngineInvalidateImage(SPR_INTRO_LOGO_00); + DrawingEngineInvalidateImage(SPR_INTRO_LOGO_10); + DrawingEngineInvalidateImage(SPR_INTRO_LOGO_20); + DrawingEngineInvalidateImage(SPR_INTRO_LOGO_01); + DrawingEngineInvalidateImage(SPR_INTRO_LOGO_11); + DrawingEngineInvalidateImage(SPR_INTRO_LOGO_21); + + GfxClear(dpi, kBackgroundColourLogo); + GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_00), { imageX + 0, 0 }); + GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_10), { imageX + 220, 0 }); + GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_20), { imageX + 440, 0 }); + GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_01), { imageX + 0, 240 }); + GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_11), { imageX + 220, 240 }); + GfxDrawSprite(dpi, ImageId(SPR_INTRO_LOGO_21), { imageX + 440, 240 }); + } +} // namespace OpenRCT2 diff --git a/src/openrct2/scenes/intro/IntroScene.h b/src/openrct2/scenes/intro/IntroScene.h new file mode 100644 index 0000000000..df6f3da349 --- /dev/null +++ b/src/openrct2/scenes/intro/IntroScene.h @@ -0,0 +1,48 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../../common.h" +#include "../Scene.h" + +struct DrawPixelInfo; + +namespace OpenRCT2 +{ + enum class IntroState : uint8_t + { + None, + PublisherBegin, + PublisherScroll, + DeveloperBegin, + DeveloperScroll, + LogoFadeIn, + LogoWait, + LogoFadeOut, + Disclaimer1, + Disclaimer2, + Clear = 254, + Finish = 255, + }; + + class IntroScene final : public Scene + { + public: + using Scene::Scene; + + void Load() override; + void Tick() override; + void Stop() override; + }; + + bool IntroIsPlaying(); + void IntroUpdate(); + void IntroDraw(DrawPixelInfo& dpi); +} // namespace OpenRCT2