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.
 
 
 
 
 
 

195 lines
4.6 KiB

/**
* @file init.cpp
*
* Implementation of routines for initializing the environment, disable screen saver, load MPQ.
*/
#include "init.hpp"
#include <cstdint>
#include <string>
#include <vector>
#include <SDL.h>
#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_common.hpp"
#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;
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";
const MpqFileHash fileHash = CalculateMpqFileHash(filename);
uint32_t fileNumber;
if (!archive.GetFileNumber(fileHash, fileNumber))
return true;
AssetRef ref;
ref.archive = &archive;
ref.fileNumber = fileNumber;
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);
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
if (event.type != SDL_WINDOWEVENT)
return;
switch (event.window.event) {
case SDL_WINDOWEVENT_HIDDEN:
case SDL_WINDOWEVENT_MINIMIZED:
gbActive = false;
break;
case SDL_WINDOWEVENT_SHOWN:
case SDL_WINDOWEVENT_EXPOSED:
case SDL_WINDOWEVENT_RESTORED:
gbActive = true;
RedrawEverything();
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
ReinitializeHardwareCursor();
break;
case SDL_WINDOWEVENT_LEAVE:
sgbMouseDown = CLICK_NONE;
LastPlayerAction = PlayerActionType::None;
RedrawEverything();
break;
case SDL_WINDOWEVENT_CLOSE:
diablo_quit(0);
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
if (*GetOptions().Gameplay.pauseOnFocusLoss)
diablo_focus_pause();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
if (*GetOptions().Gameplay.pauseOnFocusLoss)
diablo_focus_unpause();
break;
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;
}
#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