Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dialogue opcode parsing #68

Merged
merged 13 commits into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
<PackageVersion Include="CommunityToolkit.Diagnostics" Version="8.2.1" />
<PackageVersion Include="Pfim" Version="0.11.2" />

<PackageVersion Include="NVorbis" Version="0.10.5" />

<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageVersion Include="NUnit" Version="3.13.3" />
Expand Down
31 changes: 21 additions & 10 deletions documentation/Data File Details.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)

Expand Down
13 changes: 10 additions & 3 deletions src/G2DataGUI.Common/Data/Maps/Map.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -20,16 +22,18 @@ 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)
{
Map map = new()
{
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++)
Expand Down Expand Up @@ -190,4 +194,7 @@ private void ReadMapName()
}
}
}

private string ScnrFilePath() =>
$"{Version.Instance.RootTextDirectory}\\en\\scnr\\{FileName}.scn";
}
46 changes: 36 additions & 10 deletions src/G2DataGUI.Common/Data/Maps/MapDialogue.cs
Original file line number Diff line number Diff line change
@@ -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<byte[]> DialogueSections { get; set; } = new();
public ObservableCollection<ObservableCollection<IMapDialogueOpcode>> DialogueSectionOpcodes { get; set; } = new();

public static MapDialogue ReadMapDialogue(Stream reader, uint dialogueSectionLength)
{
Expand All @@ -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<IMapDialogueOpcode>());
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;
}
}
2 changes: 1 addition & 1 deletion src/G2DataGUI.Common/Data/Maps/MapDialogueHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ public static MapDialogueOffset ReadMapDialogueOffset(Stream reader)
};
return offset;
}
}
}
Original file line number Diff line number Diff line change
@@ -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(),
};
}
}
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Appears to always be 0x00
/// </summary>
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(),
};
}
}
129 changes: 129 additions & 0 deletions src/G2DataGUI.Common/Data/Maps/MapDialogueOpcodes/DialogueOpcodes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes;

public enum DialogueOpcode : byte
{
/// <summary>
/// Not sure how to handle text
/// so considering this a No Op
/// opcode, to house the text itself
/// </summary>
Text = 0x00,

/// <summary>
/// Completely unsure, likely 3 parameters
/// </summary>
Unknown03 = 0x03,

/// <summary>
/// Completely unknown, likely 1 parameter
/// </summary>
Unknown04 = 0x04,

/// <summary>
/// Seems to define a call to a script
/// within the Map's script list
/// </summary>
ScriptCall = 0x05,

/// <summary>
/// Completely unknown, may be 4 parameters
/// </summary>
Unknown06 = 0x06,

/// <summary>
/// Completely unknown, may be 1 or 4 parameters
/// </summary>
Unknown07 = 0x07,

/// <summary>
/// Completely unknown, likely 2 parameters
/// </summary>
Unknown08 = 0x08,

/// <summary>
/// Completely unknown, may be 4 parameters
/// </summary>
Unknown09 = 0x09,

/// <summary>
/// Seems to deal with camera movement
/// </summary>
CameraMove = 0x0B,

/// <summary>
/// Completely unknown, seems to have 1 parameter
/// </summary>
Unknown0C = 0x0C,

/// <summary>
/// Completely unknown, seems to have 2 parameters
/// </summary>
Unknown0D = 0x0D,

/// <summary>
/// Completely unknown, no clue on parameters(1 parameter?).
/// See Map 1000, section 8, offset 0x24.
/// Also see Map 1000, section 10, offset 0x1F.
/// </summary>
Unknown10 = 0x10,

/// <summary>
/// Adds items to inventory
/// </summary>
ItemAquire = 0x11,

/// <summary>
/// Completely unknown, no clue on parameters
/// </summary>
Unknown14 = 0x14,

/// <summary>
/// Completely unknown, likely 4 parameters
/// </summary>
Unknown15 = 0x15,

/// <summary>
/// Completely unknown, exists with tutorial guy dialogue...
/// </summary>
Unknown16 = 0x16,

/// <summary>
/// Defines a action around textboxes
/// </summary>
TextBox = 0x17,

/// <summary>
/// Defines which character protrait to display
/// </summary>
CharacterPortait = 0x18,

/// <summary>
/// Clears/Next pages within the textbox
/// </summary>
NextPage = 0x1A,

/// <summary>
/// Completely unknown, appears to have no parameters
/// </summary>
Unknown1B = 0x1B,

/// <summary>
/// Completely unknown, seems to have 1 parameter
/// </summary>
Unknown1C = 0x1C,

/// <summary>
/// Pauses text rendering for a time(tick based?)
/// </summary>
Pause = 0x1D,

/// <summary>
/// Creates a highlighted section of text
/// </summary>
Highlight = 0x1E,

/// <summary>
/// Moves text rendering to next line
/// </summary>
NextLine = 0x1F,
}
Original file line number Diff line number Diff line change
@@ -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<IMapDialogueOpcode> NestedOpcodes { get; set; } = new();

public static IMapDialogueOpcode ReadOpcode(Stream reader)
{
return new HighlightEndOpcode();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace G2DataGUI.Common.Data.Maps.MapDialogueOpcodes.Highlight;

public enum HighlightOption : byte
{
Start = 0x0C,
End = 0x0F,
}
Loading