コード例 #1
0
ファイル: DLLModGen.cs プロジェクト: End-User-Person/sa_tools
        public static DllIniData LoadMultiINI(List <string> fileName,
                                              ref Dictionary <string, bool> defaultExportState)
        {
            defaultExportState.Clear();
            DllIniData             newIniData = new DllIniData();
            List <DllDataItemInfo> curItems   = new List <DllDataItemInfo>();

            foreach (string arrFile in fileName)
            {
                DllIniData IniData = IniSerializer.Deserialize <DllIniData>(arrFile);

                Environment.CurrentDirectory = Path.GetDirectoryName(arrFile);

                foreach (KeyValuePair <string, FileTypeHash> item in IniData.Files)
                {
                    bool modified = HelperFunctions.FileHash(item.Key) != item.Value.Hash;
                    defaultExportState.Add(item.Key, modified);
                }

                foreach (DllDataItemInfo item in IniData.DataItems)
                {
                    CheckItems(item, IniData, ref defaultExportState);

                    curItems.Add(item);
                }
            }
            newIniData.DataItems = curItems;

            return(newIniData);
        }
コード例 #2
0
ファイル: ManualBuildWindow.cs プロジェクト: Sewer56/sa_tools
        private void LoadIniFiles()
        {
            assemblyIniFiles.Clear();
            assemblyItemsToExport.Clear();

            foreach (KeyValuePair <string, AssemblyType> assembly in assemblies)
            {
                string iniPath = Path.Combine(projectFolder, assembly.Key + "_data.ini");
                Dictionary <string, bool> itemsToExport = new Dictionary <string, bool>();

                switch (assembly.Value)
                {
                case AssemblyType.Exe:
                    SA_Tools.IniData iniData = StructConverter.StructConverter.LoadINI(iniPath, ref itemsToExport);
                    assemblyItemsToExport.Add(assembly.Key, itemsToExport);
                    assemblyIniFiles.Add(assembly.Key, iniData);
                    break;

                case AssemblyType.DLL:
                    DLLModGenerator.DllIniData dllIniData = DLLModGenerator.DLLModGen.LoadINI(iniPath, ref itemsToExport);
                    assemblyItemsToExport.Add(assembly.Key, itemsToExport);
                    assemblyIniFiles.Add(assembly.Key, dllIniData);
                    break;

                default:
                    break;
                }
            }
        }
コード例 #3
0
ファイル: DLLModGen.cs プロジェクト: End-User-Person/sa_tools
        public static void ExportINI(DllIniData IniData,
                                     Dictionary <string, bool> itemsToExport, string fileName)
        {
            string     dstfol = Path.GetDirectoryName(fileName);
            DllIniData output = new DllIniData()
            {
                Name     = IniData.Name,
                Game     = IniData.Game,
                Exports  = IniData.Exports,
                TexLists = IniData.TexLists
            };
            List <string> labels = new List <string>();

            foreach (KeyValuePair <string, FileTypeHash> item in
                     IniData.Files.Where(i => itemsToExport[i.Key]))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(Path.Combine(dstfol, item.Key)));
                File.Copy(item.Key, Path.Combine(dstfol, item.Key), true);
                switch (item.Value.Type)
                {
                case "landtable":
                    LandTable tbl = LandTable.LoadFromFile(item.Key);
                    labels.AddRange(tbl.GetLabels());
                    break;

                case "model":
                case "basicmodel":
                case "chunkmodel":
                case "gcmodel":
                case "basicdxmodel":
                    NJS_OBJECT mdl = new ModelFile(item.Key).Model;
                    labels.AddRange(mdl.GetLabels());
                    break;

                case "animation":
                    NJS_MOTION ani = NJS_MOTION.Load(item.Key);
                    labels.Add(ani.Name);
                    break;
                }
                output.Files.Add(item.Key, new FileTypeHash(item.Value.Type, null));
            }
            output.Items = new List <DllItemInfo>(IniData.Items.Where(a => labels.Contains(a.Label)));
            foreach (var item in IniData.DataItems.Where(i => itemsToExport[i.Filename]))
            {
                Directory.CreateDirectory(Path.Combine(dstfol, item.Filename));
                CopyDirectory(new DirectoryInfo(item.Filename), Path.Combine(dstfol, item.Filename));
                output.DataItems.Add(item);
            }
            IniSerializer.Serialize(output, fileName);
        }
