summaryrefslogtreecommitdiff
path: root/MapTool
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--MapTool/MapTool.pro35
-rw-r--r--MapTool/MapTool.pro.user113
-rw-r--r--MapTool/main.cpp10
-rw-r--r--MapTool/mtmainwindow.cpp14
-rw-r--r--MapTool/mtmainwindow.h21
-rw-r--r--MapTool/mtmainwindow.ui137
-rw-r--r--MapTool/t3d/common.h24
-rw-r--r--MapTool/t3d/material.cpp4
-rw-r--r--MapTool/t3d/material.h9
-rw-r--r--MapTool/t3d/mesh.cpp4
-rw-r--r--MapTool/t3d/mesh.h18
-rw-r--r--MapTool/t3d/model.cpp4
-rw-r--r--MapTool/t3d/model.h16
-rw-r--r--MapTool/t3d/objreader.cpp80
-rw-r--r--MapTool/t3d/objreader.h30
-rw-r--r--MapTool/wii/archiveu8.cpp263
-rw-r--r--MapTool/wii/archiveu8.h61
-rw-r--r--MapTool/wii/common.cpp134
-rw-r--r--MapTool/wii/common.h111
-rw-r--r--MapTool/wii/filesystem.cpp141
-rw-r--r--MapTool/wii/filesystem.h73
-rw-r--r--MapTool/wii/stringtablebuilder.cpp25
-rw-r--r--MapTool/wii/stringtablebuilder.h22
23 files changed, 1349 insertions, 0 deletions
diff --git a/MapTool/MapTool.pro b/MapTool/MapTool.pro
new file mode 100644
index 0000000..94e83c7
--- /dev/null
+++ b/MapTool/MapTool.pro
@@ -0,0 +1,35 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2010-12-10T10:51:23
+#
+#-------------------------------------------------
+
+QT += core gui opengl
+
+TARGET = MapTool
+TEMPLATE = app
+
+
+SOURCES += main.cpp\
+ mtmainwindow.cpp \
+ wii/stringtablebuilder.cpp \
+ wii/filesystem.cpp \
+ wii/common.cpp \
+ wii/archiveu8.cpp \
+ t3d/objreader.cpp \
+ t3d/model.cpp \
+ t3d/mesh.cpp \
+ t3d/material.cpp
+
+HEADERS += mtmainwindow.h \
+ wii/stringtablebuilder.h \
+ wii/filesystem.h \
+ wii/common.h \
+ wii/archiveu8.h \
+ t3d/objreader.h \
+ t3d/model.h \
+ t3d/mesh.h \
+ t3d/common.h \
+ t3d/material.h
+
+FORMS += mtmainwindow.ui
diff --git a/MapTool/MapTool.pro.user b/MapTool/MapTool.pro.user
new file mode 100644
index 0000000..447c181
--- /dev/null
+++ b/MapTool/MapTool.pro.user
@@ -0,0 +1,113 @@
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+ <variable>ProjectExplorer.Project.ActiveTarget</variable>
+ <value type="int">0</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.EditorSettings</variable>
+ <valuemap type="QVariantMap">
+ <value key="EditorConfiguration.Codec" type="QByteArray">System</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Target.0</variable>
+ <valuemap type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Desktop</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Target.DesktopTarget</value>
+ <value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
+ <value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Debug</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/me/Games/Newer/Kamek/MapTool-build-desktop</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <valuemap key="ProjectExplorer.Target.BuildConfiguration.1" type="QVariantMap">
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">qmake</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">QtProjectManager.QMakeBuildStep</value>
+ <valuelist key="QtProjectManager.QMakeBuildStep.QMakeArguments" type="QVariantList"/>
+ </valuemap>
+ <valuemap key="ProjectExplorer.BuildConfiguration.BuildStep.1" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.BuildStepsCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.BuildConfiguration.CleanStep.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Make</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.MakeStep</value>
+ <value key="Qt4ProjectManager.MakeStep.Clean" type="bool">true</value>
+ <valuelist key="Qt4ProjectManager.MakeStep.MakeArguments" type="QVariantList">
+ <value type="QString">clean</value>
+ </valuelist>
+ <value key="Qt4ProjectManager.MakeStep.MakeCommand" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.BuildConfiguration.CleanStepsCount" type="int">1</value>
+ <value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
+ <valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">Release</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4BuildConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.BuildDirectory" type="QString">/home/me/Games/Newer/Kamek/MapTool-build-desktop</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.QtVersionId" type="int">2</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.ToolChain" type="int">0</value>
+ <value key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild" type="bool">true</value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">2</value>
+ <valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
+ <value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString">MapTool</value>
+ <value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">Qt4ProjectManager.Qt4RunConfiguration</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.BaseEnvironmentBase" type="int">2</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.ProFile" type="QString">MapTool.pro</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal" type="bool">false</value>
+ <valuelist key="Qt4ProjectManager.Qt4RunConfiguration.UserEnvironmentChanges" type="QVariantList"/>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetName" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserSetWorkingDirectory" type="bool">false</value>
+ <value key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory" type="QString"></value>
+ </valuemap>
+ <value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
+ </valuemap>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.TargetCount</variable>
+ <value type="int">1</value>
+ </data>
+ <data>
+ <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+ <value type="int">4</value>
+ </data>
+</qtcreator>
diff --git a/MapTool/main.cpp b/MapTool/main.cpp
new file mode 100644
index 0000000..2241edd
--- /dev/null
+++ b/MapTool/main.cpp
@@ -0,0 +1,10 @@
+#include <QtGui/QApplication>
+#include "mtmainwindow.h"
+
+int main(int argc, char *argv[]) {
+ QApplication a(argc, argv);
+ MTMainWindow w;
+ w.show();
+
+ return a.exec();
+}
diff --git a/MapTool/mtmainwindow.cpp b/MapTool/mtmainwindow.cpp
new file mode 100644
index 0000000..587d0c3
--- /dev/null
+++ b/MapTool/mtmainwindow.cpp
@@ -0,0 +1,14 @@
+#include "mtmainwindow.h"
+#include "ui_mtmainwindow.h"
+
+MTMainWindow::MTMainWindow(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MTMainWindow)
+{
+ ui->setupUi(this);
+}
+
+MTMainWindow::~MTMainWindow()
+{
+ delete ui;
+}
diff --git a/MapTool/mtmainwindow.h b/MapTool/mtmainwindow.h
new file mode 100644
index 0000000..a73b9e0
--- /dev/null
+++ b/MapTool/mtmainwindow.h
@@ -0,0 +1,21 @@
+#ifndef MTMAINWINDOW_H
+#define MTMAINWINDOW_H
+
+#include <QMainWindow>
+
+namespace Ui {
+ class MTMainWindow;
+}
+
+class MTMainWindow : public QMainWindow {
+ Q_OBJECT
+
+public:
+ explicit MTMainWindow(QWidget *parent = 0);
+ ~MTMainWindow();
+
+private:
+ Ui::MTMainWindow *ui;
+};
+
+#endif // MTMAINWINDOW_H
diff --git a/MapTool/mtmainwindow.ui b/MapTool/mtmainwindow.ui
new file mode 100644
index 0000000..d0ab60d
--- /dev/null
+++ b/MapTool/mtmainwindow.ui
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MTMainWindow</class>
+ <widget class="QMainWindow" name="MTMainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>438</width>
+ <height>425</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MTMainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="loadButton">
+ <property name="text">
+ <string>Load Scene</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="saveButton">
+ <property name="text">
+ <string>Save Scene</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton">
+ <property name="text">
+ <string>Export ARC</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="groupTab">
+ <attribute name="title">
+ <string>Groups</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QListView" name="groupView"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="modelTab">
+ <attribute name="title">
+ <string>Models</string>
+ </attribute>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Scene Graph</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QTreeView" name="sceneGraphView"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Available Models</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QTreeView" name="availableModelView"/>
+ </item>
+ <item>
+ <widget class="QPushButton" name="editModelPoolButton">
+ <property name="text">
+ <string>Edit Available Models</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="stageTab">
+ <attribute name="title">
+ <string>Stages</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QTreeView" name="stageView"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="pathTab">
+ <attribute name="title">
+ <string>Paths</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_6">
+ <item>
+ <widget class="QTreeView" name="pathView"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/MapTool/t3d/common.h b/MapTool/t3d/common.h
new file mode 100644
index 0000000..15b65b8
--- /dev/null
+++ b/MapTool/t3d/common.h
@@ -0,0 +1,24 @@
+#ifndef T3DCOMMON_H
+#define T3DCOMMON_H
+
+struct Vec {
+ float x, y, z;
+};
+
+struct Vec2 {
+ float x, y;
+};
+
+struct Triangle {
+ Vec vertex[3];
+ Vec2 texcoord[3];
+ Vec normal[3];
+};
+
+struct Quad {
+ Vec vertex[4];
+ Vec2 texcoord[4];
+ Vec normal[4];
+};
+
+#endif // T3DCOMMON_H
diff --git a/MapTool/t3d/material.cpp b/MapTool/t3d/material.cpp
new file mode 100644
index 0000000..c9f3a35
--- /dev/null
+++ b/MapTool/t3d/material.cpp
@@ -0,0 +1,4 @@
+#include "material.h"
+
+T3DMaterial::T3DMaterial() {
+}
diff --git a/MapTool/t3d/material.h b/MapTool/t3d/material.h
new file mode 100644
index 0000000..cc4bab3
--- /dev/null
+++ b/MapTool/t3d/material.h
@@ -0,0 +1,9 @@
+#ifndef T3DMATERIAL_H
+#define T3DMATERIAL_H
+
+class T3DMaterial {
+public:
+ T3DMaterial();
+};
+
+#endif // T3DMATERIAL_H
diff --git a/MapTool/t3d/mesh.cpp b/MapTool/t3d/mesh.cpp
new file mode 100644
index 0000000..3dc10b8
--- /dev/null
+++ b/MapTool/t3d/mesh.cpp
@@ -0,0 +1,4 @@
+#include "mesh.h"
+
+T3DMesh::T3DMesh() {
+}
diff --git a/MapTool/t3d/mesh.h b/MapTool/t3d/mesh.h
new file mode 100644
index 0000000..2b9ce89
--- /dev/null
+++ b/MapTool/t3d/mesh.h
@@ -0,0 +1,18 @@
+#ifndef T3DMESH_H
+#define T3DMESH_H
+
+#include "common.h"
+#include "material.h"
+#include <QtCore/QVector>
+
+class T3DMesh {
+public:
+ T3DMesh();
+
+ QVector<Triangle> triangles;
+ QVector<Quad> quads;
+
+ T3DMaterial *material;
+};
+
+#endif // T3DMESH_H
diff --git a/MapTool/t3d/model.cpp b/MapTool/t3d/model.cpp
new file mode 100644
index 0000000..c2dc6dc
--- /dev/null
+++ b/MapTool/t3d/model.cpp
@@ -0,0 +1,4 @@
+#include "model.h"
+
+T3DModel::T3DModel() {
+}
diff --git a/MapTool/t3d/model.h b/MapTool/t3d/model.h
new file mode 100644
index 0000000..a6535af
--- /dev/null
+++ b/MapTool/t3d/model.h
@@ -0,0 +1,16 @@
+#ifndef T3DMODEL_H
+#define T3DMODEL_H
+
+#include <QtCore/QList>
+#include "mesh.h"
+
+class T3DModel {
+public:
+ T3DModel();
+ ~T3DModel();
+
+ QList<T3DMesh *> meshes;
+
+};
+
+#endif // T3DMODEL_H
diff --git a/MapTool/t3d/objreader.cpp b/MapTool/t3d/objreader.cpp
new file mode 100644
index 0000000..3a07323
--- /dev/null
+++ b/MapTool/t3d/objreader.cpp
@@ -0,0 +1,80 @@
+#include "objreader.h"
+
+T3DObjReader::T3DObjReader(T3DModel &model) {
+ m_model = model;
+}
+
+T3DObjReader::parseLine(QString line) {
+ line = line.trimmed();
+ if (line.isEmpty() || line.at(0) == '#')
+ return;
+
+ QStringList params = line.split(' ', QString::SkipEmptyParts);
+ QString cmd = params[0];
+
+ if (cmd == "v") {
+ float x, y, z;
+ x = params[1].toFloat();
+ y = params[2].toFloat();
+ z = params[3].toFloat();
+ known_vertices.append(Vec(x, y, z));
+ }
+
+ if (cmd == "vt") {
+ float x, y;
+ x = params[1].toFloat();
+ y = params[2].toFloat();
+ known_texcoords.append(Vec2(x, y));
+ }
+
+ if (cmd == "vn") {
+ float x, y, z;
+ x = params[1].toFloat();
+ y = params[2].toFloat();
+ z = params[3].toFloat();
+ known_normals.append(Vec(x, y, z));
+ }
+
+ if (cmd == "f") {
+ int vtxCount = params.count() - 1;
+ if (vtxCount < 3 || vtxCount > 4)
+ return;
+
+ int vtxID[4], tcID[4], nrmID[4];
+
+ for (int i = 0; i < vtxCount; i++) {
+ QString face = params[i+1];
+ QStringList ids = face.split('/');
+ vtxID[i] = ids[0].isEmpty() ? 0 : ids[0].toInt();
+ tcID[i] = ids[1].isEmpty() ? 0 : ids[1].toInt();
+ nrmID[i] = ids[2].isEmpty() ? 0 : ids[2].toInt();
+ }
+
+ if (vtxCount == 3) {
+ Triangle tri;
+ for (int i = 0; i < 3; i++) {
+ tri.vertex[i] = known_vertices[vtxID[i]];
+ tri.texcoord[i] = known_texcoords[tcID[i]];
+ tri.normal[i] = known_normals[nrmID[i]];
+ }
+ m_currentMesh->triangles.append(tri);
+ }
+
+ if (vtxCount == 4) {
+ Quad q;
+ for (int i = 0; i < 4; i++) {
+ q.vertex[i] = known_vertices[vtxID[i]];
+ q.texcoord[i] = known_texcoords[tcID[i]];
+ q.normal[i] = known_normals[nrmID[i]];
+ }
+ m_currentMesh->quads.append(q);
+ }
+ }
+
+ if (cmd == "usemtl") {
+ // treat this as "new shape"
+ m_currentMesh = new T3DMesh();
+ m_model->meshes.append(m_currentMesh);
+ m_currentMesh->material = materials[params[1]];
+ }
+}
diff --git a/MapTool/t3d/objreader.h b/MapTool/t3d/objreader.h
new file mode 100644
index 0000000..6e518e8
--- /dev/null
+++ b/MapTool/t3d/objreader.h
@@ -0,0 +1,30 @@
+#ifndef T3DOBJREADER_H
+#define T3DOBJREADER_H
+
+#include <QtCore/QList>
+#include <QtCore/QVector>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QHash>
+#include "model.h"
+
+class T3DObjReader {
+private:
+ T3DModel *m_model;
+ T3DMesh *m_currentMesh;
+
+ QVector<Vec> known_vertices;
+ QVector<Vec2> known_texcoords;
+ QVector<Vec> known_normals;
+
+public:
+ T3DObjReader(T3DModel &model);
+
+ void parseLine(QString line);
+
+ T3DModel *model() { return m_model; }
+
+ QHash<QString, T3DMaterial *> materials;
+};
+
+#endif // T3DOBJREADER_H
diff --git a/MapTool/wii/archiveu8.cpp b/MapTool/wii/archiveu8.cpp
new file mode 100644
index 0000000..d27dfde
--- /dev/null
+++ b/MapTool/wii/archiveu8.cpp
@@ -0,0 +1,263 @@
+/*******************************************************************************
+ 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"
+
+
+
+
+
+
+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) const {
+ 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(const WiiFSObject &node, WiiStringTableBuilder &table) const {
+ table.add(node.name);
+
+ if (node.isDirectory()) {
+ WiiDirectory *dir = (WiiDirectory*)&node;
+
+ foreach (WiiFSObject *p, dir->children)
+ this->addNodeToStringTable(*p, table);
+ }
+}
+
+
+void WiiArchiveU8::countNode(const WiiFSObject &node, int *countPtr) const {
+ (*countPtr)++;
+
+ if (node.isDirectory()) {
+ WiiDirectory *dir = (WiiDirectory*)&node;
+
+ foreach (WiiFSObject *p, dir->children)
+ this->countNode(*p, countPtr);
+ }
+}
+
+
+void WiiArchiveU8::writeDir(QDataStream &out, const WiiDirectory &dir, U8WriteInfo &info) const {
+ 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, const WiiFSObject &node) const {
+ 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/MapTool/wii/archiveu8.h b/MapTool/wii/archiveu8.h
new file mode 100644
index 0000000..5561beb
--- /dev/null
+++ b/MapTool/wii/archiveu8.h
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ 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"
+#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 {
+public:
+ WiiArchiveU8();
+ WiiArchiveU8(QDataStream &stream);
+
+ WiiDirectory root;
+
+ void writeToDataStream(QDataStream &out) const;
+
+private:
+ void readDir(QDataStream &in, WiiDirectory &dir, int lastChild, U8ReadInfo &info);
+
+ void addNodeToStringTable(const WiiFSObject &node, WiiStringTableBuilder &table) const;
+ void countNode(const WiiFSObject &node, int *countPtr) const;
+
+ void writeDir(QDataStream &out, const WiiDirectory &dir, U8WriteInfo &info) const;
+
+ void writeNodeData(QDataStream &out, const WiiFSObject &node) const;
+};
+
+#endif // WIIARCHIVEU8_H
diff --git a/MapTool/wii/common.cpp b/MapTool/wii/common.cpp
new file mode 100644
index 0000000..8f552b3
--- /dev/null
+++ b/MapTool/wii/common.cpp
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ 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 "common.h"
+
+QByteArray PadByteArray(const QByteArray original, int newLength, char padWith) {
+ QByteArray newArray = original;
+
+ if (original.length() > newLength) {
+ // the original array is longer than the length desired, so truncate it
+ newArray.truncate(newLength);
+
+ } else if (original.length() < newLength) {
+ // the original array is shorter, so pad it
+ int oldLength = original.length();
+ newArray.resize(newLength);
+
+ for (int i = oldLength; i < newLength; i++) {
+ newArray[i] = '\0';
+ }
+ }
+
+ return newArray;
+}
+
+QStringList ReadStringList(QDataStream &in) {
+ QStringList output;
+
+ quint16 count;
+ in >> (quint16&)count;
+ in.skipRawData(2); // padding
+
+ QVector<quint32> stringOffsets(count);
+
+ // save the initial offset so we can get the strings later
+ // string offsets are based on the first offset entry (after the count)
+ // NOT on the section offset
+ qint64 savedPos = in.device()->pos();
+
+ for (int i = 0; i < count; i++) {
+ quint32 offset;
+ in >> (quint32&)offset;
+ in.skipRawData(4); // unused?
+
+ stringOffsets[i] = offset;
+ }
+
+ // ok, now we can get the strings
+ for (int i = 0; i < count; i++) {
+ in.device()->seek(savedPos + stringOffsets[i]);
+
+ // how fun: no length is stored for each string, they're just zero
+ // terminated. so let's try to figure it out!
+ int stringLength = 0;
+ char check;
+
+ in >> (quint8&)check;
+ while (check != 0) {
+ stringLength += 1;
+ in >> (quint8&)check;
+ }
+
+ // now read the string
+ char *buffer = new char[stringLength];
+
+ in.device()->seek(savedPos + stringOffsets[i]);
+ in.readRawData(buffer, stringLength);
+
+ output.append(QString::fromAscii(buffer, stringLength));
+
+ delete[] buffer;
+
+
+ qDebug() << "Read string:" << output.last();
+ }
+
+ return output;
+}
+
+void WriteStringList(QDataStream &out, const QStringList list) {
+ out << (quint16)list.count();
+ WritePadding(2, out);
+
+ // calculate offsets for every string, and write them
+ // offset 0 points to the first entry in the offset list, etc, so
+ // take that into account for the string offset calculation
+ quint32 currentOffset = list.count() * 8;
+
+ foreach (QString str, list) {
+ out << (quint32)currentOffset;
+ WritePadding(4, out); // unused?
+
+ currentOffset += str.length() + 1;
+ }
+
+ // now write the strings
+ foreach (QString str, list) {
+ QByteArray rawStr = str.toAscii();
+ rawStr.append('\0');
+ out.writeRawData(rawStr.constData(), rawStr.length());
+ }
+}
+
+QString ReadFixedLengthASCII(QDataStream &in, int length) {
+ QByteArray readStr(length, '\0');
+ in.readRawData(readStr.data(), readStr.length());
+
+ QString str = QString::fromAscii(readStr.data(), readStr.length());
+ if (str.contains(QChar('\0')))
+ str.truncate(str.indexOf(QChar('\0')));
+
+ return str;
+}
+
+void WriteFixedLengthASCII(QDataStream &out, const QString str, int length) {
+ QByteArray paddedStr = PadByteArray(str.toAscii(), length);
+ out.writeRawData(paddedStr.constData(), paddedStr.length());
+}
+
+
diff --git a/MapTool/wii/common.h b/MapTool/wii/common.h
new file mode 100644
index 0000000..b440841
--- /dev/null
+++ b/MapTool/wii/common.h
@@ -0,0 +1,111 @@
+#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 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;
+ 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;
+}
+
+inline void WritePadding(int num, QDataStream &out) {
+ for (int i = 0; i < num; i++)
+ out << (quint8)0;
+}
+
+
+
+
+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(const 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(const 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);
+void WriteStringList(QDataStream &out, QStringList list);
+
+QString ReadFixedLengthASCII(QDataStream &in, int length);
+void WriteFixedLengthASCII(QDataStream &out, QString str, int length);
+
+#endif // WIICOMMON_H
diff --git a/MapTool/wii/filesystem.cpp b/MapTool/wii/filesystem.cpp
new file mode 100644
index 0000000..014b693
--- /dev/null
+++ b/MapTool/wii/filesystem.cpp
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ 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) const {
+ return (bool)(QString::compare(this->name, check, Qt::CaseInsensitive) == 0);
+}
+
+bool WiiFSObject::isFile() const { return false; }
+bool WiiFSObject::isDirectory() const { return false; }
+
+/******************************************************************************/
+
+bool WiiFile::isFile() const { return true; }
+
+/******************************************************************************/
+
+WiiDirectory::~WiiDirectory() {
+ foreach (WiiFSObject *ptr, children)
+ delete ptr;
+}
+
+bool WiiDirectory::isDirectory() const { return true; }
+
+WiiFSObject *WiiDirectory::findByName(QString name, bool recursive) const {
+ 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 = (WiiDirectory*)currentDir->parent;
+
+ pathComponents.removeFirst();
+ }
+
+ // 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 == ".") {
+ nextObj = currentDir;
+ } else if (next == "..") {
+ nextObj = currentDir->parent;
+ } else {
+ 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 (WiiFSObject *)nextObj;
+ }
+
+ // 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
+ currentDir = (WiiDirectory *)nextObj;
+ }
+
+ // we should not reach here
+ qWarning() << "Failed to resolve path" << path << ": unknown error";
+ 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/MapTool/wii/filesystem.h b/MapTool/wii/filesystem.h
new file mode 100644
index 0000000..7527a7d
--- /dev/null
+++ b/MapTool/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) const;
+
+ virtual bool isFile() const;
+ virtual bool isDirectory() const;
+
+
+protected:
+ WiiFSObject(); // don't instantiate this class directly!
+};
+
+
+/******************************************************************************/
+
+class WiiFile : public WiiFSObject {
+public:
+ QByteArray data;
+
+
+ bool isFile() const;
+};
+
+/******************************************************************************/
+
+class WiiDirectory : public WiiFSObject {
+public:
+ ~WiiDirectory();
+
+ QList<WiiFSObject *> children;
+
+
+ bool isDirectory() const;
+
+ WiiFSObject *findByName(QString name, bool recursive) const;
+ WiiFSObject *resolvePath(QString path);
+ bool addChild(WiiFSObject *obj);
+};
+
+
+#endif // FILESYSTEM_H
diff --git a/MapTool/wii/stringtablebuilder.cpp b/MapTool/wii/stringtablebuilder.cpp
new file mode 100644
index 0000000..d1f2d2b
--- /dev/null
+++ b/MapTool/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() const {
+ return m_data;
+}
diff --git a/MapTool/wii/stringtablebuilder.h b/MapTool/wii/stringtablebuilder.h
new file mode 100644
index 0000000..4fce60f
--- /dev/null
+++ b/MapTool/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() const;
+
+protected:
+ int m_nextOffset;
+ QByteArray m_data;
+ QHash<QString, quint32> m_lookup;
+};
+
+#endif // STRINGTABLEBUILDER_H