Arguments::Arguments()
 : outfile(0)
-, dump(false) {
+, runlevel(PLAY) {
 
 }
 
                if (arg[0] == '-') {
                        switch (arg[1]) {
                                case 'd':
-                                       dump = true;
+                                       runlevel = DUMP;
                                        break;
                                case 'o':
                                        if (i + 1 >= argc) {
                                        }
                                        ++i;
                                        outfile = argv[i];
+                                       runlevel = WRITE;
+                                       break;
+                               case 'B':
+                                       runlevel = BATTLE;
+                                       break;
+                               case 'M':
+                                       runlevel = MAP;
+                                       break;
+                               case 'S':
+                                       runlevel = SOURCE_WIKI;
                                        break;
                                default:
                                        throw std::runtime_error(std::string("unknown option ") + arg[1]);
        }
 }
 
-Arguments::RunLevel Arguments::DetectRunLevel() const {
-       if (dump) {
-               return DUMP;
-       } else if (outfile) {
-               return WRITE;
-       } else {
-               return PLAY;
-       }
-}
-
 }
 
                DUMP,
                PLAY,
                WRITE,
+
+               // temporary modes
+               BATTLE,
+               MAP,
+               SOURCE_WIKI,
        };
 
 public:
        void Read(int argc, char **argv);
 
-       RunLevel DetectRunLevel() const;
+       RunLevel GetRunLevel() const { return runlevel; }
 
        const std::vector<char *> &Infiles() const { return infiles; }
 
 private:
        std::vector<char *> infiles;
        const char *outfile;
-       bool dump;
+       RunLevel runlevel;
 
 };
 
 
        int stringId(TypeDescription::GetTypeId("String"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("Monster"));
+       td.SetDescription("All data of a monster.");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Monster));
 
-       td.AddField("name", FieldDescription(((char *)&m.name) - ((char *)&m), stringId, true));
-       td.AddField("sprite", FieldDescription(((char *)&m.sprite) - ((char *)&m), spriteId, true));
-       td.AddField("level", FieldDescription(((char *)&m.level) - ((char *)&m), numberId, false));
+       td.AddField("name", FieldDescription(((char *)&m.name) - ((char *)&m), stringId).SetReferenced());
+       td.AddField("sprite", FieldDescription(((char *)&m.sprite) - ((char *)&m), spriteId).SetReferenced());
+       td.AddField("level", FieldDescription(((char *)&m.level) - ((char *)&m), numberId));
 
-       td.AddField("maxHealth", FieldDescription(((char *)&m.maxHealth) - ((char *)&m), numberId, false));
-       td.AddField("health", FieldDescription(((char *)&m.health) - ((char *)&m), numberId, false));
-       td.AddField("maxMana", FieldDescription(((char *)&m.maxMana) - ((char *)&m), numberId, false));
-       td.AddField("mana", FieldDescription(((char *)&m.mana) - ((char *)&m), numberId, false));
-       td.AddField("stats", FieldDescription(((char *)&m.stats) - ((char *)&m), statsId, false));
+       td.AddField("maxHealth", FieldDescription(((char *)&m.maxHealth) - ((char *)&m), numberId));
+       td.AddField("health", FieldDescription(((char *)&m.health) - ((char *)&m), numberId));
+       td.AddField("maxMana", FieldDescription(((char *)&m.maxMana) - ((char *)&m), numberId));
+       td.AddField("mana", FieldDescription(((char *)&m.mana) - ((char *)&m), numberId));
+       td.AddField("stats", FieldDescription(((char *)&m.stats) - ((char *)&m), statsId));
 
-       td.AddField("attackAnimation", FieldDescription(((char *)&m.attackAnimation) - ((char *)&m), animationId, true));
-       td.AddField("spellAnimation", FieldDescription(((char *)&m.spellAnimation) - ((char *)&m), animationId, true));
-       td.AddField("meleeAnimation", FieldDescription(((char *)&m.meleeAnimation) - ((char *)&m), animationId, true));
+       td.AddField("attackAnimation", FieldDescription(((char *)&m.attackAnimation) - ((char *)&m), animationId).SetReferenced());
+       td.AddField("spellAnimation", FieldDescription(((char *)&m.spellAnimation) - ((char *)&m), animationId).SetReferenced());
+       td.AddField("meleeAnimation", FieldDescription(((char *)&m.meleeAnimation) - ((char *)&m), animationId).SetReferenced());
 }
 
 void Monster::Construct(void *data) {
 
        int vectorId(TypeDescription::GetTypeId("Vector"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("PartyLayout"));
+       td.SetDescription("Positions of party members");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(PartyLayout));
 
-       td.AddField("positions", FieldDescription(((char *)&p.positions) - ((char *)&p), vectorId, true, true));
+       td.AddField("positions", FieldDescription(((char *)&p.positions) - ((char *)&p), vectorId).SetReferenced().SetAggregate().SetDescription("the members' positions"));
 }
 
 void PartyLayout::Construct(void *data) {
 
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Resources));
 
-       td.AddField("swapCursor", FieldDescription(((char *)&r.swapCursor) - ((char *)&r), spriteId, true));
-       td.AddField("moveIcons", FieldDescription(((char *)&r.moveIcons) - ((char *)&r), spriteId, true));
-       td.AddField("attackIcons", FieldDescription(((char *)&r.attackIcons) - ((char *)&r), spriteId, true));
-       td.AddField("attackChoiceIcons", FieldDescription(((char *)&r.attackChoiceIcons) - ((char *)&r), spriteId, true));
+       td.AddField("swapCursor", FieldDescription(((char *)&r.swapCursor) - ((char *)&r), spriteId).SetReferenced().SetDescription("the cursor sprite for swapping heroes"));
+       td.AddField("moveIcons", FieldDescription(((char *)&r.moveIcons) - ((char *)&r), spriteId).SetReferenced().SetDescription("the icons of the move selection menu"));
+       td.AddField("attackIcons", FieldDescription(((char *)&r.attackIcons) - ((char *)&r), spriteId).SetReferenced().SetDescription("the icons of the attack selection menu"));
+       td.AddField("attackChoiceIcons", FieldDescription(((char *)&r.attackChoiceIcons) - ((char *)&r), spriteId).SetReferenced().SetDescription("the icons showing the hero's attack choice in the respective tag"));
 
-       td.AddField("titleFrame", FieldDescription(((char *)&r.titleFrame) - ((char *)&r), frameId, true));
-       td.AddField("titleFont", FieldDescription(((char *)&r.titleFont) - ((char *)&r), fontId, true));
+       td.AddField("titleFrame", FieldDescription(((char *)&r.titleFrame) - ((char *)&r), frameId).SetReferenced().SetDescription("frame for title headings (spell names, status information, etc.)"));
+       td.AddField("titleFont", FieldDescription(((char *)&r.titleFont) - ((char *)&r), fontId).SetReferenced().SetDescription("the font for title headings"));
 
