Skip to content

Commit

Permalink
Savegame Tool: Populate the "/input" root folder given the provided path
Browse files Browse the repository at this point in the history
  • Loading branch information
danij-deng committed Mar 19, 2014
1 parent a86e2ee commit dc28b2e
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 45 deletions.
107 changes: 68 additions & 39 deletions doomsday/tools/savegametool/src/main.cpp
Expand Up @@ -21,6 +21,7 @@
#include <QList>
#include <QMutableListIterator>
#include <QtAlgorithms>
#include <de/DirectoryFeed>
#include <de/TextApp>
#include <de/Time>
#include "id1translator.h"
Expand Down Expand Up @@ -114,55 +115,43 @@ static PackageFormatter &translator()
}

/// @param oldSavePath Path to the game state file [.dsg | .hsg | .hxs]
static bool convertSavegame(Path oldSavePath)
static void convertSavegame(Path inputPath)
{
/// @todo try all known extensions at the given path, if not specified.
String saveName = oldSavePath.lastSegment().toString();

try
foreach(PackageFormatter *xlator, translators)
{
foreach(PackageFormatter *fmt, translators)
if(xlator->recognize(inputPath))
{
if(fmt->recognize(oldSavePath))
{
LOG_VERBOSE("Recognized \"%s\" as a %s format savegame")
<< NativePath(oldSavePath).pretty() << fmt->formatName();
knownTranslator = fmt;
break;
}
LOG_VERBOSE("Recognized \"%s\" as a %s format savegame")
<< NativePath(inputPath).pretty() << xlator->formatName();
knownTranslator = xlator;
break;
}
}

// Still unknown? Try again with "fuzzy" logic.
if(!knownTranslator)
// Still unknown? Try again with "fuzzy" logic.
if(!knownTranslator)
{
// Unknown magic
if(!fallbackGameId.isEmpty())
{
// Unknown magic
if(!fallbackGameId.isEmpty())
{
// Use whichever format is applicable for the specified identity key.
knownTranslator = saveFormatForGameIdentityKey(fallbackGameId);
}
else if(!saveName.fileNameExtension().isEmpty())
{
// We'll try to guess the save format...
knownTranslator = guessSaveFormatFromFileName(saveName);
}
// Use whichever format is applicable for the specified identity key.
knownTranslator = saveFormatForGameIdentityKey(fallbackGameId);
}

if(knownTranslator)
else if(!inputPath.toString().fileNameExtension().isEmpty())
{
translator().convert(oldSavePath);
return true;
// We'll try to guess the save format...
knownTranslator = guessSaveFormatFromFileName(inputPath);
}
/// @throw Error Ambigous/unknown format.
throw Error("convertSavegame", "Format of \"" + NativePath(oldSavePath).pretty() + "\" is unknown");
}
catch(Error const &er)

if(knownTranslator)
{
LOG_ERROR("\"%s\" failed conversion:\n")
<< NativePath(oldSavePath).pretty() << er.asText();
translator().convert(inputPath);
return;
}

return false;
/// @throw Error Ambigous/unknown format.
throw Error("convertSavegame", "Format of \"" + NativePath(inputPath).pretty() + "\" is unknown");
}

int main(int argc, char **argv)
Expand Down Expand Up @@ -200,10 +189,50 @@ int main(int argc, char **argv)
// Scan the command line arguments looking for savegame names/paths.
for(int i = 1; i < args.count(); ++i)
{
if(args.at(i).first() != '-') // Not an option?
if(args.at(i).first() == '-') // Not an option?
continue;

// Process the named savegame on this input path.
args.makeAbsolutePath(i);
Path const inputPath = NativePath(args.at(i)).withSeparators('/');

// A file name is required.
if(inputPath.fileName().isEmpty())
{
LOG_ERROR("\"%s\" is missing a file name, cannot convert")
<< NativePath(inputPath).pretty();
continue;
}

// Ensure we have read access to the input folder on the local fs.
NativePath nativeInputFolderPath = inputPath.toString().fileNamePath();
if(!nativeInputFolderPath.exists() || !nativeInputFolderPath.isReadable())
{
LOG_ERROR("\"%s\" is not accessible (insufficient permissions?) and will not be converted")
<< NativePath(inputPath).pretty();
continue;
}

// Clear the virtual /input folder in native fs if it already exists.
if(Folder *existingFolder = app.rootFolder().tryLocate<Folder>("/input"))
{
delete existingFolder;
}

// Repopulate the /input folder using the input folder on the local fs.
Folder &inputFolder = app.fileSystem().makeFolder("/input");
inputFolder.attach(new DirectoryFeed(nativeInputFolderPath));
inputFolder.populate(Folder::PopulateOnlyThisFolder);

// Convert the named save game.
try
{
convertSavegame(Path("/input") / inputPath.fileName());
}
catch(Error const &er)
{
// Process this savegame.
convertSavegame(args.at(i));
LOG_ERROR("\"%s\" failed conversion:\n")
<< NativePath(inputPath).pretty() << er.asText();
}
}
}
Expand Down
17 changes: 11 additions & 6 deletions doomsday/tools/savegametool/src/nativetranslator.cpp
Expand Up @@ -20,6 +20,7 @@
#include "lzss.h"
#include <de/TextApp>
#include <de/ArrayValue>
#include <de/NativeFile>
#include <de/NumberValue>
#include <de/Writer>
#include <de/ZipArchive>
Expand Down Expand Up @@ -256,12 +257,14 @@ DENG2_PIMPL(NativeTranslator)

void openFile(Path path)
{
LOG_TRACE("openFile: Opening \"%s\"") << NativePath(path).pretty();
LOG_TRACE("openFile: Opening \"%s\"") << path;
NativeFile const &nativeFile = DENG2_TEXT_APP->fileSystem().find<NativeFile const>(path);
DENG2_ASSERT(saveFilePtr == 0);
saveFilePtr = lzOpen(NativePath(path).expand().toUtf8().constData(), "rp");
NativePath const nativeFilePath = nativeFile.nativePath();
saveFilePtr = lzOpen(nativeFilePath.toUtf8().constData(), "rp");
if(!saveFilePtr)
{
throw FileOpenError("NativeTranslator", "Failed opening \"" + NativePath(path).pretty() + "\"");
throw FileOpenError("NativeTranslator", "LZSS module failed to open \"" + nativeFilePath.pretty() + "\"");
}
}

Expand Down Expand Up @@ -337,7 +340,9 @@ DENG2_PIMPL(NativeTranslator)
// User description. A fixed 24 characters in length in "really old" versions.
dint32 len = 24;
if(saveVersion >= 10)
{
from >> len;
}
dint8 *descBuf = (dint8 *)malloc(len + 1);
DENG2_ASSERT(descBuf != 0);
from.read(descBuf, len);
Expand Down Expand Up @@ -585,21 +590,21 @@ bool NativeTranslator::recognize(Path path)
{
LOG_AS("NativeTranslator");

bool result = false;
bool recognized = false;
try
{
d->openFile(path);
LZReader *from = d->newReader();
// Native save formats can be recognized by their "magic" byte identifier.
dint32 oldMagic;
*from >> oldMagic;
result = (oldMagic == d->magic());
recognized = (oldMagic == d->magic());
delete from;
}
catch(...)
{}
d->closeFile();
return result;
return recognized;
}

void NativeTranslator::convert(Path path)
Expand Down

0 comments on commit dc28b2e

Please sign in to comment.