1 /**
2 * @file appfat.cpp
3 *
4 * Implementation of error dialogs.
5 */
6 #include "all.h"
7 #include "../3rdParty/Storm/Source/storm.h"
8 #include <config.h>
9
10 DEVILUTION_BEGIN_NAMESPACE
11
12 /** Set to true when a fatal error is encountered and the application should shut down. */
13 BOOL terminating;
14 /** Thread id of the last callee to FreeDlg(). */
15 SDL_threadID cleanup_thread_id;
16
17 /**
18 * @brief Displays an error message box based on the given format string and variable argument list.
19 * @param pszFmt Error message format
20 * @param va Additional parameters for message format
21 */
MsgBox(const char * pszFmt,va_list va)22 static void MsgBox(const char *pszFmt, va_list va)
23 {
24 char text[256];
25
26 vsnprintf(text, 256, pszFmt, va);
27
28 UiErrorOkDialog("Error", text);
29 }
30
31 /**
32 * @brief Cleans up after a fatal application error.
33 */
FreeDlg()34 static void FreeDlg()
35 {
36 if (terminating && cleanup_thread_id != SDL_GetThreadID(NULL))
37 SDL_Delay(20000);
38
39 terminating = TRUE;
40 cleanup_thread_id = SDL_GetThreadID(NULL);
41
42 if (gbIsMultiplayer) {
43 if (SNetLeaveGame(3))
44 SDL_Delay(2000);
45 }
46
47 SNetDestroy();
48 }
49
50 /**
51 * @brief Terminates the game and displays an error message box.
52 * @param pszFmt Optional error message.
53 * @param ... (see printf)
54 */
app_fatal(const char * pszFmt,...)55 void app_fatal(const char *pszFmt, ...)
56 {
57 va_list va;
58
59 va_start(va, pszFmt);
60 FreeDlg();
61
62 if (pszFmt)
63 MsgBox(pszFmt, va);
64
65 va_end(va);
66
67 diablo_quit(1);
68 }
69
70 /**
71 * @brief Displays a warning message box based on the given formatted error message.
72 * @param pszFmt Error message format
73 * @param ... Additional parameters for message format
74 */
DrawDlg(const char * pszFmt,...)75 void DrawDlg(const char *pszFmt, ...)
76 {
77 char text[256];
78 va_list va;
79
80 va_start(va, pszFmt);
81 vsnprintf(text, 256, pszFmt, va);
82 va_end(va);
83
84 UiErrorOkDialog(PROJECT_NAME, text, false);
85 }
86
87 #ifdef _DEBUG
88 /**
89 * @brief Show an error and exit the application.
90 * @param nLineNo The line number of the assertion
91 * @param pszFile File name where the assertion is located
92 * @param pszFail Fail message
93 */
assert_fail(int nLineNo,const char * pszFile,const char * pszFail)94 void assert_fail(int nLineNo, const char *pszFile, const char *pszFail)
95 {
96 app_fatal("assertion failed (%s:%d)\n%s", pszFile, nLineNo, pszFail);
97 }
98 #endif
99
100 /**
101 * @brief Terminates the game and displays an error dialog box based on the given dialog_id.
102 */
ErrDlg(const char * title,const char * error,const char * log_file_path,int log_line_nr)103 void ErrDlg(const char *title, const char *error, const char *log_file_path, int log_line_nr)
104 {
105 char text[1024];
106
107 FreeDlg();
108
109 snprintf(text, 1024, "%s\n\nThe error occurred at: %s line %d", error, log_file_path, log_line_nr);
110
111 UiErrorOkDialog(title, text);
112 app_fatal(NULL);
113 }
114
115 /**
116 * @brief Terminates the game with a file not found error dialog.
117 */
FileErrDlg(const char * error)118 void FileErrDlg(const char *error)
119 {
120 char text[1024];
121
122 FreeDlg();
123
124 if (!error)
125 error = "";
126 snprintf(
127 text,
128 1024,
129 "Unable to open a required file.\n"
130 "\n"
131 "Verify that the MD5 of diabdat.mpq matches one of the following values\n"
132 "011bc6518e6166206231080a4440b373\n"
133 "68f049866b44688a7af65ba766bef75a\n"
134 "\n"
135 "The problem occurred when loading:\n%s",
136 error);
137
138 UiErrorOkDialog("Data File Error", text);
139 app_fatal(NULL);
140 }
141
142 /**
143 * @brief Terminates the game with an insert CD error dialog.
144 */
InsertCDDlg()145 void InsertCDDlg()
146 {
147 char text[1024];
148 snprintf(
149 text,
150 1024,
151 "Unable to open main data archive (diabdat.mpq or spawn.mpq).\n"
152 "\n"
153 "Make sure that it is in the game folder and that the file name is in all lowercase.");
154
155 UiErrorOkDialog("Data File Error", text);
156 app_fatal(NULL);
157 }
158
159 /**
160 * @brief Terminates the game with a read-only directory error dialog.
161 */
DirErrorDlg(const char * error)162 void DirErrorDlg(const char *error)
163 {
164 char text[1024];
165
166 snprintf(text, 1024, "Unable to write to location:\n%s", error);
167
168 UiErrorOkDialog("Read-Only Directory Error", text);
169 app_fatal(NULL);
170 }
171
172 DEVILUTION_END_NAMESPACE
173