-       td.AddField("heroTagFrame", FieldDescription(((char *)&r.heroTagFrame) - ((char *)&r), frameId, true));
-       td.AddField("activeHeroTagFrame", FieldDescription(((char *)&r.activeHeroTagFrame) - ((char *)&r), frameId, true));
-       td.AddField("smallHeroTagFrame", FieldDescription(((char *)&r.smallHeroTagFrame) - ((char *)&r), frameId, true));
-       td.AddField("lastSmallHeroTagFrame", FieldDescription(((char *)&r.lastSmallHeroTagFrame) - ((char *)&r), frameId, true));
+       td.AddField("heroTagFrame", FieldDescription(((char *)&r.heroTagFrame) - ((char *)&r), frameId).SetReferenced().SetDescription("frame for hero tags"));
+       td.AddField("activeHeroTagFrame", FieldDescription(((char *)&r.activeHeroTagFrame) - ((char *)&r), frameId).SetReferenced().SetDescription("frame for the active hero's tag"));
+       td.AddField("smallHeroTagFrame", FieldDescription(((char *)&r.smallHeroTagFrame) - ((char *)&r), frameId).SetReferenced().SetDescription("frame for small hero tags (during attack animation)"));
+       td.AddField("lastSmallHeroTagFrame", FieldDescription(((char *)&r.lastSmallHeroTagFrame) - ((char *)&r), frameId).SetReferenced().SetDescription("frame for the last small hero tag"));
 
-       td.AddField("heroTagFont", FieldDescription(((char *)&r.heroTagFont) - ((char *)&r), fontId, true));
-       td.AddField("heroTagLabels", FieldDescription(((char *)&r.heroTagLabels) - ((char *)&r), spriteId, true));
+       td.AddField("heroTagFont", FieldDescription(((char *)&r.heroTagFont) - ((char *)&r), fontId).SetReferenced().SetDescription("font for hero tags (hero names)"));
+       td.AddField("heroTagLabels", FieldDescription(((char *)&r.heroTagLabels) - ((char *)&r), spriteId).SetReferenced().SetDescription("labels on the hero tag (hp/mp/ip/lvl/move)"));
 
-       td.AddField("healthGauge", FieldDescription(((char *)&r.healthGauge) - ((char *)&r), gaugeId, true));
-       td.AddField("manaGauge", FieldDescription(((char *)&r.manaGauge) - ((char *)&r), gaugeId, true));
-       td.AddField("ikariGauge", FieldDescription(((char *)&r.ikariGauge) - ((char *)&r), gaugeId, true));
+       td.AddField("healthGauge", FieldDescription(((char *)&r.healthGauge) - ((char *)&r), gaugeId).SetReferenced().SetDescription("health gauge"));
+       td.AddField("manaGauge", FieldDescription(((char *)&r.manaGauge) - ((char *)&r), gaugeId).SetReferenced().SetDescription("mana gauge"));
+       td.AddField("ikariGauge", FieldDescription(((char *)&r.ikariGauge) - ((char *)&r), gaugeId).SetReferenced().SetDescription("ikari gauge"));
 
-       td.AddField("selectFrame", FieldDescription(((char *)&r.selectFrame) - ((char *)&r), frameId, true));
+       td.AddField("selectFrame", FieldDescription(((char *)&r.selectFrame) - ((char *)&r), frameId).SetReferenced().SetDescription("frame for spell, item, and ikari menus"));
 
-       td.AddField("normalFont", FieldDescription(((char *)&r.normalFont) - ((char *)&r), fontId, true));
-       td.AddField("disabledFont", FieldDescription(((char *)&r.disabledFont) - ((char *)&r), fontId, true));
+       td.AddField("normalFont", FieldDescription(((char *)&r.normalFont) - ((char *)&r), fontId).SetReferenced().SetDescription("font for menus"));
+       td.AddField("disabledFont", FieldDescription(((char *)&r.disabledFont) - ((char *)&r), fontId).SetReferenced().SetDescription("font for disabled entries in menus"));
 
-       td.AddField("menuCursor", FieldDescription(((char *)&r.menuCursor) - ((char *)&r), spriteId, true));
-       td.AddField("weaponTargetCursor", FieldDescription(((char *)&r.weaponTargetCursor) - ((char *)&r), spriteId, true));
-       td.AddField("magicTargetCursor", FieldDescription(((char *)&r.magicTargetCursor) - ((char *)&r), spriteId, true));
-       td.AddField("itemTargetCursor", FieldDescription(((char *)&r.itemTargetCursor) - ((char *)&r), spriteId, true));
+       td.AddField("menuCursor", FieldDescription(((char *)&r.menuCursor) - ((char *)&r), spriteId).SetReferenced().SetDescription("selection indicator for menus"));
+       td.AddField("weaponTargetCursor", FieldDescription(((char *)&r.weaponTargetCursor) - ((char *)&r), spriteId).SetReferenced().SetDescription("cursor for selectiong attack targets"));
+       td.AddField("magicTargetCursor", FieldDescription(((char *)&r.magicTargetCursor) - ((char *)&r), spriteId).SetReferenced().SetDescription("cursor for selectiong spell targets"));
+       td.AddField("itemTargetCursor", FieldDescription(((char *)&r.itemTargetCursor) - ((char *)&r), spriteId).SetReferenced().SetDescription("cursor for selectiong item targets"));
 
-       td.AddField("spellMenuHeadline", FieldDescription(((char *)&r.spellMenuHeadline) - ((char *)&r), stringId, true));
-       td.AddField("spellMenuProperties", FieldDescription(((char *)&r.spellMenuProperties) - ((char *)&r), menuPropertiesId, true));
+       td.AddField("spellMenuHeadline", FieldDescription(((char *)&r.spellMenuHeadline) - ((char *)&r), stringId).SetReferenced().SetDescription("headline of the spell menu"));
+       td.AddField("spellMenuProperties", FieldDescription(((char *)&r.spellMenuProperties) - ((char *)&r), menuPropertiesId).SetReferenced().SetDescription("properties of the spell menu"));
 
-       td.AddField("itemMenuHeadline", FieldDescription(((char *)&r.itemMenuHeadline) - ((char *)&r), stringId, true));
-       td.AddField("itemMenuProperties", FieldDescription(((char *)&r.itemMenuProperties) - ((char *)&r), menuPropertiesId, true));
+       td.AddField("itemMenuHeadline", FieldDescription(((char *)&r.itemMenuHeadline) - ((char *)&r), stringId).SetReferenced().SetDescription("headline of the item menu"));
+       td.AddField("itemMenuProperties", FieldDescription(((char *)&r.itemMenuProperties) - ((char *)&r), menuPropertiesId).SetReferenced().SetDescription("properties of the item menu"));
 
