Skip to content

Commit 66b0f43

Browse files
glebmAJenbo
authored andcommitted
Add a threshold for skipping the loading screen
1 parent 7b05581 commit 66b0f43

File tree

5 files changed

+99
-69
lines changed

5 files changed

+99
-69
lines changed

Source/engine/palette.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -296,15 +296,15 @@ int UpdateGamma(int gamma)
296296
return 130 - *sgOptions.Graphics.gammaCorrection;
297297
}
298298

299-
void SetFadeLevel(int fadeval, bool updateHardwareCursor)
299+
void SetFadeLevel(int fadeval, bool updateHardwareCursor, const std::array<SDL_Color, 256> &srcPalette)
300300
{
301301
if (HeadlessMode)
302302
return;
303303

304304
for (int i = 0; i < 256; i++) {
305-
system_palette[i].r = (fadeval * logical_palette[i].r) / 256;
306-
system_palette[i].g = (fadeval * logical_palette[i].g) / 256;
307-
system_palette[i].b = (fadeval * logical_palette[i].b) / 256;
305+
system_palette[i].r = (fadeval * srcPalette[i].r) / 256;
306+
system_palette[i].g = (fadeval * srcPalette[i].g) / 256;
307+
system_palette[i].b = (fadeval * srcPalette[i].b) / 256;
308308
#if SDL_VERSION_ATLEAST(2, 0, 0)
309309
system_palette[i].a = SDL_ALPHA_OPAQUE;
310310
#endif
@@ -323,14 +323,14 @@ void BlackPalette()
323323
SetFadeLevel(0, /*updateHardwareCursor=*/false);
324324
}
325325

326-
void PaletteFadeIn(int fr)
326+
void PaletteFadeIn(int fr, const std::array<SDL_Color, 256> &srcPalette)
327327
{
328328
if (HeadlessMode)
329329
return;
330330
if (demo::IsRunning())
331331
fr = 0;
332332

333-
ApplyGamma(logical_palette, orig_palette, 256);
333+
ApplyGamma(logical_palette, srcPalette, 256);
334334

335335
if (fr > 0) {
336336
const uint32_t tc = SDL_GetTicks();
@@ -339,7 +339,7 @@ void PaletteFadeIn(int fr)
339339
for (uint32_t i = 0; i < 256; i = fr * (SDL_GetTicks() - tc) / 50) {
340340
if (i != prevFadeValue) {
341341
// We can skip hardware cursor update for fade level 0 (everything is black).
342-
SetFadeLevel(i, /*updateHardwareCursor=*/i != 0u);
342+
SetFadeLevel(i, /*updateHardwareCursor=*/i != 0u, logical_palette);
343343
prevFadeValue = i;
344344
}
345345
BltFast(nullptr, nullptr);
@@ -352,12 +352,12 @@ void PaletteFadeIn(int fr)
352352
RenderPresent();
353353
}
354354

355-
logical_palette = orig_palette;
355+
logical_palette = srcPalette;
356356

357357
sgbFadedIn = true;
358358
}
359359

360-
void PaletteFadeOut(int fr)
360+
void PaletteFadeOut(int fr, const std::array<SDL_Color, 256> &srcPalette)
361361
{
362362
if (!sgbFadedIn || HeadlessMode)
363363
return;
@@ -370,15 +370,15 @@ void PaletteFadeOut(int fr)
370370
uint32_t prevFadeValue = 0;
371371
for (uint32_t i = 0; i < 256; i = fr * (SDL_GetTicks() - tc) / 50) {
372372
if (i != prevFadeValue) {
373-
SetFadeLevel(256 - i);
373+
SetFadeLevel(256 - i, /*updateHardwareCursor=*/true, srcPalette);
374374
prevFadeValue = i;
375375
}
376376
BltFast(nullptr, nullptr);
377377
RenderPresent();
378378
}
379-
SetFadeLevel(0);
379+
SetFadeLevel(0, /*updateHardwareCursor=*/true, srcPalette);
380380
} else {
381-
SetFadeLevel(0);
381+
SetFadeLevel(0, /*updateHardwareCursor=*/true, srcPalette);
382382
BltFast(nullptr, nullptr);
383383
RenderPresent();
384384
}

Source/engine/palette.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,17 @@ void ApplyGamma(std::array<SDL_Color, 256> &dst, const std::array<SDL_Color, 256
6060
void DecreaseGamma();
6161
int UpdateGamma(int gamma);
6262
void BlackPalette();
63-
void SetFadeLevel(int fadeval, bool updateHardwareCursor = true);
63+
void SetFadeLevel(int fadeval, bool updateHardwareCursor = true, const std::array<SDL_Color, 256> &srcPalette = logical_palette);
6464
/**
6565
* @brief Fade screen from black
6666
* @param fr Steps per 50ms
6767
*/
68-
void PaletteFadeIn(int fr);
68+
void PaletteFadeIn(int fr, const std::array<SDL_Color, 256> &srcPalette = orig_palette);
6969
/**
7070
* @brief Fade screen to black
7171
* @param fr Steps per 50ms
7272
*/
73-
void PaletteFadeOut(int fr);
73+
void PaletteFadeOut(int fr, const std::array<SDL_Color, 256> &srcPalette = logical_palette);
7474
void palette_update_caves();
7575
void palette_update_crypt();
7676
void palette_update_hive();

Source/interfac.cpp

Lines changed: 75 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "loadsave.h"
2626
#include "pfile.h"
2727
#include "plrmsg.h"
28+
#include "utils/log.hpp"
2829
#include "utils/sdl_geometry.h"
2930
#include "utils/sdl_thread.h"
3031

@@ -403,59 +404,89 @@ void DoLoad(interface_mode uMsg)
403404
}
404405

405406
struct {
406-
uint32_t delayStart;
407+
uint32_t loadStartedAt;
407408
EventHandler prevHandler;
409+
bool skipRendering;
408410
bool done;
411+
uint32_t drawnProgress;
409412
std::array<SDL_Color, 256> palette;
410413
} ProgressEventHandlerState;
411414

415+
void InitRendering()
416+
{
417+
// Blit the background once and then free it.
418+
DrawCutsceneBackground();
419+
if (RenderDirectlyToOutputSurface && PalSurface != nullptr) {
420+
// Render into all the backbuffers if there are multiple.
421+
const void *initialPixels = PalSurface->pixels;
422+
if (DiabloUiSurface() == PalSurface)
423+
BltFast(nullptr, nullptr);
424+
RenderPresent();
425+
while (PalSurface->pixels != initialPixels) {
426+
DrawCutsceneBackground();
427+
if (DiabloUiSurface() == PalSurface)
428+
BltFast(nullptr, nullptr);
429+
RenderPresent();
430+
}
431+
}
432+
FreeCutsceneBackground();
433+
434+
// The loading thread sets `orig_palette`, so we make sure to use
435+
// our own palette for the fade-in.
436+
PaletteFadeIn(8, ProgressEventHandlerState.palette);
437+
}
438+
439+
void CheckShouldSkipRendering()
440+
{
441+
if (!ProgressEventHandlerState.skipRendering) return;
442+
const bool shouldSkip = ProgressEventHandlerState.loadStartedAt + *sgOptions.Gameplay.skipLoadingScreenThresholdMs > SDL_GetTicks();
443+
if (shouldSkip) return;
444+
ProgressEventHandlerState.skipRendering = false;
445+
if (!HeadlessMode) InitRendering();
446+
}
447+
412448
void ProgressEventHandler(const SDL_Event &event, uint16_t modState)
413449
{
414450
DisableInputEventHandler(event, modState);
415451
if (!IsCustomEvent(event.type)) return;
416452

417-
static uint32_t drawnProgress;
418-
drawnProgress = 0;
419-
420453
const interface_mode customEvent = GetCustomEvent(event.type);
421454
switch (customEvent) {
422455
case WM_PROGRESS:
423-
if (!HeadlessMode && drawnProgress != sgdwProgress) {
456+
if (!HeadlessMode && ProgressEventHandlerState.drawnProgress != sgdwProgress && !ProgressEventHandlerState.skipRendering) {
424457
DrawCutsceneForeground();
425-
drawnProgress = sgdwProgress;
458+
ProgressEventHandlerState.drawnProgress = sgdwProgress;
426459
}
427460
break;
428461
case WM_ERROR:
429462
app_fatal(*static_cast<std::string *>(event.user.data1));
430463
break;
431464
case WM_DONE: {
432-
// We may have loaded a new palette.
433-
// Temporarily switch back to the load screen palette for fade out.
434-
std::array<SDL_Color, 256> prevPalette;
435-
if (!HeadlessMode) {
436-
prevPalette = orig_palette;
437-
orig_palette = ProgressEventHandlerState.palette;
438-
ApplyGamma(logical_palette, orig_palette, 256);
439-
}
440-
NewCursor(CURSOR_HAND);
441-
442-
if (!HeadlessMode) {
443-
assert(ghMainWnd);
444-
445-
if (RenderDirectlyToOutputSurface && PalSurface != nullptr) {
446-
// Ensure that all back buffers have the full progress bar.
447-
const void *initialPixels = PalSurface->pixels;
448-
do {
449-
DrawCutsceneForeground();
450-
if (DiabloUiSurface() == PalSurface)
451-
BltFast(nullptr, nullptr);
452-
RenderPresent();
453-
} while (PalSurface->pixels != initialPixels);
465+
if (!ProgressEventHandlerState.skipRendering) {
466+
NewCursor(CURSOR_HAND);
467+
468+
if (!HeadlessMode) {
469+
assert(ghMainWnd);
470+
471+
if (RenderDirectlyToOutputSurface && PalSurface != nullptr) {
472+
// The loading thread sets `orig_palette`, so we make sure to use
473+
// our own palette for drawing the foreground.
474+
ApplyGamma(logical_palette, ProgressEventHandlerState.palette, 256);
475+
476+
// Ensure that all back buffers have the full progress bar.
477+
const void *initialPixels = PalSurface->pixels;
478+
do {
479+
DrawCutsceneForeground();
480+
if (DiabloUiSurface() == PalSurface)
481+
BltFast(nullptr, nullptr);
482+
RenderPresent();
483+
} while (PalSurface->pixels != initialPixels);
484+
}
485+
486+
// The loading thread sets `orig_palette`, so we make sure to use
487+
// our own palette for the fade-out.
488+
PaletteFadeOut(8, ProgressEventHandlerState.palette);
454489
}
455-
456-
PaletteFadeOut(8);
457-
orig_palette = prevPalette;
458-
ApplyGamma(logical_palette, orig_palette, 256);
459490
}
460491

461492
[[maybe_unused]] EventHandler prevHandler = SetEventHandler(ProgressEventHandlerState.prevHandler);
@@ -465,7 +496,7 @@ void ProgressEventHandler(const SDL_Event &event, uint16_t modState)
465496

466497
Player &myPlayer = *MyPlayer;
467498
NetSendCmdLocParam2(true, CMD_PLAYER_JOINLEVEL, myPlayer.position.tile, myPlayer.plrlevel, myPlayer.plrIsOnSetLevel ? 1 : 0);
468-
DelayPlrMessages(SDL_GetTicks() - ProgressEventHandlerState.delayStart);
499+
DelayPlrMessages(SDL_GetTicks() - ProgressEventHandlerState.loadStartedAt);
469500

470501
if (gbSomebodyWonGameKludge && myPlayer.isOnLevel(16)) {
471502
PrepDoEnding();
@@ -552,9 +583,11 @@ void ShowProgress(interface_mode uMsg)
552583
IsProgress = true;
553584
gbSomebodyWonGameKludge = false;
554585

555-
ProgressEventHandlerState.delayStart = SDL_GetTicks();
586+
ProgressEventHandlerState.loadStartedAt = SDL_GetTicks();
556587
ProgressEventHandlerState.prevHandler = SetEventHandler(ProgressEventHandler);
588+
ProgressEventHandlerState.skipRendering = true;
557589
ProgressEventHandlerState.done = false;
590+
ProgressEventHandlerState.drawnProgress = 0;
558591

559592
#ifndef USE_SDL1
560593
DeactivateVirtualGamepad();
@@ -573,42 +606,30 @@ void ShowProgress(interface_mode uMsg)
573606

574607
BlackPalette();
575608

576-
// Blit the background once and then free it.
609+
// Always load the background (even if we end up skipping rendering it).
610+
// This is because the MPQ archive can only be read by a single thread at a time.
577611
LoadCutsceneBackground(uMsg);
578-
DrawCutsceneBackground();
612+
613+
// Save the palette at this point because the loading process may replace it.
579614
ProgressEventHandlerState.palette = orig_palette;
580-
if (RenderDirectlyToOutputSurface && PalSurface != nullptr) {
581-
// Render into all the backbuffers if there are multiple.
582-
const void *initialPixels = PalSurface->pixels;
583-
if (DiabloUiSurface() == PalSurface)
584-
BltFast(nullptr, nullptr);
585-
RenderPresent();
586-
while (PalSurface->pixels != initialPixels) {
587-
DrawCutsceneBackground();
588-
if (DiabloUiSurface() == PalSurface)
589-
BltFast(nullptr, nullptr);
590-
RenderPresent();
591-
}
592-
}
593-
FreeCutsceneBackground();
594615
}
595616

596617
// Begin loading
597618
static interface_mode loadTarget;
598619
loadTarget = uMsg;
599620
SdlThread loadThread = SdlThread([]() {
621+
const uint32_t start = SDL_GetTicks();
600622
DoLoad(loadTarget);
623+
LogVerbose("Load thread finished in {}ms", SDL_GetTicks() - start);
601624
});
602625

603-
if (!HeadlessMode) {
604-
PaletteFadeIn(8);
605-
}
606-
607626
while (true) {
627+
CheckShouldSkipRendering();
608628
SDL_Event event;
609629
// We use the real `SDL_PollEvent` here instead of `FetchEvent`
610630
// to process real events rather than the recorded ones in demo mode.
611631
while (SDL_PollEvent(&event)) {
632+
CheckShouldSkipRendering();
612633
if (event.type != SDL_QUIT) {
613634
HandleMessage(event, SDL_GetModState());
614635
}

Source/options.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@ GameplayOptions::GameplayOptions()
966966
{ FloatingNumbers::Random, N_("Random Angles") },
967967
{ FloatingNumbers::Vertical, N_("Vertical Only") },
968968
})
969+
, skipLoadingScreenThresholdMs("Skip loading screen threshold, ms", OptionEntryFlags::Invisible, "", "", 0)
969970
{
970971
grabInput.SetValueChangedCallback(OptionGrabInputChanged);
971972
experienceBar.SetValueChangedCallback(OptionExperienceBarChanged);
@@ -1012,6 +1013,7 @@ std::vector<OptionEntryBase *> GameplayOptions::GetEntries()
10121013
&adriaRefillsMana,
10131014
&grabInput,
10141015
&pauseOnFocusLoss,
1016+
&skipLoadingScreenThresholdMs,
10151017
};
10161018
}
10171019

Source/options.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,13 @@ struct GameplayOptions : OptionCategoryBase {
599599
OptionEntryInt<int> numFullRejuPotionPickup;
600600
/** @brief Enable floating numbers. */
601601
OptionEntryEnum<FloatingNumbers> enableFloatingNumbers;
602+
603+
/**
604+
* @brief If loading takes less than this value, skips displaying the loading screen.
605+
*
606+
* Advanced option, not displayed in the UI.
607+
*/
608+
OptionEntryInt<int> skipLoadingScreenThresholdMs;
602609
};
603610

604611
struct ControllerOptions : OptionCategoryBase {

0 commit comments

Comments
 (0)