Skip to content

Commit

Permalink
libdoomsday|FS: Added DataBundle as a base class for classic data files
Browse files Browse the repository at this point in the history
  • Loading branch information
skyjake committed Jan 9, 2016
1 parent d2d851b commit 836440a
Show file tree
Hide file tree
Showing 9 changed files with 336 additions and 106 deletions.
62 changes: 62 additions & 0 deletions doomsday/apps/libdoomsday/include/doomsday/filesys/databundle.h
@@ -0,0 +1,62 @@
/** @file databundle.h Classic data files: PK3, WAD, LMP, DED, DEH.
*
* @authors Copyright (c) 2016 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @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, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef LIBDOOMSDAY_DATABUNDLE_H
#define LIBDOOMSDAY_DATABUNDLE_H

#include "../libdoomsday.h"
#include <de/filesys/IInterpreter>
#include <de/Folder>

/**
* Abstract base class for classic data files: PK3, WAD, LMP, DED, DEH.
*
* Generates Doomsday 2 compatible metadata for data files, allowing them to
* be treated as packages at runtime.
*
* As packages, DataFile makes sure that the data gets loaded and unloaded
* when games are loaded (and in the right order). The data is actually loaded
* using the resource subsystem. To facilitate that, data file contents are
* available as plain byte arrays.
*/
class LIBDOOMSDAY_PUBLIC DataBundle : public de::IByteArray
{
public:
enum Format { Pk3, Wad, Lump, Ded, Dehacked };

struct LIBDOOMSDAY_PUBLIC Interpreter : public de::filesys::IInterpreter {
de::File *interpretFile(de::File *sourceData) const override;
};

public:
DataBundle(Format format, de::File const &source);
~DataBundle();

Format format() const;
de::String description() const;

// Implements IByteArray.
Size size() const;
void get(Offset at, Byte *values, Size count) const;
void set(Offset at, Byte const *values, Size count);

private:
DENG2_PRIVATE(d)
};

#endif // LIBDOOMSDAY_DATABUNDLE_H
42 changes: 5 additions & 37 deletions doomsday/apps/libdoomsday/include/doomsday/filesys/datafile.h
@@ -1,4 +1,4 @@
/** @file datafile.h FS2 File for classic data files: PK3, WAD, LMP, DED, DEH.
/** @file datafile.h Classic data files: LMP, DED, DEH.
*
* @authors Copyright (c) 2016 Jaakko Keränen <jaakko.keranen@iki.fi>
*
Expand All @@ -19,54 +19,22 @@
#ifndef LIBDOOMSDAY_DATAFILE_H
#define LIBDOOMSDAY_DATAFILE_H

#include "../libdoomsday.h"
#include <de/filesys/IInterpreter>
#include "databundle.h"
#include <de/ByteArrayFile>

/**
* Interpreter (for libcore FS) for classic data files: PK3, WAD, LMP, DED, DEH.
*
* Generates Doomsday 2 compatible metadata for data files, allowing them to
* be treated as packages at runtime.
*
* As packages, DataFile makes sure that the data gets loaded and unloaded
* when games are loaded (and in the right order). The data is actually loaded
* using the resource subsystem. To facilitate that, data file contents are
* available as plain byte arrays.
* FS2 File for for classic data files: LMP, DED, DEH.
*/
class LIBDOOMSDAY_PUBLIC DataFile : public de::ByteArrayFile
class LIBDOOMSDAY_PUBLIC DataFile : public de::ByteArrayFile, public DataBundle
{
public:
enum Format { Pk3, Wad, Lump, Ded, Dehacked };

public:
DataFile(Format format, File &sourceFile);
~DataFile();

de::String describe() const;
Format format() const;

// Implements IByteArray.
Size size() const;
void get(Offset at, Byte *values, Size count) const;
void set(Offset at, Byte const *values, Size count);

public:
struct LIBDOOMSDAY_PUBLIC Interpreter : public de::filesys::IInterpreter {
de::File *interpretFile(de::File *sourceData) const override;
};

protected:
/**
* Constructs a DataFile. The constructor is protected because DataFile is
* used as an interpreter so it gets created via IInterpreter.
*
* @param format Classic data file format.
* @param name Name of the file.
*/
DataFile(Format format, de::String const &name = "");

private:
DENG2_PRIVATE(d)
};

#endif // LIBDOOMSDAY_DATAFILE_H
40 changes: 40 additions & 0 deletions doomsday/apps/libdoomsday/include/doomsday/filesys/datafolder.h
@@ -0,0 +1,40 @@
/** @file datafolder.h Classic data files: PK3, WAD.
*
* @authors Copyright (c) 2016 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @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, see:
* http://www.gnu.org/licenses</small>
*/