-       td.AddField("ikariMenuHeadline", FieldDescription(((char *)&r.ikariMenuHeadline) - ((char *)&r), stringId, true));
-       td.AddField("ikariMenuProperties", FieldDescription(((char *)&r.ikariMenuProperties) - ((char *)&r), menuPropertiesId, true));
-       td.AddField("noEquipmentText", FieldDescription(((char *)&r.noEquipmentText) - ((char *)&r), stringId, true));
+       td.AddField("ikariMenuHeadline", FieldDescription(((char *)&r.ikariMenuHeadline) - ((char *)&r), stringId).SetReferenced().SetDescription("headline of the ikari menu"));
+       td.AddField("ikariMenuProperties", FieldDescription(((char *)&r.ikariMenuProperties) - ((char *)&r), menuPropertiesId).SetReferenced().SetDescription("properties of the ikari menu"));
+       td.AddField("noEquipmentText", FieldDescription(((char *)&r.noEquipmentText) - ((char *)&r), stringId).SetReferenced().SetDescription("text to show for missing equipment"));
 
-       td.AddField("escapeText", FieldDescription(((char *)&r.escapeText) - ((char *)&r), stringId, true));
+       td.AddField("escapeText", FieldDescription(((char *)&r.escapeText) - ((char *)&r), stringId).SetReferenced().SetDescription("displayed when the party escapes"));
 
-       td.AddField("numberAnimationPrototype", FieldDescription(((char *)&r.numberAnimationPrototype) - ((char *)&r), animationId, true));
+       td.AddField("numberAnimationPrototype", FieldDescription(((char *)&r.numberAnimationPrototype) - ((char *)&r), animationId).SetReferenced().SetDescription("animation of an attack's result digit"));
 
-       td.AddField("bigNumberSprite", FieldDescription(((char *)&r.bigNumberSprite) - ((char *)&r), spriteId, true));
-       td.AddField("greenNumberSprite", FieldDescription(((char *)&r.greenNumberSprite) - ((char *)&r), spriteId, true));
+       td.AddField("bigNumberSprite", FieldDescription(((char *)&r.bigNumberSprite) - ((char *)&r), spriteId).SetReferenced().SetDescription("sprite containing the damage numbers"));
+       td.AddField("greenNumberSprite", FieldDescription(((char *)&r.greenNumberSprite) - ((char *)&r), spriteId).SetReferenced().SetDescription("sprite containing the healing numbers"));
 
-       td.AddField("weaponMenuIcon", FieldDescription(((char *)&r.weaponMenuIcon) - ((char *)&r), spriteId, true));
-       td.AddField("armorMenuIcon", FieldDescription(((char *)&r.armorMenuIcon) - ((char *)&r), spriteId, true));
-       td.AddField("shieldMenuIcon", FieldDescription(((char *)&r.shieldMenuIcon) - ((char *)&r), spriteId, true));
-       td.AddField("helmetMenuIcon", FieldDescription(((char *)&r.helmetMenuIcon) - ((char *)&r), spriteId, true));
-       td.AddField("ringMenuIcon", FieldDescription(((char *)&r.ringMenuIcon) - ((char *)&r), spriteId, true));
-       td.AddField("jewelMenuIcon", FieldDescription(((char *)&r.jewelMenuIcon) - ((char *)&r), spriteId, true));
+       td.AddField("weaponMenuIcon", FieldDescription(((char *)&r.weaponMenuIcon) - ((char *)&r), spriteId).SetReferenced().SetDescription("weapon icon for ikari menu"));
+       td.AddField("armorMenuIcon", FieldDescription(((char *)&r.armorMenuIcon) - ((char *)&r), spriteId).SetReferenced().SetDescription("armor icon for ikari menu"));
+       td.AddField("shieldMenuIcon", FieldDescription(((char *)&r.shieldMenuIcon) - ((char *)&r), spriteId).SetReferenced().SetDescription("shield icon for ikari menu"));
+       td.AddField("helmetMenuIcon", FieldDescription(((char *)&r.helmetMenuIcon) - ((char *)&r), spriteId).SetReferenced().SetDescription("helmet icon for ikari menu"));
+       td.AddField("ringMenuIcon", FieldDescription(((char *)&r.ringMenuIcon) - ((char *)&r), spriteId).SetReferenced().SetDescription("ring icon for ikari menu"));
+       td.AddField("jewelMenuIcon", FieldDescription(((char *)&r.jewelMenuIcon) - ((char *)&r), spriteId).SetReferenced().SetDescription("jewel icon for ikari menu"));
 
-       td.AddField("levelLabelRow", FieldDescription(((char *)&r.levelLabelRow) - ((char *)&r), numberId, false));
-       td.AddField("levelLabelCol", FieldDescription(((char *)&r.levelLabelCol) - ((char *)&r), numberId, false));
-       td.AddField("healthLabelRow", FieldDescription(((char *)&r.healthLabelRow) - ((char *)&r), numberId, false));
-       td.AddField("healthLabelCol", FieldDescription(((char *)&r.healthLabelCol) - ((char *)&r), numberId, false));
-       td.AddField("manaLabelRow", FieldDescription(((char *)&r.manaLabelRow) - ((char *)&r), numberId, false));
-       td.AddField("manaLabelCol", FieldDescription(((char *)&r.manaLabelCol) - ((char *)&r), numberId, false));
-       td.AddField("moveLabelRow", FieldDescription(((char *)&r.moveLabelRow) - ((char *)&r), numberId, false));
-       td.AddField("moveLabelCol", FieldDescription(((char *)&r.moveLabelCol) - ((char *)&r), numberId, false));
-       td.AddField("ikariLabelRow", FieldDescription(((char *)&r.ikariLabelRow) - ((char *)&r), numberId, false));
-       td.AddField("ikariLabelCol", FieldDescription(((char *)&r.ikariLabelCol) - ((char *)&r), numberId, false));
+       td.AddField("levelLabelRow", FieldDescription(((char *)&r.levelLabelRow) - ((char *)&r), numberId).SetDescription("column of the level label in heroTagLabels"));
+       td.AddField("levelLabelCol", FieldDescription(((char *)&r.levelLabelCol) - ((char *)&r), numberId).SetDescription("row of the level label in heroTagLabels"));
+       td.AddField("healthLabelRow", FieldDescription(((char *)&r.healthLabelRow) - ((char *)&r), numberId).SetDescription("column of the health label in heroTagLabels"));
+       td.AddField("healthLabelCol", FieldDescription(((char *)&r.healthLabelCol) - ((char *)&r), numberId).SetDescription("row of the health label in heroTagLabels"));
+       td.AddField("manaLabelRow", FieldDescription(((char *)&r.manaLabelRow) - ((char *)&r), numberId).SetDescription("column of the mana label in heroTagLabels"));
+       td.AddField("manaLabelCol", FieldDescription(((char *)&r.manaLabelCol) - ((char *)&r), numberId).SetDescription("row of the mana label in heroTagLabels"));
+       td.AddField("moveLabelRow", FieldDescription(((char *)&r.moveLabelRow) - ((char *)&r), numberId).SetDescription("column of the move label in heroTagLabels"));
+       td.AddField("moveLabelCol", FieldDescription(((char *)&r.moveLabelCol) - ((char *)&r), numberId).SetDescription("row of the move label in heroTagLabels"));
+       td.AddField("ikariLabelRow", FieldDescription(((char *)&r.ikariLabelRow) - ((char *)&r), numberId).SetDescription("column of the ikari label in heroTagLabels"));
+       td.AddField("ikariLabelCol", FieldDescription(((char *)&r.ikariLabelCol) - ((char *)&r), numberId).SetDescription("row of the ikari label in heroTagLabels"));
 
