began doExtract method

This commit is contained in:
Jack Andersen 2015-07-15 15:57:34 -10:00
parent a4d1fdbcfa
commit 07ae1e7379
31 changed files with 274 additions and 64 deletions

View File

@ -3,6 +3,7 @@ project(RetroCommon)
if (NOT TARGET NOD)
add_subdirectory(NODLib)
endif()
include_directories(${ATHENA_INCLUDE_DIR} ${LOG_VISOR_INCLUDE_DIR})
include_directories(${ATHENA_INCLUDE_DIR} ${LOG_VISOR_INCLUDE_DIR} ${ANGELSCRIPT_INCLUDE_DIR})
set(NOD_LIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/NODLib/include)
add_subdirectory(DataSpec)
add_subdirectory(Runtime)

View File

@ -3,6 +3,8 @@
namespace Retro
{
LogVisor::LogModule LogDNACommon("Retro::DNACommon");
const HECL::FourCC ENGL("ENGL");
const HECL::FourCC FREN("FREN");
const HECL::FourCC GERM("GERM");

View File

@ -3,11 +3,12 @@
#include <Athena/DNA.hpp>
#include "HECL/HECL.hpp"
#include "../Logging.hpp"
namespace Retro
{
extern LogVisor::LogModule LogDNACommon;
/* This comes up a great deal */
typedef Athena::io::DNA<Athena::BigEndian> BigDNA;
@ -151,7 +152,7 @@ public:
: m_buf(std::move(buf)), m_sz(sz), m_pos(pos)
{
if (m_pos >= m_sz)
LogModule.report(LogVisor::FatalError, "PAK stream cursor overrun");
LogDNACommon.report(LogVisor::FatalError, "PAK stream cursor overrun");
}
inline void seek(atInt64 pos, Athena::SeekOrigin origin)
{
@ -162,7 +163,7 @@ public:
else if (origin == Athena::End)
m_pos = m_sz + pos;
if (m_pos >= m_sz)
LogModule.report(LogVisor::FatalError, "PAK stream cursor overrun");
LogDNACommon.report(LogVisor::FatalError, "PAK stream cursor overrun");
}
inline atUint64 position() const {return m_pos;}
inline atUint64 length() const {return m_sz;}

View File

@ -5,13 +5,16 @@
namespace Retro
{
HECL::Database::ASListType<std::string> ASTYPE_STRGLanguage("STRG", "Language", "string");
std::unique_ptr<ISTRG> LoadSTRG(Athena::io::IStreamReader& reader)
{
reader.setEndian(Athena::BigEndian);
uint32_t magic = reader.readUint32();
if (magic != 0x87654321)
{
LogModule.report(LogVisor::Error, "invalid STRG magic");
LogDNACommon.report(LogVisor::Error, "invalid STRG magic");
return std::unique_ptr<ISTRG>();
}
@ -20,19 +23,19 @@ std::unique_ptr<ISTRG> LoadSTRG(Athena::io::IStreamReader& reader)
{
case 0:
{
DNAMP1::STRG* newStrg = new struct DNAMP1::STRG;
DNAMP1::STRG* newStrg = new DNAMP1::STRG;
newStrg->_read(reader);
return std::unique_ptr<ISTRG>(newStrg);
}
case 1:
{
DNAMP2::STRG* newStrg = new struct DNAMP2::STRG;
DNAMP2::STRG* newStrg = new DNAMP2::STRG;
newStrg->_read(reader);
return std::unique_ptr<ISTRG>(newStrg);
}
case 3:
{
DNAMP3::STRG* newStrg = new struct DNAMP3::STRG;
DNAMP3::STRG* newStrg = new DNAMP3::STRG;
newStrg->_read(reader);
return std::unique_ptr<ISTRG>(newStrg);
}

View File

@ -2,21 +2,31 @@
#define __COMMON_STRG_HPP__
#include <string>
#include <fstream>
#include <angelscript.h>
#include <HECL/HECL.hpp>
#include <HECL/Database.hpp>
#include "DNACommon.hpp"
#include "../Logging.hpp"
namespace Retro
{
struct ISTRG
{
virtual ~ISTRG() {}
virtual size_t count() const=0;
virtual std::string getUTF8(const FourCC& lang, size_t idx) const=0;
virtual std::wstring getUTF16(const FourCC& lang, size_t idx) const=0;
virtual HECL::SystemString getSystemString(const FourCC& lang, size_t idx) const=0;
virtual int32_t lookupIdx(const std::string& name) const=0;
virtual bool readAngelScript(const AngelScript::asIScriptModule& in)=0;
virtual void writeAngelScript(std::ofstream& out) const=0;
};
std::unique_ptr<ISTRG> LoadSTRG(Athena::io::IStreamReader& reader);
extern HECL::Database::ASListType<std::string> ASTYPE_STRGLanguage;
}
#endif // __COMMON_STRG_HPP__

View File

@ -2,6 +2,9 @@ make_dnalist(liblist
PAK
MLVL
STRG)
add_library(DNAMP1 ${liblist}
add_library(DNAMP1
DNAMP1.hpp
DNAMP1.cpp
${liblist}
PAK.cpp
STRG.cpp)

View File

@ -0,0 +1,9 @@
#include "DNAMP1.hpp"
namespace Retro
{
namespace DNAMP1
{
LogVisor::LogModule Log("Retro::DNAMP1");
}
}

View File

@ -0,0 +1,16 @@
#ifndef __DNAMP1_HPP__
#define __DNAMP1_HPP__
#include "../DNACommon/DNACommon.hpp"
namespace Retro
{
namespace DNAMP1
{
extern LogVisor::LogModule Log;
}
}
#endif // __DNAMP1_HPP__

View File

@ -1,5 +1,6 @@
#include <zlib.h>
#include <lzo/lzo1x.h>
#include "DNAMP1.hpp"
#include "PAK.hpp"
namespace Retro
@ -12,7 +13,7 @@ void PAK::read(Athena::io::IStreamReader& reader)
reader.setEndian(Athena::BigEndian);
atUint32 version = reader.readUint32();
if (version != 0x00030005)
LogModule.report(LogVisor::FatalError, "unexpected PAK magic");
Log.report(LogVisor::FatalError, "unexpected PAK magic");
reader.readUint32();
atUint32 nameCount = reader.readUint32();

View File

@ -4,7 +4,6 @@
#include <unordered_map>
#include <NOD/DiscBase.hpp>
#include "../Logging.hpp"
#include "../DNACommon/DNACommon.hpp"
namespace Retro

View File

@ -1,5 +1,5 @@
#include "STRG.hpp"
#include "../Logging.hpp"
#include "DNAMP1.hpp"
namespace Retro
{
@ -38,11 +38,11 @@ void STRG::read(Athena::io::IStreamReader& reader)
reader.setEndian(Athena::BigEndian);
atUint32 magic = reader.readUint32();
if (magic != 0x87654321)
LogModule.report(LogVisor::Error, "invalid STRG magic");
Log.report(LogVisor::Error, "invalid STRG magic");
atUint32 version = reader.readUint32();
if (version != 0)
LogModule.report(LogVisor::Error, "invalid STRG version");
Log.report(LogVisor::Error, "invalid STRG version");
_read(reader);
}
@ -106,5 +106,65 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
}
}
bool STRG::readAngelScript(const AngelScript::asIScriptModule& in)
{
std::wstring_convert<std::codecvt_utf8<wchar_t>> wconv;
/* Validate pass */
for (AngelScript::asUINT i=0 ; i<in.GetGlobalVarCount() ; ++i)
{
const char* name;
int typeId;
if (in.GetGlobalVar(i, &name, 0, &typeId) < 0)
continue;
if (typeId == ASTYPE_STRGLanguage.getTypeID())
{
if (strlen(name) != 4)
{
Log.report(LogVisor::Error, "STRG language string '%s' from %s must be exactly 4 characters", name, in.GetName());
return false;
}
}
}
/* Read pass */
for (AngelScript::asUINT i=0 ; i<in.GetGlobalVarCount() ; ++i)
{
const char* name;
int typeId;
if (in.GetGlobalVar(i, &name, 0, &typeId) < 0)
continue;
if (typeId == ASTYPE_STRGLanguage.getTypeID())
{
const std::vector<std::string*>& strsin = ASTYPE_STRGLanguage.vectorCast(in.GetAddressOfGlobalVar(i));
std::vector<std::wstring> strs;
for (const std::string* str : strsin)
strs.emplace_back(wconv.from_bytes(*str));
langs.emplace(std::make_pair(FourCC(name), strs));
}
}
return true;
}
void STRG::writeAngelScript(std::ofstream& out) const
{
std::wbuffer_convert<std::codecvt_utf8<wchar_t>> wconv(out.rdbuf());
std::wostream wout(&wconv);
for (const std::pair<FourCC, std::vector<std::wstring>>& lang : langs)
{
out << "STRG::Language " << lang.first.toString() << "({";
bool comma = false;
for (const std::wstring& str : lang.second)
{
out << (comma?", \"":"\"");
wout << str;
out << "\"";
comma = true;
}
out << "});\n";
}
}
}
}

View File

@ -21,7 +21,7 @@ struct STRG : ISTRG, BigDNA
inline size_t count() const
{
size_t retval = 0;
for (auto item : langs)
for (const auto& item : langs)
{
size_t sz = item.second.size();
if (sz > retval)
@ -54,6 +54,9 @@ struct STRG : ISTRG, BigDNA
#endif
return std::string();
}
bool readAngelScript(const AngelScript::asIScriptModule& in);
void writeAngelScript(std::ofstream& out) const;
};
}

View File

@ -1,5 +1,8 @@
make_dnalist(liblist
MLVL
STRG)
add_library(DNAMP2 ${liblist}
add_library(DNAMP2
DNAMP2.hpp
DNAMP2.cpp
${liblist}
STRG.cpp)

View File

@ -0,0 +1,9 @@
#include "DNAMP2.hpp"
namespace Retro
{
namespace DNAMP2
{
LogVisor::LogModule Log("Retro::DNAMP2");
}
}

View File

@ -0,0 +1,16 @@
#ifndef __DNAMP2_HPP__
#define __DNAMP2_HPP__
#include "../DNACommon/DNACommon.hpp"
namespace Retro
{
namespace DNAMP2
{
extern LogVisor::LogModule Log;
}
}
#endif // __DNAMP2_HPP__

View File

@ -1,5 +1,5 @@
#include "STRG.hpp"
#include "../Logging.hpp"
#include "DNAMP2.hpp"
namespace Retro
{
@ -53,11 +53,11 @@ void STRG::read(Athena::io::IStreamReader& reader)
reader.setEndian(Athena::BigEndian);
atUint32 magic = reader.readUint32();
if (magic != 0x87654321)
LogModule.report(LogVisor::Error, "invalid STRG magic");
Log.report(LogVisor::Error, "invalid STRG magic");
atUint32 version = reader.readUint32();
if (version != 1)
LogModule.report(LogVisor::Error, "invalid STRG version");
Log.report(LogVisor::Error, "invalid STRG version");
_read(reader);
}
@ -134,5 +134,13 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
}
}
bool STRG::readAngelScript(const AngelScript::asIScriptModule& in)
{
}
void STRG::writeAngelScript(std::ofstream& out) const
{
}
}
}

