Skip to content

Commit

Permalink
Refactor|Savegame Tool: Split up main.cpp, revised PackageFormatter b…
Browse files Browse the repository at this point in the history
…ase class
  • Loading branch information
danij-deng committed Mar 18, 2014
1 parent 06e77e2 commit 36e1583
Show file tree
Hide file tree
Showing 8 changed files with 1,177 additions and 845 deletions.
9 changes: 8 additions & 1 deletion doomsday/tools/savegametool/savegametool.pro
Expand Up @@ -20,7 +20,14 @@ CONFIG -= app_bundle
# Sources ----------------------------------------------------------------------

SOURCES += \
src/main.cpp
src/id1translator.h \
src/packageformatter.h \
src/nativetranslator.h \
\
src/id1translator.cpp \
src/main.cpp \
src/nativetranslator.cpp \
src/packageformatter.cpp

# Deployment -------------------------------------------------------------------

Expand Down
227 changes: 227 additions & 0 deletions doomsday/tools/savegametool/src/id1translator.cpp
@@ -0,0 +1,227 @@
/** @file id1translator.cpp Savegame translator for old id-tech1 formats.
*
* @authors Copyright © 2014 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#include <cstring> // memcpy
#include <de/TextApp>
#include <de/Block>
#include <de/FixedByteArray>
#include <de/game/SavedSession>
#include <de/Reader>
#include <de/Writer>
#include <de/ZipArchive>
#include "id1translator.h"

extern de::String fallbackGameId;

namespace internal {

/**
* Reader for the vanilla save format.
*/
class Id1Reader
{
public:
de::Reader *_reader;
explicit Id1Reader(de::File &file)
: _reader(new de::Reader(file))
{}

de::dint8 readInt8()
{
de::dint8 val;
*_reader >> val;
return val;
}

de::dint16 readInt16()
{
de::dint16 val;
*_reader >> val;
return val;
}

de::dint32 readInt32()
{
de::dint32 val;
*_reader >> val;
return val;
}

de::dfloat readFloat()
{
DENG2_ASSERT(sizeof(float) == 4);
de::dint32 val;
*_reader >> val;
de::dfloat retVal = 0;
std::memcpy(&retVal, &val, 4);
return retVal;
}

void read(de::dint8 *data, int len)
{
if(data)
{
de::Block tmp(len);
*_reader >> de::FixedByteArray(tmp);
tmp.get(0, (de::Block::Byte *)data, len);
}
else
{
_reader->seek(len);
}
}
};

} // namespace internal

using namespace internal;
using namespace de;
using de::game::SavedSession;
using de::game::SessionMetadata;

DENG2_PIMPL(Id1Translator)
{
FormatId id;
File *saveFilePtr;
dint32 saveVersion;

Instance(Public *i)
: Base(i)
, id (DoomV9)
, saveFilePtr(0)
, saveVersion(0)
{}

~Instance()
{
closeFile();
}

File *saveFile()
{
DENG2_ASSERT(saveFilePtr != 0);
return saveFilePtr;
}

File const *saveFile() const
{
DENG2_ASSERT(saveFilePtr != 0);
return saveFilePtr;
}

bool recognize(Path /*path*/)
{
// id Tech 1 formats can't be recognized, they require "fuzzy" logic.
return false;
}

void openFile(Path path)
{
DENG2_ASSERT(!"openFile -- not yet implemented");
/*LOG_TRACE("openFile: Opening \"%s\"") << NativePath(path).pretty();
DENG2_ASSERT(saveFilePtr == 0);
saveFilePtr = 0;
if(!saveFilePtr)
{
throw FileOpenError("Id1Translator", "Failed opening \"" + NativePath(path).pretty() + "\"");
}*/
}

void closeFile()
{
if(saveFilePtr)
{
saveFilePtr = 0;
}
}

Id1Reader *newReader() const
{
return new Id1Reader(*const_cast<Instance *>(this)->saveFile());
}

Block *bufferFile() const
{
DENG2_ASSERT(!"bufferFile -- not yet implemented");
return 0;
}

void translateInfo(SessionMetadata &/*metadata*/, Id1Reader &/*from*/)
{
DENG2_ASSERT(!"translateInfo -- not yet implemented");
}
};

Id1Translator::Id1Translator(FormatId id, String textualId, int magic, QStringList knownExtensions,
QStringList baseGameIdKeys)
: PackageFormatter(textualId, magic, knownExtensions, baseGameIdKeys)
, d(new Instance(this))
{
d->id = id;
}

Id1Translator::~Id1Translator()
{}

bool Id1Translator::recognize(Path /*path*/)
{
LOG_AS("Id1Translator");
// id Tech1 save formats cannot be recognized, "fuzzy" logic is required.
return false;
}

void Id1Translator::convert(Path oldSavePath)
{
LOG_AS("Id1Translator");

/// @todo try all known extensions at the given path, if not specified.
String saveName = oldSavePath.lastSegment().toString();

d->openFile(oldSavePath);
Id1Reader *from = d->newReader();

// Read and translate the game session metadata.
SessionMetadata metadata;
d->translateInfo(metadata, *from);

ZipArchive arch;
arch.add("Info", composeInfo(metadata, oldSavePath, 1).toUtf8());

// The only serialized map state follows the session metadata in the game state file.
// Buffer the rest of the file and write it out to a new map state file.
if(Block *xlatedData = d->bufferFile())
{
// Append the remaining translated data to header, forming the new serialized
// map state data file.
Block *mapStateData = composeMapStateHeader(magic, d->saveVersion);
*mapStateData += *xlatedData;
delete xlatedData;

arch.add(Path("maps") / metadata.gets("mapUri") + "State", *mapStateData);
delete mapStateData;
}

delete from;
d->closeFile();

File &outFile = DENG2_TEXT_APP->homeFolder().replaceFile(saveName.fileNameWithoutExtension() + ".save");
outFile.setMode(File::Write | File::Truncate);
Writer(outFile) << arch;
LOG_MSG("Wrote ") << outFile.path();
}
47 changes: 47 additions & 0 deletions doomsday/tools/savegametool/src/id1translator.h
@@ -0,0 +1,47 @@
/** @file nativetranslator.h Savegame translator for old id-tech1 formats.
*
* @authors Copyright © 2014 Daniel Swanson <danij@dengine.net>
*
* @par License
* GPL: http://www.gnu.org/licenses/gpl.html
*
* <small>This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. This program is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details. You should have received a copy of the GNU
* General Public License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA</small>
*/

#ifndef SAVEGAMETOOL_ID1TRANSLATOR_H
#define SAVEGAMETOOL_ID1TRANSLATOR_H

#include "packageformatter.h"

class Id1Translator : public PackageFormatter
{
public:
/// Logical identifiers for supported save formats.
enum FormatId {
DoomV9,
HereticV13
};

public:
Id1Translator(FormatId id, de::String textualId, int magic, QStringList knownExtensions,
QStringList baseGameIdKeys);
virtual ~Id1Translator();

bool recognize(de::Path path);

void convert(de::Path path);

private:
DENG2_PRIVATE(d)
};

#endif // SAVEGAMETOOl_ID1TRANSLATOR_H

0 comments on commit 36e1583

Please sign in to comment.