コード例 #4
0
        public static DllIniData LoadINI(string fileName,
                                         ref Dictionary <string, bool> defaultExportState)
        {
            defaultExportState.Clear();

            DllIniData IniData = IniSerializer.Deserialize <DllIniData>(fileName);

            Environment.CurrentDirectory = Path.GetDirectoryName(fileName);

            foreach (KeyValuePair <string, FileTypeHash> item in IniData.Files)
            {
                bool modified = HelperFunctions.FileHash(item.Key) != item.Value.Hash;
                defaultExportState.Add(item.Key, modified);
            }

            return(IniData);
        }
コード例 #5
0
ファイル: ManualBuildWindow.cs プロジェクト: Sewer56/sa_tools
        private void FillListViewDLLIniData(ListView listView, AssemblyType assemblyType, string assemblyName,
                                            DLLModGenerator.DllIniData iniData, Dictionary <string, bool> itemsToExport)
        {
            listView.BeginUpdate();
            listView.Items.Clear();

            foreach (KeyValuePair <string, DLLModGenerator.FileTypeHash> item in iniData.Files)
            {
                KeyValuePair <string, bool> exportStatus = itemsToExport.First(export => export.Key == item.Key);

                bool modified = exportStatus.Value;

                listView.Items.Add(new ListViewItem(new[] { item.Key, modified ? "Yes" : "No" })
                {
                    Checked = modified
                });;
            }

            listView.EndUpdate();
        }
コード例 #6
0
ファイル: DLLModGenUI.cs プロジェクト: inrg/sa_tools
		private void LoadINIFile(string fileName)
		{
			IniData = DLLModGen.LoadINI(fileName, ref itemsToExport);
			UpdateListView();
		}
