| 72 |
72 |
| 73 // |
73 // |
| 74 // ------------------------------------------------------------------------------------------------- |
74 // ------------------------------------------------------------------------------------------------- |
| 75 // |
75 // |
| 76 |
76 |
| 77 static bool isKnownVersion (QString ver) |
77 static ZandronumVersion findVersion (QString versionName) |
| 78 { |
78 { |
| 79 for (const QVariant& it : getVersions()) |
79 for (const QVariant& it : getVersions()) |
| 80 { |
80 { |
| 81 if (it.toString() == ver || it.toString() + 'M' == ver) |
81 ZandronumVersion version = it.value<ZandronumVersion>(); |
| 82 return true; |
82 |
| 83 } |
83 if (version.name == versionName |
| 84 |
84 or version.name + "M" == versionName |
| 85 return false; |
85 or version.name == versionName + "M") |
| |
86 { |
| |
87 return version; |
| |
88 } |
| |
89 } |
| |
90 |
| |
91 return ZandronumVersion(); |
| 86 } |
92 } |
| 87 |
93 |
| 88 // |
94 // |
| 89 // ------------------------------------------------------------------------------------------------- |
95 // ------------------------------------------------------------------------------------------------- |
| 90 // |
96 // |
| 186 { |
201 { |
| 187 error (tr ("'%1' is not a valid Zandronum demo file!").arg (path)); |
202 error (tr ("'%1' is not a valid Zandronum demo file!").arg (path)); |
| 188 return 1; |
203 return 1; |
| 189 } |
204 } |
| 190 } |
205 } |
| 191 |
206 |
| 192 // Zandronum stores CLD_DEMOLENGTH after the signature. This is also the |
207 stream >> headers.length |
| 193 // first demo enumerator, so we can determine the offset (which is variable!) |
|
| 194 // from this byte |
|
| 195 stream >> offset |
|
| 196 >> length; |
208 >> length; |
| |
209 |
| |
210 // The remaining headers are variable and relative to the length header. |
| |
211 headers.version = headers.length + 1; |
| |
212 headers.userInfo = headers.length + 3, |
| |
213 headers.bodyStart = headers.length + 4; |
| |
214 headers.wads = headers.length + 10; |
| 197 |
215 |
| 198 // Read the demo header and get data |
216 // Read the demo header and get data |
| 199 for (;;) |
217 for (;;) |
| 200 { |
218 { |
| 201 uint8 header; |
219 uint8 header; |
| 202 stream >> header; |
220 stream >> header; |
| 203 |
221 |
| 204 if (header == DemoBodyStart + offset) |
222 if (header == headers.bodyStart) |
| 205 { |
223 { |
| 206 ready = true; |
224 ready = true; |
| 207 break; |
225 break; |
| 208 } |
226 } |
| 209 else if (header == DemoVersion + offset) |
227 else if (header == headers.version) |
| 210 { |
228 { |
| 211 stream >> zanversionID; |
229 stream >> zanversionID; |
| 212 zanversion = readString (stream); |
230 zanversion = readString (stream); |
| 213 |
231 |
| 214 if (not zanversion.startsWith ("1.1-") and not zanversion.startsWith ("1.1.1-")) |
232 if (not zanversion.startsWith ("1.1-") and not zanversion.startsWith ("1.1.1-")) |
| 216 uint8 a; |
234 uint8 a; |
| 217 stream >> a; |
235 stream >> a; |
| 218 buildID = (BuildType) a; |
236 buildID = (BuildType) a; |
| 219 } |
237 } |
| 220 |
238 |
| |
239 // The demo wads header accidentally changed in 1.3. :( |
| |
240 if (zanversion.left(1).toInt() >= 2 or zanversion.startsWith ("1.3")) |
| |
241 headers.wads = headers.length + 8; |
| |
242 |
| 221 stream >> longSink; // rng seed - we don't need it |
243 stream >> longSink; // rng seed - we don't need it |
| 222 } |
244 } |
| 223 else if (header == DemoUserInfo + offset) |
245 else if (header == headers.userInfo) |
| 224 { |
246 { |
| 225 userinfo.netname = readString (stream); |
247 userinfo.netname = readString (stream); |
| 226 stream >> userinfo.gender; |
248 stream >> userinfo.gender; |
| 227 stream >> userinfo.color; |
249 stream >> userinfo.color; |
| 228 stream >> userinfo.aimdist; |
250 stream >> userinfo.aimdist; |
| 233 stream >> userinfo.respawnOnFire; |
255 stream >> userinfo.respawnOnFire; |
| 234 stream >> userinfo.ticsPerUpdate; |
256 stream >> userinfo.ticsPerUpdate; |
| 235 stream >> userinfo.connectionType; |
257 stream >> userinfo.connectionType; |
| 236 userinfo.className = readString (stream); |
258 userinfo.className = readString (stream); |
| 237 } |
259 } |
| 238 else if (header == DemoWads + offset) |
260 else if (header == headers.wads) |
| 239 { |
261 { |
| 240 QString sink; |
262 QString sink; |
| 241 stream >> numWads; |
263 stream >> numWads; |
| 242 |
264 |
| 243 for (uint8 i = 0; i < numWads; ++i) { |
265 for (uint8 i = 0; i < numWads; ++i) |
| |
266 { |
| 244 QString wad = readString (stream); |
267 QString wad = readString (stream); |
| 245 wads << wad; |
268 wads << wad; |
| 246 } |
269 } |
| 247 |
270 |
| 248 // The demo has two checksum strings. We're not interested |
271 // The demo has two checksum strings. We're not interested in them, though. |
| 249 // in them though. Down the sink they go... |
272 (sink = readString (stream)) = readString (stream); |
| 250 for (int i = 0; i < 2; ++i) |
|
| 251 sink = readString (stream); |
|
| 252 } |
273 } |
| 253 else |
274 else |
| 254 { |
275 { |
| 255 error (tr ("Unknown header %1!\n").arg (int (header))); |
276 error (tr ("Unknown header %1!\n").arg (int (header))); |
| 256 return 1; |
277 return 1; |
| 260 if (not ready) |
281 if (not ready) |
| 261 { |
282 { |
| 262 error (tr ("Incomplete demo header in '%s'!").arg (path)); |
283 error (tr ("Incomplete demo header in '%s'!").arg (path)); |
| 263 return 1; |
284 return 1; |
| 264 } |
285 } |
| 265 |
286 |
| 266 if (not isKnownVersion (zanversion)) |
287 ZandronumVersion version = findVersion (zanversion); |
| |
288 |
| |
289 if (version.name.isNull()) |
| 267 { |
290 { |
| 268 QDialog* prompt = new UnknownVersionPrompt (path, zanversion, (buildID == ReleaseBuild)); |
291 QDialog* prompt = new UnknownVersionPrompt (path, zanversion, (buildID == ReleaseBuild)); |
| 269 |
292 |
| 270 if (not prompt->exec()) |
293 if (not prompt->exec()) |
| 271 return 1; |
294 return 1; |
| 272 } |
|
| 273 |
|
| 274 QString binarypath = Config::get ("binarypaths").toMap()[zanversion].toString(); |
|
| 275 |
|
| 276 if (binarypath.isEmpty()) |
|
| 277 { |
|
| 278 error (tr ("No binary path specified for Zandronum version %1!").arg (zanversion)); |
|
| 279 return 1; |
|
| 280 } |
295 } |
| 281 |
296 |
| 282 QString iwadpath; |
297 QString iwadpath; |
| 283 QStringList pwadpaths; |
298 QStringList pwadpaths; |
| 284 |
299 |
| 339 if (pwadpaths.size() > 0) |
354 if (pwadpaths.size() > 0) |
| 340 cmdlineList << "-file" << pwadpaths; |
355 cmdlineList << "-file" << pwadpaths; |
| 341 |
356 |
| 342 // print ("Executing: %1 %2\n", binarypath, cmdlineList.join (" ")); |
357 // print ("Executing: %1 %2\n", binarypath, cmdlineList.join (" ")); |
| 343 QProcess* proc = new QProcess; |
358 QProcess* proc = new QProcess; |
| 344 proc->start (binarypath, cmdlineList); |
359 proc->start (version.binaryPath, cmdlineList); |
| 345 proc->waitForFinished (-1); |
360 proc->waitForFinished (-1); |
| 346 return 0; |
361 return 0; |
| 347 } |
362 } |