--- a/src/demo.cpp Fri Jun 05 18:33:51 2015 +0300 +++ b/src/demo.cpp Fri Jun 05 19:13:44 2015 +0300 @@ -74,15 +74,21 @@ // ------------------------------------------------------------------------------------------------- // -static bool isKnownVersion (QString ver) +static ZandronumVersion findVersion (QString versionName) { for (const QVariant& it : getVersions()) { - if (it.toString() == ver || it.toString() + 'M' == ver) - return true; + ZandronumVersion version = it.value<ZandronumVersion>(); + + if (version.name == versionName + or version.name + "M" == versionName + or version.name == versionName + "M") + { + return version; + } } - return false; + return ZandronumVersion(); } // @@ -149,6 +155,15 @@ uint8 connectionType; }; +struct DemoHeaders +{ + uint8 length; + uint8 version; + uint8 userInfo; + uint8 bodyStart; + uint8 wads; +}; + int launchDemo (QString path) { QFile f (path); @@ -161,8 +176,8 @@ QDataStream stream (&f); stream.setByteOrder (QDataStream::LittleEndian); - - uint8 offset; + + DemoHeaders headers; uint32 length; uint16 zanversionID, numWads; uint32 longSink; @@ -188,12 +203,15 @@ return 1; } } - - // Zandronum stores CLD_DEMOLENGTH after the signature. This is also the - // first demo enumerator, so we can determine the offset (which is variable!) - // from this byte - stream >> offset + + stream >> headers.length >> length; + + // The remaining headers are variable and relative to the length header. + headers.version = headers.length + 1; + headers.userInfo = headers.length + 3, + headers.bodyStart = headers.length + 4; + headers.wads = headers.length + 10; // Read the demo header and get data for (;;) @@ -201,12 +219,12 @@ uint8 header; stream >> header; - if (header == DemoBodyStart + offset) + if (header == headers.bodyStart) { ready = true; break; } - else if (header == DemoVersion + offset) + else if (header == headers.version) { stream >> zanversionID; zanversion = readString (stream); @@ -218,9 +236,13 @@ buildID = (BuildType) a; } + // The demo wads header accidentally changed in 1.3. :( + if (zanversion.left(1).toInt() >= 2 or zanversion.startsWith ("1.3")) + headers.wads = headers.length + 8; + stream >> longSink; // rng seed - we don't need it } - else if (header == DemoUserInfo + offset) + else if (header == headers.userInfo) { userinfo.netname = readString (stream); stream >> userinfo.gender; @@ -235,20 +257,19 @@ stream >> userinfo.connectionType; userinfo.className = readString (stream); } - else if (header == DemoWads + offset) + else if (header == headers.wads) { QString sink; stream >> numWads; - for (uint8 i = 0; i < numWads; ++i) { + for (uint8 i = 0; i < numWads; ++i) + { QString wad = readString (stream); wads << wad; } - // The demo has two checksum strings. We're not interested - // in them though. Down the sink they go... - for (int i = 0; i < 2; ++i) - sink = readString (stream); + // The demo has two checksum strings. We're not interested in them, though. + (sink = readString (stream)) = readString (stream); } else { @@ -262,22 +283,16 @@ error (tr ("Incomplete demo header in '%s'!").arg (path)); return 1; } - - if (not isKnownVersion (zanversion)) + + ZandronumVersion version = findVersion (zanversion); + + if (version.name.isNull()) { QDialog* prompt = new UnknownVersionPrompt (path, zanversion, (buildID == ReleaseBuild)); if (not prompt->exec()) return 1; } - - QString binarypath = Config::get ("binarypaths").toMap()[zanversion].toString(); - - if (binarypath.isEmpty()) - { - error (tr ("No binary path specified for Zandronum version %1!").arg (zanversion)); - return 1; - } QString iwadpath; QStringList pwadpaths; @@ -341,7 +356,7 @@ // print ("Executing: %1 %2\n", binarypath, cmdlineList.join (" ")); QProcess* proc = new QProcess; - proc->start (binarypath, cmdlineList); + proc->start (version.binaryPath, cmdlineList); proc->waitForFinished (-1); return 0; }