コード例 #7
0
ファイル: DLLModGen.cs プロジェクト: End-User-Person/sa_tools
        private static void CheckItems(DllDataItemInfo item, DllIniData iniData, ref Dictionary <string, bool> defaultExportState)
        {
            bool modified = false;

            switch (item.Type)
            {
            case "animindexlist":
            {
                Dictionary <int, string> hashes = new Dictionary <int, string>();
                foreach (var hash in item.MD5Hash.Split('|').Select(a =>
                    {
                        string[] b = a.Split(':');
                        return(int.Parse(b[0], NumberFormatInfo.InvariantInfo), b[1]);
                    }))
                {
                    hashes.Add(hash.Item1, hash.Item2);
                }
                foreach (var fn in Directory.GetFiles(item.Filename, "*.saanim"))
                {
                    if (int.TryParse(Path.GetFileNameWithoutExtension(fn), out int i))
                    {
                        if (!hashes.ContainsKey(i) || HelperFunctions.FileHash(fn) != hashes[i])
                        {
                            modified = true;
                            break;
                        }
                        hashes.Remove(i);
                    }
                }
                if (hashes.Count > 0)
                {
                    modified = true;
                }
            }
            break;

            case "charaobjectdatalist":
            {
                Dictionary <string, string> hashes = new Dictionary <string, string>();
                foreach (var hash in item.MD5Hash.Split('|').Select(a =>
                    {
                        string[] b = a.Split(':');
                        return(b[0], b[1]);
                    }))
                {
                    hashes.Add(hash.Item1, hash.Item2);
                }
                foreach (var fp in Directory.GetFiles(item.Filename, "*.sa2mdl").Concat(Directory.GetFiles(item.Filename, "*.saanim")).Append(Path.Combine(item.Filename, "info.ini")))
                {
                    string fn = Path.GetFileName(fp);
                    if (!hashes.ContainsKey(fn) || HelperFunctions.FileHash(fp) != hashes[fn])
                    {
                        modified = true;
                        break;
                    }
                    hashes.Remove(fn);
                }
                if (hashes.Count > 0)
                {
                    modified = true;
                }
            }
            break;

            case "kartspecialinfolist":
            {
                Dictionary <string, string> hashes = new Dictionary <string, string>();
                foreach (var hash in item.MD5Hash.Split('|').Select(a =>
                    {
                        string[] b = a.Split(':');
                        return(b[0], b[1]);
                    }))
                {
                    hashes.Add(hash.Item1, hash.Item2);
                }
                foreach (var fp in Directory.GetFiles(item.Filename, "*.sa2mdl").Append(Path.Combine(item.Filename, "info.ini")))
                {
                    string fn = Path.GetFileName(fp);
                    if (!hashes.ContainsKey(fn) || HelperFunctions.FileHash(fp) != hashes[fn])
                    {
                        modified = true;
                        break;
                    }
                    hashes.Remove(fn);
                }
                if (hashes.Count > 0)
                {
                    modified = true;
                }
            }
            break;

            case "kartmodelsarray":
            {
                Dictionary <string, string> hashes = new Dictionary <string, string>();
                foreach (var hash in item.MD5Hash.Split('|').Select(a =>
                    {
                        string[] b = a.Split(':');
                        return(b[0], b[1]);
                    }))
                {
                    hashes.Add(hash.Item1, hash.Item2);
                }
                foreach (var fp in Directory.GetFiles(item.Filename, "*.sa2bmdl").Concat(Directory.GetFiles(item.Filename, "*.sa1mdl")).Append(Path.Combine(item.Filename, "info.ini")))
                {
                    string fn = Path.GetFileName(fp);
                    if (!hashes.ContainsKey(fn) || HelperFunctions.FileHash(fp) != hashes[fn])
                    {
                        modified = true;
                        break;
                    }
                    hashes.Remove(fn);
                }
                if (hashes.Count > 0)
                {
                    modified = true;
                }
            }
            break;

            case "motiontable":
            {
                Dictionary <string, string> hashes = new Dictionary <string, string>();
                foreach (var hash in item.MD5Hash.Split('|').Select(a =>
                    {
                        string[] b = a.Split(':');
                        return(b[0], b[1]);
                    }))
                {
                    hashes.Add(hash.Item1, hash.Item2);
                }
                foreach (var fp in Directory.GetFiles(item.Filename, "*.saanim").Append(Path.Combine(item.Filename, "info.ini")))
                {
                    string fn = Path.GetFileName(fp);
                    if (!hashes.ContainsKey(fn) || HelperFunctions.FileHash(fp) != hashes[fn])
                    {
                        modified = true;
                        break;
                    }
                    hashes.Remove(fn);
                }
                if (hashes.Count > 0)
                {
                    modified = true;
                }
            }
            break;
            }
            defaultExportState.Add(item.Filename, modified);
        }
