Browse Source

Loading screen: Free the background early

Frees the background after blitting it once in the loading screen.
This gives the game more RAM for the actual loading.
pull/4709/head
Gleb Mazovetskiy 4 years ago committed by Anders Jenbo
parent
commit
9d2948c782
  1. 50
      Source/DiabloUI/progress.cpp
  2. 46
      Source/interfac.cpp
  3. 9
      Source/utils/display.cpp
  4. 2
      Source/utils/display.h

50
Source/DiabloUI/progress.cpp

@ -1,3 +1,5 @@
#include <SDL.h>
#include "DiabloUI/art_draw.h"
#include "DiabloUI/button.h"
#include "DiabloUI/diabloui.h"
@ -27,11 +29,15 @@ void DialogActionCancel()
endMenu = true;
}
void ProgressLoad()
void ProgressLoadBackground()
{
LoadBackgroundArt("ui_art\\black.pcx");
ArtPopupSm = LoadPcxAsset("ui_art\\spopup.pcx");
ArtProgBG = LoadPcxAsset("ui_art\\prog_bg.pcx");
}
void ProgressLoadForeground()
{
ProgFil = LoadPcxAsset("ui_art\\prog_fil.pcx");
const Point uiPosition = GetUIRectangle().position;
@ -39,25 +45,40 @@ void ProgressLoad()
vecProgress.push_back(std::make_unique<UiButton>(_("Cancel"), &DialogActionCancel, rect3));
}
void ProgressFree()
void ProgressFreeBackground()
{
ArtBackground = std::nullopt;
ArtPopupSm = std::nullopt;
ArtProgBG = std::nullopt;
}
void ProgressFreeForeground()
{
vecProgress.clear();
ProgFil = std::nullopt;
}
void ProgressRender(BYTE progress)
Point GetPosition()
{
return { GetCenterOffset(280), GetCenterOffset(144, gnScreenHeight) };
}
void ProgressRenderBackground()
{
SDL_FillRect(DiabloUiSurface(), nullptr, 0x000000);
const Surface &out = Surface(DiabloUiSurface());
RenderPcxSprite(out, PcxSpriteSheet { *ArtBackground }.sprite(0), { 0, 0 });
Point position = { GetCenterOffset(280), GetCenterOffset(144, gnScreenHeight) };
const Point position = GetPosition();
RenderPcxSprite(out, PcxSprite { *ArtPopupSm }, position);
RenderPcxSprite(out, PcxSprite { *ArtProgBG }, { GetCenterOffset(227), position.y + 52 });
}
void ProgressRenderForeground(int progress)
{
const Surface &out = Surface(DiabloUiSurface());
const Point position = GetPosition();
if (progress != 0) {
const int x = GetCenterOffset(227);
const int w = 227 * progress / 100;
@ -71,16 +92,29 @@ void ProgressRender(BYTE progress)
bool UiProgressDialog(int (*fnfunc)())
{
ProgressLoad();
SetFadeLevel(256);
// Blit the background once and then free it.
ProgressLoadBackground();
ProgressRenderBackground();
if (RenderDirectlyToOutputSurface && IsDoubleBuffered()) {
// Blit twice for triple buffering.
for (unsigned i = 0; i < 2; ++i) {
UiFadeIn();
ProgressRenderBackground();
}
}
ProgressFreeBackground();
ProgressLoadForeground();
endMenu = false;
int progress = 0;
SDL_Event event;
while (!endMenu && progress < 100) {
progress = fnfunc();
ProgressRender(progress);
ProgressRenderForeground(progress);
UiRenderItems(vecProgress);
DrawMouse();
UiFadeIn();
@ -113,7 +147,7 @@ bool UiProgressDialog(int (*fnfunc)())
UiHandleEvents(&event);
}
}
ProgressFree();
ProgressFreeForeground();
return progress == 100;
}

46
Source/interfac.cpp

@ -6,6 +6,8 @@
#include <cstdint>
#include <SDL.h>
#include "control.h"
#include "dx.h"
#include "engine.h"
@ -40,12 +42,6 @@ const int BarPos[3][2] = { { 53, 37 }, { 53, 421 }, { 53, 37 } };
std::optional<OwnedPcxSprite> ArtCutsceneWidescreen;
void FreeInterface()
{
sgpBackCel = std::nullopt;
ArtCutsceneWidescreen = std::nullopt;
}
Cutscenes PickCutscene(interface_mode uMsg)
{
switch (uMsg) {
@ -97,7 +93,7 @@ Cutscenes PickCutscene(interface_mode uMsg)
}
}
void InitCutscene(interface_mode uMsg)
void LoadCutsceneBackground(interface_mode uMsg)
{
const char *celPath;
const char *palPath;
@ -170,7 +166,13 @@ void InitCutscene(interface_mode uMsg)
sgdwProgress = 0;
}
void DrawCutscene()
void FreeCutsceneBackground()
{
sgpBackCel = std::nullopt;
ArtCutsceneWidescreen = std::nullopt;
}
void DrawCutsceneBackground()
{
const Rectangle &uiRectangle = GetUIRectangle();
const Surface &out = GlobalBackBuffer();
@ -179,7 +181,12 @@ void DrawCutscene()
RenderPcxSprite(out, sprite, { uiRectangle.position.x - (sprite.width() - uiRectangle.size.width) / 2, uiRectangle.position.y });
}
CelDrawTo(out, { uiRectangle.position.x, 480 - 1 + uiRectangle.position.y }, *sgpBackCel, 0);
}
void DrawCutsceneForeground()
{
const Rectangle &uiRectangle = GetUIRectangle();
const Surface &out = GlobalBackBuffer();
constexpr int ProgressHeight = 22;
SDL_Rect rect = MakeSdlRect(
out.region.x + BarPos[progress_id][0] + uiRectangle.position.x,
@ -188,7 +195,8 @@ void DrawCutscene()
ProgressHeight);
SDL_FillRect(out.surface, &rect, BarColor[progress_id]);
BltFast(&rect, &rect);
if (DiabloUiSurface() == PalSurface)
BltFast(&rect, &rect);
RenderPresent();
}
@ -212,8 +220,7 @@ bool IncProgress()
sgdwProgress += 23;
if (sgdwProgress > 534)
sgdwProgress = 534;
if (sgpBackCel)
DrawCutscene();
DrawCutsceneForeground();
return sgdwProgress >= 534;
}
@ -230,9 +237,21 @@ void ShowProgress(interface_mode uMsg)
interface_msg_pump();
ClearScreenBuffer();
scrollrt_draw_game_screen();
InitCutscene(uMsg);
BlackPalette();
DrawCutscene();
// Blit the background once and then free it.
LoadCutsceneBackground(uMsg);
DrawCutsceneBackground();
if (RenderDirectlyToOutputSurface && IsDoubleBuffered()) {
// Blit twice for triple buffering.
for (unsigned i = 0; i < 2; ++i) {
if (DiabloUiSurface() == PalSurface)
BltFast(nullptr, nullptr);
RenderPresent();
DrawCutsceneBackground();
}
}
FreeCutsceneBackground();
if (IsHardwareCursor())
SetHardwareCursorVisible(false);
@ -390,7 +409,6 @@ void ShowProgress(interface_mode uMsg)
assert(ghMainWnd);
PaletteFadeOut(8);
FreeInterface();
saveProc = SetWindowProc(saveProc);
assert(saveProc == DisableInputWndProc);

9
Source/utils/display.cpp

@ -473,6 +473,15 @@ SDL_Surface *GetOutputSurface()
#endif
}
bool IsDoubleBuffered()
{
#ifdef USE_SDL1
return (GetOutputSurface()->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF;
#else
return true;
#endif
}
bool OutputRequiresScaling()
{
#ifdef USE_SDL1

2
Source/utils/display.h

@ -40,6 +40,8 @@ bool IsFullScreen();
// SDL2, upscale: Renderer texture surface.
SDL_Surface *GetOutputSurface();
bool IsDoubleBuffered();
// Whether the output surface requires software scaling.
// Always returns false on SDL2.
bool OutputRequiresScaling();

Loading…
Cancel
Save