Merge branch 'master' into release

This commit is contained in:
Aruki 2018-10-21 19:58:19 -06:00
commit f92b36a8ab
2433 changed files with 179954 additions and 108025 deletions

15
.gitmodules vendored Normal file
View File

@ -0,0 +1,15 @@
[submodule "externals/tinyxml2"]
path = externals/tinyxml2
url = https://github.com/leethomason/tinyxml2
[submodule "externals/zlib"]
path = externals/zlib
url = https://github.com/madler/zlib
[submodule "externals/assimp"]
path = externals/assimp
url = https://github.com/assimp/assimp
[submodule "externals/nod"]
path = externals/nod
url = https://github.com/arukibree/nod
[submodule "externals/CodeGen"]
path = externals/CodeGen
url = https://github.com/arukibree/CodeGen

1
externals/assimp vendored Submodule

@ -0,0 +1 @@
Subproject commit bca41ceba5a76936807ea4d23d14a98444ed89b0

1
externals/nod vendored Submodule

@ -0,0 +1 @@
Subproject commit 6f777ebb481f58a4e05d7323176335b450ea8d42

1
externals/tinyxml2 vendored Submodule

@ -0,0 +1 @@
Subproject commit c483646db00a6a9ac3a8e93f7c490aecb589979d

1
externals/zlib vendored Submodule

@ -0,0 +1 @@
Subproject commit cacf7f1d4e3d44d871b605da3b647f07d718623f

1591
resources/WordList.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,13 @@
CONFIG += PUBLIC_RELEASE
win32: {
QMAKE_CXXFLAGS += /WX \ # Treat warnings as errors
/wd4267 # Disable C4267: conversion from 'size_t' to 'type', possible loss of data
QMAKE_CXXFLAGS += /WX \ # Treat warnings as errors
/wd4267 \ # Disable C4267: conversion from 'size_t' to 'type', possible loss of data
/wd4100 \ # Disable C4100: unreferenced formal parameter
/wd4101 \ # Disable C4101: unreferenced local variable
/wd4189 # Disable C4189: local variable is initialized but not referenced
QMAKE_CXXFLAGS_WARN_ON -= -w34100 -w34189 # Override C4100 and C4189 being set to w3 in Qt's default .qmake.conf file
}
BUILD_DIR = $$PWD/../build

View File

@ -8,14 +8,11 @@
/* This header declares a macro, ASSERT(Expression). ASSERT evaluates the input expression and verifies that
* it is true. If the expression is false, an error message will be printed to the log with info on what went
* wrong and (in debug builds) trigger a debug break. Application execution is not aborted, but if an assert
* fails then there is usually a decent chance of the application crashing regardless.
* wrong and (in debug builds) trigger a debug break. Application execution is aborted. In public release builds,
* asserts are compiled out entirely, so neither log messages nor debug breaks will occur.
*
* Note that in public release builds, asserts are compiled out entirely, so neither log messages nor debug breaks
* will occur.
*
* LOG_ONLY_ASSERT is similar to a regular assert, but doesn't trigger a debug break. It can be useful for debugging,
* but shouldn't be used as a permanent error check.
* Alternatively, this file also declares an ENSURE macro, which is guaranteed always executes and will never be
* compiled out, regardless of build configuration.
*/
#define __FILE_SHORT__ strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__
@ -27,39 +24,30 @@
#define CONDITIONAL_BREAK(Condition) {}
#endif
#if 1
#define ASSERT_CHECK_BEGIN(Expression) \
{ \
if (!(Expression)) \
{
// Asserts Enabled
#define ASSERT_CHECK_BEGIN(Expression) \
{ \
if (!(Expression)) \
{
#define ASSERT_CHECK_END \
} \
}
#define ASSERT_CHECK_END \
} \
}
#define WRITE_FAILURE_TO_LOG(Expression) \
Log::Write(TString(__FILE_SHORT__) + "(" + TString::FromInt32(__LINE__, 0, 10) + "): ASSERT FAILED: " + #Expression);
#define WRITE_FAILURE_TO_LOG(Expression) \
Log::Write(TString(__FILE_SHORT__) + "(" + TString::FromInt32(__LINE__, 0, 10) + "): ASSERT FAILED: " + #Expression);
#define LOG_ONLY_ASSERT(Expression) \
ASSERT_CHECK_BEGIN(Expression) \
WRITE_FAILURE_TO_LOG(Expression) \
ASSERT_CHECK_END
#define ASSERT(Expression) \
ASSERT_CHECK_BEGIN(Expression) \
WRITE_FAILURE_TO_LOG(Expression) \
DEBUG_BREAK \
ASSERT_CHECK_END
// ENSURE macro always executes, never gets compiled out
#define ENSURE(Expression) \
ASSERT_CHECK_BEGIN(Expression) \
WRITE_FAILURE_TO_LOG(Expression) \
DEBUG_BREAK \
abort(); \
ASSERT_CHECK_END
#if !PUBLIC_RELEASE
#define ASSERT(Expression) ENSURE(Expression)
#else
// Asserts Disabled
#define BREAK_ONLY_ASSERT(Expression) {}
#define LOG_ONLY_ASSERT(Expression) {}
#define ASSERT(Expression) {}
#endif
#endif // ASSERT_H

View File

@ -52,7 +52,7 @@ CAssetID::CAssetID(IInputStream& rInput, EIDLength Length)
CAssetID::CAssetID(IInputStream& rInput, EGame Game)
{
*this = CAssetID(rInput, (Game <= eEchoes ? e32Bit : e64Bit));
*this = CAssetID(rInput, (Game <= EGame::Echoes ? e32Bit : e64Bit));
}
TString CAssetID::ToString(EIDLength ForcedLength /*= eInvalidIDLength*/) const

View File

@ -49,9 +49,9 @@ public:
static CAssetID FromString(const TString& rkString);
static CAssetID RandomID();
inline static EIDLength GameIDLength(EGame Game) { return (Game == eUnknownGame ? eInvalidIDLength : (Game <= eEchoes ? e32Bit : e64Bit)); }
inline static EIDLength GameIDLength(EGame Game) { return (Game == EGame::Invalid ? eInvalidIDLength : (Game <= EGame::Echoes ? e32Bit : e64Bit)); }
inline static CAssetID InvalidID(EIDLength IDLength) { return (IDLength == e32Bit ? skInvalidID32 : skInvalidID64); }
inline static CAssetID InvalidID(EGame Game) { return InvalidID(Game <= eEchoes ? e32Bit : e64Bit); }
inline static CAssetID InvalidID(EGame Game) { return InvalidID(Game <= EGame::Echoes ? e32Bit : e64Bit); }
static CAssetID skInvalidID32;
static CAssetID skInvalidID64;

View File

@ -65,7 +65,10 @@ void CColor::Write(IOutputStream &rOutput, bool Integral /*= false*/) const
void CColor::Serialize(IArchive& rArc)
{
rArc << SERIAL_AUTO(R) << SERIAL_AUTO(G) << SERIAL_AUTO(B) << SERIAL_AUTO(A);
rArc << SerialParameter("R", R)
<< SerialParameter("G", G)
<< SerialParameter("B", B)
<< SerialParameter("A", A, SH_Optional, 1.0f);
}
long CColor::ToLongRGBA() const

View File

@ -72,7 +72,7 @@ public:
inline void Reverse() const
{
IOUtil::SwapBytes((u32) mFourCC);
IOUtil::SwapBytes((u32&) mFourCC);
}
// Operators

View File

@ -1,11 +1,11 @@
#ifndef COMMON_H
#define COMMON_H
#include "types.h"
#include "AssertMacro.h"
#include "CAssetID.h"
#include "CColor.h"
#include "CFourCC.h"
#include "CHashFNV1A.h"
#include "CScopedTimer.h"
#include "CTimer.h"
#include "EGame.h"
@ -16,8 +16,16 @@
#include "Flags.h"
#include "Log.h"
#include "TString.h"
#include "types.h"
#include "Hash/CCRC32.h"
#include "Hash/CFNV1A.h"
#include "Serialization/Binary.h"
#include "Serialization/XML.h"
#include "NBasics.h"
// temporary home for ALIGN macro, moving later
#define ALIGN(Val, Align) ((Val + (Align-1)) & ~(Align-1))
// temporary home for MEMBER_OFFSET macro
#define MEMBER_OFFSET(TypeName, MemberName) ( (int) (long long) &((TypeName*)0)->MemberName )
#endif // COMMON_H

View File

@ -21,36 +21,26 @@ CONFIG (debug, debug|release) {
# Debug Config
OBJECTS_DIR = $$BUILD_DIR/Common/debug
TARGET = Commond
# Debug Libs
LIBS += -L$$EXTERNALS_DIR/boost_1_63_0/lib64-msvc-14.0 -llibboost_filesystem-vc140-mt-gd-1_63 \
-L$$EXTERNALS_DIR/tinyxml2/lib -ltinyxml2d
}
CONFIG (release, debug|release) {
# Release Config
OBJECTS_DIR = $$BUILD_DIR/build/Common/release
TARGET = Common
# Release Libs
LIBS += -L$$EXTERNALS_DIR/boost_1_63_0/lib64-msvc-14.0 -llibboost_filesystem-vc140-mt-1_63 \
-L$$EXTERNALS_DIR/tinyxml2/lib -ltinyxml2
}
# Include Paths
INCLUDEPATH += $$PWE_MAIN_INCLUDE \
$$EXTERNALS_DIR/boost_1_63_0 \
$$EXTERNALS_DIR/tinyxml2/include
$$EXTERNALS_DIR/CodeGen/include \
$$EXTERNALS_DIR/tinyxml2
# Header Files
HEADERS += \
CColor.h \
CFourCC.h \
CHashFNV1A.h \
CTimer.h \
EKeyInputs.h \
EMouseInputs.h \
ETransformSpace.h \
Flags.h \
TString.h \
types.h \
@ -59,6 +49,7 @@ HEADERS += \
AssertMacro.h \
CScopedTimer.h \
CAssetID.h \
Hash\CFNV1A.h \
Serialization/IArchive.h \
Serialization/CXMLWriter.h \
Serialization/CXMLReader.h \
@ -83,7 +74,9 @@ HEADERS += \
FileIO\CBitStreamInWrapper.h \
FileIO\CFileLock.h \
FileIO.h \
Common.h
Common.h \
Hash/CCRC32.h \
NBasics.h
# Source Files
SOURCES += \
@ -105,4 +98,14 @@ SOURCES += \
FileIO\IOUtil.cpp \
FileIO\IInputStream.cpp \
FileIO\IOutputStream.cpp \
FileIO\CBitStreamInWrapper.cpp
FileIO\CBitStreamInWrapper.cpp \
Hash/CCRC32.cpp
# Codegen
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
CODEGEN_OUT_PATH = $$BUILD_DIR/Common/codegen_build/auto_codegen.cpp
CODEGEN_SRC_PATH = $$PWD
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
# Library Sources
SOURCES += $$EXTERNALS_DIR/tinyxml2/tinyxml2.cpp

View File

@ -2,97 +2,91 @@
#include "CFourCC.h"
#include "Common/Serialization/IArchive.h"
CFourCC GetGameID(EGame Game)
{
switch (Game)
{
case ePrimeDemo: return "MP1D";
case ePrime: return "MPRM";
case eEchoesDemo: return "MP2D";
case eEchoes: return "MP2E";
case eCorruptionProto: return "MP3P";
case eCorruption: return "MP3C";
case eReturns: return "DKCR";
default: return "UNKN";
}
}
EGame GetGameForID(const CFourCC& rkID)
{
if (rkID == "MP1D") return ePrimeDemo;
if (rkID == "MPRM") return ePrime;
if (rkID == "MP2D") return eEchoesDemo;
if (rkID == "MP2E") return eEchoes;
if (rkID == "MP3P") return eCorruptionProto;
if (rkID == "MP3C") return eCorruption;
if (rkID == "DKCR") return eReturns;
return eUnknownGame;
}
TString GetGameName(EGame Game)
{
switch (Game)
static const TString skGameNames[EGame::Max] =
{
case ePrimeDemo: return "Metroid Prime Kiosk Demo";
case ePrime: return "Metroid Prime";
case eEchoesDemo: return "Metroid Prime 2: Echoes Demo";
case eEchoes: return "Metroid Prime 2: Echoes";
case eCorruptionProto: return "Metroid Prime 3: Corruption Prototype";
case eCorruption: return "Metroid Prime 3: Corruption";
case eReturns: return "Donkey Kong Country Returns";
default: return "Unknown Game";
}
"Metroid Prime Demo",
"Metroid Prime",
"Metroid Prime 2: Echoes Demo",
"Metroid Prime 2: Echoes",
"Metroid Prime 3: Corruption E3 2006 Prototype",
"Metroid Prime 3: Corruption",
"Donkey Kong Country Returns"
};
int GameIdx = (int) Game;
return (GameIdx >= 0 && GameIdx < (int) EGame::Max) ? skGameNames[GameIdx] : "Unknown Game";
}
TString GetGameShortName(EGame Game)
{
switch (Game)
static const TString skGameNames[EGame::Max] = {
"MP1Demo",
"MP1",
"MP2Demo",
"MP2",
"MP3Proto",
"MP3",
"DKCR"
};
int GameIdx = (int) Game;
return (GameIdx >= 0 && GameIdx < (int) EGame::Max) ? skGameNames[GameIdx] : "Unknown";
}
CFourCC GameTo4CC(EGame Game)
{
static const CFourCC skGame4CCs[EGame::Max] =
{
case ePrimeDemo: return "MP1Demo";
case ePrime: return "MP1";
case eEchoesDemo: return "MP2Demo";
case eEchoes: return "MP2";
case eCorruptionProto: return "MP3Proto";
case eCorruption: return "MP3";
case eReturns: return "DKCR";
default: return "Unknown";
}
FOURCC('MP1D'), FOURCC('MPRM'),
FOURCC('MP2D'), FOURCC('MP2E'),
FOURCC('MP3P'), FOURCC('MP3C'),
FOURCC('DKCR')
};
int GameIdx = (int) Game;
return (GameIdx >= 0 && GameIdx < (int) EGame::Max) ? skGame4CCs[GameIdx] : FOURCC('UNKN');
}
EGame GameFrom4CC(CFourCC GameId)
{
static const std::unordered_map<u32, EGame> skIdToGame =
{
{ FOURCC('MP1D'), EGame::PrimeDemo },
{ FOURCC('MPRM'), EGame::Prime },
{ FOURCC('MP2D'), EGame::EchoesDemo },
{ FOURCC('MP2E'), EGame::Echoes },
{ FOURCC('MP3P'), EGame::CorruptionProto },
{ FOURCC('MP3C'), EGame::Corruption },
{ FOURCC('DKCR'), EGame::DKCReturns }
};
auto MapFindIter = skIdToGame.find(GameId.ToLong());
return (MapFindIter != skIdToGame.end() ? MapFindIter->second : EGame::Invalid);
}
void Serialize(IArchive& rArc, EGame& rGame)
{
CFourCC GameID = GetGameID(rGame);
rArc.SerializePrimitive(GameID);
if (rArc.IsReader()) rGame = GetGameForID(GameID);
}
// ERegion
static const TString gskRegionNames[] = { "NTSC", "PAL", "JPN", "UnknownRegion" };
static const u32 gskNumRegions = sizeof(gskRegionNames) / sizeof(gskRegionNames[0]);
TString GetRegionName(ERegion Region)
{
return gskRegionNames[(int) Region];
}
ERegion GetRegionForName(const TString& rkName)
{
for (u32 iReg = 0; iReg < gskNumRegions; iReg++)
if (gskRegionNames[iReg] == rkName)
return (ERegion) iReg;
return eRegion_Unknown;
}
void Serialize(IArchive& rArc, ERegion& rRegion)
{
TString Name;
if (rArc.IsWriter())
Name = GetRegionName(rRegion);
rArc.SerializePrimitive(Name);
if (rArc.IsReader())
rRegion = GetRegionForName(Name);
// We serialize EGame as a fourCC in binary formats as a future-proofing measure.
// Additionally, older versions of IArchive always serialized EGame as a fourCC.
if (rArc.ArchiveVersion() < IArchive::eArVer_GameEnumClass || rArc.IsBinaryFormat())
{
CFourCC GameId;
if (rArc.IsWriter())
{
GameId = GameTo4CC(rGame);
}
rArc.SerializePrimitive(GameId, 0);
if (rArc.IsReader())
{
rGame = GameFrom4CC(GameId);
}
}
else
{
DefaultEnumSerialize<EGame>(rArc, rGame);
}
}

View File

@ -7,37 +7,36 @@
class CFourCC;
class IArchive;
// Note: The reason why the EGame value isn't just the fourCC game ID is because a lot of code does inequality
// comparisons on EGame for version checking ie. "if (Game <= eEchoes)", which means the enum values need to be
// in chronological order.
enum EGame
//@todo I'm not really happy with EGame being in Common (would like Common to be more
// generic so it's more reusable between different projects) but atm can't think of
// any other decent way to integrate it with IArchive unfortunately
enum class EGame
{
ePrimeDemo,
ePrime,
eEchoesDemo,
eEchoes,
eCorruptionProto,
eCorruption,
eReturns,
eUnknownGame = -1
PrimeDemo,
Prime,
EchoesDemo,
Echoes,
CorruptionProto,
Corruption,
DKCReturns,
Max,
Invalid = -1
};
CFourCC GetGameID(EGame Game);
EGame GetGameForID(const CFourCC& rkID);
TString GetGameName(EGame Game);
TString GetGameShortName(EGame Game);
CFourCC GameTo4CC(EGame Game);
EGame GameFrom4CC(CFourCC GameId);
void Serialize(IArchive& rArc, EGame& rGame);
// ERegion
enum ERegion
enum class ERegion
{
eRegion_NTSC,
eRegion_PAL,
eRegion_JPN,
eRegion_Unknown = -1
NTSC,
PAL,
JPN,
Unknown = -1
};
TString GetRegionName(ERegion Region);
ERegion GetRegionForName(const TString& rkName);
void Serialize(IArchive& rArc, ERegion& rRegion);
#endif // EGAME_H

View File

@ -1,10 +1,10 @@
#include "CVectorOutStream.h"
#include "Common/Common.h"
CVectorOutStream::CVectorOutStream()
: mpVector(new std::vector<char>)
, mOwnsVector(true)
, mPos(0)
, mUsed(0)
{
mDataEndianness = IOUtil::eBigEndian;
}
@ -13,7 +13,6 @@ CVectorOutStream::CVectorOutStream(IOUtil::EEndianness DataEndianness)
: mpVector(new std::vector<char>)
, mOwnsVector(true)
, mPos(0)
, mUsed(0)
{
mDataEndianness = DataEndianness;
}
@ -22,7 +21,6 @@ CVectorOutStream::CVectorOutStream(u32 InitialSize, IOUtil::EEndianness DataEndi
: mpVector(new std::vector<char>(InitialSize))
, mOwnsVector(true)
, mPos(0)
, mUsed(0)
{
mDataEndianness = DataEndianness;
}
@ -31,7 +29,6 @@ CVectorOutStream::CVectorOutStream(std::vector<char> *pVector, IOUtil::EEndianne
: mpVector(pVector)
, mOwnsVector(false)
, mPos(0)
, mUsed(0)
{
mDataEndianness = DataEndianness;
}
@ -45,12 +42,18 @@ void CVectorOutStream::WriteBytes(const void *pkSrc, u32 Count)
{
if (!IsValid()) return;
if ((mPos + Count) > mpVector->size())
mpVector->resize(mPos + Count);
u32 NewSize = mPos + Count;
if (NewSize > mpVector->size())
{
if (NewSize > mpVector->capacity())
mpVector->reserve( ALIGN(mPos + Count, skAllocSize) );
mpVector->resize(NewSize);
}
memcpy(mpVector->data() + mPos, pkSrc, Count);
mPos += Count;
if (mPos > mUsed) mUsed = mPos;
}
bool CVectorOutStream::Seek(s32 Offset, u32 Origin)
@ -68,7 +71,7 @@ bool CVectorOutStream::Seek(s32 Offset, u32 Origin)
break;
case SEEK_END:
mPos = mUsed - Offset;
mPos = mpVector->size() - Offset;
break;
default:
@ -81,9 +84,6 @@ bool CVectorOutStream::Seek(s32 Offset, u32 Origin)
return false;
}
if (mPos > mUsed)
mUsed = mPos;
if (mPos > mpVector->size())
mpVector->resize(mPos);
@ -107,20 +107,19 @@ bool CVectorOutStream::IsValid() const
u32 CVectorOutStream::Size() const
{
return mUsed;
}
u32 CVectorOutStream::SizeRemaining() const
{
return mpVector->size() - mPos;
return mPos;
}
void CVectorOutStream::SetVector(std::vector<char> *pVector)
{
if (mOwnsVector) delete mpVector;
if (mOwnsVector)
{
delete mpVector;
mOwnsVector = false;
}
mpVector = pVector;
mPos = 0;
mUsed = 0;
}
void* CVectorOutStream::Data()
@ -133,24 +132,8 @@ void* CVectorOutStream::DataAtPosition()
return mpVector->data() + mPos;
}
void CVectorOutStream::Expand(u32 Amount)
{
mpVector->resize(mpVector->size() + Amount);
}
void CVectorOutStream::Shrink()
{
mpVector->resize(mUsed);
}
void CVectorOutStream::Reset()
{
mPos = 0;
mUsed = 0;
}
void CVectorOutStream::Clear()
{
mPos = 0;
mpVector->clear();
Reset();
}

View File

@ -6,10 +6,11 @@
class CVectorOutStream : public IOutputStream
{
static const u32 skAllocSize = 1; // must be 1 or a power of 2
std::vector<char> *mpVector;
bool mOwnsVector;
u32 mPos;
u32 mUsed;
public:
CVectorOutStream();
@ -24,13 +25,9 @@ public:
bool EoF() const;
bool IsValid() const;
u32 Size() const;
u32 SizeRemaining() const;
void SetVector(std::vector<char> *pVector);
void *Data();
void *DataAtPosition();
void Expand(u32 Amount);
void Shrink();
void Reset();
void Clear();
};

View File