コード例 #8
0
ファイル: DLLModGen.cs プロジェクト: End-User-Person/sa_tools
        public static void ExportCPP(DllIniData IniData,
                                     Dictionary <string, bool> itemsToExport, string fileName)
        {
            using (TextWriter writer = File.CreateText(fileName))
            {
                bool            SA2      = IniData.Game == SA_Tools.SplitDLL.Game.SA2B;
                ModelFormat     modelfmt = SA2 ? ModelFormat.Chunk : ModelFormat.BasicDX;
                LandTableFormat landfmt  = SA2 ? LandTableFormat.SA2 : LandTableFormat.SADX;
                writer.WriteLine("// Generated by SA Tools DLL Mod Generator");
                writer.WriteLine();
                if (SA2)
                {
                    writer.WriteLine("#include \"SA2ModLoader.h\"");
                }
                else
                {
                    writer.WriteLine("#include \"SADXModLoader.h\"");
                }
                writer.WriteLine();
                List <string>             labels   = new List <string>();
                Dictionary <string, uint> texlists = new Dictionary <string, uint>();
                foreach (KeyValuePair <string, FileTypeHash> item in
                         IniData.Files.Where(i => itemsToExport[i.Key]))
                {
                    switch (item.Value.Type)
                    {
                    case "landtable":
                        LandTable tbl = LandTable.LoadFromFile(item.Key);
                        texlists.Add(tbl.Name, tbl.TextureList);
                        tbl.ToStructVariables(writer, landfmt, new List <string>());
                        labels.AddRange(tbl.GetLabels());
                        break;

                    case "model":
                        NJS_OBJECT mdl = new ModelFile(item.Key).Model;
                        mdl.ToStructVariables(writer, modelfmt == ModelFormat.BasicDX, new List <string>());
                        labels.AddRange(mdl.GetLabels());
                        break;

                    case "basicmodel":
                    case "chunkmodel":
                    case "gcmodel":
                        mdl = new ModelFile(item.Key).Model;
                        mdl.ToStructVariables(writer, false, new List <string>());
                        labels.AddRange(mdl.GetLabels());
                        break;

                    case "basicdxmodel":
                        mdl = new ModelFile(item.Key).Model;
                        mdl.ToStructVariables(writer, true, new List <string>());
                        labels.AddRange(mdl.GetLabels());
                        break;

                    case "animation":
                        NJS_MOTION ani = NJS_MOTION.Load(item.Key);
                        ani.ToStructVariables(writer);
                        labels.Add(ani.Name);
                        break;
                    }
                    writer.WriteLine();
                }
                foreach (var item in IniData.DataItems.Where(i => itemsToExport[i.Filename]))
                {
                    switch (item.Type)
                    {
                    case "animindexlist":
                    {
                        SortedDictionary <short, NJS_MOTION> anims = new SortedDictionary <short, NJS_MOTION>();
                        foreach (string file in Directory.GetFiles(item.Filename, "*.saanim"))
                        {
                            if (short.TryParse(Path.GetFileNameWithoutExtension(file), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out short i))
                            {
                                anims.Add(i, NJS_MOTION.Load(file));
                            }
                        }
                        foreach (KeyValuePair <short, NJS_MOTION> obj in anims)
                        {
                            obj.Value.ToStructVariables(writer);
                            writer.WriteLine();
                        }
                        writer.WriteLine("AnimationIndex {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(anims.Count);
                        foreach (KeyValuePair <short, NJS_MOTION> obj in anims)
                        {
                            objs.Add($"{{ {obj.Key}, {obj.Value.ModelParts}, &{obj.Value.Name} }}");
                        }
                        objs.Add("{ -1 }");
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;

                    case "charaobjectdatalist":
                    {
                        foreach (string file in Directory.GetFiles(item.Filename, "*.sa2mdl"))
                        {
                            new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>());
                            writer.WriteLine();
                        }
                        foreach (string file in Directory.GetFiles(item.Filename, "*.saanim"))
                        {
                            NJS_MOTION.Load(file).ToStructVariables(writer);
                            writer.WriteLine();
                        }
                        var data = IniSerializer.Deserialize <CharaObjectData[]>(Path.Combine(item.Filename, "info.ini"));
                        writer.WriteLine("CharaObjectData {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(data.Length);
                        foreach (var obj in data)
                        {
                            objs.Add(obj.ToStruct());
                        }
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;

                    case "kartspecialinfolist":
                    {
                        foreach (string file in Directory.GetFiles(item.Filename, "*.sa2mdl"))
                        {
                            new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>());
                            writer.WriteLine();
                        }
                        var data = IniSerializer.Deserialize <KartSpecialInfo[]>(Path.Combine(item.Filename, "info.ini"));
                        writer.WriteLine("KartSpecialInfo {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(data.Length);
                        for (int i = 0; i < data.Length; i++)
                        {
                            KartSpecialInfo obj = data[i];
                            objs.Add(obj.ToStruct());
                            texlists.Add($"{item.Export}[{i}]", obj.TexList);
                        }
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;

                    case "kartmodelsarray":
                    {
                        foreach (string file in Directory.GetFiles(item.Filename, "*.sa2bmdl"))
                        {
                            new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>());
                            writer.WriteLine();
                        }
                        foreach (string file in Directory.GetFiles(item.Filename, "*.sa1mdl"))
                        {
                            new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>());
                            writer.WriteLine();
                        }
                        var data = IniSerializer.Deserialize <CharaObjectData[]>(Path.Combine(item.Filename, "info.ini"));
                        writer.WriteLine("KartModelsArray {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(data.Length);
                        foreach (var obj in data)
                        {
                            objs.Add(obj.ToStruct());
                        }
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;

                    case "motiontable":
                    {
                        foreach (string file in Directory.GetFiles(item.Filename, "*.saanim"))
                        {
                            NJS_MOTION.Load(file).ToStructVariables(writer);
                            writer.WriteLine();
                        }
                        var data = IniSerializer.Deserialize <MotionTableEntry[]>(Path.Combine(item.Filename, "info.ini"));
                        writer.WriteLine("MotionTableEntry {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(data.Length);
                        foreach (var obj in data)
                        {
                            objs.Add(obj.ToStruct());
                        }
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;
                    }
                }
                writer.WriteLine("extern \"C\" __declspec(dllexport) void __cdecl Init(const char *path, const HelperFunctions &helperFunctions)");
                writer.WriteLine("{");
                writer.WriteLine("\tHMODULE handle = GetModuleHandle(L\"{0}\");", IniData.Name);
                List <string> exports = new List <string>(IniData.Items.Where(item => labels.Contains(item.Label)).Select(item => item.Export).Distinct());
                foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key)))
                {
                    writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key);
                }
                foreach (DllItemInfo item in IniData.Items.Where(item => labels.Contains(item.Label)))
                {
                    if (typemap[IniData.Exports[item.Export]].EndsWith("**"))
                    {
                        writer.WriteLine("\t{0} = &{1};", item.ToString(), item.Label);
                    }
                    else
                    {
                        writer.WriteLine("\t*{0} = {1};", item.ToString(), item.Label);
                    }
                }
                foreach (var item in IniData.DataItems.Where(item => itemsToExport[item.Filename]))
                {
                    switch (item.Type)
                    {
                    case "animindexlist":
                    case "charaobjectdatalist":
                    case "kartspecialinfolist":
                    case "kartmodelsarray":
                        writer.WriteLine("\tHookExport(handle, \"{0}\", {0});", item.Export);
                        break;

                    default:
                        writer.WriteLine("\t{0}{1}_exp = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Type], item.Export);
                        writer.WriteLine("\t*{0}_exp = {0};", item.Export);
                        break;
                    }
                }
                if (texlists.Count > 0 && IniData.TexLists != null && IniData.TexLists.Items != null)
                {
                    exports = new List <string>(IniData.TexLists.Where(item => texlists.Values.Contains(item.Key)).Select(item => item.Value.Export).Distinct());
                    foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key)))
                    {
                        writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key);
                    }
                    foreach (KeyValuePair <string, uint> item in texlists.Where(item => IniData.TexLists.ContainsKey(item.Value)))
                    {
                        DllTexListInfo tex = IniData.TexLists[item.Value];
                        string         str;
                        if (tex.Index.HasValue)
                        {
                            str = $"{tex.Export}[{tex.Index.Value}]";
                        }
                        else
                        {
                            str = tex.Export;
                        }
                        writer.WriteLine("\t{0}.TexList = {1};", item.Key, str);
                    }
                }
                writer.WriteLine("}");
                writer.WriteLine();
                writer.WriteLine("extern \"C\" __declspec(dllexport) const ModInfo {0}ModInfo = {{ ModLoaderVer }};", SA2 ? "SA2" : "SADX");
            }
        }