-       td.AddField("heroesBgColor", FieldDescription(((char *)&r.heroesBgColor) - ((char *)&r), colorId, false));
+       td.AddField("heroesBgColor", FieldDescription(((char *)&r.heroesBgColor) - ((char *)&r), colorId).SetDescription("background color of the small tags during attack animation"));
 }
 
 void Resources::Construct(void *data) {
 
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Hero));
 
-       td.AddField("name", FieldDescription(((char *)&h.name) - ((char *)&h), stringId, true));
+       td.AddField("name", FieldDescription(((char *)&h.name) - ((char *)&h), stringId).SetReferenced());
 
-       td.AddField("maxHealth", FieldDescription(((char *)&h.maxHealth) - ((char *)&h), numberId, false));
-       td.AddField("health", FieldDescription(((char *)&h.health) - ((char *)&h), numberId, false));
-       td.AddField("maxMana", FieldDescription(((char *)&h.maxMana) - ((char *)&h), numberId, false));
-       td.AddField("mana", FieldDescription(((char *)&h.mana) - ((char *)&h), numberId, false));
-       td.AddField("ip", FieldDescription(((char *)&h.ip) - ((char *)&h), numberId, false));
+       td.AddField("maxHealth", FieldDescription(((char *)&h.maxHealth) - ((char *)&h), numberId));
+       td.AddField("health", FieldDescription(((char *)&h.health) - ((char *)&h), numberId));
+       td.AddField("maxMana", FieldDescription(((char *)&h.maxMana) - ((char *)&h), numberId));
+       td.AddField("mana", FieldDescription(((char *)&h.mana) - ((char *)&h), numberId));
+       td.AddField("ip", FieldDescription(((char *)&h.ip) - ((char *)&h), numberId));
 
-       td.AddField("stats", FieldDescription(((char *)&h.stats) - ((char *)&h), statsId, false));
+       td.AddField("stats", FieldDescription(((char *)&h.stats) - ((char *)&h), statsId));
 
-       td.AddField("level", FieldDescription(((char *)&h.level) - ((char *)&h), numberId, false));
+       td.AddField("level", FieldDescription(((char *)&h.level) - ((char *)&h), numberId));
 
-       td.AddField("battleSprite", FieldDescription(((char *)&h.battleSprite) - ((char *)&h), spriteId, true));
-       td.AddField("attackAnimation", FieldDescription(((char *)&h.attackAnimation) - ((char *)&h), animationId, true));
-       td.AddField("spellAnimation", FieldDescription(((char *)&h.spellAnimation) - ((char *)&h), animationId, true));
-       td.AddField("meleeAnimation", FieldDescription(((char *)&h.meleeAnimation) - ((char *)&h), animationId, true));
+       td.AddField("battleSprite", FieldDescription(((char *)&h.battleSprite) - ((char *)&h), spriteId).SetReferenced().SetDescription("the sprite used for battle scenes"));
+       td.AddField("attackAnimation", FieldDescription(((char *)&h.attackAnimation) - ((char *)&h), animationId).SetReferenced().SetDescription("the animation played for physical attacks"));
+       td.AddField("spellAnimation", FieldDescription(((char *)&h.spellAnimation) - ((char *)&h), animationId).SetReferenced().SetDescription("the animation played for magical attacks"));
+       td.AddField("meleeAnimation", FieldDescription(((char *)&h.meleeAnimation) - ((char *)&h), animationId).SetReferenced().SetDescription("the animation played on attacked monsters when the hero has no weapon"));
 
-       td.AddField("mapEntity", FieldDescription(((char *)&h.mapEntity) - ((char *)&h), entityId, false));
+       td.AddField("mapEntity", FieldDescription(((char *)&h.mapEntity) - ((char *)&h), entityId).SetDescription("the entity representing the hero on maps"));
 }
 
 void Hero::Construct(void *data) {
 
        int targetsId(TypeDescription::GetTypeId("TargetingMode"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("Ikari"));
+       td.SetDescription(
+                       "Information of a single ikari attack.");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Ikari));
 
-       td.AddField("name", FieldDescription(((char *)&i.name) - ((char *)&i), stringId, true));
-       td.AddField("cost", FieldDescription(((char *)&i.cost) - ((char *)&i), numberId, false));
-       td.AddField("targets", FieldDescription(((char *)&i.targetingMode) - ((char *)&i), targetsId, false));
-       td.AddField("type", FieldDescription(((char *)&i.isPhysical) - ((char *)&i), boolId, false));
+       td.AddField("name", FieldDescription(((char *)&i.name) - ((char *)&i), stringId).SetReferenced().SetDescription("the attack's name"));
+       td.AddField("cost", FieldDescription(((char *)&i.cost) - ((char *)&i), numberId).SetDescription("amount of ikari points needed and deducted for use"));
+       td.AddField("targets", FieldDescription(((char *)&i.targetingMode) - ((char *)&i), targetsId).SetDescription("how target selection is to be performed"));
+       td.AddField("type", FieldDescription(((char *)&i.isPhysical) - ((char *)&i), boolId).SetDescription("if the attack is physical (true) or magical(false)"));
 }
 
 void Ikari::Construct(void *data) {
 
        int targetsId(TypeDescription::GetTypeId("TargetingMode"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("Item"));
+       td.SetDescription("All data of an item (soon).");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Item));
 
-       td.AddField("name", FieldDescription(((char *)&i.name) - ((char *)&i), stringId, true));
-       td.AddField("menuicon", FieldDescription(((char *)&i.menuIcon) - ((char *)&i), spriteId, true));
+       td.AddField("name", FieldDescription(((char *)&i.name) - ((char *)&i), stringId).SetReferenced().SetDescription("the item's name"));
+       td.AddField("menuicon", FieldDescription(((char *)&i.menuIcon) - ((char *)&i), spriteId).SetReferenced().SetDescription("icon that is displayed in menus"));
 
-       td.AddField("mostUseful", FieldDescription(((char *)&i.mostUseful) - ((char *)&i), boolId, false));
-       td.AddField("equipable", FieldDescription(((char *)&i.equipable) - ((char *)&i), boolId, false));
-       td.AddField("cursed", FieldDescription(((char *)&i.cursed) - ((char *)&i), boolId, false));
-       td.AddField("fruit", FieldDescription(((char *)&i.fruit) - ((char *)&i), boolId, false));
-       td.AddField("scenario", FieldDescription(((char *)&i.scenario) - ((char *)&i), boolId, false));
-       td.AddField("status", FieldDescription(((char *)&i.status) - ((char *)&i), boolId, false));
-       td.AddField("battle", FieldDescription(((char *)&i.battle) - ((char *)&i), boolId, false));
+       td.AddField("mostUseful", FieldDescription(((char *)&i.mostUseful) - ((char *)&i), boolId));
+       td.AddField("equipable", FieldDescription(((char *)&i.equipable) - ((char *)&i), boolId));
+       td.AddField("cursed", FieldDescription(((char *)&i.cursed) - ((char *)&i), boolId));
+       td.AddField("fruit", FieldDescription(((char *)&i.fruit) - ((char *)&i), boolId));
+       td.AddField("scenario", FieldDescription(((char *)&i.scenario) - ((char *)&i), boolId));
+       td.AddField("status", FieldDescription(((char *)&i.status) - ((char *)&i), boolId));
+       td.AddField("battle", FieldDescription(((char *)&i.battle) - ((char *)&i), boolId).SetDescription("if the item can be used in battle"));
 
