mirror of https://github.com/libAthena/athena.git
* Added proper tree generation for WiiSave
This commit is contained in:
parent
6187eb3f77
commit
f92811004f
|
@ -1,4 +1,4 @@
|
|||
#ifndef ATHENA_NO_SAVES
|
||||
#if !defined(ATHENA_NO_SAVES) && !defined(ATHENA_NO_ZQUEST)
|
||||
// This file is part of libAthena.
|
||||
//
|
||||
// libAthena is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef ATHENA_NO_SAVES
|
||||
#if !defined(ATHENA_NO_SAVES) && !defined(ATHENA_NO_ZQUEST)
|
||||
// This file is part of libAthena.
|
||||
//
|
||||
// libAthena is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef ATHENA_NO_SAVES
|
||||
#if !defined(ATHENA_NO_SAVES) && !defined(ATHENA_NO_ZQUEST)
|
||||
// This file is part of libAthena.
|
||||
//
|
||||
// libAthena is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef ATHENA_NO_SAVES
|
||||
#if !defined(ATHENA_NO_SAVES) && !defined(ATHENA_NO_ZQUEST)
|
||||
// This file is part of libAthena.
|
||||
//
|
||||
// libAthena is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -166,6 +166,20 @@ public:
|
|||
*/
|
||||
bool isFile() const;
|
||||
|
||||
void addChild(WiiFile* file);
|
||||
std::vector<WiiFile*> children();
|
||||
WiiFile* child(const std::string& name);
|
||||
void removeChild(const std::string& name);
|
||||
void removeChild(WiiFile* file);
|
||||
|
||||
WiiFile* parent();
|
||||
void setParent(WiiFile *parent);
|
||||
|
||||
atUint32 fileCount();
|
||||
|
||||
std::vector<WiiFile*> allChildren();
|
||||
|
||||
std::string fullpath();
|
||||
protected:
|
||||
private:
|
||||
atUint8 m_permissions;
|
||||
|
@ -174,6 +188,8 @@ private:
|
|||
std::string m_filename;
|
||||
int m_fileLen;
|
||||
atUint8* m_fileData;
|
||||
WiiFile* m_parent;
|
||||
std::vector<WiiFile*> m_children;
|
||||
};
|
||||
|
||||
} // zelda
|
||||
|
|
|
@ -59,18 +59,20 @@ public:
|
|||
* \param file
|
||||
*/
|
||||
void addFile(const std::string& filename, WiiFile* file);
|
||||
void setFiles(std::unordered_map<std::string, WiiFile*> files);
|
||||
void setRoot(WiiFile* root);
|
||||
/*!
|
||||
* \brief file
|
||||
* \param filename
|
||||
* \return
|
||||
*/
|
||||
WiiFile* file(const std::string& filename) const;
|
||||
WiiFile* file(const std::string& filename);
|
||||
|
||||
atUint32 fileCount() const;
|
||||
/*!
|
||||
* \brief fileList
|
||||
* \return
|
||||
*/
|
||||
std::unordered_map<std::string, WiiFile*>& fileList();
|
||||
WiiFile* root();
|
||||
|
||||
/*!
|
||||
* \brief setBanner
|
||||
|
@ -84,10 +86,12 @@ public:
|
|||
*/
|
||||
WiiBanner* banner() const;
|
||||
|
||||
std::vector<WiiFile*> allFiles() const;
|
||||
|
||||
protected:
|
||||
private:
|
||||
|
||||
std::unordered_map<std::string, WiiFile*> m_files;
|
||||
WiiFile* m_root;
|
||||
WiiBanner* m_banner;
|
||||
|
||||
};
|
||||
|
|
|
@ -64,6 +64,7 @@ private:
|
|||
WiiFile* readFile();
|
||||
WiiImage* readImage(atUint32 width, atUint32 height);
|
||||
void readCerts(atUint32 totalSize);
|
||||
WiiFile* buildTree(std::vector<WiiFile*> files);
|
||||
};
|
||||
|
||||
} // io
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef ATHENA_NO_SAVES
|
||||
#if !defined(ATHENA_NO_SAVES) && !defined(ATHENA_NO_ZQUEST)
|
||||
// This file is part of libAthena.
|
||||
//
|
||||
// libAthena is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef ATHENA_NO_SAVES
|
||||
#if !defined(ATHENA_NO_SAVES) && !defined(ATHENA_NO_ZQUEST)
|
||||
// This file is part of libAthena.
|
||||
//
|
||||
// libAthena is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef ATHENA_NO_SAVES
|
||||
#if !defined(ATHENA_NO_SAVES) && !defined(ATHENA_NO_ZQUEST)
|
||||
// This file is part of libAthena.
|
||||
//
|
||||
// libAthena is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef ATHENA_NO_SAVES
|
||||
#if !defined(ATHENA_NO_SAVES) && !defined(ATHENA_NO_ZQUEST)
|
||||
// This file is part of libAthena.
|
||||
//
|
||||
// libAthena is free software: you can redistribute it and/or modify
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
#include "Athena/WiiFile.hpp"
|
||||
|
||||
#include "Athena/InvalidOperationException.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace Athena
|
||||
{
|
||||
|
@ -27,7 +28,8 @@ WiiFile::WiiFile() :
|
|||
m_type(WiiFile::File),
|
||||
m_filename(""),
|
||||
m_fileLen(0),
|
||||
m_fileData(NULL)
|
||||
m_fileData(NULL),
|
||||
m_parent(NULL)
|
||||
{
|
||||
//ctor
|
||||
}
|
||||
|
@ -38,7 +40,8 @@ WiiFile::WiiFile(const std::string& filename) :
|
|||
m_type(WiiFile::File),
|
||||
m_filename(filename),
|
||||
m_fileLen(0),
|
||||
m_fileData(NULL)
|
||||
m_fileData(NULL),
|
||||
m_parent(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -56,6 +59,9 @@ WiiFile::~WiiFile()
|
|||
{
|
||||
if (m_fileData)
|
||||
delete[] m_fileData;
|
||||
|
||||
for (WiiFile* child : m_children)
|
||||
delete child;
|
||||
}
|
||||
|
||||
|
||||
|
@ -134,5 +140,144 @@ bool WiiFile::isFile() const
|
|||
return (m_type == WiiFile::File);
|
||||
}
|
||||
|
||||
void WiiFile::addChild(WiiFile *file)
|
||||
{
|
||||
if (!isDirectory())
|
||||
THROW_INVALID_OPERATION_EXCEPTION("%s is not a directory", filename().c_str());
|
||||
|
||||
if (std::find(m_children.begin(), m_children.end(), file) != m_children.end())
|
||||
return;
|
||||
|
||||
// Lets figure out it's place
|
||||
std::string tmpName(file->filename());
|
||||
// Since we only support *NIX paths this is simple
|
||||
atUint32 depth = Athena::utility::countChar(tmpName, '/');
|
||||
bool owned = false;
|
||||
while ((depth--) > 0)
|
||||
{
|
||||
// add them from the beginning of the path up
|
||||
tmpName = tmpName.substr(0, tmpName.find('/'));
|
||||
for (int i = 0; i < m_children.size(); i++)
|
||||
{
|
||||
if (!m_children[i]->filename().compare(tmpName))
|
||||
{
|
||||
std::string newName = file->filename();
|
||||
newName = newName.substr(newName.rfind("/") + 1, newName.size() - newName.rfind("/"));
|
||||
file->setFilename(newName);
|
||||
m_children[i]->addChild(file);
|
||||
owned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!owned)
|
||||
{
|
||||
m_children.push_back(file);
|
||||
file->setParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
WiiFile* WiiFile::child(const std::string &name)
|
||||
{
|
||||
std::vector<WiiFile*>::iterator iter = std::find_if(m_children.begin(), m_children.end(),
|
||||
[&name](WiiFile* f) { return !f->filename().compare(name); });
|
||||
if (iter != m_children.end())
|
||||
return *iter;
|
||||
|
||||
std::string tmpName(name);
|
||||
tmpName = tmpName.substr(tmpName.rfind('/')+1, tmpName.size() - tmpName.rfind('/'));
|
||||
|
||||
for (WiiFile* f : m_children)
|
||||
{
|
||||
if (f->isFile())
|
||||
continue;
|
||||
|
||||
WiiFile* ret = f->child(tmpName);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void WiiFile::removeChild(WiiFile* file)
|
||||
{
|
||||
std::vector<WiiFile*>::iterator iter = std::find(m_children.begin(), m_children.end(), file);
|
||||
|
||||
if (iter == m_children.end())
|
||||
return;
|
||||
|
||||
m_children.erase(iter);
|
||||
}
|
||||
|
||||
WiiFile* WiiFile::parent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
void WiiFile::setParent(WiiFile* parent)
|
||||
{
|
||||
if (m_parent)
|
||||
m_parent->removeChild(this);
|
||||
|
||||
m_parent = parent;
|
||||
m_parent->addChild(this);
|
||||
}
|
||||
|
||||
atUint32 WiiFile::fileCount()
|
||||
{
|
||||
int ret = m_children.size();
|
||||
|
||||
for (WiiFile* f : m_children)
|
||||
{
|
||||
if (f->isFile())
|
||||
continue;
|
||||
|
||||
ret += f->fileCount();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<WiiFile *> WiiFile::allChildren()
|
||||
{
|
||||
std::vector<WiiFile*> ret;
|
||||
if (m_children.size() == 0)
|
||||
return ret;
|
||||
// Add our children first
|
||||
for (WiiFile* f : m_children)
|
||||
ret.push_back(f);
|
||||
|
||||
// now lets add our children's children
|
||||
for (WiiFile* f : m_children)
|
||||
{
|
||||
if (f->isFile())
|
||||
continue;
|
||||
|
||||
std::vector<WiiFile*> tmp = f->allChildren();
|
||||
|
||||
if (tmp.size() == 0)
|
||||
continue;
|
||||
|
||||
ret.insert(ret.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string WiiFile::fullpath()
|
||||
{
|
||||
std::string ret;
|
||||
if (m_parent)
|
||||
ret = m_parent->filename() + "/";
|
||||
|
||||
ret = ret + filename();
|
||||
|
||||
while (ret.at(0) == '/')
|
||||
ret.erase(ret.begin());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // zelda
|
||||
#endif // ATHENA_NO_SAVES
|
||||
|
|
|
@ -37,14 +37,15 @@ namespace Athena
|
|||
{
|
||||
|
||||
WiiSave::WiiSave()
|
||||
: m_banner(NULL)
|
||||
: m_root(NULL),
|
||||
m_banner(NULL)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
WiiSave::~WiiSave()
|
||||
{
|
||||
m_files.clear();
|
||||
|
||||
delete m_root;
|
||||
delete m_banner;
|
||||
m_banner = NULL;
|
||||
|
||||
|
@ -52,48 +53,38 @@ WiiSave::~WiiSave()
|
|||
|
||||
void WiiSave::addFile(const std::string& filepath, WiiFile* file)
|
||||
{
|
||||
m_files[filepath] = file;
|
||||
m_root->addChild(file);
|
||||
}
|
||||
|
||||
void WiiSave::setFiles(std::unordered_map<std::string, WiiFile*> files)
|
||||
void WiiSave::setRoot(WiiFile* root)
|
||||
{
|
||||
if (files.size() <= 0)
|
||||
return;
|
||||
if (root != m_root)
|
||||
delete m_root;
|
||||
|
||||
std::cout << "Setting file map...";
|
||||
if (m_files.size() > 0)
|
||||
{
|
||||
std::unordered_map<std::string, WiiFile*>::iterator iter = m_files.begin();
|
||||
|
||||
for (;iter != m_files.end(); ++iter)
|
||||
{
|
||||
if (iter->second)
|
||||
delete iter->second;
|
||||
}
|
||||
|
||||
m_files.clear();
|
||||
}
|
||||
|
||||
m_files = files;
|
||||
std::cout << "done" << std::endl;
|
||||
m_root = root;
|
||||
}
|
||||
|
||||
WiiFile* WiiSave::file(const std::string& filepath) const
|
||||
WiiFile* WiiSave::file(const std::string& filepath)
|
||||
{
|
||||
std::unordered_map<std::string, WiiFile*>::const_iterator iter = m_files.begin();
|
||||
if (filepath.empty())
|
||||
return nullptr;
|
||||
|
||||
for (;iter != m_files.end(); ++iter)
|
||||
{
|
||||
if (iter->first == filepath)
|
||||
return (WiiFile*)iter->second;
|
||||
}
|
||||
std::string cleanPath(filepath);
|
||||
|
||||
return NULL;
|
||||
while (cleanPath.at(0) == '/')
|
||||
cleanPath.erase(cleanPath.begin());
|
||||
|
||||
return m_root->child(cleanPath);
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, WiiFile*>& WiiSave::fileList()
|
||||
atUint32 WiiSave::fileCount() const
|
||||
{
|
||||
return m_files;
|
||||
return m_root->fileCount();
|
||||
}
|
||||
|
||||
WiiFile* WiiSave::root()
|
||||
{
|
||||
return m_root;
|
||||
}
|
||||
|
||||
void WiiSave::setBanner(WiiBanner* banner)
|
||||
|
@ -106,6 +97,11 @@ WiiBanner* WiiSave::banner() const
|
|||
return m_banner;
|
||||
}
|
||||
|
||||
std::vector<WiiFile *> WiiSave::allFiles() const
|
||||
{
|
||||
return m_root->allChildren();
|
||||
}
|
||||
|
||||
} // zelda
|
||||
|
||||
#endif // ATHENA_NO_SAVES
|
||||
|
|
|
@ -87,15 +87,15 @@ WiiSave* WiiSaveReader::readSave()
|
|||
base::seek(2);
|
||||
base::seek(0x10);
|
||||
|
||||
std::unordered_map<std::string, WiiFile*> files;
|
||||
std::vector<WiiFile*> files;
|
||||
for (atUint32 i = 0; i < numFiles; ++i)
|
||||
{
|
||||
WiiFile* file = readFile();
|
||||
if (file)
|
||||
files["/"+file->filename()] = file;
|
||||
files.push_back(file);
|
||||
}
|
||||
|
||||
ret->setFiles(files);
|
||||
ret->setRoot(buildTree(files));
|
||||
|
||||
readCerts(totalSize);
|
||||
}
|
||||
|
@ -313,6 +313,18 @@ void WiiSaveReader::readCerts(atUint32 totalSize)
|
|||
std::cout << "done" << std::endl;
|
||||
}
|
||||
|
||||
WiiFile* WiiSaveReader::buildTree(std::vector<WiiFile*> files)
|
||||
{
|
||||
// This is simply a virtual root that will contain all the other nodes
|
||||
WiiFile* root = new WiiFile("/");
|
||||
root->setType(WiiFile::Directory);
|
||||
|
||||
for (WiiFile* f : files)
|
||||
root->addChild(f);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
} // io
|
||||
} // zelda
|
||||
#endif // ATHENA_NO_SAVES
|
||||
|
|
|
@ -64,7 +64,7 @@ bool WiiSaveWriter::writeSave(WiiSave *save, atUint8 *macAddress, atUint32 ngId,
|
|||
base::writeUint32(0x70);
|
||||
base::writeUint32(0x426B0001);
|
||||
base::writeUint32(ngId); // NG-ID
|
||||
base::writeUint32(save->fileList().size());
|
||||
base::writeUint32(save->fileCount());
|
||||
base::writeUint32(0); // Size of files;
|
||||
base::seek(8);
|
||||
base::writeUint32(0); // totalSize
|
||||
|
@ -74,9 +74,9 @@ bool WiiSaveWriter::writeSave(WiiSave *save, atUint8 *macAddress, atUint32 ngId,
|
|||
base::seek(2); // unknown;
|
||||
base::seek(0x10); // padding;
|
||||
atUint32 totalSize = 0;
|
||||
for (std::unordered_map<std::string, WiiFile*>::const_iterator iter = save->fileList().begin(); iter != save->fileList().end(); ++iter)
|
||||
for (WiiFile* file : save->allFiles())
|
||||
{
|
||||
totalSize += writeFile(iter->second);
|
||||
totalSize += writeFile(file);
|
||||
}
|
||||
int pos = base::position();
|
||||
// Write size data
|
||||
|
@ -167,8 +167,8 @@ atUint32 WiiSaveWriter::writeFile(WiiFile *file)
|
|||
|
||||
atUint8 name[0x45];
|
||||
utility::fillRandom(name, 0x45);
|
||||
memcpy(name, file->filename().c_str(), file->filename().size());
|
||||
name[file->filename().size()] = '\0';
|
||||
memcpy(name, file->fullpath().c_str(), file->fullpath().size());
|
||||
name[file->fullpath().size()] = '\0';
|
||||
base::writeBytes((atInt8*)name, 0x45);
|
||||
atUint8 iv[16];
|
||||
utility::fillRandom(iv, 0x10);
|
||||
|
|
Loading…
Reference in New Issue