コード例 #9
0
        public static DllIniData LoadINI(string fileName,
                                         ref Dictionary <string, bool> defaultExportState)
        {
            defaultExportState.Clear();

            DllIniData IniData = IniSerializer.Deserialize <DllIniData>(fileName);

            Environment.CurrentDirectory = Path.GetDirectoryName(fileName);

            foreach (KeyValuePair <string, FileTypeHash> item in IniData.Files)
            {
                bool modified = HelperFunctions.FileHash(item.Key) != item.Value.Hash;
                defaultExportState.Add(item.Key, modified);
            }

            foreach (var item in IniData.DataItems)
            {
                bool modified = false;
                switch (item.Type)
                {
                case "animindexlist":
                {
                    Dictionary <int, string> hashes = new Dictionary <int, string>();
                    foreach (var hash in item.MD5Hash.Split('|').Select(a =>
                        {
                            string[] b = a.Split(':');
                            return(int.Parse(b[0], System.Globalization.NumberFormatInfo.InvariantInfo), b[1]);
                        }))
                    {
                        hashes.Add(hash.Item1, hash.Item2);
                    }
                    foreach (var fn in Directory.GetFiles(item.Filename, "*.saanim"))
                    {
                        if (int.TryParse(Path.GetFileNameWithoutExtension(fn), out int i))
                        {
                            if (!hashes.ContainsKey(i) || HelperFunctions.FileHash(fn) != hashes[i])
                            {
                                modified = true;
                                break;
                            }
                            hashes.Remove(i);
                        }
                    }
                    if (hashes.Count > 0)
                    {
                        modified = true;
                    }
                }
                break;

                case "charaobjectdatalist":
                {
                    Dictionary <string, string> hashes = new Dictionary <string, string>();
                    foreach (var hash in item.MD5Hash.Split('|').Select(a =>
                        {
                            string[] b = a.Split(':');
                            return(b[0], b[1]);
                        }))
                    {
                        hashes.Add(hash.Item1, hash.Item2);
                    }
                    foreach (var fp in Directory.GetFiles(item.Filename, "*.sa2mdl").Concat(Directory.GetFiles(item.Filename, "*.saanim")).Append(Path.Combine(item.Filename, "info.ini")))
                    {
                        string fn = Path.GetFileName(fp);
                        if (!hashes.ContainsKey(fn) || HelperFunctions.FileHash(fp) != hashes[fn])
                        {
                            modified = true;
                            break;
                        }
                        hashes.Remove(fn);
                    }
                    if (hashes.Count > 0)
                    {
                        modified = true;
                    }
                }
                break;

                case "kartspecialinfolist":
                {
                    Dictionary <string, string> hashes = new Dictionary <string, string>();
                    foreach (var hash in item.MD5Hash.Split('|').Select(a =>
                        {
                            string[] b = a.Split(':');
                            return(b[0], b[1]);
                        }))
                    {
                        hashes.Add(hash.Item1, hash.Item2);
                    }
                    foreach (var fp in Directory.GetFiles(item.Filename, "*.sa2mdl").Append(Path.Combine(item.Filename, "info.ini")))
                    {
                        string fn = Path.GetFileName(fp);
                        if (!hashes.ContainsKey(fn) || HelperFunctions.FileHash(fp) != hashes[fn])
                        {
                            modified = true;
                            break;
                        }
                        hashes.Remove(fn);
                    }
                    if (hashes.Count > 0)
                    {
                        modified = true;
                    }
                }
                break;
                }
                defaultExportState.Add(item.Filename, modified);
            }

            return(IniData);
        }
