static void Main(string[] args) { Queue<string> argq = new Queue<string>(args); string inifilename; if (argq.Count > 0) { inifilename = argq.Dequeue(); Console.WriteLine("INI File: {0}", inifilename); } else { Console.Write("INI File: "); inifilename = Console.ReadLine(); } Dictionary<int, string> modelnames = IniSerializer.Deserialize<Dictionary<int, string>>(inifilename, inisettings); string mdlfilename; if (argq.Count > 0) { mdlfilename = argq.Dequeue(); Console.WriteLine("Model File: {0}", mdlfilename); } else { Console.Write("Model File: "); mdlfilename = Console.ReadLine(); } ModelFile model = new ModelFile(mdlfilename); NJS_OBJECT[] objects = model.Model.GetObjects(); string repmdlfilename; if (argq.Count > 0) { repmdlfilename = argq.Dequeue(); Console.WriteLine("Replacement Model File: {0}", repmdlfilename); } else { Console.Write("Replacement Model File: "); repmdlfilename = Console.ReadLine(); } ModelFile repmodel = new ModelFile(repmdlfilename); NJS_OBJECT[] repobjects = repmodel.Model.GetObjects(); if (objects.Length != repobjects.Length) Console.WriteLine("Models have different structures, the game may crash."); foreach (KeyValuePair<int, string> item in modelnames.ToList()) if (objects.Any((obj) => obj.Name == item.Value)) modelnames[item.Key] = repobjects[Array.IndexOf(objects, objects.Single((o) => o.Name == item.Value))].Name; ModelFile.CreateFile(mdlfilename, repmodel.Model, null, null, repmodel.Author, repmodel.Description, "replaceMDL", repmodel.Metadata, repmodel.Format); IniSerializer.Serialize(modelnames, inisettings, inifilename); }
private List<string> ExportCPP(TextWriter writer, bool SA2) { 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>(); foreach (KeyValuePair<string, FileTypeHash> item in IniData.Files.Where((a, i) => listView1.CheckedIndices.Contains(i))) switch (item.Value.Type) { case "landtable": LandTable tbl = LandTable.LoadFromFile(item.Key); writer.WriteLine(tbl.ToStructVariables(landfmt, new List<string>())); labels.AddRange(tbl.GetLabels()); break; case "model": SonicRetro.SAModel.NJS_OBJECT mdl = new ModelFile(item.Key).Model; writer.WriteLine(mdl.ToStructVariables(modelfmt == ModelFormat.BasicDX, new List<string>())); labels.AddRange(mdl.GetLabels()); break; case "basicmodel": case "chunkmodel": mdl = new ModelFile(item.Key).Model; writer.WriteLine(mdl.ToStructVariables(false, new List<string>())); labels.AddRange(mdl.GetLabels()); break; case "basicdxmodel": mdl = new ModelFile(item.Key).Model; writer.WriteLine(mdl.ToStructVariables(true, new List<string>())); labels.AddRange(mdl.GetLabels()); break; case "animation": Animation ani = Animation.Load(item.Key); writer.WriteLine(ani.ToStructVariables()); labels.Add(ani.Name); break; } return labels; }
private void button6_Click(object sender, EventArgs e) { using (SaveFileDialog fd = new SaveFileDialog() { DefaultExt = "ini", Filter = "INI files|*.ini", InitialDirectory = Environment.CurrentDirectory, RestoreDirectory = true }) if (fd.ShowDialog(this) == DialogResult.OK) { string dstfol = Path.GetDirectoryName(fd.FileName); DllIniData output = new DllIniData(); output.Name = IniData.Name; output.Game = IniData.Game; output.Exports = IniData.Exports; output.Files = new DictionaryContainer<FileTypeHash>(); List<string> labels = new List<string>(); foreach (KeyValuePair<string, FileTypeHash> item in IniData.Files.Where((a, i) => listView1.CheckedIndices.Contains(i))) { 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 "basicdxmodel": SonicRetro.SAModel.NJS_OBJECT mdl = new ModelFile(item.Key).Model; labels.AddRange(mdl.GetLabels()); break; case "animation": Animation ani = Animation.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))); IniSerializer.Serialize(output, fd.FileName); } }
static void Main(string[] args) { Queue<string> argq = new Queue<string>(args); string mdlfilename; if (argq.Count > 0) { mdlfilename = argq.Dequeue(); Console.WriteLine("Model File: {0}", mdlfilename); } else { Console.Write("Model File: "); mdlfilename = Console.ReadLine(); } ModelFile model = new ModelFile(mdlfilename); NJS_OBJECT[] objects = model.Model.GetObjects(); string repmdlfilename; if (argq.Count > 0) { repmdlfilename = argq.Dequeue(); Console.WriteLine("Replacement Model File: {0}", repmdlfilename); } else { Console.Write("Replacement Model File: "); repmdlfilename = Console.ReadLine(); } ModelFile repmodel = new ModelFile(repmdlfilename); NJS_OBJECT[] repobjects = repmodel.Model.GetObjects(); if (model.Format != repmodel.Format) Console.WriteLine("Format mismatch between files! Most data will be unable to be relabeled."); if (objects.Length != repobjects.Length) Console.WriteLine("Models have different structures, the game may crash."); for (int i = 0; i < Math.Min(objects.Length, repobjects.Length); i++) { objects[i].Name = repobjects[i].Name; if (objects[i].Attach != null && repobjects[i].Attach != null) { objects[i].Attach.Name = repobjects[i].Attach.Name; if (objects[i].Attach is BasicAttach && repobjects[i].Attach is BasicAttach) { BasicAttach attach = (BasicAttach)objects[i].Attach; BasicAttach repattach = (BasicAttach)repobjects[i].Attach; attach.VertexName = repattach.VertexName; attach.NormalName = repattach.NormalName; attach.MaterialName = repattach.MaterialName; attach.MeshName = repattach.MeshName; for (int j = 0; j < Math.Min(attach.Mesh.Count, repattach.Mesh.Count); j++) { attach.Mesh[j].PolyName = repattach.Mesh[j].PolyName; attach.Mesh[j].PolyNormalName = repattach.Mesh[j].PolyNormalName; attach.Mesh[j].UVName = repattach.Mesh[j].UVName; attach.Mesh[j].VColorName = repattach.Mesh[j].VColorName; } } } else if (objects[i].Attach is ChunkAttach && repobjects[i].Attach is ChunkAttach) { ChunkAttach attach = (ChunkAttach)objects[i].Attach; ChunkAttach repattach = (ChunkAttach)objects[i].Attach; attach.VertexName = repattach.VertexName; attach.PolyName = repattach.PolyName; } } model.SaveToFile(mdlfilename); }
private void ExportCPP(TextWriter writer, bool SA2) { Dictionary<uint, string> pointers = new Dictionary<uint, string>(); uint imagebase = IniData.ImageBase ?? 0x400000; ModelFormat modelfmt = 0; LandTableFormat landfmt = 0; switch (IniData.Game) { case Game.SA1: modelfmt = ModelFormat.Basic; landfmt = LandTableFormat.SA1; break; case Game.SADX: modelfmt = ModelFormat.BasicDX; landfmt = LandTableFormat.SADX; break; case Game.SA2: case Game.SA2B: modelfmt = ModelFormat.Chunk; landfmt = LandTableFormat.SA2; break; } writer.WriteLine("// Generated by SA Tools Struct Converter"); writer.WriteLine(); if (SA2) writer.WriteLine("#include \"SA2ModLoader.h\""); else writer.WriteLine("#include \"SADXModLoader.h\""); writer.WriteLine(); Dictionary<string, string> models = new Dictionary<string, string>(); foreach (KeyValuePair<string, SA_Tools.FileInfo> item in IniData.Files.Where((a, i) => listView1.CheckedIndices.Contains(i))) { string name = item.Key.MakeIdentifier(); SA_Tools.FileInfo data = item.Value; switch (data.Type) { case "landtable": LandTable tbl = LandTable.LoadFromFile(data.Filename); name = tbl.Name; writer.WriteLine(tbl.ToStructVariables(landfmt, new List<string>())); break; case "model": SonicRetro.SAModel.NJS_OBJECT mdl = new ModelFile(data.Filename).Model; name = mdl.Name; writer.WriteLine(mdl.ToStructVariables(modelfmt == ModelFormat.BasicDX, new List<string>())); models.Add(item.Key, mdl.Name); break; case "basicmodel": mdl = new SonicRetro.SAModel.ModelFile(data.Filename).Model; name = mdl.Name; writer.WriteLine(mdl.ToStructVariables(false, new List<string>())); models.Add(item.Key, mdl.Name); break; case "basicdxmodel": mdl = new SonicRetro.SAModel.ModelFile(data.Filename).Model; name = mdl.Name; writer.WriteLine(mdl.ToStructVariables(true, new List<string>())); models.Add(item.Key, mdl.Name); break; case "chunkmodel": mdl = new SonicRetro.SAModel.ModelFile(data.Filename).Model; name = mdl.Name; writer.WriteLine(mdl.ToStructVariables(false, new List<string>())); models.Add(item.Key, mdl.Name); break; case "action": Animation ani = Animation.Load(data.Filename); name = "action_" + ani.Name.MakeIdentifier(); writer.WriteLine(ani.ToStructVariables()); writer.WriteLine("NJS_ACTION {0} = {{ &{1}, &{2} }};", name, models[data.CustomProperties["model"]], ani.Name.MakeIdentifier()); break; case "animation": ani = Animation.Load(data.Filename); name = ani.Name.MakeIdentifier(); writer.WriteLine(ani.ToStructVariables()); break; case "objlist": { ObjectListEntry[] list = ObjectList.Load(data.Filename, SA2); writer.WriteLine("ObjectListEntry {0}_list[] = {{", name); List<string> objs = new List<string>(list.Length); foreach (ObjectListEntry obj in list) objs.Add(obj.ToStruct() + " " + obj.Name.ToComment()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); writer.WriteLine("ObjectList {0} = {{ arraylengthandptr({0}_list) }};", name); } break; case "startpos": if (SA2) { Dictionary<SA2LevelIDs, SA2StartPosInfo> list = SA2StartPosList.Load(data.Filename); writer.WriteLine("StartPosition {0}[] = {{", name); List<string> objs = new List<string>(list.Count + 1); foreach (KeyValuePair<SA2LevelIDs, SA2StartPosInfo> obj in list) objs.Add(obj.ToStruct()); objs.Add("{ LevelIDs_Invalid }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } else { Dictionary<SA1LevelAct, SA1StartPosInfo> list = SA1StartPosList.Load(data.Filename); writer.WriteLine("StartPosition {0}[] = {{", name); List<string> objs = new List<string>(list.Count + 1); foreach (KeyValuePair<SA1LevelAct, SA1StartPosInfo> obj in list) objs.Add(obj.ToStruct()); objs.Add("{ LevelIDs_Invalid }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "texlist": { TextureListEntry[] list = TextureList.Load(data.Filename); writer.WriteLine("PVMEntry {0}[] = {{", name); List<string> objs = new List<string>(list.Length + 1); foreach (TextureListEntry obj in list) objs.Add(obj.ToStruct()); objs.Add("{ 0 }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "leveltexlist": { LevelTextureList list = LevelTextureList.Load(data.Filename); writer.WriteLine("PVMEntry {0}_list[] = {{", name); List<string> objs = new List<string>(list.TextureList.Length); foreach (TextureListEntry obj in list.TextureList) objs.Add(obj.ToStruct()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); writer.WriteLine("LevelPVMList {0} = {{ {1}, arraylengthandptr({0}_list) }};", name, list.Level.ToC()); } break; case "triallevellist": { SA1LevelAct[] list = TrialLevelList.Load(data.Filename); writer.WriteLine("TrialLevelListEntry {0}_list[] = {{", name); List<string> objs = new List<string>(list.Length); foreach (SA1LevelAct obj in list) objs.Add(string.Format("{{ {0}, {1} }}", obj.Level.ToC("LevelIDs"), obj.Act)); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); writer.WriteLine("TrialLevelList {0} = {{ arrayptrandlength({0}_list) }};", name); } break; case "bosslevellist": { SA1LevelAct[] list = BossLevelList.Load(data.Filename); writer.WriteLine("__int16 {0}[] = {{", name); List<string> objs = new List<string>(list.Length + 1); foreach (SA1LevelAct obj in list) objs.Add(obj.ToC()); objs.Add("levelact(LevelIDs_Invalid, 0)"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "fieldstartpos": { Dictionary<SA1LevelIDs, FieldStartPosInfo> list = FieldStartPosList.Load(data.Filename); writer.WriteLine("FieldStartPosition {0}[] = {{", name); List<string> objs = new List<string>(list.Count + 1); foreach (KeyValuePair<SA1LevelIDs, FieldStartPosInfo> obj in list) objs.Add(obj.ToStruct()); objs.Add("{ LevelIDs_Invalid }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "soundtestlist": { SoundTestListEntry[] list = SoundTestList.Load(data.Filename); writer.WriteLine("SoundTestEntry {0}_list[] = {{", name); List<string> objs = new List<string>(list.Length); foreach (SoundTestListEntry obj in list) objs.Add(obj.ToStruct() + " " + obj.Title.ToComment()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); writer.WriteLine("SoundTestCategory {0} = {{ arrayptrandlength({0}_list) }};", name); } break; case "musiclist": { MusicListEntry[] list = MusicList.Load(data.Filename); writer.WriteLine("MusicInfo {0}[] = {{", name); List<string> objs = new List<string>(list.Length); foreach (MusicListEntry obj in list) objs.Add(obj.ToStruct()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "soundlist": { SoundListEntry[] list = SoundList.Load(data.Filename); writer.WriteLine("SoundFileInfo {0}_list[] = {{", name); List<string> objs = new List<string>(list.Length); foreach (SoundListEntry obj in list) objs.Add(obj.ToStruct()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); writer.WriteLine("SoundList {0} = {{ arraylengthandptr({0}_list) }};", name); } break; case "stringarray": { string[] strs = StringArray.Load(data.Filename); Languages lang = Languages.Japanese; if (data.CustomProperties.ContainsKey("language")) lang = (Languages)Enum.Parse(typeof(Languages), data.CustomProperties["language"], true); writer.WriteLine("char *{0}[] = {{", name); List<string> objs = new List<string>(strs.Length); foreach (string obj in strs) objs.Add(obj.ToC(lang) + " " + obj.ToComment()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "nextlevellist": { NextLevelListEntry[] list = NextLevelList.Load(data.Filename); writer.WriteLine("NextLevelData {0}[] = {{", name); List<string> objs = new List<string>(list.Length + 1); foreach (NextLevelListEntry obj in list) objs.Add(obj.ToStruct()); objs.Add("{ 0, -1 }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "cutscenetext": { CutsceneText texts = new CutsceneText(data.Filename); uint addr = (uint)(data.Address + imagebase); for (int j = 0; j < 5; j++) { string[] strs = texts.Text[j]; Languages lang = (Languages)j; writer.WriteLine("char *{0}_{1}[] = {{", name, lang); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", strs.Select((a) => a.ToC(lang) + " " + a.ToComment()).ToArray())); writer.WriteLine("};"); writer.WriteLine(); pointers.Add(addr, string.Format("{0}_{1}", name, lang)); addr += 4; } } break; case "recapscreen": { uint addr = (uint)(data.Address + imagebase); RecapScreen[][] texts = RecapScreenList.Load(data.Filename, int.Parse(data.CustomProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo)); for (int l = 0; l < 5; l++) for (int j = 0; j < texts.Length; j++) { writer.WriteLine("char *{0}_{1}_{2}_Text[] = {{", name, (Languages)l, j); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", texts[j][l].Text.Split('\n').Select((a) => a.ToC((Languages)l) + " " + a.ToComment()).ToArray())); writer.WriteLine("};"); writer.WriteLine(); } for (int l = 0; l < 5; l++) { writer.WriteLine("RecapScreen {0}_{1}[] = {{", name, (Languages)l); List<string> objs = new List<string>(texts.Length); for (int j = 0; j < texts.Length; j++) { RecapScreen scr = texts[j][l]; objs.Add(string.Format("{{ {0}, arraylengthandptr({1}_{2}_{3}_Text) }}", SA_Tools.HelperFunctions.ToC(scr.Speed), name, (Languages)l, j)); } writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); pointers.Add(addr, string.Format("{0}_{1}", name, (Languages)l)); addr += 4; } } break; case "npctext": { NPCText[][] texts = NPCTextList.Load(data.Filename, int.Parse(data.CustomProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo)); uint headaddr = (uint)(data.Address + imagebase); for (int l = 0; l < 5; l++) { for (int j = 0; j < texts[l].Length; j++) { if (texts[l][j].Groups.Count == 0) continue; if (texts[l][j].HasControl) { writer.WriteLine("__int16 {0}_{1}_{2}_Control[] = {{", name, (Languages)l, j); bool first = true; List<string> objs = new List<string>(); foreach (NPCTextGroup group in texts[l][j].Groups) { if (!first) objs.Add(NPCTextControl.NewGroup.ToC()); else first = false; foreach (ushort flag in group.EventFlags) { objs.Add(NPCTextControl.EventFlag.ToC()); objs.Add(flag.ToCHex()); } foreach (ushort flag in group.NPCFlags) { objs.Add(NPCTextControl.NPCFlag.ToC()); objs.Add(flag.ToCHex()); } if (group.Character != (SA1CharacterFlags)0xFF) { objs.Add(NPCTextControl.Character.ToC()); objs.Add(group.Character.ToC("CharacterFlags")); } if (group.Voice.HasValue) { objs.Add(NPCTextControl.Voice.ToC()); objs.Add(group.Voice.Value.ToString()); } if (group.SetEventFlag.HasValue) { objs.Add(NPCTextControl.SetEventFlag.ToC()); objs.Add(group.SetEventFlag.Value.ToCHex()); } } objs.Add(NPCTextControl.End.ToC()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); } if (texts[l][j].HasText) { writer.WriteLine("HintText_Text {0}_{1}_{2}_Text[] = {{", name, (Languages)l, j); List<string> objs = new List<string>(); foreach (NPCTextGroup group in texts[l][j].Groups) { foreach (NPCTextLine line in group.Lines) objs.Add(line.ToStruct((Languages)l) + " " + line.Line.ToComment()); objs.Add("{ 0 }"); } writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); } } } for (int l = 0; l < 5; l++) { if (l > 0) writer.WriteLine(); writer.WriteLine("HintText_Entry {0}_{1}[] = {{", name, (Languages)l); List<string> objs = new List<string>(); for (int j = 0; j < texts[l].Length; j++) { if (texts[l][j].Groups.Count == 0) { objs.Add("{ 0 }"); continue; } StringBuilder line = new StringBuilder("{ "); if (texts[l][j].HasControl) line.AppendFormat("{0}_{1}_{2}_Control", name, (Languages)l, j); else line.Append("NULL"); line.Append(", "); if (texts[l][j].HasText) line.AppendFormat("{0}_{1}_{2}_Text", name, (Languages)l, j); else line.Append("NULL"); line.Append(" }"); objs.Add(line.ToString()); } writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); pointers.Add(headaddr, string.Format("{0}_{1}", name, (Languages)l)); headaddr += 4; } } break; case "levelclearflags": { LevelClearFlag[] list = LevelClearFlagList.Load(data.Filename); writer.WriteLine("LevelClearFlagData {0}[] = {{", name); List<string> objs = new List<string>(list.Length); foreach (LevelClearFlag obj in list) objs.Add(obj.ToStruct()); objs.Add("{ -1 }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "deathzone": { DeathZoneFlags[] list = DeathZoneFlagsList.Load(data.Filename); string path = Path.GetDirectoryName(data.Filename); List<string> mdls = new List<string>(list.Length); List<string> objs = new List<string>(); for (int j = 0; j < list.Length; j++) { SonicRetro.SAModel.NJS_OBJECT obj = new ModelFile(Path.Combine(path, j.ToString(NumberFormatInfo.InvariantInfo) + ".sa1mdl")).Model; writer.WriteLine(obj.ToStructVariables(modelfmt == ModelFormat.BasicDX, objs)); mdls.Add(obj.Name); objs.Clear(); } writer.WriteLine("DeathZone {0}[] = {{", name); for (int j = 0; j < list.Length; j++) objs.Add(string.Format("{{ {0}, &{1} }}", list[j].Flags.ToC("CharacterFlags"), mdls[j])); objs.Add("{ 0 }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "skyboxscale": { uint headaddr = (uint)(data.Address + imagebase); int cnt = int.Parse(data.CustomProperties["count"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo); SkyboxScale[] sclini = SkyboxScaleList.Load(data.Filename); for (int j = 0; j < cnt; j++) { writer.WriteLine("SkyboxScale {0}_{1} = {2};", name, j, sclini[j].ToStruct()); pointers.Add(headaddr, string.Format("{0}_{1}", name, j)); headaddr += 4; } } break; case "stageselectlist": { StageSelectLevel[] list = StageSelectLevelList.Load(data.Filename); writer.WriteLine("StageSelectLevel {0}[] = {{", name); List<string> objs = new List<string>(list.Length); foreach (StageSelectLevel obj in list) objs.Add(obj.ToStruct()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "levelrankscores": { Dictionary<SA2LevelIDs, LevelRankScores> list = LevelRankScoresList.Load(data.Filename); writer.WriteLine("LevelRankScores {0}[] = {{", name); List<string> objs = new List<string>(list.Count); foreach (KeyValuePair<SA2LevelIDs, LevelRankScores> obj in list) objs.Add(obj.ToStruct()); objs.Add("{ LevelIDs_Invalid }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "levelranktimes": { Dictionary<SA2LevelIDs, LevelRankTimes> list = LevelRankTimesList.Load(data.Filename); writer.WriteLine("LevelRankTimes {0}[] = {{", name); List<string> objs = new List<string>(list.Count); foreach (KeyValuePair<SA2LevelIDs, LevelRankTimes> obj in list) objs.Add(obj.ToStruct()); objs.Add("{ LevelIDs_Invalid }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "endpos": { Dictionary<SA2LevelIDs, SA2EndPosInfo> list = SA2EndPosList.Load(data.Filename); writer.WriteLine("LevelEndPosition {0}[] = {{", name); List<string> objs = new List<string>(list.Count); foreach (KeyValuePair<SA2LevelIDs, SA2EndPosInfo> obj in list) objs.Add(obj.ToStruct()); objs.Add("{ LevelIDs_Invalid }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "animationlist": { SA2AnimationInfo[] list = SA2AnimationInfoList.Load(data.Filename); writer.WriteLine("AnimationInfo {0}[] = {{", name); List<string> objs = new List<string>(list.Length); foreach (SA2AnimationInfo obj in list) objs.Add(obj.ToStruct()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "levelpathlist": { List<SA1LevelAct> levels = new List<SA1LevelAct>(); foreach (string dir in Directory.GetDirectories(data.Filename)) { SA1LevelAct level; try { level = new SA1LevelAct(new DirectoryInfo(dir).Name); } catch { continue; } levels.Add(level); List<PathData> paths = PathList.Load(dir); for (int i = 0; i < paths.Count; i++) { writer.WriteLine("Loop {0}_{1}_{2}_Entries[] = {{", name, level.ToString().MakeIdentifier(), i); List<string> objs = new List<string>(paths[i].Path.Count); foreach (PathDataEntry entry in paths[i].Path) objs.Add(entry.ToStruct()); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); writer.WriteLine("LoopHead {0}_{1}_{2} = {{ {3}, LengthOfArray({0}_{1}_{2}_Entries), {4}, {0}_{1}_{2}_Entries, (ObjectFuncPtr){5} }};", name, level.ToString().MakeIdentifier(), i, paths[i].Unknown, HelperFunctions.ToC(paths[i].TotalDistance), HelperFunctions.ToCHex(paths[i].Code)); writer.WriteLine(); } writer.WriteLine("LoopHead *{0}_{1}[] = {{", name, level.ToString().MakeIdentifier()); for (int i = 0; i < paths.Count; i++) writer.WriteLine("\t&{0}_{1}_{2},", name, level.ToString().MakeIdentifier(), i); writer.WriteLine("\tNULL"); writer.WriteLine("};"); writer.WriteLine(); } writer.WriteLine("PathDataPtr {0}[] = {{", name); foreach (SA1LevelAct level in levels) writer.WriteLine("\t{{ {0}, {1}_{2} }},", level.ToC(), name, level.ToString().MakeIdentifier()); writer.WriteLine("\t{ 0xFFFF }"); writer.WriteLine("};"); writer.WriteLine(); } break; case "stagelightdatalist": { List<SA1StageLightData> list = SA1StageLightDataList.Load(data.Filename); writer.WriteLine("StageLightData {0}[] = {{", name); List<string> objs = new List<string>(list.Count + 1); foreach (SA1StageLightData obj in list) objs.Add(obj.ToStruct()); objs.Add("{ 0xFFu }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; } writer.WriteLine(); if (data.PointerList != null && data.PointerList.Length > 0) foreach (int ptr in data.PointerList) pointers.Add((uint)(ptr + imagebase), name); } writer.WriteLine("PointerInfo pointers[] = {"); List<string> ptrs = new List<string>(pointers.Count); foreach (KeyValuePair<uint, string> ptr in pointers) ptrs.Add(string.Format("ptrdecl({0}, &{1})", HelperFunctions.ToCHex(ptr.Key), ptr.Value)); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", ptrs.ToArray())); writer.WriteLine("};"); writer.WriteLine(); }