summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2010-10-09 01:00:16 +0200
committerTreeki <treeki@gmail.com>2010-10-09 01:00:16 +0200
commit7213ca723a65dff8ebb0c6c08669695217e60453 (patch)
tree1003cdfc9dd8fa21f2521c2e22071f391c555c78
parentc2cd2300ab03a41999b8e4e38cf0d29abb786918 (diff)
downloadLayoutStudio-7213ca723a65dff8ebb0c6c08669695217e60453.tar.gz
LayoutStudio-7213ca723a65dff8ebb0c6c08669695217e60453.zip
material bugfixes, plus the beginning of U8 archive code, and a nice little API for handling archive filesystems
-rw-r--r--LayoutStudio.pro11
-rw-r--r--lyt/common.h97
-rw-r--r--lyt/materials/indirectstage.h8
-rw-r--r--lyt/materials/material.cpp101
-rw-r--r--lyt/materials/material.h49
-rw-r--r--main.cpp6
-rw-r--r--wii/archiveu8.cpp20
-rw-r--r--wii/archiveu8.h37
-rw-r--r--wii/common.cpp (renamed from lyt/common.cpp)1
-rw-r--r--wii/common.h97
-rw-r--r--wii/filesystem.cpp138
-rw-r--r--wii/filesystem.h73
12 files changed, 478 insertions, 160 deletions
diff --git a/LayoutStudio.pro b/LayoutStudio.pro
index 8665bcd..9c5df61 100644
--- a/LayoutStudio.pro
+++ b/LayoutStudio.pro
@@ -14,7 +14,6 @@ SOURCES += main.cpp \
lyt/binaryfilesection.cpp \
lyt/materials/material.cpp \
lyt/pane.cpp \
- lyt/common.cpp \
lyt/textbox.cpp \
lyt/picture.cpp \
lyt/window.cpp \
@@ -28,7 +27,10 @@ SOURCES += main.cpp \
lyt/materials/indirectstage.cpp \
lyt/materials/tevstage.cpp \
lyt/materials/alphacompare.cpp \
- lyt/materials/blendmode.cpp
+ lyt/materials/blendmode.cpp \
+ wii/common.cpp \
+ wii/archiveu8.cpp \
+ wii/filesystem.cpp
HEADERS += lsmainwindow.h \
lsglobals.h \
lyt/packagebase.h \
@@ -52,7 +54,10 @@ HEADERS += lsmainwindow.h \
lyt/materials/indirectstage.h \
lyt/materials/tevstage.h \
lyt/materials/alphacompare.h \
- lyt/materials/blendmode.h
+ lyt/materials/blendmode.h \
+ wii/archiveu8.h \
+ wii/common.h \
+ wii/filesystem.h
FORMS += lsmainwindow.ui
RESOURCES += resources.qrc
diff --git a/lyt/common.h b/lyt/common.h
index c75813b..9c39339 100644
--- a/lyt/common.h
+++ b/lyt/common.h
@@ -19,13 +19,8 @@
#define LYTCOMMON_H
#include <QtGlobal>
-#include <QtCore/QByteArray>
-#include <QtGui/QColor>
-#include <QtCore/QPointF>
-#include <QtCore/QDataStream>
-#include <QtCore/QStringList>
-#include <QtCore/QDebug>
-#include <QtCore/QVector>
+
+#include "../wii/common.h"
union Magic {
char str[4];
@@ -39,97 +34,9 @@ union Version {
-inline quint32 BitExtract(quint32 value, int count, int start) {
- // this function relies on heavy compiler optimisation to be efficient :p
- quint32 mask = 0;
- for (int i = start; i < start+count; i++) {
- mask |= (0x80000000 >> i);
- }
-
- return (value & mask) >> (32 - (start + count));
-}
-
-inline quint32 BitInsert(quint32 value, int newValue, int count, int start) {
- quint32 mask = 0;
- for (int i = start; i < start+count; i++) {
- mask |= (0x80000000 >> i);
- }
-
- value &= ~mask;
- value |= (newValue << (32 - (start + count))) & mask;
- return value;
-}
-
-
-
-
-
-QByteArray PadByteArray(QByteArray original, int newLength, char padWith='\0');
-
-inline quint32 ColorToRGBA(QColor col) {
- return (col.red() << 24) | (col.green() << 16) | (col.blue() << 8) | (col.alpha());
-}
-
-inline QColor RGBAToColor(quint32 col) {
- return QColor(col >> 24, (col >> 16) & 0xFF, (col >> 8) & 0xFF, col & 0xFF);
-}
-
-inline void ReadRGBA8Color(QColor &out, QDataStream &in) {
- quint32 col;
- in >> (quint32&)col;
- out = RGBAToColor(col);
-}
-
-inline void WriteRGBA8Color(QColor &in, QDataStream &out) {
- out << (quint32)ColorToRGBA(in);
-}
-
-inline void ReadS10Color(QColor &out, QDataStream &in) {
- quint16 r, g, b, a;
- in >> (quint16&)r;
- in >> (quint16&)g;
- in >> (quint16&)b;
- in >> (quint16&)a;
- out.setRgb(r, g, b, a);
-}
-
-inline void WriteS10Color(QColor &in, QDataStream &out) {
- out << (quint16)in.red();
- out << (quint16)in.green();
- out << (quint16)in.blue();
- out << (quint16)in.alpha();
-}
-
-
-
-
struct LYTTexCoords {
QPointF coord[4];
};
-inline void ReadPointF(QDataStream &stream, QPointF &point) {
- float x, y;
- stream >> x;
- stream >> y;
- point.setX(x);
- point.setY(y);
-}
-
-inline void WritePointF(QDataStream &stream, const QPointF &point) {
- stream << (float)point.x();
- stream << (float)point.y();
-}
-
-inline void InitDataStream(QDataStream &stream) {
- stream.setByteOrder(QDataStream::BigEndian);
- stream.setVersion(QDataStream::Qt_4_5);
-}
-
-QStringList ReadStringList(QDataStream &in);
-
-QString ReadFixedLengthASCII(QDataStream &in, int length);
-void WriteFixedLengthASCII(QDataStream &out, QString str, int length);
-
-
#endif // LYTCOMMON_H
diff --git a/lyt/materials/indirectstage.h b/lyt/materials/indirectstage.h
index 30c6f9d..8f381bf 100644
--- a/lyt/materials/indirectstage.h
+++ b/lyt/materials/indirectstage.h
@@ -30,10 +30,10 @@ public:
void dumpToDebug();
- int texCoord;
- int texMap;
- int wrap_s;
- int wrap_t;
+ quint8 texCoord;
+ quint8 texMap;
+ quint8 wrap_s;
+ quint8 wrap_t;
};
diff --git a/lyt/materials/material.cpp b/lyt/materials/material.cpp
index f79fd08..a4498c5 100644
--- a/lyt/materials/material.cpp
+++ b/lyt/materials/material.cpp
@@ -31,8 +31,61 @@ LYTLayout &LYTMaterial::layout() const {
void LYTMaterial::dumpToDebug() {
qDebug() << "LYTMaterial" << name << "@" << (void*)this;
- // todo: move dumpToDebug calls for the various Material structs out of
- // LYTMaterial::read...() and put them here, since it makes more sense
+
+ for (int i = 0; i < 3; i++)
+ qDebug() << "Colour" << i << ":" << colours[i];
+
+ for (int i = 0; i < 4; i++)
+ qDebug() << "TEV Constant Colour" << i << ":" << tevKColour[i];
+
+ qDebug() << "TexMaps:" << texMaps.count();
+ foreach (LYTTexMap texMap, texMaps)
+ texMap.dumpToDebug();
+
+ qDebug() << "TexSRTs:" << texSRTs.count();
+ foreach (LYTTexSRT texSRT, texSRTs)
+ texSRT.dumpToDebug();
+
+ qDebug() << "TexCoordGens:" << texCoordGens.count();
+ foreach (LYTTexCoordGen texCoordGen, texCoordGens)
+ texCoordGen.dumpToDebug();
+
+ if (hasChanCtrl)
+ chanCtrl.dumpToDebug();
+ else
+ qDebug() << "ChanCtrl: none";
+
+ if (hasMatCol)
+ qDebug() << "MatCol:" << matCol;
+ else
+ qDebug() << "MatCol: none";
+
+ if (hasTevSwapTable)
+ tevSwapTable.dumpToDebug();
+ else
+ qDebug() << "TevSwapTable: none";
+
+ qDebug() << "IndTexSRTs:" << indTexSRTs.count();
+ foreach (LYTTexSRT indTexSRT, indTexSRTs)
+ indTexSRT.dumpToDebug();
+
+ qDebug() << "IndirectStages:" << indTexStages.count();
+ foreach (LYTIndirectStage indTexStage, indTexStages)
+ indTexStage.dumpToDebug();
+
+ qDebug() << "TevStages:" << tevStages.count();
+ foreach (LYTTevStage tevStage, tevStages)
+ tevStage.dumpToDebug();
+
+ if (hasAlphaCompare)
+ alphaCompare.dumpToDebug();
+ else
+ qDebug() << "AlphaCompare: none";
+
+ if (hasBlendMode)
+ blendMode.dumpToDebug();
+ else
+ qDebug() << "BlendMode: none";
}
@@ -51,8 +104,9 @@ void LYTMaterial::readFromDataStream(QDataStream &in) {
ReadRGBA8Color(this->tevKColour[i], in);
- LYTMaterialResourceNum resourceNum;
- in >> (quint32&)resourceNum.value;
+ quint32 resNumValue;
+ in >> (quint32&)resNumValue;
+ LYTMaterialResourceNum resourceNum(resNumValue);
// this is really complicated -_-
// first off: TexMap
@@ -79,7 +133,7 @@ void LYTMaterial::readFromDataStream(QDataStream &in) {
// ChanCtrl
if (resourceNum.hasChanCtrl()) {
this->hasChanCtrl = true;
- this->readChanCtrl(in);
+ this->chanCtrl.readFromDataStream(in);
} else {
this->hasChanCtrl = false;
}
@@ -87,7 +141,7 @@ void LYTMaterial::readFromDataStream(QDataStream &in) {
// MatCol
if (resourceNum.hasMatCol()) {
this->hasMatCol = true;
- this->readMatCol(in);
+ ReadRGBA8Color(this->matCol, in);
} else {
this->hasMatCol = false;
}
@@ -95,7 +149,7 @@ void LYTMaterial::readFromDataStream(QDataStream &in) {
// TevSwapTable
if (resourceNum.hasTevSwapTable()) {
this->hasTevSwapTable = true;
- this->readTevSwapTable(in);
+ this->tevSwapTable.readFromDataStream(in);
} else {
this->hasTevSwapTable = false;
}
@@ -124,7 +178,7 @@ void LYTMaterial::readFromDataStream(QDataStream &in) {
// AlphaCompare
if (resourceNum.hasAlphaCompare()) {
this->hasAlphaCompare = true;
- this->readAlphaCompare(in);
+ this->alphaCompare.readFromDataStream(in);
} else {
this->hasAlphaCompare = false;
}
@@ -132,7 +186,7 @@ void LYTMaterial::readFromDataStream(QDataStream &in) {
// BlendMode
if (resourceNum.hasBlendMode()) {
this->hasBlendMode = true;
- this->readBlendMode(in);
+ this->blendMode.readFromDataStream(in);
} else {
this->hasBlendMode = false;
}
@@ -143,60 +197,31 @@ void LYTMaterial::readFromDataStream(QDataStream &in) {
void LYTMaterial::readTexMap(QDataStream &in) {
this->texMaps.append(LYTTexMap());
this->texMaps.last().readFromDataStream(in, m_layout);
- this->texMaps.last().dumpToDebug();
}
void LYTMaterial::readTexSRT(QDataStream &in) {
this->texSRTs.append(LYTTexSRT());
this->texSRTs.last().readFromDataStream(in);
- this->texSRTs.last().dumpToDebug();
}
void LYTMaterial::readTexCoordGen(QDataStream &in) {
this->texCoordGens.append(LYTTexCoordGen());
this->texCoordGens.last().readFromDataStream(in);
- this->texCoordGens.last().dumpToDebug();
-}
-
-void LYTMaterial::readChanCtrl(QDataStream &in) {
- this->chanCtrl.readFromDataStream(in);
- this->chanCtrl.dumpToDebug();
-}
-
-void LYTMaterial::readMatCol(QDataStream &in) {
- ReadRGBA8Color(this->matCol, in);
-}
-
-void LYTMaterial::readTevSwapTable(QDataStream &in) {
- this->tevSwapTable.readFromDataStream(in);
- this->tevSwapTable.dumpToDebug();
}
void LYTMaterial::readIndTexSRT(QDataStream &in) {
this->indTexSRTs.append(LYTTexSRT());
this->indTexSRTs.last().readFromDataStream(in);
- this->indTexSRTs.last().dumpToDebug();
}
void LYTMaterial::readIndirectStage(QDataStream &in) {
this->indTexStages.append(LYTIndirectStage());
this->indTexStages.last().readFromDataStream(in);
- this->indTexStages.last().dumpToDebug();
}
void LYTMaterial::readTevStage(QDataStream &in) {
this->tevStages.append(LYTTevStage());
this->tevStages.last().readFromDataStream(in);
- this->tevStages.last().dumpToDebug();
}
-void LYTMaterial::readAlphaCompare(QDataStream &in) {
- this->alphaCompare.readFromDataStream(in);
- this->alphaCompare.dumpToDebug();
-}
-
-void LYTMaterial::readBlendMode(QDataStream &in) {
- this->blendMode.readFromDataStream(in);
- this->blendMode.dumpToDebug();
-}
diff --git a/lyt/materials/material.h b/lyt/materials/material.h
index bfdf80b..d605244 100644
--- a/lyt/materials/material.h
+++ b/lyt/materials/material.h
@@ -40,19 +40,37 @@ class LYTLayout;
class LYTMaterialResourceNum {
public:
- quint32 value;
-
- inline int getTexMapNum() { return BitExtract(value, 4, 28); }
- inline int getTexSRTNum() { return BitExtract(value, 4, 24); }
- inline int getTexCoordGenNum() { return BitExtract(value, 4, 20); }
- inline bool hasChanCtrl() { return BitExtract(value, 1, 6); }
- inline bool hasMatCol() { return BitExtract(value, 1, 4); }
- inline bool hasTevSwapTable() { return BitExtract(value, 1, 19); }
- inline bool hasAlphaCompare() { return BitExtract(value, 1, 8); }
- inline bool hasBlendMode() { return BitExtract(value, 1, 7); }
- inline int getIndTexSRTNum() { return BitExtract(value, 2, 17); }
- inline int getIndTexStageNum() { return BitExtract(value, 3, 14); }
- inline int getTevStageNum() { return BitExtract(value, 5, 9); }
+ LYTMaterialResourceNum() : m_value(0) { }
+ LYTMaterialResourceNum(int initValue) : m_value(initValue) { }
+
+ quint32 value() { return m_value; }
+
+ int getTexMapNum() { return BitExtract(m_value, 4, 28); }
+ int getTexSRTNum() { return BitExtract(m_value, 4, 24); }
+ int getTexCoordGenNum() { return BitExtract(m_value, 4, 20); }
+ bool hasChanCtrl() { return BitExtract(m_value, 1, 6); }
+ bool hasMatCol() { return BitExtract(m_value, 1, 4); }
+ bool hasTevSwapTable() { return BitExtract(m_value, 1, 19); }
+ bool hasAlphaCompare() { return BitExtract(m_value, 1, 8); }
+ bool hasBlendMode() { return BitExtract(m_value, 1, 7); }
+ int getIndTexSRTNum() { return BitExtract(m_value, 2, 17); }
+ int getIndTexStageNum() { return BitExtract(m_value, 3, 14); }
+ int getTevStageNum() { return BitExtract(m_value, 5, 9); }
+
+ void setTexMapNum(int v) { m_value = BitInsert(m_value, v, 4, 28); }
+ void setTexSRTNum(int v) { m_value = BitInsert(m_value, v, 4, 24); }
+ void setTexCoordGenNum(int v) { m_value = BitInsert(m_value, v, 4, 20); }
+ void setHasChanCtrl(bool v) { m_value = BitInsert(m_value, v, 1, 6); }
+ void setHasMatCol(bool v) { m_value = BitInsert(m_value, v, 1, 4); }
+ void setHasTevSwapTable(bool v) { m_value = BitInsert(m_value, v, 1, 19); }
+ void setHasAlphaCompare(bool v) { m_value = BitInsert(m_value, v, 1, 8); }
+ void setHasBlendMode(bool v) { m_value = BitInsert(m_value, v, 1, 7); }
+ void setIndTexSRTNum(int v) { m_value = BitInsert(m_value, v, 2, 17); }
+ void setIndTexStageNum(int v) { m_value = BitInsert(m_value, v, 3, 14); }
+ void setTevStageNum(int v) { m_value = BitInsert(m_value, v, 5, 9); }
+
+private:
+ quint32 m_value;
};
@@ -109,11 +127,6 @@ protected:
void readTexMap(QDataStream &in);
void readTexSRT(QDataStream &in);
void readTexCoordGen(QDataStream &in);
- void readChanCtrl(QDataStream &in);
- void readMatCol(QDataStream &in);
- void readTevSwapTable(QDataStream &in);
- void readAlphaCompare(QDataStream &in);
- void readBlendMode(QDataStream &in);
void readIndirectStage(QDataStream &in);
void readIndTexSRT(QDataStream &in);
void readTevStage(QDataStream &in);
diff --git a/main.cpp b/main.cpp
index eddf190..e54215b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -28,8 +28,10 @@ int main(int argc, char *argv[]) {
LSGlobals::setup();
- LYTDirectoryPackage package("H:\\ISOs\\NSMBWii\\Extracted\\Layout\\continue\\continue\\arc");
- LYTLayout layout(package, "continue_05.brlyt");
+ //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");
LSMainWindow w;
w.show();
diff --git a/wii/archiveu8.cpp b/wii/archiveu8.cpp
new file mode 100644
index 0000000..aeb3aac
--- /dev/null
+++ b/wii/archiveu8.cpp
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ 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 "archiveu8.h"
+
+
diff --git a/wii/archiveu8.h b/wii/archiveu8.h
new file mode 100644
index 0000000..66f3fbe
--- /dev/null
+++ b/wii/archiveu8.h
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ 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 WIIARCHIVEU8_H
+#define WIIARCHIVEU8_H
+
+#include "common.h"
+#include "filesystem.h"
+
+
+
+
+class WiiArchiveU8 {
+public:
+ WiiArchiveU8();
+ WiiArchiveU8(QDataStream &stream);
+
+ WiiDirectory root;
+
+ void writeToDataStream(QDataStream &out);
+};
+
+#endif // WIIARCHIVEU8_H
diff --git a/lyt/common.cpp b/wii/common.cpp
index ba86246..f4a961c 100644
--- a/lyt/common.cpp
+++ b/wii/common.cpp
@@ -107,3 +107,4 @@ void WriteFixedLengthASCII(QDataStream &out, QString str, int length) {
out.writeRawData(paddedStr.constData(), paddedStr.length());
}
+
diff --git a/wii/common.h b/wii/common.h
new file mode 100644
index 0000000..aa7dce0
--- /dev/null
+++ b/wii/common.h
@@ -0,0 +1,97 @@
+#ifndef WIICOMMON_H
+#define WIICOMMON_H
+
+#include <QtGlobal>
+#include <QtCore/QByteArray>
+#include <QtGui/QColor>
+#include <QtCore/QPointF>
+#include <QtCore/QDataStream>
+#include <QtCore/QStringList>
+#include <QtCore/QDebug>
+#include <QtCore/QVector>
+
+inline quint32 BitExtract(quint32 value, int count, int start) {
+ // this function relies on heavy compiler optimisation to be efficient :p
+ quint32 mask = 0;
+ for (int i = start; i < start+count; i++) {
+ mask |= (0x80000000 >> i);
+ }
+
+ return (value & mask) >> (32 - (start + count));
+}
+
+inline quint32 BitInsert(quint32 value, int newValue, int count, int start) {
+ quint32 mask = 0;
+ for (int i = start; i < start+count; i++) {
+ mask |= (0x80000000 >> i);
+ }
+
+ value &= ~mask;
+ value |= (newValue << (32 - (start + count))) & mask;
+ return value;
+}
+
+
+
+
+
+QByteArray PadByteArray(QByteArray original, int newLength, char padWith='\0');
+
+inline quint32 ColorToRGBA(QColor col) {
+ return (col.red() << 24) | (col.green() << 16) | (col.blue() << 8) | (col.alpha());
+}
+
+inline QColor RGBAToColor(quint32 col) {
+ return QColor(col >> 24, (col >> 16) & 0xFF, (col >> 8) & 0xFF, col & 0xFF);
+}
+
+inline void ReadRGBA8Color(QColor &out, QDataStream &in) {
+ quint32 col;
+ in >> (quint32&)col;
+ out = RGBAToColor(col);
+}
+
+inline void WriteRGBA8Color(QColor &in, QDataStream &out) {
+ out << (quint32)ColorToRGBA(in);
+}
+
+inline void ReadS10Color(QColor &out, QDataStream &in) {
+ quint16 r, g, b, a;
+ in >> (quint16&)r;
+ in >> (quint16&)g;
+ in >> (quint16&)b;
+ in >> (quint16&)a;
+ out.setRgb(r, g, b, a);
+}
+
+inline void WriteS10Color(QColor &in, QDataStream &out) {
+ out << (quint16)in.red();
+ out << (quint16)in.green();
+ out << (quint16)in.blue();
+ out << (quint16)in.alpha();
+}
+
+inline void ReadPointF(QDataStream &stream, QPointF &point) {
+ float x, y;
+ stream >> x;
+ stream >> y;
+ point.setX(x);
+ point.setY(y);
+}
+
+inline void WritePointF(QDataStream &stream, const QPointF &point) {
+ stream << (float)point.x();
+ stream << (float)point.y();
+}
+
+inline void InitDataStream(QDataStream &stream) {
+ stream.setByteOrder(QDataStream::BigEndian);
+ stream.setVersion(QDataStream::Qt_4_5);
+}
+
+QStringList ReadStringList(QDataStream &in);
+
+QString ReadFixedLengthASCII(QDataStream &in, int length);
+void WriteFixedLengthASCII(QDataStream &out, QString str, int length);
+
+#endif // WIICOMMON_H
diff --git a/wii/filesystem.cpp b/wii/filesystem.cpp
new file mode 100644
index 0000000..9926109
--- /dev/null
+++ b/wii/filesystem.cpp
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ 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 "filesystem.h"
+
+
+/******************************************************************************/
+
+WiiFSObject::WiiFSObject() { parent = 0; }
+WiiFSObject::~WiiFSObject() { }
+
+
+
+void WiiFSObject::unlinkFromParent() {
+ if (this->parent == 0)
+ return;
+
+ if (this->parent->isDirectory()) {
+ WiiDirectory *p = (WiiDirectory *)this->parent;
+ if (p->children.contains(this))
+ p->children.removeAt(p->children.indexOf(this));
+ }
+
+ this->parent = 0;
+}
+
+bool WiiFSObject::nameIsEqual(QString check) {
+ return (bool)(QString::compare(this->name, check, Qt::CaseInsensitive));
+}
+
+bool WiiFSObject::isFile() { return false; }
+bool WiiFSObject::isDirectory() { return false; }
+
+/******************************************************************************/
+
+bool WiiFile::isFile() { return true; }
+
+/******************************************************************************/
+
+WiiDirectory::~WiiDirectory() {
+ foreach (WiiFSObject *ptr, children)
+ delete ptr;
+}
+
+bool WiiDirectory::isDirectory() { return true; }
+
+WiiFSObject *WiiDirectory::findByName(QString name, bool recursive) {
+ foreach (WiiFSObject *obj, children) {
+ if (obj->nameIsEqual(name))
+ return obj;
+
+ if (recursive && obj->isDirectory()) {
+ WiiDirectory *dir = (WiiDirectory*)obj;
+ WiiFSObject *tryThis = dir->findByName(name, recursive);
+
+ if (tryThis)
+ return tryThis;
+ }
+ }
+
+ return 0;
+}
+
+WiiFSObject *WiiDirectory::resolvePath(QString path) {
+ QStringList pathComponents = path.split('/');
+ WiiDirectory *currentDir = this;
+
+ // special case: handle absolute paths
+ if (pathComponents.at(0) == "") {
+ while (currentDir->parent != 0)
+ currentDir = currentDir->parent;
+
+ pathComponents.removeFirst();
+ }
+
+ // now we can loop through the path
+ while (!pathComponents.isEmpty()) {
+ QString next = pathComponents.takeFirst();
+
+ // get the next object in the path
+ if (next == ".") {
+ next = currentDir;
+ } else if (next == "..") {
+ next = currentDir->parent;
+ } else {
+ WiiFSObject *nextObj = currentDir->findByName(next, false);
+ }
+
+ if (nextObj == 0) {
+ qWarning() << "Failed to resolve path" << path << ": missing component" << next;
+ return 0;
+ }
+
+ if (pathComponents.isEmpty()) {
+ // we've reached the end \o/
+ return nextObj;
+ }
+
+ // verify that this object is a directory
+ if (!nextObj->isDirectory()) {
+ qWarning() << "Failed to resolve path" << path << ": component" << next << "is not a directory";
+ }
+
+ // ok, this has to be a directory, so let's just continue
+ currentDir = (WiiDirectory *)nextObj;
+ }
+
+ // we should not reach here
+ return 0;
+}
+
+bool WiiDirectory::addChild(WiiFSObject *obj) {
+ // verify to make sure an object does not exist with this name
+ if (this->findByName(obj->name, false) != 0)
+ return false;
+
+ obj->unlinkFromParent();
+
+ this->children.append(obj);
+ obj->parent = this;
+
+ return true;
+}
+
diff --git a/wii/filesystem.h b/wii/filesystem.h
new file mode 100644
index 0000000..1a7ecfa
--- /dev/null
+++ b/wii/filesystem.h
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ 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 WIIFILESYSTEM_H
+#define WIIFILESYSTEM_H
+
+#include "common.h"
+
+
+class WiiFSObject {
+ // abstract base class of all filesystem objects
+public:
+ virtual ~WiiFSObject();
+
+ WiiFSObject *parent;
+
+ QString name;
+
+
+ void unlinkFromParent();
+ bool nameIsEqual(QString check);
+
+ virtual bool isFile();
+ virtual bool isDirectory();
+
+
+protected:
+ WiiFSObject(); // don't instantiate this class directly!
+};
+
+
+/******************************************************************************/
+
+class WiiFile : public WiiFSObject {
+public:
+ QByteArray data;
+
+
+ bool isFile();
+};
+
+/******************************************************************************/
+
+class WiiDirectory : public WiiFSObject {
+public:
+ ~WiiDirectory();
+
+ QList<WiiFSObject *> children;
+
+
+ bool isDirectory();
+
+ WiiFSObject *findByName(QString name, bool recursive);
+ WiiFSObject *resolvePath(QString path);
+ bool addChild(WiiFSObject *obj);
+};
+
+
+#endif // FILESYSTEM_H