コード例 #10
0
        public static void ExportCPP(DllIniData IniData,
                                     Dictionary <string, bool> itemsToExport, string fileName)
        {
            using (TextWriter writer = File.CreateText(fileName))
            {
                bool            SA2      = IniData.Game == Game.SA2B;
                ModelFormat     modelfmt = SA2 ? ModelFormat.Chunk : ModelFormat.BasicDX;
                LandTableFormat landfmt  = SA2 ? LandTableFormat.SA2 : LandTableFormat.SADX;
                writer.WriteLine("// Generated by SA Tools DLL Mod Generator");
                writer.WriteLine();
                if (SA2)
                {
                    writer.WriteLine("#include \"SA2ModLoader.h\"");
                }
                else
                {
                    writer.WriteLine("#include \"SADXModLoader.h\"");
                }
                writer.WriteLine();
                List <string>             labels   = new List <string>();
                Dictionary <string, uint> texlists = new Dictionary <string, uint>();
                foreach (KeyValuePair <string, FileTypeHash> item in
                         IniData.Files.Where(i => itemsToExport[i.Key]))
                {
                    switch (item.Value.Type)
                    {
                    case "landtable":
                        LandTable tbl = LandTable.LoadFromFile(item.Key);
                        texlists.Add(tbl.Name, tbl.TextureList);
                        tbl.ToStructVariables(writer, landfmt, new List <string>());
                        labels.AddRange(tbl.GetLabels());
                        break;

                    case "model":
                        NJS_OBJECT mdl = new ModelFile(item.Key).Model;
                        mdl.ToStructVariables(writer, modelfmt == ModelFormat.BasicDX, new List <string>());
                        labels.AddRange(mdl.GetLabels());
                        break;

                    case "basicmodel":
                    case "chunkmodel":
                        mdl = new ModelFile(item.Key).Model;
                        mdl.ToStructVariables(writer, false, new List <string>());
                        labels.AddRange(mdl.GetLabels());
                        break;

                    case "basicdxmodel":
                        mdl = new ModelFile(item.Key).Model;
                        mdl.ToStructVariables(writer, true, new List <string>());
                        labels.AddRange(mdl.GetLabels());
                        break;

                    case "animation":
                    case "animindex":
                        NJS_MOTION ani = NJS_MOTION.Load(item.Key);
                        ani.ToStructVariables(writer);
                        labels.Add(ani.Name);
                        break;
                    }
                    writer.WriteLine();
                }
                writer.WriteLine("extern \"C\" __declspec(dllexport) void __cdecl Init(const char *path, const HelperFunctions &helperFunctions)");
                writer.WriteLine("{");
                writer.WriteLine("\tHMODULE handle = GetModuleHandle(L\"{0}\");", IniData.Name);
                List <string> exports = new List <string>(IniData.Items.Where(item => labels.Contains(item.Label)).Select(item => item.Export).Distinct());
                foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key)))
                {
                    writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key);
                }
                foreach (DllItemInfo item in IniData.Items.Where(item => labels.Contains(item.Label)))
                {
                    writer.WriteLine("\t{0} = &{1};", item.ToString(), item.Label);
                }
                if (texlists.Count > 0 && IniData.TexLists != null && IniData.TexLists.Items != null)
                {
                    exports = new List <string>(IniData.TexLists.Where(item => texlists.Values.Contains(item.Key)).Select(item => item.Value.Export).Distinct());
                    foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key)))
                    {
                        writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key);
                    }
                    foreach (KeyValuePair <string, uint> item in texlists.Where(item => IniData.TexLists.ContainsKey(item.Value)))
                    {
                        DllTexListInfo tex = IniData.TexLists[item.Value];
                        string         str;
                        if (tex.Index.HasValue)
                        {
                            str = $"{tex.Export}[{tex.Index.Value}]";
                        }
                        else
                        {
                            str = tex.Export;
                        }
                        writer.WriteLine("\t{0}.TexList = {1};", item.Key, str);
                    }
                }
                writer.WriteLine("}");
                writer.WriteLine();
                writer.WriteLine("extern \"C\" __declspec(dllexport) const ModInfo {0}ModInfo = {{ ModLoaderVer }};", SA2 ? "SA2" : "SADX");
            }
        }