|
|
|
|
/**
|
|
|
|
|
* @file init.cpp
|
|
|
|
|
*
|
|
|
|
|
* Implementation of routines for initializing the environment, disable screen saver, load MPQ.
|
|
|
|
|
*/
|
|
|
|
|
#include <SDL.h>
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
#if defined(_WIN64) || defined(_WIN32)
|
|
|
|
|
#include <find_steam_game.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "DiabloUI/diabloui.h"
|
|
|
|
|
#include "dx.h"
|
|
|
|
|
#include "options.h"
|
|
|
|
|
#include "pfile.h"
|
|
|
|
|
#include "storm/storm.h"
|
|
|
|
|
#include "storm/storm_sdl_rw.h"
|
|
|
|
|
#include "utils/language.h"
|
|
|
|
|
#include "utils/log.hpp"
|
|
|
|
|
#include "utils/paths.h"
|
|
|
|
|
#include "utils/ui_fwd.h"
|
|
|
|
|
|
|
|
|
|
#ifdef __vita__
|
|
|
|
|
// increase default allowed heap size on Vita
|
|
|
|
|
int _newlib_heap_size_user = 100 * 1024 * 1024;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
namespace devilution {
|
|
|
|
|
|
|
|
|
|
/** True if the game is the current active window */
|
|
|
|
|
bool gbActive;
|
|
|
|
|
/** A handle to an hellfire.mpq archive. */
|
|
|
|
|
HANDLE hellfire_mpq;
|
|
|
|
|
/** The current input handler function */
|
|
|
|
|
WNDPROC CurrentProc;
|
|
|
|
|
/** A handle to the spawn.mpq archive. */
|
|
|
|
|
HANDLE spawn_mpq;
|
|
|
|
|
/** A handle to the diabdat.mpq archive. */
|
|
|
|
|
HANDLE diabdat_mpq;
|
|
|
|
|
/** Indicate if we only have access to demo data */
|
|
|
|
|
bool gbIsSpawn;
|
|
|
|
|
/** Indicate if we have loaded the Hellfire expansion data */
|
|
|
|
|
bool gbIsHellfire;
|
|
|
|
|
/** Indicate if we want vanilla savefiles */
|
|
|
|
|
bool gbVanilla;
|
|
|
|
|
/** Whether the Hellfire mode is required (forced). */
|
|
|
|
|
bool forceHellfire;
|
|
|
|
|
HANDLE hfmonk_mpq;
|
|
|
|
|
HANDLE hfbard_mpq;
|
|
|
|
|
HANDLE hfbarb_mpq;
|
|
|
|
|
HANDLE hfmusic_mpq;
|
|
|
|
|
HANDLE hfvoice_mpq;
|
|
|
|
|
HANDLE devilutionx_mpq;
|
|
|
|
|
HANDLE lang_mpq;
|
|
|
|
|
HANDLE font_mpq;
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
HANDLE LoadMPQ(const std::vector<std::string> &paths, const char *mpqName)
|
|
|
|
|
{
|
|
|
|
|
HANDLE archive;
|
|
|
|
|
std::string mpqAbsPath;
|
|
|
|
|
for (const auto &path : paths) {
|
|
|
|
|
mpqAbsPath = path + mpqName;
|
|
|
|
|
if (SFileOpenArchive(mpqAbsPath.c_str(), 0, MPQ_OPEN_READ_ONLY, &archive)) {
|
|
|
|
|
LogVerbose(" Found: {} in {}", mpqName, path);
|
|
|
|
|
paths::SetMpqDir(path);
|
|
|
|
|
return archive;
|
|
|
|
|
}
|
|
|
|
|
if (SErrGetLastError() != STORM_ERROR_FILE_NOT_FOUND) {
|
|
|
|
|
LogError("Open error {}: {}", SErrGetLastError(), mpqAbsPath);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (SErrGetLastError() == STORM_ERROR_FILE_NOT_FOUND) {
|
|
|
|
|
LogVerbose("Missing: {}", mpqName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void init_cleanup()
|
|
|
|
|
{
|
|
|
|
|
if (gbIsMultiplayer && gbRunGame) {
|
|
|
|
|
pfile_write_hero(/*writeGameData=*/false, /*clearTables=*/true);
|
|
|
|
|
}
|
Clean up appfat.cpp (#585)
* Clean up appfat.cpp
GetErrorStr, TraceErrorDD, TraceErrorDS, TraceLastError, DDErrMsg,
DSErrMsg, ErrDlg, ErrOkDlg, DirErrorDlg, InsertCDDlg, FuncDlg,
init_cleanup, FreeDlg, center_window
* Fix style
7 years ago
|
|
|
|
|
|
|
|
if (spawn_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(spawn_mpq);
|
|
|
|
|
spawn_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (diabdat_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(diabdat_mpq);
|
|
|
|
|
diabdat_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (hellfire_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(hellfire_mpq);
|
|
|
|
|
hellfire_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (hfmonk_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(hfmonk_mpq);
|
|
|
|
|
hfmonk_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (hfbard_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(hfbard_mpq);
|
|
|
|
|
hfbard_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (hfbarb_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(hfbarb_mpq);
|
|
|
|
|
hfbarb_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (hfmusic_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(hfmusic_mpq);
|
|
|
|
|
hfmusic_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (hfvoice_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(hfvoice_mpq);
|
|
|
|
|
hfvoice_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (lang_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(lang_mpq);
|
|
|
|
|
lang_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (font_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(font_mpq);
|
|
|
|
|
font_mpq = nullptr;
|
|
|
|
|
}
|
|
|
|
|
if (devilutionx_mpq != nullptr) {
|
|
|
|
|
SFileCloseArchive(devilutionx_mpq);
|
|
|
|
|
devilutionx_mpq = nullptr;
|
|
|
|
|
}
|
Clean up appfat.cpp (#585)
* Clean up appfat.cpp
GetErrorStr, TraceErrorDD, TraceErrorDS, TraceLastError, DDErrMsg,
DSErrMsg, ErrDlg, ErrOkDlg, DirErrorDlg, InsertCDDlg, FuncDlg,
init_cleanup, FreeDlg, center_window
* Fix style
7 years ago
|
|
|
|
|
|
|
|
NetClose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void init_archives()
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::string> paths;
|
|
|
|
|
paths.push_back(paths::BasePath());
|
|
|
|
|
paths.push_back(paths::PrefPath());
|
|
|
|
|
if (paths[0] == paths[1])
|
|
|
|
|
paths.pop_back();
|
|
|
|
|
|
|
|
|
|
#if defined(__linux__) && !defined(__ANDROID__)
|
|
|
|
|
paths.emplace_back("/usr/share/diasurgical/devilutionx/");
|
|
|
|
|
paths.emplace_back("/usr/local/share/diasurgical/devilutionx/");
|
|
|
|
|
#elif defined(__3DS__)
|
|
|
|
|
paths.emplace_back("romfs:/");
|
|
|
|
|
#elif defined(_WIN64) || defined(_WIN32)
|
|
|
|
|
char gogpath[_FSG_PATH_MAX];
|
|
|
|
|
fsg_get_gog_game_path(gogpath, "1412601690");
|
|
|
|
|
if (strlen(gogpath) > 0) {
|
|
|
|
|
paths.emplace_back(std::string(gogpath) + "/");
|
|
|
|
|
paths.emplace_back(std::string(gogpath) + "/hellfire/");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
paths.emplace_back(""); // PWD
|
|
|
|
|
|
|
|
|
|
if (SDL_LOG_PRIORITY_VERBOSE >= SDL_LogGetPriority(SDL_LOG_CATEGORY_APPLICATION)) {
|
|
|
|
|
LogVerbose("Paths:\n base: {}\n pref: {}\n config: {}\n assets: {}",
|
|
|
|
|
paths::BasePath(), paths::PrefPath(), paths::ConfigPath(), paths::AssetsPath());
|
|
|
|
|
|
|
|
|
|
std::string message;
|
|
|
|
|
for (std::size_t i = 0; i < paths.size(); ++i) {
|
|
|
|
|
char prefix[32];
|
|
|
|
|
std::snprintf(prefix, sizeof(prefix), "\n%6u. '", static_cast<unsigned>(i + 1));
|
|
|
|
|
message.append(prefix);
|
|
|
|
|
message.append(paths[i]);
|
|
|
|
|
message += '\'';
|
|
|
|
|
}
|
|
|
|
|
LogVerbose("MPQ search paths:{}", message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef __ANDROID__
|
|
|
|
|
// Load devilutionx.mpq first to get the font file for error messages
|
|
|
|
|
devilutionx_mpq = LoadMPQ(paths, "devilutionx.mpq");
|
|
|
|
|
#endif
|
|
|
|
|
font_mpq = LoadMPQ(paths, "fonts.mpq"); // Extra fonts
|
|
|
|
|
|
|
|
|
|
if (strcasecmp("en", sgOptions.Language.szCode) != 0 || strlen(sgOptions.Language.szCode) != 2) {
|
|
|
|
|
char langMpqName[10] = {};
|
|
|
|
|
strncpy(langMpqName, sgOptions.Language.szCode, sizeof(langMpqName) - strlen(langMpqName) - 1);
|
|
|
|
|
|
|
|
|
|
strncat(langMpqName, ".mpq", sizeof(langMpqName) - strlen(langMpqName) - 1);
|
|
|
|
|
lang_mpq = LoadMPQ(paths, langMpqName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diabdat_mpq = LoadMPQ(paths, "DIABDAT.MPQ");
|
|
|
|
|
if (diabdat_mpq == nullptr) {
|
|
|
|
|
// DIABDAT.MPQ is uppercase on the original CD and the GOG version.
|
|
|
|
|
diabdat_mpq = LoadMPQ(paths, "diabdat.mpq");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (diabdat_mpq == nullptr) {
|
|
|
|
|
spawn_mpq = LoadMPQ(paths, "spawn.mpq");
|
|
|
|
|
if (spawn_mpq != nullptr)
|
|
|
|
|
gbIsSpawn = true;
|
|
|
|
|
}
|
|
|
|
|
SDL_RWops *handle = SFileOpenRw("ui_art\\title.pcx");
|
|
|
|
|
if (handle == nullptr)
|
|
|
|
|
InsertCDDlg(_("diabdat.mpq or spawn.mpq"));
|
|
|
|
|
SDL_RWclose(handle);
|
|
|
|
|
|
|
|
|
|
hellfire_mpq = LoadMPQ(paths, "hellfire.mpq");
|
|
|
|
|
if (hellfire_mpq != nullptr)
|
|
|
|
|
gbIsHellfire = true;
|
|
|
|
|
if (forceHellfire && hellfire_mpq == nullptr)
|
|
|
|
|
InsertCDDlg("hellfire.mpq");
|
|
|
|
|
|
|
|
|
|
hfmonk_mpq = LoadMPQ(paths, "hfmonk.mpq");
|
|
|
|
|
hfbard_mpq = LoadMPQ(paths, "hfbard.mpq");
|
|
|
|
|
if (hfbard_mpq != nullptr)
|
|
|
|
|
gbBard = true;
|
|
|
|
|
hfbarb_mpq = LoadMPQ(paths, "hfbarb.mpq");
|
|
|
|
|
if (hfbarb_mpq != nullptr)
|
|
|
|
|
gbBarbarian = true;
|
|
|
|
|
hfmusic_mpq = LoadMPQ(paths, "hfmusic.mpq");
|
|
|
|
|
hfvoice_mpq = LoadMPQ(paths, "hfvoice.mpq");
|
|
|
|
|
|
|
|
|
|
if (gbIsHellfire && (hfmonk_mpq == nullptr || hfmusic_mpq == nullptr || hfvoice_mpq == nullptr)) {
|
|
|
|
|
UiErrorOkDialog(_("Some Hellfire MPQs are missing"), _("Not all Hellfire MPQs were found.\nPlease copy all the hf*.mpq files."));
|
|
|
|
|
app_fatal(nullptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void init_create_window()
|
|
|
|
|
{
|
|
|
|
|
if (!SpawnWindow(PROJECT_NAME))
|
|
|
|
|
app_fatal("%s", _("Unable to create main window"));
|
|
|
|
|
dx_init();
|
|
|
|
|
gbActive = true;
|
|
|
|
|
#ifndef USE_SDL1
|
|
|
|
|
SDL_DisableScreenSaver();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MainWndProc(uint32_t msg)
|
|
|
|
|
{
|
|
|
|
|
switch (msg) {
|
|
|
|
|
case DVL_WM_PAINT:
|
|
|
|
|
force_redraw = 255;
|
|
|
|
|
break;
|
|
|
|
|
case DVL_WM_QUERYENDSESSION:
|
|
|
|
|
diablo_quit(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WNDPROC SetWindowProc(WNDPROC newProc)
|
|
|
|
|
{
|
|
|
|
|
WNDPROC oldProc;
|
|
|
|
|
|
|
|
|
|
oldProc = CurrentProc;
|
|
|
|
|
CurrentProc = newProc;
|
|
|
|
|
return oldProc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace devilution
|