@ -1,22 +1,21 @@
#include "FileUtil.h"
#include "AssertMacro.h"
#include <boost/filesystem.hpp>
#include <boost/system/error_code.hpp>
#include "Common/FileIO/CFileInStream.h"
// These are mostly just wrappers around boost::filesystem functions.
using namespace boost::filesystem;
#include <experimental/filesystem>
#include <system_error>
// Macro encapsulating a TString -> boost::filesystem::path conversion
// boost does not handle conversion from UTF-8 correctly so we need to do it manually
#define TO_PATH(String) path( *String.ToUTF16() )
#define FROM_PATH(Path) TWideString( Path.native() ).ToUTF8()
// These are mostly just wrappers around std::filesystem functions.
using namespace std::experimental::filesystem::v1;
namespace FileUtil
{
#define ToPath(Path) u8path(Path)
bool Exists(const TString &rkFilePath)
{
return exists( TO_PATH(rkFilePath) );
return exists(ToPath(*rkFilePath));
}
bool IsRoot(const TString& rkPath)
@ -29,22 +28,22 @@ bool IsRoot(const TString& rkPath)
bool IsFile(const TString& rkFilePath)
{
return is_regular_file( TO_PATH(rkFilePath) );
return is_regular_file(ToPath(*rkFilePath));
}
bool IsDirectory(const TString& rkDirPath)
{
return is_directory( TO_PATH(rkDirPath) );
return is_directory(ToPath(*rkDirPath));
}
bool IsAbsolute(const TString& rkDirPath)
{
return boost::filesystem::path( TO_PATH(rkDirPath) ).is_absolute();
return ToPath(*rkDirPath).is_absolute();
}
bool IsRelative(const TString& rkDirPath)
{
return boost::filesystem::path( TO_PATH(rkDirPath) ).is_relative();
return ToPath(*rkDirPath).is_relative();
}
bool IsEmpty(const TString& rkDirPath)
@ -52,11 +51,10 @@ bool IsEmpty(const TString& rkDirPath)
if (!IsDirectory(rkDirPath))
{
Log::Error("Non-directory path passed to IsEmpty(): " + rkDirPath);
DEBUG_BREAK;
return false;
}
return is_empty( TO_PATH(rkDirPath) );
return is_empty(ToPath(*rkDirPath));
}
bool MakeDirectory(const TString& rkNewDir)
@ -67,7 +65,7 @@ bool MakeDirectory(const TString& rkNewDir)
return false;
}
return create_directories( TO_PATH(rkNewDir) );
return create_directories(ToPath(*rkNewDir));
}
bool CopyFile(const TString& rkOrigPath, const TString& rkNewPath)
@ -79,9 +77,10 @@ bool CopyFile(const TString& rkOrigPath, const TString& rkNewPath)
}
MakeDirectory(rkNewPath.GetFileDirectory());
boost::system::error_code Error;
copy(TO_PATH(rkOrigPath), TO_PATH(rkNewPath), Error);
return (Error == boost::system::errc::success);
std::error_code Error;
// call std::filesystem::copy, not std::copy
std::experimental::filesystem::copy(ToPath(*rkOrigPath), ToPath(*rkNewPath), Error);
return (Error.value() == 0);
}
bool CopyDirectory(const TString& rkOrigPath, const TString& rkNewPath)
@ -93,9 +92,10 @@ bool CopyDirectory(const TString& rkOrigPath, const TString& rkNewPath)
}
MakeDirectory(rkNewPath.GetFileDirectory());
boost::system::error_code Error;
copy_directory(TO_PATH(rkOrigPath), TO_PATH(rkNewPath), Error);
return (Error == boost::system::errc::success);
std::error_code Error;
// call std::filesystem::copy, not std::copy
std::experimental::filesystem::copy(ToPath(*rkOrigPath), ToPath(*rkNewPath), Error);
return (Error.value() == 0);
}
bool MoveFile(const TString& rkOldPath, const TString& rkNewPath)
@ -112,8 +112,9 @@ bool MoveFile(const TString& rkOldPath, const TString& rkNewPath)
return false;
}
int Result = rename(*rkOldPath, *rkNewPath);
return (Result == 0);
std::error_code Error;
rename(ToPath(*rkOldPath), ToPath(*rkNewPath), Error);
return Error.value() == 0;
}
bool MoveDirectory(const TString& rkOldPath, const TString& rkNewPath)
@ -126,18 +127,19 @@ bool MoveDirectory(const TString& rkOldPath, const TString& rkNewPath)
if (Exists(rkNewPath))
{
Log::Error("Unable to move directory because there is an existing directory at the destination path: " + rkNewPath);
Log::Error("Unable to move directory because there is an existing directory at the destination path: %s" + rkNewPath);
return false;
}
int Result = rename(*rkOldPath, *rkNewPath);
return (Result == 0);
std::error_code Error;
rename(ToPath(*rkOldPath), ToPath(*rkNewPath), Error);
return Error.value() == 0;
}
bool DeleteFile(const TString& rkFilePath)
{
if (!IsFile(rkFilePath)) return false;
return remove( TO_PATH(rkFilePath) ) == 1;
return remove(ToPath(*rkFilePath)) == 1;
}
bool DeleteDirectory(const TString& rkDirPath, bool FailIfNotEmpty)
@ -151,7 +153,7 @@ bool DeleteDirectory(const TString& rkDirPath, bool FailIfNotEmpty)
if (Root)
{
ASSERT(false);
Log::Error("Attempted to delete root directory!");
Log::Fatal("Attempted to delete root directory!");
return false;
}
@ -160,9 +162,9 @@ bool DeleteDirectory(const TString& rkDirPath, bool FailIfNotEmpty)
return false;
// Delete directory
boost::system::error_code Error;
remove_all(TO_PATH(rkDirPath), Error);
return (Error == boost::system::errc::success);
std::error_code Error;
remove_all(ToPath(*rkDirPath), Error);
return (Error.value() == 0);
}
bool ClearDirectory(const TString& rkDirPath)
@ -176,7 +178,7 @@ bool ClearDirectory(const TString& rkDirPath)
if (Root)
{
ASSERT(false);
Log::Error("Attempted to clear root directory!");
Log::Fatal("Attempted to clear root directory!");
return false;
}
@ -202,22 +204,22 @@ bool ClearDirectory(const TString& rkDirPath)
u64 FileSize(const TString &rkFilePath)
{
return (u64) (Exists(rkFilePath) ? file_size( TO_PATH(rkFilePath) ) : -1);
return (u64) (Exists(rkFilePath) ? file_size(ToPath(*rkFilePath)) : -1);
}
u64 LastModifiedTime(const TString& rkFilePath)
{
return (u64) last_write_time( TO_PATH(rkFilePath) );
return (u64) last_write_time(ToPath(*rkFilePath)).time_since_epoch().count();
}
TString WorkingDirectory()
{
return FROM_PATH( boost::filesystem::current_path() );
return current_path().string();
}
TString MakeAbsolute(TString Path)
{
if (!TO_PATH(Path).has_root_name())
if (!ToPath(*Path).has_root_name())
Path = WorkingDirectory() + "/" + Path;
TStringList Components = Path.Split("/\\");
@ -474,26 +476,26 @@ void GetDirectoryContents(TString DirPath, TStringList& rOut, bool Recursive /*=
DirPath.Replace("\\", "/");
bool IncludeAll = IncludeFiles && IncludeDirs;
auto AddFileLambda = [IncludeFiles, IncludeDirs, IncludeAll, &rOut](TString Path) -> void {
bool ShouldAddFile = IncludeAll || (IncludeFiles && IsFile(Path)) || (IncludeDirs && IsDirectory(Path));
auto AddFileLambda = [IncludeFiles, IncludeDirs, IncludeAll, &rOut](const TString& rkPath) -> void {
bool ShouldAddFile = IncludeAll || (IncludeFiles && IsFile(rkPath)) || (IncludeDirs && IsDirectory(rkPath));
if (ShouldAddFile)
rOut.push_back(Path);
rOut.push_back(rkPath);
};
if (Recursive)
{
for (recursive_directory_iterator It( TO_PATH(DirPath) ); It != recursive_directory_iterator(); ++It)
for (recursive_directory_iterator It(ToPath(*DirPath)); It != recursive_directory_iterator(); ++It)
{
AddFileLambda( FROM_PATH(It->path()) );
AddFileLambda(It->path().string());
}
}
else
{
for (directory_iterator It( TO_PATH(DirPath) ); It != directory_iterator(); ++It)
for (directory_iterator It(ToPath(*DirPath)); It != directory_iterator(); ++It)
{
AddFileLambda( FROM_PATH(It->path()) );
AddFileLambda(It->path().string());
}
}
}
@ -501,13 +503,27 @@ void GetDirectoryContents(TString DirPath, TStringList& rOut, bool Recursive /*=
TString FindFileExtension(const TString& rkDir, const TString& rkName)
{
for (directory_iterator It( TO_PATH(rkDir) ); It != directory_iterator(); ++It)
for (directory_iterator It(ToPath(*rkDir)); It != directory_iterator(); ++It)
{
TString Name = FROM_PATH( It->path().filename() );
TString Name = It->path().filename().string();
if (Name.GetFileName(false) == rkName) return Name.GetFileExtension();
}
return "";
}
bool LoadFileToString(const TString& rkFilePath, TString& rOut)
{
CFileInStream File(rkFilePath);
if (File.IsValid())
{
rOut = TString(File.Size());
File.ReadBytes(&rOut[0], rOut.Size());
return true;
}
else
return false;
}
}

View File

@ -36,6 +36,7 @@ bool IsValidName(const TString& rkName, bool Directory, bool RootDir = false);
bool IsValidPath(const TString& rkPath, bool Directory);
void GetDirectoryContents(TString DirPath, TStringList& rOut, bool Recursive = true, bool IncludeFiles = true, bool IncludeDirs = true);
TString FindFileExtension(const TString& rkDir, const TString& rkName);
bool LoadFileToString(const TString& rkFilePath, TString& rOut);
}

View File

@ -13,7 +13,7 @@ public:
TFlags() : mValue(0) {}
TFlags(int Val) : mValue(Val) {}
TFlags(u32 Val) : mValue(Val) {}
TFlags(FlagEnum Val) : mValue(Val) {}
TFlags(FlagEnum Val) : mValue((u32) Val) {}
inline operator int() const { return mValue; }
inline bool operator!() const { return !mValue; }
@ -22,25 +22,41 @@ public:
inline void operator&=(int Mask) { mValue &= Mask; }
inline void operator&=(u32 Mask) { mValue &= Mask; }
inline void operator|=(TFlags Flags) { mValue |= Flags.mValue; }
inline void operator|=(FlagEnum Flag) { mValue |= Flag; }
inline void operator|=(FlagEnum Flag) { mValue |= (u32) Flag; }
inline TFlags operator|(TFlags Flags) const { return TFlags(FlagEnum(mValue | Flags.mValue)); }
inline TFlags operator|(FlagEnum Flag) const { return TFlags(FlagEnum(mValue | Flag)); }
inline TFlags operator|(FlagEnum Flag) const { return TFlags(FlagEnum(mValue | (u32) Flag)); }
inline TFlags operator&(int Mask) const { return TFlags(FlagEnum(mValue & Mask)); }
inline TFlags operator&(u32 Mask) const { return TFlags(FlagEnum(mValue & Mask)); }
inline TFlags operator&(FlagEnum Flag) const { return TFlags(FlagEnum(mValue & Flag)); }
inline TFlags operator&(FlagEnum Flag) const { return TFlags(FlagEnum(mValue & (u32) Flag)); }
inline bool HasFlag(FlagEnum Flag) const { return ((mValue & Flag) != 0); }
inline bool HasFlag(FlagEnum Flag) const { return ((mValue & (u32) Flag) != 0); }
inline bool HasAnyFlags(TFlags Flags) const { return ((mValue & Flags) != 0); }
inline bool HasAllFlags(TFlags Flags) const { return ((mValue & Flags) == Flags); }
inline void SetFlag(FlagEnum Flag) { mValue |= Flag; }
inline void SetFlag(FlagEnum Flag) { mValue |= (u32) Flag; }
inline void SetFlag(TFlags Flags) { mValue |= Flags; }
inline void ClearFlag(FlagEnum Flag) { mValue &= ~Flag; }
inline void ClearFlag(FlagEnum Flag) { mValue &= ~((u32) Flag); }
inline void ClearFlag(TFlags Flags) { mValue &= ~Flags; }
inline void Serialize(IArchive& rArc) { rArc.SerializeHexPrimitive(mValue); }
inline void Serialize(IArchive& rArc) { rArc.SerializePrimitive(mValue, SH_HexDisplay); }
};
#define DECLARE_FLAGS(Enum, FlagTypeName) typedef TFlags<Enum> FlagTypeName;
// Alternate version for enum class flags
#define DECLARE_FLAGS_ENUMCLASS(Enum, FlagTypeName) \
DECLARE_FLAGS(Enum, FlagTypeName) \
inline int operator|(Enum Left, Enum Right) \
{ \
return (int) Left | (int) Right; \
} \
inline int operator&(Enum Left, Enum Right) \
{ \
return (int) Left & (int) Right; \
} \
inline int operator~(Enum Value) \
{ \
return ~((int) Value); \
} \
#endif // FLAGS_H

128
src/Common/Hash/CCRC32.cpp Normal file
View File

@ -0,0 +1,128 @@
#include "CCRC32.h"
const u32 gkCrcTable[] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
/** Default constructor, initializes the hash to the default value */
CCRC32::CCRC32()
: mHash( 0xFFFFFFFF )
{
}
/** Allows the hash to be initialized to an arbitrary value */
CCRC32::CCRC32(u32 InitialValue)
: mHash( InitialValue )
{
}
/** Hash arbitrary data */
void CCRC32::Hash(const void* pkData, int Size)
{
const u8* pkCastData = static_cast<const u8*>(pkData);
while (Size--)
{
mHash = gkCrcTable[(mHash ^ *pkCastData++) & 0xFF] ^ (mHash >> 8);
}
}
/** Retrieve the final output hash. (You can keep adding data to the hash after calling this.) */
u32 CCRC32::Digest() const
{
return mHash;
}
/** Convenience hash methods */
void CCRC32::Hash(u8 v)
{
Hash(&v, 1);
}
void CCRC32::Hash(u16 v)
{
Hash(&v, 2);
}
void CCRC32::Hash(u32 v)
{
Hash(&v, 4);
}
void CCRC32::Hash(u64 v)
{
Hash(&v, 8);
}
void CCRC32::Hash(float v)
{
Hash(&v, 4);
}
void CCRC32::Hash(double v)
{
Hash(&v, 8);
}
void CCRC32::Hash(char v)
{
Hash(&v, 1);
}
void CCRC32::Hash(const char* pkString)
{
while (*pkString)
{
Hash(pkString++, 1);
}
}
/** Static */
u32 CCRC32::StaticHashString(const char* pkString)
{
CCRC32 Hasher;
Hasher.Hash(pkString);
return Hasher.Digest();
}

41
src/Common/Hash/CCRC32.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef CCRC32_H
#define CCRC32_H
#include "Common/TString.h"
#include "Common/types.h"
/**
* CRC32 hash implementation
*/
class CCRC32
{
/** Current hash value */
u32 mHash;
public:
/** Default constructor, initializes the hash to the default value */
CCRC32();
/** Allows the hash to be initialized to an arbitrary value */
CCRC32(u32 InitialValue);
/** Hash arbitrary data */
void Hash(const void* pkData, int Size);
/** Retrieve the final output hash. (You can keep adding data to the hash after calling this.) */
u32 Digest() const;
/** Convenience hash methods */
void Hash(u8 v);
void Hash(u16 v);
void Hash(u32 v);
void Hash(u64 v);
void Hash(float v);
void Hash(double v);
void Hash(char v);
void Hash(const char* pkString);
static u32 StaticHashString(const char* pkString);
};
#endif // CCRC32_H

View File

@ -1,10 +1,10 @@
#ifndef CHASHFNV1A_H
#define CHASHFNV1A_H
#ifndef CFNV1A_H
#define CFNV1A_H
#include "types.h"
#include "TString.h"
#include "Common/types.h"
#include "Common/TString.h"
class CHashFNV1A
class CFNV1A
{
public:
enum EHashLength {
@ -21,7 +21,7 @@ private:
static const u64 skFNVPrime64 = 0x100000001B3;
public:
CHashFNV1A(EHashLength Length)
CFNV1A(EHashLength Length)
{
if (Length == e32Bit)
Init32();
@ -65,4 +65,4 @@ public:
inline void HashString(const TString& rkVal) { HashData(rkVal.Data(), rkVal.Size()); }
};
#endif // CHASHFNV1A_H
#endif // CFNV1A_H

View File

@ -53,8 +53,10 @@ bool InitLog(const TString& rkFilename)
fprintf(gpLogFile, "Opened log file at %s\n", Buffer);
fflush(gpLogFile);
#ifdef APP_FULL_NAME
// Print app name and version
fprintf(gpLogFile, APP_FULL_NAME"\n");
#endif
// Print any messages that were attempted before we initialized
if (!gPreInitLogs.empty())

97
src/Common/NBasics.h Normal file
View File

@ -0,0 +1,97 @@
#ifndef NBASICS_H
#define NBASICS_H
#include "types.h"
#include <vector>
namespace NBasics
{
/** Remove an element from a container */
template<typename T, typename ContainerT>
bool ContainerRemoveOne(ContainerT& Container, const T& kElement)
{
for (auto Iter = Container.begin(); Iter != Container.end(); Iter++)
{
if (*Iter == kElement)
{
Container.erase(Iter);
return true;
}
}
return false;
}
template<typename T>
inline bool VectorRemoveOne(std::vector<T>& Vector, const T& kElement)
{
return ContainerRemoveOne< T, std::vector<T> >(Vector, kElement);
}
template<typename T>
inline bool ListRemoveOne(std::list<T>& List, const T& kElement)
{
return ContainerRemoveOne< T, std::list<T> >(List, kElement);
}
/** Remove all occurrences of an element from a container. Returns the number of elements that were removed. */
template<typename T, typename ContainerT>
int ContainerRemoveAll(ContainerT& Container, const T& kElement)
{
int NumRemoved = 0;
for (auto Iter = Container.begin(); Iter != Container.end(); Iter++)
{
if (*Iter == kElement)
{
Iter = Container.erase(Iter);
NumRemoved++;
}
}
return NumRemoved;
}
template<typename T>
inline int VectorRemoveAll(std::vector<T>& Vector, const T& kElement)
{
return ContainerRemoveAll< T, std::vector<T> >(Vector, kElement);
}
template<typename T>
inline int ListRemoveAll(std::list<T>& List, const T& kElement)
{
return ContainerRemoveAll< T, std::list<T> >(List, kElement);
}
/** Returns whether the vector contains the given element */
template<typename T>
bool VectorContains(std::vector<T>& Vector, const T& kElement)
{
for (auto Iter = Vector.begin(); Iter != Vector.end(); Iter++)
{
if (*Iter == kElement)
{
return true;
}
}
return false;
}
/** Adds an element to a vector only if it is not already present */
template<typename T>
bool VectorAddUnique(std::vector<T>& Vector, const T& kElement)
{
if (!VectorContains(Vector, kElement))
{
Vector.push_back(kElement);
return true;
}
return false;
}
}
#endif // NBASICS_H

View File

@ -17,29 +17,41 @@ class CBasicBinaryReader : public IArchive
public:
CBasicBinaryReader(const TString& rkFilename, u32 Magic)
: IArchive(true, false)
: IArchive()
, mOwnsStream(true)
{
mArchiveFlags = AF_Binary | AF_Reader | AF_NoSkipping;
mpStream = new CFileInStream(rkFilename, IOUtil::eBigEndian);
if (mpStream->IsValid())
{
mMagicValid = (mpStream->ReadLong() == Magic);
CSerialVersion Version(*mpStream);
SetVersion(Version);
SerializeVersion();
}
}
CBasicBinaryReader(IInputStream *pStream, const CSerialVersion& rkVersion)
: IArchive(true, false)
: IArchive()
, mMagicValid(true)
, mOwnsStream(false)
{
mArchiveFlags = AF_Binary | AF_Reader | AF_NoSkipping;
ASSERT(pStream->IsValid());
mpStream = pStream;
SetVersion(rkVersion);
}
CBasicBinaryReader(void *pData, u32 DataSize, const CSerialVersion& rkVersion, IOUtil::EEndianness Endian = IOUtil::kSystemEndianness)
: IArchive()
, mMagicValid(true)
, mOwnsStream(true)
{
mArchiveFlags = AF_Binary | AF_Reader | AF_NoSkipping;
mpStream = new CMemoryInStream(pData, DataSize, Endian);
SetVersion(rkVersion);
}
~CBasicBinaryReader()
{
if (mOwnsStream) delete mpStream;
@ -48,32 +60,33 @@ public:
inline bool IsValid() const { return mpStream->IsValid(); }
// Interface
virtual bool ParamBegin(const char*) { return true; }
virtual void ParamEnd() { }
virtual bool IsReader() const { return true; }
virtual bool IsWriter() const { return false; }
virtual bool IsTextFormat() const { return false; }
virtual void SerializeContainerSize(u32& rSize, const TString&) { SerializePrimitive(rSize); }
virtual void SerializeAbstractObjectType(u32& rType) { SerializePrimitive(rType); }
virtual void SerializePrimitive(bool& rValue) { rValue = mpStream->ReadBool(); }
virtual void SerializePrimitive(char& rValue) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(s8& rValue) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(u8& rValue) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(s16& rValue) { rValue = mpStream->ReadShort(); }
virtual void SerializePrimitive(u16& rValue) { rValue = mpStream->ReadShort(); }
virtual void SerializePrimitive(s32& rValue) { rValue = mpStream->ReadLong(); }
virtual void SerializePrimitive(u32& rValue) { rValue = mpStream->ReadLong(); }
virtual void SerializePrimitive(s64& rValue) { rValue = mpStream->ReadLongLong(); }
virtual void SerializePrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); }
virtual void SerializePrimitive(float& rValue) { rValue = mpStream->ReadFloat(); }
virtual void SerializePrimitive(double& rValue) { rValue = mpStream->ReadDouble(); }
virtual void SerializePrimitive(TString& rValue) { rValue = mpStream->ReadSizedString(); }
virtual void SerializePrimitive(TWideString& rValue) { rValue = mpStream->ReadSizedWString(); }
virtual void SerializePrimitive(CFourCC& rValue) { rValue = CFourCC(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue) { rValue = CAssetID(*mpStream, mGame); }
virtual bool ParamBegin(const char*, u32) { return true; }
virtual void ParamEnd() { }
virtual void SerializeHexPrimitive(u8& rValue) { rValue = mpStream->ReadByte(); }
virtual void SerializeHexPrimitive(u16& rValue) { rValue = mpStream->ReadShort(); }
virtual void SerializeHexPrimitive(u32& rValue) { rValue = mpStream->ReadLong(); }
virtual void SerializeHexPrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); }
virtual bool PreSerializePointer(void*& Pointer, u32 Flags) { return ArchiveVersion() >= eArVer_Refactor ? mpStream->ReadBool() : true; }
virtual void SerializeContainerSize(u32& rSize, const TString&, u32 Flags) { SerializePrimitive(rSize, Flags); }
virtual void SerializeBulkData(void* pData, u32 Size, u32 Flags) { mpStream->ReadBytes(pData, Size); }
virtual void SerializePrimitive(bool& rValue, u32 Flags) { rValue = mpStream->ReadBool(); }
virtual void SerializePrimitive(char& rValue, u32 Flags) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(s8& rValue, u32 Flags) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(u8& rValue, u32 Flags) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(s16& rValue, u32 Flags) { rValue = mpStream->ReadShort(); }
virtual void SerializePrimitive(u16& rValue, u32 Flags) { rValue = mpStream->ReadShort(); }
virtual void SerializePrimitive(s32& rValue, u32 Flags) { rValue = mpStream->ReadLong(); }
virtual void SerializePrimitive(u32& rValue, u32 Flags) { rValue = mpStream->ReadLong(); }
virtual void SerializePrimitive(s64& rValue, u32 Flags) { rValue = mpStream->ReadLongLong(); }
virtual void SerializePrimitive(u64& rValue, u32 Flags) { rValue = mpStream->ReadLongLong(); }
virtual void SerializePrimitive(float& rValue, u32 Flags) { rValue = mpStream->ReadFloat(); }
virtual void SerializePrimitive(double& rValue, u32 Flags) { rValue = mpStream->ReadDouble(); }
virtual void SerializePrimitive(TString& rValue, u32 Flags) { rValue = mpStream->ReadSizedString(); }
virtual void SerializePrimitive(TWideString& rValue, u32 Flags) { rValue = mpStream->ReadSizedWString(); }
virtual void SerializePrimitive(CFourCC& rValue, u32 Flags) { rValue = CFourCC(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue, u32 Flags) { rValue = CAssetID(*mpStream, mGame); }
};
#endif // CBASICBINARYREADER

View File

@ -16,34 +16,37 @@ class CBasicBinaryWriter : public IArchive
public:
CBasicBinaryWriter(const TString& rkFilename, u32 Magic, u16 FileVersion, EGame Game)
: IArchive(false, true)
: IArchive()
, mMagic(Magic)
, mOwnsStream(true)
{
mArchiveFlags = AF_Binary | AF_Writer | AF_NoSkipping;
mpStream = new CFileOutStream(rkFilename, IOUtil::eBigEndian);
if (mpStream->IsValid())
{
mpStream->WriteLong(0); // Magic is written after the rest of the file is successfully saved
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
GetVersionInfo().Write(*mpStream);
SerializeVersion();
}
}
CBasicBinaryWriter(IOutputStream *pStream, u16 FileVersion, EGame Game)
: IArchive(false, true)
: IArchive()
, mOwnsStream(false)
{
ASSERT(pStream->IsValid());
mArchiveFlags = AF_Binary | AF_Writer | AF_NoSkipping;
mpStream = pStream;
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
}
CBasicBinaryWriter(IOutputStream *pStream, const CSerialVersion& rkVersion)
: IArchive(false, true)
: IArchive()
, mOwnsStream(false)
{
ASSERT(pStream->IsValid());
mArchiveFlags = AF_Binary | AF_Writer | AF_NoSkipping;
mpStream = pStream;
SetVersion(rkVersion);
}
@ -62,32 +65,39 @@ public:
inline bool IsValid() const { return mpStream->IsValid(); }
// Interface
virtual bool ParamBegin(const char*) { return true; }
virtual void ParamEnd() { }
virtual bool IsReader() const { return false; }
virtual bool IsWriter() const { return true; }
virtual bool IsTextFormat() const { return false; }
virtual void SerializeContainerSize(u32& rSize, const TString&) { mpStream->WriteLong(rSize); }
virtual void SerializeAbstractObjectType(u32& rType) { mpStream->WriteLong(rType); }
virtual void SerializePrimitive(bool& rValue) { mpStream->WriteBool(rValue); }
virtual void SerializePrimitive(char& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(s8& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(u8& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(s16& rValue) { mpStream->WriteShort(rValue); }
virtual void SerializePrimitive(u16& rValue) { mpStream->WriteShort(rValue); }
virtual void SerializePrimitive(s32& rValue) { mpStream->WriteLong(rValue); }
virtual void SerializePrimitive(u32& rValue) { mpStream->WriteLong(rValue); }
virtual void SerializePrimitive(s64& rValue) { mpStream->WriteLongLong(rValue); }
virtual void SerializePrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); }
virtual void SerializePrimitive(float& rValue) { mpStream->WriteFloat(rValue); }
virtual void SerializePrimitive(double& rValue) { mpStream->WriteDouble(rValue); }
virtual void SerializePrimitive(TString& rValue) { mpStream->WriteSizedString(rValue); }
virtual void SerializePrimitive(TWideString& rValue) { mpStream->WriteSizedWString(rValue); }
virtual void SerializePrimitive(CFourCC& rValue) { rValue.Write(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue) { rValue.Write(*mpStream, CAssetID::GameIDLength(Game())); }
virtual bool ParamBegin(const char*, u32) { return true; }
virtual void ParamEnd() { }
virtual void SerializeHexPrimitive(u8& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializeHexPrimitive(u16& rValue) { mpStream->WriteShort(rValue); }
virtual void SerializeHexPrimitive(u32& rValue) { mpStream->WriteLong(rValue); }
virtual void SerializeHexPrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); }
virtual bool PreSerializePointer(void*& Pointer, u32 Flags)
{
bool ValidPtr = (Pointer != nullptr);
mpStream->WriteBool(ValidPtr);
return ValidPtr;
}
virtual void SerializeContainerSize(u32& rSize, const TString&) { mpStream->WriteLong(rSize); }
virtual void SerializePrimitive(bool& rValue, u32 Flags) { mpStream->WriteBool(rValue); }
virtual void SerializePrimitive(char& rValue, u32 Flags) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(s8& rValue, u32 Flags) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(u8& rValue, u32 Flags) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(s16& rValue, u32 Flags) { mpStream->WriteShort(rValue); }
virtual void SerializePrimitive(u16& rValue, u32 Flags) { mpStream->WriteShort(rValue); }
virtual void SerializePrimitive(s32& rValue, u32 Flags) { mpStream->WriteLong(rValue); }
virtual void SerializePrimitive(u32& rValue, u32 Flags) { mpStream->WriteLong(rValue); }
virtual void SerializePrimitive(s64& rValue, u32 Flags) { mpStream->WriteLongLong(rValue); }
virtual void SerializePrimitive(u64& rValue, u32 Flags) { mpStream->WriteLongLong(rValue); }
virtual void SerializePrimitive(float& rValue, u32 Flags) { mpStream->WriteFloat(rValue); }
virtual void SerializePrimitive(double& rValue, u32 Flags) { mpStream->WriteDouble(rValue); }
virtual void SerializePrimitive(TString& rValue, u32 Flags) { mpStream->WriteSizedString(rValue); }
virtual void SerializePrimitive(TWideString& rValue, u32 Flags) { mpStream->WriteSizedWString(rValue); }
virtual void SerializePrimitive(CFourCC& rValue, u32 Flags) { rValue.Write(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue, u32 Flags) { rValue.Write(*mpStream, CAssetID::GameIDLength(Game())); }
virtual void SerializeBulkData(void* pData, u32 Size, u32 Flags) { mpStream->WriteBytes(pData, Size); }
};
#endif // CBASICBINARYWRITER

View File

@ -7,43 +7,46 @@
class CBinaryReader : public IArchive
{
struct SParameter
struct SBinaryParm
{
u32 Offset;
u32 Size;
u32 NumChildren;
u32 ChildIndex;
bool Abstract;
};
std::vector<SParameter> mParamStack;
std::vector<SBinaryParm> mBinaryParmStack;
IInputStream *mpStream;
bool mMagicValid;
bool mOwnsStream;
bool mInAttribute;
public:
CBinaryReader(const TString& rkFilename, u32 Magic)
: IArchive(true, false)
: IArchive()
, mOwnsStream(true)
, mInAttribute(false)
{
mArchiveFlags = AF_Reader | AF_Binary;
mpStream = new CFileInStream(rkFilename, IOUtil::eBigEndian);
if (mpStream->IsValid())
{
mMagicValid = (mpStream->ReadLong() == Magic);
CSerialVersion Version(*mpStream);
SetVersion(Version);
}
InitParamStack();
SerializeVersion();
}
CBinaryReader(IInputStream *pStream, const CSerialVersion& rkVersion)
: IArchive(true, false)
: IArchive()
, mMagicValid(true)
, mOwnsStream(false)
, mInAttribute(false)
{
ASSERT(pStream && pStream->IsValid());
mArchiveFlags = AF_Reader | AF_Binary;
mpStream = pStream;
SetVersion(rkVersion);
@ -64,8 +67,8 @@ private:
u32 Size = ReadSize();
u32 Offset = mpStream->Tell();
u32 NumChildren = ReadSize();
mParamStack.push_back( SParameter { Offset, Size, NumChildren, 0, false } );
mParamStack.reserve(20);
mBinaryParmStack.push_back( SBinaryParm { Offset, Size, NumChildren, 0 } );
mBinaryParmStack.reserve(20);
}
public:
@ -75,12 +78,12 @@ public:
return (mArchiveVersion < eArVer_32BitBinarySize ? (u32) mpStream->ReadShort() : mpStream->ReadLong());
}
virtual bool ParamBegin(const char *pkName)
virtual bool ParamBegin(const char *pkName, u32 Flags)
{
// If this is the parent parameter's first child, then read the child count
if (mParamStack.back().NumChildren == 0xFFFFFFFF)
if (mBinaryParmStack.back().NumChildren == 0xFFFFFFFF)
{
mParamStack.back().NumChildren = ReadSize();
mBinaryParmStack.back().NumChildren = ReadSize();
}
// Save current offset
@ -88,26 +91,25 @@ public:
u32 ParamID = TString(pkName).Hash32();
// Check the next parameter ID first and check whether it's a match for the current parameter
if (mParamStack.back().ChildIndex < mParamStack.back().NumChildren)
if (mBinaryParmStack.back().ChildIndex < mBinaryParmStack.back().NumChildren)
{
u32 NextID = mpStream->ReadLong();
u32 NextSize = ReadSize();
// Does the next parameter ID match the current one?
if (NextID == ParamID)
if (NextID == ParamID || (Flags & SH_IgnoreName))
{
mParamStack.push_back( SParameter { mpStream->Tell(), NextSize, 0xFFFFFFFF, 0, false } );
mBinaryParmStack.push_back( SBinaryParm { mpStream->Tell(), NextSize, 0xFFFFFFFF, 0 } );
return true;
}
}
// It's not a match - return to the parent parameter's first child and check all children to find a match
if (!mParamStack.empty())
if (!mBinaryParmStack.empty())
{
bool ParentAbstract = mParamStack.back().Abstract;
u32 ParentOffset = mParamStack.back().Offset;
u32 NumChildren = mParamStack.back().NumChildren;
mpStream->GoTo(ParentOffset + (ParentAbstract ? 4 : 0));
u32 ParentOffset = mBinaryParmStack.back().Offset;
u32 NumChildren = mBinaryParmStack.back().NumChildren;
mpStream->GoTo(ParentOffset);
for (u32 ChildIdx = 0; ChildIdx < NumChildren; ChildIdx++)
{
@ -118,8 +120,8 @@ public:
mpStream->Skip(ChildSize);
else
{
mParamStack.back().ChildIndex = ChildIdx;
mParamStack.push_back( SParameter { mpStream->Tell(), ChildSize, 0xFFFFFFFF, 0, false } );
mBinaryParmStack.back().ChildIndex = ChildIdx;
mBinaryParmStack.push_back( SBinaryParm { mpStream->Tell(), ChildSize, 0xFFFFFFFF, 0 } );
return true;
}
}
@ -133,14 +135,28 @@ public:
virtual void ParamEnd()
{
// Make sure we're at the end of the parameter
SParameter& rParam = mParamStack.back();
SBinaryParm& rParam = mBinaryParmStack.back();
u32 EndOffset = rParam.Offset + rParam.Size;
mpStream->GoTo(EndOffset);
mParamStack.pop_back();
mBinaryParmStack.pop_back();
// Increment parent child index
if (!mParamStack.empty())
mParamStack.back().ChildIndex++;
if (!mBinaryParmStack.empty())
mBinaryParmStack.back().ChildIndex++;
}
virtual bool PreSerializePointer(void*& Pointer, u32 Flags)
{
if (ArchiveVersion() >= eArVer_Refactor)
{
bool ValidPtr = (Pointer != nullptr);
*this << SerialParameter("PointerValid", ValidPtr);
return ValidPtr;
}
else
{
return true;
}
}
virtual void SerializeContainerSize(u32& rSize, const TString& /*rkElemName*/)
@ -149,34 +165,23 @@ public:
rSize = (mArchiveVersion < eArVer_32BitBinarySize ? (u32) mpStream->PeekShort() : mpStream->PeekLong());
}
virtual void SerializeAbstractObjectType(u32& rType)
{
// Mark current parameter as abstract so we can account for the object type in the filestream
rType = mpStream->ReadLong();
mParamStack.back().Abstract = true;
}
virtual void SerializePrimitive(bool& rValue) { rValue = mpStream->ReadBool(); }
virtual void SerializePrimitive(char& rValue) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(s8& rValue) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(u8& rValue) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(s16& rValue) { rValue = mpStream->ReadShort(); }
virtual void SerializePrimitive(u16& rValue) { rValue = mpStream->ReadShort(); }
virtual void SerializePrimitive(s32& rValue) { rValue = mpStream->ReadLong(); }
virtual void SerializePrimitive(u32& rValue) { rValue = mpStream->ReadLong(); }
virtual void SerializePrimitive(s64& rValue) { rValue = mpStream->ReadLongLong(); }
virtual void SerializePrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); }
virtual void SerializePrimitive(float& rValue) { rValue = mpStream->ReadFloat(); }
virtual void SerializePrimitive(double& rValue) { rValue = mpStream->ReadDouble(); }
virtual void SerializePrimitive(TString& rValue) { rValue = mpStream->ReadSizedString(); }
virtual void SerializePrimitive(TWideString& rValue) { rValue = mpStream->ReadSizedWString(); }
virtual void SerializePrimitive(CFourCC& rValue) { rValue = CFourCC(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue) { rValue = CAssetID(*mpStream, Game()); }
virtual void SerializeHexPrimitive(u8& rValue) { rValue = mpStream->ReadByte(); }
virtual void SerializeHexPrimitive(u16& rValue) { rValue = mpStream->ReadShort(); }
virtual void SerializeHexPrimitive(u32& rValue) { rValue = mpStream->ReadLong(); }
virtual void SerializeHexPrimitive(u64& rValue) { rValue = mpStream->ReadLongLong(); }
virtual void SerializePrimitive(bool& rValue, u32 Flags) { rValue = mpStream->ReadBool(); }
virtual void SerializePrimitive(char& rValue, u32 Flags) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(s8& rValue, u32 Flags) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(u8& rValue, u32 Flags) { rValue = mpStream->ReadByte(); }
virtual void SerializePrimitive(s16& rValue, u32 Flags) { rValue = mpStream->ReadShort(); }
virtual void SerializePrimitive(u16& rValue, u32 Flags) { rValue = mpStream->ReadShort(); }
virtual void SerializePrimitive(s32& rValue, u32 Flags) { rValue = mpStream->ReadLong(); }
virtual void SerializePrimitive(u32& rValue, u32 Flags) { rValue = mpStream->ReadLong(); }
virtual void SerializePrimitive(s64& rValue, u32 Flags) { rValue = mpStream->ReadLongLong(); }
virtual void SerializePrimitive(u64& rValue, u32 Flags) { rValue = mpStream->ReadLongLong(); }
virtual void SerializePrimitive(float& rValue, u32 Flags) { rValue = mpStream->ReadFloat(); }
virtual void SerializePrimitive(double& rValue, u32 Flags) { rValue = mpStream->ReadDouble(); }
virtual void SerializePrimitive(TString& rValue, u32 Flags) { rValue = mpStream->ReadSizedString(); }
virtual void SerializePrimitive(TWideString& rValue, u32 Flags) { rValue = mpStream->ReadSizedWString(); }
virtual void SerializePrimitive(CFourCC& rValue, u32 Flags) { rValue = CFourCC(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue, u32 Flags) { rValue = CAssetID(*mpStream, Game()); }
virtual void SerializeBulkData(void* pData, u32 Size, u32 Flags) { mpStream->ReadBytes(pData, Size); }
};
#endif // CBINARYREADER

View File

@ -10,7 +10,6 @@ class CBinaryWriter : public IArchive
{
u32 Offset;
u32 NumSubParams;
bool Abstract;
};
std::vector<SParameter> mParamStack;
@ -19,40 +18,43 @@ class CBinaryWriter : public IArchive
bool mOwnsStream;
public:
CBinaryWriter(const TString& rkFilename, u32 Magic, u16 FileVersion, EGame Game)
: IArchive(false, true)
CBinaryWriter(const TString& rkFilename, u32 Magic, u16 FileVersion = 0, EGame Game = EGame::Invalid)
: IArchive()
, mMagic(Magic)
, mOwnsStream(true)
{
mArchiveFlags = AF_Writer | AF_Binary;
mpStream = new CFileOutStream(rkFilename, IOUtil::eBigEndian);
if (mpStream->IsValid())
{
mpStream->WriteLong(0); // Magic is written after the rest of the file has been successfully written
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
GetVersionInfo().Write(*mpStream);
}
InitParamStack();
SerializeVersion();
}
CBinaryWriter(IOutputStream *pStream, u16 FileVersion, EGame Game)
: IArchive(false, true)
CBinaryWriter(IOutputStream *pStream, u16 FileVersion = 0, EGame Game = EGame::Invalid)
: IArchive()
, mMagic(0)
, mOwnsStream(false)
{
ASSERT(pStream && pStream->IsValid());
mArchiveFlags = AF_Writer | AF_Binary;
mpStream = pStream;
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
InitParamStack();
}
CBinaryWriter(IOutputStream *pStream, const CSerialVersion& rkVersion)
: IArchive(false, true)
: IArchive()
, mMagic(0)
, mOwnsStream(false)
{
ASSERT(pStream && pStream->IsValid());
mArchiveFlags = AF_Writer | AF_Binary;
mpStream = pStream;
SetVersion(rkVersion);
InitParamStack();
@ -83,12 +85,12 @@ private:
mParamStack.reserve(20);
mpStream->WriteLong(0xFFFFFFFF);
mpStream->WriteLong(0); // Size filler
mParamStack.push_back( SParameter { mpStream->Tell(), 0, false } );
mParamStack.push_back( SParameter { mpStream->Tell(), 0 } );
}
public:
// Interface
virtual bool ParamBegin(const char *pkName)
virtual bool ParamBegin(const char *pkName, u32 Flags)
{
// Update parent param
mParamStack.back().NumSubParams++;
@ -102,7 +104,7 @@ public:
mpStream->WriteLong(-1); // Param size filler
// Add new param to the stack
mParamStack.push_back( SParameter { mpStream->Tell(), 0, false } );
mParamStack.push_back( SParameter { mpStream->Tell(), 0 } );
return true;
}
@ -121,7 +123,6 @@ public:
// Write param child count
if (rParam.NumSubParams > 0 || mParamStack.size() == 1)
{
if (rParam.Abstract) mpStream->Skip(4);
mpStream->WriteLong(rParam.NumSubParams);
}
@ -129,6 +130,13 @@ public:
mParamStack.pop_back();
}
virtual bool PreSerializePointer(void*& Pointer, u32 Flags)
{
bool ValidPtr = (Pointer != nullptr);
*this << SerialParameter("PointerValid", ValidPtr);
return ValidPtr;
}
virtual void SerializeContainerSize(u32& rSize, const TString& /*rkElemName*/)
{
// Normally handled by ParamBegin and ParamEnd but we need to do something here to account for zero-sized containers
@ -136,34 +144,23 @@ public:
mpStream->WriteLong(0);
}
virtual void SerializeAbstractObjectType(u32& rType)
{
// Mark this parameter as abstract so we can account for the object type in the filestream
mpStream->WriteLong(rType);
mParamStack.back().Abstract = true;
}
virtual void SerializePrimitive(bool& rValue) { mpStream->WriteBool(rValue); }
virtual void SerializePrimitive(char& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(s8& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(u8& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(s16& rValue) { mpStream->WriteShort(rValue); }
virtual void SerializePrimitive(u16& rValue) { mpStream->WriteShort(rValue); }
virtual void SerializePrimitive(s32& rValue) { mpStream->WriteLong(rValue); }
virtual void SerializePrimitive(u32& rValue) { mpStream->WriteLong(rValue); }
virtual void SerializePrimitive(s64& rValue) { mpStream->WriteLongLong(rValue); }
virtual void SerializePrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); }
virtual void SerializePrimitive(float& rValue) { mpStream->WriteFloat(rValue); }
virtual void SerializePrimitive(double& rValue) { mpStream->WriteDouble(rValue); }
virtual void SerializePrimitive(TString& rValue) { mpStream->WriteSizedString(rValue); }
virtual void SerializePrimitive(TWideString& rValue) { mpStream->WriteSizedWString(rValue); }
virtual void SerializePrimitive(CFourCC& rValue) { rValue.Write(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue) { rValue.Write(*mpStream, CAssetID::GameIDLength(Game())); }
virtual void SerializeHexPrimitive(u8& rValue) { mpStream->WriteByte(rValue); }
virtual void SerializeHexPrimitive(u16& rValue) { mpStream->WriteShort(rValue); }
virtual void SerializeHexPrimitive(u32& rValue) { mpStream->WriteLong(rValue); }
virtual void SerializeHexPrimitive(u64& rValue) { mpStream->WriteLongLong(rValue); }
virtual void SerializePrimitive(bool& rValue, u32 Flags) { mpStream->WriteBool(rValue); }
virtual void SerializePrimitive(char& rValue, u32 Flags) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(s8& rValue, u32 Flags) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(u8& rValue, u32 Flags) { mpStream->WriteByte(rValue); }
virtual void SerializePrimitive(s16& rValue, u32 Flags) { mpStream->WriteShort(rValue); }
virtual void SerializePrimitive(u16& rValue, u32 Flags) { mpStream->WriteShort(rValue); }
virtual void SerializePrimitive(s32& rValue, u32 Flags) { mpStream->WriteLong(rValue); }
virtual void SerializePrimitive(u32& rValue, u32 Flags) { mpStream->WriteLong(rValue); }
virtual void SerializePrimitive(s64& rValue, u32 Flags) { mpStream->WriteLongLong(rValue); }
virtual void SerializePrimitive(u64& rValue, u32 Flags) { mpStream->WriteLongLong(rValue); }
virtual void SerializePrimitive(float& rValue, u32 Flags) { mpStream->WriteFloat(rValue); }
virtual void SerializePrimitive(double& rValue, u32 Flags) { mpStream->WriteDouble(rValue); }
virtual void SerializePrimitive(TString& rValue, u32 Flags) { mpStream->WriteSizedString(rValue); }
virtual void SerializePrimitive(TWideString& rValue, u32 Flags) { mpStream->WriteSizedWString(rValue); }
virtual void SerializePrimitive(CFourCC& rValue, u32 Flags) { rValue.Write(*mpStream); }
virtual void SerializePrimitive(CAssetID& rValue, u32 Flags) { rValue.Write(*mpStream, CAssetID::GameIDLength(Game())); }
virtual void SerializeBulkData(void* pData, u32 Size, u32 Flags) { mpStream->WriteBytes(pData, Size); }
};
#endif // CBINARYWRITER

View File

@ -22,13 +22,13 @@ void CSerialVersion::Read(IInputStream& rInput)
mArchiveVersion = rInput.ReadShort();
mFileVersion = rInput.ReadShort();
CFourCC GameID(rInput);
mGame = GetGameForID(GameID);
mGame = GameFrom4CC(GameID);
}
void CSerialVersion::Write(IOutputStream& rOutput)
{
rOutput.WriteShort(mArchiveVersion);
rOutput.WriteShort(mFileVersion);
CFourCC GameID = GetGameID(mGame);
CFourCC GameID = GameTo4CC(mGame);
GameID.Write(rOutput);
}

View File

@ -8,23 +8,24 @@ class CXMLReader : public IArchive
{
tinyxml2::XMLDocument mDoc;
tinyxml2::XMLElement *mpCurElem; // Points to the next element being read
const char* mpAttribute; // Name of the parameter we are reading from an attribute
bool mJustEndedParam; // Indicates we just ended a primitive parameter
public:
CXMLReader(const TString& rkFileName)
: IArchive(true, false)
: IArchive()
, mpAttribute(nullptr)
, mJustEndedParam(false)
{
mArchiveFlags = AF_Reader | AF_Text;
// Load XML and set current element to the root element; read version
mDoc.LoadFile(*rkFileName);
mpCurElem = mDoc.FirstChildElement();
if (mpCurElem != nullptr)
{
mArchiveVersion = (u16) TString( mpCurElem->Attribute("ArchiveVer") ).ToInt32(10);
mFileVersion = (u16) TString( mpCurElem->Attribute("FileVer") ).ToInt32(10);
const char *pkGameAttr = mpCurElem->Attribute("Game");
mGame = pkGameAttr ? GetGameForID( CFourCC(pkGameAttr) ) : eUnknownGame;
SerializeVersion();
}
else
{
@ -38,9 +39,21 @@ public:
}
// Interface
virtual bool ParamBegin(const char *pkName)
virtual bool IsReader() const { return true; }
virtual bool IsWriter() const { return false; }
virtual bool IsTextFormat() const { return true; }
virtual bool ParamBegin(const char *pkName, u32 Flags)
{
ASSERT(IsValid());
ASSERT(!mpAttribute); // Attributes cannot have sub-children
// Store as an attribute if requested
if (Flags & SH_Attribute)
{
mpAttribute = mpCurElem->Attribute(pkName);
return mpAttribute != nullptr;
}
// Push new parent if needed
if (!mJustEndedParam)
@ -51,7 +64,7 @@ public:
}
// Verify the current element matches the name of the next serialized parameter.
if ( strcmp(mpCurElem->Name(), pkName) == 0)
if ( (Flags & SH_IgnoreName) || strcmp(mpCurElem->Name(), pkName) == 0 )
{
mJustEndedParam = false;
return true;
@ -84,57 +97,71 @@ public:
virtual void ParamEnd()
{
if (mJustEndedParam)
mpCurElem = mpCurElem->Parent()->ToElement();
if (mpAttribute)
mpAttribute = nullptr;
tinyxml2::XMLElement *pElem = mpCurElem->NextSiblingElement();
if (pElem)
mpCurElem = pElem;
else
{
if (mJustEndedParam)
mpCurElem = mpCurElem->Parent()->ToElement();
mJustEndedParam = true;
tinyxml2::XMLElement *pElem = mpCurElem->NextSiblingElement();
if (pElem)
mpCurElem = pElem;
mJustEndedParam = true;
}
}
protected:
TString ReadParam()
{
return TString(mpCurElem->GetText());
return TString( mpAttribute ? mpAttribute : mpCurElem->GetText() );
}
public:
virtual void SerializeContainerSize(u32& rSize, const TString& rkElemName)
virtual void SerializeArraySize(u32& Value)
{
rSize = 0;
Value = 0;
for (tinyxml2::XMLElement *pElem = mpCurElem->FirstChildElement(*rkElemName); pElem; pElem = pElem->NextSiblingElement(*rkElemName))
rSize++;
for (tinyxml2::XMLElement *pElem = mpCurElem->FirstChildElement(); pElem; pElem = pElem->NextSiblingElement())
Value++;
}
virtual void SerializeAbstractObjectType(u32& rType)
virtual bool PreSerializePointer(void*& InPointer, u32 Flags)
{
rType = TString(mpCurElem->Attribute("Type")).ToInt32(10);
return mpCurElem->GetText() == nullptr || strcmp(mpCurElem->GetText(), "NULL") != 0;
}
virtual void SerializePrimitive(bool& rValue) { rValue = (ReadParam() == "true" ? true : false); }
virtual void SerializePrimitive(char& rValue) { rValue = ReadParam().Front(); }
virtual void SerializePrimitive(s8& rValue) { rValue = (s8) ReadParam().ToInt32(10); }
virtual void SerializePrimitive(u8& rValue) { rValue = (u8) ReadParam().ToInt32(10); }
virtual void SerializePrimitive(s16& rValue) { rValue = (s16) ReadParam().ToInt32(10); }
virtual void SerializePrimitive(u16& rValue) { rValue = (u16) ReadParam().ToInt32(10); }
virtual void SerializePrimitive(s32& rValue) { rValue = (s32) ReadParam().ToInt32(10); }
virtual void SerializePrimitive(u32& rValue) { rValue = (u32) ReadParam().ToInt32(10); }
virtual void SerializePrimitive(s64& rValue) { rValue = (s64) ReadParam().ToInt64(10); }
virtual void SerializePrimitive(u64& rValue) { rValue = (u64) ReadParam().ToInt64(10); }
virtual void SerializePrimitive(float& rValue) { rValue = ReadParam().ToFloat(); }
virtual void SerializePrimitive(double& rValue) { rValue = (double) ReadParam().ToFloat(); }
virtual void SerializePrimitive(TString& rValue) { rValue = ReadParam(); }
virtual void SerializePrimitive(TWideString& rValue) { rValue = ReadParam().ToUTF16(); }
virtual void SerializePrimitive(CFourCC& rValue) { rValue = CFourCC( ReadParam() ); }
virtual void SerializePrimitive(CAssetID& rValue) { rValue = CAssetID::FromString( ReadParam() ); }
virtual void SerializePrimitive(bool& rValue, u32 Flags) { rValue = (ReadParam() == "true" ? true : false); }
virtual void SerializePrimitive(char& rValue, u32 Flags) { rValue = ReadParam().Front(); }
virtual void SerializePrimitive(s8& rValue, u32 Flags) { rValue = (s8) ReadParam().ToInt32( (Flags & SH_HexDisplay) ? 16 : 10 ); }
virtual void SerializePrimitive(u8& rValue, u32 Flags) { rValue = (u8) ReadParam().ToInt32( (Flags & SH_HexDisplay) ? 16 : 10 ); }
virtual void SerializePrimitive(s16& rValue, u32 Flags) { rValue = (s16) ReadParam().ToInt32( (Flags & SH_HexDisplay) ? 16 : 10 ); }
virtual void SerializePrimitive(u16& rValue, u32 Flags) { rValue = (u16) ReadParam().ToInt32( (Flags & SH_HexDisplay) ? 16 : 10 ); }
virtual void SerializePrimitive(s32& rValue, u32 Flags) { rValue = (s32) ReadParam().ToInt32( (Flags & SH_HexDisplay) ? 16 : 10 ); }
virtual void SerializePrimitive(u32& rValue, u32 Flags) { rValue = (u32) ReadParam().ToInt32( (Flags & SH_HexDisplay) ? 16 : 10 ); }
virtual void SerializePrimitive(s64& rValue, u32 Flags) { rValue = (s64) ReadParam().ToInt64( (Flags & SH_HexDisplay) ? 16 : 10 ); }
virtual void SerializePrimitive(u64& rValue, u32 Flags) { rValue = (u64) ReadParam().ToInt64( (Flags & SH_HexDisplay) ? 16 : 10 ); }
virtual void SerializePrimitive(float& rValue, u32 Flags) { rValue = ReadParam().ToFloat(); }
virtual void SerializePrimitive(double& rValue, u32 Flags) { rValue = (double) ReadParam().ToFloat(); }
virtual void SerializePrimitive(TString& rValue, u32 Flags) { rValue = ReadParam(); }
virtual void SerializePrimitive(TWideString& rValue, u32 Flags) { rValue = ReadParam().ToUTF16(); }
virtual void SerializePrimitive(CFourCC& rValue, u32 Flags) { rValue = CFourCC( ReadParam() ); }
virtual void SerializePrimitive(CAssetID& rValue, u32 Flags) { rValue = CAssetID::FromString( ReadParam() ); }
virtual void SerializeHexPrimitive(u8& rValue) { rValue = (u8) ReadParam().ToInt32(16); }
virtual void SerializeHexPrimitive(u16& rValue) { rValue = (u16) ReadParam().ToInt32(16); }
virtual void SerializeHexPrimitive(u32& rValue) { rValue = (u32) ReadParam().ToInt32(16); }
virtual void SerializeHexPrimitive(u64& rValue) { rValue = (u64) ReadParam().ToInt32(16); }
virtual void SerializeBulkData(void* pData, u32 Size, u32 Flags)
{
char* pCharData = (char*) pData;
TString StringData = ReadParam();
ASSERT(StringData.Size() == Size*2);
for (u32 ByteIdx = 0; ByteIdx < Size; ByteIdx++)
{
*pCharData = (char) StringData.SubString(ByteIdx*2, 2).ToInt32(16);
pCharData++;
}
}
};
#endif // CXMLREADER

View File

@ -9,16 +9,19 @@
class CXMLWriter : public IArchive
{
tinyxml2::XMLDocument mDoc;
TString mOutFilename;
tinyxml2::XMLElement *mpCurElem;
TString mOutFilename;
const char* mpAttributeName;
bool mSaved;
public:
CXMLWriter(const TString& rkFileName, const TString& rkRootName, u16 FileVersion, EGame Game = eUnknownGame)
: IArchive(false, true)
CXMLWriter(const TString& rkFileName, const TString& rkRootName, u16 FileVersion = 0, EGame Game = EGame::Invalid)
: IArchive()
, mOutFilename(rkFileName)
, mpAttributeName(nullptr)
, mSaved(false)
{
mArchiveFlags = AF_Writer | AF_Text;
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
// Create declaration and root node
@ -29,9 +32,7 @@ public:
mDoc.LinkEndChild(mpCurElem);
// Write version data
mpCurElem->SetAttribute("ArchiveVer", (int) skCurrentArchiveVersion);
mpCurElem->SetAttribute("FileVer", (int) FileVersion);
if (Game != eUnknownGame) mpCurElem->SetAttribute("Game", *GetGameID(Game).ToString());
SerializeVersion();
}
~CXMLWriter()
@ -69,59 +70,103 @@ public:
}
// Interface
virtual bool ParamBegin(const char *pkName)
virtual bool ParamBegin(const char *pkName, u32 Flags)
{
ASSERT(IsValid());
ASSERT(!mpAttributeName); // Attributes cannot have sub-children
// Read as attribute if needed
if (Flags & SH_Attribute)
{
mpAttributeName = pkName;
}
else
{
tinyxml2::XMLElement *pElem = mDoc.NewElement(pkName);
mpCurElem->LinkEndChild(pElem);
mpCurElem = pElem;
}
tinyxml2::XMLElement *pElem = mDoc.NewElement(pkName);
mpCurElem->LinkEndChild(pElem);
mpCurElem = pElem;
return true;
}
virtual void ParamEnd()
{
mpCurElem = mpCurElem->Parent()->ToElement();
if (mpAttributeName)
{
mpAttributeName = nullptr;
}
else
{
// If we didn't save any sub parameters, remove the element.
tinyxml2::XMLElement* pParent = mpCurElem->Parent()->ToElement();
if ( mpCurElem->FirstAttribute() == nullptr
&& mpCurElem->FirstChild() == nullptr
&& mpCurElem->GetText() == nullptr )
{
pParent->DeleteChild(mpCurElem);
}
mpCurElem = pParent;
}
}
protected:
void WriteParam(const char *pkValue)
{
mpCurElem->SetText(pkValue);
if (mpAttributeName)
mpCurElem->SetAttribute(mpAttributeName, pkValue);
else
mpCurElem->SetText(pkValue);
}
public:
virtual void SerializeContainerSize(u32&, const TString&)
virtual bool PreSerializePointer(void*& Pointer, u32 Flags)
{
// Reader obtains container size from number of child elements
if (!Pointer)
{
mpCurElem->SetText("NULL");
return false;
}
return true;
}
virtual void SerializeAbstractObjectType(u32& rType)
virtual void SerializeArraySize(u32& Value)
{
mpCurElem->SetAttribute("Type", (unsigned int) rType);
// Do nothing. Reader obtains container size from number of child elements
}
virtual void SerializePrimitive(bool& rValue) { WriteParam(rValue ? "true" : "false"); }
virtual void SerializePrimitive(char& rValue) { WriteParam(*TString(rValue)); }
virtual void SerializePrimitive(s8& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(u8& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(s16& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(u16& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(s32& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(u32& rValue) { WriteParam(*TString::FromInt32(rValue, 0, 10)); }
virtual void SerializePrimitive(s64& rValue) { WriteParam(*TString::FromInt64(rValue, 0, 10)); }
virtual void SerializePrimitive(u64& rValue) { WriteParam(*TString::FromInt64(rValue, 0, 10)); }
virtual void SerializePrimitive(float& rValue) { WriteParam(*TString::FromFloat(rValue)); }
virtual void SerializePrimitive(double& rValue) { WriteParam(*TString::FromFloat((float) rValue)); }
virtual void SerializePrimitive(TString& rValue) { WriteParam(*rValue); }
virtual void SerializePrimitive(TWideString& rValue) { WriteParam(*rValue.ToUTF8()); }
virtual void SerializePrimitive(CFourCC& rValue) { WriteParam(*rValue.ToString()); }
virtual void SerializePrimitive(CAssetID& rValue) { WriteParam(*rValue.ToString( CAssetID::GameIDLength(Game()) )); }
virtual void SerializePrimitive(bool& rValue, u32 Flags) { WriteParam(rValue ? "true" : "false"); }
virtual void SerializePrimitive(char& rValue, u32 Flags) { WriteParam(*TString(rValue)); }
virtual void SerializePrimitive(s8& rValue, u32 Flags) { WriteParam( (Flags & SH_HexDisplay) ? *TString::HexString((u8&) rValue, 0) : *TString::FromInt32(rValue, 0, 10) ); }
virtual void SerializePrimitive(u8& rValue, u32 Flags) { WriteParam( (Flags & SH_HexDisplay) ? *TString::HexString((u8&) rValue, 0) : *TString::FromInt32(rValue, 0, 10) ); }
virtual void SerializePrimitive(s16& rValue, u32 Flags) { WriteParam( (Flags & SH_HexDisplay) ? *TString::HexString((u16&) rValue, 0) : *TString::FromInt32(rValue, 0, 10) ); }
virtual void SerializePrimitive(u16& rValue, u32 Flags) { WriteParam( (Flags & SH_HexDisplay) ? *TString::HexString((u16&) rValue, 0) : *TString::FromInt32(rValue, 0, 10) ); }
virtual void SerializePrimitive(s32& rValue, u32 Flags) { WriteParam( (Flags & SH_HexDisplay) ? *TString::HexString((u32&) rValue, 0) : *TString::FromInt32(rValue, 0, 10) ); }
virtual void SerializePrimitive(u32& rValue, u32 Flags) { WriteParam( (Flags & SH_HexDisplay) ? *TString::HexString((u32&) rValue, 0) : *TString::FromInt32(rValue, 0, 10) ); }
virtual void SerializePrimitive(s64& rValue, u32 Flags) { WriteParam( *TString::FromInt64(rValue, 0, (Flags & SH_HexDisplay) ? 16 : 10) ); }
virtual void SerializePrimitive(u64& rValue, u32 Flags) { WriteParam( *TString::FromInt64(rValue, 0, (Flags & SH_HexDisplay) ? 16 : 10) ); }
virtual void SerializePrimitive(float& rValue, u32 Flags) { WriteParam( *TString::FromFloat(rValue, 1, true) ); }
virtual void SerializePrimitive(double& rValue, u32 Flags) { WriteParam( *TString::FromFloat((float) rValue, 1, true) ); }
virtual void SerializePrimitive(TString& rValue, u32 Flags) { WriteParam( *rValue ); }
virtual void SerializePrimitive(TWideString& rValue, u32 Flags) { WriteParam( *rValue.ToUTF8() ); }
virtual void SerializePrimitive(CFourCC& rValue, u32 Flags) { WriteParam( *rValue.ToString() ); }
virtual void SerializePrimitive(CAssetID& rValue, u32 Flags) { WriteParam( *rValue.ToString( CAssetID::GameIDLength(Game()) ) ); }
virtual void SerializeHexPrimitive(u8& rValue) { WriteParam(*TString::HexString(rValue, 2)); }
virtual void SerializeHexPrimitive(u16& rValue) { WriteParam(*TString::HexString(rValue, 4)); }
virtual void SerializeHexPrimitive(u32& rValue) { WriteParam(*TString::HexString(rValue, 8)); }
virtual void SerializeHexPrimitive(u64& rValue) { WriteParam(*TString::HexString((u32) rValue, 16)); }
virtual void SerializeBulkData(void* pData, u32 Size, u32 Flags)
{
char* pCharData = (char*) pData;
TString OutString(Size*2);
for (u32 ByteIdx = 0; ByteIdx < Size; ByteIdx++)
{
//@todo: sloooooow. maybe replace with a LUT?
sprintf(&OutString[ByteIdx*2], "%02X", pCharData[ByteIdx]);
}
WriteParam(*OutString);
}
};
#endif // CXMLWRITER

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,22 @@
#include "TString.h"
#include "CHashFNV1A.h"
#include <FileIO/IOUtil.h>
#include "Hash/CCRC32.h"
#include "Hash/CFNV1A.h"
#include "FileIO/IOUtil.h"
#include <codecvt>
#include <locale>
// ************ TString ************
u32 TString::Hash32() const
{
CHashFNV1A Hash(CHashFNV1A::e32Bit);
Hash.HashString(*this);
return Hash.GetHash32();
CCRC32 Hash;
Hash.Hash(**this);
return Hash.Digest();
}
u64 TString::Hash64() const
{
CHashFNV1A Hash(CHashFNV1A::e64Bit);
// todo: replace with MD5
CFNV1A Hash(CFNV1A::e64Bit);
Hash.HashString(*this);
return Hash.GetHash64();
}
@ -108,14 +110,14 @@ TWideString TString::ToUTF16() const
// ************ TWideString ************
u32 TWideString::Hash32() const
{
CHashFNV1A Hash(CHashFNV1A::e32Bit);
CFNV1A Hash(CFNV1A::e32Bit);
Hash.HashData(Data(), Size() * sizeof(wchar_t));
return Hash.GetHash32();
}
u64 TWideString::Hash64() const
{
CHashFNV1A Hash(CHashFNV1A::e64Bit);
CFNV1A Hash(CFNV1A::e64Bit);
Hash.HashData(Data(), Size() * sizeof(wchar_t));
return Hash.GetHash64();
}

View File

@ -930,14 +930,9 @@ public:
return SStream.str();
}
static _TString FromFloat(float Value, int MinDecimals = 1)
static _TString FromFloat(float Value, int MinDecimals = 1, bool Scientific = false)
{
// Initial float -> string conversion
std::basic_stringstream<CharType> SStream;
if (MinDecimals > 0) SStream.setf(std::ios_base::showpoint);
SStream.setf(std::ios_base::fixed, std::ios_base::floatfield);
SStream << Value;
_TString Out = SStream.str();
_TString Out = _TString::Format(Scientific ? "%.8g" : "%f", Value);
// Make sure we have the right number of decimals
int DecIdx = Out.IndexOf(CHAR_LITERAL('.'));
@ -954,7 +949,7 @@ public:
if (NumZeroes < MinDecimals)
{
for (int iDec = 0; iDec < (MinDecimals - NumZeroes); iDec++)
Out.Append(CHAR_LITERAL('.'));
Out.Append(CHAR_LITERAL('0'));
}
// Remove unnecessary trailing zeroes from the end of the string
@ -1065,6 +1060,16 @@ public:
return (Chr >= CHAR_LITERAL('a') && Chr <= CHAR_LITERAL('z')) ? Chr - 0x20 : Chr;
}
static bool IsVowel(CharType Chr)
{
Chr = CharToUpper(Chr);
return (Chr == 'A' ||
Chr == 'E' ||
Chr == 'I' ||
Chr == 'O' ||
Chr == 'U');
}
static bool IsWhitespace(CharType Chr)
{
return ( (Chr == CHAR_LITERAL('\t')) ||

View File

@ -1,5 +1,5 @@
#include "CAreaAttributes.h"
#include "Core/Resource/Script/CMasterTemplate.h"
#include "Core/Resource/Script/CGameTemplate.h"
#include "Core/Resource/Script/CScriptLayer.h"
CAreaAttributes::CAreaAttributes(CScriptObject *pObj)
@ -13,48 +13,30 @@ CAreaAttributes::~CAreaAttributes()
void CAreaAttributes::SetObject(CScriptObject *pObj)
{
mpObj = pObj;
mGame = pObj->Template()->MasterTemplate()->Game();
CScriptTemplate* pTemplate = pObj->Template();
CStructProperty* pProperties = pTemplate->Properties();
mpObject = pObj;
mGame = pTemplate->GameTemplate()->Game();
mNeedSky = CBoolRef(pObj->PropertyData(), pProperties->ChildByIndex(1));
if (mGame == EGame::Prime)
mOverrideSky = CAssetRef(pObj->PropertyData(), pProperties->ChildByIndex(7));
else if (mGame > EGame::Prime)
mOverrideSky = CAssetRef(pObj->PropertyData(), pProperties->ChildByID(0xD208C9FA));
}
bool CAreaAttributes::IsLayerEnabled() const
{
return mpObj->Layer()->IsActive();
return mpObject->Layer()->IsActive();
}
bool CAreaAttributes::IsSkyEnabled() const
{
CPropertyStruct *pBaseStruct = mpObj->Properties();
switch (mGame)
{
case ePrime:
case eEchoesDemo:
case eEchoes:
case eCorruptionProto:
case eCorruption:
case eReturns:
return static_cast<TBoolProperty*>(pBaseStruct->PropertyByIndex(1))->Get();
default:
return false;
}
return mNeedSky.IsValid() ? mNeedSky.Get() : false;
}
CModel* CAreaAttributes::SkyModel() const
{
CPropertyStruct *pBaseStruct = mpObj->Properties();
switch (mGame)
{
case ePrime:
return gpResourceStore->LoadResource<CModel>( static_cast<TAssetProperty*>(pBaseStruct->PropertyByIndex(7))->Get() );
case eEchoesDemo:
case eEchoes:
case eCorruptionProto:
case eCorruption:
case eReturns:
return gpResourceStore->LoadResource<CModel>( static_cast<TAssetProperty*>(pBaseStruct->PropertyByID(0xD208C9FA))->Get() );
default:
return nullptr;
}
return mOverrideSky.IsValid() ? gpResourceStore->LoadResource<CModel>(mOverrideSky.Get()) : nullptr;
}

View File

@ -2,11 +2,15 @@
#define CAREAATTRIBUTES_H
#include "Core/Resource/Script/CScriptObject.h"
#include "Core/Resource/Script/Property/Properties.h"
class CAreaAttributes
{
CScriptObject* mpObject;
EGame mGame;
CScriptObject *mpObj;
CBoolRef mNeedSky;
CAssetRef mOverrideSky;
public:
CAreaAttributes(CScriptObject *pObj);
@ -16,7 +20,7 @@ public:
bool IsSkyEnabled() const;
CModel* SkyModel() const;
inline CScriptObject* Instance() const { return mpObj; }
inline CScriptObject* Instance() const { return mpObject; }
};
#endif // CAREAATTRIBUTES_H

View File

@ -41,13 +41,13 @@ void CAudioManager::LoadAssets()
}
// Load audio lookup table + sfx name list
TString AudioLookupName = (mpProject->Game() < eEchoesDemo ? "sound_lookup" : "sound_lookup_ATBL");
TString AudioLookupName = (mpProject->Game() < EGame::EchoesDemo ? "sound_lookup" : "sound_lookup_ATBL");
CAssetID AudioLookupID = mpProject->FindNamedResource(AudioLookupName);
if (AudioLookupID.IsValid())
mpAudioLookupTable = mpProject->ResourceStore()->LoadResource<CAudioLookupTable>(AudioLookupID);
if (mpProject->Game() >= eEchoesDemo)
if (mpProject->Game() >= EGame::EchoesDemo)
{
CAssetID SfxNameListID = mpProject->FindNamedResource("audio_name_lookup_STLC");
@ -77,7 +77,7 @@ SSoundInfo CAudioManager::GetSoundInfo(u32 SoundID)
if (Iter != mSfxIdMap.end())
Out.pAudioGroup = Iter->second;
if (mpProject->Game() >= eEchoesDemo)
if (mpProject->Game() >= EGame::EchoesDemo)
Out.Name = mpSfxNameList->StringByIndex(Out.DefineID);
}
@ -90,7 +90,7 @@ void CAudioManager::LogSoundInfo(u32 SoundID)
if (SoundInfo.DefineID != 0xFFFF)
{
if (mpProject->Game() >= eEchoesDemo)
if (mpProject->Game() >= EGame::EchoesDemo)
Log::Write("Sound Name: " + SoundInfo.Name);
Log::Write("Sound ID: " + TString::HexString(SoundInfo.SoundID, 4));

View File

@ -2,7 +2,7 @@
#define CLIGHTPARAMETERS_H
#include "Core/Resource/Area/CGameArea.h"
#include "Core/Resource/Script/IProperty.h"
#include "Core/Resource/Script/Property/Properties.h"
enum EWorldLightingOptions
{
@ -14,48 +14,35 @@ enum EWorldLightingOptions
class CLightParameters
{
CPropertyStruct *mpStruct;
EGame mGame;
TLongProperty *mpLightLayer;
TEnumProperty *mpWorldLightingOptions;
CIntRef mLightLayer;
TEnumRef<EWorldLightingOptions> mWorldLightingOptions;
public:
CLightParameters(CPropertyStruct *pStruct, EGame Game)
: mpStruct(pStruct)
, mGame(Game)
, mpLightLayer(nullptr)
, mpWorldLightingOptions(nullptr)
CLightParameters(CStructRef InStruct, EGame Game)
{
if (mpStruct)
if (InStruct.IsValid())
{
if (mGame <= ePrime)
if (Game <= EGame::Prime)
{
mpWorldLightingOptions = TPropCast<TEnumProperty>(mpStruct->PropertyByIndex(0x7));
mpLightLayer = TPropCast<TLongProperty>(mpStruct->PropertyByIndex(0xD));
mWorldLightingOptions = TEnumRef<EWorldLightingOptions>(InStruct.DataPointer(), InStruct.Property()->ChildByIndex(0x7));
mLightLayer = CIntRef(InStruct.DataPointer(), InStruct.Property()->ChildByIndex(0xD));
}
else
{
mpWorldLightingOptions = TPropCast<TEnumProperty>(mpStruct->PropertyByID(0x6B5E7509));
mpLightLayer = TPropCast<TLongProperty>(mpStruct->PropertyByID(0x1F715FD3));
mWorldLightingOptions = TEnumRef<EWorldLightingOptions>(InStruct.DataPointer(), InStruct.Property()->ChildByID(0x6B5E7509));
mLightLayer = CIntRef(InStruct.DataPointer(), InStruct.Property()->ChildByID(0x1F715FD3));
}
}
}
inline int LightLayerIndex() const
{
if (!mpLightLayer)
return 0;
else
return mpLightLayer->Get();
return mLightLayer.IsValid() ? mLightLayer.Get() : 0;
}
inline EWorldLightingOptions WorldLightingOptions() const
{
if (mpWorldLightingOptions)
return (EWorldLightingOptions) mpWorldLightingOptions->Get();
else
return eNormalLighting;
return mWorldLightingOptions.IsValid() ? mWorldLightingOptions.Get() : eNormalLighting;
}
};

View File

@ -12,6 +12,9 @@ TEMPLATE = lib
DESTDIR = $$BUILD_DIR/Core
DEFINES += GLEW_STATIC
win32 {
QMAKE_CXXFLAGS += -std:c++17
}
unix {
target.path = /usr/lib
QMAKE_CXXFLAGS += /WX
@ -26,11 +29,9 @@ CONFIG (debug, debug|release) {
# Debug Libs
LIBS += -L$$BUILD_DIR/Common/ -lCommond \
-L$$BUILD_DIR/Math/ -lMathd \
-L$$EXTERNALS_DIR/assimp/lib/ -lassimp-vc140-mtd \
-L$$EXTERNALS_DIR/lzo-2.09/lib/ -llzo2d \
-L$$EXTERNALS_DIR/nodtool/build/debug/lib/ -lnod \
-L$$EXTERNALS_DIR/nodtool/build/debug/logvisor/ -llogvisor \
-L$$EXTERNALS_DIR/tinyxml2/lib/ -ltinyxml2d \
-L$$EXTERNALS_DIR/assimp/lib/Debug -lassimp-vc140-mt \
-L$$EXTERNALS_DIR/nod/lib/Debug -lnod \
-L$$EXTERNALS_DIR/nod/logvisor/Debug -llogvisor \
-L$$EXTERNALS_DIR/zlib/lib/ -lzlibd
# Debug Target Dependencies
@ -48,11 +49,9 @@ CONFIG (release, debug|release) {
# Release Libs
LIBS += -L$$BUILD_DIR/Common/ -lCommon \
-L$$BUILD_DIR/Math/ -lMath \
-L$$EXTERNALS_DIR/assimp/lib/ -lassimp-vc140-mt \
-L$$EXTERNALS_DIR/lzo-2.09/lib/ -llzo2 \
-L$$EXTERNALS_DIR/nodtool/build/release/lib/ -lnod \
-L$$EXTERNALS_DIR/nodtool/build/release/logvisor -llogvisor \
-L$$EXTERNALS_DIR/tinyxml2/lib/ -ltinyxml2 \
-L$$EXTERNALS_DIR/assimp/lib/Release -lassimp-vc140-mt \
-L$$EXTERNALS_DIR/nod/lib/Release -lnod \
-L$$EXTERNALS_DIR/nod/logvisor/Release -llogvisor \
-L$$EXTERNALS_DIR/zlib/lib/ -lzlib
# Release Target Dependencies
@ -63,18 +62,19 @@ CONFIG (release, debug|release) {
}
# Debug/Release Libs
LIBS += -L$$EXTERNALS_DIR/glew-2.0.0/lib/Release/x64 -lglew32s \
LIBS += -L$$EXTERNALS_DIR/glew-2.1.0/lib/Release/x64 -lglew32s \
-lopengl32
# Include Paths
INCLUDEPATH += $$PWE_MAIN_INCLUDE \
$$EXTERNALS_DIR/assimp/include \
$$EXTERNALS_DIR/glew-2.0.0/include \
$$EXTERNALS_DIR/lzo-2.09/include \
$$EXTERNALS_DIR/nodtool/include \
$$EXTERNALS_DIR/nodtool/logvisor/include \
$$EXTERNALS_DIR/tinyxml2/include \
$$EXTERNALS_DIR/zlib/include
$$EXTERNALS_DIR/CodeGen/include \
$$EXTERNALS_DIR/glew-2.1.0/include \
$$EXTERNALS_DIR/lzo-2.10/include \
$$EXTERNALS_DIR/nod/include \
$$EXTERNALS_DIR/nod/logvisor/include \
$$EXTERNALS_DIR/tinyxml2 \
$$EXTERNALS_DIR/zlib
# Header Files
HEADERS += \
@ -91,7 +91,6 @@ HEADERS += \
Resource/Cooker/CMaterialCooker.h \
Resource/Cooker/CModelCooker.h \
Resource/Cooker/CSectionMgrOut.h \
Resource/Cooker/CTemplateWriter.h \
Resource/Cooker/CTextureEncoder.h \
Resource/Cooker/CWorldCooker.h \
Resource/Factory/CAnimSetLoader.h \
@ -103,7 +102,6 @@ HEADERS += \
Resource/Factory/CScanLoader.h \
Resource/Factory/CScriptLoader.h \
Resource/Factory/CStringLoader.h \
Resource/Factory/CTemplateLoader.h \
Resource/Factory/CTextureDecoder.h \
Resource/Factory/CWorldLoader.h \
Resource/Model/CBasicModel.h \
@ -111,11 +109,9 @@ HEADERS += \
Resource/Model/CStaticModel.h \
Resource/Model/CVertex.h \
Resource/Model/SSurface.h \
Resource/Script/CMasterTemplate.h \
Resource/Script/CScriptLayer.h \
Resource/Script/CScriptObject.h \
Resource/Script/CScriptTemplate.h \
Resource/Script/EPropertyType.h \
Resource/Script/EVolumeShape.h \
Resource/CCollisionMesh.h \
Resource/CCollisionMeshGroup.h \
@ -162,11 +158,7 @@ HEADERS += \
OpenGL/CVertexBuffer.h \
OpenGL/GLCommon.h \
ScriptExtra/CRadiusSphereExtra.h \
Resource/EGame.h \
Resource/Cooker/CAreaCooker.h \
Resource/Script/IPropertyValue.h \
Resource/Script/IPropertyTemplate.h \
Resource/Script/IProperty.h \
Resource/Model/EVertexAttribute.h \
Render/FRenderOptions.h \
Scene/FShowFlags.h \
@ -231,7 +223,34 @@ HEADERS += \
IProgressNotifier.h \
IUIRelay.h \
Resource/CResTypeFilter.h \
GameProject/COpeningBanner.h
GameProject/COpeningBanner.h \
Resource/Script/Property/CPropertyNameGenerator.h \
Resource/Script/Property/IProperty.h \
Resource/Script/Property/CEnumProperty.h \
Resource/Script/Property/CFlagsProperty.h \
Resource/Script/Property/CAssetProperty.h \
Resource/Script/Property/CPointerProperty.h \
Resource/Script/Property/CArrayProperty.h \
Resource/Script/Property/Properties.h \
Resource/Script/Property/TPropertyRef.h \
Resource/Script/Property/CBoolProperty.h \
Resource/Script/Property/CByteProperty.h \
Resource/Script/Property/CShortProperty.h \
Resource/Script/Property/CIntProperty.h \
Resource/Script/Property/CFloatProperty.h \
Resource/Script/Property/CStringProperty.h \
Resource/Script/Property/CSoundProperty.h \
Resource/Script/Property/CAnimationProperty.h \
Resource/Script/Property/CSequenceProperty.h \
Resource/Script/Property/CSplineProperty.h \
Resource/Script/Property/CAnimationSetProperty.h \
Resource/Script/Property/CVectorProperty.h \
Resource/Script/Property/CColorProperty.h \
Resource/Script/Property/CStructProperty.h \
Resource/Script/Property/CGuidProperty.h \
Resource/Script/CGameTemplate.h \
Resource/Script/NPropertyMap.h \
Resource/Script/NGameList.h
# Source Files
SOURCES += \
@ -243,7 +262,6 @@ SOURCES += \
Resource/Area/CGameArea.cpp \
Resource/Cooker/CMaterialCooker.cpp \
Resource/Cooker/CModelCooker.cpp \
Resource/Cooker/CTemplateWriter.cpp \
Resource/Cooker/CTextureEncoder.cpp \
Resource/Cooker/CWorldCooker.cpp \
Resource/Factory/CAnimSetLoader.cpp \
@ -255,14 +273,12 @@ SOURCES += \
Resource/Factory/CScanLoader.cpp \
Resource/Factory/CScriptLoader.cpp \
Resource/Factory/CStringLoader.cpp \
Resource/Factory/CTemplateLoader.cpp \
Resource/Factory/CTextureDecoder.cpp \
Resource/Factory/CWorldLoader.cpp \
Resource/Model/CBasicModel.cpp \
Resource/Model/CModel.cpp \
Resource/Model/CStaticModel.cpp \
Resource/Model/SSurface.cpp \
Resource/Script/CMasterTemplate.cpp \
Resource/Script/CScriptObject.cpp \
Resource/Script/CScriptTemplate.cpp \
Resource/CCollisionMesh.cpp \
@ -296,8 +312,6 @@ SOURCES += \
OpenGL/GLCommon.cpp \
ScriptExtra/CRadiusSphereExtra.cpp \
Resource/Cooker/CAreaCooker.cpp \
Resource/Script/IPropertyTemplate.cpp \
Resource/Script/IProperty.cpp \
Scene/FShowFlags.cpp \
Scene/CScene.cpp \
Scene/CSceneIterator.cpp \
@ -340,4 +354,22 @@ SOURCES += \
CompressionUtil.cpp \
IUIRelay.cpp \
GameProject\COpeningBanner.cpp \
IProgressNotifier.cpp
IProgressNotifier.cpp \
Resource/Script/Property/CPropertyNameGenerator.cpp \
Resource/Script/Property/IProperty.cpp \
Resource/Script/Property/CStructProperty.cpp \
Resource/Script/Property/CFlagsProperty.cpp \
Resource/Script/CGameTemplate.cpp \
Resource/Script/NPropertyMap.cpp \
Resource/Script/NGameList.cpp
# Codegen
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
CODEGEN_OUT_PATH = $$BUILD_DIR/Core/codegen_build/auto_codegen.cpp
CODEGEN_SRC_PATH = $$PWD
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
# Library Sources
SOURCES += $$EXTERNALS_DIR/lzo-2.10/src/lzo_init.c \
$$EXTERNALS_DIR/lzo-2.10/src/lzo1x_9x.c \
$$EXTERNALS_DIR/lzo-2.10/src/lzo1x_d1.c

View File

@ -43,7 +43,7 @@ void ApplyGeneratedName(CResourceEntry *pEntry, const TString& rkDir, const TStr
// trying to keep these as consistent with Retro's naming scheme as possible, and
// for some reason in MP3 they started using all lowercase folder names...
if (pEntry->Game() >= eCorruptionProto)
if (pEntry->Game() >= EGame::CorruptionProto)
SanitizedDir = SanitizedDir.ToLower();
pNewDir = pEntry->ResourceStore()->GetVirtualDirectory(SanitizedDir, true);
@ -245,9 +245,9 @@ void GenerateAssetNames(CGameProject *pProj)
{
CMaterialPass *pPass = pMat->Pass(iPass);
bool IsLightmap = ( (pArea->Game() <= eEchoes && pMat->Options().HasFlag(CMaterial::eLightmap) && iPass == 0) ||
(pArea->Game() >= eCorruptionProto && pPass->Type() == "DIFF") );
bool IsBloomLightmap = (pArea->Game() >= eCorruptionProto && pPass->Type() == "BLOL");
bool IsLightmap = ( (pArea->Game() <= EGame::Echoes && pMat->Options().HasFlag(CMaterial::eLightmap) && iPass == 0) ||
(pArea->Game() >= EGame::CorruptionProto && pPass->Type() == "DIFF") );
bool IsBloomLightmap = (pArea->Game() >= EGame::CorruptionProto && pPass->Type() == "BLOL");
TString TexName;
@ -283,7 +283,8 @@ void GenerateAssetNames(CGameProject *pProj)
for (u32 iInst = 0; iInst < pLayer->NumInstances(); iInst++)
{
CScriptObject *pInst = pLayer->InstanceByIndex(iInst);
CScriptObject* pInst = pLayer->InstanceByIndex(iInst);
CStructProperty* pProperties = pInst->Template()->Properties();
if (pInst->ObjectTypeID() == 0x42 || pInst->ObjectTypeID() == FOURCC('POIN'))
{
@ -291,13 +292,13 @@ void GenerateAssetNames(CGameProject *pProj)
if (Name.StartsWith("POI_", false))
{
TIDString ScanIDString = (pProj->Game() <= ePrime ? "0x4:0x0" : "0xBDBEC295:0xB94E9BE7");
TAssetProperty *pScanProperty = TPropCast<TAssetProperty>(pInst->PropertyByIDString(ScanIDString));
TIDString ScanIDString = (pProj->Game() <= EGame::Prime ? "0x4:0x0" : "0xBDBEC295:0xB94E9BE7");
CAssetProperty *pScanProperty = TPropCast<CAssetProperty>(pProperties->ChildByIDString(ScanIDString));
ASSERT(pScanProperty); // Temporary assert to remind myself later to update this code when uncooked properties are added to the template
if (pScanProperty)
{
CAssetID ScanID = pScanProperty->Get();
CAssetID ScanID = pScanProperty->Value(pInst->PropertyData());
CResourceEntry *pEntry = pStore->FindEntry(ScanID);
if (pEntry && !pEntry->IsNamed())
@ -326,13 +327,13 @@ void GenerateAssetNames(CGameProject *pProj)
if (Name.EndsWith(".STRG", false))
{
u32 StringPropID = (pProj->Game() <= ePrime ? 0x4 : 0x9182250C);
TAssetProperty *pStringProperty = TPropCast<TAssetProperty>(pInst->Properties()->PropertyByID(StringPropID));
u32 StringPropID = (pProj->Game() <= EGame::Prime ? 0x4 : 0x9182250C);
CAssetProperty *pStringProperty = TPropCast<CAssetProperty>(pProperties->ChildByID(StringPropID));
ASSERT(pStringProperty); // Temporary assert to remind myself later to update this code when uncooked properties are added to the template
if (pStringProperty)
{
CAssetID StringID = pStringProperty->Get();
CAssetID StringID = pStringProperty->Value(pInst->PropertyData());
CResourceEntry *pEntry = pStore->FindEntry(StringID);
if (pEntry && !pEntry->IsNamed())
@ -352,13 +353,13 @@ void GenerateAssetNames(CGameProject *pProj)
else if (pInst->ObjectTypeID() == 0x0 || pInst->ObjectTypeID() == FOURCC('ACTR') ||
pInst->ObjectTypeID() == 0x8 || pInst->ObjectTypeID() == FOURCC('PLAT'))
{
u32 ModelPropID = (pProj->Game() <= ePrime ? (pInst->ObjectTypeID() == 0x0 ? 0xA : 0x6) : 0xC27FFA8F);
TAssetProperty *pModelProperty = TPropCast<TAssetProperty>(pInst->Properties()->PropertyByID(ModelPropID));
u32 ModelPropID = (pProj->Game() <= EGame::Prime ? (pInst->ObjectTypeID() == 0x0 ? 0xA : 0x6) : 0xC27FFA8F);
CAssetProperty *pModelProperty = TPropCast<CAssetProperty>(pProperties->ChildByID(ModelPropID));
ASSERT(pModelProperty); // Temporary assert to remind myself later to update this code when uncooked properties are added to the template
if (pModelProperty)
{
CAssetID ModelID = pModelProperty->Get();
CAssetID ModelID = pModelProperty->Value(pInst->PropertyData());
CResourceEntry *pEntry = pStore->FindEntry(ModelID);
if (pEntry && !pEntry->IsCategorized())
@ -414,8 +415,8 @@ void GenerateAssetNames(CGameProject *pProj)
{
CMaterialPass *pPass = pMat->Pass(iPass);
bool IsLightmap = ( (pMat->Version() <= eEchoes && pMat->Options().HasFlag(CMaterial::eLightmap) && iPass == 0) ||
(pMat->Version() >= eCorruptionProto && pPass->Type() == "DIFF") );
bool IsLightmap = ( (pMat->Version() <= EGame::Echoes && pMat->Options().HasFlag(CMaterial::eLightmap) && iPass == 0) ||
(pMat->Version() >= EGame::CorruptionProto && pPass->Type() == "DIFF") );
if (IsLightmap)
{
@ -484,7 +485,7 @@ void GenerateAssetNames(CGameProject *pProj)
// Generate animation format names
// Hacky syntax because animsets are under eAnimSet in MP1/2 and eCharacter in MP3/DKCR
Log::Write("Processing animation data");
CResourceIterator *pIter = (pProj->Game() <= eEchoes ? (CResourceIterator*) new TResourceIterator<eAnimSet> : (CResourceIterator*) new TResourceIterator<eCharacter>);
CResourceIterator *pIter = (pProj->Game() <= EGame::Echoes ? (CResourceIterator*) new TResourceIterator<eAnimSet> : (CResourceIterator*) new TResourceIterator<eCharacter>);
CResourceIterator& It = *pIter;
for (; It; ++It)
@ -504,7 +505,7 @@ void GenerateAssetNames(CGameProject *pProj)
if (pkChar->pSkeleton) ApplyGeneratedName(pkChar->pSkeleton->Entry(), SetDir, CharName);
if (pkChar->pSkin) ApplyGeneratedName(pkChar->pSkin->Entry(), SetDir, CharName);
if (pProj->Game() >= eCorruptionProto && pProj->Game() <= eCorruption && pkChar->ID == 0)
if (pProj->Game() >= EGame::CorruptionProto && pProj->Game() <= EGame::Corruption && pkChar->ID == 0)
{
CResourceEntry *pAnimDataEntry = gpResourceStore->FindEntry( pkChar->AnimDataID );
@ -606,7 +607,7 @@ void GenerateAssetNames(CGameProject *pProj)
CScan *pScan = (CScan*) It->Load();
TString ScanName;
if (pProj->Game() >= eEchoesDemo)
if (pProj->Game() >= EGame::EchoesDemo)
{
CAssetID DisplayAsset = pScan->LogbookDisplayAssetID();
CResourceEntry *pEntry = pStore->FindEntry(DisplayAsset);
@ -621,7 +622,7 @@ void GenerateAssetNames(CGameProject *pProj)
ApplyGeneratedName(pScan->Entry(), It->DirectoryPath(), ScanName);
if (!ScanName.IsEmpty() && pProj->Game() <= ePrime)
if (!ScanName.IsEmpty() && pProj->Game() <= EGame::Prime)
{
CAssetID FrameID = pScan->GuiFrame();
CResourceEntry *pEntry = pStore->FindEntry(FrameID);

View File

@ -36,7 +36,7 @@ bool CAssetNameMap::SaveAssetNames(TString Path /*= ""*/)
if (Path.IsEmpty())
Path = DefaultNameMapPath(mIDLength);
EGame Game = (mIDLength == e32Bit ? ePrime : eCorruption);
EGame Game = (mIDLength == e32Bit ? EGame::Prime : EGame::Corruption);
CXMLWriter Writer(Path, "AssetNameMap", 0, Game);
Serialize(Writer);
return Writer.Save();
@ -58,7 +58,7 @@ bool CAssetNameMap::GetNameInfo(CAssetID ID, TString& rOutDirectory, TString& rO
else
{
EGame Game = (ID.Length() == e32Bit ? ePrime : eCorruption);
EGame Game = (ID.Length() == e32Bit ? EGame::Prime : EGame::Corruption);
rOutDirectory = CResourceStore::StaticDefaultResourceDirPath(Game);
rOutName = ID.ToString();
rOutAutoGenDir = true;
@ -133,7 +133,7 @@ void CAssetNameMap::CopyFromStore(CResourceStore *pStore /*= gpResourceStore*/)
// ************ PRIVATE ************
void CAssetNameMap::Serialize(IArchive& rArc)
{
rArc << SERIAL_CONTAINER("AssetNameMap", mMap, "Asset");
rArc << SerialParameter("AssetNameMap", mMap);
if (rArc.IsReader())
PostLoadValidate();

View File

@ -28,7 +28,11 @@ class CAssetNameMap
void Serialize(IArchive& rArc)
{
rArc << SERIAL_AUTO(Name) << SERIAL_AUTO(Directory) << SERIAL_AUTO(Type) << SERIAL_AUTO(AutoGenName) << SERIAL_AUTO(AutoGenDir);
rArc << SerialParameter("Name", Name)
<< SerialParameter("Directory", Directory)
<< SerialParameter("Type", Type)
<< SerialParameter("AutoGenName", AutoGenName)
<< SerialParameter("AutoGenDir", AutoGenDir);
}
bool operator<(const SAssetNameInfo& rkOther) const

View File

@ -1,11 +1,10 @@
#include "CDependencyTree.h"
#include "Core/GameProject/CGameProject.h"
#include "Core/Resource/Animation/CAnimSet.h"
#include "Core/Resource/Script/CMasterTemplate.h"
#include "Core/Resource/Script/CGameTemplate.h"
#include "Core/Resource/Script/CScriptLayer.h"
#include "Core/Resource/Script/CScriptObject.h"
CDependencyNodeFactory gDependencyNodeFactory;
#include "Core/Resource/Script/NGameList.h"
// ************ IDependencyNode ************
IDependencyNode::~IDependencyNode()
@ -31,6 +30,24 @@ void IDependencyNode::GetAllResourceReferences(std::set<CAssetID>& rOutSet) cons
mChildren[iChild]->GetAllResourceReferences(rOutSet);
}
// Serialization constructor
IDependencyNode* IDependencyNode::ArchiveConstructor(EDependencyNodeType Type)
{
switch (Type)
{
case eDNT_DependencyTree: return new CDependencyTree;
case eDNT_ResourceDependency: return new CResourceDependency;
case eDNT_ScriptInstance: return new CScriptInstanceDependency;
case eDNT_ScriptProperty: return new CPropertyDependency;
case eDNT_CharacterProperty: return new CCharPropertyDependency;
case eDNT_SetCharacter: return new CSetCharacterDependency;
case eDNT_SetAnimation: return new CSetAnimationDependency;
case eDNT_AnimEvent: return new CAnimEventDependency;
case eDNT_Area: return new CAreaDependencyTree;
default: ASSERT(false); return nullptr;
}
}
// ************ CDependencyTree ************
EDependencyNodeType CDependencyTree::Type() const
{
@ -39,7 +56,7 @@ EDependencyNodeType CDependencyTree::Type() const
void CDependencyTree::Serialize(IArchive& rArc)
{
rArc << SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
rArc << SerialParameter("Children", mChildren);
}
void CDependencyTree::AddChild(IDependencyNode *pNode)
@ -78,7 +95,7 @@ EDependencyNodeType CResourceDependency::Type() const
void CResourceDependency::Serialize(IArchive& rArc)
{
rArc << SERIAL("ID", mID);
rArc << SerialParameter("ID", mID);
}
void CResourceDependency::GetAllResourceReferences(std::set<CAssetID>& rOutSet) const
@ -99,7 +116,7 @@ EDependencyNodeType CPropertyDependency::Type() const
void CPropertyDependency::Serialize(IArchive& rArc)
{
rArc << SERIAL("PropertyID", mIDString);
rArc << SerialParameter("PropertyID", mIDString);
CResourceDependency::Serialize(rArc);
}
@ -112,7 +129,7 @@ EDependencyNodeType CCharPropertyDependency::Type() const
void CCharPropertyDependency::Serialize(IArchive& rArc)
{
CPropertyDependency::Serialize(rArc);
rArc << SERIAL("CharIndex", mUsedChar);
rArc << SerialParameter("CharIndex", mUsedChar);
}
// ************ CScriptInstanceDependency ************
@ -123,8 +140,8 @@ EDependencyNodeType CScriptInstanceDependency::Type() const
void CScriptInstanceDependency::Serialize(IArchive& rArc)
{
rArc << SERIAL("ObjectType", mObjectType)
<< SERIAL_ABSTRACT_CONTAINER("Properties", mChildren, "Property", &gDependencyNodeFactory);
rArc << SerialParameter("ObjectType", mObjectType)
<< SerialParameter("Properties", mChildren);
}
// Static
@ -132,28 +149,32 @@ CScriptInstanceDependency* CScriptInstanceDependency::BuildTree(CScriptObject *p
{
CScriptInstanceDependency *pInst = new CScriptInstanceDependency();
pInst->mObjectType = pInstance->ObjectTypeID();
ParseStructDependencies(pInst, pInstance->Properties());
ParseStructDependencies(pInst, pInstance, pInstance->Template()->Properties());
return pInst;
}
void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependency *pInst, CPropertyStruct *pStruct)
void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependency* pInst, CScriptObject* pInstance, CStructProperty *pStruct)
{
// Recursive function for parsing script dependencies and loading them into the script instance dependency
for (u32 iProp = 0; iProp < pStruct->Count(); iProp++)
void* pPropertyData = pInstance->PropertyData();
for (u32 PropertyIdx = 0; PropertyIdx < pStruct->NumChildren(); PropertyIdx++)
{
IProperty *pProp = pStruct->PropertyByIndex(iProp);
IProperty *pProp = pStruct->ChildByIndex(PropertyIdx);
EPropertyType Type = pProp->Type();
if (Type == eStructProperty || Type == eArrayProperty)
ParseStructDependencies(pInst, static_cast<CPropertyStruct*>(pProp));
// Technically we aren't parsing array children, but it's not really worth refactoring this function
// to support it when there aren't any array properties that contain any asset references anyway...
if (Type == EPropertyType::Struct)
ParseStructDependencies(pInst, pInstance, TPropCast<CStructProperty>(pProp));
else if (Type == eSoundProperty)
else if (Type == EPropertyType::Sound)
{
u32 SoundID = static_cast<TSoundProperty*>(pProp)->Get();
u32 SoundID = TPropCast<CSoundProperty>(pProp)->Value(pPropertyData);
if (SoundID != -1)
{
CGameProject *pProj = pStruct->Instance()->Area()->Entry()->Project();
CGameProject *pProj = pInstance->Area()->Entry()->Project();
SSoundInfo Info = pProj->AudioManager()->GetSoundInfo(SoundID);
if (Info.pAudioGroup)
@ -164,9 +185,9 @@ void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependenc
}
}
else if (Type == eAssetProperty)
else if (Type == EPropertyType::Asset)
{
CAssetID ID = static_cast<TAssetProperty*>(pProp)->Get();
CAssetID ID = TPropCast<CAssetProperty>(pProp)->Value(pPropertyData);
if (ID.IsValid())
{
@ -175,16 +196,15 @@ void CScriptInstanceDependency::ParseStructDependencies(CScriptInstanceDependenc
}
}
else if (Type == eCharacterProperty)
else if (Type == EPropertyType::AnimationSet)
{
TCharacterProperty *pChar = static_cast<TCharacterProperty*>(pProp);
CAnimationParameters Params = pChar->Get();
CAnimationParameters Params = TPropCast<CAnimationSetProperty>(pProp)->Value(pPropertyData);
CAssetID ID = Params.ID();
if (ID.IsValid())
{
// Character sets are removed starting in MP3, so we only need char property dependencies in Echoes and earlier
if (pStruct->Instance()->Area()->Game() <= eEchoes)
if (pStruct->Game() <= EGame::Echoes)
{
CCharPropertyDependency *pDep = new CCharPropertyDependency(pProp->IDString(true), ID, Params.CharacterIndex());
pInst->mChildren.push_back(pDep);
@ -207,8 +227,8 @@ EDependencyNodeType CSetCharacterDependency::Type() const
void CSetCharacterDependency::Serialize(IArchive& rArc)
{
rArc << SERIAL("CharSetIndex", mCharSetIndex)
<< SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
rArc << SerialParameter("CharSetIndex", mCharSetIndex)
<< SerialParameter("Children", mChildren);
}
CSetCharacterDependency* CSetCharacterDependency::BuildTree(const SSetCharacter& rkChar)
@ -252,8 +272,8 @@ EDependencyNodeType CSetAnimationDependency::Type() const
void CSetAnimationDependency::Serialize(IArchive& rArc)
{
rArc << SERIAL_CONTAINER("CharacterIndices", mCharacterIndices, "Index")
<< SERIAL_ABSTRACT_CONTAINER("Children", mChildren, "Child", &gDependencyNodeFactory);
rArc << SerialParameter("CharacterIndices", mCharacterIndices)
<< SerialParameter("Children", mChildren);
}
CSetAnimationDependency* CSetAnimationDependency::BuildTree(const CAnimSet *pkOwnerSet, u32 AnimIndex)
@ -279,7 +299,7 @@ CSetAnimationDependency* CSetAnimationDependency::BuildTree(const CAnimSet *pkOw
const CAnimPrimitive& rkPrim = *Iter;
pTree->AddDependency(rkPrim.Animation());
if (pkOwnerSet->Game() >= eEchoesDemo)
if (pkOwnerSet->Game() >= EGame::EchoesDemo)
{
CAnimEventData *pEvents = pkOwnerSet->AnimationEventData(rkPrim.ID());
ASSERT(pEvents && !pEvents->Entry());
@ -299,7 +319,7 @@ EDependencyNodeType CAnimEventDependency::Type() const
void CAnimEventDependency::Serialize(IArchive& rArc)
{
CResourceDependency::Serialize(rArc);
rArc << SERIAL("CharacterIndex", mCharIndex);
rArc << SerialParameter("CharacterIndex", mCharIndex);
}
// ************ CAreaDependencyTree ************
@ -311,7 +331,7 @@ EDependencyNodeType CAreaDependencyTree::Type() const
void CAreaDependencyTree::Serialize(IArchive& rArc)
{
CDependencyTree::Serialize(rArc);
rArc << SERIAL_CONTAINER("LayerOffsets", mLayerOffsets, "Offset");
rArc << SerialParameter("LayerOffsets", mLayerOffsets);
}
void CAreaDependencyTree::AddScriptLayer(CScriptLayer *pLayer, const std::vector<CAssetID>& rkExtraDeps)
@ -326,7 +346,7 @@ void CAreaDependencyTree::AddScriptLayer(CScriptLayer *pLayer, const std::vector
ASSERT(pTree != nullptr);
// Note: MP2+ need to track all instances (not just instances with dependencies) to be able to build the layer module list
if (pTree->NumChildren() > 0 || pLayer->Area()->Game() >= eEchoesDemo)
if (pTree->NumChildren() > 0 || pLayer->Area()->Game() >= EGame::EchoesDemo)
{
mChildren.push_back(pTree);
pTree->GetAllResourceReferences(UsedIDs);
@ -341,7 +361,7 @@ void CAreaDependencyTree::AddScriptLayer(CScriptLayer *pLayer, const std::vector
void CAreaDependencyTree::GetModuleDependencies(EGame Game, std::vector<TString>& rModuleDepsOut, std::vector<u32>& rModuleLayerOffsetsOut) const
{
CMasterTemplate *pMaster = CMasterTemplate::MasterForGame(Game);
CGameTemplate *pGame = NGameList::GetGameTemplate(Game);
// Output module list will be split per-script layer
// The output offset list contains two offsets per layer - start index and end index
@ -367,7 +387,7 @@ void CAreaDependencyTree::GetModuleDependencies(EGame Game, std::vector<TString>
if (UsedObjectTypes.find(ObjType) == UsedObjectTypes.end())
{
// Get the module list for this object type and check whether any of them are new before adding them to the output list
CScriptTemplate *pTemplate = pMaster->TemplateByID(ObjType);
CScriptTemplate *pTemplate = pGame->TemplateByID(ObjType);
const std::vector<TString>& rkModules = pTemplate->RequiredModules();
for (u32 iMod = 0; iMod < rkModules.size(); iMod++)

View File

@ -8,7 +8,7 @@
class CScriptLayer;
class CScriptObject;
class CPropertyStruct;
class CStructProperty;
class CAnimSet;
class CAnimationParameters;
struct SSetCharacter;
@ -40,6 +40,9 @@ public:
virtual void GetAllResourceReferences(std::set<CAssetID>& rOutSet) const;
virtual bool HasDependency(const CAssetID& rkID) const;
// Serialization constructor
static IDependencyNode* ArchiveConstructor(EDependencyNodeType Type);
// Accessors
inline u32 NumChildren() const { return mChildren.size(); }
inline IDependencyNode* ChildByIndex(u32 Index) const { return mChildren[Index]; }
@ -142,7 +145,7 @@ public:
// Static
static CScriptInstanceDependency* BuildTree(CScriptObject *pInstance);
protected:
static void ParseStructDependencies(CScriptInstanceDependency *pTree, CPropertyStruct *pStruct);
static void ParseStructDependencies(CScriptInstanceDependency *pTree, CScriptObject* pInstance, CStructProperty *pStruct);
};
// Node representing an animset character. Indicates what index the character is within the animset.
@ -223,28 +226,5 @@ public:
inline u32 ScriptLayerOffset(u32 LayerIdx) const { return mLayerOffsets[LayerIdx]; }
};
// Dependency node factory for serialization
class CDependencyNodeFactory
{
public:
IDependencyNode* SpawnObject(u32 NodeID)
{
switch (NodeID)
{
case eDNT_DependencyTree: return new CDependencyTree;
case eDNT_ResourceDependency: return new CResourceDependency;
case eDNT_ScriptInstance: return new CScriptInstanceDependency;
case eDNT_ScriptProperty: return new CPropertyDependency;
case eDNT_CharacterProperty: return new CCharPropertyDependency;
case eDNT_SetCharacter: return new CSetCharacterDependency;
case eDNT_SetAnimation: return new CSetAnimationDependency;
case eDNT_AnimEvent: return new CAnimEventDependency;
case eDNT_Area: return new CAreaDependencyTree;
default: ASSERT(false); return nullptr;
}
}
};
extern CDependencyNodeFactory gDependencyNodeFactory;
#endif // CDEPENDENCYTREE

View File

@ -4,12 +4,14 @@
#include "CResourceStore.h"
#include "Core/CompressionUtil.h"
#include "Core/Resource/CWorld.h"
#include "Core/Resource/Script/CMasterTemplate.h"
#include "Core/Resource/Script/CGameTemplate.h"
#include <Common/AssertMacro.h>
#include <Common/CScopedTimer.h>
#include <Common/FileIO.h>
#include <Common/FileUtil.h>
#include <Common/Serialization/CXMLWriter.h>
#include <nod/nod.hpp>
#include <tinyxml2.h>
#define LOAD_PAKS 1
@ -27,8 +29,8 @@ CGameExporter::CGameExporter(EDiscType DiscType, EGame Game, bool FrontEnd, EReg
, mFrontEnd(FrontEnd)
, mpProgress(nullptr)
{
ASSERT(mGame != eUnknownGame);
ASSERT(mRegion != eRegion_Unknown);
ASSERT(mGame != EGame::Invalid);
ASSERT(mRegion != ERegion::Unknown);
}
bool CGameExporter::Export(nod::DiscBase *pDisc, const TString& rkOutputDir, CAssetNameMap *pNameMap, CGameInfo *pGameInfo, IProgressNotifier *pProgress)
@ -112,15 +114,15 @@ bool CGameExporter::ShouldExportDiscNode(const nod::Node *pkNode, bool IsInRoot)
switch (mGame)
{
case ePrime:
case EGame::Prime:
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "MP1JPN") ||
(mDiscType == eDT_Trilogy && pkNode->getName() == "MP1") );
case eEchoes:
case EGame::Echoes:
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "MP2JPN") ||
(mDiscType == eDT_Trilogy && pkNode->getName() == "MP2") );
case eCorruption:
case EGame::Corruption:
return (mDiscType == eDT_Trilogy && pkNode->getName() == "MP3");
default:
@ -140,15 +142,15 @@ bool CGameExporter::ShouldExportDiscNode(const nod::Node *pkNode, bool IsInRoot)
switch (mGame)
{
case ePrime:
case EGame::Prime:
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "rs5mp1jpn_p.dol") ||
(mDiscType == eDT_Trilogy && pkNode->getName() == "rs5mp1_p.dol") );
case eEchoes:
case EGame::Echoes:
return ( (mDiscType == eDT_WiiDeAsobu && pkNode->getName() == "rs5mp2jpn_p.dol") ||
(mDiscType == eDT_Trilogy && pkNode->getName() == "rs5mp2_p.dol") );
case eCorruption:
case EGame::Corruption:
return (mDiscType == eDT_Trilogy && pkNode->getName() == "rs5mp3_p.dol");
default:
@ -176,11 +178,11 @@ bool CGameExporter::ExtractDiscData()
FileUtil::MakeDirectory(AbsDiscDir);
// Extract disc filesystem
nod::Partition *pDataPartition = mpDisc->getDataPartition();
nod::IPartition *pDataPartition = mpDisc->getDataPartition();
nod::ExtractionContext Context;
Context.force = false;
Context.progressCB = [&](const std::string& rkDesc, float ProgressPercent) {
mpProgress->Report((int) (ProgressPercent * 10000), 10000, rkDesc);
Context.progressCB = [&](const std::string_view rkDesc, float ProgressPercent) {
mpProgress->Report((int) (ProgressPercent * 10000), 10000, rkDesc.data());
};
TString FilesDir = AbsDiscDir + "files/";
@ -223,7 +225,7 @@ bool CGameExporter::ExtractDiscNodeRecursive(const nod::Node *pkNode, const TStr
if (Iter->getKind() == nod::Node::Kind::File)
{
TString FilePath = rkDir + Iter->getName();
TString FilePath = rkDir + Iter->getName().data();
bool Success = Iter->extractToDirectory(*rkDir.ToUTF16(), rkContext);
if (!Success) return false;
@ -237,7 +239,7 @@ bool CGameExporter::ExtractDiscNodeRecursive(const nod::Node *pkNode, const TStr
else
{
TString Subdir = rkDir + Iter->getName() + "/";
TString Subdir = rkDir + Iter->getName().data() + "/";
bool Success = FileUtil::MakeDirectory(Subdir);
if (!Success) return false;
@ -274,7 +276,7 @@ void CGameExporter::LoadPaks()
CPackage *pPackage = new CPackage(mpProject, PakPath.GetFileName(false), RelPakPath);
// MP1-MP3Proto
if (mGame < eCorruption)
if (mGame < EGame::Corruption)
{
u32 PakVersion = Pak.ReadLong();
Pak.Seek(0x4, SEEK_CUR);
@ -392,7 +394,7 @@ void CGameExporter::LoadPaks()
mResourceMap[ResID] = SResourceInstance { PakPath, ResID, Type, Offset, Size, Compressed, false };
// Check for duplicate resources (unnecessary for DKCR)
if (mGame != eReturns)
if (mGame != EGame::DKCReturns)
{
if (Type == "MREA")
{
@ -434,9 +436,9 @@ void CGameExporter::LoadResource(const SResourceInstance& rkResource, std::vecto
// Handle compression
if (rkResource.Compressed)
{
bool ZlibCompressed = (mGame <= eEchoesDemo || mGame == eReturns);
bool ZlibCompressed = (mGame <= EGame::EchoesDemo || mGame == EGame::DKCReturns);
if (mGame <= eCorruptionProto)
if (mGame <= EGame::CorruptionProto)
{
std::vector<u8> CompressedData(rkResource.PakSize);
@ -682,14 +684,14 @@ TString CGameExporter::MakeWorldName(CAssetID WorldID)
{
// World names are basically formatted differently in every game...
// MP1 demo - Remove ! from the beginning
if (mGame == ePrimeDemo)
if (mGame == EGame::PrimeDemo)
{
if (WorldName.StartsWith('!'))
WorldName = WorldName.ChopFront(1);
}
// MP1 - Remove prefix characters and ending date
else if (mGame == ePrime)
else if (mGame == EGame::Prime)
{
WorldName = WorldName.ChopFront(2);
bool StartedDate = false;
@ -708,7 +710,7 @@ TString CGameExporter::MakeWorldName(CAssetID WorldID)
}
// MP2 demo - Use text between the first and second underscores
else if (mGame == eEchoesDemo)
else if (mGame == EGame::EchoesDemo)
{
u32 UnderscoreA = WorldName.IndexOf('_');
u32 UnderscoreB = WorldName.IndexOf('_', UnderscoreA + 1);
@ -718,7 +720,7 @@ TString CGameExporter::MakeWorldName(CAssetID WorldID)
}
// MP2 - Remove text before first underscore and after last underscore, strip remaining underscores (except multiplayer maps, which have one underscore)
else if (mGame == eEchoes)
else if (mGame == EGame::Echoes)
{
u32 FirstUnderscore = WorldName.IndexOf('_');
u32 LastUnderscore = WorldName.LastIndexOf('_');
@ -732,7 +734,7 @@ TString CGameExporter::MakeWorldName(CAssetID WorldID)
}
// MP3 proto - Remove ! from the beginning and all text after last underscore
else if (mGame == eCorruptionProto)
else if (mGame == EGame::CorruptionProto)
{
if (WorldName.StartsWith('!'))
WorldName = WorldName.ChopFront(1);
@ -742,7 +744,7 @@ TString CGameExporter::MakeWorldName(CAssetID WorldID)
}
// MP3 - Remove text after last underscore
else if (mGame == eCorruption)
else if (mGame == EGame::Corruption)
{
u32 LastUnderscore = WorldName.LastIndexOf('_');
@ -751,7 +753,7 @@ TString CGameExporter::MakeWorldName(CAssetID WorldID)
}
// DKCR - Remove text prior to first underscore
else if (mGame == eReturns)
else if (mGame == EGame::DKCReturns)
{
u32 Underscore = WorldName.IndexOf('_');
WorldName = WorldName.ChopFront(Underscore + 1);

View File

@ -24,7 +24,7 @@ bool CGameInfo::LoadGameInfo(TString Path)
bool CGameInfo::SaveGameInfo(TString Path /*= ""*/)
{
ASSERT(mGame != eUnknownGame); // can't save game info that was never loaded
ASSERT(mGame != EGame::Invalid); // can't save game info that was never loaded
if (Path.IsEmpty()) Path = GetDefaultGameInfoPath(mGame);
CXMLWriter Writer(Path, "GameInfo", 0, mGame);
@ -35,16 +35,16 @@ bool CGameInfo::SaveGameInfo(TString Path /*= ""*/)
void CGameInfo::Serialize(IArchive& rArc)
{
// Validate game
if (rArc.IsReader() && mGame != eUnknownGame)
if (rArc.IsReader() && mGame != EGame::Invalid)
{
ASSERT(mGame == rArc.Game());
}
// Serialize data
rArc << SERIAL_CONTAINER("GameBuilds", mBuilds, "Build");
rArc << SerialParameter("GameBuilds", mBuilds);
if (mGame <= ePrime)
rArc << SERIAL_CONTAINER("AreaNameMap", mAreaNameMap, "AreaName");
if (mGame <= EGame::Prime)
rArc << SerialParameter("AreaNameMap", mAreaNameMap);
}
TString CGameInfo::GetBuildName(float BuildVer, ERegion Region) const
@ -69,9 +69,9 @@ TString CGameInfo::GetAreaName(const CAssetID &rkID) const
// ************ STATIC ************
EGame CGameInfo::RoundGame(EGame Game)
{
if (Game == ePrimeDemo) return ePrime;
if (Game == eEchoesDemo) return eEchoes;
if (Game == eCorruptionProto) return eCorruption;
if (Game == EGame::PrimeDemo) return EGame::Prime;
if (Game == EGame::EchoesDemo) return EGame::Echoes;
if (Game == EGame::CorruptionProto) return EGame::Corruption;
return Game;
}
@ -79,7 +79,7 @@ TString CGameInfo::GetDefaultGameInfoPath(EGame Game)
{
Game = RoundGame(Game);
if (Game == eUnknownGame)
if (Game == EGame::Invalid)
return "";
TString GameName = GetGameShortName(Game);

View File

@ -11,6 +11,8 @@
const TString gkGameInfoDir = "../resources/gameinfo";
const TString gkGameInfoExt = "xml";
//@todo merge this class into CGameTemplate
// they serve similar purposes, no real reason for them to be different classes
class CGameInfo
{
EGame mGame;
@ -24,7 +26,9 @@ class CGameInfo
void Serialize(IArchive& rArc)
{
rArc << SERIAL_AUTO(Version) << SERIAL_AUTO(Region) << SERIAL_AUTO(Name);
rArc << SerialParameter("Version", Version)
<< SerialParameter("Region", Region)
<< SerialParameter("Name", Name);
}
};
std::vector<SBuildInfo> mBuilds;
@ -34,7 +38,7 @@ class CGameInfo
public:
CGameInfo()
: mGame(eUnknownGame)
: mGame(EGame::Invalid)
{}
bool LoadGameInfo(EGame Game);

View File

@ -1,7 +1,6 @@
#include "CGameProject.h"
#include "IUIRelay.h"
#include "Core/Resource/Factory/CTemplateLoader.h"
#include "Core/Resource/Script/CMasterTemplate.h"
#include "Core/Resource/Script/CGameTemplate.h"
#include <Common/Serialization/XML.h>
#include <nod/nod.hpp>
@ -36,10 +35,10 @@ bool CGameProject::Save()
bool CGameProject::Serialize(IArchive& rArc)
{
rArc << SERIAL("Name", mProjectName)
<< SERIAL("Region", mRegion)
<< SERIAL("GameID", mGameID)
<< SERIAL("BuildVersion", mBuildVersion);
rArc << SerialParameter("Name", mProjectName)
<< SerialParameter("Region", mRegion)
<< SerialParameter("GameID", mGameID)
<< SerialParameter("BuildVersion", mBuildVersion);
// Serialize package list
std::vector<TString> PackageList;
@ -50,7 +49,7 @@ bool CGameProject::Serialize(IArchive& rArc)
PackageList.push_back( mPackages[iPkg]->DefinitionPath(true) );
}
rArc << SERIAL_CONTAINER("Packages", PackageList, "Package");
rArc << SerialParameter("Packages", PackageList);
// Load packages
if (rArc.IsReader())
@ -82,9 +81,9 @@ bool CGameProject::BuildISO(const TString& rkIsoPath, IProgressNotifier *pProgre
ASSERT( FileUtil::IsValidPath(rkIsoPath, false) );
ASSERT( !IsWiiDeAsobu() && !IsTrilogy() );
auto ProgressCallback = [&](float ProgressPercent, const nod::SystemString& rkInfoString, size_t)
auto ProgressCallback = [&](float ProgressPercent, const nod::SystemStringView& rkInfoString, size_t)
{
pProgress->Report((int) (ProgressPercent * 10000), 10000, TWideString(rkInfoString).ToUTF8());
pProgress->Report((int) (ProgressPercent * 10000), 10000, TWideString(rkInfoString.data()).ToUTF8());
};
pProgress->SetTask(0, "Building " + rkIsoPath.GetFileName());
@ -108,9 +107,9 @@ bool CGameProject::MergeISO(const TString& rkIsoPath, nod::DiscWii *pOriginalIso
ASSERT( IsWiiDeAsobu() || IsTrilogy() );
ASSERT( pOriginalIso != nullptr );
auto ProgressCallback = [&](float ProgressPercent, const nod::SystemString& rkInfoString, size_t)
auto ProgressCallback = [&](float ProgressPercent, const nod::SystemStringView& rkInfoString, size_t)
{
pProgress->Report((int) (ProgressPercent * 10000), 10000, TWideString(rkInfoString).ToUTF8());
pProgress->Report((int) (ProgressPercent * 10000), 10000, TWideString(rkInfoString.data()).ToUTF8());
};
pProgress->SetTask(0, "Building " + rkIsoPath.GetFileName());
@ -266,7 +265,6 @@ CGameProject* CGameProject::LoadProject(const TString& rkProjPath, IProgressNoti
return nullptr;
}
CTemplateLoader::LoadGameTemplates(pProj->mGame);
pProj->mProjFileLock.Lock(ProjPath);
pProj->mpGameInfo->LoadGameInfo(pProj->mGame);
pProj->mpAudioManager->LoadAssets();

View File

@ -6,7 +6,7 @@
#include "CResourceStore.h"
#include "Core/CAudioManager.h"
#include "Core/IProgressNotifier.h"
#include "Core/Resource/Script/CMasterTemplate.h"
#include "Core/Resource/Script/CGameTemplate.h"
#include <Common/CAssetID.h>
#include <Common/EGame.h>
#include <Common/FileUtil.h>
@ -45,8 +45,8 @@ class CGameProject
// Private Constructor
CGameProject()
: mProjectName("Unnamed Project")
, mGame(eUnknownGame)
, mRegion(eRegion_Unknown)
, mGame(EGame::Invalid)
, mRegion(ERegion::Unknown)
, mGameID("000000")
, mBuildVersion(0.f)
, mpResourceStore(nullptr)
@ -103,8 +103,8 @@ public:
inline TString GameID() const { return mGameID; }
inline float BuildVersion() const { return mBuildVersion; }
inline bool IsWiiBuild() const { return mBuildVersion >= 3.f; }
inline bool IsTrilogy() const { return mGame <= eCorruption && mBuildVersion >= 3.593f; }
inline bool IsWiiDeAsobu() const { return mGame <= eCorruption && mBuildVersion >= 3.570f && mBuildVersion < 3.593f; }
inline bool IsTrilogy() const { return mGame <= EGame::Corruption && mBuildVersion >= 3.593f; }
inline bool IsWiiDeAsobu() const { return mGame <= EGame::Corruption && mBuildVersion >= 3.570f && mBuildVersion < 3.593f; }
};
#endif // CGAMEPROJECT_H

View File

@ -29,15 +29,15 @@ bool CPackage::Save()
TString DefPath = DefinitionPath(false);
FileUtil::MakeDirectory(DefPath.GetFileDirectory());
CXMLWriter Writer(DefPath, "PackageDefinition", 0, mpProject ? mpProject->Game() : eUnknownGame);
CXMLWriter Writer(DefPath, "PackageDefinition", 0, mpProject ? mpProject->Game() : EGame::Invalid);
Serialize(Writer);
return Writer.Save();
}
void CPackage::Serialize(IArchive& rArc)
{
rArc << SERIAL("NeedsRecook", mNeedsRecook)
<< SERIAL_CONTAINER("NamedResources", mResources, "Resource");
rArc << SerialParameter("NeedsRecook", mNeedsRecook)
<< SerialParameter("NamedResources", mResources);
}
void CPackage::AddResource(const TString& rkName, const CAssetID& rkID, const CFourCC& rkType)
@ -82,7 +82,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
}
EGame Game = mpProject->Game();
u32 Alignment = (Game <= eCorruptionProto ? 0x20 : 0x40);
u32 Alignment = (Game <= EGame::CorruptionProto ? 0x20 : 0x40);
u32 AlignmentMinusOne = Alignment - 1;
u32 TocOffset = 0;
@ -92,7 +92,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
u32 ResDataSize = 0;
// Write MP1 pak header
if (Game <= eCorruptionProto)
if (Game <= EGame::CorruptionProto)
{
Pak.WriteLong(0x00030005); // Major/Minor Version
Pak.WriteLong(0); // Unknown
@ -188,7 +188,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
// Update table info
SResourceTableInfo& rTableInfo = ResourceTableData[ResIdx];
rTableInfo.pEntry = pEntry;
rTableInfo.Offset = (Game <= eEchoes ? AssetOffset : AssetOffset - ResDataOffset);
rTableInfo.Offset = (Game <= EGame::Echoes ? AssetOffset : AssetOffset - ResDataOffset);
// Load resource data
CFileInStream CookedAsset(pEntry->CookedAssetPath(), IOUtil::eBigEndian);
@ -201,12 +201,12 @@ void CPackage::Cook(IProgressNotifier *pProgress)
// Check if this asset should be compressed; there are a few resource types that are
// always compressed, and some types that are compressed if they're over a certain size
EResType Type = pEntry->ResourceType();
u32 CompressThreshold = (Game <= eCorruptionProto ? 0x400 : 0x80);
u32 CompressThreshold = (Game <= EGame::CorruptionProto ? 0x400 : 0x80);
bool ShouldAlwaysCompress = (Type == eTexture || Type == eModel || Type == eSkin ||
Type == eAnimSet || Type == eAnimation || Type == eFont);
if (Game >= eCorruption)
if (Game >= EGame::Corruption)
{
ShouldAlwaysCompress = ShouldAlwaysCompress ||
(Type == eCharacter || Type == eSourceAnimData || Type == eScan ||
@ -234,7 +234,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
std::vector<u8> CompressedData(ResourceData.size() * 2);
bool Success = false;
if (Game <= eEchoesDemo || Game == eReturns)
if (Game <= EGame::EchoesDemo || Game == EGame::DKCReturns)
Success = CompressionUtil::CompressZlib(ResourceData.data(), ResourceData.size(), CompressedData.data(), CompressedData.size(), CompressedSize);
else
Success = CompressionUtil::CompressLZOSegmented(ResourceData.data(), ResourceData.size(), CompressedData.data(), CompressedSize, false);
@ -242,7 +242,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
// Make sure that the compressed data is actually smaller, accounting for padding + uncompressed size value
if (Success)
{
u32 CompressionHeaderSize = (Game <= eCorruptionProto ? 4 : 0x10);
u32 CompressionHeaderSize = (Game <= EGame::CorruptionProto ? 4 : 0x10);
u32 PaddedUncompressedSize = (ResourceSize + AlignmentMinusOne) & ~AlignmentMinusOne;
u32 PaddedCompressedSize = (CompressedSize + CompressionHeaderSize + AlignmentMinusOne) & ~AlignmentMinusOne;
Success = (PaddedCompressedSize < PaddedUncompressedSize);
@ -252,7 +252,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
if (Success)
{
// Write MP1/2 compressed asset
if (Game <= eCorruptionProto)
if (Game <= EGame::CorruptionProto)
{
Pak.WriteLong(ResourceSize);
}
@ -292,7 +292,7 @@ void CPackage::Cook(IProgressNotifier *pProgress)
else
{
// Write table of contents for real
if (Game >= eCorruption)
if (Game >= EGame::Corruption)
{
Pak.Seek(TocOffset, SEEK_SET);
Pak.WriteLong(3); // Always 3 pak sections

View File

@ -17,7 +17,9 @@ struct SNamedResource
void Serialize(IArchive& rArc)
{
rArc << SERIAL_AUTO(Name) << SERIAL_AUTO(ID) << SERIAL_AUTO(Type);
rArc << SerialParameter("Name", Name)
<< SerialParameter("ID", ID)
<< SerialParameter("Type", Type);
}
};

View File

@ -127,9 +127,9 @@ void CResourceEntry::SerializeEntryInfo(IArchive& rArc, bool MetadataOnly)
{
CAssetID ID = mID;
rArc << SERIAL("AssetID", ID)
<< SERIAL("Type", mpTypeInfo)
<< SERIAL("Flags", mFlags);
rArc << SerialParameter("AssetID", ID)
<< SerialParameter("Type", mpTypeInfo)
<< SerialParameter("Flags", mFlags);
// Don't allow the file to override our asset ID if we already have a valid one.
if (rArc.IsReader() && !mID.IsValid())
@ -140,9 +140,9 @@ void CResourceEntry::SerializeEntryInfo(IArchive& rArc, bool MetadataOnly)
{
TString Dir = (mpDirectory ? mpDirectory->FullPath() : "");
rArc << SERIAL("Name", mName)
<< SERIAL("Directory", Dir)
<< SERIAL_ABSTRACT("Dependencies", mpDependencies, &gDependencyNodeFactory);
rArc << SerialParameter("Name", mName)
<< SerialParameter("Directory", Dir)
<< SerialParameter("Dependencies", mpDependencies);
if (rArc.IsReader())
{
@ -618,7 +618,7 @@ CGameProject* CResourceEntry::Project() const
EGame CResourceEntry::Game() const
{
return mpStore ? mpStore->Game() : eUnknownGame;
return mpStore ? mpStore->Game() : EGame::Invalid;
}
void CResourceEntry::SetFlag(EResEntryFlag Flag)

View File

@ -18,7 +18,7 @@ CResourceStore *gpEditorStore = nullptr;
// Constructor for editor store
CResourceStore::CResourceStore(const TString& rkDatabasePath)
: mpProj(nullptr)
, mGame(ePrime)
, mGame(EGame::Prime)
, mDatabaseCacheDirty(false)
{
mpDatabaseRoot = new CVirtualDirectory(this);
@ -29,7 +29,7 @@ CResourceStore::CResourceStore(const TString& rkDatabasePath)
// Main constructor for game projects and game exporter
CResourceStore::CResourceStore(CGameProject *pProject)
: mpProj(nullptr)
, mGame(eUnknownGame)
, mGame(EGame::Invalid)
, mpDatabaseRoot(nullptr)
, mDatabaseCacheDirty(false)
{
@ -62,17 +62,17 @@ void RecursiveGetListOfEmptyDirectories(CVirtualDirectory *pDir, TStringList& rO
bool CResourceStore::SerializeDatabaseCache(IArchive& rArc)
{
// Serialize resources
if (rArc.ParamBegin("Resources"))
if (rArc.ParamBegin("Resources", 0))
{
// Serialize resources
u32 ResourceCount = mResourceEntries.size();
rArc << SERIAL_AUTO(ResourceCount);
rArc << SerialParameter("ResourceCount", ResourceCount);
if (rArc.IsReader())
{
for (u32 ResIdx = 0; ResIdx < ResourceCount; ResIdx++)
{
if (rArc.ParamBegin("Resource"))
if (rArc.ParamBegin("Resource", 0))
{
CResourceEntry *pEntry = CResourceEntry::BuildFromArchive(this, rArc);
ASSERT( FindEntry(pEntry->ID()) == nullptr );
@ -85,7 +85,7 @@ bool CResourceStore::SerializeDatabaseCache(IArchive& rArc)
{
for (CResourceIterator It(this); It; ++It)
{
if (rArc.ParamBegin("Resource"))
if (rArc.ParamBegin("Resource", 0))
{
It->SerializeEntryInfo(rArc, false);
rArc.ParamEnd();
@ -101,7 +101,7 @@ bool CResourceStore::SerializeDatabaseCache(IArchive& rArc)
if (!rArc.IsReader())
RecursiveGetListOfEmptyDirectories(mpDatabaseRoot, EmptyDirectories);
rArc << SERIAL_CONTAINER_AUTO(EmptyDirectories, "Directory");
rArc << SerialParameter("EmptyDirectories", EmptyDirectories);
if (rArc.IsReader())
{
@ -218,7 +218,7 @@ void CResourceStore::CloseProject()
delete mpDatabaseRoot;
mpDatabaseRoot = nullptr;
mpProj = nullptr;
mGame = eUnknownGame;
mGame = EGame::Invalid;
}
CVirtualDirectory* CResourceStore::GetVirtualDirectory(const TString& rkPath, bool AllowCreate)
@ -622,5 +622,5 @@ bool CResourceStore::IsValidResourcePath(const TString& rkPath, const TString& r
TString CResourceStore::StaticDefaultResourceDirPath(EGame Game)
{
return (Game < eCorruptionProto ? "Uncategorized/" : "uncategorized/");
return (Game < EGame::CorruptionProto ? "Uncategorized/" : "uncategorized/");
}

View File

@ -3,7 +3,7 @@
// ************ CCharacterUsageMap ************
bool CCharacterUsageMap::IsCharacterUsed(const CAssetID& rkID, u32 CharacterIndex) const
{
if (mpStore->Game() >= eCorruptionProto) return true;
if (mpStore->Game() >= EGame::CorruptionProto) return true;
auto Find = mUsageMap.find(rkID);
if (Find == mUsageMap.end()) return false;
@ -214,7 +214,7 @@ void CPackageDependencyListBuilder::AddDependency(CResourceEntry *pCurEntry, con
// Is this entry valid?
bool IsValid = ResType != eMidi &&
(ResType != eAudioGroup || mGame >= eEchoesDemo) &&
(ResType != eAudioGroup || mGame >= EGame::EchoesDemo) &&
(ResType != eWorld || !pCurEntry) &&
(ResType != eArea || !pCurEntry || pCurEntry->ResourceType() == eWorld);
@ -232,7 +232,7 @@ void CPackageDependencyListBuilder::AddDependency(CResourceEntry *pCurEntry, con
// New area - toggle duplicates and find character usages
if (ResType == eArea)
{
if (mGame <= eEchoes)
if (mGame <= EGame::Echoes)
mCharacterUsageMap.FindUsagesForArea(mpWorld, pEntry);
mAreaUsedAssets.clear();
@ -417,7 +417,7 @@ void CAreaDependencyListBuilder::BuildDependencyList(std::list<CAssetID>& rAsset
CPropertyDependency *pDep = static_cast<CPropertyDependency*>(pInst->ChildByIndex(iDep));
// For MP3, exclude the CMDL/CSKR properties for the suit assets - only include default character assets
if (mGame == eCorruption && mIsPlayerActor)
if (mGame == EGame::Corruption && mIsPlayerActor)
{
TString PropID = pDep->PropertyID();
@ -467,7 +467,7 @@ void CAreaDependencyListBuilder::AddDependency(const CAssetID& rkID, std::list<C
EResType ResType = pEntry->ResourceType();
// If this is an audio group, for MP1, save it in the output set. For MP2, treat audio groups as a normal dependency.
if (mGame <= ePrime && ResType == eAudioGroup)
if (mGame <= EGame::Prime && ResType == eAudioGroup)
{
if (pAudioGroupsOut)
pAudioGroupsOut->insert(rkID);
@ -534,7 +534,7 @@ void CAreaDependencyListBuilder::EvaluateDependencyNode(CResourceEntry *pCurEntr
else if (Type == eDNT_SetCharacter)
{
// Note: For MP1/2 PlayerActor, always treat as if Empty Suit is the only used one
const u32 kEmptySuitIndex = (mGame >= eEchoesDemo ? 3 : 5);
const u32 kEmptySuitIndex = (mGame >= EGame::EchoesDemo ? 3 : 5);
CSetCharacterDependency *pChar = static_cast<CSetCharacterDependency*>(pNode);
u32 SetIndex = pChar->CharSetIndex();

View File

@ -30,7 +30,7 @@ public:
mTaskCount = Math::Max(mTaskCount, TaskIndex + 1);
}
void Report(int StepIndex, int StepCount, const TString& rkStepDesc)
void Report(int StepIndex, int StepCount, const TString& rkStepDesc = "")
{
ASSERT(mTaskCount >= 1);

View File

@ -6,6 +6,7 @@
class IUIRelay
{
public:
virtual void AsyncMessageBox(const TString& rkInfoBoxTitle, const TString& rkMessage) = 0;
virtual bool AskYesNoQuestion(const TString& rkInfoBoxTitle, const TString& rkQuestion) = 0;
};
extern IUIRelay *gpUIRelay;

View File

@ -481,7 +481,7 @@ bool CShaderGenerator::CreatePixelShader(const CMaterial& rkMat)
if (rkMat.Options() & CMaterial::ePunchthrough)
{
if (rkMat.Version() < eCorruptionProto)
if (rkMat.Version() < EGame::CorruptionProto)
{
ShaderCode << " if (Prev.a <= 0.25) discard;\n"
<< " else Prev.a = 1.0;\n\n";

View File

@ -141,7 +141,7 @@ public:
}
// Animation dependencies
if (Game() <= eEchoes)
if (Game() <= EGame::Echoes)
{
for (u32 iAnim = 0; iAnim < mAnimations.size(); iAnim++)
{
@ -151,7 +151,7 @@ public:
}
}
else if (Game() <= eCorruption)
else if (Game() <= EGame::Corruption)
{
const SSetCharacter& rkChar = mCharacters[0];
std::set<CAnimPrimitive> PrimitiveSet;
@ -228,7 +228,7 @@ public:
{
ASSERT(Index >= 0 && Index < NumAnimations());
if (Game() <= ePrime)
if (Game() <= EGame::Prime)
{
const CAnimPrimitive& rkPrim = mAnimPrimitives[Index];
return rkPrim.Animation() ? rkPrim.Animation()->EventData() : nullptr;

View File

@ -5,7 +5,7 @@
#include <iostream>
CAnimationParameters::CAnimationParameters()
: mGame(ePrime)
: mGame(EGame::Prime)
, mCharIndex(0)
, mAnimIndex(0)
, mUnknown2(0)
@ -15,6 +15,7 @@ CAnimationParameters::CAnimationParameters()
CAnimationParameters::CAnimationParameters(EGame Game)
: mGame(Game)
, mCharacterID( CAssetID::InvalidID(Game) )
, mCharIndex(0)
, mAnimIndex(0)
, mUnknown2(0)
@ -29,20 +30,20 @@ CAnimationParameters::CAnimationParameters(IInputStream& rSCLY, EGame Game)
, mUnknown2(0)
, mUnknown3(0)
{
if (Game <= eEchoes)
if (Game <= EGame::Echoes)
{
mCharacterID = CAssetID(rSCLY, Game);
mCharIndex = rSCLY.ReadLong();
mAnimIndex = rSCLY.ReadLong();
}
else if (Game <= eCorruption)
else if (Game <= EGame::Corruption)
{
mCharacterID = CAssetID(rSCLY, Game);
mAnimIndex = rSCLY.ReadLong();
}
else if (Game == eReturns)
else if (Game == EGame::DKCReturns)
{
u8 Flags = rSCLY.ReadByte();
@ -79,7 +80,7 @@ CAnimationParameters::CAnimationParameters(IInputStream& rSCLY, EGame Game)
void CAnimationParameters::Write(IOutputStream& rSCLY)
{
if (mGame <= eEchoes)
if (mGame <= EGame::Echoes)
{
if (mCharacterID.IsValid())
{
@ -95,7 +96,7 @@ void CAnimationParameters::Write(IOutputStream& rSCLY)
}
}
else if (mGame <= eCorruption)
else if (mGame <= EGame::Corruption)
{
if (mCharacterID.IsValid())
{
@ -136,6 +137,25 @@ void CAnimationParameters::Write(IOutputStream& rSCLY)
}
}
void CAnimationParameters::Serialize(IArchive& rArc)
{
if (rArc.IsReader())
mGame = rArc.Game();
rArc << SerialParameter("AnimationSetAsset", mCharacterID);
if (mGame <= EGame::Echoes)
rArc << SerialParameter("CharacterID", mCharIndex);
rArc << SerialParameter("AnimationID", mAnimIndex);
if (mGame >= EGame::DKCReturns)
{
rArc << SerialParameter("Unknown0", mUnknown2)
<< SerialParameter("Unknown1", mUnknown3);
}
}
const SSetCharacter* CAnimationParameters::GetCurrentSetCharacter(s32 NodeIndex /*= -1*/)
{
CAnimSet *pSet = AnimSet();

View File

@ -20,6 +20,7 @@ public:
CAnimationParameters(EGame Game);
CAnimationParameters(IInputStream& rSCLY, EGame Game);
void Write(IOutputStream& rSCLY);
void Serialize(IArchive& rArc);
const SSetCharacter* GetCurrentSetCharacter(s32 NodeIndex = -1);
CModel* GetCurrentModel(s32 NodeIndex = -1);
@ -34,11 +35,36 @@ public:
inline void SetCharIndex(u32 Index) { mCharIndex = Index; }
inline void SetAnimIndex(u32 Index) { mAnimIndex = Index; }
inline void SetGame(EGame Game)
{
mGame = Game;
if (!mCharacterID.IsValid())
{
mCharacterID = CAssetID::InvalidID(mGame);
}
else
{
ASSERT( mCharacterID.Length() == CAssetID::GameIDLength(mGame) );
}
}
u32 Unknown(u32 Index);
void SetResource(const CAssetID& rkID);
void SetUnknown(u32 Index, u32 Value);
// Operators
inline CAnimationParameters& operator=(const CAnimationParameters& rkOther)
{
mGame = rkOther.mGame;
mCharacterID = rkOther.mCharacterID;
mCharIndex = rkOther.mCharIndex;
mAnimIndex = rkOther.mAnimIndex;
mUnknown2 = rkOther.mUnknown2;
mUnknown3 = rkOther.mUnknown3;
return *this;
}
inline bool operator==(const CAnimationParameters& rkOther) const
{
return ( (mGame == rkOther.mGame) &&

View File

@ -56,7 +56,7 @@ CMetaTransTrans::CMetaTransTrans(EMetaTransitionType Type, IInputStream& rInput,
ASSERT(Type == eMTT_Trans || Type == eMTT_PhaseTrans);
mType = Type;
if (Game <= eEchoes)
if (Game <= EGame::Echoes)
{
mUnknownA = rInput.ReadFloat();
mUnknownB = rInput.ReadLong();

View File

@ -42,7 +42,7 @@ CDependencyTree* CGameArea::BuildDependencyTree() const
pTree->AddDependency(mPathID);
if (Game() >= eEchoesDemo)
if (Game() >= EGame::EchoesDemo)
{
pTree->AddDependency(mPortalAreaID);
pTree->AddDependency(mpPoiToWorldMap);
@ -224,7 +224,7 @@ CScriptObject* CGameArea::SpawnInstance(CScriptTemplate *pTemplate,
pInstance->SetRotation(rkRotation.ToEuler());
pInstance->SetScale(rkScale);
pInstance->SetName(pTemplate->Name());
if (pTemplate->Game() < eEchoesDemo) pInstance->SetActive(true);
if (pTemplate->Game() < EGame::EchoesDemo) pInstance->SetActive(true);
pLayer->AddInstance(pInstance, SuggestedLayerIndex);
mObjectMap[InstanceID] = pInstance;
return pInstance;

View File

@ -21,7 +21,7 @@ ECollisionFlag CCollisionMaterial::SurfaceType(EGame Game) const
const ECollisionFlag* pkFlagArray;
u32 Num;
if (Game <= ePrime)
if (Game <= EGame::Prime)
{
pkFlagArray = skPrimeTypeHierarchy;
Num = sizeof(skPrimeTypeHierarchy) / sizeof(ECollisionFlag);
@ -79,5 +79,5 @@ bool CCollisionMaterial::IsFloor() const
bool CCollisionMaterial::IsUnstandable(EGame Game) const
{
return HasFlag(eCF_JumpNotAllowed) || (Game >= eCorruptionProto && !HasFlag(eCF_Floor) && HasAnyFlags(eCF_Wall | eCF_Ceiling));
return HasFlag(eCF_JumpNotAllowed) || (Game >= EGame::CorruptionProto && !HasFlag(eCF_Floor) && HasAnyFlags(eCF_Wall | eCF_Ceiling));
}

View File

@ -1,5 +1,6 @@
#include "CLight.h"
#include "Core/Render/CGraphics.h"
#include <Common/Common.h>
#include <cmath>
#include <float.h>
@ -127,6 +128,52 @@ void CLight::SetAngleAtten(float AngleCoefA, float AngleCoefB, float AngleCoefC)
mAngleAttenCoefficients.Z = AngleCoefC;
}
CStructProperty* CLight::GetProperties() const
{
//@todo MP1 properties only
//@todo we cannot display full properties because a lot of them are discarded on load
static CStructProperty* pProperties = nullptr;
if (!pProperties)
{
pProperties = (CStructProperty*) IProperty::CreateIntrinsic(EPropertyType::Struct,
EGame::Prime,
0,
"Light");
CChoiceProperty* pLightType = (CChoiceProperty*) IProperty::CreateIntrinsic(EPropertyType::Choice,
pProperties,
MEMBER_OFFSET(CLight, mType),
"LightType");
pLightType->AddValue("LocalAmbient", eLocalAmbient);
pLightType->AddValue("Directional", eDirectional);
pLightType->AddValue("Spot", eSpot);
pLightType->AddValue("Custom", eCustom);
IProperty::CreateIntrinsic(EPropertyType::Color,
pProperties,
MEMBER_OFFSET(CLight, mColor),
"Color");
IProperty::CreateIntrinsic(EPropertyType::Vector,
pProperties,
MEMBER_OFFSET(CLight, mPosition),
"Position");
IProperty::CreateIntrinsic(EPropertyType::Vector,
pProperties,
MEMBER_OFFSET(CLight, mDirection),
"Direction");
IProperty::CreateIntrinsic(EPropertyType::Float,
pProperties,
MEMBER_OFFSET(CLight, mSpotCutoff),
"SpotCutoff");
}
return pProperties;
}
// ************ OTHER ************
void CLight::Load() const
{

View File

@ -1,6 +1,7 @@
#ifndef CLIGHT_H
#define CLIGHT_H
#include "Core/Resource/Script/Property/Properties.h"
#include <Common/CColor.h>
#include <Common/FileIO/IInputStream.h>
#include <Math/CVector3f.h>
@ -62,6 +63,8 @@ public:
void SetDistAtten(float DistCoefA, float DistCoefB, float DistCoefC);
void SetAngleAtten(float AngleCoefA, float AngleCoefB, float AngleCoefC);
CStructProperty* GetProperties() const;
// Other
void Load() const;

View File

@ -4,7 +4,7 @@
#include "Core/Render/CRenderer.h"
#include "Core/OpenGL/GLCommon.h"
#include "Core/OpenGL/CShaderGenerator.h"
#include <Common/CHashFNV1A.h>
#include <Common/Hash/CFNV1A.h>
#include <iostream>
#include <GL/glew.h>
@ -18,7 +18,7 @@ CMaterial::CMaterial()
, mShaderStatus(eNoShader)
, mRecalcHash(true)
, mEnableBloom(false)
, mVersion(eUnknownGame)
, mVersion(EGame::Invalid)
, mOptions(eNoSettings)
, mVtxDesc(eNoAttributes)
, mBlendSrcFac(GL_ONE)
@ -34,7 +34,7 @@ CMaterial::CMaterial(EGame Version, FVertexDescription VtxDesc)
: mpShader(nullptr)
, mShaderStatus(eNoShader)
, mRecalcHash(true)
, mEnableBloom(Version == eCorruption)
, mEnableBloom(Version == EGame::Corruption)
, mVersion(Version)
, mOptions(eDepthWrite)
, mVtxDesc(VtxDesc)
@ -48,7 +48,7 @@ CMaterial::CMaterial(EGame Version, FVertexDescription VtxDesc)
mpShader = nullptr;
mShaderStatus = eNoShader;
mRecalcHash = true;
mEnableBloom = (Version == eCorruption);
mEnableBloom = (Version == EGame::Corruption);
mVersion = Version;
mOptions = eDepthWrite;
mVtxDesc = VtxDesc;
@ -243,9 +243,9 @@ u64 CMaterial::HashParameters()
{
if (mRecalcHash)
{
CHashFNV1A Hash(CHashFNV1A::e64Bit);
CFNV1A Hash(CFNV1A::e64Bit);
Hash.HashLong(mVersion);
Hash.HashLong((int) mVersion);
Hash.HashLong(mOptions);
Hash.HashLong(mVtxDesc);
Hash.HashData(mKonstColors, sizeof(CColor) * 4);

View File

@ -112,7 +112,7 @@ public:
inline void SetOptions(FMaterialOptions Options) { mOptions = Options; Update(); }
inline void SetVertexDescription(FVertexDescription Desc) { mVtxDesc = Desc; Update(); }
inline void SetBlendMode(GLenum SrcFac, GLenum DstFac) { mBlendSrcFac = SrcFac; mBlendDstFac = DstFac; mRecalcHash = true; }
inline void SetKonst(CColor& Konst, u32 KIndex) { mKonstColors[KIndex] = Konst; Update(); }
inline void SetKonst(const CColor& Konst, u32 KIndex) { mKonstColors[KIndex] = Konst; Update(); }
inline void SetIndTexture(CTexture *pTex) { mpIndirectTexture = pTex; }
inline void SetLightingEnabled(bool Enabled) { mLightingEnabled = Enabled; Update(); }

View File

@ -58,7 +58,7 @@ CMaterialPass* CMaterialPass::Clone(CMaterial *pParent)
return pOut;
}
void CMaterialPass::HashParameters(CHashFNV1A& rHash)
void CMaterialPass::HashParameters(CFNV1A& rHash)
{
if (mEnabled)
{

View File

@ -6,7 +6,7 @@
#include "ETevEnums.h"
#include "Core/Render/FRenderOptions.h"
#include <Common/CFourCC.h>
#include <Common/CHashFNV1A.h>
#include <Common/Hash/CFNV1A.h>
class CMaterial;
@ -45,7 +45,7 @@ public:
CMaterialPass(CMaterial *pParent);
~CMaterialPass();
CMaterialPass* Clone(CMaterial *pParent);
void HashParameters(CHashFNV1A& rHash);
void HashParameters(CFNV1A& rHash);
void LoadTexture(u32 PassIndex);
void SetAnimCurrent(FRenderOptions Options, u32 PassIndex);

View File

@ -11,7 +11,7 @@ class CResTypeFilter
std::set<EResType> mAcceptedTypes;
public:
CResTypeFilter() { }
CResTypeFilter() : mGame(EGame::Invalid) { }
CResTypeFilter(EGame Game, const TString& rkTypeList) { FromString(Game, rkTypeList); }
void SetAcceptedTypes(EGame Game, const TStringList& rkTypes)
@ -47,6 +47,12 @@ public:
SetAcceptedTypes(Game, rkString.Split(","));
}
void Serialize(IArchive& rArc)
{
if (rArc.IsReader()) mGame = rArc.Game();
rArc << SerialParameter("AcceptedTypes", mAcceptedTypes, SH_Proxy);
}
inline bool Accepts(EResType Type) const
{
return mAcceptedTypes.find(Type) != mAcceptedTypes.end();

View File

@ -4,9 +4,10 @@
std::unordered_map<EResType, CResTypeInfo*> CResTypeInfo::smTypeMap;
CResTypeInfo::CResTypeInfo(EResType Type, const TString& rkTypeName)
CResTypeInfo::CResTypeInfo(EResType Type, const TString& rkTypeName, const TString& rkRetroExtension)
: mType(Type)
, mTypeName(rkTypeName)
, mRetroExtension(rkRetroExtension)
, mCanBeSerialized(false)
, mCanHaveDependencies(true)
{
@ -16,12 +17,6 @@ CResTypeInfo::CResTypeInfo(EResType Type, const TString& rkTypeName)
smTypeMap[Type] = this;
}
CResTypeInfo::~CResTypeInfo()
{
// shouldn't happen - we want to just create these at launch and keep them around forever
ASSERT(false);
}
bool CResTypeInfo::IsInGame(EGame Game) const
{
for (u32 iGame = 0; iGame < mCookedExtensions.size(); iGame++)
@ -35,8 +30,8 @@ bool CResTypeInfo::IsInGame(EGame Game) const
CFourCC CResTypeInfo::CookedExtension(EGame Game) const
{
// Default to MP1
if (Game == eUnknownGame)
Game = ePrime;
if (Game == EGame::Invalid)
Game = EGame::Prime;
for (u32 iGame = 0; iGame < mCookedExtensions.size(); iGame++)
{
@ -63,7 +58,7 @@ CResTypeInfo* CResTypeInfo::TypeForCookedExtension(EGame Game, CFourCC Ext)
{
// Extensions can vary between games, but we're not likely to be calling this function for different games very often.
// So, to speed things up a little, cache the lookup results in a map.
static EGame sCachedGame = eUnknownGame;
static EGame sCachedGame = EGame::Invalid;
static std::map<CFourCC, CResTypeInfo*> sCachedTypeMap;
Ext = Ext.ToUpper();
@ -113,7 +108,7 @@ void Serialize(IArchive& rArc, CResTypeInfo*& rpType)
Ext = rpType->CookedExtension(rArc.Game());
}
rArc.SerializePrimitive(Ext);
rArc.SerializePrimitive(Ext, 0);
if (rArc.IsReader())
{
@ -122,6 +117,27 @@ void Serialize(IArchive& rArc, CResTypeInfo*& rpType)
}
}
void Serialize(IArchive& rArc, EResType& rType)
{
CFourCC Extension;
if (rArc.IsWriter())
{
CResTypeInfo* pTypeInfo = CResTypeInfo::FindTypeInfo(rType);
ASSERT(pTypeInfo != nullptr);
Extension = pTypeInfo->CookedExtension(rArc.Game());
}
rArc.SerializePrimitive(Extension, 0);
if (rArc.IsReader())
{
CResTypeInfo* pTypeInfo = CResTypeInfo::TypeForCookedExtension(rArc.Game(), Extension);
ASSERT(pTypeInfo != nullptr);
rType = pTypeInfo->Type();
}
}
// ************ CREATION ************
CResTypeInfo::CResTypeInfoFactory CResTypeInfo::smTypeInfoFactory;
@ -132,16 +148,16 @@ CResTypeInfo::CResTypeInfoFactory::CResTypeInfoFactory()
void CResTypeInfo::CResTypeInfoFactory::AddExtension(CResTypeInfo *pType, CFourCC Ext, EGame FirstGame, EGame LastGame)
{
ASSERT(FirstGame >= ePrimeDemo && LastGame <= eReturns && FirstGame <= LastGame);
ASSERT(FirstGame != eUnknownGame && LastGame != eUnknownGame);
ASSERT(FirstGame >= EGame::PrimeDemo && LastGame <= EGame::DKCReturns && FirstGame <= LastGame);
ASSERT(FirstGame != EGame::Invalid && LastGame != EGame::Invalid);
for (int iGame = FirstGame; iGame <= LastGame; iGame++)
for (int GameIdx = (int) FirstGame; GameIdx <= (int) LastGame; GameIdx++)
{
#if !PUBLIC_RELEASE
ASSERT(!pType->IsInGame((EGame) iGame));
ASSERT(!pType->IsInGame((EGame) GameIdx));
#endif
CResTypeInfo::SGameExtension Info { (EGame) iGame, Ext };
CResTypeInfo::SGameExtension Info { (EGame) GameIdx, Ext };
pType->mCookedExtensions.push_back(Info);
}
@ -153,236 +169,236 @@ void CResTypeInfo::CResTypeInfoFactory::AddExtension(CResTypeInfo *pType, CFourC
void CResTypeInfo::CResTypeInfoFactory::InitTypes()
{
{
CResTypeInfo *pType = new CResTypeInfo(eAnimation, "Animation");
AddExtension(pType, "ANIM", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eAnimation, "Animation", "ani");
AddExtension(pType, "ANIM", EGame::PrimeDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eAnimCollisionPrimData, "Animation Collision Primitive Data");
AddExtension(pType, "CPRM", eReturns, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eAnimCollisionPrimData, "Animation Collision Primitive Data", "?");
AddExtension(pType, "CPRM", EGame::DKCReturns, EGame::DKCReturns);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eAnimEventData, "Animation Event Data");
AddExtension(pType, "EVNT", ePrimeDemo, ePrime);
CResTypeInfo *pType = new CResTypeInfo(eAnimEventData, "Animation Event Data", "evnt");
AddExtension(pType, "EVNT", EGame::PrimeDemo, EGame::Prime);
}
{
CResTypeInfo *pType = new CResTypeInfo(eAnimSet, "Animation Character Set");
AddExtension(pType, "ANCS", ePrimeDemo, eEchoes);
CResTypeInfo *pType = new CResTypeInfo(eAnimSet, "Animation Character Set", "acs");
AddExtension(pType, "ANCS", EGame::PrimeDemo, EGame::Echoes);
}
{
CResTypeInfo *pType = new CResTypeInfo(eArea, "Area");
AddExtension(pType, "MREA", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eArea, "Area", "mrea");
AddExtension(pType, "MREA", EGame::PrimeDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eAudioAmplitudeData, "Audio Amplitude Data");
AddExtension(pType, "CAAD", eCorruption, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eAudioAmplitudeData, "Audio Amplitude Data", "?");
AddExtension(pType, "CAAD", EGame::Corruption, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eAudioGroup, "Audio Group");
AddExtension(pType, "AGSC", ePrimeDemo, eEchoes);
CResTypeInfo *pType = new CResTypeInfo(eAudioGroup, "Audio Group", "agsc");
AddExtension(pType, "AGSC", EGame::PrimeDemo, EGame::Echoes);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eAudioMacro, "Audio Macro");
AddExtension(pType, "CAUD", eCorruptionProto, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eAudioMacro, "Audio Macro", "caud");
AddExtension(pType, "CAUD", EGame::CorruptionProto, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eAudioSample, "Audio Sample");
AddExtension(pType, "CSMP", eCorruptionProto, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eAudioSample, "Audio Sample", "csmp");
AddExtension(pType, "CSMP", EGame::CorruptionProto, EGame::DKCReturns);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eAudioLookupTable, "Audio Lookup Table");
AddExtension(pType, "ATBL", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eAudioLookupTable, "Audio Lookup Table", "atbl");
AddExtension(pType, "ATBL", EGame::PrimeDemo, EGame::Corruption);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eBinaryData, "Generic Data");
AddExtension(pType, "DUMB", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eBinaryData, "Generic Data", "dat");
AddExtension(pType, "DUMB", EGame::PrimeDemo, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eBurstFireData, "Burst Fire Data");
AddExtension(pType, "BFRC", eCorruptionProto, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eBurstFireData, "Burst Fire Data", "bfre.bfrc");
AddExtension(pType, "BFRC", EGame::CorruptionProto, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eCharacter, "Character");
AddExtension(pType, "CHAR", eCorruptionProto, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eCharacter, "Character", "char");
AddExtension(pType, "CHAR", EGame::CorruptionProto, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eDependencyGroup, "Dependency Group");
AddExtension(pType, "DGRP", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eDependencyGroup, "Dependency Group", "?");
AddExtension(pType, "DGRP", EGame::PrimeDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eDynamicCollision, "Dynamic Collision");
AddExtension(pType, "DCLN", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eDynamicCollision, "Dynamic Collision", "dcln");
AddExtension(pType, "DCLN", EGame::PrimeDemo, EGame::DKCReturns);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eFont, "Font");
AddExtension(pType, "FONT", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eFont, "Font", "rpff");
AddExtension(pType, "FONT", EGame::PrimeDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eGuiFrame, "Gui Frame");
AddExtension(pType, "FRME", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eGuiFrame, "Gui Frame", "frme");
AddExtension(pType, "FRME", EGame::PrimeDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eGuiKeyFrame, "Gui Keyframe");
AddExtension(pType, "KFAM", ePrimeDemo, ePrimeDemo);
CResTypeInfo *pType = new CResTypeInfo(eGuiKeyFrame, "Gui Keyframe", "?");
AddExtension(pType, "KFAM", EGame::PrimeDemo, EGame::PrimeDemo);
}
{
CResTypeInfo *pType = new CResTypeInfo(eHintSystem, "Hint System Data");
AddExtension(pType, "HINT", ePrime, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eHintSystem, "Hint System Data", "hint");
AddExtension(pType, "HINT", EGame::Prime, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eMapArea, "Area Map");
AddExtension(pType, "MAPA", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eMapArea, "Area Map", "mapa");
AddExtension(pType, "MAPA", EGame::PrimeDemo, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eMapWorld, "World Map");
AddExtension(pType, "MAPW", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eMapWorld, "World Map", "mapw");
AddExtension(pType, "MAPW", EGame::PrimeDemo, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eMapUniverse, "Universe Map");
AddExtension(pType, "MAPU", ePrimeDemo, eEchoes);
CResTypeInfo *pType = new CResTypeInfo(eMapUniverse, "Universe Map", "mapu");
AddExtension(pType, "MAPU", EGame::PrimeDemo, EGame::Echoes);
}
{
CResTypeInfo *pType = new CResTypeInfo(eMidi, "MIDI");
AddExtension(pType, "CSNG", ePrimeDemo, eEchoes);
CResTypeInfo *pType = new CResTypeInfo(eMidi, "MIDI", "?");
AddExtension(pType, "CSNG", EGame::PrimeDemo, EGame::Echoes);
}
{
CResTypeInfo *pType = new CResTypeInfo(eModel, "Model");
AddExtension(pType, "CMDL", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eModel, "Model", "cmdl");
AddExtension(pType, "CMDL", EGame::PrimeDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eParticle, "Particle System");
AddExtension(pType, "PART", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eParticle, "Particle System", "gpsm.part");
AddExtension(pType, "PART", EGame::PrimeDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eParticleCollisionResponse, "Collision Response Particle System");
AddExtension(pType, "CRSC", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eParticleCollisionResponse, "Collision Response Particle System", "crsm.crsc");
AddExtension(pType, "CRSC", EGame::PrimeDemo, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eParticleDecal, "Decal Particle System");
AddExtension(pType, "DPSC", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eParticleDecal, "Decal Particle System", "dpsm.dpsc");
AddExtension(pType, "DPSC", EGame::PrimeDemo, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eParticleElectric, "Electric Particle System");
AddExtension(pType, "ELSC", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eParticleElectric, "Electric Particle System", "elsm.elsc");
AddExtension(pType, "ELSC", EGame::PrimeDemo, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eParticleSorted, "Sorted Particle System");
AddExtension(pType, "SRSC", eEchoesDemo, eEchoes);
CResTypeInfo *pType = new CResTypeInfo(eParticleSorted, "Sorted Particle System", "srsm.srsc");
AddExtension(pType, "SRSC", EGame::EchoesDemo, EGame::Echoes);
}
{
CResTypeInfo *pType = new CResTypeInfo(eParticleSpawn, "Spawn Particle System");
AddExtension(pType, "SPSC", eEchoesDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eParticleSpawn, "Spawn Particle System", "spsm.spsc");
AddExtension(pType, "SPSC", EGame::EchoesDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eParticleSwoosh, "Swoosh Particle System");
AddExtension(pType, "SWHC", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eParticleSwoosh, "Swoosh Particle System", "swsh.swhc");
AddExtension(pType, "SWHC", EGame::PrimeDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eParticleTransform, "Transform Particle System");
AddExtension(pType, "XFSC", eReturns, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eParticleTransform, "Transform Particle System", "xfsm.xfsc");
AddExtension(pType, "XFSC", EGame::DKCReturns, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eParticleWeapon, "Weapon Particle System");
AddExtension(pType, "WPSC", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eParticleWeapon, "Weapon Particle System", "wpsm.wpsc");
AddExtension(pType, "WPSC", EGame::PrimeDemo, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(ePathfinding, "Pathfinding Mesh");
AddExtension(pType, "PATH", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(ePathfinding, "Pathfinding Mesh", "path");
AddExtension(pType, "PATH", EGame::PrimeDemo, EGame::Corruption);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(ePortalArea, "Portal Area");
AddExtension(pType, "PTLA", eEchoesDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(ePortalArea, "Portal Area", "?");
AddExtension(pType, "PTLA", EGame::EchoesDemo, EGame::Corruption);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eRuleSet, "Rule Set");
AddExtension(pType, "RULE", eEchoesDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eRuleSet, "Rule Set", "rule");
AddExtension(pType, "RULE", EGame::EchoesDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eSaveArea, "Area Save Info");
AddExtension(pType, "SAVA", eCorruptionProto, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eSaveArea, "Area Save Info", "sava");
AddExtension(pType, "SAVA", EGame::CorruptionProto, EGame::Corruption);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eSaveWorld, "World Save Info");
AddExtension(pType, "SAVW", ePrime, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eSaveWorld, "World Save Info", "savw");
AddExtension(pType, "SAVW", EGame::Prime, EGame::DKCReturns);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eScan, "Scan");
AddExtension(pType, "SCAN", ePrimeDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eScan, "Scan", "scan");
AddExtension(pType, "SCAN", EGame::PrimeDemo, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eSkeleton, "Skeleton");
AddExtension(pType, "CINF", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eSkeleton, "Skeleton", "cin");
AddExtension(pType, "CINF", EGame::PrimeDemo, EGame::DKCReturns);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eSkin, "Skin");
AddExtension(pType, "CSKR", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eSkin, "Skin", "cskr");
AddExtension(pType, "CSKR", EGame::PrimeDemo, EGame::DKCReturns);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eSourceAnimData, "Source Animation Data");
AddExtension(pType, "SAND", eCorruptionProto, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eSourceAnimData, "Source Animation Data", "sand");
AddExtension(pType, "SAND", EGame::CorruptionProto, EGame::Corruption);
pType->mCanHaveDependencies = false; // all dependencies are added to the CHAR dependency tree
}
{
CResTypeInfo *pType = new CResTypeInfo(eSpatialPrimitive, "Spatial Primitive");
AddExtension(pType, "CSPP", eEchoesDemo, eEchoes);
CResTypeInfo *pType = new CResTypeInfo(eSpatialPrimitive, "Spatial Primitive", "?");
AddExtension(pType, "CSPP", EGame::EchoesDemo, EGame::Echoes);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eStateMachine, "State Machine");
AddExtension(pType, "AFSM", ePrimeDemo, eEchoes);
AddExtension(pType, "FSM2", eCorruptionProto, eCorruption);
AddExtension(pType, "FSMC", eReturns, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eStateMachine, "State Machine", "afsm");
AddExtension(pType, "AFSM", EGame::PrimeDemo, EGame::Echoes);
AddExtension(pType, "FSM2", EGame::CorruptionProto, EGame::Corruption);
AddExtension(pType, "FSMC", EGame::DKCReturns, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eStateMachine2, "State Machine 2");
AddExtension(pType, "FSM2", eEchoesDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eStateMachine2, "State Machine 2", "fsm2");
AddExtension(pType, "FSM2", EGame::EchoesDemo, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eStaticGeometryMap, "Static Scan Map");
AddExtension(pType, "EGMC", eEchoesDemo, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eStaticGeometryMap, "Static Scan Map", "egmc");
AddExtension(pType, "EGMC", EGame::EchoesDemo, EGame::Corruption);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eStreamedAudio, "Streamed Audio");
AddExtension(pType, "STRM", eCorruptionProto, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eStreamedAudio, "Streamed Audio", "?");
AddExtension(pType, "STRM", EGame::CorruptionProto, EGame::DKCReturns);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eStringList, "String List");
AddExtension(pType, "STLC", eEchoesDemo, eCorruptionProto);
CResTypeInfo *pType = new CResTypeInfo(eStringList, "String List", "stlc");
AddExtension(pType, "STLC", EGame::EchoesDemo, EGame::CorruptionProto);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eStringTable, "String Table");
AddExtension(pType, "STRG", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eStringTable, "String Table", "strg");
AddExtension(pType, "STRG", EGame::PrimeDemo, EGame::DKCReturns);
}
{
CResTypeInfo *pType = new CResTypeInfo(eTexture, "Texture");
AddExtension(pType, "TXTR", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eTexture, "Texture", "txtr");
AddExtension(pType, "TXTR", EGame::PrimeDemo, EGame::DKCReturns);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eTweak, "Tweak Data");
AddExtension(pType, "CTWK", ePrimeDemo, ePrime);
CResTypeInfo *pType = new CResTypeInfo(eTweak, "Tweak Data", "ctwk");
AddExtension(pType, "CTWK", EGame::PrimeDemo, EGame::Prime);
pType->mCanHaveDependencies = false;
}
{
CResTypeInfo *pType = new CResTypeInfo(eUserEvaluatorData, "User Evaluator Data");
AddExtension(pType, "USRC", eCorruptionProto, eCorruption);
CResTypeInfo *pType = new CResTypeInfo(eUserEvaluatorData, "User Evaluator Data", "user.usrc");
AddExtension(pType, "USRC", EGame::CorruptionProto, EGame::Corruption);
}
{
CResTypeInfo *pType = new CResTypeInfo(eWorld, "World");
AddExtension(pType, "MLVL", ePrimeDemo, eReturns);
CResTypeInfo *pType = new CResTypeInfo(eWorld, "World", "mwld");
AddExtension(pType, "MLVL", EGame::PrimeDemo, EGame::DKCReturns);
pType->mCanBeSerialized = true;
}
}

View File

@ -20,14 +20,15 @@ class CResTypeInfo
EResType mType;
TString mTypeName;
std::vector<SGameExtension> mCookedExtensions;
TString mRetroExtension; // File extension in Retro's directory tree. We don't use it directly but it is needed for generating asset ID hashes
bool mCanBeSerialized;
bool mCanHaveDependencies;
static std::unordered_map<EResType, CResTypeInfo*> smTypeMap;
// Private Methods
CResTypeInfo(EResType Type, const TString& rkTypeName);
~CResTypeInfo();
CResTypeInfo(EResType Type, const TString& rkTypeName, const TString& rkRetroExtension);
~CResTypeInfo() {}
// Public Methods
public:

View File

@ -51,7 +51,7 @@ public:
inline TString Source() const { return mpEntry ? mpEntry->CookedAssetPath(true).GetFileName() : ""; }
inline TString FullSource() const { return mpEntry ? mpEntry->CookedAssetPath(true) : ""; }
inline CAssetID ID() const { return mpEntry ? mpEntry->ID() : CAssetID::skInvalidID64; }
inline EGame Game() const { return mpEntry ? mpEntry->Game() : eUnknownGame; }
inline EGame Game() const { return mpEntry ? mpEntry->Game() : EGame::Invalid; }
inline bool IsReferenced() const { return mRefCount > 0; }
inline void Lock() { mRefCount++; }
inline void Release() { mRefCount--; }

View File

@ -46,10 +46,18 @@ public:
void Serialize(IArchive& rArc)
{
TString Str;
if (rArc.IsWriter()) Str = ToString();
rArc.SerializePrimitive(Str);
if (rArc.IsReader()) *this = FromString(Str);
if (rArc.IsBinaryFormat())
{
rArc.SerializePrimitive(m[0], 0);
rArc.SerializePrimitive(m[1], 0);
}
else
{
TString Str;
if (rArc.IsWriter()) Str = ToString();
rArc.SerializePrimitive(Str, 0);
if (rArc.IsReader()) *this = FromString(Str);
}
}
// Operators

View File

@ -69,7 +69,7 @@ public:
CDependencyTree *pTree = new CDependencyTree();
// Corruption's SCAN has a list of all assets - just grab that
if (Game() >= eCorruptionProto)
if (Game() >= EGame::CorruptionProto)
{
for (u32 iDep = 0; iDep < mDependencyList.size(); iDep++)
{
@ -80,18 +80,18 @@ public:
}
// Otherwise add all the dependencies we need from the properties
if (Game() <= ePrime)
if (Game() <= EGame::Prime)
pTree->AddDependency(mFrameID);
pTree->AddDependency(mpStringTable);
if (Game() <= ePrime)
if (Game() <= EGame::Prime)
{
for (u32 iImg = 0; iImg < 4; iImg++)
pTree->AddDependency(mScanImageTextures[iImg]);
}
else if (Game() <= eEchoes)
else if (Game() <= EGame::Echoes)
{
pTree->AddDependency(mPostOverrideTexture);
pTree->AddDependency(mLogbookModel);

View File

@ -46,7 +46,7 @@ public:
{
// STRGs can reference FONTs with the &font=; formatting tag and TXTRs with the &image=; tag
CDependencyTree *pTree = new CDependencyTree();
EIDLength IDLength = (Game() <= eEchoes ? e32Bit : e64Bit);
EIDLength IDLength = (Game() <= EGame::Echoes ? e32Bit : e64Bit);
for (u32 iLang = 0; iLang < mLangTables.size(); iLang++)
{
@ -77,7 +77,7 @@ public:
// Font
if (TagName == "font")
{
if (Game() >= eCorruptionProto)
if (Game() >= EGame::CorruptionProto)
{
ASSERT(ParamString.StartsWith("0x"));
ParamString = ParamString.ChopFront(2);
@ -126,7 +126,7 @@ public:
{
TString Param = *Iter;
if (Game() >= eCorruptionProto)
if (Game() >= EGame::CorruptionProto)
{
ASSERT(Param.StartsWith("0x"));
Param = Param.ChopFront(2);

View File

@ -92,87 +92,87 @@ u32 CWorld::AreaIndex(CAssetID AreaID) const
// ************ SERIALIZATION ************
void CWorld::Serialize(IArchive& rArc)
{
rArc << SERIAL("Name", mName)
<< SERIAL("NameString", mpWorldName);
rArc << SerialParameter("Name", mName)
<< SerialParameter("NameString", mpWorldName);
if (rArc.Game() == eEchoesDemo || rArc.Game() == eEchoes)
rArc << SERIAL("DarkNameString", mpDarkWorldName);
if (rArc.Game() == EGame::EchoesDemo || rArc.Game() == EGame::Echoes)
rArc << SerialParameter("DarkNameString", mpDarkWorldName);
rArc << SERIAL("WorldSaveInfo", mpSaveWorld)
<< SERIAL("WorldMap", mpMapWorld)
<< SERIAL("DefaultSkyModel", mpDefaultSkybox);
rArc << SerialParameter("WorldSaveInfo", mpSaveWorld)
<< SerialParameter("WorldMap", mpMapWorld)
<< SerialParameter("DefaultSkyModel", mpDefaultSkybox);
if (rArc.Game() >= eEchoesDemo && rArc.Game() <= eCorruption)
rArc << SERIAL("TempleKeyWorldIndex", mTempleKeyWorldIndex);
if (rArc.Game() >= EGame::EchoesDemo && rArc.Game() <= EGame::Corruption)
rArc << SerialParameter("TempleKeyWorldIndex", mTempleKeyWorldIndex);
if (rArc.Game() == eReturns)
rArc << SERIAL("TimeAttackData", mTimeAttackData);
if (rArc.Game() == EGame::DKCReturns)
rArc << SerialParameter("TimeAttackData", mTimeAttackData);
if (rArc.Game() == ePrime)
rArc << SERIAL_CONTAINER("MemoryRelays", mMemoryRelays, "MemoryRelay");
if (rArc.Game() == EGame::Prime)
rArc << SerialParameter("MemoryRelays", mMemoryRelays);
rArc << SERIAL_CONTAINER("Areas", mAreas, "Area");
rArc << SerialParameter("Areas", mAreas);
}
void Serialize(IArchive& rArc, CWorld::STimeAttackData& rData)
{
rArc << SERIAL("HasTimeAttack", rData.HasTimeAttack)
<< SERIAL("ActNumber", rData.ActNumber)
<< SERIAL("BronzeTime", rData.BronzeTime)
<< SERIAL("SilverTime", rData.SilverTime)
<< SERIAL("GoldTime", rData.GoldTime)
<< SERIAL("ShinyGoldTime", rData.ShinyGoldTime);
rArc << SerialParameter("HasTimeAttack", rData.HasTimeAttack)
<< SerialParameter("ActNumber", rData.ActNumber)
<< SerialParameter("BronzeTime", rData.BronzeTime)
<< SerialParameter("SilverTime", rData.SilverTime)
<< SerialParameter("GoldTime", rData.GoldTime)
<< SerialParameter("ShinyGoldTime", rData.ShinyGoldTime);
}
void Serialize(IArchive& rArc, CWorld::SMemoryRelay& rMemRelay)
{
rArc << SERIAL_HEX("MemoryRelayID", rMemRelay.InstanceID)
<< SERIAL_HEX("TargetID", rMemRelay.TargetID)
<< SERIAL("Message", rMemRelay.Message)
<< SERIAL("Active", rMemRelay.Active);
rArc << SerialParameter("MemoryRelayID", rMemRelay.InstanceID, SH_HexDisplay)
<< SerialParameter("TargetID", rMemRelay.TargetID, SH_HexDisplay)
<< SerialParameter("Message", rMemRelay.Message)
<< SerialParameter("Active", rMemRelay.Active);
}
void Serialize(IArchive& rArc, CWorld::SArea& rArea)
{
rArc << SERIAL("Name", rArea.InternalName)
<< SERIAL("NameString", rArea.pAreaName)
<< SERIAL("MREA", rArea.AreaResID)
<< SERIAL("ID", rArea.AreaID)
<< SERIAL("Transform", rArea.Transform)
<< SERIAL("BoundingBox", rArea.AetherBox)
<< SERIAL("AllowPakDuplicates", rArea.AllowPakDuplicates)
<< SERIAL_CONTAINER("AttachedAreas", rArea.AttachedAreaIDs, "AreaIndex")
<< SERIAL_CONTAINER("RelModules", rArea.RelFilenames, "Module")
<< SERIAL_CONTAINER("RelOffsets", rArea.RelOffsets, "Offset")
<< SERIAL_CONTAINER("Docks", rArea.Docks, "Dock")
<< SERIAL_CONTAINER("Layers", rArea.Layers, "Layer");
rArc << SerialParameter("Name", rArea.InternalName)
<< SerialParameter("NameString", rArea.pAreaName)
<< SerialParameter("MREA", rArea.AreaResID)
<< SerialParameter("ID", rArea.AreaID)
<< SerialParameter("Transform", rArea.Transform)
<< SerialParameter("BoundingBox", rArea.AetherBox)
<< SerialParameter("AllowPakDuplicates", rArea.AllowPakDuplicates)
<< SerialParameter("AttachedAreas", rArea.AttachedAreaIDs)
<< SerialParameter("RelModules", rArea.RelFilenames)
<< SerialParameter("RelOffsets", rArea.RelOffsets)
<< SerialParameter("Docks", rArea.Docks)
<< SerialParameter("Layers", rArea.Layers);
}
void Serialize(IArchive& rArc, CWorld::SArea::SDock& rDock)
{
rArc << SERIAL_CONTAINER("ConnectingDocks", rDock.ConnectingDocks, "ConnectingDock")
<< SERIAL_CONTAINER("DockCoords", rDock.DockCoordinates, "Coord");
rArc << SerialParameter("ConnectingDocks", rDock.ConnectingDocks)
<< SerialParameter("DockCoords", rDock.DockCoordinates);
}
void Serialize(IArchive& rArc, CWorld::SArea::SDock::SConnectingDock& rDock)
{
rArc << SERIAL("AreaIndex", rDock.AreaIndex)
<< SERIAL("DockIndex", rDock.DockIndex);
rArc << SerialParameter("AreaIndex", rDock.AreaIndex)
<< SerialParameter("DockIndex", rDock.DockIndex);
}
void Serialize(IArchive& rArc, CWorld::SArea::SLayer& rLayer)
{
rArc << SERIAL("Name", rLayer.LayerName)
<< SERIAL("Active", rLayer.Active);
rArc << SerialParameter("Name", rLayer.LayerName)
<< SerialParameter("Active", rLayer.Active);
if (rArc.Game() >= eCorruption)
if (rArc.Game() >= EGame::Corruption)
{
rArc << SERIAL("StateID", rLayer.LayerStateID);
rArc << SerialParameter("StateID", rLayer.LayerStateID);
}
}
void Serialize(IArchive& rArc, CWorld::SAudioGrp& rAudioGrp)
{
rArc << SERIAL("GroupID", rAudioGrp.GroupID)
<< SERIAL("AGSC", rAudioGrp.ResID);
rArc << SerialParameter("GroupID", rAudioGrp.GroupID)
<< SerialParameter("AGSC", rAudioGrp.ResID);
}

View File

@ -35,14 +35,14 @@ void CAreaCooker::DetermineSectionNumbersPrime()
switch (mVersion)
{
case ePrimeDemo:
case ePrime:
case EGame::PrimeDemo:
case EGame::Prime:
GeometrySections = 1 + (7 * OriginalMeshCount); // Accounting for materials
break;
case eEchoesDemo:
case EGame::EchoesDemo:
GeometrySections = 2 + (9 * OriginalMeshCount); // Account for materials + AROT
break;
case eEchoes:
case EGame::Echoes:
GeometrySections = 3 + (9 * OriginalMeshCount); // Acount for materials + AROT + an unknown section
break;
}
@ -52,13 +52,13 @@ void CAreaCooker::DetermineSectionNumbersPrime()
// Set section numbers
u32 SecNum = GeometrySections;
if (mVersion <= ePrime) mAROTSecNum = SecNum++;
if (mVersion >= eEchoesDemo) mFFFFSecNum = SecNum++;
if (mVersion <= EGame::Prime) mAROTSecNum = SecNum++;
if (mVersion >= EGame::EchoesDemo) mFFFFSecNum = SecNum++;
if (mVersion >= eEchoesDemo)
if (mVersion >= EGame::EchoesDemo)
{
mSCLYSecNum = SecNum;
SecNum += (mVersion >= eEchoes ? mpArea->mScriptLayers.size() : 1);
SecNum += (mVersion >= EGame::Echoes ? mpArea->mScriptLayers.size() : 1);
mSCGNSecNum = SecNum++;
}
else
@ -70,7 +70,7 @@ void CAreaCooker::DetermineSectionNumbersPrime()
mVISISecNum = SecNum++;
mPATHSecNum = SecNum++;
if (mVersion >= eEchoesDemo)
if (mVersion >= EGame::EchoesDemo)
{
mPTLASecNum = SecNum++;
mEGMCSecNum = SecNum++;
@ -98,18 +98,18 @@ void CAreaCooker::WritePrimeHeader(IOutputStream& rOut)
rOut.WriteLong(GetMREAVersion(mVersion));
mpArea->mTransform.Write(rOut);
rOut.WriteLong(mpArea->mOriginalWorldMeshCount);
if (mVersion >= eEchoes) rOut.WriteLong(mpArea->mScriptLayers.size());
if (mVersion >= EGame::Echoes) rOut.WriteLong(mpArea->mScriptLayers.size());
rOut.WriteLong(mpArea->mSectionDataBuffers.size());
rOut.WriteLong(mGeometrySecNum);
rOut.WriteLong(mSCLYSecNum);
if (mVersion >= eEchoesDemo) rOut.WriteLong(mSCGNSecNum);
if (mVersion >= EGame::EchoesDemo) rOut.WriteLong(mSCGNSecNum);
rOut.WriteLong(mCollisionSecNum);
rOut.WriteLong(mUnknownSecNum);
rOut.WriteLong(mLightsSecNum);
rOut.WriteLong(mVISISecNum);
rOut.WriteLong(mPATHSecNum);
if (mVersion <= ePrime) rOut.WriteLong(mAROTSecNum);
if (mVersion <= EGame::Prime) rOut.WriteLong(mAROTSecNum);
else
{
@ -118,9 +118,9 @@ void CAreaCooker::WritePrimeHeader(IOutputStream& rOut)
rOut.WriteLong(mEGMCSecNum);
}
if (mVersion >= eEchoesDemo)
if (mVersion >= EGame::EchoesDemo)
{
if (mVersion >= eEchoes) rOut.WriteLong(mCompressedBlocks.size());
if (mVersion >= EGame::Echoes) rOut.WriteLong(mCompressedBlocks.size());
rOut.WriteToBoundary(32, 0);
}
@ -128,7 +128,7 @@ void CAreaCooker::WritePrimeHeader(IOutputStream& rOut)
rOut.WriteLong(mSectionSizes[iSec]);
rOut.WriteToBoundary(32, 0);
if (mVersion >= eEchoes)
if (mVersion >= EGame::Echoes)
WriteCompressionHeader(rOut);
}
@ -188,7 +188,7 @@ void CAreaCooker::WritePrimeSCLY(IOutputStream& rOut)
// This function covers both Prime 1 and the Echoes demo.
// The Echoes demo has a similar SCLY format but with minor layout differences and with SCGN.
rOut.WriteFourCC( FOURCC('SCLY') );
mVersion <= ePrime ? rOut.WriteLong(1) : rOut.WriteByte(1);
mVersion <= EGame::Prime ? rOut.WriteLong(1) : rOut.WriteByte(1);
u32 NumLayers = mpArea->mScriptLayers.size();
rOut.WriteLong(NumLayers);
@ -227,7 +227,7 @@ void CAreaCooker::WritePrimeSCLY(IOutputStream& rOut)
FinishSection(false);
// SCGN
if (mVersion == eEchoesDemo)
if (mVersion == EGame::EchoesDemo)
{
rOut.WriteFourCC( FOURCC('SCGN') );
rOut.WriteByte(1);
@ -327,7 +327,7 @@ void CAreaCooker::FinishSection(bool SingleSectionBlock)
mSectionSizes.push_back(SecSize);
// Only track compressed blocks for MP2+. Write everything to one block for MP1.
if (mVersion >= eEchoes)
if (mVersion >= EGame::Echoes)
{
// Finish the current block if this is a single section block OR if the new section would push the block over the size limit.
if (mCurBlock.NumSections > 0 && (mCurBlock.DecompressedSize + SecSize > kSizeThreshold || SingleSectionBlock))
@ -350,8 +350,8 @@ void CAreaCooker::FinishBlock()
if (mCurBlock.NumSections == 0) return;
std::vector<u8> CompressedBuf(mCompressedData.Size() * 2);
bool EnableCompression = (mVersion >= eEchoes) && mpArea->mUsesCompression && !gkForceDisableCompression;
bool UseZlib = (mVersion == eReturns);
bool EnableCompression = (mVersion >= EGame::Echoes) && mpArea->mUsesCompression && !gkForceDisableCompression;
bool UseZlib = (mVersion == EGame::DKCReturns);
u32 CompressedSize = 0;
bool WriteCompressedData = false;
@ -394,7 +394,7 @@ bool CAreaCooker::CookMREA(CGameArea *pArea, IOutputStream& rOut)
Cooker.mpArea = pArea;
Cooker.mVersion = pArea->Game();
if (Cooker.mVersion <= eEchoes)
if (Cooker.mVersion <= EGame::Echoes)
Cooker.DetermineSectionNumbersPrime();
else
Cooker.DetermineSectionNumbersCorruption();
@ -413,13 +413,13 @@ bool CAreaCooker::CookMREA(CGameArea *pArea, IOutputStream& rOut)
}
// Write SCLY
if (Cooker.mVersion <= eEchoesDemo)
if (Cooker.mVersion <= EGame::EchoesDemo)
Cooker.WritePrimeSCLY(Cooker.mSectionData);
else
Cooker.WriteEchoesSCLY(Cooker.mSectionData);
// Write post-SCLY data sections
u32 PostSCLY = (Cooker.mVersion <= ePrime ? Cooker.mSCLYSecNum + 1 : Cooker.mSCGNSecNum + 1);
u32 PostSCLY = (Cooker.mVersion <= EGame::Prime ? Cooker.mSCLYSecNum + 1 : Cooker.mSCGNSecNum + 1);
for (u32 iSec = PostSCLY; iSec < pArea->mSectionDataBuffers.size(); iSec++)
{
if (iSec == Cooker.mModulesSecNum)
@ -435,7 +435,7 @@ bool CAreaCooker::CookMREA(CGameArea *pArea, IOutputStream& rOut)
Cooker.FinishBlock();
// Write to actual file
if (Cooker.mVersion <= eEchoes)
if (Cooker.mVersion <= EGame::Echoes)
Cooker.WritePrimeHeader(rOut);
else
Cooker.WriteCorruptionHeader(rOut);
@ -448,13 +448,13 @@ u32 CAreaCooker::GetMREAVersion(EGame Version)
{
switch (Version)
{
case ePrimeDemo: return 0xC;
case ePrime: return 0xF;
case eEchoesDemo: return 0x15;
case eEchoes: return 0x19;
case eCorruptionProto: return 0x1D;
case eCorruption: return 0x1E;
case eReturns: return 0x20;
default: return 0;
case EGame::PrimeDemo: return 0xC;
case EGame::Prime: return 0xF;
case EGame::EchoesDemo: return 0x15;
case EGame::Echoes: return 0x19;
case EGame::CorruptionProto: return 0x1D;
case EGame::Corruption: return 0x1E;
case EGame::DKCReturns: return 0x20;
default: return 0;
}
}

View File

@ -161,7 +161,7 @@ void CMaterialCooker::WriteMaterialPrime(IOutputStream& rOut)
bool HasKonst = (NumKonst > 0);
u32 Flags;
if (mVersion <= ePrime)
if (mVersion <= EGame::Prime)
Flags = 0x1003;
else
Flags = 0x4002;
@ -178,13 +178,13 @@ void CMaterialCooker::WriteMaterialPrime(IOutputStream& rOut)
// Vertex description
u32 VtxFlags = ConvertFromVertexDescription( mpMat->VtxDesc() );
if (mVersion < eEchoes)
if (mVersion < EGame::Echoes)
VtxFlags &= 0x00FFFFFF;
rOut.WriteLong(VtxFlags);
// Echoes unknowns
if (mVersion == eEchoes)
if (mVersion == EGame::Echoes)
{
rOut.WriteLong(mpMat->EchoesUnknownA());
rOut.WriteLong(mpMat->EchoesUnknownB());
@ -359,10 +359,10 @@ void CMaterialCooker::WriteCookedMatSet(CMaterialSet *pSet, EGame Version, IOutp
switch (Version)
{
case ePrimeDemo:
case ePrime:
case eEchoesDemo:
case eEchoes:
case EGame::PrimeDemo:
case EGame::Prime:
case EGame::EchoesDemo:
case EGame::Echoes:
Cooker.WriteMatSetPrime(rOut);
break;
}
@ -376,10 +376,10 @@ void CMaterialCooker::WriteCookedMaterial(CMaterial *pMat, EGame Version, IOutpu
switch (Version)
{
case ePrimeDemo:
case ePrime:
case eEchoesDemo:
case eEchoes:
case EGame::PrimeDemo:
case EGame::Prime:
case EGame::EchoesDemo:
case EGame::Echoes:
Cooker.WriteMaterialPrime(rOut);
break;
// TODO: Corruption/Uncooked

View File

@ -168,7 +168,7 @@ void CModelCooker::WriteModelPrime(IOutputStream& rOut)
{
CVertex *pVert = &pPrimitive->Vertices[iVert];
if (mVersion == eEchoes)
if (mVersion == EGame::Echoes)
{
for (u32 iMtxAttribs = 0; iMtxAttribs < 8; iMtxAttribs++)
if (VtxAttribs & (ePosMtx << iMtxAttribs))
@ -232,10 +232,10 @@ bool CModelCooker::CookCMDL(CModel *pModel, IOutputStream& rOut)
switch (pModel->Game())
{
case ePrimeDemo:
case ePrime:
case eEchoesDemo:
case eEchoes:
case EGame::PrimeDemo:
case EGame::Prime:
case EGame::EchoesDemo:
case EGame::Echoes:
Cooker.WriteModelPrime(rOut);
return true;
@ -248,17 +248,17 @@ u32 CModelCooker::GetCMDLVersion(EGame Version)
{
switch (Version)
{
case ePrimeDemo:
case ePrime:
case EGame::PrimeDemo:
case EGame::Prime:
return 0x2;
case eEchoesDemo:
case EGame::EchoesDemo:
return 0x3;
case eEchoes:
case EGame::Echoes:
return 0x4;
case eCorruptionProto:
case eCorruption:
case EGame::CorruptionProto:
case EGame::Corruption:
return 0x5;
case eReturns:
case EGame::DKCReturns:
return 0xA;
default:
return 0;

View File

@ -1,121 +1,149 @@
#include "CScriptCooker.h"
#include "Core/Resource/Script/CLink.h"
#include <Core/Resource/Script/Property/CArrayProperty.h>
#include <Core/Resource/Script/Property/CAssetProperty.h>
#include <Core/Resource/Script/Property/CEnumProperty.h>
#include <Core/Resource/Script/Property/CFlagsProperty.h>
void CScriptCooker::WriteProperty(IOutputStream& rOut,IProperty *pProp, bool InSingleStruct)
void CScriptCooker::WriteProperty(IOutputStream& rOut, IProperty* pProperty, bool InAtomicStruct)
{
u32 SizeOffset = 0, PropStart = 0;
void* pData = (mpArrayItemData ? mpArrayItemData : mpObject->PropertyData());
if (mGame >= eEchoesDemo && !InSingleStruct)
if (mGame >= EGame::EchoesDemo && !InAtomicStruct)
{
rOut.WriteLong(pProp->ID());
rOut.WriteLong(pProperty->ID());
SizeOffset = rOut.Tell();
rOut.WriteShort(0x0);
PropStart = rOut.Tell();
}
switch (pProp->Type())
switch (pProperty->Type())
{
case eBoolProperty:
case EPropertyType::Bool:
{
TBoolProperty *pBoolCast = static_cast<TBoolProperty*>(pProp);
rOut.WriteBool(pBoolCast->Get());
CBoolProperty* pBool = TPropCast<CBoolProperty>(pProperty);
rOut.WriteBool( pBool->Value(pData) );
break;
}
case eByteProperty:
case EPropertyType::Byte:
{
TByteProperty *pByteCast = static_cast<TByteProperty*>(pProp);
rOut.WriteByte(pByteCast->Get());
CByteProperty* pByte = TPropCast<CByteProperty>(pProperty);
rOut.WriteByte( pByte->Value(pData) );
break;
}
case eShortProperty:
case EPropertyType::Short:
{
TShortProperty *pShortCast = static_cast<TShortProperty*>(pProp);
rOut.WriteShort(pShortCast->Get());
CShortProperty* pShort = TPropCast<CShortProperty>(pProperty);
rOut.WriteShort( pShort->Value(pData) );
break;
}
case eLongProperty:
case EPropertyType::Int:
{
TLongProperty *pLongCast = static_cast<TLongProperty*>(pProp);
rOut.WriteLong(pLongCast->Get());
CIntProperty* pInt = TPropCast<CIntProperty>(pProperty);
rOut.WriteLong( pInt->Value(pData) );
break;
}
case eEnumProperty:
case EPropertyType::Float:
{
TEnumProperty *pEnumCast = static_cast<TEnumProperty*>(pProp);
rOut.WriteLong(pEnumCast->Get());
CFloatProperty* pFloat = TPropCast<CFloatProperty>(pProperty);
rOut.WriteFloat( pFloat->Value(pData) );
break;
}
case eBitfieldProperty:
case EPropertyType::Choice:
{
TBitfieldProperty *pBitfieldCast = static_cast<TBitfieldProperty*>(pProp);
rOut.WriteLong(pBitfieldCast->Get());
CChoiceProperty* pChoice = TPropCast<CChoiceProperty>(pProperty);
rOut.WriteLong( pChoice->Value(pData) );
break;
}
case eFloatProperty:
case EPropertyType::Enum:
{
TFloatProperty *pFloatCast = static_cast<TFloatProperty*>(pProp);
rOut.WriteFloat(pFloatCast->Get());
CEnumProperty* pEnum = TPropCast<CEnumProperty>(pProperty);
rOut.WriteLong( pEnum->Value(pData) );
break;
}
case eStringProperty:
case EPropertyType::Flags:
{
TStringProperty *pStringCast = static_cast<TStringProperty*>(pProp);
rOut.WriteString(pStringCast->Get());
CFlagsProperty* pFlags = TPropCast<CFlagsProperty>(pProperty);
rOut.WriteLong( pFlags->Value(pData) );
break;
}
case eVector3Property:
case EPropertyType::String:
{
TVector3Property *pVectorCast = static_cast<TVector3Property*>(pProp);
pVectorCast->Get().Write(rOut);
CStringProperty* pString = TPropCast<CStringProperty>(pProperty);
rOut.WriteString( pString->Value(pData) );
break;
}
case eColorProperty:
case EPropertyType::Vector:
{
TColorProperty *pColorCast = static_cast<TColorProperty*>(pProp);
pColorCast->Get().Write(rOut, false);
CVectorProperty* pVector = TPropCast<CVectorProperty>(pProperty);
pVector->ValueRef(pData).Write(rOut);
break;
}
case eSoundProperty:
case EPropertyType::Color:
{
TSoundProperty *pSoundCast = static_cast<TSoundProperty*>(pProp);
rOut.WriteLong(pSoundCast->Get());
CColorProperty* pColor = TPropCast<CColorProperty>(pProperty);
pColor->ValueRef(pData).Write(rOut);
break;
}
case eAssetProperty:
case EPropertyType::Asset:
{
TAssetProperty *pAssetCast = static_cast<TAssetProperty*>(pProp);
pAssetCast->Get().Write(rOut);
CAssetProperty* pAsset = TPropCast<CAssetProperty>(pProperty);
pAsset->ValueRef(pData).Write(rOut);
break;
}
case eCharacterProperty:
case EPropertyType::Sound:
{
TCharacterProperty *pCharCast = static_cast<TCharacterProperty*>(pProp);
pCharCast->Get().Write(rOut);
CSoundProperty* pSound = TPropCast<CSoundProperty>(pProperty);
rOut.WriteLong( pSound->Value(pData) );
break;
}
case eMayaSplineProperty:
case EPropertyType::Animation:
{
TMayaSplineProperty *pSplineCast = static_cast<TMayaSplineProperty*>(pProp);
std::vector<u8> Buffer = pSplineCast->Get();
if (!Buffer.empty()) rOut.WriteBytes(Buffer.data(), Buffer.size());
CAnimationProperty* pAnim = TPropCast<CAnimationProperty>(pProperty);
rOut.WriteLong( pAnim->Value(pData) );
break;
}
case EPropertyType::AnimationSet:
{
CAnimationSetProperty* pAnimSet = TPropCast<CAnimationSetProperty>(pProperty);
pAnimSet->ValueRef(pData).Write(rOut);
break;
}
case EPropertyType::Sequence:
{
// TODO
break;
}
case EPropertyType::Spline:
{
CSplineProperty* pSpline = TPropCast<CSplineProperty>(pProperty);
std::vector<char>& rBuffer = pSpline->ValueRef(pData);
if (!rBuffer.empty())
{
rOut.WriteBytes( rBuffer.data(), rBuffer.size() );
}
else
{
if (mGame < eReturns)
if (mGame < EGame::DKCReturns)
{
rOut.WriteShort(0);
rOut.WriteLong(0);
@ -132,47 +160,63 @@ void CScriptCooker::WriteProperty(IOutputStream& rOut,IProperty *pProp, bool InS
rOut.WriteByte(1);
}
}
break;
}
case eStructProperty:
case EPropertyType::Guid:
{
CPropertyStruct *pStruct = static_cast<CPropertyStruct*>(pProp);
CStructTemplate *pTemp = static_cast<CStructTemplate*>(pStruct->Template());
CGuidProperty* pGuid = TPropCast<CGuidProperty>(pProperty);
std::vector<char>& rBuffer = pGuid->ValueRef(pData);
if (rBuffer.empty())
rBuffer.resize(16, 0);
rOut.WriteBytes( rBuffer.data(), rBuffer.size() );
break;
}
case EPropertyType::Struct:
{
CStructProperty* pStruct = TPropCast<CStructProperty>(pProperty);
std::vector<IProperty*> PropertiesToWrite;
for (u32 iProp = 0; iProp < pStruct->Count(); iProp++)
for (u32 ChildIdx = 0; ChildIdx < pStruct->NumChildren(); ChildIdx++)
{
IProperty *pSubProp = pStruct->PropertyByIndex(iProp);\
IProperty *pChild = pStruct->ChildByIndex(ChildIdx);
if (pTemp->IsSingleProperty() || pSubProp->ShouldCook())
PropertiesToWrite.push_back(pSubProp);
if (pStruct->IsAtomic() || pChild->ShouldCook(pData))
PropertiesToWrite.push_back(pChild);
}
if (!pTemp->IsSingleProperty())
if (!pStruct->IsAtomic())
{
if (mGame <= ePrime)
if (mGame <= EGame::Prime)
rOut.WriteLong(PropertiesToWrite.size());
else
rOut.WriteShort((u16) PropertiesToWrite.size());
}
for (u32 iProp = 0; iProp < PropertiesToWrite.size(); iProp++)
WriteProperty(rOut, PropertiesToWrite[iProp], pTemp->IsSingleProperty());
for (u32 PropertyIdx = 0; PropertyIdx < PropertiesToWrite.size(); PropertyIdx++)
WriteProperty(rOut, PropertiesToWrite[PropertyIdx], pStruct->IsAtomic());
break;
}
case eArrayProperty:
case EPropertyType::Array:
{
CArrayProperty *pArray = static_cast<CArrayProperty*>(pProp);
rOut.WriteLong(pArray->Count());
CArrayProperty* pArray = TPropCast<CArrayProperty>(pProperty);
u32 Count = pArray->ArrayCount(pData);
rOut.WriteLong(Count);
for (u32 iProp = 0; iProp < pArray->Count(); iProp++)
WriteProperty(rOut, pArray->PropertyByIndex(iProp), true);
void* pOldItemData = mpArrayItemData;
for (u32 ElementIdx = 0; ElementIdx < pArray->ArrayCount(pData); ElementIdx++)
{
mpArrayItemData = pArray->ItemPointer(pData, ElementIdx);
WriteProperty(rOut, pArray->ItemArchetype(), true);
}
mpArrayItemData = pOldItemData;
break;
}
@ -194,7 +238,7 @@ void CScriptCooker::WriteInstance(IOutputStream& rOut, CScriptObject *pInstance)
// Note the format is pretty much the same between games; the main difference is a
// number of fields changed size between MP1 and 2, but they're still the same fields
bool IsPrime1 = (mGame <= ePrime);
bool IsPrime1 = (mGame <= EGame::Prime);
u32 ObjectType = pInstance->ObjectTypeID();
IsPrime1 ? rOut.WriteByte((u8) ObjectType) : rOut.WriteLong(ObjectType);
@ -209,15 +253,16 @@ void CScriptCooker::WriteInstance(IOutputStream& rOut, CScriptObject *pInstance)
u32 NumLinks = pInstance->NumLinks(eOutgoing);
IsPrime1 ? rOut.WriteLong(NumLinks) : rOut.WriteShort((u16) NumLinks);
for (u32 iLink = 0; iLink < pInstance->NumLinks(eOutgoing); iLink++)
for (u32 LinkIdx = 0; LinkIdx < NumLinks; LinkIdx++)
{
CLink *pLink = pInstance->Link(eOutgoing, iLink);
CLink *pLink = pInstance->Link(eOutgoing, LinkIdx);
rOut.WriteLong(pLink->State());
rOut.WriteLong(pLink->Message());
rOut.WriteLong(pLink->ReceiverID());
}
WriteProperty(rOut, pInstance->Properties(), false);
mpObject = pInstance;
WriteProperty(rOut, pInstance->Template()->Properties(), false);
u32 InstanceEnd = rOut.Tell();
rOut.Seek(SizeOffset, SEEK_SET);
@ -230,7 +275,7 @@ void CScriptCooker::WriteLayer(IOutputStream& rOut, CScriptLayer *pLayer)
{
ASSERT(pLayer->Area()->Game() == mGame);
rOut.WriteByte( mGame <= ePrime ? 0 : 1 ); // Version
rOut.WriteByte( mGame <= EGame::Prime ? 0 : 1 ); // Version
u32 InstanceCountOffset = rOut.Tell();
u32 NumWrittenInstances = 0;
@ -246,7 +291,7 @@ void CScriptCooker::WriteLayer(IOutputStream& rOut, CScriptLayer *pLayer)
if (mWriteGeneratedSeparately)
{
// GenericCreature instances in DKCR always write to both SCLY and SCGN
if (mGame == eReturns && pInstance->ObjectTypeID() == FOURCC('GCTR'))
if (mGame == EGame::DKCReturns && pInstance->ObjectTypeID() == FOURCC('GCTR'))
mGeneratedObjects.push_back(pInstance);
// Instances receiving a Generate/Activate message (MP2) or a
@ -257,7 +302,7 @@ void CScriptCooker::WriteLayer(IOutputStream& rOut, CScriptLayer *pLayer)
{
CLink *pLink = pInstance->Link(eIncoming, LinkIdx);
if (mGame <= eEchoes)
if (mGame <= EGame::Echoes)
{
if (pLink->State() == FOURCC('GRNT') && pLink->Message() == FOURCC('ACTV'))
{
@ -302,6 +347,6 @@ void CScriptCooker::WriteGeneratedLayer(IOutputStream& rOut)
rOut.WriteByte(1); // Version
rOut.WriteLong(mGeneratedObjects.size());
for (u32 InstIdx = 0; InstIdx < mGeneratedObjects.size(); InstIdx++)
WriteInstance(rOut, mGeneratedObjects[InstIdx]);
for (u32 ObjectIdx = 0; ObjectIdx < mGeneratedObjects.size(); ObjectIdx++)
WriteInstance(rOut, mGeneratedObjects[ObjectIdx]);
}

View File

@ -10,15 +10,19 @@
class CScriptCooker
{
EGame mGame;
CScriptObject* mpObject;
void* mpArrayItemData;
std::vector<CScriptObject*> mGeneratedObjects;
bool mWriteGeneratedSeparately;
void WriteProperty(IOutputStream& rOut,IProperty *pProp, bool InSingleStruct);
void WriteProperty(IOutputStream& rOut, IProperty* pProperty, bool InAtomicStruct);
public:
CScriptCooker(EGame Game, bool WriteGeneratedObjectsSeparately = true)
: mGame(Game)
, mWriteGeneratedSeparately(WriteGeneratedObjectsSeparately && mGame >= eEchoesDemo)
, mpObject(nullptr)
, mpArrayItemData(nullptr)
, mWriteGeneratedSeparately(WriteGeneratedObjectsSeparately && mGame >= EGame::EchoesDemo)
{}
void WriteInstance(IOutputStream& rOut, CScriptObject *pInstance);

View File

@ -1,841 +0,0 @@
#include "CTemplateWriter.h"
#include "CAreaCooker.h"
#include <Common/FileUtil.h>
#include <tinyxml2.h>
using namespace tinyxml2;
TString CTemplateWriter::smTemplatesDir = "../templates/";
CTemplateWriter::CTemplateWriter()
{
}
void CTemplateWriter::SavePropertyTemplate(IPropertyTemplate *pTemp)
{
// Check for a source file in the template's hierarchy; that indicates it's part of a struct template, not a script template
TString SourceFile = pTemp->FindStructSource();
// Struct
if (!SourceFile.IsEmpty())
{
CMasterTemplate *pMaster = pTemp->MasterTemplate();
auto StructIt = pMaster->mStructTemplates.find(SourceFile);
if (StructIt != pMaster->mStructTemplates.end())
{
CStructTemplate *pStruct = StructIt->second;
CTemplateWriter::SaveStructTemplate(pStruct);
}
}
// Script
else if (pTemp->ScriptTemplate())
CTemplateWriter::SaveScriptTemplate(pTemp->ScriptTemplate());
// Error
else
Log::Error("Couldn't save property template " + pTemp->IDString(true) + "; no struct template source path or script template found");
}
void CTemplateWriter::SaveAllTemplates()
{
// Create directory
std::list<CMasterTemplate*> MasterList = CMasterTemplate::MasterList();
FileUtil::MakeDirectory(smTemplatesDir);
// Resave property list
SavePropertyList();
// Resave master templates
for (auto it = MasterList.begin(); it != MasterList.end(); it++)
SaveGameTemplates(*it);
// Resave game list
XMLDocument GameList;
XMLDeclaration *pDecl = GameList.NewDeclaration();
GameList.LinkEndChild(pDecl);
XMLElement *pBase = GameList.NewElement("GameList");
pBase->SetAttribute("version", 4);
GameList.LinkEndChild(pBase);
XMLElement *pProperties = GameList.NewElement("properties");
pProperties->SetText("Properties.xml");
pBase->LinkEndChild(pProperties);
for (auto it = MasterList.begin(); it != MasterList.end(); it++)
{
CMasterTemplate *pMaster = *it;
XMLElement *pGame = GameList.NewElement("game");
pBase->LinkEndChild(pGame);
XMLElement *pGameName = GameList.NewElement("name");
pGameName->SetText(*pMaster->mGameName);
pGame->LinkEndChild(pGameName);
XMLElement *pAreaVersion = GameList.NewElement("mrea");
u32 VersionNumber = CAreaCooker::GetMREAVersion(pMaster->Game());
pAreaVersion->SetText(*TString::HexString(VersionNumber, 2));
pGame->LinkEndChild(pAreaVersion);
XMLElement *pTempPath = GameList.NewElement("master");
pTempPath->SetText(*pMaster->mSourceFile);
pGame->LinkEndChild(pTempPath);
}
TString GameListName = smTemplatesDir + "GameList.xml";
GameList.SaveFile(*GameListName);
}
void CTemplateWriter::SaveGameTemplates(CMasterTemplate *pMaster)
{
// Create directory
TString OutFile = smTemplatesDir + pMaster->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
FileUtil::MakeDirectory(OutDir);
// Resave script templates
for (auto it = pMaster->mTemplates.begin(); it != pMaster->mTemplates.end(); it++)
SaveScriptTemplate(it->second);
// Resave struct templates
for (auto it = pMaster->mStructTemplates.begin(); it != pMaster->mStructTemplates.end(); it++)
SaveStructTemplate(it->second);
// Resave master template
XMLDocument Master;
XMLDeclaration *pDecl = Master.NewDeclaration();
Master.LinkEndChild(pDecl);
XMLElement *pBase = Master.NewElement("MasterTemplate");
pBase->SetAttribute("version", 4);
Master.LinkEndChild(pBase);
// Write versions
if (!pMaster->mGameVersions.empty())
{
XMLElement *pVersionsBlock = Master.NewElement("versions");
pBase->LinkEndChild(pVersionsBlock);
for (auto it = pMaster->mGameVersions.begin(); it != pMaster->mGameVersions.end(); it++)
{
XMLElement *pVersion = Master.NewElement("version");
pVersion->SetText(*(*it));
pVersionsBlock->LinkEndChild(pVersion);
}
}
// Write script objects
XMLElement *pObjects = Master.NewElement("objects");
pBase->LinkEndChild(pObjects);
for (auto it = pMaster->mTemplates.begin(); it != pMaster->mTemplates.end(); it++)
{
u32 ObjID = (it->second)->ObjectID();
TString StrID;
if (ObjID <= 0xFF)
StrID = TString::HexString(ObjID, 2);
else
StrID = CFourCC(ObjID).ToString();
XMLElement *pObj = Master.NewElement("object");
pObj->SetAttribute("ID", *StrID);
pObj->SetAttribute("template", *(it->second)->mSourceFile);
pObjects->LinkEndChild(pObj);
}
// Write script states/messages
for (u32 iType = 0; iType < 2; iType++)
{
TString Type = (iType == 0 ? "state" : "message");
XMLElement *pElem = Master.NewElement(*(Type + "s"));
pBase->LinkEndChild(pElem);
u32 Num = (iType == 0 ? pMaster->NumStates() : pMaster->NumMessages());
for (u32 iScr = 0; iScr < Num; iScr++)
{
u32 ID;
TString Name;
if (iType == 0)
{
SState State = pMaster->StateByIndex(iScr);
ID = State.ID;
Name = State.Name;
}
else
{
SMessage Message = pMaster->MessageByIndex(iScr);
ID = Message.ID;
Name = Message.Name;
}
TString StrID;
if (ID <= 0xFF) StrID = TString::HexString(ID, 2);
else StrID = CFourCC(ID).ToString();
XMLElement *pSubElem = Master.NewElement(*Type);
pSubElem->SetAttribute("ID", *StrID);
pSubElem->SetAttribute("name", *Name);
pElem->LinkEndChild(pSubElem);
}
}
// Save file
Master.SaveFile(*OutFile);
}
void CTemplateWriter::SavePropertyList()
{
// Create XML
XMLDocument List;
XMLDeclaration *pDecl = List.NewDeclaration();
List.LinkEndChild(pDecl);
XMLElement *pBase = List.NewElement("Properties");
pBase->SetAttribute("version", 4);
List.LinkEndChild(pBase);
// Write properties
for (auto it = CMasterTemplate::smPropertyNames.begin(); it != CMasterTemplate::smPropertyNames.end(); it++)
{
u32 ID = it->first;
TString Name = it->second;
XMLElement *pElem = List.NewElement("property");
pElem->SetAttribute("ID", *TString::HexString(ID));
pElem->SetAttribute("name", *Name);
pBase->LinkEndChild(pElem);
}
TString OutFile = smTemplatesDir + "Properties.xml";
List.SaveFile(*OutFile);
}
void CTemplateWriter::SaveScriptTemplate(CScriptTemplate *pTemp)
{
CMasterTemplate *pMaster = pTemp->MasterTemplate();
// Create directory
TString OutFile = smTemplatesDir + pMaster->GetDirectory() + pTemp->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
FileUtil::MakeDirectory(*OutDir);
// Create new document
XMLDocument ScriptXML;
XMLDeclaration *pDecl = ScriptXML.NewDeclaration();
ScriptXML.LinkEndChild(pDecl);
// Base element
XMLElement *pRoot = ScriptXML.NewElement("ScriptTemplate");
pRoot->SetAttribute("version", 4);
ScriptXML.LinkEndChild(pRoot);
// Write object name
XMLElement *pName = ScriptXML.NewElement("name");
pName->SetText(*pTemp->Name());
pRoot->LinkEndChild(pName);
// Write modules
if (!pTemp->mModules.empty())
{
XMLElement *pModules = ScriptXML.NewElement("modules");
pRoot->LinkEndChild(pModules);
for (u32 iMod = 0; iMod < pTemp->mModules.size(); iMod++)
{
XMLElement *pModule = ScriptXML.NewElement("module");
pModule->SetText(*pTemp->mModules[iMod]);
pModules->LinkEndChild(pModule);
}
}
// Write properties
SaveProperties(&ScriptXML, pRoot, pTemp->mpBaseStruct);
// States/Messages [todo]
XMLElement *pStates = ScriptXML.NewElement("states");
pRoot->LinkEndChild(pStates);
XMLElement *pMessages = ScriptXML.NewElement("messages");
pRoot->LinkEndChild(pMessages);
// Write editor properties
XMLElement *pEditor = ScriptXML.NewElement("editor");
pRoot->LinkEndChild(pEditor);
// Editor Properties
XMLElement *pEditorProperties = ScriptXML.NewElement("properties");
pEditor->LinkEndChild(pEditorProperties);
TString PropNames[6] = {
"InstanceName", "Position", "Rotation",
"Scale", "Active", "LightParameters"
};
TIDString *pPropStrings[6] = {
&pTemp->mNameIDString, &pTemp->mPositionIDString, &pTemp->mRotationIDString,
&pTemp->mScaleIDString, &pTemp->mActiveIDString, &pTemp->mLightParametersIDString
};
for (u32 iProp = 0; iProp < 6; iProp++)
{
if (!pPropStrings[iProp]->IsEmpty())
{
XMLElement *pProperty = ScriptXML.NewElement("property");
pProperty->SetAttribute("name", *PropNames[iProp]);
pProperty->SetAttribute("ID", **pPropStrings[iProp]);
pEditorProperties->LinkEndChild(pProperty);
}
}
// Editor Assets
XMLElement *pAssets = ScriptXML.NewElement("assets");
pEditor->LinkEndChild(pAssets);
for (auto it = pTemp->mAssets.begin(); it != pTemp->mAssets.end(); it++)
{
TString Source = (it->AssetSource == CScriptTemplate::SEditorAsset::eFile ? "file" : "property");
TString Type;
switch (it->AssetType)
{
case CScriptTemplate::SEditorAsset::eModel: Type = "model"; break;
case CScriptTemplate::SEditorAsset::eAnimParams: Type = "animparams"; break;
case CScriptTemplate::SEditorAsset::eBillboard: Type = "billboard"; break;
case CScriptTemplate::SEditorAsset::eCollision: Type = "collision"; break;
}
s32 Force = -1;
if (it->AssetType == CScriptTemplate::SEditorAsset::eAnimParams)
Force = it->ForceNodeIndex;
XMLElement *pAsset = ScriptXML.NewElement(*Type);
pAsset->SetAttribute("source", *Source);
if (Force >= 0) pAsset->SetAttribute("force", *TString::FromInt32(Force, 0, 10));
pAsset->SetText(*it->AssetLocation);
pAssets->LinkEndChild(pAsset);
}
// Attachments
if (!pTemp->mAttachments.empty())
{
XMLElement *pAttachments = ScriptXML.NewElement("attachments");
pEditor->LinkEndChild(pAttachments);
for (auto it = pTemp->mAttachments.begin(); it != pTemp->mAttachments.end(); it++)
{
XMLElement *pAttachment = ScriptXML.NewElement("attachment");
pAttachment->SetAttribute("propertyID", *it->AttachProperty);
pAttachment->SetAttribute("locator", *it->LocatorName);
pAttachments->LinkEndChild(pAttachment);
// Sub-properties
if (it->AttachType != eAttach)
{
XMLElement *pAttachType = ScriptXML.NewElement("attach_type");
pAttachType->SetText("follow");
pAttachment->LinkEndChild(pAttachType);
}
}
}
// Preview Scale
if (pTemp->mPreviewScale != 1.f)
{
XMLElement *pPreviewScale = ScriptXML.NewElement("preview_scale");
pPreviewScale->SetText(*TString::FromFloat(pTemp->mPreviewScale));
pEditor->LinkEndChild(pPreviewScale);
}
// Rot/Scale Type
XMLElement *pRotType = ScriptXML.NewElement("rotation_type");
pEditor->LinkEndChild(pRotType);
pRotType->SetText(pTemp->mRotationType == CScriptTemplate::eRotationEnabled ? "enabled" : "disabled");
XMLElement *pScaleType = ScriptXML.NewElement("scale_type");
pEditor->LinkEndChild(pScaleType);
if (pTemp->mScaleType != CScriptTemplate::eScaleVolume)
pScaleType->SetText(pTemp->mScaleType == CScriptTemplate::eScaleEnabled ? "enabled" : "disabled");
else
{
pScaleType->SetText("volume");
// Volume Preview
XMLElement *pVolume = ScriptXML.NewElement("preview_volume");
pEditor->LinkEndChild(pVolume);
// Enum -> String conversion lambda to avoid redundant code
auto GetVolumeString = [](EVolumeShape shape) -> TString
{
switch (shape)
{
case eBoxShape: return "Box";
case eAxisAlignedBoxShape: return "AxisAlignedBox";
case eEllipsoidShape: return "Ellipsoid";
case eCylinderShape: return "Cylinder";
case eConditionalShape: return "Conditional";
default: return "INVALID";
}
};
pVolume->SetAttribute("shape", *GetVolumeString(pTemp->mVolumeShape));
if (pTemp->mVolumeScale != 1.f)
pVolume->SetAttribute("scale", pTemp->mVolumeScale);
if (pTemp->mVolumeShape == eConditionalShape)
{
pVolume->SetAttribute("propertyID", *pTemp->mVolumeConditionIDString);
// Find conditional test property
IPropertyTemplate *pProp = pTemp->mpBaseStruct->PropertyByIDString(pTemp->mVolumeConditionIDString);
// Write conditions
for (auto it = pTemp->mVolumeConditions.begin(); it != pTemp->mVolumeConditions.end(); it++)
{
// Value should be an integer, or a boolean condition
TString StrVal;
if (pProp->Type() == eBoolProperty)
StrVal = (it->Value == 1 ? "true" : "false");
else
StrVal = TString::HexString((u32) it->Value, (it->Value > 0xFF ? 8 : 2));
XMLElement *pCondition = ScriptXML.NewElement("condition");
pCondition->SetAttribute("value", *StrVal);
pCondition->SetAttribute("shape", *GetVolumeString(it->Shape));
if (it->Scale != 1.f) pCondition->SetAttribute("scale", it->Scale);
pVolume->LinkEndChild(pCondition);
}
}
}
// Write to file
ScriptXML.SaveFile(*OutFile);
}
void CTemplateWriter::SaveStructTemplate(CStructTemplate *pTemp)
{
// Create directory
CMasterTemplate *pMaster = pTemp->MasterTemplate();
TString OutFile = smTemplatesDir + pMaster->GetDirectory() + pTemp->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
TString Name = OutFile.GetFileName(false);
FileUtil::MakeDirectory(OutDir);
// Create new document and write struct properties to it
XMLDocument StructXML;
XMLDeclaration *pDecl = StructXML.NewDeclaration();
StructXML.LinkEndChild(pDecl);
XMLElement *pRoot = StructXML.NewElement("struct");
pRoot->SetAttribute("name", *Name);
pRoot->SetAttribute("type", (pTemp->IsSingleProperty() ? "single" : "multi"));
StructXML.LinkEndChild(pRoot);
SaveProperties(&StructXML, pRoot, pTemp);
StructXML.SaveFile(*OutFile);
}
void CTemplateWriter::SaveEnumTemplate(CEnumTemplate *pTemp)
{
// Create directory
CMasterTemplate *pMaster = pTemp->MasterTemplate();
TString OutFile = smTemplatesDir + pMaster->GetDirectory() + pTemp->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
TString Name = OutFile.GetFileName(false);
FileUtil::MakeDirectory(OutDir);
// Create new document and write enumerators to it
XMLDocument EnumXML;
XMLDeclaration *pDecl = EnumXML.NewDeclaration();
EnumXML.LinkEndChild(pDecl);
XMLElement *pRoot = EnumXML.NewElement("enum");
pRoot->SetAttribute("name", *Name);
EnumXML.LinkEndChild(pRoot);
SaveEnumerators(&EnumXML, pRoot, pTemp);
EnumXML.SaveFile(*OutFile);
}
void CTemplateWriter::SaveBitfieldTemplate(CBitfieldTemplate *pTemp)
{
// Create directory
CMasterTemplate *pMaster = pTemp->MasterTemplate();
TString OutFile = smTemplatesDir + pMaster->GetDirectory() + pTemp->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
TString Name = pTemp->mSourceFile.GetFileName(false);
FileUtil::MakeDirectory(OutDir);
// Create new document and write enumerators to it
XMLDocument BitfieldXML;
XMLDeclaration *pDecl = BitfieldXML.NewDeclaration();
BitfieldXML.LinkEndChild(pDecl);
XMLElement *pRoot = BitfieldXML.NewElement("bitfield");
pRoot->SetAttribute("name", *Name);
BitfieldXML.LinkEndChild(pRoot);
SaveBitFlags(&BitfieldXML, pRoot, pTemp);
BitfieldXML.SaveFile(*OutFile);
}
void CTemplateWriter::SaveProperties(XMLDocument *pDoc, XMLElement *pParent, CStructTemplate *pTemp)
{
// Create base element
XMLElement *pPropsBlock = pDoc->NewElement("properties");
pParent->LinkEndChild(pPropsBlock);
for (u32 iProp = 0; iProp < pTemp->Count(); iProp++)
{
// Get ID
IPropertyTemplate *pProp = pTemp->PropertyByIndex(iProp);
u32 ID = pProp->PropertyID();
TString StrID = TString::HexString(ID, (ID > 0xFF ? 8 : 2));
// Create element
XMLElement *pElem;
if (pProp->Type() == eStructProperty)
pElem = pDoc->NewElement("struct");
else if (pProp->Type() == eEnumProperty)
pElem = pDoc->NewElement("enum");
else if (pProp->Type() == eBitfieldProperty)
pElem = pDoc->NewElement("bitfield");
else if (pProp->Type() == eArrayProperty)
pElem = pDoc->NewElement("array");
else
pElem = pDoc->NewElement("property");
pPropsBlock->LinkEndChild(pElem);
// Set common property parameters, starting with ID
pElem->SetAttribute("ID", *StrID);
// Name
TString Name = pProp->Name();
if (pProp->Game() >= eEchoesDemo && ID > 0xFF)
{
TString MasterName = CMasterTemplate::PropertyName(ID);
if (Name != MasterName)
pElem->SetAttribute("name", *Name);
}
else
pElem->SetAttribute("name", *Name);
// Type
if (pProp->Type() == eStructProperty)
{
CStructTemplate *pStruct = static_cast<CStructTemplate*>(pProp);
if (pStruct->mSourceFile.IsEmpty())
pElem->SetAttribute("type", (pStruct->mIsSingleProperty ? "single" : "multi"));
}
else if (TString(pElem->Name()) == "property")
pElem->SetAttribute("type", *PropEnumToPropString(pProp->Type()));
// Versions
CMasterTemplate *pMaster = pProp->MasterTemplate();
u32 NumVersions = pProp->mAllowedVersions.size();
if (NumVersions > 0 && NumVersions != pMaster->mGameVersions.size())
{
XMLElement *pVersions = pDoc->NewElement("versions");
pElem->LinkEndChild(pVersions);
for (u32 iVer = 0; iVer < pMaster->mGameVersions.size(); iVer++)
{
if (pProp->IsInVersion(iVer))
{
XMLElement *pVersion = pDoc->NewElement("version");
pVersion->SetText(*pMaster->mGameVersions[iVer]);
pVersions->LinkEndChild(pVersion);
}
}
}
// Default
if (pProp->CanHaveDefault() && pProp->Game() >= eEchoesDemo)
{
XMLElement *pDefault = pDoc->NewElement("default");
pDefault->SetText(*pProp->DefaultToString());
pElem->LinkEndChild(pDefault);
}
// Description
if (!pProp->Description().IsEmpty())
{
XMLElement *pDesc = pDoc->NewElement("description");
pDesc->SetText(*pProp->Description());
pElem->LinkEndChild(pDesc);
}
// Range
if (pProp->IsNumerical() && pProp->HasValidRange())
{
XMLElement *pRange = pDoc->NewElement("range");
pRange->SetText(*pProp->RangeToString());
pElem->LinkEndChild(pRange);
}
// Suffix
if (pProp->IsNumerical())
{
TString Suffix = pProp->Suffix();
if (!Suffix.IsEmpty())
{
XMLElement *pSuffix = pDoc->NewElement("suffix");
pSuffix->SetText(*Suffix);
pElem->LinkEndChild(pSuffix);
}
}
// Cook Pref
ECookPreference CookPref = pProp->CookPreference();
if (CookPref != eNoCookPreference)
{
XMLElement *pCookPref = pDoc->NewElement("cook_pref");
pCookPref->SetText(CookPref == eAlwaysCook ? "always" : "never");
pElem->LinkEndChild(pCookPref);
}
// Asset-specific parameters
if (pProp->Type() == eAssetProperty)
{
CAssetTemplate *pAsset = static_cast<CAssetTemplate*>(pProp);
const CResTypeFilter& rkFilter = pAsset->TypeFilter();
TString ExtensionsString = rkFilter.ToString();
if (ExtensionsString.IsEmpty()) ExtensionsString = "UNKN";
pElem->SetAttribute("extensions", *ExtensionsString);
}
// Enum-specific parameters
else if (pProp->Type() == eEnumProperty)
{
CEnumTemplate *pEnum = static_cast<CEnumTemplate*>(pProp);
if (pEnum->mSourceFile.IsEmpty())
SaveEnumerators(pDoc, pElem, pEnum);
else
{
SaveEnumTemplate(pEnum);
pElem->SetAttribute("template", *pEnum->mSourceFile);
}
}
// Bitfield-specific parameters
else if (pProp->Type() == eBitfieldProperty)
{
CBitfieldTemplate *pBitfield = static_cast<CBitfieldTemplate*>(pProp);
if (pBitfield->mSourceFile.IsEmpty())
SaveBitFlags(pDoc, pElem, pBitfield);
else
{
SaveBitfieldTemplate(pBitfield);
pElem->SetAttribute("template", *pBitfield->mSourceFile);
}
}
// Struct/array-specific parameters
else if (pProp->Type() == eStructProperty || pProp->Type() == eArrayProperty)
{
// Element Name
if (pProp->Type() == eArrayProperty)
{
CArrayTemplate *pArray = static_cast<CArrayTemplate*>(pProp);
if (!pArray->ElementName().IsEmpty())
{
XMLElement *pElement = pDoc->NewElement("element_name");
pElement->SetText(*static_cast<CArrayTemplate*>(pProp)->ElementName());
pElem->LinkEndChild(pElement);
}
}
// Sub-properties
CStructTemplate *pStruct = static_cast<CStructTemplate*>(pProp);
if (pStruct->mSourceFile.IsEmpty())
SaveProperties(pDoc, pElem, pStruct);
else
{
CStructTemplate *pOriginal = pMaster->StructAtSource(pStruct->mSourceFile);
if (pOriginal)
SavePropertyOverrides(pDoc, pElem, pStruct, pOriginal);
pElem->SetAttribute("template", *pStruct->mSourceFile);
}
}
}
}
void CTemplateWriter::SavePropertyOverrides(XMLDocument *pDoc, XMLElement *pParent, CStructTemplate *pStruct, CStructTemplate *pOriginal)
{
if (!pStruct->StructDataMatches(pOriginal))
{
// Create base element
XMLElement *pPropsBlock = pDoc->NewElement("properties");
pParent->LinkEndChild(pPropsBlock);
for (u32 iProp = 0; iProp < pStruct->Count(); iProp++)
{
IPropertyTemplate *pProp = pStruct->PropertyByIndex(iProp);
IPropertyTemplate *pSource = pOriginal->PropertyByIndex(iProp);
if (!pProp->Matches(pSource))
{
// Create element
XMLElement *pElem;
if (pProp->Type() == eStructProperty)
pElem = pDoc->NewElement("struct");
else if (pProp->Type() == eEnumProperty)
pElem = pDoc->NewElement("enum");
else if (pProp->Type() == eBitfieldProperty)
pElem = pDoc->NewElement("bitfield");
else if (pProp->Type() == eArrayProperty)
pElem = pDoc->NewElement("array");
else
pElem = pDoc->NewElement("property");
pPropsBlock->LinkEndChild(pElem);
// ID
u32 ID = pProp->PropertyID();
pElem->SetAttribute("ID", *TString::HexString(pProp->PropertyID(), (ID > 0xFF ? 8 : 2)));
// Name
if (pProp->Name() != pSource->Name())
pElem->SetAttribute("name", *pProp->Name());
// Default
if (pProp->CanHaveDefault() && !pProp->RawDefaultValue()->Matches(pSource->RawDefaultValue()))
{
XMLElement *pDefault = pDoc->NewElement("default");
pDefault->SetText(*pProp->DefaultToString());
pElem->LinkEndChild(pDefault);
}
// Description
if (pProp->Description() != pSource->Description())
{
XMLElement *pDesc = pDoc->NewElement("description");
pDesc->SetText(*pProp->Description());
pElem->LinkEndChild(pDesc);
}
// Range
if (pProp->IsNumerical())
{
TString Range = pProp->RangeToString();
if (Range != pSource->RangeToString())
{
XMLElement *pRange = pDoc->NewElement("range");
pRange->SetText(*Range);
pElem->LinkEndChild(pRange);
}
}
// Suffix
if (pProp->Suffix() != pSource->Suffix())
{
XMLElement *pSuffix = pDoc->NewElement("suffix");
pSuffix->SetText(*pProp->Suffix());
pElem->LinkEndChild(pSuffix);
}
// Cook Pref
if (pProp->CookPreference() != pSource->CookPreference())
{
XMLElement *pCookPref = pDoc->NewElement("cook_pref");
TString PrefStr;
if (pProp->CookPreference() == eAlwaysCook) PrefStr = "always";
else if (pProp->CookPreference() == eNeverCook) PrefStr = "never";
else PrefStr = "none";
pCookPref->SetText(*PrefStr);
pElem->LinkEndChild(pCookPref);
}
// Asset-specific parameters
if (pProp->Type() == eAssetProperty)
{
CAssetTemplate *pAsset = static_cast<CAssetTemplate*>(pProp);
CAssetTemplate *pSourceAsset = static_cast<CAssetTemplate*>(pSource);
if (pAsset->TypeFilter() != pSourceAsset->TypeFilter())
{
TString ExtensionsString = pAsset->TypeFilter().ToString();
if (ExtensionsString.IsEmpty()) ExtensionsString = "UNKN";
pElem->SetAttribute("extensions", *ExtensionsString);
}
}
// Struct/array-specific parameters
else if (pProp->Type() == eStructProperty || pProp->Type() == eArrayProperty)
{
CStructTemplate *pStruct = static_cast<CStructTemplate*>(pProp);
CStructTemplate *pSourceStruct = static_cast<CStructTemplate*>(pSource);
SavePropertyOverrides(pDoc, pElem, pStruct, pSourceStruct);
}
}
}
}
}
void CTemplateWriter::SaveEnumerators(XMLDocument *pDoc, XMLElement *pParent, CEnumTemplate *pTemp)
{
XMLElement *pEnumerators = pDoc->NewElement("enumerators");
pParent->LinkEndChild(pEnumerators);
for (u32 iEnum = 0; iEnum < pTemp->NumEnumerators(); iEnum++)
{
XMLElement *pElem = pDoc->NewElement("enumerator");
u32 EnumerID = pTemp->EnumeratorID(iEnum);
pElem->SetAttribute("ID", *TString::HexString(EnumerID, (EnumerID > 0xFF ? 8 : 2)));
pElem->SetAttribute("name", *pTemp->EnumeratorName(iEnum));
pEnumerators->LinkEndChild(pElem);
}
}
void CTemplateWriter::SaveBitFlags(XMLDocument *pDoc, XMLElement *pParent, CBitfieldTemplate *pTemp)
{
XMLElement *pFlags = pDoc->NewElement("flags");
pParent->LinkEndChild(pFlags);
for (u32 iFlag = 0; iFlag < pTemp->NumFlags(); iFlag++)
{
XMLElement *pElem = pDoc->NewElement("flag");
pElem->SetAttribute("mask", *TString::HexString(pTemp->FlagMask(iFlag)));
pElem->SetAttribute("name", *pTemp->FlagName(iFlag));
pFlags->LinkEndChild(pElem);
}
}

View File

@ -1,28 +0,0 @@
#ifndef CTEMPLATEWRITER_H
#define CTEMPLATEWRITER_H
#include "Core/Resource/Script/CMasterTemplate.h"
#include "Core/Resource/Script/CScriptTemplate.h"
#include <tinyxml2.h>
class CTemplateWriter
{
CTemplateWriter();
static TString smTemplatesDir;
public:
static void SavePropertyTemplate(IPropertyTemplate *pTemp);
static void SaveAllTemplates();
static void SaveGameTemplates(CMasterTemplate *pMaster);
static void SavePropertyList();
static void SaveScriptTemplate(CScriptTemplate *pTemp);
static void SaveStructTemplate(CStructTemplate *pTemp);
static void SaveEnumTemplate(CEnumTemplate *pTemp);
static void SaveBitfieldTemplate(CBitfieldTemplate *pTemp);
static void SaveProperties(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CStructTemplate *pTemp);
static void SavePropertyOverrides(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CStructTemplate *pStruct, CStructTemplate *pOriginal);
static void SaveEnumerators(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CEnumTemplate *pTemp);
static void SaveBitFlags(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CBitfieldTemplate *pTemp);
};
#endif // CTEMPLATEWRITER_H

View File

@ -22,15 +22,15 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
WorldNameID.Write(rMLVL);
if (Game == eEchoesDemo || Game == eEchoes)
if (Game == EGame::EchoesDemo || Game == EGame::Echoes)
{
DarkWorldNameID.Write(rMLVL);
}
if (Game >= eEchoesDemo && Game <= eCorruption)
if (Game >= EGame::EchoesDemo && Game <= EGame::Corruption)
{
rMLVL.WriteLong(pWorld->mTempleKeyWorldIndex);
}
if (Game == eReturns)
if (Game == EGame::DKCReturns)
{
const CWorld::STimeAttackData& rkData = pWorld->mTimeAttackData;
rMLVL.WriteBool(rkData.HasTimeAttack);
@ -49,7 +49,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
DefaultSkyID.Write(rMLVL);
// Memory Relays
if (Game == ePrime)
if (Game == EGame::Prime)
{
rMLVL.WriteLong( pWorld->mMemoryRelays.size() );
@ -65,7 +65,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
// Areas
rMLVL.WriteLong(pWorld->mAreas.size());
if (Game <= ePrime) rMLVL.WriteLong(1); // Unknown
if (Game <= EGame::Prime) rMLVL.WriteLong(1); // Unknown
std::set<CAssetID> AudioGroups;
for (u32 iArea = 0; iArea < pWorld->mAreas.size(); iArea++)
@ -83,7 +83,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
rArea.AreaID.Write(rMLVL);
// Attached Areas
if (Game <= eCorruption)
if (Game <= EGame::Corruption)
{
rMLVL.WriteLong( rArea.AttachedAreaIDs.size() );
@ -92,7 +92,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
}
// Dependencies
if (Game <= eEchoes)
if (Game <= EGame::Echoes)
{
std::list<CAssetID> Dependencies;
std::list<u32> LayerDependsOffsets;
@ -117,7 +117,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
}
// Docks
if (Game <= eCorruption)
if (Game <= EGame::Corruption)
{
rMLVL.WriteLong( rArea.Docks.size() );
@ -141,7 +141,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
}
// Module Dependencies
if (Game == eEchoesDemo || Game == eEchoes)
if (Game == EGame::EchoesDemo || Game == EGame::Echoes)
{
std::vector<TString> ModuleNames;
std::vector<u32> ModuleLayerOffsets;
@ -160,15 +160,15 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
}
// Unknown
if (Game == eReturns)
if (Game == EGame::DKCReturns)
rMLVL.WriteLong(0);
// Internal Name
if (Game >= eEchoesDemo)
if (Game >= EGame::EchoesDemo)
rMLVL.WriteString(rArea.InternalName);
}
if (Game <= eCorruption)
if (Game <= EGame::Corruption)
{
// World Map
CAssetID MapWorldID = pWorld->mpMapWorld ? pWorld->mpMapWorld->ID() : CAssetID::skInvalidID32;
@ -180,7 +180,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
}
// Audio Groups
if (Game <= ePrime)
if (Game <= EGame::Prime)
{
// Create sorted list of audio groups (sort by group ID)
std::vector<CAudioGroup*> SortedAudioGroups;
@ -244,7 +244,7 @@ bool CWorldCooker::CookMLVL(CWorld *pWorld, IOutputStream& rMLVL)
rMLVL.WriteString(LayerNames[iLyr]);
// Layer Saved State IDs
if (Game >= eCorruption)
if (Game >= EGame::Corruption)
{
rMLVL.WriteLong(LayerStateIDs.size());
@ -265,12 +265,12 @@ u32 CWorldCooker::GetMLVLVersion(EGame Version)
{
switch (Version)
{
case ePrimeDemo: return 0xD;
case ePrime: return 0x11;
case eEchoesDemo: return 0x14;
case eEchoes: return 0x17;
case eCorruption: return 0x19;
case eReturns: return 0x1B;
case EGame::PrimeDemo: return 0xD;
case EGame::Prime: return 0x11;
case EGame::EchoesDemo: return 0x14;
case EGame::Echoes: return 0x17;
case EGame::Corruption: return 0x19;
case EGame::DKCReturns: return 0x1B;
default: return 0;
}
}

View File

@ -74,5 +74,8 @@ enum EResType
eInvalidResType = -1
};
// Defined in CResTypeInfo.cpp
void Serialize(IArchive& rArc, EResType& rType);
#endif // ERESTYPE

View File

@ -47,9 +47,9 @@ s32 CAnimEventLoader::LoadEventBase(IInputStream& rEVNT)
{
rEVNT.Skip(0x2);
rEVNT.ReadString();
rEVNT.Skip(mGame < eCorruptionProto ? 0x13 : 0x17);
rEVNT.Skip(mGame < EGame::CorruptionProto ? 0x13 : 0x17);
s32 CharacterIndex = rEVNT.ReadLong();
rEVNT.Skip(mGame < eCorruptionProto ? 0x4 : 0x18);
rEVNT.Skip(mGame < EGame::CorruptionProto ? 0x4 : 0x18);
return CharacterIndex;
}
@ -69,13 +69,13 @@ void CAnimEventLoader::LoadUserEvent(IInputStream& rEVNT)
void CAnimEventLoader::LoadEffectEvent(IInputStream& rEVNT)
{
s32 CharIndex = LoadEventBase(rEVNT);
rEVNT.Skip(mGame < eCorruptionProto ? 0x8 : 0x4);
rEVNT.Skip(mGame < EGame::CorruptionProto ? 0x8 : 0x4);
CAssetID ParticleID(rEVNT, mGame);
mpEventData->AddEvent(CharIndex, ParticleID);
if (mGame <= ePrime)
if (mGame <= EGame::Prime)
rEVNT.ReadString();
else if (mGame <= eEchoes)
else if (mGame <= EGame::Echoes)
rEVNT.Skip(0x4);
rEVNT.Skip(0x8);
@ -86,11 +86,11 @@ void CAnimEventLoader::LoadSoundEvent(IInputStream& rEVNT)
s32 CharIndex = LoadEventBase(rEVNT);
// Metroid Prime 1/2
if (mGame <= eEchoes)
if (mGame <= EGame::Echoes)
{
u32 SoundID = rEVNT.ReadLong() & 0xFFFF;
rEVNT.Skip(0x8);
if (mGame >= eEchoes) rEVNT.Skip(0xC);
if (mGame >= EGame::Echoes) rEVNT.Skip(0xC);
if (SoundID != 0xFFFF)
{
@ -134,7 +134,7 @@ CAnimEventData* CAnimEventLoader::LoadEVNT(IInputStream& rEVNT, CResourceEntry *
{
CAnimEventLoader Loader;
Loader.mpEventData = new CAnimEventData(pEntry);
Loader.mGame = ePrime;
Loader.mGame = EGame::Prime;
Loader.LoadEvents(rEVNT);
return Loader.mpEventData;
}
@ -143,7 +143,7 @@ CAnimEventData* CAnimEventLoader::LoadAnimSetEvents(IInputStream& rANCS)
{
CAnimEventLoader Loader;
Loader.mpEventData = new CAnimEventData();
Loader.mGame = eEchoes;
Loader.mGame = EGame::Echoes;
Loader.LoadEvents(rANCS);
return Loader.mpEventData;
}
@ -152,7 +152,7 @@ CAnimEventData* CAnimEventLoader::LoadCorruptionCharacterEventSet(IInputStream&
{
CAnimEventLoader Loader;
Loader.mpEventData = new CAnimEventData();
Loader.mGame = eCorruption;
Loader.mGame = EGame::Corruption;
// Read event set header
rCHAR.Skip(0x4); // Skip animation ID

View File

@ -116,8 +116,8 @@ CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR)
for (u32 ModelIdx = 0; ModelIdx < NumModels; ModelIdx++)
{
rCHAR.ReadString();
CAssetID ModelID(rCHAR, eReturns);
CAssetID SkinID(rCHAR, eReturns);
CAssetID ModelID(rCHAR, EGame::DKCReturns);
CAssetID SkinID(rCHAR, EGame::DKCReturns);
rCHAR.Skip(0x18);
if (ModelIdx == 0)
@ -138,7 +138,7 @@ CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR)
for (u32 AnimIdx = 0; AnimIdx < NumAnims; AnimIdx++)
{
TString AnimName = rCHAR.ReadString();
CAssetID AnimID(rCHAR, eReturns);
CAssetID AnimID(rCHAR, EGame::DKCReturns);
rCHAR.Skip(0x25);
rChar.DKDependencies.push_back(AnimID);
@ -229,7 +229,7 @@ CAnimSet* CAnimSetLoader::LoadReturnsCHAR(IInputStream& rCHAR)
for (u32 ResIdx = 0; ResIdx < NumResources; ResIdx++)
{
CAssetID ResID(rCHAR, eReturns);
CAssetID ResID(rCHAR, EGame::DKCReturns);
rCHAR.Skip(3);
rChar.DKDependencies.push_back(ResID);
}
@ -293,7 +293,7 @@ void CAnimSetLoader::LoadParticleResourceData(IInputStream& rFile, SSetCharacter
for (u32 iSwoosh = 0; iSwoosh < SwooshCount; iSwoosh++)
pChar->SwooshParticles.push_back( CAssetID(rFile, mGame) );
if (CharVersion >= 6 && mGame <= eEchoes) rFile.Seek(0x4, SEEK_CUR);
if (CharVersion >= 6 && mGame <= EGame::Echoes) rFile.Seek(0x4, SEEK_CUR);
u32 ElectricCount = rFile.ReadLong();
pChar->ElectricParticles.reserve(ElectricCount);
@ -301,7 +301,7 @@ void CAnimSetLoader::LoadParticleResourceData(IInputStream& rFile, SSetCharacter
for (u32 iElec = 0; iElec < ElectricCount; iElec++)
pChar->ElectricParticles.push_back( CAssetID(rFile, mGame) );
if (mGame >= eEchoes)
if (mGame >= EGame::Echoes)
{
u32 SpawnCount = rFile.ReadLong();
pChar->SpawnParticles.reserve(SpawnCount);
@ -311,7 +311,7 @@ void CAnimSetLoader::LoadParticleResourceData(IInputStream& rFile, SSetCharacter
}
rFile.Seek(0x4, SEEK_CUR);
if (mGame >= eEchoes) rFile.Seek(0x4, SEEK_CUR);
if (mGame >= EGame::Echoes) rFile.Seek(0x4, SEEK_CUR);
}
void CAnimSetLoader::LoadAnimationSet(IInputStream& rANCS)
@ -379,7 +379,7 @@ void CAnimSetLoader::LoadAnimationSet(IInputStream& rANCS)
// Skipping MP1 ANIM asset list
// Events
if (mGame >= eEchoesDemo)
if (mGame >= EGame::EchoesDemo)
{
u32 EventDataCount = rANCS.ReadLong();
pSet->mAnimEvents.reserve(EventDataCount);
@ -410,7 +410,7 @@ void CAnimSetLoader::ProcessPrimitives()
for (u32 iTrans = 0; iTrans < pSet->mHalfTransitions.size(); iTrans++)
pSet->mHalfTransitions[iTrans].pMetaTrans->GetUniquePrimitives(UniquePrimitives);
if (mGame == eCorruptionProto || mGame == eCorruption)
if (mGame == EGame::CorruptionProto || mGame == EGame::Corruption)
{
CSourceAnimData *pAnimData = gpResourceStore->LoadResource<CSourceAnimData>( pSet->mCharacters[0].AnimDataID );
@ -431,7 +431,7 @@ void CAnimSetLoader::ProcessPrimitives()
}
// Add used animation indices from the animset to the character's list
if (mGame <= eEchoes)
if (mGame <= EGame::Echoes)
{
// Add animations referenced by default transition
if (pSet->mpDefaultTransition)
@ -537,9 +537,9 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
pChar->ID = rANCS.ReadLong();
u16 CharVersion = rANCS.ReadShort();
if (iNode == 0 && Loader.mGame == eUnknownGame)
if (iNode == 0 && Loader.mGame == EGame::Invalid)
{
Loader.mGame = (CharVersion == 0xA) ? eEchoes : ePrime;
Loader.mGame = (CharVersion == 0xA) ? EGame::Echoes : EGame::Prime;
}
pChar->Name = rANCS.ReadString();
pChar->pModel = gpResourceStore->LoadResource<CModel>(rANCS.ReadLong());
@ -554,7 +554,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
for (u32 iAnim = 0; iAnim < AnimCount; iAnim++)
{
rANCS.Seek(0x4, SEEK_CUR);
if (Loader.mGame == ePrime) rANCS.Seek(0x1, SEEK_CUR);
if (Loader.mGame == EGame::Prime) rANCS.Seek(0x1, SEEK_CUR);
rANCS.ReadString();
}
@ -584,8 +584,8 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
CAssetID ParticleID(rANCS, e32Bit);
if (ParticleID.IsValid()) pChar->EffectParticles.push_back(ParticleID);
if (Loader.mGame == ePrime) rANCS.ReadString();
if (Loader.mGame == eEchoes) rANCS.Seek(0x4, SEEK_CUR);
if (Loader.mGame == EGame::Prime) rANCS.ReadString();
if (Loader.mGame == EGame::Echoes) rANCS.Seek(0x4, SEEK_CUR);
rANCS.Seek(0xC, SEEK_CUR);
}
}
@ -604,7 +604,7 @@ CAnimSet* CAnimSetLoader::LoadANCS(IInputStream& rANCS, CResourceEntry *pEntry)
pChar->UsedAnimationIndices.insert(AnimIndex);
}
if (Loader.mGame == eEchoes)
if (Loader.mGame == EGame::Echoes)
{
pChar->SpatialPrimitives = rANCS.ReadLong();
rANCS.Seek(0x1, SEEK_CUR);
@ -629,14 +629,14 @@ CAnimSet* CAnimSetLoader::LoadCHAR(IInputStream& rCHAR, CResourceEntry *pEntry)
if (Check == 0x5 || Check == 0x3)
{
Loader.mGame = eCorruption;
Loader.mGame = EGame::Corruption;
Loader.pSet = new CAnimSet(pEntry);
return Loader.LoadCorruptionCHAR(rCHAR);
}
if (Check == 0x59)
{
Loader.mGame = eReturns;
Loader.mGame = EGame::DKCReturns;
Loader.pSet = new CAnimSet(pEntry);
return Loader.LoadReturnsCHAR(rCHAR);
}

View File

@ -43,7 +43,7 @@ EGame CAnimationLoader::UncompressedCheckVersion()
u32 Start = mpInput->Tell();
bool Echoes = UncompressedCheckEchoes();
mpInput->Seek(Start, SEEK_SET);
return (Echoes ? eEchoes : ePrime);
return (Echoes ? EGame::Echoes : EGame::Prime);
}
void CAnimationLoader::ReadUncompressedANIM()
@ -75,13 +75,13 @@ void CAnimationLoader::ReadUncompressedANIM()
NumBoneChannels++;
}
if (mGame == eUnknownGame)
if (mGame == EGame::Invalid)
mGame = UncompressedCheckVersion();
// Echoes only - rotation channel indices
std::vector<u8> RotationIndices;
if (mGame == eEchoes)
if (mGame == EGame::Echoes)
{
u32 NumRotationIndices = mpInput->ReadLong();
RotationIndices.resize(NumRotationIndices);
@ -125,7 +125,7 @@ void CAnimationLoader::ReadUncompressedANIM()
// Echoes only - scale channel indices
std::vector<u8> ScaleIndices;
if (mGame == eEchoes)
if (mGame == EGame::Echoes)
{
u32 NumScaleIndices = mpInput->ReadLong();
ScaleIndices.resize(NumScaleIndices);
@ -161,7 +161,7 @@ void CAnimationLoader::ReadUncompressedANIM()
}
// Read bone transforms
if (mGame == eEchoes)
if (mGame == EGame::Echoes)
{
mpInput->Seek(0x4, SEEK_CUR); // Skipping scale key count
mpAnim->mScaleChannels.resize(NumScaleChannels);
@ -197,7 +197,7 @@ void CAnimationLoader::ReadUncompressedANIM()
mpAnim->mTranslationChannels[iTrans][iKey] = CVector3f(*mpInput);
}
if (mGame == ePrime)
if (mGame == EGame::Prime)
{
mpAnim->mpEventData = gpResourceStore->LoadResource<CAnimEventData>(mpInput->ReadLong());
}
@ -208,10 +208,10 @@ void CAnimationLoader::ReadCompressedANIM()
// Header
mpInput->Seek(0x4, SEEK_CUR); // Skip alloc size
if (mGame == eUnknownGame)
mGame = (mpInput->PeekShort() == 0x0101 ? eEchoes : ePrime);
if (mGame == EGame::Invalid)
mGame = (mpInput->PeekShort() == 0x0101 ? EGame::Echoes : EGame::Prime);
if (mGame == ePrime)
if (mGame == EGame::Prime)
{
mpAnim->mpEventData = gpResourceStore->LoadResource<CAnimEventData>(mpInput->ReadLong());
mpInput->Seek(0x4, SEEK_CUR); // Skip unknown
@ -224,7 +224,7 @@ void CAnimationLoader::ReadCompressedANIM()
mRotationDivisor = mpInput->ReadLong();
mTranslationMultiplier = mpInput->ReadFloat();
if (mGame == eEchoes) mScaleMultiplier = mpInput->ReadFloat();
if (mGame == EGame::Echoes) mScaleMultiplier = mpInput->ReadFloat();
u32 NumBoneChannels = mpInput->ReadLong();
mpInput->Seek(0x4, SEEK_CUR); // Skip unknown value
@ -238,7 +238,7 @@ void CAnimationLoader::ReadCompressedANIM()
for (u32 iBit = 0; iBit < NumKeys; iBit++)
mKeyFlags[iBit] = BitStream.ReadBit();
}
mpInput->Seek(mGame == ePrime ? 0x8 : 0x4, SEEK_CUR);
mpInput->Seek(mGame == EGame::Prime ? 0x8 : 0x4, SEEK_CUR);
// Read bone channel descriptors
mCompressedChannels.resize(NumBoneChannels);
@ -249,7 +249,7 @@ void CAnimationLoader::ReadCompressedANIM()
for (u32 iChan = 0; iChan < NumBoneChannels; iChan++)
{
SCompressedChannel& rChan = mCompressedChannels[iChan];
rChan.BoneID = (mGame == ePrime ? mpInput->ReadLong() : mpInput->ReadByte());
rChan.BoneID = (mGame == EGame::Prime ? mpInput->ReadLong() : mpInput->ReadByte());
// Read rotation parameters
rChan.NumRotationKeys = mpInput->ReadShort();
@ -284,7 +284,7 @@ void CAnimationLoader::ReadCompressedANIM()
// Read scale parameters
u8 ScaleIdx = 0xFF;
if (mGame == eEchoes)
if (mGame == EGame::Echoes)
{
rChan.NumScaleKeys = mpInput->ReadShort();
@ -465,7 +465,7 @@ CQuaternion CAnimationLoader::DequantizeRotation(bool Sign, s16 X, s16 Y, s16 Z)
CAnimation* CAnimationLoader::LoadANIM(IInputStream& rANIM, CResourceEntry *pEntry)
{
// MP3/DKCR unsupported
if (pEntry->Game() > eEchoes)
if (pEntry->Game() > EGame::Echoes)
return new CAnimation(pEntry);
u32 CompressionType = rANIM.ReadLong();

View File

@ -81,7 +81,7 @@ void CAreaLoader::ReadGeometryPrime()
CModel *pModel = CModelLoader::LoadWorldModel(*mpMREA, *mpSectionMgr, *mpArea->mpMaterialSet, mVersion);
FileModels.push_back(pModel);
if (mVersion <= ePrime)
if (mVersion <= EGame::Prime)
mpArea->AddWorldModel(pModel);
// For Echoes+, load surface mesh IDs, then skip to the start of the next mesh
@ -101,7 +101,7 @@ void CAreaLoader::ReadGeometryPrime()
}
// Split meshes
if (mVersion >= eEchoesDemo)
if (mVersion >= EGame::EchoesDemo)
{
std::vector<CModel*> SplitModels;
CModelLoader::BuildWorldMeshes(FileModels, SplitModels, true);
@ -124,7 +124,7 @@ void CAreaLoader::ReadSCLYPrime()
Log::FileError(mpMREA->GetSourceString(), mpMREA->Tell() - 4, "Invalid SCLY magic: " + SCLY.ToString());
return;
}
mpMREA->Seek(mVersion <= ePrime ? 4 : 1, SEEK_CUR); // Skipping unknown value which is always 1
mpMREA->Seek(mVersion <= EGame::Prime ? 4 : 1, SEEK_CUR); // Skipping unknown value which is always 1
// Read layer sizes
mNumLayers = mpMREA->ReadLong();
@ -145,7 +145,7 @@ void CAreaLoader::ReadSCLYPrime()
// SCGN
CScriptLayer *pGenLayer = nullptr;
if (mVersion >= eEchoesDemo)
if (mVersion >= EGame::EchoesDemo)
{
mpSectionMgr->ToSection(mScriptGeneratorBlockNum);
CFourCC SCGN = mpMREA->ReadFourCC();
@ -252,7 +252,7 @@ void CAreaLoader::ReadHeaderEchoes()
// This function reads the header for Echoes and the Echoes demo disc
mpArea->mTransform = CTransform4f(*mpMREA);
mNumMeshes = mpMREA->ReadLong();
if (mVersion == eEchoes) mNumLayers = mpMREA->ReadLong();
if (mVersion == EGame::Echoes) mNumLayers = mpMREA->ReadLong();
u32 numBlocks = mpMREA->ReadLong();
mGeometryBlockNum = mpMREA->ReadLong();
@ -266,13 +266,13 @@ void CAreaLoader::ReadHeaderEchoes()
mFFFFBlockNum = mpMREA->ReadLong();
mPTLABlockNum = mpMREA->ReadLong();
mEGMCBlockNum = mpMREA->ReadLong();
if (mVersion == eEchoes) mClusters.resize(mpMREA->ReadLong());
if (mVersion == EGame::Echoes) mClusters.resize(mpMREA->ReadLong());
mpMREA->SeekToBoundary(32);
mpSectionMgr = new CSectionMgrIn(numBlocks, mpMREA);
mpMREA->SeekToBoundary(32);
if (mVersion == eEchoes)
if (mVersion == EGame::Echoes)
{
ReadCompressedBlocks();
Decompress();
@ -440,7 +440,7 @@ void CAreaLoader::ReadDependenciesCorruption()
for (u32 DepIdx = 0; DepIdx < NumLayerDeps; DepIdx++)
{
CAssetID AssetID(*mpMREA, eCorruption);
CAssetID AssetID(*mpMREA, EGame::Corruption);
mpMREA->Skip(4);
mpArea->mExtraLayerDeps[LayerIdx].push_back(AssetID);
}
@ -452,7 +452,7 @@ void CAreaLoader::ReadDependenciesCorruption()
for (u32 DepIdx = 0; DepIdx < NumAreaDeps; DepIdx++)
{
CAssetID AssetID(*mpMREA, eCorruption);
CAssetID AssetID(*mpMREA, EGame::Corruption);
mpMREA->Skip(4);
mpArea->mExtraAreaDeps.push_back(AssetID);
}
@ -562,7 +562,7 @@ void CAreaLoader::Decompress()
{
// This function decompresses compressed clusters into a buffer.
// It should be called at the beginning of the first compressed cluster.
if (mVersion < eEchoes) return;
if (mVersion < EGame::Echoes) return;
// Decompress clusters
mpDecmpBuffer = new u8[mTotalDecmpSize];
@ -699,7 +699,7 @@ void CAreaLoader::SetUpObjects(CScriptLayer *pGenLayer)
}
// Remove "-component" garbage from MP1 instance names
if (mVersion <= ePrime)
if (mVersion <= EGame::Prime)
{
TString InstanceName = pInst->InstanceName();
@ -747,8 +747,8 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA, CResourceEntry *pEntry)
switch (Loader.mVersion)
{
case ePrimeDemo:
case ePrime:
case EGame::PrimeDemo:
case EGame::Prime:
Loader.ReadHeaderPrime();
Loader.ReadGeometryPrime();
Loader.ReadSCLYPrime();
@ -756,7 +756,7 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA, CResourceEntry *pEntry)
Loader.ReadLightsPrime();
Loader.ReadPATH();
break;
case eEchoesDemo:
case EGame::EchoesDemo:
Loader.ReadHeaderEchoes();
Loader.ReadGeometryPrime();
Loader.ReadSCLYPrime();
@ -766,7 +766,7 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA, CResourceEntry *pEntry)
Loader.ReadPTLA();
Loader.ReadEGMC();
break;
case eEchoes:
case EGame::Echoes:
Loader.ReadHeaderEchoes();
Loader.ReadGeometryPrime();
Loader.ReadSCLYEchoes();
@ -776,7 +776,7 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA, CResourceEntry *pEntry)
Loader.ReadPTLA();
Loader.ReadEGMC();
break;
case eCorruptionProto:
case EGame::CorruptionProto:
Loader.ReadHeaderCorruption();
Loader.ReadGeometryPrime();
Loader.ReadDependenciesCorruption();
@ -787,14 +787,14 @@ CGameArea* CAreaLoader::LoadMREA(IInputStream& MREA, CResourceEntry *pEntry)
Loader.ReadPTLA();
Loader.ReadEGMC();
break;
case eCorruption:
case eReturns:
case EGame::Corruption:
case EGame::DKCReturns:
Loader.ReadHeaderCorruption();
Loader.ReadGeometryCorruption();
Loader.ReadDependenciesCorruption();
Loader.ReadSCLYEchoes();
Loader.ReadCollision();
if (Loader.mVersion == eCorruption)
if (Loader.mVersion == EGame::Corruption)
{
Loader.ReadLightsCorruption();
Loader.ReadPATH();
@ -817,13 +817,13 @@ EGame CAreaLoader::GetFormatVersion(u32 Version)
{
switch (Version)
{
case 0xC: return ePrimeDemo;
case 0xF: return ePrime;
case 0x15: return eEchoesDemo;
case 0x19: return eEchoes;
case 0x1D: return eCorruptionProto;
case 0x1E: return eCorruption;
case 0x20: return eReturns;
default: return eUnknownGame;
case 0xC: return EGame::PrimeDemo;
case 0xF: return EGame::Prime;
case 0x15: return EGame::EchoesDemo;
case 0x19: return EGame::Echoes;
case 0x1D: return EGame::CorruptionProto;
case 0x1E: return EGame::Corruption;
case 0x20: return EGame::DKCReturns;
default: return EGame::Invalid;
}
}

View File

@ -5,11 +5,11 @@ CAudioGroup* CAudioGroupLoader::LoadAGSC(IInputStream& rAGSC, CResourceEntry *pE
// For now we only load sound define IDs and the group ID!
// Version check
u32 Check = rAGSC.PeekLong();
EGame Game = (Check == 0x1 ? eEchoes : ePrime);
EGame Game = (Check == 0x1 ? EGame::Echoes : EGame::Prime);
CAudioGroup *pOut = new CAudioGroup(pEntry);
// Read header, navigate to Proj chunk
if (Game == ePrime)
if (Game == EGame::Prime)
{
rAGSC.ReadString();
pOut->mGroupName = rAGSC.ReadString();
@ -38,7 +38,7 @@ CAudioGroup* CAudioGroupLoader::LoadAGSC(IInputStream& rAGSC, CResourceEntry *pE
rAGSC.Seek(0x14, SEEK_CUR);
u32 SfxTableStart = rAGSC.ReadLong();
if (Game == ePrime)
if (Game == EGame::Prime)
pOut->mGroupID = GroupID;
else
ASSERT(pOut->mGroupID == GroupID);

View File

@ -39,10 +39,10 @@ void CCollisionLoader::ParseOBBNode(IInputStream& rDCLN)
void CCollisionLoader::ReadPropertyFlags(IInputStream& rSrc)
{
CCollisionMaterial Material;
u64 RawFlags = (mVersion <= ePrime ? rSrc.ReadLong() : rSrc.ReadLongLong());
u64 RawFlags = (mVersion <= EGame::Prime ? rSrc.ReadLong() : rSrc.ReadLongLong());
Material.mRawFlags = RawFlags;
if (mVersion <= ePrime)
if (mVersion <= EGame::Prime)
{
if (RawFlags & 0x00000001) Material |= eCF_Unknown;
if (RawFlags & 0x00000002) Material |= eCF_Stone;
@ -71,7 +71,7 @@ void CCollisionLoader::ReadPropertyFlags(IInputStream& rSrc)
if (RawFlags & 0x80000000) Material |= eCF_Floor;
}
else if (mVersion <= eCorruption)
else if (mVersion <= EGame::Corruption)
{
if (RawFlags & 0x00000001) Material |= eCF_Unknown;
if (RawFlags & 0x00000002) Material |= eCF_Stone;
@ -105,7 +105,7 @@ void CCollisionLoader::ReadPropertyFlags(IInputStream& rSrc)
if (RawFlags & 0x0400000000000000) Material |= eCF_JumpNotAllowed;
}
else if (mVersion == eReturns)
else if (mVersion == EGame::DKCReturns)
{
if (RawFlags & 0x10000000) Material |= eCF_FlippedTri;
}
@ -158,7 +158,7 @@ void CCollisionLoader::LoadCollisionIndices(IInputStream &rFile, bool BuildAABox
}
// Echoes introduces a new data chunk; don't know what it is yet, skipping for now
if (mVersion >= eEchoes)
if (mVersion >= EGame::Echoes)
{
u32 UnknownCount = rFile.ReadLong();
rFile.Seek(UnknownCount * 2, SEEK_CUR);
@ -236,12 +236,12 @@ CCollisionMeshGroup* CCollisionLoader::LoadDCLN(IInputStream& rDCLN, CResourceEn
Loader.mpMesh = new CCollisionMesh;
Loader.mpMesh->mOctreeLoaded = false;
if (Loader.mVersion == eReturns)
if (Loader.mVersion == EGame::DKCReturns)
Loader.mpMesh->mAABox = CAABox(rDCLN);
// Read indices and return
rDCLN.Seek(0x4, SEEK_CUR);
Loader.LoadCollisionIndices(rDCLN, Loader.mVersion != eReturns);
Loader.LoadCollisionIndices(rDCLN, Loader.mVersion != EGame::DKCReturns);
Loader.mpGroup->AddMesh(Loader.mpMesh);
// Parse OBB tree
@ -254,10 +254,10 @@ EGame CCollisionLoader::GetFormatVersion(u32 Version)
{
switch (Version)
{
case 0x2: return ePrime;
case 0x3: return ePrime;
case 0x4: return eEchoes;
case 0x5: return eReturns;
default: return eUnknownGame;
case 0x2: return EGame::Prime;
case 0x3: return EGame::Prime;
case 0x4: return EGame::Echoes;
case 0x5: return EGame::DKCReturns;
default: return EGame::Invalid;
}
}

View File

@ -8,7 +8,7 @@ EGame CDependencyGroupLoader::VersionTest(IInputStream& rDGRP, u32 DepCount)
rDGRP.Seek(DepCount * 8, SEEK_CUR);
u32 Remaining = rDGRP.Size() - rDGRP.Tell();
EGame Game = eCorruptionProto;
EGame Game = EGame::CorruptionProto;
if (Remaining < 32)
{
@ -25,7 +25,7 @@ EGame CDependencyGroupLoader::VersionTest(IInputStream& rDGRP, u32 DepCount)
}
}
if (IsEOF) Game = ePrimeDemo;
if (IsEOF) Game = EGame::PrimeDemo;
}
rDGRP.Seek(Start, SEEK_SET);

View File

@ -13,12 +13,12 @@ CFont* CFontLoader::LoadFont(IInputStream& rFONT)
mpFont->mLineHeight = rFONT.ReadLong();
mpFont->mVerticalOffset = rFONT.ReadLong();
mpFont->mLineMargin = rFONT.ReadLong();
if (mVersion > ePrimeDemo) rFONT.Seek(0x4, SEEK_CUR);
if (mVersion > EGame::PrimeDemo) rFONT.Seek(0x4, SEEK_CUR);
rFONT.Seek(0x2, SEEK_CUR);
mpFont->mDefaultSize = rFONT.ReadLong();
mpFont->mFontName = rFONT.ReadString();
if (mVersion <= eEchoes) mpFont->mpFontTexture = gpResourceStore->LoadResource(rFONT.ReadLong(), eTexture);
if (mVersion <= EGame::Echoes) mpFont->mpFontTexture = gpResourceStore->LoadResource(rFONT.ReadLong(), eTexture);
else mpFont->mpFontTexture = gpResourceStore->LoadResource(rFONT.ReadLongLong(), eTexture);
mpFont->mTextureFormat = rFONT.ReadLong();
@ -39,7 +39,7 @@ CFont* CFontLoader::LoadFont(IInputStream& rFONT)
Glyph.TexCoords[2] = CVector2f(TexCoordL, TexCoordD); // Lower-left
Glyph.TexCoords[3] = CVector2f(TexCoordR, TexCoordD); // Lower-right
if (mVersion <= ePrime)
if (mVersion <= EGame::Prime)
{
Glyph.RGBAChannel = 0;
Glyph.LeftPadding = rFONT.ReadLong();
@ -50,7 +50,7 @@ CFont* CFontLoader::LoadFont(IInputStream& rFONT)
Glyph.BaseOffset = rFONT.ReadLong();
Glyph.KerningIndex = rFONT.ReadLong();
}
else if (mVersion >= eEchoes)
else if (mVersion >= EGame::Echoes)
{
Glyph.RGBAChannel = rFONT.ReadByte();
Glyph.LeftPadding = rFONT.ReadByte();
@ -92,7 +92,7 @@ CFont* CFontLoader::LoadFONT(IInputStream& rFONT, CResourceEntry *pEntry)
u32 FileVersion = rFONT.ReadLong();
EGame Version = GetFormatVersion(FileVersion);
if (Version == eUnknownGame)
if (Version == EGame::Invalid)
{
Log::FileError(rFONT.GetSourceString(), "Unsupported FONT version: " + TString::HexString(FileVersion, 0));
return nullptr;
@ -108,10 +108,10 @@ EGame CFontLoader::GetFormatVersion(u32 Version)
{
switch (Version)
{
case 1: return ePrimeDemo;
case 2: return ePrime;
case 4: return eEchoes;
case 5: return eCorruption;
default: return eUnknownGame;
case 1: return EGame::PrimeDemo;
case 2: return EGame::Prime;
case 4: return EGame::Echoes;
case 5: return EGame::Corruption;
default: return EGame::Invalid;
}
}

View File

@ -92,7 +92,7 @@ CMaterial* CMaterialLoader::ReadPrimeMaterial()
pMat->mVtxDesc = ConvertToVertexDescription( mpFile->ReadLong() );
// Unknowns
if (mVersion >= eEchoesDemo)
if (mVersion >= EGame::EchoesDemo)
{
pMat->mEchoesUnknownA = mpFile->ReadLong();
pMat->mEchoesUnknownB = mpFile->ReadLong();
@ -648,7 +648,7 @@ CMaterialSet* CMaterialLoader::LoadMaterialSet(IInputStream& rMat, EGame Version
Loader.mpFile = &rMat;
Loader.mVersion = Version;
if ((Version >= ePrimeDemo) && (Version <= eEchoes))
if ((Version >= EGame::PrimeDemo) && (Version <= EGame::Echoes))
Loader.ReadPrimeMatSet();
else
Loader.ReadCorruptionMatSet();

View File

@ -52,7 +52,7 @@ void CModelLoader::LoadAttribArrays(IInputStream& rModel)
if (mFlags & eShortNormals) // Shorts
{
mNormals.resize(mpSectionMgr->CurrentSectionSize() / 0x6);
float Divisor = (mVersion < eReturns) ? 32768.f : 16384.f;
float Divisor = (mVersion < EGame::DKCReturns) ? 32768.f : 16384.f;
for (u32 iVtx = 0; iVtx < mNormals.size(); iVtx++)
{
@ -93,7 +93,7 @@ void CModelLoader::LoadAttribArrays(IInputStream& rModel)
if (mFlags & eHasTex1)
{
mTex1.resize(mpSectionMgr->CurrentSectionSize() / 0x4);
float Divisor = (mVersion < eReturns) ? 32768.f : 8192.f;
float Divisor = (mVersion < EGame::DKCReturns) ? 32768.f : 8192.f;
for (u32 iVtx = 0; iVtx < mTex1.size(); iVtx++)
{
@ -122,7 +122,7 @@ SSurface* CModelLoader::LoadSurface(IInputStream& rModel)
SSurface *pSurf = new SSurface;
// Surface header
if (mVersion < eReturns)
if (mVersion < EGame::DKCReturns)
LoadSurfaceHeaderPrime(rModel, pSurf);
else
LoadSurfaceHeaderDKCR(rModel, pSurf);
@ -172,7 +172,7 @@ SSurface* CModelLoader::LoadSurface(IInputStream& rModel)
Vtx.Color[iClr] = mColors[rModel.ReadShort() & 0xFFFF];
// Tex Coords - these are done a bit differently in DKCR than in the Prime series
if (mVersion < eReturns)
if (mVersion < EGame::DKCReturns)
{
// Tex0
if (VtxDesc & eTex0)
@ -238,7 +238,7 @@ void CModelLoader::LoadSurfaceHeaderPrime(IInputStream& rModel, SSurface *pSurf)
u32 ExtraSize = rModel.ReadLong();
pSurf->ReflectionDirection = CVector3f(rModel);
if (mVersion >= eEchoesDemo)
if (mVersion >= EGame::EchoesDemo)
rModel.Seek(0x4, SEEK_CUR); // Skipping unknown values
bool HasAABox = (ExtraSize >= 0x18); // MREAs have a set of bounding box coordinates here.
@ -446,7 +446,7 @@ CModel* CModelLoader::LoadCMDL(IInputStream& rCMDL, CResourceEntry *pEntry)
// The rest is common to all CMDL versions
Loader.mVersion = GetFormatVersion(Version);
if (Loader.mVersion == eUnknownGame)
if (Loader.mVersion == EGame::Invalid)
{
Log::FileError(rCMDL.GetSourceString(), "Unsupported CMDL version: " + TString::HexString(Magic, 0));
return nullptr;
@ -464,13 +464,13 @@ CModel* CModelLoader::LoadCMDL(IInputStream& rCMDL, CResourceEntry *pEntry)
{
Loader.mMaterials[iSet] = CMaterialLoader::LoadMaterialSet(rCMDL, Loader.mVersion);
if (Loader.mVersion < eCorruptionProto)
if (Loader.mVersion < EGame::CorruptionProto)
Loader.mpSectionMgr->ToNextSection();
}
pModel->mMaterialSets = Loader.mMaterials;
pModel->mHasOwnMaterials = true;
if (Loader.mVersion >= eCorruptionProto) Loader.mpSectionMgr->ToNextSection();
if (Loader.mVersion >= EGame::CorruptionProto) Loader.mpSectionMgr->ToNextSection();
// Mesh
Loader.LoadAttribArrays(rCMDL);
@ -499,7 +499,7 @@ CModel* CModelLoader::LoadWorldModel(IInputStream& rMREA, CSectionMgrIn& rBlockM
Loader.mpSectionMgr = &rBlockMgr;
Loader.mVersion = Version;
Loader.mFlags = eShortNormals;
if (Version != eCorruptionProto) Loader.mFlags |= eHasTex1;
if (Version != EGame::CorruptionProto) Loader.mFlags |= eHasTex1;
Loader.mMaterials.resize(1);
Loader.mMaterials[0] = &rMatSet;
@ -534,7 +534,7 @@ CModel* CModelLoader::LoadCorruptionWorldModel(IInputStream& rMREA, CSectionMgrI
Loader.mFlags = eShortNormals;
Loader.mMaterials.resize(1);
Loader.mMaterials[0] = &rMatSet;
if (Version == eReturns) Loader.mFlags |= eHasTex1;
if (Version == EGame::DKCReturns) Loader.mFlags |= eHasTex1;
// Corruption/DKCR MREAs split the mesh header and surface offsets away from the actual geometry data so I need two section numbers to read it
rBlockMgr.ToSection(HeaderSecNum);
@ -638,11 +638,11 @@ EGame CModelLoader::GetFormatVersion(u32 Version)
{
switch (Version)
{
case 0x2: return ePrime;
case 0x3: return eEchoesDemo;
case 0x4: return eEchoes;
case 0x5: return eCorruption;
case 0xA: return eReturns;
default: return eUnknownGame;
case 0x2: return EGame::Prime;
case 0x3: return EGame::EchoesDemo;
case 0x4: return EGame::Echoes;
case 0x5: return EGame::Corruption;
case 0xA: return EGame::DKCReturns;
default: return EGame::Invalid;
}
}

View File

@ -101,11 +101,11 @@ public:
case eStateMachine:
// AFSM currently unsupported
if (pEntry->Game() <= eEchoes)
if (pEntry->Game() <= EGame::Echoes)
pRes = new CDependencyGroup(pEntry);
else if (pEntry->Game() <= eCorruption)
else if (pEntry->Game() <= EGame::Corruption)
pRes = CUnsupportedFormatLoader::LoadFSM2(rInput, pEntry);
else if (pEntry->Game() == eReturns)
else if (pEntry->Game() == EGame::DKCReturns)
pRes = CUnsupportedFormatLoader::LoadFSMC(rInput, pEntry);
break;

View File

@ -82,7 +82,7 @@ CScan* CScanLoader::LoadScanMP2(IInputStream& rSCAN)
}
// Load MP3 dependency list
if (mpScan->Game() == eCorruption)
if (mpScan->Game() == EGame::Corruption)
{
rSCAN.GoTo(InstanceEnd);
u32 NumDeps = rSCAN.ReadLong();
@ -275,7 +275,7 @@ CScan* CScanLoader::LoadSCAN(IInputStream& rSCAN, CResourceEntry *pEntry)
{
// The MP2 load function will check for MP3
CScanLoader Loader;
Loader.mVersion = eEchoes;
Loader.mVersion = EGame::Echoes;
Loader.mpEntry = pEntry;
if (Magic == 0x01000000) rSCAN.Seek(-4, SEEK_CUR); // The version number isn't present in the Echoes demo
return Loader.LoadScanMP2(rSCAN);
@ -295,7 +295,7 @@ CScan* CScanLoader::LoadSCAN(IInputStream& rSCAN, CResourceEntry *pEntry)
// MP1 SCAN - read the file!
CScanLoader Loader;
Loader.mVersion = ePrime;
Loader.mVersion = EGame::Prime;
Loader.mpScan = new CScan(pEntry);
Loader.mpEntry = pEntry;
return Loader.LoadScanMP1(rSCAN);

Some files were not shown because too many files have changed in this diff Show More