mirror of
https://github.com/libAthena/athena.git
synced 2025-07-06 13:16:18 +00:00
* 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.
|
// This file is part of libAthena.
|
||||||
//
|
//
|
||||||
// libAthena is free software: you can redistribute it and/or modify
|
// 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.
|
// This file is part of libAthena.
|
||||||
//
|
//
|
||||||
// libAthena is free software: you can redistribute it and/or modify
|
// 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.
|
// This file is part of libAthena.
|
||||||
//
|
//
|
||||||
// libAthena is free software: you can redistribute it and/or modify
|
// 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.
|
// This file is part of libAthena.
|
||||||
//
|
//
|
||||||
// libAthena is free software: you can redistribute it and/or modify
|
// libAthena is free software: you can redistribute it and/or modify
|
||||||
|
@ -166,6 +166,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isFile() const;
|
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:
|
protected:
|
||||||
private:
|
private:
|
||||||
atUint8 m_permissions;
|
atUint8 m_permissions;
|
||||||
@ -174,6 +188,8 @@ private:
|
|||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
int m_fileLen;
|
int m_fileLen;
|
||||||
atUint8* m_fileData;
|
atUint8* m_fileData;
|
||||||
|
WiiFile* m_parent;
|
||||||
|
std::vector<WiiFile*> m_children;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // zelda
|
} // zelda
|
||||||
|
@ -59,18 +59,20 @@ public:
|
|||||||
* \param file
|
* \param file
|
||||||
*/
|
*/
|
||||||
void addFile(const std::string& filename, WiiFile* file);
|
void addFile(const std::string& filename, WiiFile* file);
|
||||||
void setFiles(std::unordered_map<std::string, WiiFile*> files);
|
void setRoot(WiiFile* root);
|
||||||
/*!
|
/*!
|
||||||
* \brief file
|
* \brief file
|
||||||
* \param filename
|
* \param filename
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
WiiFile* file(const std::string& filename) const;
|
WiiFile* file(const std::string& filename);
|
||||||
|
|
||||||
|
atUint32 fileCount() const;
|
||||||
/*!
|
/*!
|
||||||
* \brief fileList
|
* \brief fileList
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
std::unordered_map<std::string, WiiFile*>& fileList();
|
WiiFile* root();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief setBanner
|
* \brief setBanner
|
||||||
@ -84,10 +86,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
WiiBanner* banner() const;
|
WiiBanner* banner() const;
|
||||||
|
|
||||||
|
std::vector<WiiFile*> allFiles() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::unordered_map<std::string, WiiFile*> m_files;
|
WiiFile* m_root;
|
||||||
WiiBanner* m_banner;
|
WiiBanner* m_banner;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -64,6 +64,7 @@ private:
|
|||||||
WiiFile* readFile();
|
WiiFile* readFile();
|
||||||
WiiImage* readImage(atUint32 width, atUint32 height);
|
WiiImage* readImage(atUint32 width, atUint32 height);
|
||||||
void readCerts(atUint32 totalSize);
|
void readCerts(atUint32 totalSize);
|
||||||
|
WiiFile* buildTree(std::vector<WiiFile*> files);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // io
|
} // io
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#ifndef ATHENA_NO_SAVES
|
#if !defined(ATHENA_NO_SAVES) && !defined(ATHENA_NO_ZQUEST)
|
||||||
// This file is part of libAthena.
|
// This file is part of libAthena.
|
||||||
//
|
//
|
||||||
// libAthena is free software: you can redistribute it and/or modify
|
// 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.
|
// This file is part of libAthena.
|
||||||
//
|
//
|
||||||
// libAthena is free software: you can redistribute it and/or modify
|
// 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.
|
// This file is part of libAthena.
|
||||||
//
|
//
|
||||||
// libAthena is free software: you can redistribute it and/or modify
|
// 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.
|
// This file is part of libAthena.
|
||||||
//
|
//
|
||||||
// libAthena is free software: you can redistribute it and/or modify
|
// 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/>
|
// along with libAthena. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
|
||||||
#include "Athena/WiiFile.hpp"
|
#include "Athena/WiiFile.hpp"
|
||||||
|
#include "Athena/InvalidOperationException.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace Athena
|
namespace Athena
|
||||||
{
|
{
|
||||||
@ -27,7 +28,8 @@ WiiFile::WiiFile() :
|
|||||||
m_type(WiiFile::File),
|
m_type(WiiFile::File),
|
||||||
m_filename(""),
|
m_filename(""),
|
||||||
m_fileLen(0),
|
m_fileLen(0),
|
||||||
m_fileData(NULL)
|
m_fileData(NULL),
|
||||||
|
m_parent(NULL)
|
||||||
{
|
{
|
||||||
//ctor
|
//ctor
|
||||||
}
|
}
|
||||||
@ -38,7 +40,8 @@ WiiFile::WiiFile(const std::string& filename) :
|
|||||||
m_type(WiiFile::File),
|
m_type(WiiFile::File),
|
||||||
m_filename(filename),
|
m_filename(filename),
|
||||||
m_fileLen(0),
|
m_fileLen(0),
|
||||||
m_fileData(NULL)
|
m_fileData(NULL),
|
||||||
|
m_parent(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,6 +59,9 @@ WiiFile::~WiiFile()
|
|||||||
{
|
{
|
||||||
if (m_fileData)
|
if (m_fileData)
|
||||||
delete[] 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);
|
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
|
} // zelda
|
||||||
#endif // ATHENA_NO_SAVES
|
#endif // ATHENA_NO_SAVES
|
||||||
|
@ -37,14 +37,15 @@ namespace Athena
|
|||||||
{
|
{
|
||||||
|
|
||||||
WiiSave::WiiSave()
|
WiiSave::WiiSave()
|
||||||
: m_banner(NULL)
|
: m_root(NULL),
|
||||||
|
m_banner(NULL)
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
WiiSave::~WiiSave()
|
WiiSave::~WiiSave()
|
||||||
{
|
{
|
||||||
m_files.clear();
|
delete m_root;
|
||||||
|
|
||||||
delete m_banner;
|
delete m_banner;
|
||||||
m_banner = NULL;
|
m_banner = NULL;
|
||||||
|
|
||||||
@ -52,48 +53,38 @@ WiiSave::~WiiSave()
|
|||||||
|
|
||||||
void WiiSave::addFile(const std::string& filepath, WiiFile* file)
|
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)
|
if (root != m_root)
|
||||||
return;
|
delete m_root;
|
||||||
|
|
||||||
std::cout << "Setting file map...";
|
m_root = root;
|
||||||
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();
|
WiiFile* WiiSave::file(const std::string& filepath)
|
||||||
}
|
|
||||||
|
|
||||||
m_files = files;
|
|
||||||
std::cout << "done" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
WiiFile* WiiSave::file(const std::string& filepath) const
|
|
||||||
{
|
{
|
||||||
std::unordered_map<std::string, WiiFile*>::const_iterator iter = m_files.begin();
|
if (filepath.empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
for (;iter != m_files.end(); ++iter)
|
std::string cleanPath(filepath);
|
||||||
{
|
|
||||||
if (iter->first == filepath)
|
while (cleanPath.at(0) == '/')
|
||||||
return (WiiFile*)iter->second;
|
cleanPath.erase(cleanPath.begin());
|
||||||
|
|
||||||
|
return m_root->child(cleanPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
atUint32 WiiSave::fileCount() const
|
||||||
|
{
|
||||||
|
return m_root->fileCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, WiiFile*>& WiiSave::fileList()
|
WiiFile* WiiSave::root()
|
||||||
{
|
{
|
||||||
return m_files;
|
return m_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WiiSave::setBanner(WiiBanner* banner)
|
void WiiSave::setBanner(WiiBanner* banner)
|
||||||
@ -106,6 +97,11 @@ WiiBanner* WiiSave::banner() const
|
|||||||
return m_banner;
|
return m_banner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<WiiFile *> WiiSave::allFiles() const
|
||||||
|
{
|
||||||
|
return m_root->allChildren();
|
||||||
|
}
|
||||||
|
|
||||||
} // zelda
|
} // zelda
|
||||||
|
|
||||||
#endif // ATHENA_NO_SAVES
|
#endif // ATHENA_NO_SAVES
|
||||||
|
@ -87,15 +87,15 @@ WiiSave* WiiSaveReader::readSave()
|
|||||||
base::seek(2);
|
base::seek(2);
|
||||||
base::seek(0x10);
|
base::seek(0x10);
|
||||||
|
|
||||||
std::unordered_map<std::string, WiiFile*> files;
|
std::vector<WiiFile*> files;
|
||||||
for (atUint32 i = 0; i < numFiles; ++i)
|
for (atUint32 i = 0; i < numFiles; ++i)
|
||||||
{
|
{
|
||||||
WiiFile* file = readFile();
|
WiiFile* file = readFile();
|
||||||
if (file)
|
if (file)
|
||||||
files["/"+file->filename()] = file;
|
files.push_back(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret->setFiles(files);
|
ret->setRoot(buildTree(files));
|
||||||
|
|
||||||
readCerts(totalSize);
|
readCerts(totalSize);
|
||||||
}
|
}
|
||||||
@ -313,6 +313,18 @@ void WiiSaveReader::readCerts(atUint32 totalSize)
|
|||||||
std::cout << "done" << std::endl;
|
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
|
} // io
|
||||||
} // zelda
|
} // zelda
|
||||||
#endif // ATHENA_NO_SAVES
|
#endif // ATHENA_NO_SAVES
|
||||||
|
@ -64,7 +64,7 @@ bool WiiSaveWriter::writeSave(WiiSave *save, atUint8 *macAddress, atUint32 ngId,
|
|||||||
base::writeUint32(0x70);
|
base::writeUint32(0x70);
|
||||||
base::writeUint32(0x426B0001);
|
base::writeUint32(0x426B0001);
|
||||||
base::writeUint32(ngId); // NG-ID
|
base::writeUint32(ngId); // NG-ID
|
||||||
base::writeUint32(save->fileList().size());
|
base::writeUint32(save->fileCount());
|
||||||
base::writeUint32(0); // Size of files;
|
base::writeUint32(0); // Size of files;
|
||||||
base::seek(8);
|
base::seek(8);
|
||||||
base::writeUint32(0); // totalSize
|
base::writeUint32(0); // totalSize
|
||||||
@ -74,9 +74,9 @@ bool WiiSaveWriter::writeSave(WiiSave *save, atUint8 *macAddress, atUint32 ngId,
|
|||||||
base::seek(2); // unknown;
|
base::seek(2); // unknown;
|
||||||
base::seek(0x10); // padding;
|
base::seek(0x10); // padding;
|
||||||
atUint32 totalSize = 0;
|
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();
|
int pos = base::position();
|
||||||
// Write size data
|
// Write size data
|
||||||
@ -167,8 +167,8 @@ atUint32 WiiSaveWriter::writeFile(WiiFile *file)
|
|||||||
|
|
||||||
atUint8 name[0x45];
|
atUint8 name[0x45];
|
||||||
utility::fillRandom(name, 0x45);
|
utility::fillRandom(name, 0x45);
|
||||||
memcpy(name, file->filename().c_str(), file->filename().size());
|
memcpy(name, file->fullpath().c_str(), file->fullpath().size());
|
||||||
name[file->filename().size()] = '\0';
|
name[file->fullpath().size()] = '\0';
|
||||||
base::writeBytes((atInt8*)name, 0x45);
|
base::writeBytes((atInt8*)name, 0x45);
|
||||||
atUint8 iv[16];
|
atUint8 iv[16];
|
||||||
utility::fillRandom(iv, 0x10);
|
utility::fillRandom(iv, 0x10);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user