View File

@ -28,7 +28,7 @@ struct STRG : ISTRG, BigDNA
inline size_t count() const
{
size_t retval = 0;
for (auto item : langs)
for (const auto& item : langs)
{
size_t sz = item.second.size();
if (sz > retval)
@ -61,6 +61,9 @@ struct STRG : ISTRG, BigDNA
#endif
return std::string();
}
bool readAngelScript(const AngelScript::asIScriptModule& in);
void writeAngelScript(std::ofstream& out) const;
};
}

View File

@ -2,6 +2,9 @@ make_dnalist(liblist
PAK
MLVL
STRG)
add_library(DNAMP3 ${liblist}
add_library(DNAMP3
DNAMP3.hpp
DNAMP3.cpp
${liblist}
PAK.cpp
STRG.cpp)

View File

@ -0,0 +1,9 @@
#include "DNAMP3.hpp"
namespace Retro
{
namespace DNAMP3
{
LogVisor::LogModule Log("Retro::DNAMP3");
}
}

View File

@ -0,0 +1,16 @@
#ifndef __DNAMP3_HPP__
#define __DNAMP3_HPP__
#include "../DNACommon/DNACommon.hpp"
namespace Retro
{
namespace DNAMP3
{
extern LogVisor::LogModule Log;
}
}
#endif // __DNAMP3_HPP__

View File

@ -1,4 +1,5 @@
#include "PAK.hpp"
#include "DNAMP3.hpp"
namespace Retro
{
@ -12,7 +13,7 @@ void PAK::read(Athena::io::IStreamReader& reader)
reader.setEndian(Athena::BigEndian);
m_header.read(reader);
if (m_header.version != 2)
LogModule.report(LogVisor::FatalError, "unexpected PAK magic");
Log.report(LogVisor::FatalError, "unexpected PAK magic");
reader.seek(8, Athena::Current);
atUint32 strgSz = reader.readUint32();
@ -115,7 +116,7 @@ std::unique_ptr<atUint8[]> PAK::Entry::getBuffer(const NOD::DiscBase::IPartition
strm->read(&head, 8);
if (head.magic != CMPD)
{
LogModule.report(LogVisor::Error, "invalid CMPD block");
Log.report(LogVisor::Error, "invalid CMPD block");
return std::unique_ptr<atUint8[]>();
}
head.blockCount = HECL::SBig(head.blockCount);

View File

@ -6,7 +6,6 @@
#include <lzo/lzo1x.h>
#include <NOD/DiscBase.hpp>
#include "../DNACommon/DNACommon.hpp"
#include "../Logging.hpp"
namespace Retro
{

View File

@ -1,5 +1,5 @@
#include "STRG.hpp"
#include "../Logging.hpp"
#include "DNAMP3.hpp"
namespace Retro
{
@ -67,14 +67,14 @@ void STRG::read(Athena::io::IStreamReader& reader)
atUint32 magic = reader.readUint32();
if (magic != 0x87654321)
{
LogModule.report(LogVisor::Error, "invalid STRG magic");
Log.report(LogVisor::Error, "invalid STRG magic");
return;
}
atUint32 version = reader.readUint32();
if (version != 3)
{
LogModule.report(LogVisor::Error, "invalid STRG version");
Log.report(LogVisor::Error, "invalid STRG version");
return;
}
@ -142,5 +142,13 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
}
}
bool STRG::readAngelScript(const AngelScript::asIScriptModule& in)
{
}
void STRG::writeAngelScript(std::ofstream& out) const
{
}
}
}

View File

@ -28,7 +28,7 @@ struct STRG : ISTRG, BigDNA
inline size_t count() const
{
size_t retval = 0;
for (auto item : langs)
for (const auto& item : langs)
{
size_t sz = item.second.size();
if (sz > retval)
@ -61,6 +61,9 @@ struct STRG : ISTRG, BigDNA
#endif
return std::string();
}
bool readAngelScript(const AngelScript::asIScriptModule& in);
void writeAngelScript(std::ofstream& out) const;
};
}