-       td.AddField("targets", FieldDescription(((char *)&i.targettingMode) - ((char *)&i), targetsId, false));
-       td.AddField("ikari", FieldDescription(((char *)&i.ikari) - ((char *)&i), ikariId, true));
-       td.AddField("attackanimation", FieldDescription(((char *)&i.attackAnimation) - ((char *)&i), animationId, true));
+       td.AddField("targets", FieldDescription(((char *)&i.targettingMode) - ((char *)&i), targetsId).SetDescription("how target selection is to be performed"));
+       td.AddField("ikari", FieldDescription(((char *)&i.ikari) - ((char *)&i), ikariId).SetReferenced().SetDescription("ikari attack of the item (sensible only for equipment)"));
+       td.AddField("attackanimation", FieldDescription(((char *)&i.attackAnimation) - ((char *)&i), animationId).SetReferenced().SetDescription("animation that is run when the item is used for attacking"));
 }
 
 void Item::Construct(void *data) {
 
        int targetsId(TypeDescription::GetTypeId("TargetingMode"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("Spell"));
+       td.SetDescription("All data about a spell (soon).");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Spell));
 
-       td.AddField("name", FieldDescription(((char *)&s.name) - ((char *)&s), stringId, true));
-       td.AddField("cost", FieldDescription(((char *)&s.cost) - ((char *)&s), numberId, false));
-       td.AddField("targets", FieldDescription(((char *)&s.targetingMode) - ((char *)&s), targetsId, false));
-       td.AddField("status", FieldDescription(((char *)&s.status) - ((char *)&s), boolId, false));
-       td.AddField("battle", FieldDescription(((char *)&s.battle) - ((char *)&s), boolId, false));
+       td.AddField("name", FieldDescription(((char *)&s.name) - ((char *)&s), stringId).SetReferenced().SetDescription("the spell's name"));
+       td.AddField("cost", FieldDescription(((char *)&s.cost) - ((char *)&s), numberId).SetDescription("Amount of magic points needed and deducted for invocation"));
+       td.AddField("targets", FieldDescription(((char *)&s.targetingMode) - ((char *)&s), targetsId).SetDescription("how target selection is to be performed"));
+       td.AddField("status", FieldDescription(((char *)&s.status) - ((char *)&s), boolId).SetDescription("if the spell can be used at the status screen"));
+       td.AddField("battle", FieldDescription(((char *)&s.battle) - ((char *)&s), boolId).SetDescription("if the spell can be used in battle"));
 }
 
 void Spell::Construct(void *data) {
 
        int numberId(TypeDescription::GetTypeId("Number"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("Stats"));
+       td.SetDescription("Attributes of a battle's participant.");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Stats));
 
-       td.AddField("atp", FieldDescription(((char *)&s.attack) - ((char *)&s), numberId, false));
-       td.AddField("dfp", FieldDescription(((char *)&s.defense) - ((char *)&s), numberId, false));
-       td.AddField("str", FieldDescription(((char *)&s.strength) - ((char *)&s), numberId, false));
-       td.AddField("agl", FieldDescription(((char *)&s.agility) - ((char *)&s), numberId, false));
-       td.AddField("int", FieldDescription(((char *)&s.intelligence) - ((char *)&s), numberId, false));
-       td.AddField("gut", FieldDescription(((char *)&s.gut) - ((char *)&s), numberId, false));
-       td.AddField("mgr", FieldDescription(((char *)&s.magicResistance) - ((char *)&s), numberId, false));
+       td.AddField("atp", FieldDescription(((char *)&s.attack) - ((char *)&s), numberId).SetDescription("attack points"));
+       td.AddField("dfp", FieldDescription(((char *)&s.defense) - ((char *)&s), numberId).SetDescription("defense points"));
+       td.AddField("str", FieldDescription(((char *)&s.strength) - ((char *)&s), numberId).SetDescription("strength"));
+       td.AddField("agl", FieldDescription(((char *)&s.agility) - ((char *)&s), numberId).SetDescription("agility"));
+       td.AddField("int", FieldDescription(((char *)&s.intelligence) - ((char *)&s), numberId).SetDescription("intelligence"));
+       td.AddField("gut", FieldDescription(((char *)&s.gut) - ((char *)&s), numberId).SetDescription("gut (ikari factor)"));
+       td.AddField("mgr", FieldDescription(((char *)&s.magicResistance) - ((char *)&s), numberId).SetDescription("magic resistance"));
 }
 
 void Stats::Construct(void *data) {
 
        int numberId(TypeDescription::GetTypeId("Number"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("TargetingMode"));
+       td.SetDescription("Specifies how selection of a target (e.g. for a spell) is performed.");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(TargetingMode));
 
-       td.AddField("faction", FieldDescription(((char *)&t.ally) - ((char *)&t), boolId, false));
-       td.AddField("mode", FieldDescription(((char *)&t.mode) - ((char *)&t), numberId, false));
+       td.AddField("faction", FieldDescription(((char *)&t.ally) - ((char *)&t), boolId).SetDescription("targetted faction; true for ally, false for enemy"));
+       td.AddField("mode", FieldDescription(((char *)&t.mode) - ((char *)&t), numberId).SetDescription("attack mode; 0 = all, 1 = multiple, 2 = single"));
 }
 
 void TargetingMode::Construct(void *data) {
 
 namespace graphics {
 
 void Animation::AddFields(TypeDescription &td, const Animation &a, std::ptrdiff_t offset, int boolId, int numberId, int spriteId) {
-       td.AddField("sprite", FieldDescription(((char *)&a.sprite) - ((char *)&a) - offset, spriteId, true));
-       td.AddField("frametime", FieldDescription(((char *)&a.frameTime) - ((char *)&a) - offset, numberId, false));
-       td.AddField("repeat", FieldDescription(((char *)&a.repeat) - ((char *)&a) - offset, boolId, false));
+       td.AddField("sprite", FieldDescription(((char *)&a.sprite) - ((char *)&a) - offset, spriteId).SetReferenced().SetDescription("the sprite used for cutting out frames"));
+       td.AddField("frametime", FieldDescription(((char *)&a.frameTime) - ((char *)&a) - offset, numberId).SetDescription("duration of a frame in miliseconds"));
+       td.AddField("repeat", FieldDescription(((char *)&a.repeat) - ((char *)&a) - offset, boolId).SetDescription("whether the animation should start over at the beginning after reaching the last frame"));
 }
 
 }
 
        int vectorId(TypeDescription::GetTypeId("Vector"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("ComplexAnimation"));
+       td.SetDescription("Complex animation type that supports per-frame disposition and non-linear sprite offset selection.");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(ComplexAnimation));
        td.AddSupertype(animationId, ((char *)a) - ((char *)&ca));
 
        Animation::AddFields(td, ca, ((char *)a) - ((char *)&ca), boolId, numberId, spriteId);
-       td.AddField("frames", FieldDescription(((char *)&ca.frames) - ((char *)&ca), frameId, true, true));
+       td.AddField("frames", FieldDescription(((char *)&ca.frames) - ((char *)&ca), frameId).SetReferenced().SetAggregate().SetDescription("a variable number of frames"));
 
 
        FrameProp fp;
 
        TypeDescription &ftd(TypeDescription::CreateOrGet("ComplexAnimationFrame"));
+       ftd.SetDescription("Information about how a frame of a complex animation should be rendered.");
        ftd.SetSize(sizeof(FrameProp));
 
-       ftd.AddField("column", FieldDescription(((char *)&fp.col) - ((char *)&fp), numberId, false));
-       ftd.AddField("row", FieldDescription(((char *)&fp.row) - ((char *)&fp), numberId, false));
-       ftd.AddField("disposition", FieldDescription(((char *)&fp.disposition) - ((char *)&fp), vectorId, false));
+       ftd.AddField("column", FieldDescription(((char *)&fp.col) - ((char *)&fp), numberId).SetDescription("the column of the sprite that will be drawn"));
+       ftd.AddField("row", FieldDescription(((char *)&fp.row) - ((char *)&fp), numberId).SetDescription("the row of the sprite that will be drawn"));
+       ftd.AddField("disposition", FieldDescription(((char *)&fp.disposition) - ((char *)&fp), vectorId).SetDescription("offset from the original drawing position"));
 }
 
 void ComplexAnimation::Construct(void *data) {
 
        int spriteId(TypeDescription::GetTypeId("Sprite"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("Font"));
+       td.SetDescription(
+                       "Simple font with fixed-width characters using a sprite for rendering.\n"
+                       "Characters from strings are mapped as follows:\n"
+                       "<pre>sprite column = column offset + (character % 16)\n"
+                       "sprite row    = row    offset + (character / 16)</pre>");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Font));
 
