You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
5.2 KiB

/**
* @file init.cpp
*
* Implementation of routines for initializing the environment, disable screen saver, load MPQ.
*/
10 months ago
#include "init.hpp"
#include <cstdint>
#include <string>
#include <vector>
#ifdef USE_SDL3
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_video.h>
#else
#include <SDL.h>
#endif
#include <config.h>
#include "DiabloUI/diabloui.h"
#include "engine/assets.hpp"
#include "engine/backbuffer_state.hpp"
#include "engine/dx.h"
#include "engine/events.hpp"
#include "game_mode.hpp"
#include "headless_mode.hpp"
#include "hwcursor.hpp"
#include "options.h"
#include "pfile.h"
#include "utils/file_util.h"
#include "utils/language.h"
#include "utils/log.hpp"
#include "utils/paths.h"
#include "utils/str_split.hpp"
#include "utils/ui_fwd.h"
#include "utils/utf8.hpp"
#ifndef UNPACKED_MPQS
#include "mpq/mpq_reader.hpp"
#endif
#ifdef __vita__
// increase default allowed heap size on Vita
int _newlib_heap_size_user = 100 * 1024 * 1024;
#endif
namespace devilution {
bool gbActive;
namespace {
constexpr char DevilutionXMpqVersion[] = "1\n";
constexpr char ExtraFontsVersion[] = "1\n";
bool AssetContentsEq(AssetRef &&ref, std::string_view expected)
{
const size_t size = ref.size();
AssetHandle handle = OpenAsset(std::move(ref), false);
if (!handle.ok()) return false;
const std::unique_ptr<char[]> contents { new char[size] };
if (!handle.read(contents.get(), size)) return false;
return std::string_view { contents.get(), size } == expected;
}
bool CheckDevilutionXMpqVersion(AssetRef &&ref)
{
return !AssetContentsEq(std::move(ref), DevilutionXMpqVersion);
}
bool CheckExtraFontsVersion(AssetRef &&ref)
{
return !AssetContentsEq(std::move(ref), ExtraFontsVersion);
}
} // namespace
bool IsDevilutionXMpqOutOfDate()
{
AssetRef ref = FindAsset("ASSETS_VERSION");
if (!ref.ok())
return true;
return CheckDevilutionXMpqVersion(std::move(ref));
}
#ifdef UNPACKED_MPQS
bool AreExtraFontsOutOfDate(std::string_view path)
{
const std::string versionPath = StrCat(path, "fonts" DIRECTORY_SEPARATOR_STR "VERSION");
if (versionPath.size() + 1 > AssetRef::PathBufSize)
app_fatal("Path too long");
AssetRef ref;
*BufCopy(ref.path, versionPath) = '\0';
return CheckExtraFontsVersion(std::move(ref));
}
#else
bool AreExtraFontsOutOfDate(MpqArchive &archive)
{
const char filename[] = "fonts\\VERSION";
if (!archive.HasFile(filename))
return true;
AssetRef ref;
ref.archive = &archive;
ref.filename = filename;
return CheckExtraFontsVersion(std::move(ref));
}
#endif
bool AreExtraFontsOutOfDate()
{
const auto it = MpqArchives.find(FontMpqPriority);
return it != MpqArchives.end() && AreExtraFontsOutOfDate(it->second);
}
void init_cleanup()
{
if (gbIsMultiplayer && gbRunGame) {
pfile_write_hero(/*writeGameData=*/false);
4 years ago
sfile_write_stash();
}
MpqArchives.clear();
HasHellfireMpq = false;
NetClose();
}
void init_create_window()
{
if (!SpawnWindow(PROJECT_NAME))
app_fatal(_("Unable to create main window"));
dx_init();
gbActive = true;
#ifndef USE_SDL1
SDL_DisableScreenSaver();
#endif
}
void MainWndProc(const SDL_Event &event)
{
#ifndef USE_SDL1
#ifdef USE_SDL3
switch (event.type)
#else
if (event.type != SDL_WINDOWEVENT) return;
switch (event.window.event)
#endif
{
#ifdef USE_SDL3
case SDL_EVENT_WINDOW_HIDDEN:
case SDL_EVENT_WINDOW_MINIMIZED:
#else
case SDL_WINDOWEVENT_HIDDEN:
case SDL_WINDOWEVENT_MINIMIZED:
#endif
gbActive = false;
break;
#ifdef USE_SDL3
case SDL_EVENT_WINDOW_SHOWN:
case SDL_EVENT_WINDOW_EXPOSED:
case SDL_EVENT_WINDOW_RESTORED:
#else
case SDL_WINDOWEVENT_SHOWN:
case SDL_WINDOWEVENT_EXPOSED:
case SDL_WINDOWEVENT_RESTORED:
#endif
gbActive = true;
RedrawEverything();
break;
#ifdef USE_SDL3
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
#else
case SDL_WINDOWEVENT_SIZE_CHANGED:
#endif
ReinitializeHardwareCursor();
break;
#ifdef USE_SDL3
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
#else
case SDL_WINDOWEVENT_LEAVE:
#endif
sgbMouseDown = CLICK_NONE;
LastPlayerAction = PlayerActionType::None;
RedrawEverything();
break;
#ifdef USE_SDL3
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
#else
case SDL_WINDOWEVENT_CLOSE:
#endif
diablo_quit(0);
break;
#ifdef USE_SDL3
case SDL_EVENT_WINDOW_FOCUS_LOST:
#else
case SDL_WINDOWEVENT_FOCUS_LOST:
#endif
if (*GetOptions().Gameplay.pauseOnFocusLoss)
diablo_focus_pause();
break;
#ifdef USE_SDL3
case SDL_EVENT_WINDOW_FOCUS_GAINED:
#else
case SDL_WINDOWEVENT_FOCUS_GAINED:
#endif
if (*GetOptions().Gameplay.pauseOnFocusLoss)
diablo_focus_unpause();
break;
#ifdef USE_SDL3
default:
break;
#else
case SDL_WINDOWEVENT_MOVED:
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_MAXIMIZED:
case SDL_WINDOWEVENT_ENTER:
case SDL_WINDOWEVENT_TAKE_FOCUS:
break;
default:
LogVerbose("Unhandled SDL_WINDOWEVENT event: {:d}", event.window.event);
break;
#endif
}
#else
if (event.type != SDL_ACTIVEEVENT)
return;
if ((event.active.state & SDL_APPINPUTFOCUS) != 0) {
if (event.active.gain == 0)
diablo_focus_pause();
else
diablo_focus_unpause();
}
#endif
}
} // namespace devilution