1 /**
2  * @file init.cpp
3  *
4  * Implementation of routines for initializing the environment, disable screen saver, load MPQ.
5  */
6 #include <string>
7 #include <vector>
8 
9 #include "all.h"
10 #include "paths.h"
11 #include "../3rdParty/Storm/Source/storm.h"
12 #include "../DiabloUI/diabloui.h"
13 #include <SDL.h>
14 #include <config.h>
15 
16 #ifdef __vita__
17 // increase default allowed heap size on Vita
18 int _newlib_heap_size_user = 100 * 1024 * 1024;
19 #endif
20 
21 DEVILUTION_BEGIN_NAMESPACE
22 
23 _SNETVERSIONDATA fileinfo;
24 /** True if the game is the current active window */
25 int gbActive;
26 /** A handle to an hellfire.mpq archive. */
27 HANDLE hellfire_mpq;
28 /** The current input handler function */
29 WNDPROC CurrentProc;
30 /** A handle to the spawn.mpq archive. */
31 HANDLE spawn_mpq;
32 /** A handle to the diabdat.mpq archive. */
33 HANDLE diabdat_mpq;
34 /** A handle to the patch_rt.mpq archive. */
35 HANDLE patch_rt_mpq;
36 /** Indicate if we only have access to demo data */
37 bool gbIsSpawn;
38 /** Indicate if we have loaded the Hellfire expansion data */
39 bool gbIsHellfire;
40 /** Indicate if we want vanilla savefiles */
41 bool gbVanilla;
42 HANDLE hfmonk_mpq;
43 HANDLE hfbard_mpq;
44 HANDLE hfbarb_mpq;
45 HANDLE hfmusic_mpq;
46 HANDLE hfvoice_mpq;
47 HANDLE hfopt1_mpq;
48 HANDLE hfopt2_mpq;
49 HANDLE devilutionx_mpq;
50 
51 namespace {
52 
init_test_access(const std::vector<std::string> & paths,const char * mpq_name,const char * reg_loc,int dwPriority,int fs)53 HANDLE init_test_access(const std::vector<std::string> &paths, const char *mpq_name, const char *reg_loc, int dwPriority, int fs)
54 {
55 	HANDLE archive;
56 	std::string mpq_abspath;
57 	DWORD mpq_flags = 0;
58 #if !defined(__SWITCH__) && !defined(__AMIGA__) && !defined(__vita__)
59 	mpq_flags |= MPQ_FLAG_READ_ONLY;
60 #endif
61 	for (int i = 0; i < paths.size(); i++) {
62 		mpq_abspath = paths[i] + mpq_name;
63 		if (SFileOpenArchive(mpq_abspath.c_str(), dwPriority, mpq_flags, &archive)) {
64 			SFileSetBasePath(paths[i].c_str());
65 			return archive;
66 		}
67 	}
68 
69 	return NULL;
70 }
71 
72 } // namespace
73 
74 /* data */
75 
76 char gszVersionNumber[64] = "internal version unknown";
77 char gszProductName[64] = "DevilutionX vUnknown";
78 
init_cleanup()79 void init_cleanup()
80 {
81 	if (gbIsMultiplayer && gbRunGame) {
82 		pfile_write_hero();
83 	}
84 	pfile_flush_W();
85 
86 	if (spawn_mpq) {
87 		SFileCloseArchive(spawn_mpq);
88 		spawn_mpq = NULL;
89 	}
90 	if (diabdat_mpq) {
91 		SFileCloseArchive(diabdat_mpq);
92 		diabdat_mpq = NULL;
93 	}
94 	if (patch_rt_mpq) {
95 		SFileCloseArchive(patch_rt_mpq);
96 		patch_rt_mpq = NULL;
97 	}
98 	if (hellfire_mpq) {
99 		SFileCloseArchive(hellfire_mpq);
100 		hellfire_mpq = NULL;
101 	}
102 	if (hfmonk_mpq) {
103 		SFileCloseArchive(hfmonk_mpq);
104 		hfmonk_mpq = NULL;
105 	}
106 	if (hfbard_mpq) {
107 		SFileCloseArchive(hfbard_mpq);
108 		hfbard_mpq = NULL;
109 	}
110 	if (hfbarb_mpq) {
111 		SFileCloseArchive(hfbarb_mpq);
112 		hfbarb_mpq = NULL;
113 	}
114 	if (hfmusic_mpq) {
115 		SFileCloseArchive(hfmusic_mpq);
116 		hfmusic_mpq = NULL;
117 	}
118 	if (hfvoice_mpq) {
119 		SFileCloseArchive(hfvoice_mpq);
120 		hfvoice_mpq = NULL;
121 	}
122 	if (hfopt1_mpq) {
123 		SFileCloseArchive(hfopt1_mpq);
124 		hfopt1_mpq = NULL;
125 	}
126 	if (hfopt2_mpq) {
127 		SFileCloseArchive(hfopt2_mpq);
128 		hfopt2_mpq = NULL;
129 	}
130 	if (devilutionx_mpq) {
131 		SFileCloseArchive(patch_rt_mpq);
132 		patch_rt_mpq = NULL;
133 	}
134 
135 	NetClose();
136 }
137 
init_get_file_info()138 static void init_get_file_info()
139 {
140 	snprintf(gszProductName, sizeof(gszProductName) / sizeof(char), "%s v%s", PROJECT_NAME, PROJECT_VERSION);
141 	snprintf(gszVersionNumber, sizeof(gszVersionNumber) / sizeof(char), "version %s", PROJECT_VERSION);
142 }
143 
init_archives()144 void init_archives()
145 {
146 	HANDLE fh = NULL;
147 	memset(&fileinfo, 0, sizeof(fileinfo));
148 	fileinfo.size = sizeof(fileinfo);
149 	fileinfo.versionstring = gszVersionNumber;
150 	init_get_file_info();
151 
152 	std::vector<std::string> paths;
153 	paths.reserve(5);
154 	paths.push_back(GetBasePath());
155 	paths.push_back(GetPrefPath());
156 	if (paths[0] == paths[1])
157 		paths.pop_back();
158 
159 #ifdef __linux__
160 	paths.push_back("/usr/share/diasurgical/devilutionx/");
161 	paths.push_back("/usr/local/share/diasurgical/devilutionx/");
162 #endif
163 
164 	paths.push_back(""); // PWD
165 
166 	diabdat_mpq = init_test_access(paths, "DIABDAT.MPQ", "DiabloCD", 1000, FS_CD);
167 	if (diabdat_mpq == NULL) {
168 		// DIABDAT.MPQ is uppercase on the original CD and the GOG version.
169 		diabdat_mpq = init_test_access(paths, "diabdat.mpq", "DiabloCD", 1000, FS_CD);
170 	}
171 
172 	if (diabdat_mpq == NULL) {
173 		spawn_mpq = init_test_access(paths, "spawn.mpq", "DiabloSpawn", 1000, FS_PC);
174 		if (spawn_mpq != NULL)
175 			gbIsSpawn = true;
176 	}
177 	if (!SFileOpenFile("ui_art\\title.pcx", &fh))
178 		InsertCDDlg();
179 	SFileCloseFile(fh);
180 
181 	patch_rt_mpq = init_test_access(paths, "patch_rt.mpq", "DiabloInstall", 2000, FS_PC);
182 	if (patch_rt_mpq == NULL)
183 		patch_rt_mpq = init_test_access(paths, "patch_sh.mpq", "DiabloSpawn", 2000, FS_PC);
184 
185 	hellfire_mpq = init_test_access(paths, "hellfire.mpq", "DiabloInstall", 8000, FS_PC);
186 	if (hellfire_mpq != NULL)
187 		gbIsHellfire = true;
188 	hfmonk_mpq = init_test_access(paths, "hfmonk.mpq", "DiabloInstall", 8100, FS_PC);
189 	hfbard_mpq = init_test_access(paths, "hfbard.mpq", "DiabloInstall", 8110, FS_PC);
190 	if (hfbard_mpq != NULL)
191 		gbBard = true;
192 	hfbarb_mpq = init_test_access(paths, "hfbarb.mpq", "DiabloInstall", 8120, FS_PC);
193 	if (hfbarb_mpq != NULL)
194 		gbBarbarian = true;
195 	hfmusic_mpq = init_test_access(paths, "hfmusic.mpq", "DiabloInstall", 8200, FS_PC);
196 	hfvoice_mpq = init_test_access(paths, "hfvoice.mpq", "DiabloInstall", 8500, FS_PC);
197 	hfopt1_mpq = init_test_access(paths, "hfopt1.mpq", "DiabloInstall", 8600, FS_PC);
198 	hfopt2_mpq = init_test_access(paths, "hfopt2.mpq", "DiabloInstall", 8610, FS_PC);
199 
200 	if (gbIsHellfire && (hfmonk_mpq == NULL || hfmusic_mpq == NULL || hfvoice_mpq == NULL)) {
201 		UiErrorOkDialog("Some Hellfire MPQs are missing", "Not all Hellfire MPQs were found.\nPlease copy all the hf*.mpq files.");
202 		app_fatal(NULL);
203 	}
204 
205 	devilutionx_mpq = init_test_access(paths, "devilutionx.mpq", "DiabloInstall", 9000, FS_PC);
206 }
207 
init_create_window()208 void init_create_window()
209 {
210 	if (!SpawnWindow(PROJECT_NAME))
211 		app_fatal("Unable to create main window");
212 	dx_init();
213 	gbActive = true;
214 	SDL_DisableScreenSaver();
215 }
216 
MainWndProc(UINT Msg,WPARAM wParam,LPARAM lParam)217 void MainWndProc(UINT Msg, WPARAM wParam, LPARAM lParam)
218 {
219 	switch (Msg) {
220 	case DVL_WM_PAINT:
221 		force_redraw = 255;
222 		break;
223 	case DVL_WM_QUERYENDSESSION:
224 		diablo_quit(0);
225 		break;
226 	}
227 }
228 
SetWindowProc(WNDPROC NewProc)229 WNDPROC SetWindowProc(WNDPROC NewProc)
230 {
231 	WNDPROC OldProc;
232 
233 	OldProc = CurrentProc;
234 	CurrentProc = NewProc;
235 	return OldProc;
236 }
237 
238 DEVILUTION_END_NAMESPACE
239