-       td.AddField("sprite", FieldDescription(((char *)&f.sprite) - ((char *)&f), spriteId, true));
-       td.AddField("columnoffset", FieldDescription(((char *)&f.colOffset) - ((char *)&f), numberId, false));
-       td.AddField("rowoffset", FieldDescription(((char *)&f.rowOffset) - ((char *)&f), numberId, false));
+       td.AddField("sprite", FieldDescription(((char *)&f.sprite) - ((char *)&f), spriteId).SetReferenced().SetDescription("a sprite where each tile corresponds to a character"));
+       td.AddField("columnoffset", FieldDescription(((char *)&f.colOffset) - ((char *)&f), numberId).SetDescription("offset of the column of the first character"));
+       td.AddField("rowoffset", FieldDescription(((char *)&f.rowOffset) - ((char *)&f), numberId).SetDescription("offset of the row of the first character"));
 }
 
 void Font::Construct(void *data) {
 
        int vectorId(TypeDescription::GetTypeId("Vector"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("Frame"));
+       td.SetDescription(
+                       "A frame is basically a border + a background texture.\n"
+                       "It splits an image into 3*3 parts where the edges are kept as is and the sides and the middle part are repeated as needed.");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Frame));
 
-       td.AddField("image", FieldDescription(((char *)&f.surface) - ((char *)&f), imageId, true));
-       td.AddField("border", FieldDescription(((char *)&f.borderSize) - ((char *)&f), vectorId, false));
-       td.AddField("repeat", FieldDescription(((char *)&f.repeatSize) - ((char *)&f), vectorId, false));
-       td.AddField("offset", FieldDescription(((char *)&f.offset) - ((char *)&f), vectorId, false));
+       td.AddField("image", FieldDescription(((char *)&f.surface) - ((char *)&f), imageId).SetReferenced().SetDescription("the underlying graphic from which the frame parts are cut"));
+       td.AddField("border", FieldDescription(((char *)&f.borderSize) - ((char *)&f), vectorId).SetDescription("size of the border part, dimensions of top-left corner"));
+       td.AddField("repeat", FieldDescription(((char *)&f.repeatSize) - ((char *)&f), vectorId).SetDescription("size of the repeat part, dimensions of a single tile of the background texture"));
+       td.AddField("offset", FieldDescription(((char *)&f.offset) - ((char *)&f), vectorId).SetDescription("offset into the image where to start cutting, coordinates of the top-left corner on the image"));
 }
 
 void Frame::Construct(void *data) {
 
        int vectorId(TypeDescription::GetTypeId("Vector"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("Gauge"));
+       td.SetDescription(
+                       "Gauges display a percentage by filling the left part different than the right.\n"
+                       "The fill level is only mapped with repeat.\n"
+                       "Start is filled if the level in greater than zero, end is filled if the level is at its maximum.");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Gauge));
 
-       td.AddField("image", FieldDescription(((char *)&g.surface) - ((char *)&g), imageId, true));
-       td.AddField("full", FieldDescription(((char *)&g.fullOffset) - ((char *)&g), vectorId, false));
-       td.AddField("empty", FieldDescription(((char *)&g.emptyOffset) - ((char *)&g), vectorId, false));
-       td.AddField("height", FieldDescription(((char *)&g.height) - ((char *)&g), numberId, false));
-       td.AddField("start", FieldDescription(((char *)&g.startWidth) - ((char *)&g), numberId, false));
-       td.AddField("repeat", FieldDescription(((char *)&g.repeatWidth) - ((char *)&g), numberId, false));
-       td.AddField("end", FieldDescription(((char *)&g.endWidth) - ((char *)&g), numberId, false));
+       td.AddField("image", FieldDescription(((char *)&g.surface) - ((char *)&g), imageId).SetReferenced().SetDescription("the underlying graphic from which the gauge parts are cut"));
+       td.AddField("full", FieldDescription(((char *)&g.fullOffset) - ((char *)&g), vectorId).SetDescription("top-left corner of the filled gauge"));
+       td.AddField("empty", FieldDescription(((char *)&g.emptyOffset) - ((char *)&g), vectorId).SetDescription("top-left corner of the empty gauge"));
+       td.AddField("height", FieldDescription(((char *)&g.height) - ((char *)&g), numberId).SetDescription("height of the gauges"));
+       td.AddField("start", FieldDescription(((char *)&g.startWidth) - ((char *)&g), numberId).SetDescription("width of the start part"));
+       td.AddField("repeat", FieldDescription(((char *)&g.repeatWidth) - ((char *)&g), numberId).SetDescription("width of the repeat part"));
+       td.AddField("end", FieldDescription(((char *)&g.endWidth) - ((char *)&g), numberId).SetDescription("width of the end part"));
 }
 
 void Gauge::Construct(void *data) {
 
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(MenuProperties));
 