#ifndef LIBDOOMSDAY_DATAFOLDER_H
#define LIBDOOMSDAY_DATAFOLDER_H

#include "databundle.h"
#include <de/Folder>

/**
* FS2 file for classic container-like data files: PK3 and WAD.
*
* Containers are represented as folders so that their contents can be
* accessed via the file tree.
*/
class LIBDOOMSDAY_PUBLIC DataFolder : public de::Folder, public DataBundle
{
public:
DataFolder(Format format, de::File &sourceFile);
~DataFolder();

de::String describe() const;
};

#endif // LIBDOOMSDAY_DATABUNDLE_H
6 changes: 3 additions & 3 deletions doomsday/apps/libdoomsday/src/doomsdayapp.cpp
Expand Up @@ -19,7 +19,7 @@
#include "doomsday/doomsdayapp.h"
#include "doomsday/filesys/sys_direc.h"
#include "doomsday/filesys/fs_util.h"
#include "doomsday/filesys/datafile.h"
#include "doomsday/filesys/databundle.h"
#include "doomsday/paths.h"

#include <de/App>
Expand Down Expand Up @@ -175,8 +175,8 @@ DoomsdayApp::DoomsdayApp(Players::Constructor playerConstructor)
DENG2_ASSERT(!theDoomsdayApp);
theDoomsdayApp = this;

static DataFile::Interpreter intrpDataFile;
App::fileSystem().addInterpreter(intrpDataFile);
static DataBundle::Interpreter intrpDataBundle;
App::fileSystem().addInterpreter(intrpDataBundle);
}

void DoomsdayApp::determineGlobalPaths()
Expand Down
122 changes: 122 additions & 0 deletions doomsday/apps/libdoomsday/src/filesys/databundle.cpp
@@ -0,0 +1,122 @@
/** @file databundle.cpp Classic data files: PK3, WAD, LMP, DED, DEH.
*
* @authors Copyright (c) 2016 Jaakko Keränen <jaakko.keranen@iki.fi>
*
* @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, see:
* http://www.gnu.org/licenses</small>
*/

#include "doomsday/filesys/databundle.h"
#include "doomsday/filesys/datafolder.h"
#include "doomsday/filesys/datafile.h"

#include <de/ArchiveFeed>

using namespace de;

namespace internal
{
static char const *formatDescriptions[] =
{
"PK3 archive",
"WAD file",
"data lump",
"DED definitions",
"DeHackEd patch"
};
}

DENG2_PIMPL(DataBundle)
{
SafePtr<File const> source;
Format format;

Instance(Public *i, Format fmt) : Base(i), format(fmt)
{}
};

DataBundle::DataBundle(Format format, File const &source)
: d(new Instance(this, format))
{
d->source.reset(&source);
}

DataBundle::~DataBundle()
{}

String DataBundle::description() const
{
if(!d->source)
{
return "invalid data bundle";
}
return QString("%1 \"%2\"")
.arg(internal::formatDescriptions[d->format])
.arg(d->source->name().fileNameWithoutExtension());
}

IByteArray::Size DataBundle::size() const
{
if(d->source)
{
return d->source->size();
}
return 0;
}

void DataBundle::get(Offset at, Byte *values, Size count) const
{
if(!d->source)
{
throw File::InputError("DataBundle::get", "Source file has been destroyed");
}
d->source->as<ByteArrayFile>().get(at, values, count);
}

void DataBundle::set(Offset, Byte const *, Size)
{
throw File::OutputError("DataBundle::set", "Classic data formats are read-only");
}

File *DataBundle::Interpreter::interpretFile(File *sourceData) const
{
// Naive check using the file extension.
static struct { String str; Format format; } formats[] = {
{ ".pk3", Pk3 },
{ ".wad", Wad },
{ ".lmp", Lump },
{ ".ded", Ded },
{ ".deh", Dehacked }
};
String const ext = sourceData->name().fileNameExtension();
for(auto const &fmt : formats)
{
if(ext == fmt.str)
{
LOG_RES_VERBOSE("Interpreted ") << sourceData->description()
<< " as "
<< internal::formatDescriptions[fmt.format];

switch(fmt.format)
{
case Pk3:
return new DataFolder(fmt.format, *sourceData);

default:
return new DataFile(fmt.format, *sourceData);
}
}
}
// Was not interpreted.
return nullptr;
}

0 comments on commit 836440a

Please sign in to comment.