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 } |