From 6f30239ce3dd28fb6caeffbf7a4a15b113264516 Mon Sep 17 00:00:00 2001 From: danij Date: Wed, 1 Oct 2014 22:02:14 +0100 Subject: [PATCH] DehReader: Added support for [Strings] replacement in BEX patches --- doomsday/plugins/dehread/src/dehreader.cpp | 150 +++++++++++++++------ 1 file changed, 109 insertions(+), 41 deletions(-) diff --git a/doomsday/plugins/dehread/src/dehreader.cpp b/doomsday/plugins/dehread/src/dehreader.cpp index 30edca4d21..5afc4cc42c 100644 --- a/doomsday/plugins/dehread/src/dehreader.cpp +++ b/doomsday/plugins/dehread/src/dehreader.cpp @@ -262,7 +262,7 @@ class DehReader try { /// @note Some sections have their own grammar quirks! - if(line.beginsWith("include", Qt::CaseInsensitive)) // .bex + if(line.beginsWith("include", Qt::CaseInsensitive)) // BEX { parseInclude(line.substr(7).leftStrip()); skipToNextSection(); @@ -411,46 +411,44 @@ class DehReader LOG_WARNING("[Cheat] patches are not supported."); skipToNextSection(); } - else if(line.beginsWith("[CODEPTR]", Qt::CaseInsensitive)) // .bex + else if(line.beginsWith("[CODEPTR]", Qt::CaseInsensitive)) // BEX { skipToNextLine(); - parsePointerBex(); + parseCodePointers(); } - else if(line.beginsWith("[PARS]", Qt::CaseInsensitive)) // .bex + else if(line.beginsWith("[PARS]", Qt::CaseInsensitive)) // BEX { skipToNextLine(); - parseParsBex(); + parsePars(); } - else if(line.beginsWith("[STRINGS]", Qt::CaseInsensitive)) // .bex + else if(line.beginsWith("[STRINGS]", Qt::CaseInsensitive)) // BEX { - // Not yet supported. - //skipToNextLine(); - parseStringsBex(); - skipToNextSection(); + skipToNextLine(); + parseStrings(); } - else if(line.beginsWith("[HELPER]", Qt::CaseInsensitive)) // .bex + else if(line.beginsWith("[HELPER]", Qt::CaseInsensitive)) // BEX { // Not yet supported (Helper Dogs from MBF). //skipToNextLine(); - parseHelperBex(); + parseHelper(); skipToNextSection(); } - else if(line.beginsWith("[SPRITES]", Qt::CaseInsensitive)) // .bex + else if(line.beginsWith("[SPRITES]", Qt::CaseInsensitive)) // BEX { // Not yet supported. //skipToNextLine(); - parseSpritesBex(); + parseSprites(); skipToNextSection(); } - else if(line.beginsWith("[SOUNDS]", Qt::CaseInsensitive)) // .bex + else if(line.beginsWith("[SOUNDS]", Qt::CaseInsensitive)) // BEX { skipToNextLine(); - parseSoundsBex(); + parseSounds(); } - else if(line.beginsWith("[MUSIC]", Qt::CaseInsensitive)) // .bex + else if(line.beginsWith("[MUSIC]", Qt::CaseInsensitive)) // BEX { skipToNextLine(); - parseMusicBex(); + parseMusic(); } else { @@ -726,7 +724,7 @@ class DehReader continue; } - // Flags can also be specified by name (a .bex extension). + // Flags can also be specified by name (a BEX extension). FlagMapping const *flag; if(parseMobjTypeFlag(token, &flag)) { @@ -1396,10 +1394,10 @@ class DehReader } } - void parseParsBex() + void parsePars() // BEX { - LOG_AS("parseParsBex"); - // .bex doesn't follow the same rules as .deh + LOG_AS("parsePars"); + // BEX doesn't follow the same rules as .deh for(; !line.trimmed().isEmpty(); readLine()) { // Skip comment lines. @@ -1476,22 +1474,22 @@ class DehReader } } - void parseHelperBex() + void parseHelper() // BEX { - LOG_AS("parseHelperBex"); + LOG_AS("parseHelper"); LOG_WARNING("[HELPER] patches are not supported."); } - void parseSpritesBex() + void parseSprites() // BEX { - LOG_AS("parseSpritesBex"); + LOG_AS("parseSprites"); LOG_WARNING("[SPRITES] patches are not supported."); } - void parseSoundsBex() + void parseSounds() // BEX { - LOG_AS("parseSoundsBex"); - // .bex doesn't follow the same rules as .deh + LOG_AS("parseSounds"); + // BEX doesn't follow the same rules as .deh for(; !line.trimmed().isEmpty(); readLine()) { // Skip comment lines. @@ -1518,10 +1516,10 @@ class DehReader } } - void parseMusicBex() + void parseMusic() // BEX { - LOG_AS("parseMusicBex"); - // .bex doesn't follow the same rules as .deh + LOG_AS("parseMusic"); + // BEX doesn't follow the same rules as .deh for(; !line.trimmed().isEmpty(); readLine()) { // Skip comment lines. @@ -1548,10 +1546,10 @@ class DehReader } } - void parsePointerBex() + void parseCodePointers() // BEX { - LOG_AS("parsePointerBex"); - // .bex doesn't follow the same rules as .deh + LOG_AS("parseCodePointers"); + // BEX doesn't follow the same rules as .deh for(; !line.trimmed().isEmpty(); readLine()) { // Skip comment lines. @@ -1614,8 +1612,8 @@ class DehReader { LOG_AS("parseText"); - String oldStr = readTextBlob(oldSize); - String newStr = readTextBlob(newSize); + String const oldStr = readTextBlob(oldSize); + String const newStr = readTextBlob(newSize); if(!(flags & NoText)) // Disabled? { @@ -1642,13 +1640,83 @@ class DehReader skipToNextLine(); } - void parseStringsBex() + static void replaceTextValue(String const &id, String newValue) { - LOG_AS("parseStringsBex"); - LOG_WARNING("[Strings] patches not supported."); + if(id.isEmpty()) return; + + int textIdx = Def_Get(DD_DEF_TEXT, id.toUtf8().constData(), nullptr); + if(textIdx < 0) return; + + // We must escape new lines. + newValue.replace("\n", "\\n"); + + // Replace this text. + Def_Set(DD_DEF_TEXT, textIdx, 0, newValue.toUtf8().constData()); + LOG_DEBUG("Text #%i \"%s\" is now:\n%s") + << textIdx << id << newValue; + } + + void parseStrings() // BEX + { + LOG_AS("parseStrings"); + + bool multiline = false; + String textId; + String newValue; + + // BEX doesn't follow the same rules as .deh + for(;; readLine()) + { + if(!multiline) + { + if(line.trimmed().isEmpty()) break; + + // Skip comment lines. + if(line.at(0) == '#') continue; + + // Determine the split (or 'pivot') position. + int assign = line.indexOf('='); + if(assign < 0) + { + throw SyntaxError("parseStrings", String("Expected assignment statement but encountered \"%1\" on line #%2") + .arg(line).arg(currentLineNumber)); + } + + textId = line.substr(0, assign).rightStrip(); + + // Nothing before '=' ? + if(textId.isEmpty()) + { + throw SyntaxError("parseStrings", String("Expected keyword before '=' on line #%1") + .arg(currentLineNumber)); + } + + newValue = line.substr(assign + 1).leftStrip(); + } + else + { + newValue += line.leftStrip(); + } + + // Concatenate another multi-line replacement? + if(newValue.endsWith('\\')) + { + newValue.truncate(newValue.length() - 1); + multiline = true; + continue; + } + + replaceTextValue(textId, newValue); + multiline = false; + } + + if(line.trimmed().isEmpty()) + { + skipToNextSection(); + } } - void createValueDef(QString const &path, QString const &value) + void createValueDef(String const &path, String const &value) { // An existing value? ded_value_t *def;