summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2010-10-14 03:15:41 +0200
committerTreeki <treeki@gmail.com>2010-10-14 03:15:41 +0200
commitfdf8cfec2b795393d7ee901abaf747575067068b (patch)
tree1eb3a65765c1c43c4ea91530462cd15d54f995d1
parent7213ca723a65dff8ebb0c6c08669695217e60453 (diff)
downloadLayoutStudio-fdf8cfec2b795393d7ee901abaf747575067068b.tar.gz
LayoutStudio-fdf8cfec2b795393d7ee901abaf747575067068b.zip
bugfixes; working U8 archive support for reading/writing
-rw-r--r--LayoutStudio.pro8
-rw-r--r--README.markdown2
-rw-r--r--lyt/archivepackage.cpp168
-rw-r--r--lyt/archivepackage.h62
-rw-r--r--lyt/directorypackage.cpp2
-rw-r--r--lyt/packagebase.cpp3
-rw-r--r--lyt/packagebase.h1
-rw-r--r--main.cpp19
-rw-r--r--wii/archiveu8.cpp243
-rw-r--r--wii/archiveu8.h24
-rw-r--r--wii/common.h13
-rw-r--r--wii/filesystem.cpp13
-rw-r--r--wii/stringtablebuilder.cpp25
-rw-r--r--wii/stringtablebuilder.h22
14 files changed, 594 insertions, 11 deletions
diff --git a/LayoutStudio.pro b/LayoutStudio.pro
index 9c5df61..0b6a395 100644
--- a/LayoutStudio.pro
+++ b/LayoutStudio.pro
@@ -30,7 +30,9 @@ SOURCES += main.cpp \
lyt/materials/blendmode.cpp \
wii/common.cpp \
wii/archiveu8.cpp \
- wii/filesystem.cpp
+ wii/filesystem.cpp \
+ lyt/archivepackage.cpp \
+ wii/stringtablebuilder.cpp
HEADERS += lsmainwindow.h \
lsglobals.h \
lyt/packagebase.h \
@@ -57,7 +59,9 @@ HEADERS += lsmainwindow.h \
lyt/materials/blendmode.h \
wii/archiveu8.h \
wii/common.h \
- wii/filesystem.h
+ wii/filesystem.h \
+ lyt/archivepackage.h \
+ wii/stringtablebuilder.h
FORMS += lsmainwindow.ui
RESOURCES += resources.qrc
diff --git a/README.markdown b/README.markdown
index 0aa3ff0..9a3852d 100644
--- a/README.markdown
+++ b/README.markdown
@@ -16,6 +16,7 @@ GX GPU emulation in the [Dolphin][dol] GameCube/Wii emulator.
### Implemented Features ###
- BRLYT reading (materials are not yet fully implemented)
- Simple API for manipulating layout files from other code
+- Wii filesystem API (currently only supports U8 archives)
### Planned Features ###
@@ -31,7 +32,6 @@ GX GPU emulation in the [Dolphin][dol] GameCube/Wii emulator.
- Test code for material structs
- Add usd1 handling
- Add LYTLayout packing
-- Add U8 archive support
- Add TPL file support
diff --git a/lyt/archivepackage.cpp b/lyt/archivepackage.cpp
new file mode 100644
index 0000000..6b5a476
--- /dev/null
+++ b/lyt/archivepackage.cpp
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ This file is part of LayoutStudio (http://github.com/Treeki/LayoutStudio)
+ Copyright (c) 2010 Treeki (treeki@gmail.com)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 2.0.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License 2.0 for more details.
+
+ You should have received a copy of the GNU General Public License 2.0
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*******************************************************************************/
+
+#include "archivepackage.h"
+
+#include <QtCore/QFile>
+
+LYTArchivePackage::LYTArchivePackage() : LYTPackageBase() {
+ m_archive = new WiiArchiveU8;
+}
+
+LYTArchivePackage::LYTArchivePackage(QString filename) : LYTPackageBase() {
+ m_filename = filename;
+
+ QFile file(filename);
+ file.open(QFile::ReadOnly);
+ QByteArray data = file.readAll();
+
+ QDataStream stream(data);
+ m_archive = new WiiArchiveU8(stream);
+}
+
+LYTArchivePackage::~LYTArchivePackage() {
+ delete m_archive;
+}
+
+
+
+WiiArchiveU8 *LYTArchivePackage::archive() {
+ return m_archive;
+}
+
+QString LYTArchivePackage::filename() {
+ return m_filename;
+}
+
+
+
+QStringList LYTArchivePackage::listSubDirIfExists(QString dirName) {
+ WiiFSObject *obj = this->m_archive->root.resolvePath(dirName);
+
+ if (obj && obj->isDirectory()) {
+ QStringList output;
+
+ foreach (WiiFSObject *ptr, ((WiiDirectory*)obj)->children) {
+ output.append(ptr->name);
+ }
+
+ return output;
+ }
+
+ return QStringList();
+}
+
+
+QByteArray LYTArchivePackage::getFileFromSubDirIfExists(QString dirName, QString fileName) {
+ WiiFSObject *obj = this->m_archive->root.resolvePath(QString("%1/%2").arg(dirName, fileName));
+
+ if (obj && obj->isFile()) {
+ return ((WiiFile*)obj)->data;
+ }
+
+ return QByteArray();
+}
+
+
+bool LYTArchivePackage::writeFileToSubDir(QString dirName, QString fileName, QByteArray data) {
+ WiiFSObject *obj = this->m_archive->root.resolvePath(QString("%1/%2").arg(dirName, fileName));
+
+ if (obj && obj->isFile()) {
+ ((WiiFile*)obj)->data = data;
+ return true;
+ }
+
+ return false;
+}
+
+
+
+
+QStringList LYTArchivePackage::listAnims() {
+ return this->listSubDirIfExists("arc/anim");
+}
+
+QStringList LYTArchivePackage::listLayouts() {
+ return this->listSubDirIfExists("arc/blyt");
+}
+
+QStringList LYTArchivePackage::listTextures() {
+ return this->listSubDirIfExists("arc/timg");
+}
+
+QStringList LYTArchivePackage::listFonts() {
+ return this->listSubDirIfExists("arc/font");
+}
+
+
+
+QByteArray LYTArchivePackage::getAnim(QString name) {
+ return this->getFileFromSubDirIfExists("arc/anim", name);
+}
+
+QByteArray LYTArchivePackage::getLayout(QString name) {
+ return this->getFileFromSubDirIfExists("arc/blyt", name);
+}
+
+QByteArray LYTArchivePackage::getTexture(QString name) {
+ return this->getFileFromSubDirIfExists("arc/timg", name);
+}
+
+QByteArray LYTArchivePackage::getFont(QString name) {
+ return this->getFileFromSubDirIfExists("arc/font", name);
+}
+
+
+
+bool LYTArchivePackage::writeAnim(QString name, QByteArray data) {
+ return this->writeFileToSubDir("arc/anim", name, data);
+}
+
+bool LYTArchivePackage::writeLayout(QString name, QByteArray data) {
+ return this->writeFileToSubDir("arc/blyt", name, data);
+}
+
+bool LYTArchivePackage::writeTexture(QString name, QByteArray data) {
+ return this->writeFileToSubDir("arc/timg", name, data);
+}
+
+bool LYTArchivePackage::writeFont(QString name, QByteArray data) {
+ return this->writeFileToSubDir("arc/font", name, data);
+}
+
+
+
+bool LYTArchivePackage::savePackage() {
+ QFile file(m_filename);
+
+ if (file.open(QFile::WriteOnly)) {
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::ReadWrite);
+
+ m_archive->writeToDataStream(stream);
+ file.write(data);
+
+ return true;
+ }
+
+ return false;
+}
+
+
+QString LYTArchivePackage::description() {
+ return m_filename;
+}
diff --git a/lyt/archivepackage.h b/lyt/archivepackage.h
new file mode 100644
index 0000000..7ef1abd
--- /dev/null
+++ b/lyt/archivepackage.h
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ This file is part of LayoutStudio (http://github.com/Treeki/LayoutStudio)
+ Copyright (c) 2010 Treeki (treeki@gmail.com)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 2.0.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License 2.0 for more details.
+
+ You should have received a copy of the GNU General Public License 2.0
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*******************************************************************************/
+
+#ifndef LYTARCHIVEPACKAGE_H
+#define LYTARCHIVEPACKAGE_H
+
+#include "packagebase.h"
+#include "wii/archiveu8.h"
+
+class LYTArchivePackage : public LYTPackageBase {
+public:
+ LYTArchivePackage();
+ LYTArchivePackage(QString filename);
+
+ ~LYTArchivePackage();
+
+ QStringList listAnims();
+ QStringList listLayouts();
+ QStringList listTextures();
+ QStringList listFonts();
+
+ QByteArray getAnim(QString name);
+ QByteArray getLayout(QString name);
+ QByteArray getTexture(QString name);
+ QByteArray getFont(QString name);
+
+ bool writeAnim(QString name, QByteArray data);
+ bool writeLayout(QString name, QByteArray data);
+ bool writeTexture(QString name, QByteArray data);
+ bool writeFont(QString name, QByteArray data);
+
+ bool savePackage();
+ QString description();
+
+ WiiArchiveU8 *archive();
+ QString filename();
+
+
+protected:
+ QStringList listSubDirIfExists(QString dirName);
+ QByteArray getFileFromSubDirIfExists(QString dirName, QString fileName);
+ bool writeFileToSubDir(QString dirName, QString fileName, QByteArray data);
+
+ WiiArchiveU8 *m_archive;
+ QString m_filename;
+};
+
+#endif // LYTARCHIVEPACKAGE_H
diff --git a/lyt/directorypackage.cpp b/lyt/directorypackage.cpp
index 84287e6..e8f31b9 100644
--- a/lyt/directorypackage.cpp
+++ b/lyt/directorypackage.cpp
@@ -17,7 +17,7 @@
#include "directorypackage.h"
-#include <QDir>
+#include <QtCore/QDir>
LYTDirectoryPackage::LYTDirectoryPackage(QString path) : LYTPackageBase() {
QDir fix_path(path);
diff --git a/lyt/packagebase.cpp b/lyt/packagebase.cpp
index c9004e7..e186435 100644
--- a/lyt/packagebase.cpp
+++ b/lyt/packagebase.cpp
@@ -20,3 +20,6 @@
LYTPackageBase::LYTPackageBase() {
// do nothing
}
+
+LYTPackageBase::~LYTPackageBase() {
+}
diff --git a/lyt/packagebase.h b/lyt/packagebase.h
index 3de3e58..9ad45c0 100644
--- a/lyt/packagebase.h
+++ b/lyt/packagebase.h
@@ -25,6 +25,7 @@
class LYTPackageBase {
public:
LYTPackageBase();
+ virtual ~LYTPackageBase();
virtual QStringList listAnims() = 0;
virtual QStringList listLayouts() = 0;
diff --git a/main.cpp b/main.cpp
index e54215b..b830731 100644
--- a/main.cpp
+++ b/main.cpp
@@ -20,18 +20,33 @@
#include "lsglobals.h"
#include "lyt/directorypackage.h"
+#include "lyt/archivepackage.h"
#include "lyt/layout.h"
+#include <QtCore/QFile>
+
+#include "wii/archiveu8.h"
+
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
LSGlobals::setup();
+ /*QFile file("H:\\ISOs\\NSMBWii\\Extracted\\Layout\\continue\\continue.arc");
+ file.open(QFile::ReadOnly);
+ QByteArray arc = file.readAll();
+ file.close();*/
+
+ LYTArchivePackage package("H:\\ISOs\\NSMBWii\\Extracted\\Layout\\continue\\continue.arc");
+ LYTLayout layout(package, "continue_05.brlyt");
+ package.savePackage();
+
+
//LYTDirectoryPackage package("H:\\ISOs\\NSMBWii\\Extracted\\Layout\\continue\\continue\\arc");
//LYTLayout layout(package, "continue_05.brlyt");
- LYTDirectoryPackage package("H:\\ISOs\\TP\\banner\\arc_extr");
- LYTLayout layout(package, "banner.brlyt");
+ //LYTDirectoryPackage package("H:\\ISOs\\TP\\banner\\arc_extr");
+ //LYTLayout layout(package, "banner.brlyt");
LSMainWindow w;
w.show();
diff --git a/wii/archiveu8.cpp b/wii/archiveu8.cpp
index aeb3aac..5e0ad5d 100644
--- a/wii/archiveu8.cpp
+++ b/wii/archiveu8.cpp
@@ -18,3 +18,246 @@
#include "archiveu8.h"
+
+
+
+
+WiiArchiveU8::WiiArchiveU8() { }
+
+WiiArchiveU8::WiiArchiveU8(QDataStream &stream) {
+ U8ReadInfo info;
+ info.startPos = stream.device()->pos();
+
+ quint32 magic;
+ stream >> (quint32&)magic;
+
+ if (magic != 0x55AA382D)
+ qWarning() << "WiiArchiveU8: tried to load an archive without the U8 magic";
+
+ quint32 fstStart, fstSize, dataOffset;
+ stream >> (quint32&)fstStart;
+ stream >> (quint32&)fstSize;
+ stream >> (quint32&)dataOffset;
+
+ // read the FST
+ stream.device()->seek(info.startPos + fstStart);
+
+ // read the root node
+ quint32 rootNodeLastChild;
+
+ stream.skipRawData(8); // ignore type, nameOffset and dataOffset
+ stream >> (quint32&)rootNodeLastChild;
+
+ // but before we do this, read the string table
+ qint64 savePos = stream.device()->pos();
+ stream.device()->seek(savePos + ((rootNodeLastChild - 1) * 12));
+
+ int stringTableLength = fstSize - (rootNodeLastChild * 12);
+
+ QByteArray rawStringTable;
+ rawStringTable.resize(stringTableLength);
+ stream.readRawData(rawStringTable.data(), stringTableLength);
+
+ info.stringTable = QString::fromAscii(rawStringTable.constData(), stringTableLength);
+
+ // now read the root node
+ stream.device()->seek(savePos);
+
+ qDebug() << "Reading root node: last child is" << rootNodeLastChild;
+ info.currentNode = 1;
+ this->readDir(stream, this->root, rootNodeLastChild, info);
+}
+
+
+void WiiArchiveU8::readDir(QDataStream &in, WiiDirectory &dir, int lastChild, U8ReadInfo &info) {
+ // read every node in this directory
+
+ while (info.currentNode < lastChild) {
+ info.currentNode++;
+
+ //qDebug() << "Reading @ pos" << in.device()->pos();
+
+ quint32 value, dataOffset, size;
+ in >> (quint32&)value;
+ in >> (quint32&)dataOffset;
+ in >> (quint32&)size;
+
+ int nameOffset = value & 0xFFFFFF;
+ int type = value >> 24;
+
+ WiiFSObject *newObj;
+ if (type == 0)
+ newObj = new WiiFile;
+ else if (type == 1)
+ newObj = new WiiDirectory;
+ else
+ qFatal("WiiArchiveU8::readDir: Unknown fs obj type %d", type);
+
+ // get the name
+ int nameSize = info.stringTable.indexOf(QChar::Null, nameOffset) - nameOffset;
+ newObj->name = info.stringTable.mid(nameOffset, nameSize);
+
+ qDebug() << "Reading node" << info.currentNode << newObj->name << "- type:" << type << "size:" << size << "offset:" << dataOffset;
+
+ // read the contents
+ if (newObj->isFile()) {
+ // get the file data
+ qint64 savePos = in.device()->pos();
+ in.device()->seek(info.startPos + dataOffset);
+
+ WiiFile *file = (WiiFile*)newObj;
+ file->data.resize(size);
+ in.readRawData(file->data.data(), size);
+
+ in.device()->seek(savePos);
+
+ } else if (newObj->isDirectory()) {
+ // read the children
+ this->readDir(in, *((WiiDirectory*)newObj), size, info);
+
+ }
+
+ qDebug() << "Adding" << newObj->name << "to" << dir.name;
+ dir.addChild(newObj);
+ };
+}
+
+
+
+void WiiArchiveU8::writeToDataStream(QDataStream &out) {
+ U8WriteInfo info;
+
+ // first off, before we do anything else, create the string table
+ this->addNodeToStringTable(this->root, info.stringTableBuilder);
+
+ QByteArray stringTable = info.stringTableBuilder.pack();
+
+ // calculate various fun offsets/sizes
+ int nodeCount = 0;
+ this->countNode(this->root, &nodeCount);
+
+ info.startPos = out.device()->pos();
+
+ quint32 fstStart = 0x20;
+ quint32 nodeDataSize = nodeCount * 12;
+ quint32 stringTableSize = stringTable.length();
+ quint32 fstSize = nodeDataSize + stringTableSize;
+ quint32 dataOffset = AlignUp(fstStart + fstSize, 0x20);
+
+ qDebug() << "Writing: fstStart" << fstStart << "nodeCount" << nodeCount;
+ qDebug() << "nodeDataSize" << nodeDataSize << "stringTableSize" << stringTableSize;
+ qDebug() << "fstSize" << fstSize << "dataOffset" << dataOffset;
+
+ // now write the header
+ out << (quint32)0x55AA382D;
+ out << (quint32)fstStart;
+ out << (quint32)fstSize;
+ out << (quint32)dataOffset;
+
+ WritePadding(0x10, out);
+
+ // write root node
+ info.currentNode = 1; // root node is 1
+ info.currentRecursionLevel = 0;
+ info.nextDataOffset = dataOffset;
+
+ out << (quint32)(0x01000000 << info.stringTableBuilder.add(""));
+ out << (quint32)0;
+ out << (quint32)nodeCount;
+
+ this->writeDir(out, this->root, info);
+
+ // write string table
+ out.writeRawData(stringTable.constData(), stringTable.length());
+
+ // write data (after padding)
+ WritePadding(dataOffset - fstSize - fstStart, out);
+
+ this->writeNodeData(out, this->root);
+
+ // looks like we are finally done
+}
+
+
+void WiiArchiveU8::addNodeToStringTable(WiiFSObject &node, WiiStringTableBuilder &table) {
+ table.add(node.name);
+
+ if (node.isDirectory()) {
+ WiiDirectory *dir = (WiiDirectory*)&node;
+
+ foreach (WiiFSObject *p, dir->children)
+ this->addNodeToStringTable(*p, table);
+ }
+}
+
+
+void WiiArchiveU8::countNode(WiiFSObject &node, int *countPtr) {
+ (*countPtr)++;
+
+ if (node.isDirectory()) {
+ WiiDirectory *dir = (WiiDirectory*)&node;
+
+ foreach (WiiFSObject *p, dir->children)
+ this->countNode(*p, countPtr);
+ }
+}
+
+
+void WiiArchiveU8::writeDir(QDataStream &out, WiiDirectory &dir, U8WriteInfo &info) {
+ foreach (WiiFSObject *p, dir.children) {
+ info.currentNode++;
+
+ if (p->isDirectory()) {
+ // write directory
+ WiiDirectory *thisDir = (WiiDirectory*)p;
+
+ out << (quint32)(0x01000000 | info.stringTableBuilder.add(thisDir->name));
+ out << (quint32)info.currentRecursionLevel;
+
+ qint64 lastChildFieldPos = out.device()->pos();
+ out << (quint32)0; // placeholder
+
+ info.currentRecursionLevel++;
+
+ this->writeDir(out, *thisDir, info);
+
+ info.currentRecursionLevel--;
+
+ // write lastChild field
+ qint64 dirEndPos = out.device()->pos();
+
+ out.device()->seek(lastChildFieldPos);
+ out << (quint32)info.currentNode;
+ out.device()->seek(dirEndPos);
+
+ } else if (p->isFile()) {
+ // write file
+ WiiFile *thisFile = (WiiFile*)p;
+
+ out << (quint32)info.stringTableBuilder.add(thisFile->name);
+ out << (quint32)info.nextDataOffset;
+ out << (quint32)thisFile->data.size();
+
+ info.nextDataOffset = AlignUp(info.nextDataOffset + thisFile->data.size(), 0x20);
+ }
+ }
+}
+
+
+void WiiArchiveU8::writeNodeData(QDataStream &out, WiiFSObject &node) {
+ if (node.isDirectory()) {
+ // write all the children's data
+ WiiDirectory *thisDir = (WiiDirectory*)&node;
+
+ foreach (WiiFSObject *p, thisDir->children)
+ this->writeNodeData(out, *p);
+
+ } else if (node.isFile()) {
+ // write this file's data
+ WiiFile *thisFile = (WiiFile*)&node;
+
+ int len = thisFile->data.length();
+ out.writeRawData(thisFile->data.constData(), len);
+ WritePadding(AlignUp(len, 0x20) - len, out);
+ }
+}
diff --git a/wii/archiveu8.h b/wii/archiveu8.h
index 66f3fbe..6f54ba2 100644
--- a/wii/archiveu8.h
+++ b/wii/archiveu8.h
@@ -20,8 +20,22 @@
#include "common.h"
#include "filesystem.h"
+#include "stringtablebuilder.h"
+struct U8ReadInfo {
+ qint64 startPos;
+ QString stringTable;
+ int currentNode;
+};
+
+struct U8WriteInfo {
+ qint64 startPos;
+ WiiStringTableBuilder stringTableBuilder;
+ int currentRecursionLevel;
+ int currentNode;
+ int nextDataOffset;
+};
class WiiArchiveU8 {
@@ -32,6 +46,16 @@ public:
WiiDirectory root;
void writeToDataStream(QDataStream &out);
+
+private:
+ void readDir(QDataStream &in, WiiDirectory &dir, int lastChild, U8ReadInfo &info);
+
+ void addNodeToStringTable(WiiFSObject &node, WiiStringTableBuilder &table);
+ void countNode(WiiFSObject &node, int *countPtr);
+
+ void writeDir(QDataStream &out, WiiDirectory &dir, U8WriteInfo &info);
+
+ void writeNodeData(QDataStream &out, WiiFSObject &node);
};
#endif // WIIARCHIVEU8_H
diff --git a/wii/common.h b/wii/common.h
index aa7dce0..34f1526 100644
--- a/wii/common.h
+++ b/wii/common.h
@@ -10,6 +10,15 @@
#include <QtCore/QDebug>
#include <QtCore/QVector>
+inline quint32 AlignUp(quint32 value, quint32 alignTo) {
+ return (value + alignTo - 1) & ~(alignTo - 1);
+}
+
+inline quint32 AlignDown(quint32 value, quint32 alignTo) {
+ return value & ~(alignTo - 1);
+}
+
+
inline quint32 BitExtract(quint32 value, int count, int start) {
// this function relies on heavy compiler optimisation to be efficient :p
quint32 mask = 0;
@@ -31,6 +40,10 @@ inline quint32 BitInsert(quint32 value, int newValue, int count, int start) {
return value;
}
+inline void WritePadding(int num, QDataStream &out) {
+ for (int i = 0; i < num; i++)
+ out << (quint8)0;
+}
diff --git a/wii/filesystem.cpp b/wii/filesystem.cpp
index 9926109..09fe207 100644
--- a/wii/filesystem.cpp
+++ b/wii/filesystem.cpp
@@ -39,7 +39,7 @@ void WiiFSObject::unlinkFromParent() {
}
bool WiiFSObject::nameIsEqual(QString check) {
- return (bool)(QString::compare(this->name, check, Qt::CaseInsensitive));
+ return (bool)(QString::compare(this->name, check, Qt::CaseInsensitive) == 0);
}
bool WiiFSObject::isFile() { return false; }
@@ -82,7 +82,7 @@ WiiFSObject *WiiDirectory::resolvePath(QString path) {
// special case: handle absolute paths
if (pathComponents.at(0) == "") {
while (currentDir->parent != 0)
- currentDir = currentDir->parent;
+ currentDir = (WiiDirectory*)currentDir->parent;
pathComponents.removeFirst();
}
@@ -90,14 +90,15 @@ WiiFSObject *WiiDirectory::resolvePath(QString path) {
// now we can loop through the path
while (!pathComponents.isEmpty()) {
QString next = pathComponents.takeFirst();
+ WiiFSObject *nextObj;
// get the next object in the path
if (next == ".") {
- next = currentDir;
+ nextObj = currentDir;
} else if (next == "..") {
- next = currentDir->parent;
+ nextObj = currentDir->parent;
} else {
- WiiFSObject *nextObj = currentDir->findByName(next, false);
+ nextObj = currentDir->findByName(next, false);
}
if (nextObj == 0) {
@@ -113,6 +114,7 @@ WiiFSObject *WiiDirectory::resolvePath(QString path) {
// verify that this object is a directory
if (!nextObj->isDirectory()) {
qWarning() << "Failed to resolve path" << path << ": component" << next << "is not a directory";
+ return 0;
}
// ok, this has to be a directory, so let's just continue
@@ -120,6 +122,7 @@ WiiFSObject *WiiDirectory::resolvePath(QString path) {
}
// we should not reach here
+ qWarning() << "Failed to resolve path" << path << ": unknown error";
return 0;
}
diff --git a/wii/stringtablebuilder.cpp b/wii/stringtablebuilder.cpp
new file mode 100644
index 0000000..679247c
--- /dev/null
+++ b/wii/stringtablebuilder.cpp
@@ -0,0 +1,25 @@
+#include "stringtablebuilder.h"
+
+WiiStringTableBuilder::WiiStringTableBuilder() {
+ m_nextOffset = 0;
+ m_data = "";
+}
+
+quint32 WiiStringTableBuilder::add(QString str) {
+ if (m_lookup.contains(str))
+ return m_lookup.value(str);
+
+ quint32 added = m_nextOffset;
+ m_lookup.insert(str, added);
+
+ m_data.append(str.toAscii());
+ m_data.append('\0');
+
+ m_nextOffset = m_data.length();
+
+ return added;
+}
+
+QByteArray WiiStringTableBuilder::pack() {
+ return m_data;
+}
diff --git a/wii/stringtablebuilder.h b/wii/stringtablebuilder.h
new file mode 100644
index 0000000..f416a37
--- /dev/null
+++ b/wii/stringtablebuilder.h
@@ -0,0 +1,22 @@
+#ifndef STRINGTABLEBUILDER_H
+#define STRINGTABLEBUILDER_H
+
+#include "common.h"
+#include <QtCore/QString>
+#include <QtCore/QHash>
+#include <QtCore/QByteArray>
+
+class WiiStringTableBuilder {
+public:
+ WiiStringTableBuilder();
+
+ quint32 add(QString str);
+ QByteArray pack();
+
+protected:
+ int m_nextOffset;
+ QByteArray m_data;
+ QHash<QString, quint32> m_lookup;
+};
+
+#endif // STRINGTABLEBUILDER_H