View File

@ -1,11 +0,0 @@
#ifndef __RETRO_DATASPEC_LOGGING__
#define __RETRO_DATASPEC_LOGGING__
#include <LogVisor/LogVisor.hpp>
namespace Retro
{
extern LogVisor::LogModule LogModule;
}
#endif // __RETRO_DATASPEC_LOGGING__

View File

@ -3,27 +3,22 @@
namespace Retro
{
LogVisor::LogModule LogModule("RetroDataSpec");
bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps)
{
bool isWii;
std::unique_ptr<NOD::DiscBase> disc = NOD::OpenDiscFromImage(info.srcpath.c_str(), isWii);
if (!disc)
m_disc = NOD::OpenDiscFromImage(info.srcpath.c_str(), isWii);
if (!m_disc)
return false;
const char* gameID = disc->getHeader().gameID;
const char* gameID = m_disc->getHeader().gameID;
bool standalone = true;
if (isWii)
{
if (!memcmp(gameID, "R3M", 3))
standalone = false;
}
if (isWii && !memcmp(gameID, "R3M", 3))
standalone = false;
if (standalone && !checkStandaloneID(gameID))
return false;
char region = disc->getHeader().gameID[3];
char region = m_disc->getHeader().gameID[3];
static const HECL::SystemString regNONE = _S("");
static const HECL::SystemString regE = _S("NTSC");
static const HECL::SystemString regJ = _S("NTSC-J");
@ -43,13 +38,14 @@ bool SpecBase::canExtract(const ExtractPassInfo& info, std::vector<ExtractReport
}
if (standalone)
return checkFromStandaloneDisc(*disc.get(), *regstr, info.extractArgs, reps);
return checkFromStandaloneDisc(*m_disc.get(), *regstr, info.extractArgs, reps);
else
return checkFromTrilogyDisc(*disc.get(), *regstr, info.extractArgs, reps);
return checkFromTrilogyDisc(*m_disc.get(), *regstr, info.extractArgs, reps);
}
void SpecBase::doExtract(const HECL::Database::Project& project, const ExtractPassInfo& info)
void SpecBase::doExtract(const HECL::Database::Project& project, const ExtractPassInfo&)
{
extractFromDisc(*m_disc.get(), project);
}
bool SpecBase::canCook(const HECL::Database::Project& project, const CookTaskInfo& info)

