From 9a06296fc62236c69ea6a75cf145d9d2e6d85c6c Mon Sep 17 00:00:00 2001 From: Zurphing <72351816+Zurphing@users.noreply.github.com> Date: Sun, 22 Feb 2026 01:47:29 -0500 Subject: [PATCH 1/5] Add files via upload --- OpenKh.Kh2/Slct.cs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 OpenKh.Kh2/Slct.cs diff --git a/OpenKh.Kh2/Slct.cs b/OpenKh.Kh2/Slct.cs new file mode 100644 index 000000000..05ba6cd93 --- /dev/null +++ b/OpenKh.Kh2/Slct.cs @@ -0,0 +1,40 @@ +using OpenKh.Common; +using OpenKh.Kh2.Extensions; +using OpenKh.Kh2.Utils; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Xe.BinaryMapper; + +namespace OpenKh.Kh2 +{ + + public class ChoiceEntry + { + [Data] public short Id { get; set; } + [Data] public short MessageId { get; set; } + } + public class Slct + { + + [Data] public ushort Id { get; set; } + [Data] public byte ChoiceNum { get; set; } + [Data] public byte ChoiceDefault { get; set; } + + [Data(Count = 4)] public ChoiceEntry[] Choice { get; set; } + [Data] public short BaseSequence { get; set; } + [Data] public short TitleSequence { get; set; } + [Data] public int Information { get; set; } + [Data] public int EntryId { get; set; } + [Data] public int Task { get; set; } + [Data] public byte PauseMode { get; set; } + [Data] public byte Flag { get; set; } + [Data] public byte SoundPause { get; set; } + [Data(Count = 25)] public byte[] Padding { get; set; } + + public static List Read(Stream stream) => BaseTable.Read(stream); + public static void Write(Stream stream, IEnumerable entries) => + BaseTable.Write(stream, 2, entries); + } +} From 7221623139bfd65906b33a913a049d9ccc30640b Mon Sep 17 00:00:00 2001 From: Zurphing <72351816+Zurphing@users.noreply.github.com> Date: Sun, 22 Feb 2026 01:48:07 -0500 Subject: [PATCH 2/5] Add slct listpatch --- OpenKh.Patcher/PatcherProcessor.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/OpenKh.Patcher/PatcherProcessor.cs b/OpenKh.Patcher/PatcherProcessor.cs index 1633ccbb9..56be0cd28 100644 --- a/OpenKh.Patcher/PatcherProcessor.cs +++ b/OpenKh.Patcher/PatcherProcessor.cs @@ -940,6 +940,27 @@ private static void PatchList(Context context, List sources, Stream s Kh2.SystemData.Cmd.Write(stream.SetPosition(0), cmdList); break; + case "slct": + var slctList = Kh2.Slct.Read(stream); + var moddedSlct = deserializer.Deserialize>(sourceText); + + foreach (var entries in moddedSlct) + { + var existingEntry = slctList.FirstOrDefault(x => x.Id == entries.Id); + + if (existingEntry != null) + { + slctList[slctList.IndexOf(existingEntry)] = entries; + } + else + { + slctList.Add(entries); + } + } + + Kh2.Slct.Write(stream.SetPosition(0), slctList); + break; + case "localset": var localList = Kh2.Localset.Read(stream); var moddedLocal = deserializer.Deserialize>(sourceText); @@ -1627,3 +1648,4 @@ private static void PatchSynth(Context context, List sources, Stream } } } + From 64957abe2043f81a8b5eacd921a6eabfe37ec60f Mon Sep 17 00:00:00 2001 From: Zurphing <72351816+Zurphing@users.noreply.github.com> Date: Sun, 22 Feb 2026 01:51:00 -0500 Subject: [PATCH 3/5] Add 'slct' mod type documentation Added documentation for the 'slct' mod type, including its source example. --- docs/tool/GUI.ModsManager/creatingMods.md | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/tool/GUI.ModsManager/creatingMods.md b/docs/tool/GUI.ModsManager/creatingMods.md index 2a609b9e2..1d8635058 100644 --- a/docs/tool/GUI.ModsManager/creatingMods.md +++ b/docs/tool/GUI.ModsManager/creatingMods.md @@ -41,6 +41,7 @@ This document will focus on teaching you how to create mods using the OpenKH Mod * [soundinfo](#soundinfo-source-example) * [place](#place-source-example) * [jigsaw](#jigsaw-source-example) + * [slct](#slct-source-example) * [bbsarc](#bbsarc-bbs) * [Example of a Fully Complete `mod.yml` File](#an-example-of-a-fully-complete-modyml-can-be-seen-below-and-the-full-source-of-the-mod-can-be-seen-here) * [Generating a Simple `mod.yml` for New Mod Authors](#generating-a-simple-modyml-for-new-mod-authors) @@ -332,6 +333,7 @@ Asset Example * `soundinfo` * `place` * `jigsaw` + * `slct` Asset Example ``` @@ -863,6 +865,31 @@ Sora: Unk07: 0 Unk08: 0 ``` +### `slct` Source Example +``` +- Id: 1 + ChoiceNum: 4 #Amount of options + ChoiceDefault: 3 #Option to default to + Choice: + - Id: 0 #Choice "Function" + MessageId: 0 #MessageID to assign to the Choice + - Id: 1 + MessageId: 1 + - Id: 2 + MessageId: 2 + - Id: 3 + MessageId: 3 + BaseSequence: 12 #Signed short, can be negative + TitleSequence: 13 #Signed short, can be negative + Information: 14 + EntryId: 15 + Task: 16 + PauseMode: 17 + Flag: 18 + SoundPause: 19 + Padding: #There are 25 padding bytes in total + - 0 +``` * `synthpatch` (KH2) - Modifies Mixdata.bar, a file used for various properties related to synthesis in KH2. From 209231d65bdf330b272030e67635eddb28fbeaaf Mon Sep 17 00:00:00 2001 From: Zurphing <72351816+Zurphing@users.noreply.github.com> Date: Sun, 22 Feb 2026 02:38:21 -0500 Subject: [PATCH 4/5] Add test for Slct listpatching --- OpenKh.Tests/Patcher/PatcherTests.cs | 88 ++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/OpenKh.Tests/Patcher/PatcherTests.cs b/OpenKh.Tests/Patcher/PatcherTests.cs index d81254c0b..8daec281d 100644 --- a/OpenKh.Tests/Patcher/PatcherTests.cs +++ b/OpenKh.Tests/Patcher/PatcherTests.cs @@ -3187,6 +3187,94 @@ public void ListPatchJigsawTest() } + [Fact] + public void ListPatchSlctTest() + { + var patcher = new PatcherProcessor(); + var serializer = new Serializer(); + var patch = new Metadata() + { + Assets = new List() + { + new AssetFile() + { + Name = "14mission.bar", + Method = "binarc", + Source = new List() + { + new AssetFile() + { + Name = "slct", + Method = "listpatch", + Type = "List", + Source = new List() + { + new AssetFile() + { + Name = "SlctList.yml", + Type = "slct" + } + } + } + } + } + } + }; + + File.Create(Path.Combine(AssetsInputDir, "14mission.bar")).Using(stream => + { + var slctEntry = new List() + { + new Kh2.Slct + { + Id = 1, + ChoiceNum = 2, + ChoiceDefault = 3, + Choice = Enumerable.Range(0, 4).Select(_ => new Kh2.ChoiceEntry { Id = 0, MessageId = 0 }).ToArray(), + Padding = new byte[25] + } + }; + using var slctStream = new MemoryStream(); + Kh2.Slct.Write(slctStream, slctEntry); + Bar.Write(stream, new Bar() { + new Bar.Entry() + { + Name = "slct", + Type = Bar.EntryType.List, + Stream = slctStream + } + }); + }); + + File.Create(Path.Combine(ModInputDir, "SlctList.yml")).Using(stream => + { + var writer = new StreamWriter(stream); + writer.WriteLine("- Id: 1"); + writer.WriteLine(" ChoiceNum: 2"); + writer.WriteLine(" ChoiceDefault: 3"); + writer.WriteLine(" Choice:"); + writer.WriteLine(" - Id: 0"); + writer.WriteLine(" MessageId: 0"); + writer.WriteLine(" Padding:"); + writer.WriteLine(" - 0"); + writer.Flush(); + }); + + patcher.Patch(AssetsInputDir, ModOutputDir, patch, ModInputDir, Tests: true); + + AssertFileExists(ModOutputDir, "14mission.bar"); + + File.OpenRead(Path.Combine(ModOutputDir, "14mission.bar")).Using(stream => + { + var binarc = Bar.Read(stream); + var slctStream = Kh2.Slct.Read(binarc[0].Stream); + Assert.Equal(1, slctStream[0].Id); + Assert.Equal(2, slctStream[0].ChoiceNum); + Assert.Equal(3, slctStream[0].ChoiceDefault); + }); + } + + [Fact] public void ListPatchPlacesTest() { From 810a6d5b644153f89e6be30450bba58f72c8a12d Mon Sep 17 00:00:00 2001 From: Zurphing <72351816+Zurphing@users.noreply.github.com> Date: Sun, 22 Feb 2026 02:48:18 -0500 Subject: [PATCH 5/5] Update slct comments Clarified comments for PauseMode and Flag fields. --- docs/tool/GUI.ModsManager/creatingMods.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/tool/GUI.ModsManager/creatingMods.md b/docs/tool/GUI.ModsManager/creatingMods.md index 1d8635058..8ae76c64f 100644 --- a/docs/tool/GUI.ModsManager/creatingMods.md +++ b/docs/tool/GUI.ModsManager/creatingMods.md @@ -881,11 +881,11 @@ Sora: MessageId: 3 BaseSequence: 12 #Signed short, can be negative TitleSequence: 13 #Signed short, can be negative - Information: 14 - EntryId: 15 + Information: 14 #Value tends to always be 0? + EntryId: 15 # Task: 16 - PauseMode: 17 - Flag: 18 + PauseMode: 0 #6 possible values. 0 = Null, 1 = Battle, 2 = Form, 3 = Mission, 4 = Event, 5 = Musical + Flag: 1 #Two possible flags. 0 Allows you to unpause, 1 disables unpausing to get out of the menu. SoundPause: 19 Padding: #There are 25 padding bytes in total - 0