From 2973d9864174913ca8841ae60d9be5aeb785b8d5 Mon Sep 17 00:00:00 2001 From: krogenth Date: Sat, 13 Jan 2024 10:26:17 -0500 Subject: [PATCH] Add dialogue opcode parsing (#68) * add currently known dialogue opcodes * add more textbox opcodes, document additional potential opcodes * add unknown opcodes for parsing * get all maps to not throw errors when parsing dialogue section opcodes * start trying to implement ui rendering for opcodes * use observablecollection for lists of opcodes, add basic rendering of opcodes * add styling to opcode tree * add highlight opcodes, add unknown opcode 0x16 * adjust opcode returns * fix opcode 10 mapid, fix some stream read functions * implement handling for base element index searching for listbox items * add in scnr file path parsing --- Directory.Packages.props | 2 + documentation/Data File Details.txt | 31 +- src/G2DataGUI.Common/Data/Maps/Map.cs | 13 +- src/G2DataGUI.Common/Data/Maps/MapDialogue.cs | 46 +- .../Data/Maps/MapDialogueHeader.cs | 2 +- .../MapDialogueOpcodes/CameraMoveOpcode.cs | 20 + .../CharacterPortaitOpcode.cs | 25 + .../MapDialogueOpcodes/DialogueOpcodes.cs | 129 ++ .../Highlight/HighlightEndOpcode.cs | 16 + .../Highlight/HighlightOptions.cs | 7 + .../Highlight/HighlightStartOpcode.cs | 38 + .../Highlight/IHighlightOpcode.cs | 29 + .../MapDialogueOpcodes/IMapDialogueOpcode.cs | 26 + .../MapDialogueOpcodes/ItemAcquireOpcode.cs | 20 + .../Maps/MapDialogueOpcodes/NextLineOpcode.cs | 13 + .../Maps/MapDialogueOpcodes/NextPageOpcode.cs | 13 + .../MapDialogueOpcodes/ParseDialogueOpcode.cs | 42 + .../MapDialogueOpcodes/Pause/IPauseOpcode.cs | 21 + .../MapDialogueOpcodes/Pause/PauseOptions.cs | 7 + .../Pause/PauseUnknown1Opcode.cs | 21 + .../Pause/PauseUnknown2Opcode.cs | 19 + .../MapDialogueOpcodes/ScriptCallOpcode.cs | 20 + .../TextBox/CreateOptionsTextBoxOpcode.cs | 52 + .../TextBox/CreateOverworldTextBoxOpcode.cs | 50 + .../TextBox/CreateSubTextBoxOpcode.cs | 49 + .../TextBox/CreateTextBoxOpcode.cs | 39 + .../TextBox/ITextBoxOpcode.cs | 27 + .../TextBox/RemoveTextBoxOpcode.cs | 13 + .../TextBox/TextBoxOptions.cs | 11 + .../Maps/MapDialogueOpcodes/TextOpcode.cs | 38 + .../MapDialogueOpcodes/Unknown03Opcode.cs | 22 + .../MapDialogueOpcodes/Unknown04Opcode.cs | 18 + .../MapDialogueOpcodes/Unknown06Opcode.cs | 22 + .../MapDialogueOpcodes/Unknown07Opcode.cs | 18 + .../MapDialogueOpcodes/Unknown08Opcode.cs | 22 + .../MapDialogueOpcodes/Unknown09Opcode.cs | 24 + .../MapDialogueOpcodes/Unknown0COpcode.cs | 18 + .../MapDialogueOpcodes/Unknown0DOpcode.cs | 20 + .../Unknown10/IUnknown10Opcode.cs | 27 + .../Unknown10/Unknon10Options.cs | 7 + .../Unknown10/Unknown10Unknown1Opcode.cs | 25 + .../Unknown10/Unknown10Unknown2Opcode.cs | 11 + .../MapDialogueOpcodes/Unknown14Opcode.cs | 26 + .../MapDialogueOpcodes/Unknown15Opcode.cs | 24 + .../MapDialogueOpcodes/Unknown16Opcode.cs | 26 + .../MapDialogueOpcodes/Unknown1BOpcode.cs | 13 + .../MapDialogueOpcodes/Unknown1COpcode.cs | 18 + src/G2DataGUI.Common/Data/Maps/Maps.cs | 17 +- .../Extensions/EnumExtensions.cs | 22 + src/G2DataGUI.Common/G2DataGUI.Common.csproj | 4 + src/G2DataGUI.Common/Paths/ProjectPaths.cs | 26 + src/G2DataGUI.Common/ProjectPaths.cs | 26 - src/G2DataGUI.Common/Version.cs | 11 +- .../Extensions/StreamExtensions.cs | 8 +- src/G2DataGUI/Assets/Styles/Styles.xaml | 66 +- .../Converters/ListElementToIndexConverter.cs | 22 + .../UI/Selectors/MapOpcodeSelector.cs | 33 + .../UI/ViewModels/MapDialogueViewModel.cs | 64 + src/G2DataGUI/UI/ViewModels/MapsViewModel.cs | 2 + .../UI/ViewModels/MenuBarViewModel.cs | 1 + .../UI/Views/Content/MapDialogue.axaml | 1071 +++++++++++++++++ .../UI/Views/Content/MapDialogue.axaml.cs | 13 + src/G2DataGUI/UI/Views/Content/Maps.axaml | 3 + src/G2DataGUI/UI/Views/Content/Maps.axaml.cs | 3 + 64 files changed, 2483 insertions(+), 89 deletions(-) create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/CameraMoveOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/CharacterPortaitOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/DialogueOpcodes.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightEndOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightOptions.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightStartOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/IHighlightOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/IMapDialogueOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ItemAcquireOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/NextLineOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/NextPageOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ParseDialogueOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/IPauseOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseOptions.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseUnknown1Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseUnknown2Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ScriptCallOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateOptionsTextBoxOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateOverworldTextBoxOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateSubTextBoxOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateTextBoxOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/ITextBoxOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/RemoveTextBoxOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/TextBoxOptions.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown03Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown04Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown06Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown07Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown08Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown09Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown0COpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown0DOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/IUnknown10Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknon10Options.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknown10Unknown1Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknown10Unknown2Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown14Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown15Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown16Opcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown1BOpcode.cs create mode 100644 src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown1COpcode.cs create mode 100644 src/G2DataGUI.Common/Extensions/EnumExtensions.cs create mode 100644 src/G2DataGUI.Common/Paths/ProjectPaths.cs delete mode 100644 src/G2DataGUI.Common/ProjectPaths.cs create mode 100644 src/G2DataGUI/Converters/ListElementToIndexConverter.cs create mode 100644 src/G2DataGUI/UI/Selectors/MapOpcodeSelector.cs create mode 100644 src/G2DataGUI/UI/ViewModels/MapDialogueViewModel.cs create mode 100644 src/G2DataGUI/UI/Views/Content/MapDialogue.axaml create mode 100644 src/G2DataGUI/UI/Views/Content/MapDialogue.axaml.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index fbdbc14..0ced3fb 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,6 +15,8 @@ + + diff --git a/documentation/Data File Details.txt b/documentation/Data File Details.txt index 93f4fb3..cc6b073 100644 --- a/documentation/Data File Details.txt +++ b/documentation/Data File Details.txt @@ -58,18 +58,27 @@ .MDT FILES { CODES DETAILS - 0x05 XX YY XX = script number? YY = character id - 0x08 XX YY ZZ XX = ???, YY = ???(noticed either 0x21 or 0x41), ZZ = ???(only been 0x01) - 0x0B ??? 2 parameters most likely(seen in 2000.mdt at 0x1AB71), according to old notes, this handles camera changes - 0x11 XX [] adds item to inventory, XX = ??? + 0x03 ??? Seems to have 3 parameters + 0x04 ??? Seems to have 1 parameter + 0x05 XX YY XX = script number? YY = character id + 0x06 ??? Unsure on parameter count + 0x08 XX YY ZZ XX = ???, YY = ???(noticed either 0x21 or 0x41), ZZ = ???(only been 0x01) + 0x09 ??? Seems to have 4 parameters + 0x10 Unsure on parameter count + 0x0B ??? 2 parameters most likely(seen in 2000.mdt at 0x1AB71), according to old notes, this handles camera changes + 0x11 XX [] adds item to inventory, XX = ??? + 0x14 ??? Unsure on parameter count + 0x15 ??? Unsure, may be 4 parameters? 0x17 XX [YY ZZ] Box stuff - XX = 00 Remove textbox? Used at end of dialogues - XX = 01 Create textbox? Used at beginning of dialogues + XX = 00 Remove textbox? Used at end of dialogues + XX = 01 Create textbox? Used at beginning of dialogues + XX = 20 Create sub textbox(textbox that appears top-right of current textbox) + XX = 40 Create options textbox(user interaction required) XX = 80, YY ZZ Create overword textbox, YY = length of textbox, ZZ = height of textbox - 0x18 00 XX changes character portrait, XX = character portrait offset - 0x1A next page - 0x1D FF XX pause(frame/tick?) - 0x1F next line + 0x18 00 XX changes character portrait, XX = character portrait offset + 0x1A next page + 0x1D FF XX pause(frame/tick?) + 0x1F next line Likely Codes 0x02 @@ -78,6 +87,8 @@ 0x1B 1 byte 0x?? 0x70 + Codes likely span from 0x01 to 0x1F, all ASCII values before text. + 0x0000 - Header Length(always 0x200) diff --git a/src/G2DataGUI.Common/Data/Maps/Map.cs b/src/G2DataGUI.Common/Data/Maps/Map.cs index 9255e87..502a856 100644 --- a/src/G2DataGUI.Common/Data/Maps/Map.cs +++ b/src/G2DataGUI.Common/Data/Maps/Map.cs @@ -1,6 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Text; +using G2DataGUI.Common.Paths; namespace G2DataGUI.Common.Data.Maps; @@ -20,7 +22,8 @@ public class Map public string MapName { get; set; } = ""; public string FileLocation { get; set; } = ""; - public string Filename { get; set; } = ""; + public string ScnrFileLocation { get; set; } = ""; + public string FileName { get; set; } = ""; public static Map ReadMap(FileStream reader, string filepath) { @@ -28,8 +31,9 @@ public static Map ReadMap(FileStream reader, string filepath) { Header = MapHeader.ReadMapHeader(reader), FileLocation = filepath, - Filename = Path.GetFileNameWithoutExtension(filepath), + FileName = Path.GetFileNameWithoutExtension(filepath), }; + map.ScnrFileLocation = map.ScnrFilePath(); reader.Seek(map.Header.OffsetMapEntries, SeekOrigin.Begin); for (var index = 0; index < map.Header.NumMapEntries; index++) @@ -190,4 +194,7 @@ private void ReadMapName() } } } + + private string ScnrFilePath() => + $"{Version.Instance.RootTextDirectory}\\en\\scnr\\{FileName}.scn"; } diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogue.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogue.cs index 5677b35..4ae9302 100644 --- a/src/G2DataGUI.Common/Data/Maps/MapDialogue.cs +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogue.cs @@ -1,12 +1,16 @@ using System.Collections.Generic; using System.IO; +using G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; using G2DataGUI.IO.Streams; +using System.Linq; +using System.Collections.ObjectModel; namespace G2DataGUI.Common.Data.Maps; public class MapDialogue { public MapDialogueHeader Header { get; set; } public List DialogueSections { get; set; } = new(); + public ObservableCollection> DialogueSectionOpcodes { get; set; } = new(); public static MapDialogue ReadMapDialogue(Stream reader, uint dialogueSectionLength) { @@ -15,16 +19,38 @@ public static MapDialogue ReadMapDialogue(Stream reader, uint dialogueSectionLen Header = MapDialogueHeader.ReadMapDialogueHeader(reader), }; - var dialogueStartPosition = reader.Position; - for (var index = 1; index < dialogue.Header.Offsets.Count; index++) - { - var length = (index == dialogue.Header.Offsets.Count - 1) ? - (dialogueSectionLength - dialogue.Header.HeaderLength - (dialogue.Header.Offsets[index - 1].Offset * 8)) : - (dialogue.Header.Offsets[index].Offset - dialogue.Header.Offsets[index - 1].Offset) * 8; - reader.Seek(dialogueStartPosition + (dialogue.Header.Offsets[index - 1].Offset * 8), SeekOrigin.Begin); - dialogue.DialogueSections.Add(reader.ReadRawByteArray((uint)length)); - } + var dialogueStartPosition = reader.Position; + for (var index = 1; index < dialogue.Header.Offsets.Count; index++) + { + dialogue.DialogueSectionOpcodes.Add(new ObservableCollection()); + var length = (index == dialogue.Header.Offsets.Count - 1) ? + (dialogueSectionLength - dialogue.Header.HeaderLength - (dialogue.Header.Offsets[index - 1].Offset * 8)) : + (dialogue.Header.Offsets[index].Offset - dialogue.Header.Offsets[index - 1].Offset) * 8; + using MemoryStream memReader = new(); + + // write section to memory stream to force cutoff from overrunning opcodes + memReader.Write(reader.ReadRawByteArray((uint)length)); + memReader.Seek(0, SeekOrigin.Begin); + while (memReader.Position < memReader.Length) + { + var opcode = IMapDialogueOpcode.ParseNextOpcode(memReader); + if (opcode != null) + { + dialogue.DialogueSectionOpcodes.Last().Add(opcode); + } + } + } + + reader.Seek(dialogueStartPosition, SeekOrigin.Begin); + for (var index = 1; index < dialogue.Header.Offsets.Count; index++) + { + var length = (index == dialogue.Header.Offsets.Count - 1) ? + (dialogueSectionLength - dialogue.Header.HeaderLength - (dialogue.Header.Offsets[index - 1].Offset * 8)) : + (dialogue.Header.Offsets[index].Offset - dialogue.Header.Offsets[index - 1].Offset) * 8; + reader.Seek(dialogueStartPosition + (dialogue.Header.Offsets[index - 1].Offset * 8), SeekOrigin.Begin); + dialogue.DialogueSections.Add(reader.ReadRawByteArray((uint)length)); + } - return dialogue; + return dialogue; } } diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueHeader.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueHeader.cs index 9e1fd50..9893ff4 100644 --- a/src/G2DataGUI.Common/Data/Maps/MapDialogueHeader.cs +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueHeader.cs @@ -37,4 +37,4 @@ public static MapDialogueOffset ReadMapDialogueOffset(Stream reader) }; return offset; } -} \ No newline at end of file +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/CameraMoveOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/CameraMoveOpcode.cs new file mode 100644 index 0000000..267dc7c --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/CameraMoveOpcode.cs @@ -0,0 +1,20 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class CameraMoveOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.CameraMove; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new CameraMoveOpcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/CharacterPortaitOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/CharacterPortaitOpcode.cs new file mode 100644 index 0000000..187d741 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/CharacterPortaitOpcode.cs @@ -0,0 +1,25 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class CharacterPortaitOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.CharacterPortait; + + /// + /// Appears to always be 0x00 + /// + public byte Unknown1 { get; set; } = 0x00; + + public byte PortaitOffset { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new CharacterPortaitOpcode() + { + Unknown1 = reader.ReadRawByte(), + PortaitOffset = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/DialogueOpcodes.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/DialogueOpcodes.cs new file mode 100644 index 0000000..b1bfb45 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/DialogueOpcodes.cs @@ -0,0 +1,129 @@ +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public enum DialogueOpcode : byte +{ + /// + /// Not sure how to handle text + /// so considering this a No Op + /// opcode, to house the text itself + /// + Text = 0x00, + + /// + /// Completely unsure, likely 3 parameters + /// + Unknown03 = 0x03, + + /// + /// Completely unknown, likely 1 parameter + /// + Unknown04 = 0x04, + + /// + /// Seems to define a call to a script + /// within the Map's script list + /// + ScriptCall = 0x05, + + /// + /// Completely unknown, may be 4 parameters + /// + Unknown06 = 0x06, + + /// + /// Completely unknown, may be 1 or 4 parameters + /// + Unknown07 = 0x07, + + /// + /// Completely unknown, likely 2 parameters + /// + Unknown08 = 0x08, + + /// + /// Completely unknown, may be 4 parameters + /// + Unknown09 = 0x09, + + /// + /// Seems to deal with camera movement + /// + CameraMove = 0x0B, + + /// + /// Completely unknown, seems to have 1 parameter + /// + Unknown0C = 0x0C, + + /// + /// Completely unknown, seems to have 2 parameters + /// + Unknown0D = 0x0D, + + /// + /// Completely unknown, no clue on parameters(1 parameter?). + /// See Map 1000, section 8, offset 0x24. + /// Also see Map 1000, section 10, offset 0x1F. + /// + Unknown10 = 0x10, + + /// + /// Adds items to inventory + /// + ItemAquire = 0x11, + + /// + /// Completely unknown, no clue on parameters + /// + Unknown14 = 0x14, + + /// + /// Completely unknown, likely 4 parameters + /// + Unknown15 = 0x15, + + /// + /// Completely unknown, exists with tutorial guy dialogue... + /// + Unknown16 = 0x16, + + /// + /// Defines a action around textboxes + /// + TextBox = 0x17, + + /// + /// Defines which character protrait to display + /// + CharacterPortait = 0x18, + + /// + /// Clears/Next pages within the textbox + /// + NextPage = 0x1A, + + /// + /// Completely unknown, appears to have no parameters + /// + Unknown1B = 0x1B, + + /// + /// Completely unknown, seems to have 1 parameter + /// + Unknown1C = 0x1C, + + /// + /// Pauses text rendering for a time(tick based?) + /// + Pause = 0x1D, + + /// + /// Creates a highlighted section of text + /// + Highlight = 0x1E, + + /// + /// Moves text rendering to next line + /// + NextLine = 0x1F, +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightEndOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightEndOpcode.cs new file mode 100644 index 0000000..37d5940 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightEndOpcode.cs @@ -0,0 +1,16 @@ +using System.Collections.ObjectModel; +using System.IO; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Highlight; + +public class HighlightEndOpcode : IHighlightOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Highlight; + public HighlightOption Option { get; set; } = HighlightOption.End; + public ObservableCollection NestedOpcodes { get; set; } = new(); + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new HighlightEndOpcode(); + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightOptions.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightOptions.cs new file mode 100644 index 0000000..26e3934 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightOptions.cs @@ -0,0 +1,7 @@ +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Highlight; + +public enum HighlightOption : byte +{ + Start = 0x0C, + End = 0x0F, +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightStartOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightStartOpcode.cs new file mode 100644 index 0000000..6287c32 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/HighlightStartOpcode.cs @@ -0,0 +1,38 @@ +using System.Collections.ObjectModel; +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Highlight; + +public class HighlightStartOpcode : IHighlightOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Highlight; + public HighlightOption Option { get; set; } = HighlightOption.Start; + public ObservableCollection NestedOpcodes { get; set; } = new(); + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + HighlightStartOpcode opcode = new(); + + do + { + byte data = reader.ReadRawByte(); + if (data.EnumExists()) + { + var nestedOpcode = ParseDialogueOpcode.ParseNextOpcode(reader, data); + opcode.NestedOpcodes.Add(nestedOpcode); + + if (nestedOpcode is HighlightEndOpcode _) + { + return opcode; + } + } + else + { + reader.Seek(-1, SeekOrigin.Current); + opcode.NestedOpcodes.Add(TextOpcode.ReadOpcode(reader)); + } + } while (true); + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/IHighlightOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/IHighlightOpcode.cs new file mode 100644 index 0000000..33d44fa --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Highlight/IHighlightOpcode.cs @@ -0,0 +1,29 @@ +using System.Collections.ObjectModel; +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Highlight; + +public interface IHighlightOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public HighlightOption Option { get; set; } + public ObservableCollection NestedOpcodes { get; set; } + + public static new IMapDialogueOpcode ReadOpcode(Stream reader) + { + var option = reader.ReadRawByte(); + if (option.EnumExists()) + { + return option.ToEnum() switch + { + HighlightOption.Start => HighlightStartOpcode.ReadOpcode(reader), + HighlightOption.End => HighlightEndOpcode.ReadOpcode(reader), + _ => null, + }; + } + + reader.Seek(-1, SeekOrigin.Current); + return null; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/IMapDialogueOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/IMapDialogueOpcode.cs new file mode 100644 index 0000000..284a228 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/IMapDialogueOpcode.cs @@ -0,0 +1,26 @@ +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public interface IMapDialogueOpcode +{ + DialogueOpcode Opcode { get; set; } + + public static IMapDialogueOpcode ParseNextOpcode(Stream reader) + { + var opcode = reader.ReadRawByte(); + if (!opcode.EnumExists()) + { + return null; + } + + return ParseDialogueOpcode.ParseNextOpcode(reader, opcode); + } +} + +public interface IMapDialogueOpcodeReader +{ + abstract static IMapDialogueOpcode ReadOpcode(Stream reader); +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ItemAcquireOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ItemAcquireOpcode.cs new file mode 100644 index 0000000..f37382d --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ItemAcquireOpcode.cs @@ -0,0 +1,20 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class ItemAcquireOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.ItemAquire; + public byte Unknown1 { get; set; } + public byte Item1Offset { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new ItemAcquireOpcode() + { + Unknown1 = reader.ReadRawByte(), + Item1Offset = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/NextLineOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/NextLineOpcode.cs new file mode 100644 index 0000000..fb7bd87 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/NextLineOpcode.cs @@ -0,0 +1,13 @@ +using System.IO; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class NextLineOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.NextLine; + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new NextLineOpcode(); + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/NextPageOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/NextPageOpcode.cs new file mode 100644 index 0000000..0113669 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/NextPageOpcode.cs @@ -0,0 +1,13 @@ +using System.IO; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class NextPageOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.NextPage; + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new NextPageOpcode(); + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ParseDialogueOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ParseDialogueOpcode.cs new file mode 100644 index 0000000..687bfef --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ParseDialogueOpcode.cs @@ -0,0 +1,42 @@ +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.TextBox; +using G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Unknown10; +using G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Pause; +using G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Highlight; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public static class ParseDialogueOpcode +{ + public static IMapDialogueOpcode ParseNextOpcode(Stream reader, byte opcode) + { + return opcode.ToEnum() switch + { + DialogueOpcode.Unknown03 => Unknown03Opcode.ReadOpcode(reader), + DialogueOpcode.Unknown04 => Unknown04Opcode.ReadOpcode(reader), + DialogueOpcode.ScriptCall => ScriptCallOpcode.ReadOpcode(reader), + DialogueOpcode.Unknown06 => Unknown06Opcode.ReadOpcode(reader), + DialogueOpcode.Unknown07 => Unknown07Opcode.ReadOpcode(reader), + DialogueOpcode.Unknown08 => Unknown08Opcode.ReadOpcode(reader), + DialogueOpcode.Unknown09 => Unknown09Opcode.ReadOpcode(reader), + DialogueOpcode.CameraMove => CameraMoveOpcode.ReadOpcode(reader), + DialogueOpcode.Unknown0C => Unknown0COpcode.ReadOpcode(reader), + DialogueOpcode.Unknown0D => Unknown0DOpcode.ReadOpcode(reader), + DialogueOpcode.Unknown10 => IUnknown10Opcode.ReadOpcode(reader), + DialogueOpcode.ItemAquire => ItemAcquireOpcode.ReadOpcode(reader), + DialogueOpcode.Unknown14 => Unknown14Opcode.ReadOpcode(reader), + DialogueOpcode.Unknown15 => Unknown15Opcode.ReadOpcode(reader), + DialogueOpcode.Unknown16 => Unknown16Opcode.ReadOpcode(reader), + DialogueOpcode.TextBox => ITextBoxOpcode.ReadOpcode(reader), + DialogueOpcode.CharacterPortait => CharacterPortaitOpcode.ReadOpcode(reader), + DialogueOpcode.NextPage => NextPageOpcode.ReadOpcode(reader), + DialogueOpcode.Unknown1B => Unknown1BOpcode.ReadOpcode(reader), + DialogueOpcode.Unknown1C => Unknown1COpcode.ReadOpcode(reader), + DialogueOpcode.Pause => IPauseOpcode.ReadOpcode(reader), + DialogueOpcode.Highlight => IHighlightOpcode.ReadOpcode(reader), + DialogueOpcode.NextLine => NextLineOpcode.ReadOpcode(reader), + _ => null, + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/IPauseOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/IPauseOpcode.cs new file mode 100644 index 0000000..4630fe7 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/IPauseOpcode.cs @@ -0,0 +1,21 @@ +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Pause; + +public interface IPauseOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + PauseOption Option { get; set; } + + public static new IMapDialogueOpcode ReadOpcode(Stream reader) + { + var option = reader.ReadRawByte(); + return option.ToEnum() switch + { + PauseOption.Unknown1 => PauseUnknown1Opcode.ReadOpcode(reader), + PauseOption.Unknown2 => PauseUnknown2Opcode.ReadOpcode(reader), + _ => null, + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseOptions.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseOptions.cs new file mode 100644 index 0000000..b7fc462 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseOptions.cs @@ -0,0 +1,7 @@ +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Pause; + +public enum PauseOption : byte +{ + Unknown1 = 0x01, + Unknown2 = 0xFF, +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseUnknown1Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseUnknown1Opcode.cs new file mode 100644 index 0000000..b9b1359 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseUnknown1Opcode.cs @@ -0,0 +1,21 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Pause; + +public class PauseUnknown1Opcode : IPauseOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Pause; + public PauseOption Option { get; set; } = PauseOption.Unknown1; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new PauseUnknown1Opcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseUnknown2Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseUnknown2Opcode.cs new file mode 100644 index 0000000..98af2a1 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Pause/PauseUnknown2Opcode.cs @@ -0,0 +1,19 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Pause; + +public class PauseUnknown2Opcode : IPauseOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Pause; + public PauseOption Option { get; set; } = PauseOption.Unknown2; + public byte Unknown1 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new PauseUnknown2Opcode() + { + Unknown1 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ScriptCallOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ScriptCallOpcode.cs new file mode 100644 index 0000000..1eba85d --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/ScriptCallOpcode.cs @@ -0,0 +1,20 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class ScriptCallOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.ScriptCall; + public byte ScriptId { get; set; } + public byte CharacterId { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new ScriptCallOpcode() + { + ScriptId = reader.ReadRawByte(), + CharacterId = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateOptionsTextBoxOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateOptionsTextBoxOpcode.cs new file mode 100644 index 0000000..b760699 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateOptionsTextBoxOpcode.cs @@ -0,0 +1,52 @@ +using System.Collections.ObjectModel; +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.TextBox; + +/// +/// Creates a textbox in the top-left of the screen +/// that displays a list of options for the palyer to choose from. +/// +public class CreateOptionsTextBoxOpcode : ITextBoxOpcode, IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.TextBox; + public TextBoxOption Option { get; set; } = TextBoxOption.CreateOptionsTextBox; + public byte TextBoxLength { get; set; } + public byte TextBoxHeight { get; set; } + public ObservableCollection NestedOpcodes { get; set; } = new(); + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + CreateOptionsTextBoxOpcode opcode = new() + { + TextBoxLength = reader.ReadRawByte(), + TextBoxHeight = reader.ReadRawByte(), + }; + + do + { + byte data = reader.ReadRawByte(); + if (data.EnumExists()) + { + var nestedOpcode = ParseDialogueOpcode.ParseNextOpcode(reader, data); + opcode.NestedOpcodes.Add(nestedOpcode); + + if (nestedOpcode is ITextBoxOpcode _) + { + return opcode; + } + } + else if (data == 0x02) + { + return opcode; + } + else + { + reader.Seek(-1, SeekOrigin.Current); + opcode.NestedOpcodes.Add(TextOpcode.ReadOpcode(reader)); + } + } while (true); + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateOverworldTextBoxOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateOverworldTextBoxOpcode.cs new file mode 100644 index 0000000..ee8783a --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateOverworldTextBoxOpcode.cs @@ -0,0 +1,50 @@ +using System.Collections.ObjectModel; +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.TextBox; + +/// +/// Creates a textbox at the top center of the screen, +/// generally used for screen transition labels. +/// i.e. - to Carbo Village +/// +public class CreateOverworldTextBoxOpcode : ITextBoxOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.TextBox; + public TextBoxOption Option { get; set; } = TextBoxOption.CreateOverworldTextBox; + public byte TextBoxLength { get; set; } + public byte TextBoxHeight { get; set; } + public ObservableCollection NestedOpcodes { get; set; } = new(); + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + CreateOverworldTextBoxOpcode opcode = new() + { + TextBoxLength = reader.ReadRawByte(), + TextBoxHeight = reader.ReadRawByte(), + }; + + byte data; + do + { + data = reader.ReadRawByte(); + if (data.EnumExists()) + { + var nestedOpcode = ParseDialogueOpcode.ParseNextOpcode(reader, data); + opcode.NestedOpcodes.Add(nestedOpcode); + + if (nestedOpcode is ITextBoxOpcode _) + { + return opcode; + } + } + else + { + reader.Seek(-1, SeekOrigin.Current); + opcode.NestedOpcodes.Add(TextOpcode.ReadOpcode(reader)); + } + } while (true); + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateSubTextBoxOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateSubTextBoxOpcode.cs new file mode 100644 index 0000000..cb0decd --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateSubTextBoxOpcode.cs @@ -0,0 +1,49 @@ +using System.Collections.ObjectModel; +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.TextBox; + +/// +/// Defines a sub textbox that appears during dialogue. +/// Sub textboxes appear overlapping the primary textbox +/// in the top-right of the primary textbox. +/// +internal class CreateSubTextBoxOpcode : ITextBoxOpcode, IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.TextBox; + public TextBoxOption Option { get; set; } = TextBoxOption.CreateSubTextBox; + public byte Unknown1 { get; set; } + public byte TextBoxHeight { get; set; } + public ObservableCollection NestedOpcodes { get; set; } = new(); + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + CreateSubTextBoxOpcode opcode = new() + { + Unknown1 = reader.ReadRawByte(), + TextBoxHeight = reader.ReadRawByte(), + }; + + do + { + byte data = reader.ReadRawByte(); + if (data.EnumExists()) + { + var nestedOpcode = ParseDialogueOpcode.ParseNextOpcode(reader, data); + opcode.NestedOpcodes.Add(nestedOpcode); + + if (nestedOpcode is ITextBoxOpcode _) + { + return opcode; + } + } + else + { + reader.Seek(-1, SeekOrigin.Current); + opcode.NestedOpcodes.Add(TextOpcode.ReadOpcode(reader)); + } + } while (true); + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateTextBoxOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateTextBoxOpcode.cs new file mode 100644 index 0000000..57f7763 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/CreateTextBoxOpcode.cs @@ -0,0 +1,39 @@ +using System.Collections.ObjectModel; +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.TextBox; + +public class CreateTextBoxOpcode : ITextBoxOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.TextBox; + public TextBoxOption Option { get; set; } = TextBoxOption.CreateTextBox; + public ObservableCollection NestedOpcodes { get; set; } = new(); + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + CreateTextBoxOpcode opcode = new(); + + byte data; + do + { + data = reader.ReadRawByte(); + if (data.EnumExists()) + { + var nestedOpcode = ParseDialogueOpcode.ParseNextOpcode(reader, data); + opcode.NestedOpcodes.Add(nestedOpcode); + + if (nestedOpcode is ITextBoxOpcode _) + { + return opcode; + } + } + else + { + reader.Seek(-1, SeekOrigin.Current); + opcode.NestedOpcodes.Add(TextOpcode.ReadOpcode(reader)); + } + } while (true); + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/ITextBoxOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/ITextBoxOpcode.cs new file mode 100644 index 0000000..d11d9a7 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/ITextBoxOpcode.cs @@ -0,0 +1,27 @@ +using System.Collections.ObjectModel; +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.TextBox; + +public interface ITextBoxOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + TextBoxOption Option { get; set; } + public ObservableCollection NestedOpcodes { get; set; } + + public static new IMapDialogueOpcode ReadOpcode(Stream reader) + { + var option = reader.ReadRawByte(); + return option.ToEnum() switch + { + TextBoxOption.RemoveTextBox => RemoveTextBoxOpcode.ReadOpcode(reader), + TextBoxOption.CreateTextBox => CreateTextBoxOpcode.ReadOpcode(reader), + TextBoxOption.Unknown1 => RemoveTextBoxOpcode.ReadOpcode(reader), + TextBoxOption.CreateSubTextBox => CreateSubTextBoxOpcode.ReadOpcode(reader), + TextBoxOption.CreateOptionsTextBox => CreateOptionsTextBoxOpcode.ReadOpcode(reader), + TextBoxOption.CreateOverworldTextBox => CreateOverworldTextBoxOpcode.ReadOpcode(reader), + _ => null, + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/RemoveTextBoxOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/RemoveTextBoxOpcode.cs new file mode 100644 index 0000000..ea75882 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/RemoveTextBoxOpcode.cs @@ -0,0 +1,13 @@ +using System.Collections.ObjectModel; +using System.IO; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.TextBox; + +public class RemoveTextBoxOpcode : ITextBoxOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.TextBox; + public TextBoxOption Option { get; set; } = TextBoxOption.RemoveTextBox; + public ObservableCollection NestedOpcodes { get; set; } = new(); + + public static IMapDialogueOpcode ReadOpcode(Stream reader) => new RemoveTextBoxOpcode(); +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/TextBoxOptions.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/TextBoxOptions.cs new file mode 100644 index 0000000..901ca32 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextBox/TextBoxOptions.cs @@ -0,0 +1,11 @@ +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.TextBox; + +public enum TextBoxOption : byte +{ + RemoveTextBox = 0x00, + CreateTextBox = 0x01, + Unknown1 = 0x02, + CreateSubTextBox = 0x20, + CreateOptionsTextBox = 0x40, + CreateOverworldTextBox = 0x80, +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextOpcode.cs new file mode 100644 index 0000000..10cb5a1 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/TextOpcode.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class TextOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Text; + public string Text { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + + TextOpcode opcode = new(); + + try + { + var data = reader.ReadRawByte(); + while (!data.EnumExists() || data.ToEnum() == DialogueOpcode.NextLine) + { + opcode.Text += data == (byte)DialogueOpcode.NextLine ? + "\n" : + Convert.ToChar(data); + data = reader.ReadRawByte(); + } + + reader.Seek(-1, SeekOrigin.Current); + } + catch (Exception ex) + { + Errors.Errors.Instance.AddError(new Errors.Error("Maps", ex.Message)); + } + + return opcode; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown03Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown03Opcode.cs new file mode 100644 index 0000000..d012d70 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown03Opcode.cs @@ -0,0 +1,22 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown03Opcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown03; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + public byte Unknown3 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown03Opcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + Unknown3 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown04Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown04Opcode.cs new file mode 100644 index 0000000..444810f --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown04Opcode.cs @@ -0,0 +1,18 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown04Opcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown04; + public byte Unknown1 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown04Opcode() + { + Unknown1 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown06Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown06Opcode.cs new file mode 100644 index 0000000..2ddae58 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown06Opcode.cs @@ -0,0 +1,22 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown06Opcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown06; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + public byte Unknown3 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown06Opcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + Unknown3 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown07Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown07Opcode.cs new file mode 100644 index 0000000..75eb8c9 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown07Opcode.cs @@ -0,0 +1,18 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown07Opcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown07; + public byte Unknown1 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown07Opcode() + { + Unknown1 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown08Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown08Opcode.cs new file mode 100644 index 0000000..3a1c7f6 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown08Opcode.cs @@ -0,0 +1,22 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown08Opcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown08; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + public byte Unknown3 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown08Opcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + Unknown3 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown09Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown09Opcode.cs new file mode 100644 index 0000000..a2ddf85 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown09Opcode.cs @@ -0,0 +1,24 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown09Opcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown09; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + public byte Unknown3 { get; set; } + public byte Unknown4 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown09Opcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + Unknown3 = reader.ReadRawByte(), + Unknown4 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown0COpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown0COpcode.cs new file mode 100644 index 0000000..a67be62 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown0COpcode.cs @@ -0,0 +1,18 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown0COpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown0C; + public byte Unknown1 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown0COpcode() + { + Unknown1 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown0DOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown0DOpcode.cs new file mode 100644 index 0000000..b1b4347 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown0DOpcode.cs @@ -0,0 +1,20 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown0DOpcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown0D; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown0DOpcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/IUnknown10Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/IUnknown10Opcode.cs new file mode 100644 index 0000000..7902f6e --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/IUnknown10Opcode.cs @@ -0,0 +1,27 @@ +using System.IO; +using G2DataGUI.Common.Extensions; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Unknown10; + +public interface IUnknown10Opcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public Unknown10Option Option { get; set; } + + public static new IMapDialogueOpcode ReadOpcode(Stream reader) + { + var option = reader.ReadRawByte(); + if (option.EnumExists()) + { + return option.ToEnum() switch + { + Unknown10Option.Unknown1 => Unknown10Unknown1Opcode.ReadOpcode(reader), + Unknown10Option.Unknown2 => Unknown10Unknown2Opcode.ReadOpcode(reader), + _ => null, + }; + } + + reader.Seek(-1, SeekOrigin.Current); + return null; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknon10Options.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknon10Options.cs new file mode 100644 index 0000000..898b81b --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknon10Options.cs @@ -0,0 +1,7 @@ +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Unknown10; + +public enum Unknown10Option : byte +{ + Unknown1 = 0x00, + Unknown2 = 0x02, +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknown10Unknown1Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknown10Unknown1Opcode.cs new file mode 100644 index 0000000..a707388 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknown10Unknown1Opcode.cs @@ -0,0 +1,25 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Unknown10; + +public class Unknown10Unknown1Opcode : IUnknown10Opcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown10; + public Unknown10Option Option { get; set; } = Unknown10Option.Unknown1; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + public short MapID { get; set; } + public byte Unknown3 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown10Unknown1Opcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + MapID = reader.ReadRawShort(), + Unknown3 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknown10Unknown2Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknown10Unknown2Opcode.cs new file mode 100644 index 0000000..13f7361 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown10/Unknown10Unknown2Opcode.cs @@ -0,0 +1,11 @@ +using System.IO; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Unknown10; + +public class Unknown10Unknown2Opcode : IUnknown10Opcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown10; + public Unknown10Option Option { get; set; } = Unknown10Option.Unknown2; + + public static IMapDialogueOpcode ReadOpcode(Stream reader) => new Unknown10Unknown1Opcode(); +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown14Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown14Opcode.cs new file mode 100644 index 0000000..31c4d6e --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown14Opcode.cs @@ -0,0 +1,26 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown14Opcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown14; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + public byte Unknown3 { get; set; } + public byte Unknown4 { get; set; } + public byte Unknown5 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown14Opcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + Unknown3 = reader.ReadRawByte(), + Unknown4 = reader.ReadRawByte(), + Unknown5 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown15Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown15Opcode.cs new file mode 100644 index 0000000..9e2339d --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown15Opcode.cs @@ -0,0 +1,24 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown15Opcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown15; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + public byte Unknown3 { get; set; } + public byte Unknown4 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown15Opcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + Unknown3 = reader.ReadRawByte(), + Unknown4 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown16Opcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown16Opcode.cs new file mode 100644 index 0000000..9e3c4a0 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown16Opcode.cs @@ -0,0 +1,26 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown16Opcode : IMapDialogueOpcode +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown16; + public byte Unknown1 { get; set; } + public byte Unknown2 { get; set; } + public byte Unknown3 { get; set; } + public byte Unknown4 { get; set; } + public byte Unknown5 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown16Opcode() + { + Unknown1 = reader.ReadRawByte(), + Unknown2 = reader.ReadRawByte(), + Unknown3 = reader.ReadRawByte(), + Unknown4 = reader.ReadRawByte(), + Unknown5 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown1BOpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown1BOpcode.cs new file mode 100644 index 0000000..88f39f5 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown1BOpcode.cs @@ -0,0 +1,13 @@ +using System.IO; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown1BOpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown1B; + + public static IMapDialogueOpcode ReadOpcode(Stream _) + { + return new Unknown1BOpcode(); + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown1COpcode.cs b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown1COpcode.cs new file mode 100644 index 0000000..c62b351 --- /dev/null +++ b/src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/Unknown1COpcode.cs @@ -0,0 +1,18 @@ +using System.IO; +using G2DataGUI.IO.Streams; + +namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes; + +public class Unknown1COpcode : IMapDialogueOpcode, IMapDialogueOpcodeReader +{ + public DialogueOpcode Opcode { get; set; } = DialogueOpcode.Unknown1C; + public byte Unknown1 { get; set; } + + public static IMapDialogueOpcode ReadOpcode(Stream reader) + { + return new Unknown1COpcode() + { + Unknown1 = reader.ReadRawByte(), + }; + } +} diff --git a/src/G2DataGUI.Common/Data/Maps/Maps.cs b/src/G2DataGUI.Common/Data/Maps/Maps.cs index ec892bf..8a5880c 100644 --- a/src/G2DataGUI.Common/Data/Maps/Maps.cs +++ b/src/G2DataGUI.Common/Data/Maps/Maps.cs @@ -9,6 +9,7 @@ namespace G2DataGUI.Common.Data.Maps; public class Maps { public static Maps Instance { get; private set; } = new Maps(); + public ObservableCollection GameMapIDs { get; private set; } = new(); public ObservableCollection GameMaps { get; private set; } = new(); public event EventHandler CollectionRefreshed; @@ -26,13 +27,18 @@ private async Task ReadMapsAsync() => private void ReadMaps() { + FileStream reader = null; try { GameMaps.Clear(); + GameMapIDs.Clear(); foreach (var file in Directory.GetFiles(Version.Instance.RootDataDirectory + "map", "*.mdt", SearchOption.AllDirectories)) { - using FileStream reader = File.Open(file, FileMode.Open); + reader = File.Open(file, FileMode.Open); GameMaps.Add(Map.ReadMap(reader, file)); + var name = new DirectoryInfo(Path.GetDirectoryName(file)).Name; + GameMapIDs.Add(Convert.ToUInt16(name, 16)); + reader.Dispose(); } CollectionRefreshed?.Invoke(this, EventArgs.Empty); @@ -41,7 +47,14 @@ private void ReadMaps() { Errors.Errors.Instance.AddError(new Error("Maps", ex.Message)); } - } + finally + { + reader?.Dispose(); + } + + using var vorbis = new NVorbis.VorbisReader("F:\\Steam\\steamapps\\common\\Grandia II Anniversary Edition\\content\\data\\sound\\staffrollus.ogg"); + var channels = vorbis.Channels; + } private void WriteMaps() { diff --git a/src/G2DataGUI.Common/Extensions/EnumExtensions.cs b/src/G2DataGUI.Common/Extensions/EnumExtensions.cs new file mode 100644 index 0000000..33931e7 --- /dev/null +++ b/src/G2DataGUI.Common/Extensions/EnumExtensions.cs @@ -0,0 +1,22 @@ +using System; + +namespace G2DataGUI.Common.Extensions; + +public static class EnumExtensions +{ + public static T ToEnum(this string enumString) => + (T)Enum.Parse(typeof(T), enumString); + + public static bool EnumExists(this byte enumValue) where T : Enum => + Enum.IsDefined(typeof(T), enumValue); + + public static T ToEnum(this byte enumValue) where T : Enum + { + if (Enum.IsDefined(typeof(T), enumValue)) + { + return (T)(object)enumValue; + } + + throw new ArgumentOutOfRangeException(enumValue.ToString()); + } +} diff --git a/src/G2DataGUI.Common/G2DataGUI.Common.csproj b/src/G2DataGUI.Common/G2DataGUI.Common.csproj index 57004a1..026ec4e 100644 --- a/src/G2DataGUI.Common/G2DataGUI.Common.csproj +++ b/src/G2DataGUI.Common/G2DataGUI.Common.csproj @@ -6,6 +6,10 @@ true + + + + diff --git a/src/G2DataGUI.Common/Paths/ProjectPaths.cs b/src/G2DataGUI.Common/Paths/ProjectPaths.cs new file mode 100644 index 0000000..08aa944 --- /dev/null +++ b/src/G2DataGUI.Common/Paths/ProjectPaths.cs @@ -0,0 +1,26 @@ +namespace G2DataGUI.Common.Paths; + +public class ProjectPaths +{ + public const string DocumentationDirectory = ".\\documentation"; + + public const string MovesCSVPath = $"{DocumentationDirectory}\\MOVES.CSV"; + public const string SkillsCSVPath = $"{DocumentationDirectory}\\SKILLS.CSV"; + public const string InitialCSVPath = $"{DocumentationDirectory}\\INITIAL.CSV"; + public const string LevelupsCSVPath = $"{DocumentationDirectory}\\LEVELUPS.CSV"; + public const string LevelupsSumCSVPath = $"{DocumentationDirectory}\\LEVELUPS_SUM.CSV"; + public const string ManaeggsCSVPath = $"{DocumentationDirectory}\\MANAEGGS.CSV"; + public const string SkillbooksCSVPath = $"{DocumentationDirectory}\\SKILLBOOKS.CSV"; + public const string SpecialsCSVPath = $"{DocumentationDirectory}\\SPECIALS.CSV"; + public const string ItemsCSVPath = $"{DocumentationDirectory}\\ITEMS.CSV"; + + public const string EnemiesCSVPath = $"{DocumentationDirectory}\\ENEMIES.CSV"; + public const string EnemiesHardmodeCSVPath = $"{DocumentationDirectory}\\ENEMIES_HARDMODE.CSV"; + public const string EnemyMovesCSVPath = $"{DocumentationDirectory}\\ENEMY_MOVES.CSV"; + public const string EnemyHardmodeMovesCSVPath = $"{DocumentationDirectory}\\ENEMY_HARDMODE_MOVES.CSV"; + + public const string BossesCSVPath = $"{DocumentationDirectory}\\BOSSES.CSV"; + public const string BossesHardmodeCSVPath = $"{DocumentationDirectory}\\BOSSES_HARDMODE.CSV"; + public const string BossMovesCSVPath = $"{DocumentationDirectory}\\BOSS_MOVES.CSV"; + public const string BossHardmodeMovesCSVPath = $"{DocumentationDirectory}\\BOSS_HARDMODE_MOVES.CSV"; +} diff --git a/src/G2DataGUI.Common/ProjectPaths.cs b/src/G2DataGUI.Common/ProjectPaths.cs deleted file mode 100644 index 477ae54..0000000 --- a/src/G2DataGUI.Common/ProjectPaths.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace G2DataGUI.Common; - -public class ProjectPaths -{ - public const string DocumentationDirectory = ".\\documentation"; - - public const string MovesCSVPath = $"{DocumentationDirectory}\\MOVES.CSV"; - public const string SkillsCSVPath = $"{DocumentationDirectory}\\SKILLS.CSV"; - public const string InitialCSVPath = $"{DocumentationDirectory}\\INITIAL.CSV"; - public const string LevelupsCSVPath = $"{DocumentationDirectory}\\LEVELUPS.CSV"; - public const string LevelupsSumCSVPath = $"{DocumentationDirectory}\\LEVELUPS_SUM.CSV"; - public const string ManaeggsCSVPath = $"{DocumentationDirectory}\\MANAEGGS.CSV"; - public const string SkillbooksCSVPath = $"{DocumentationDirectory}\\SKILLBOOKS.CSV"; - public const string SpecialsCSVPath = $"{DocumentationDirectory}\\SPECIALS.CSV"; - public const string ItemsCSVPath = $"{DocumentationDirectory}\\ITEMS.CSV"; - - public const string EnemiesCSVPath = $"{DocumentationDirectory}\\ENEMIES.CSV"; - public const string EnemiesHardmodeCSVPath = $"{DocumentationDirectory}\\ENEMIES_HARDMODE.CSV"; - public const string EnemyMovesCSVPath = $"{DocumentationDirectory}\\ENEMY_MOVES.CSV"; - public const string EnemyHardmodeMovesCSVPath = $"{DocumentationDirectory}\\ENEMY_HARDMODE_MOVES.CSV"; - - public const string BossesCSVPath = $"{DocumentationDirectory}\\BOSSES.CSV"; - public const string BossesHardmodeCSVPath = $"{DocumentationDirectory}\\BOSSES_HARDMODE.CSV"; - public const string BossMovesCSVPath = $"{DocumentationDirectory}\\BOSS_MOVES.CSV"; - public const string BossHardmodeMovesCSVPath = $"{DocumentationDirectory}\\BOSS_HARDMODE_MOVES.CSV"; -} diff --git a/src/G2DataGUI.Common/Version.cs b/src/G2DataGUI.Common/Version.cs index 8811d7c..daa8c58 100644 --- a/src/G2DataGUI.Common/Version.cs +++ b/src/G2DataGUI.Common/Version.cs @@ -15,8 +15,9 @@ private Version() } } - public string RootDataDirectory - { - get => IsHDVersion ? ".\\content\\data\\afs\\" : ".\\data\\afs\\"; - } -} \ No newline at end of file + public string RootDataDirectory => + IsHDVersion ? ".\\content\\data\\afs\\" : ".\\data\\afs\\"; + + public string RootTextDirectory => + IsHDVersion ? ".\\content\\data\\text" : ".\\data\\text"; +} diff --git a/src/G2DataGUI.IO/Extensions/StreamExtensions.cs b/src/G2DataGUI.IO/Extensions/StreamExtensions.cs index fa70318..d361cf0 100644 --- a/src/G2DataGUI.IO/Extensions/StreamExtensions.cs +++ b/src/G2DataGUI.IO/Extensions/StreamExtensions.cs @@ -57,11 +57,11 @@ public static byte[] StreamToBytesArray(this Stream stream) public static ushort ReadRawUShort(this Stream stream) => BinaryPrimitives.ReadUInt16LittleEndian(stream.InternalRead(2)); public static int ReadRawInt(this Stream stream) => BinaryPrimitives.ReadInt32LittleEndian(stream.InternalRead(4)); public static uint ReadRawUInt(this Stream stream) => BinaryPrimitives.ReadUInt32LittleEndian(stream.InternalRead(4)); - public static long ReadRawLong(this Stream stream) => BinaryPrimitives.ReadInt64LittleEndian(stream.InternalRead(4)); - public static ulong ReadRawULong(this Stream stream) => BinaryPrimitives.ReadUInt64LittleEndian(stream.InternalRead(4)); - public static Half ReadRawHalf(this Stream stream) => BinaryPrimitives.ReadHalfLittleEndian(stream.InternalRead(2)); + public static long ReadRawLong(this Stream stream) => BinaryPrimitives.ReadInt64LittleEndian(stream.InternalRead(8)); + public static ulong ReadRawULong(this Stream stream) => BinaryPrimitives.ReadUInt64LittleEndian(stream.InternalRead(8)); + public static Half ReadRawHalf(this Stream stream) => BitConverter.Int16BitsToHalf(stream.ReadRawShort()); public static float ReadRawFloat(this Stream stream) => BitConverter.Int32BitsToSingle(stream.ReadRawInt()); - public static double ReadRawDouble(this Stream stream) => BitConverter.Int64BitsToDouble(stream.ReadRawInt()); + public static double ReadRawDouble(this Stream stream) => BitConverter.Int64BitsToDouble(stream.ReadRawLong()); public static byte[] ReadRawByteArray(this Stream stream, uint numBytes) => stream.InternalRead(numBytes).ToArray(); public static int[] ReadRawIntArray(this Stream stream, uint numInts) { diff --git a/src/G2DataGUI/Assets/Styles/Styles.xaml b/src/G2DataGUI/Assets/Styles/Styles.xaml index d4a0281..1cc3e39 100644 --- a/src/G2DataGUI/Assets/Styles/Styles.xaml +++ b/src/G2DataGUI/Assets/Styles/Styles.xaml @@ -84,7 +84,43 @@ + + + + + + + @@ -215,33 +251,6 @@ - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/G2DataGUI/UI/Views/Content/MapDialogue.axaml.cs b/src/G2DataGUI/UI/Views/Content/MapDialogue.axaml.cs new file mode 100644 index 0000000..67721fd --- /dev/null +++ b/src/G2DataGUI/UI/Views/Content/MapDialogue.axaml.cs @@ -0,0 +1,13 @@ +using Avalonia.Controls; +using G2DataGUI.UI.ViewModels; + +namespace G2DataGUI.UI.Views.Content; + +public partial class MapDialogue : UserControl +{ + public MapDialogue() + { + DataContext = MapDialogueViewModel.Instance; + InitializeComponent(); + } +} diff --git a/src/G2DataGUI/UI/Views/Content/Maps.axaml b/src/G2DataGUI/UI/Views/Content/Maps.axaml index 3686451..21a59ca 100644 --- a/src/G2DataGUI/UI/Views/Content/Maps.axaml +++ b/src/G2DataGUI/UI/Views/Content/Maps.axaml @@ -61,6 +61,7 @@ + + diff --git a/src/G2DataGUI/UI/Views/Content/Maps.axaml.cs b/src/G2DataGUI/UI/Views/Content/Maps.axaml.cs index 927554e..bb19814 100644 --- a/src/G2DataGUI/UI/Views/Content/Maps.axaml.cs +++ b/src/G2DataGUI/UI/Views/Content/Maps.axaml.cs @@ -54,6 +54,9 @@ private void MapNavPanelOnSelectionChange(object sender, NavigationViewSelection case "MapShopPage": MapNavPanel.Content = MapShopPage; break; + case "MapDialoguePage": + MapNavPanel.Content = MapDialoguePage; + break; } } }