-       td.AddField("font", FieldDescription(((char *)&p.font) - ((char *)&p), fontId, true));
-       td.AddField("disabledFont", FieldDescription(((char *)&p.disabledFont) - ((char *)&p), fontId, true));
-       td.AddField("cursor", FieldDescription(((char *)&p.cursor) - ((char *)&p), spriteId, true));
-       td.AddField("charsPerEntry", FieldDescription(((char *)&p.charsPerEntry) - ((char *)&p), numberId, false));
-       td.AddField("rows", FieldDescription(((char *)&p.rows) - ((char *)&p), numberId, false));
-       td.AddField("rowGap", FieldDescription(((char *)&p.rowGap) - ((char *)&p), numberId, false));
-       td.AddField("iconSpace", FieldDescription(((char *)&p.iconSpace) - ((char *)&p), numberId, false));
-       td.AddField("cols", FieldDescription(((char *)&p.cols) - ((char *)&p), numberId, false));
-       td.AddField("colGap", FieldDescription(((char *)&p.colGap) - ((char *)&p), numberId, false));
-       td.AddField("delimiter", FieldDescription(((char *)&p.delimiter) - ((char *)&p), stringId, false));
-       td.AddField("charsPerNumber", FieldDescription(((char *)&p.charsPerNumber) - ((char *)&p), numberId, false));
-       td.AddField("charsPerAdditionalText", FieldDescription(((char *)&p.charsPerAdditionalText) - ((char *)&p), numberId, false));
-       td.AddField("additionalTextGap", FieldDescription(((char *)&p.additionalTextGap) - ((char *)&p), numberId, false));
+       td.AddField("font", FieldDescription(((char *)&p.font) - ((char *)&p), fontId).SetReferenced().SetDescription("the font to use for normal/enabled entries"));
+       td.AddField("disabledFont", FieldDescription(((char *)&p.disabledFont) - ((char *)&p), fontId).SetReferenced().SetDescription("the font for disabled entries"));
+       td.AddField("cursor", FieldDescription(((char *)&p.cursor) - ((char *)&p), spriteId).SetReferenced().SetDescription("the cursor sprite indicating the current selection"));
+       td.AddField("charsPerEntry", FieldDescription(((char *)&p.charsPerEntry) - ((char *)&p), numberId).SetDescription("width of an entry in characters"));
+       td.AddField("rows", FieldDescription(((char *)&p.rows) - ((char *)&p), numberId).SetDescription("number of visible rows"));
+       td.AddField("rowGap", FieldDescription(((char *)&p.rowGap) - ((char *)&p), numberId).SetDescription("space between rows in pixles"));
+       td.AddField("iconSpace", FieldDescription(((char *)&p.iconSpace) - ((char *)&p), numberId).SetDescription("space reserved for icons in pixels"));
+       td.AddField("cols", FieldDescription(((char *)&p.cols) - ((char *)&p), numberId).SetDescription("number of columns"));
+       td.AddField("colGap", FieldDescription(((char *)&p.colGap) - ((char *)&p), numberId).SetDescription("space between cols in pixels"));
+       td.AddField("delimiter", FieldDescription(((char *)&p.delimiter) - ((char *)&p), stringId).SetDescription("delimiter between text and number; only first character is used"));
+       td.AddField("charsPerNumber", FieldDescription(((char *)&p.charsPerNumber) - ((char *)&p), numberId).SetDescription("maximum width of a number in chars"));
+       td.AddField("charsPerAdditionalText", FieldDescription(((char *)&p.charsPerAdditionalText) - ((char *)&p), numberId).SetDescription("maximum number of additional text characters"));
+       td.AddField("additionalTextGap", FieldDescription(((char *)&p.additionalTextGap) - ((char *)&p), numberId).SetDescription("space between normal and additional text in pixels"));
 }
 
 void MenuProperties::Construct(void *data) {
 
        int spriteId(TypeDescription::GetTypeId("Sprite"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("SimpleAnimation"));
+       td.SetDescription("An animation that uses a fixed column and increasing row of a sprite based on the frame number.");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(SimpleAnimation));
        td.AddSupertype(animationId, ((char *)a) - ((char *)&sa));
 
        Animation::AddFields(td, sa, ((char *)a) - ((char *)&sa), boolId, numberId, spriteId);
-       td.AddField("framecount", FieldDescription(((char *)&sa.numFrames) - ((char *)&sa), numberId, false));
-       td.AddField("col", FieldDescription(((char *)&sa.col) - ((char *)&sa), numberId, false));
-       td.AddField("row", FieldDescription(((char *)&sa.row) - ((char *)&sa), numberId, false));
+       td.AddField("framecount", FieldDescription(((char *)&sa.numFrames) - ((char *)&sa), numberId).SetDescription("number of frames of a single run"));
+       td.AddField("col", FieldDescription(((char *)&sa.col) - ((char *)&sa), numberId).SetDescription("the column of the sprite to draw from"));
+       td.AddField("row", FieldDescription(((char *)&sa.row) - ((char *)&sa), numberId).SetDescription("the row of the sprite of the first frame"));
 }
 
 void SimpleAnimation::Construct(void *data) {
 
        int vectorId(TypeDescription::GetTypeId("Vector"));
 
        TypeDescription &td(TypeDescription::CreateOrGet("Sprite"));
+       td.SetDescription(
+                       "An image + a size and offset.\n"
+                       "The resulting section or a section offset by a multiple of its size can be drawn.");
        td.SetConstructor(&Construct);
        td.SetSize(sizeof(Sprite));
 
-       td.AddField("image", FieldDescription(((char *)&s.surface) - ((char *)&s), imageId, true));
-       td.AddField("size", FieldDescription(((char *)&s.size) - ((char *)&s), vectorId, false));
-       td.AddField("offset", FieldDescription(((char *)&s.offset) - ((char *)&s), vectorId, false));
+       td.AddField("image", FieldDescription(((char *)&s.surface) - ((char *)&s), imageId).SetReferenced().SetDescription("the image to cut this sprite from"));
+       td.AddField("size", FieldDescription(((char *)&s.size) - ((char *)&s), vectorId).SetDescription("dimensions of the sprite"));
+       td.AddField("offset", FieldDescription(((char *)&s.offset) - ((char *)&s), vectorId).SetDescription("offset into the image, top-left corner of the sprite's (0,0) clip"));
 }
 
 void Sprite::Construct(void *data) {
 
 void Interpreter::CreateTypeDescriptions() {
        {
                TypeDescription &td(TypeDescription::CreateOrGet("Boolean"));
+               td.SetDescription("Logical value which can be either true or false.");
                td.SetSize(sizeof(bool));
        }
        {
                TypeDescription &td(TypeDescription::CreateOrGet("Color"));
+               td.SetDescription(
+                               "A color in RGB format with an optional alpha channel.\n"
+                               "Components range from 0 to 255.\n"
+                               "Alpha defaults to 255 if omitted.");
                td.SetSize(sizeof(Color));
        }
        {
                TypeDescription &td(TypeDescription::CreateOrGet("Image"));
+               td.SetDescription("Path to a PNG file with image data.");
                td.SetSize(sizeof(SDL_Surface));
        }
        {
                TypeDescription &td(TypeDescription::CreateOrGet("Number"));
+               td.SetDescription("A signed integer.");
                td.SetSize(sizeof(int));
        }
        {
                int stringId(TypeDescription::GetTypeId("String"));
                TypeDescription &td(TypeDescription::CreateOrGet("Path"));
+               td.SetDescription("A path in the filesystem which is interpreted relative to the source file's location.");
                td.SetSize(1);
                td.AddSupertype(stringId, 0);
        }
        {
                TypeDescription &td(TypeDescription::CreateOrGet("String"));
+               td.SetDescription("Some characters.");
                td.SetSize(1);
        }
        {
                TypeDescription &td(TypeDescription::CreateOrGet("Vector"));
+               td.SetDescription("A pair of numbers usually describing a 2D translation or offset.");
                td.SetSize(sizeof(Vector<int>));
        }
 }
 
 
 #include "TypeDescription.h"
 
+#include <algorithm>
 #include <cassert>
 #include <cstring>
+#include <ostream>
 #include <stdexcept>
 
+using std::endl;
 using std::map;
 using std::string;
 using std::vector;
        return typeDescriptions[id];
 }
 