View File

@ -9,8 +9,6 @@
namespace Retro
{
extern LogVisor::LogModule LogModule;
struct SpecBase : HECL::Database::IDataSpec
{
bool canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps);
@ -33,7 +31,7 @@ struct SpecBase : HECL::Database::IDataSpec
const HECL::SystemString& regstr,
const std::vector<HECL::SystemString>& args,
std::vector<ExtractReport>& reps)=0;
virtual bool extractFromDisc()=0;
virtual bool extractFromDisc(NOD::DiscBase& disc, const HECL::Database::Project& project)=0;
virtual bool checkFromProject(HECL::Database::Project& proj)=0;
virtual bool readFromProject(HECL::Database::Project& proj)=0;
@ -49,6 +47,9 @@ struct SpecBase : HECL::Database::IDataSpec
virtual bool visitAreas(std::function<bool(const IAreaSpec&)>)=0;
};
virtual bool visitLevels(std::function<bool(const ILevelSpec&)>)=0;
private:
std::unique_ptr<NOD::DiscBase> m_disc;
};
}

View File

@ -1,4 +1,5 @@
#include <utility>
#include <stdio.h>
#define NOD_ATHENA 1
#include "SpecBase.hpp"
@ -9,6 +10,8 @@
namespace Retro
{
static LogVisor::LogModule Log("Retro::SpecMP1");
struct SpecMP1 : SpecBase
{
bool checkStandaloneID(const char* id) const
@ -95,7 +98,7 @@ struct SpecMP1 : SpecBase
m_orderedPaks[dpak.node.getName()] = &dpak;
/* Assemble extract report */
for (std::pair<std::string, DiscPAK*> item : m_orderedPaks)
for (const std::pair<std::string, DiscPAK*>& item : m_orderedPaks)
{
rep.childOpts.emplace_back();
ExtractReport& childRep = rep.childOpts.back();
@ -205,8 +208,36 @@ struct SpecMP1 : SpecBase
return true;
}
bool extractFromDisc()
bool extractFromDisc(NOD::DiscBase& disc, const HECL::Database::Project& project)
{
HECL::ProjectPath mp1Path(project.getProjectRootPath(), "MP1");
for (const DiscPAK& pak : m_paks)
{
const std::string& name = pak.node.getName();
std::string::const_iterator extit = name.end() - 4;
std::string baseName(name.begin(), extit);
HECL::ProjectPath pakPath(mp1Path, baseName);
for (const std::pair<UniqueID32, DNAMP1::PAK::Entry*>& item : pak.pak.m_idMap)
{
if (item.second->type == STRG)
{
DNAMP1::STRG strg;
PAKEntryReadStream strgIn = item.second->beginReadStream(pak.node);
strg.read(strgIn);
HECL::SystemChar strgPath[1024];
HECL::SNPrintf(strgPath, 1024, _S("%s/%08X.strg"), pakPath.getAbsolutePath().c_str(), item.second->id.toUint32());
std::ofstream strgOut(strgPath);
strg.writeAngelScript(strgOut);
}
}
}
return true;
}
bool checkFromProject(HECL::Database::Project& proj)

View File

@ -9,6 +9,8 @@
namespace Retro
{
static LogVisor::LogModule Log("Retro::SpecMP2");
struct SpecMP2 : SpecBase
{
bool checkStandaloneID(const char* id) const
@ -95,7 +97,7 @@ struct SpecMP2 : SpecBase
m_orderedPaks[dpak.node.getName()] = &dpak;
/* Assemble extract report */
for (std::pair<std::string, DiscPAK*> item : m_orderedPaks)
for (const std::pair<std::string, DiscPAK*>& item : m_orderedPaks)
{
rep.childOpts.emplace_back();
ExtractReport& childRep = rep.childOpts.back();
@ -205,7 +207,8 @@ struct SpecMP2 : SpecBase
return true;
}
bool extractFromDisc()
bool extractFromDisc(NOD::DiscBase& disc, const HECL::Database::Project& project)
{
}

View File

@ -10,6 +10,8 @@
namespace Retro
{
static LogVisor::LogModule Log("Retro::SpecMP3");
struct SpecMP3 : SpecBase
{
bool checkStandaloneID(const char* id) const
@ -96,7 +98,7 @@ struct SpecMP3 : SpecBase
m_orderedPaks[dpak.node.getName()] = &dpak;
/* Assemble extract report */
for (std::pair<std::string, DiscPAK*> item : m_orderedPaks)
for (const std::pair<std::string, DiscPAK*>& item : m_orderedPaks)
{
rep.childOpts.emplace_back();
ExtractReport& childRep = rep.childOpts.back();
@ -105,6 +107,7 @@ struct SpecMP3 : SpecBase
continue;
else if (!item.first.compare("Metroid6.pak"))
{
/* Phaaze doesn't have a world name D: */
childRep.desc = _S("Phaaze");
continue;
}
@ -219,7 +222,8 @@ struct SpecMP3 : SpecBase
return true;
}
bool extractFromDisc()
bool extractFromDisc(NOD::DiscBase& disc, const HECL::Database::Project& project)
{
}

2
NODLib

@ -1 +1 @@
Subproject commit 993b30e4a5657f8bfb7bd1adedb82244219b66eb
Subproject commit 7114f079a45788f5f9ddd6bfca8fa8901d939f9a