+
+void TypeDescription::WriteSourceWiki(std::ostream &out) {
+       vector<string> types;
+       for (vector<TypeDescription>::const_iterator i(typeDescriptions.begin()), end(typeDescriptions.end()); i != end; ++i) {
+               if (i->name != "Animation") {
+                       types.push_back(i->name);
+               }
+       }
+       std::sort(types.begin(), types.end());
+
+       out << "h2. Data types" << endl << endl;
+
+       for (vector<string>::const_iterator i(types.begin()), end(types.end()); i != end; ++i) {
+               out << "* [[LoaderSource#" << *i << "|" << *i << "]]" << endl;
+       }
+       out << endl << endl;
+
+       for (vector<string>::const_iterator i(types.begin()), end(types.end()); i != end; ++i) {
+               const TypeDescription &td(Get(GetTypeId(*i)));
+               out << "h3. " << td.TypeName() << endl << endl;
+
+               if (td.Description()) {
+                       out << td.Description() << endl << endl;
+               }
+
+               if (td.FieldsBegin() == td.FieldsEnd()) {
+                       out << "No properties." << endl << endl;
+               } else {
+                       out << "| *Property* | *Type* | *Description* |" << endl;
+                       for (FieldIterator field(td.FieldsBegin()); field != td.FieldsEnd(); ++field) {
+                               const FieldDescription &fd(field->second);
+                               out << "| " << field->first << " | ";
+                               if (fd.IsAggregate()) {
+                                       out << "Array<" << Get(fd.TypeId()).TypeName() << ">";
+                               } else {
+                                       out << Get(fd.TypeId()).TypeName();
+                               }
+                               out << " | ";
+                               if (fd.Description()) {
+                                       out << fd.Description();
+                               }
+                               out << " |" << endl;
+                       }
+                       out << endl;
+               }
+       }
+}
+
 }
 
 #ifndef LOADER_TYPEDESCRIPTION_H_
 #define LOADER_TYPEDESCRIPTION_H_
 
+#include <iosfwd>
 #include <map>
 #include <memory>
 #include <string>
 class FieldDescription {
 
 public:
-       FieldDescription(std::ptrdiff_t offset, int type, bool reference = true, bool aggregate = false)
-       : offset(offset), type(type), reference(reference), aggregate(aggregate) { }
+       FieldDescription(std::ptrdiff_t offset, int type)
+       : description(0), offset(offset), type(type), reference(false), aggregate(false) { }
 
        std::ptrdiff_t Offset() const { return offset; };
        int TypeId() const { return type; }
        bool IsReferenced() const { return reference; }
        bool IsAggregate() const { return aggregate; }
+       const char *Description() const { return description; }
+
+       FieldDescription &SetReferenced() { reference = true; return *this; }
+       FieldDescription &SetAggregate() { aggregate = true; return *this; }
+       FieldDescription &SetDescription(const char *d) { description = d; return *this; }
 
 private:
+       const char *description;
        std::ptrdiff_t offset;
        int type;
        bool reference;
        void SetSize(int s) { size = s; }
        int Size() const { return size; }
 
+       void SetDescription(const char *d) { description = d; }
+       const char *Description() const { return description; }
+
        typedef std::map<std::string, FieldDescription>::const_iterator FieldIterator;
        FieldIterator FieldsBegin() const { return fields.begin(); }
        FieldIterator FieldsEnd() const { return fields.end(); }
        static int GetTypeId(const std::string &);
        static const TypeDescription &Get(int id);
 
+       static void WriteSourceWiki(std::ostream &);
+
 private:
-       TypeDescription(int id, const std::string &name) : constructor(0), loader(0), name(name), id(id), size(0) { }
+       TypeDescription(int id, const std::string &name) : constructor(0), loader(0), description(0), name(name), id(id), size(0) { }
 
 private:
        void (*constructor)(void *);
        void (*loader)(void *);
+       const char *description;
        std::string name;
        std::map<std::string, FieldDescription> fields;
        std::map<int, std::ptrdiff_t> supertypes;
 
        const int tileSize = 32;
        const float walkSpeed = 128.0f;
 
-       const bool battle(false);
+       bool battle(false);
 
 //     std::srand(std::time(0));
 
                        Parser(*i, source).Parse();
                }
 
-               switch (args.DetectRunLevel()) {
+               switch (args.GetRunLevel()) {
                        case Arguments::WRITE:
                        {
                                int length(std::strlen(args.OutfilePath()));
                                std::cout << source << std::endl;
                                return 0;
                        }
+                       case Arguments::SOURCE_WIKI: {
+                               TypeDescription::WriteSourceWiki(std::cout);
+                               return 0;
+                       }
+                       case Arguments::BATTLE:
+                               battle = true;
+                               break;
                        case Arguments::PLAY:
+                       case Arguments::MAP:
                                break;
                }
 
 
        td.SetLoader(&Load);
        td.SetSize(sizeof(Entity));
 
-       td.AddField("animation", FieldDescription(((char *)&e.animation) - ((char *)&e), animationId, true));
-       td.AddField("spriteOffset", FieldDescription(((char *)&e.spriteOffset) - ((char *)&e), vectorId, false));
+       td.AddField("animation", FieldDescription(((char *)&e.animation) - ((char *)&e), animationId).SetReferenced());
+       td.AddField("spriteOffset", FieldDescription(((char *)&e.spriteOffset) - ((char *)&e), vectorId));
 }
 
 void Entity::Construct(void *data) {