diff --git a/.editorconfig b/.editorconfig
index da8f0f4ab..df97264a7 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -2,23 +2,16 @@ root = true
[*]
charset = utf-8
-end_of_line = lf
+end_of_line = crlf
insert_final_newline = true
indent_style = space
indent_size = 4
tab_size = 4
-[*.md]
-end_of_line = crlf
-
-[*.sln]
-end_of_line = crlf
-
-[*.csproj]
-end_of_line = crlf
+[*.sh]
+end_of_line = lf
[*.cs]
-end_of_line = lf
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
diff --git a/.github/workflows/format-code.yml b/.github/workflows/format-code.yml
new file mode 100644
index 000000000..d767e707b
--- /dev/null
+++ b/.github/workflows/format-code.yml
@@ -0,0 +1,29 @@
+name: Format code
+on:
+ push:
+ pull_request:
+jobs:
+ format-code:
+ runs-on: ubuntu-latest
+ container:
+ image: mcr.microsoft.com/dotnet/sdk:latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ - name: Download formatting tool
+ run: dotnet tool install -g dotnet-format
+ - name: Format source code
+ run: |
+ export PATH="$PATH:/github/home/.dotnet/tools"
+ dotnet format
+ - name: Check if files have been modified
+ id: git-check
+ run: echo ::set-output name=modified::$(if git diff-index --quiet HEAD --; then echo "false"; else echo "true"; fi)
+ - name: Push changes
+ if: steps.git-check.outputs.modified == 'true'
+ run: |
+ git config --global user.name 'Formatting bot'
+ git config --global user.email 'xeeynamo@users.noreply.github.com'
+ git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
+ git commit -am "Format code"
+ git push
diff --git a/IteEditor/IteEntry.cs b/IteEditor/IteEntry.cs
index de7ed222a..99fc98d9f 100644
--- a/IteEditor/IteEntry.cs
+++ b/IteEditor/IteEntry.cs
@@ -1,20 +1,20 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Text;
-using System.Windows.Forms;
-using OpenKh.Bbs.SystemData;
-
-namespace OpenKh.Tools.IteEditor
-{
- public partial class IteEntry : UserControl
- {
- public IteEntry()
- {
- InitializeComponent();
- ItemComboBox.DataSource = Enum.GetValues(typeof(Item.Type));
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using OpenKh.Bbs.SystemData;
+
+namespace OpenKh.Tools.IteEditor
+{
+ public partial class IteEntry : UserControl
+ {
+ public IteEntry()
+ {
+ InitializeComponent();
+ ItemComboBox.DataSource = Enum.GetValues(typeof(Item.Type));
+ }
+ }
+}
diff --git a/IteEditor/MainForm.cs b/IteEditor/MainForm.cs
index fe6198823..3274954be 100644
--- a/IteEditor/MainForm.cs
+++ b/IteEditor/MainForm.cs
@@ -1,93 +1,93 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.IO;
-using OpenKh.Bbs;
-using OpenKh.Bbs.SystemData;
-
-namespace OpenKh.Tools.IteEditor
-{
- public partial class MainForm : Form
- {
- public MainForm()
- {
- InitializeComponent();
- }
-
- public Ite ite = new Ite();
- Stream iteFile;
-
- private void UpdateParameters(Ite ite)
- {
- int cnt = 1;
- for(int i = 0; i < ite.header.WeaponDataCount; i++)
- {
- IteEntry itEntry = new IteEntry();
- itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
- itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.WeaponList[i].ItemID;
- FlowWeapons.Controls.Add(itEntry);
- cnt++;
- }
-
- for (int i = 0; i < ite.header.FlavorDataCount; i++)
- {
- IteEntry itEntry = new IteEntry();
- itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
- itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.FlavorList[i].ItemID;
- FlowFlavors.Controls.Add(itEntry);
- cnt++;
- }
-
- for (int i = 0; i < ite.header.KeyItemDataCount; i++)
- {
- IteEntry itEntry = new IteEntry();
- itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
- itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.KeyItemList[i].ItemID;
- FlowKeyItem.Controls.Add(itEntry);
- cnt++;
- }
-
- for (int i = 0; i < ite.header.KeyItemHideDataCount; i++)
- {
- IteEntry itEntry = new IteEntry();
- itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
- itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.KeyItemHideList[i].ItemID;
- FlowKeyItemHide.Controls.Add(itEntry);
- cnt++;
- }
-
- for (int i = 0; i < ite.header.SynthesisDataCount; i++)
- {
- IteEntry itEntry = new IteEntry();
- itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
- itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.SynthesisList[i].ItemID;
- FlowSynthesis.Controls.Add(itEntry);
- cnt++;
- }
-
- }
-
- private void LoadITEButton_Click(object sender, EventArgs e)
- {
- OpenFileDialog dialog = new OpenFileDialog();
- dialog.Filter = "Item files (*.ite)|*.ite|All files (*.*)|*.*";
- DialogResult result = dialog.ShowDialog();
-
- if (result == DialogResult.OK)
- {
- if (iteFile != null)
- iteFile.Close();
- iteFile = File.OpenRead(dialog.FileName);
- ite = Ite.Read(iteFile);
- UpdateParameters(ite);
- //SaveITEButton.Enabled = true;
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.IO;
+using OpenKh.Bbs;
+using OpenKh.Bbs.SystemData;
+
+namespace OpenKh.Tools.IteEditor
+{
+ public partial class MainForm : Form
+ {
+ public MainForm()
+ {
+ InitializeComponent();
+ }
+
+ public Ite ite = new Ite();
+ Stream iteFile;
+
+ private void UpdateParameters(Ite ite)
+ {
+ int cnt = 1;
+ for (int i = 0; i < ite.header.WeaponDataCount; i++)
+ {
+ IteEntry itEntry = new IteEntry();
+ itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
+ itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.WeaponList[i].ItemID;
+ FlowWeapons.Controls.Add(itEntry);
+ cnt++;
+ }
+
+ for (int i = 0; i < ite.header.FlavorDataCount; i++)
+ {
+ IteEntry itEntry = new IteEntry();
+ itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
+ itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.FlavorList[i].ItemID;
+ FlowFlavors.Controls.Add(itEntry);
+ cnt++;
+ }
+
+ for (int i = 0; i < ite.header.KeyItemDataCount; i++)
+ {
+ IteEntry itEntry = new IteEntry();
+ itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
+ itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.KeyItemList[i].ItemID;
+ FlowKeyItem.Controls.Add(itEntry);
+ cnt++;
+ }
+
+ for (int i = 0; i < ite.header.KeyItemHideDataCount; i++)
+ {
+ IteEntry itEntry = new IteEntry();
+ itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
+ itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.KeyItemHideList[i].ItemID;
+ FlowKeyItemHide.Controls.Add(itEntry);
+ cnt++;
+ }
+
+ for (int i = 0; i < ite.header.SynthesisDataCount; i++)
+ {
+ IteEntry itEntry = new IteEntry();
+ itEntry.ITE_GBox.Text = "ITC Entry " + cnt;
+ itEntry.ItemComboBox.SelectedItem = (Item.Type)ite.SynthesisList[i].ItemID;
+ FlowSynthesis.Controls.Add(itEntry);
+ cnt++;
+ }
+
+ }
+
+ private void LoadITEButton_Click(object sender, EventArgs e)
+ {
+ OpenFileDialog dialog = new OpenFileDialog();
+ dialog.Filter = "Item files (*.ite)|*.ite|All files (*.*)|*.*";
+ DialogResult result = dialog.ShowDialog();
+
+ if (result == DialogResult.OK)
+ {
+ if (iteFile != null)
+ iteFile.Close();
+ iteFile = File.OpenRead(dialog.FileName);
+ ite = Ite.Read(iteFile);
+ UpdateParameters(ite);
+ //SaveITEButton.Enabled = true;
+ }
+ }
+ }
+}
diff --git a/IteEditor/Program.cs b/IteEditor/Program.cs
index f73189ab1..78136964e 100644
--- a/IteEditor/Program.cs
+++ b/IteEditor/Program.cs
@@ -1,23 +1,23 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace OpenKh.Tools.IteEditor
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- Application.SetHighDpiMode(HighDpiMode.SystemAware);
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new MainForm());
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace OpenKh.Tools.IteEditor
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.SetHighDpiMode(HighDpiMode.SystemAware);
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainForm());
+ }
+ }
+}
diff --git a/OpenKh.Bbs/Arc.cs b/OpenKh.Bbs/Arc.cs
index 445d50e26..74a5db04d 100644
--- a/OpenKh.Bbs/Arc.cs
+++ b/OpenKh.Bbs/Arc.cs
@@ -1,116 +1,116 @@
-using OpenKh.Common;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Xe.BinaryMapper;
-
-namespace OpenKh.Bbs
-{
- public static class Arc
- {
- private const int MagicCode = 0x435241;
- private const int Version = 1;
- private const int MetaEntrySize = 0x20;
- private const int Alignment = 0x10;
-
- private class Header
- {
- [Data] public int MagicCode { get; set; }
- [Data] public short Version { get; set; }
- [Data] public short EntryCount { get; set; }
- [Data] public int Unused08 { get; set; }
- [Data] public int Unused0c { get; set; }
- }
-
- private class MetaEntry
- {
- [Data] public uint DirectoryPointer { get; set; }
- [Data] public int Offset { get; set; }
- [Data] public int Length { get; set; }
- [Data] public int Unused { get; set; }
- [Data(Count = 16)] public string Name { get; set; }
-
- public bool IsPointer => DirectoryPointer != 0;
- }
-
- public class Entry
- {
- public bool IsLink => DirectoryPointer != 0;
- public uint DirectoryPointer { get; set; }
- public string Name { get; set; }
- public byte[] Data { get; set; }
-
- public string Path
- {
- get
- {
- if (DirectoryPointer == 0)
- return Name;
-
- var directory = Bbsa.GetDirectoryName(DirectoryPointer);
- if (string.IsNullOrEmpty(directory))
- return $"{DirectoryPointer:X08}/{Name}";
-
- return $"{directory}/{Name}";
-
- }
- }
- }
-
- public static IEnumerable Read(Stream stream)
- {
- var header = BinaryMapping.ReadObject(stream.SetPosition(0));
-
- return Enumerable.Range(0, header.EntryCount)
- .Select(x => BinaryMapping.ReadObject(stream))
- .ToArray()
- .Select(x => new Entry
- {
- DirectoryPointer = x.DirectoryPointer,
- Name = x.Name,
- Data = x.IsPointer ? null : stream.SetPosition(x.Offset).ReadBytes(x.Length)
- })
- .ToArray();
- }
-
- public static void Write(this IEnumerable entries, Stream stream)
- {
- var myEntries = entries.ToArray();
-
- stream.Position = 0;
- BinaryMapping.WriteObject(stream, new Header
- {
- MagicCode = MagicCode,
- Version = Version,
- EntryCount = (short)myEntries.Length,
- Unused08 = 0,
- Unused0c = 0
- });
-
- var dataStartOffset = (int)stream.Position + myEntries.Length * MetaEntrySize;
- foreach (var entry in myEntries)
- {
- BinaryMapping.WriteObject(stream, new MetaEntry
- {
- DirectoryPointer = entry.DirectoryPointer,
- Offset = entry.IsLink ? 0 : dataStartOffset,
- Length = entry.IsLink ? 0 : entry.Data.Length,
- Unused = 0,
- Name = entry.Name
- });
-
- dataStartOffset += Helpers.Align(entry.Data?.Length ?? 0, Alignment);
- }
-
- foreach (var entry in myEntries.Where(x => !x.IsLink))
- {
- stream.Write(entry.Data, 0, entry.Data.Length);
- stream.AlignPosition(Alignment);
- }
- }
-
- public static bool IsValid(Stream stream) =>
- stream.Length >= 4 &&
- new BinaryReader(stream.SetPosition(0)).ReadInt32() == MagicCode;
- }
-}
+using OpenKh.Common;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Xe.BinaryMapper;
+
+namespace OpenKh.Bbs
+{
+ public static class Arc
+ {
+ private const int MagicCode = 0x435241;
+ private const int Version = 1;
+ private const int MetaEntrySize = 0x20;
+ private const int Alignment = 0x10;
+
+ private class Header
+ {
+ [Data] public int MagicCode { get; set; }
+ [Data] public short Version { get; set; }
+ [Data] public short EntryCount { get; set; }
+ [Data] public int Unused08 { get; set; }
+ [Data] public int Unused0c { get; set; }
+ }
+
+ private class MetaEntry
+ {
+ [Data] public uint DirectoryPointer { get; set; }
+ [Data] public int Offset { get; set; }
+ [Data] public int Length { get; set; }
+ [Data] public int Unused { get; set; }
+ [Data(Count = 16)] public string Name { get; set; }
+
+ public bool IsPointer => DirectoryPointer != 0;
+ }
+
+ public class Entry
+ {
+ public bool IsLink => DirectoryPointer != 0;
+ public uint DirectoryPointer { get; set; }
+ public string Name { get; set; }
+ public byte[] Data { get; set; }
+
+ public string Path
+ {
+ get
+ {
+ if (DirectoryPointer == 0)
+ return Name;
+
+ var directory = Bbsa.GetDirectoryName(DirectoryPointer);
+ if (string.IsNullOrEmpty(directory))
+ return $"{DirectoryPointer:X08}/{Name}";
+
+ return $"{directory}/{Name}";
+
+ }
+ }
+ }
+
+ public static IEnumerable Read(Stream stream)
+ {
+ var header = BinaryMapping.ReadObject(stream.SetPosition(0));
+
+ return Enumerable.Range(0, header.EntryCount)
+ .Select(x => BinaryMapping.ReadObject(stream))
+ .ToArray()
+ .Select(x => new Entry
+ {
+ DirectoryPointer = x.DirectoryPointer,
+ Name = x.Name,
+ Data = x.IsPointer ? null : stream.SetPosition(x.Offset).ReadBytes(x.Length)
+ })
+ .ToArray();
+ }
+
+ public static void Write(this IEnumerable entries, Stream stream)
+ {
+ var myEntries = entries.ToArray();
+
+ stream.Position = 0;
+ BinaryMapping.WriteObject(stream, new Header
+ {
+ MagicCode = MagicCode,
+ Version = Version,
+ EntryCount = (short)myEntries.Length,
+ Unused08 = 0,
+ Unused0c = 0
+ });
+
+ var dataStartOffset = (int)stream.Position + myEntries.Length * MetaEntrySize;
+ foreach (var entry in myEntries)
+ {
+ BinaryMapping.WriteObject(stream, new MetaEntry
+ {
+ DirectoryPointer = entry.DirectoryPointer,
+ Offset = entry.IsLink ? 0 : dataStartOffset,
+ Length = entry.IsLink ? 0 : entry.Data.Length,
+ Unused = 0,
+ Name = entry.Name
+ });
+
+ dataStartOffset += Helpers.Align(entry.Data?.Length ?? 0, Alignment);
+ }
+
+ foreach (var entry in myEntries.Where(x => !x.IsLink))
+ {
+ stream.Write(entry.Data, 0, entry.Data.Length);
+ stream.AlignPosition(Alignment);
+ }
+ }
+
+ public static bool IsValid(Stream stream) =>
+ stream.Length >= 4 &&
+ new BinaryReader(stream.SetPosition(0)).ReadInt32() == MagicCode;
+ }
+}
diff --git a/OpenKh.Bbs/Bbsa.Entry.cs b/OpenKh.Bbs/Bbsa.Entry.cs
index 75e947308..6349302e4 100644
--- a/OpenKh.Bbs/Bbsa.Entry.cs
+++ b/OpenKh.Bbs/Bbsa.Entry.cs
@@ -1,175 +1,193 @@
-using OpenKh.Common;
-using System;
-using System.IO;
-using Xe.IO;
-
-namespace OpenKh.Bbs
-{
- public partial class Bbsa
- {
- public class Entry
- {
- private const int SectorLength = 0x800;
- private readonly Header bbsaHeader;
- private readonly int offset;
- private readonly int length;
- private readonly string fileName;
- private readonly string folderName;
-
- internal Entry(
- Bbsa bbsa,
- int offset,
- int length,
- string fileName,
- string folderName,
- uint fileHash,
- uint folderHash)
- {
- bbsaHeader = bbsa._header;
- this.offset = offset;
- this.length = length;
- this.fileName = fileName;
- this.folderName = folderName;
- FileHash = fileHash;
- FolderHash = folderHash;
- }
-
- public uint FileHash { get; }
- public uint FolderHash { get; }
- public string Name => $"{FolderName}/{FileName}";
- public bool HasCompleteName => fileName != null && folderName != null;
-
- public string CalculateNameWithExtension(Func bbsaLoader)
- {
- if (!CalculateArchiveOffset(bbsaHeader, offset, out var archiveIndex, out var physicalSector))
- return Name;
-
- var stream = bbsaLoader(archiveIndex);
- var extension = CalculateExtension(stream, physicalSector * SectorLength);
- if (extension == null)
- return Name;
-
- return $"{Name}.{extension}";
- }
-
- public SubStream OpenStream(Func bbsaLoader)
- {
- if (!CalculateArchiveOffset(bbsaHeader, offset, out var archiveIndex, out var physicalSector))
- return null;
-
- var stream = bbsaLoader(archiveIndex);
- var subStreamOffset = physicalSector * SectorLength;
- var subStreamLength = length * SectorLength;
-
- if (length == 0xFFF)
- {
- if (IsPsmf(stream, subStreamOffset))
- subStreamLength = GetPsmfLength(stream, subStreamOffset);
- }
-
- return new SubStream(stream, subStreamOffset, subStreamLength);
- }
-
- private string FileName => fileName ?? $"@{FileHash:X08}";
- private string FolderName =>
- folderName ??
- CalculateFolderName(FolderHash) ??
- $"@{FolderHash:X08}";
- }
-
- private static bool IsPsmf(Stream stream, int offset) =>
- new BinaryReader(stream.SetPosition(offset)).ReadInt32() == 0x464D5350;
-
- private static int GetPsmfLength(Stream stream, int offset)
- {
- stream.SetPosition(offset + 12);
- return (stream.ReadByte() << 24) |
- (stream.ReadByte() << 16) |
- (stream.ReadByte() << 8) |
- (stream.ReadByte() << 0);
- }
-
- private static bool CalculateArchiveOffset(
- Header header, int offset, out int archiveIndex, out int physicalSector)
- {
- if (offset >= header.Archive4Sector)
- {
- archiveIndex = 4;
- physicalSector = offset - header.Archive4Sector + 1;
- }
- else if (offset >= header.Archive3Sector)
- {
- archiveIndex = 3;
- physicalSector = offset - header.Archive3Sector + 1;
- }
- else if (offset >= header.Archive2Sector)
- {
- archiveIndex = 2;
- physicalSector = offset - header.Archive2Sector + 1;
- }
- else if (offset >= header.Archive1Sector)
- {
- archiveIndex = 1;
- physicalSector = offset - header.Archive1Sector + 1;
- }
- else if (offset >= header.Archive0Sector)
- {
- archiveIndex = 0;
- physicalSector = offset + header.Archive0Sector;
- }
- else
- {
- archiveIndex = -1;
- physicalSector = -1;
- return false;
- }
-
- return true;
- }
-
- private static string CalculateExtension(Stream stream, int offset)
- {
- stream.Position = offset;
- var magicCode = new BinaryReader(stream).ReadUInt32();
- switch (magicCode)
- {
- case 0x61754C1B: return "lub";
- case 0x41264129: return "ice";
- case 0x44544340: return "ctd";
- case 0x50444540: return "edp";
- case 0x00435241: return "arc";
- case 0x44424D40: return "mbd";
- case 0x00444145: return "ead";
- case 0x07504546: return "fep";
- case 0x00425449: return "itb";
- case 0x00435449: return "itc";
- case 0x00455449: return "ite";
- case 0x004D4150: return "pam";
- case 0x004F4D50: return "pmo";
- case 0x42444553: return "scd";
- case 0x324D4954: return "tm2";
- case 0x00415854: return "txa";
- case 0x00617865: return "exa";
- default: return null;
- }
- }
-
- private static string CalculateFolderName(uint hash)
- {
- var category = (byte)(hash >> 24);
- var world = (hash >> 16) & 0x1F;
- var language = (hash >> 21) & 7;
- var id = hash & 0xFFFF;
-
- var strWorld = world < Constants.Worlds.Length ?
- Constants.Worlds[world] : null;
- var strLanguage = language < Constants.Language.Length ?
- Constants.Language[language] : null;
-
- if (!PathCategories.TryGetValue(category, out var pathCategory))
- return null;
-
- return string.Format(pathCategory, strLanguage, strWorld);
- }
- }
-}
+using OpenKh.Common;
+using System;
+using System.IO;
+using Xe.IO;
+
+namespace OpenKh.Bbs
+{
+ public partial class Bbsa
+ {
+ public class Entry
+ {
+ private const int SectorLength = 0x800;
+ private readonly Header bbsaHeader;
+ private readonly int offset;
+ private readonly int length;
+ private readonly string fileName;
+ private readonly string folderName;
+
+ internal Entry(
+ Bbsa bbsa,
+ int offset,
+ int length,
+ string fileName,
+ string folderName,
+ uint fileHash,
+ uint folderHash)
+ {
+ bbsaHeader = bbsa._header;
+ this.offset = offset;
+ this.length = length;
+ this.fileName = fileName;
+ this.folderName = folderName;
+ FileHash = fileHash;
+ FolderHash = folderHash;
+ }
+
+ public uint FileHash { get; }
+ public uint FolderHash { get; }
+ public string Name => $"{FolderName}/{FileName}";
+ public bool HasCompleteName => fileName != null && folderName != null;
+
+ public string CalculateNameWithExtension(Func bbsaLoader)
+ {
+ if (!CalculateArchiveOffset(bbsaHeader, offset, out var archiveIndex, out var physicalSector))
+ return Name;
+
+ var stream = bbsaLoader(archiveIndex);
+ var extension = CalculateExtension(stream, physicalSector * SectorLength);
+ if (extension == null)
+ return Name;
+
+ return $"{Name}.{extension}";
+ }
+
+ public SubStream OpenStream(Func bbsaLoader)
+ {
+ if (!CalculateArchiveOffset(bbsaHeader, offset, out var archiveIndex, out var physicalSector))
+ return null;
+
+ var stream = bbsaLoader(archiveIndex);
+ var subStreamOffset = physicalSector * SectorLength;
+ var subStreamLength = length * SectorLength;
+
+ if (length == 0xFFF)
+ {
+ if (IsPsmf(stream, subStreamOffset))
+ subStreamLength = GetPsmfLength(stream, subStreamOffset);
+ }
+
+ return new SubStream(stream, subStreamOffset, subStreamLength);
+ }
+
+ private string FileName => fileName ?? $"@{FileHash:X08}";
+ private string FolderName =>
+ folderName ??
+ CalculateFolderName(FolderHash) ??
+ $"@{FolderHash:X08}";
+ }
+
+ private static bool IsPsmf(Stream stream, int offset) =>
+ new BinaryReader(stream.SetPosition(offset)).ReadInt32() == 0x464D5350;
+
+ private static int GetPsmfLength(Stream stream, int offset)
+ {
+ stream.SetPosition(offset + 12);
+ return (stream.ReadByte() << 24) |
+ (stream.ReadByte() << 16) |
+ (stream.ReadByte() << 8) |
+ (stream.ReadByte() << 0);
+ }
+
+ private static bool CalculateArchiveOffset(
+ Header header, int offset, out int archiveIndex, out int physicalSector)
+ {
+ if (offset >= header.Archive4Sector)
+ {
+ archiveIndex = 4;
+ physicalSector = offset - header.Archive4Sector + 1;
+ }
+ else if (offset >= header.Archive3Sector)
+ {
+ archiveIndex = 3;
+ physicalSector = offset - header.Archive3Sector + 1;
+ }
+ else if (offset >= header.Archive2Sector)
+ {
+ archiveIndex = 2;
+ physicalSector = offset - header.Archive2Sector + 1;
+ }
+ else if (offset >= header.Archive1Sector)
+ {
+ archiveIndex = 1;
+ physicalSector = offset - header.Archive1Sector + 1;
+ }
+ else if (offset >= header.Archive0Sector)
+ {
+ archiveIndex = 0;
+ physicalSector = offset + header.Archive0Sector;
+ }
+ else
+ {
+ archiveIndex = -1;
+ physicalSector = -1;
+ return false;
+ }
+
+ return true;
+ }
+
+ private static string CalculateExtension(Stream stream, int offset)
+ {
+ stream.Position = offset;
+ var magicCode = new BinaryReader(stream).ReadUInt32();
+ switch (magicCode)
+ {
+ case 0x61754C1B:
+ return "lub";
+ case 0x41264129:
+ return "ice";
+ case 0x44544340:
+ return "ctd";
+ case 0x50444540:
+ return "edp";
+ case 0x00435241:
+ return "arc";
+ case 0x44424D40:
+ return "mbd";
+ case 0x00444145:
+ return "ead";
+ case 0x07504546:
+ return "fep";
+ case 0x00425449:
+ return "itb";
+ case 0x00435449:
+ return "itc";
+ case 0x00455449:
+ return "ite";
+ case 0x004D4150:
+ return "pam";
+ case 0x004F4D50:
+ return "pmo";
+ case 0x42444553:
+ return "scd";
+ case 0x324D4954:
+ return "tm2";
+ case 0x00415854:
+ return "txa";
+ case 0x00617865:
+ return "exa";
+ default:
+ return null;
+ }
+ }
+
+ private static string CalculateFolderName(uint hash)
+ {
+ var category = (byte)(hash >> 24);
+ var world = (hash >> 16) & 0x1F;
+ var language = (hash >> 21) & 7;
+ var id = hash & 0xFFFF;
+
+ var strWorld = world < Constants.Worlds.Length ?
+ Constants.Worlds[world] : null;
+ var strLanguage = language < Constants.Language.Length ?
+ Constants.Language[language] : null;
+
+ if (!PathCategories.TryGetValue(category, out var pathCategory))
+ return null;
+
+ return string.Format(pathCategory, strLanguage, strWorld);
+ }
+ }
+}
diff --git a/OpenKh.Bbs/Bbsa.Hash.cs b/OpenKh.Bbs/Bbsa.Hash.cs
index 1dc130b63..65c8d6d89 100644
--- a/OpenKh.Bbs/Bbsa.Hash.cs
+++ b/OpenKh.Bbs/Bbsa.Hash.cs
@@ -1,59 +1,59 @@
-using System.Text;
-
-namespace OpenKh.Bbs
-{
- public partial class Bbsa
- {
- private static uint[] CrcTable = new uint[]
- {
- 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
- 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
- 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
- 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
- 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
- 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
- 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
- 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
- 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
- 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
- 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
- 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
- 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
- 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
- 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
- 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
- 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
- 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
- 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
- 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
- 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
- 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
- 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
- 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
- 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
- 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
- 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
- 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
- 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
- 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
- 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
- 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
- };
-
- public static uint GetHash(string text) => GetHash(Encoding.UTF8.GetBytes(text));
-
- public static uint GetHash(byte[] data)
- {
- var a0 = uint.MaxValue;
-
- foreach (var ch in data)
- {
- var v0 = a0 >> 8;
- var t2 = ch ^ a0;
- a0 = v0 ^ CrcTable[t2 & 0xFF];
- }
-
- return ~a0;
- }
- }
-}
+using System.Text;
+
+namespace OpenKh.Bbs
+{
+ public partial class Bbsa
+ {
+ private static uint[] CrcTable = new uint[]
+ {
+ 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+ 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+ 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+ 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+ 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+ 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+ 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+ 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+ 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+ 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+ 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+ 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+ 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+ 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+ 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+ 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+ 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+ 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+ 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+ 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+ 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+ 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+ 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+ 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+ 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+ 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+ 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+ 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+ 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+ 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+ 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+ 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
+ };
+
+ public static uint GetHash(string text) => GetHash(Encoding.UTF8.GetBytes(text));
+
+ public static uint GetHash(byte[] data)
+ {
+ var a0 = uint.MaxValue;
+
+ foreach (var ch in data)
+ {
+ var v0 = a0 >> 8;
+ var t2 = ch ^ a0;
+ a0 = v0 ^ CrcTable[t2 & 0xFF];
+ }
+
+ return ~a0;
+ }
+ }
+}
diff --git a/OpenKh.Bbs/Bbsa.Names.cs b/OpenKh.Bbs/Bbsa.Names.cs
index cf6f43840..96b9410cc 100644
--- a/OpenKh.Bbs/Bbsa.Names.cs
+++ b/OpenKh.Bbs/Bbsa.Names.cs
@@ -1,32 +1,32 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace OpenKh.Bbs
-{
- public partial class Bbsa
- {
- protected static Dictionary NameDictionary =
- TryReadLines(Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory), "resources/bbsa.txt"))
- .ToDictionary(x => GetHash(x), x => x);
-
- private static IEnumerable TryReadLines(string fileName) =>
- File.Exists(fileName) ? ReadLines(fileName) : new string[0];
-
- private static IEnumerable ReadLines(string fileName)
- {
- using (var stream = File.OpenText(fileName))
- {
- while (true)
- {
- var line = stream.ReadLine();
- if (line == null)
- break;
-
- yield return line;
- }
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace OpenKh.Bbs
+{
+ public partial class Bbsa
+ {
+ protected static Dictionary NameDictionary =
+ TryReadLines(Path.Combine(Path.GetDirectoryName(AppContext.BaseDirectory), "resources/bbsa.txt"))
+ .ToDictionary(x => GetHash(x), x => x);
+
+ private static IEnumerable TryReadLines(string fileName) =>
+ File.Exists(fileName) ? ReadLines(fileName) : new string[0];
+
+ private static IEnumerable ReadLines(string fileName)
+ {
+ using (var stream = File.OpenText(fileName))
+ {
+ while (true)
+ {
+ var line = stream.ReadLine();
+ if (line == null)
+ break;
+
+ yield return line;
+ }
+ }
+ }
+ }
+}
diff --git a/OpenKh.Bbs/Bbsa.Partition.cs b/OpenKh.Bbs/Bbsa.Partition.cs
index f617e1456..b5750d85b 100644
--- a/OpenKh.Bbs/Bbsa.Partition.cs
+++ b/OpenKh.Bbs/Bbsa.Partition.cs
@@ -1,115 +1,115 @@
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Xe.BinaryMapper;
-
-namespace OpenKh.Bbs
-{
- public partial class Bbsa
- {
- protected interface ILba
- {
- uint Hash { get; }
- }
-
- protected class Partition where TLba : ILba
- {
- [Data] public uint Name { get; set; }
- [Data] public short Count { get; set; }
- [Data] public short Offset { get; set; }
- public TLba[] Lba { get; set; }
-
- public override string ToString() =>
- $"{Name:X08} {Count:X04} {Offset:X04}";
- }
-
- protected class PartitionFileEntry : ILba
- {
- [Data] public uint Hash { get; set; }
- [Data] public uint Info { get; set; }
- public int Offset => (int)(Info >> 12);
- public int Size => (int)(Info & 0xFFF);
-
- public override string ToString() =>
- $"{Hash:X08} {Offset:X06} {Size:X03}";
-
- internal static PartitionFileEntry Read(Stream stream) =>
- BinaryMapping.ReadObject(stream);
- }
-
- protected class ArchivePartitionEntry : ILba
- {
- [Data] public uint Hash { get; set; }
- [Data] public short Offset { get; set; }
- [Data] public byte Count { get; set; }
- [Data] public byte Unknown { get; set; }
- public ArcEntry[] UnknownItems { get; set; }
-
- public override string ToString() =>
- $"{Hash:X08} {Offset:X04} {Count:X02} {Unknown:X02}";
-
- internal static ArchivePartitionEntry Read(Stream stream) =>
- BinaryMapping.ReadObject(stream);
- }
-
- protected class ArcEntry
- {
- [Data] public short Unknown00 { get; set; }
- [Data] public uint Hash { get; set; }
-
- public override string ToString() =>
- $"{Hash:X08} {Unknown00:X04}";
-
- internal static ArcEntry Read(Stream stream) =>
- BinaryMapping.ReadObject(stream);
- }
-
- private static Partition[] ReadPartitions(Stream stream, int offset, int count)
- where TLba : ILba
- {
- stream.Position = offset;
- return Enumerable.Range(0, count)
- .Select(x => ReadPartition(stream))
- .ToArray();
- }
-
- private static Partition ReadPartition(Stream stream)
- where TLba : ILba =>
- BinaryMapping.ReadObject>(stream);
-
- private static void ReadPartitionLba(IEnumerable> partitions, Stream stream, int baseOffset)
- {
- stream.Position = baseOffset;
- foreach (var partition in partitions)
- {
- stream.Position = baseOffset + partition.Offset * LbaLength;
- partition.Lba = Enumerable.Range(0, partition.Count)
- .Select(x => PartitionFileEntry.Read(stream)).ToArray();
- }
- }
-
- private static void ReadPartitionLba(IEnumerable> partitions, Stream stream, int baseOffset)
- {
- stream.Position = baseOffset;
- foreach (var partition in partitions)
- {
- stream.Position = baseOffset + partition.Offset * LbaLength;
- partition.Lba = Enumerable.Range(0, partition.Count)
- .Select(x => ArchivePartitionEntry.Read(stream)).ToArray();
- }
- }
-
- private static void ReadUnknownStruct(IEnumerable> partitions, Stream stream, int baseOffset)
- {
- foreach (var partition in partitions)
- {
- foreach (var lba in partition.Lba)
- {
- stream.Position = baseOffset + lba.Offset * 6;
- lba.UnknownItems = Enumerable.Range(0, lba.Count)
- .Select(x => ArcEntry.Read(stream)).ToArray();
- }
- }
- }
- }
-}
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Xe.BinaryMapper;
+
+namespace OpenKh.Bbs
+{
+ public partial class Bbsa
+ {
+ protected interface ILba
+ {
+ uint Hash { get; }
+ }
+
+ protected class Partition where TLba : ILba
+ {
+ [Data] public uint Name { get; set; }
+ [Data] public short Count { get; set; }
+ [Data] public short Offset { get; set; }
+ public TLba[] Lba { get; set; }
+
+ public override string ToString() =>
+ $"{Name:X08} {Count:X04} {Offset:X04}";
+ }
+
+ protected class PartitionFileEntry : ILba
+ {
+ [Data] public uint Hash { get; set; }
+ [Data] public uint Info { get; set; }
+ public int Offset => (int)(Info >> 12);
+ public int Size => (int)(Info & 0xFFF);
+
+ public override string ToString() =>
+ $"{Hash:X08} {Offset:X06} {Size:X03}";
+
+ internal static PartitionFileEntry Read(Stream stream) =>
+ BinaryMapping.ReadObject(stream);
+ }
+
+ protected class ArchivePartitionEntry : ILba
+ {
+ [Data] public uint Hash { get; set; }
+ [Data] public short Offset { get; set; }
+ [Data] public byte Count { get; set; }
+ [Data] public byte Unknown { get; set; }
+ public ArcEntry[] UnknownItems { get; set; }
+
+ public override string ToString() =>
+ $"{Hash:X08} {Offset:X04} {Count:X02} {Unknown:X02}";
+
+ internal static ArchivePartitionEntry Read(Stream stream) =>
+ BinaryMapping.ReadObject(stream);
+ }
+
+ protected class ArcEntry
+ {
+ [Data] public short Unknown00 { get; set; }
+ [Data] public uint Hash { get; set; }
+
+ public override string ToString() =>
+ $"{Hash:X08} {Unknown00:X04}";
+
+ internal static ArcEntry Read(Stream stream) =>
+ BinaryMapping.ReadObject(stream);
+ }
+
+ private static Partition[] ReadPartitions(Stream stream, int offset, int count)
+ where TLba : ILba
+ {
+ stream.Position = offset;
+ return Enumerable.Range(0, count)
+ .Select(x => ReadPartition(stream))
+ .ToArray();
+ }
+
+ private static Partition ReadPartition(Stream stream)
+ where TLba : ILba =>
+ BinaryMapping.ReadObject>(stream);
+
+ private static void ReadPartitionLba(IEnumerable> partitions, Stream stream, int baseOffset)
+ {
+ stream.Position = baseOffset;
+ foreach (var partition in partitions)
+ {
+ stream.Position = baseOffset + partition.Offset * LbaLength;
+ partition.Lba = Enumerable.Range(0, partition.Count)
+ .Select(x => PartitionFileEntry.Read(stream)).ToArray();
+ }
+ }
+
+ private static void ReadPartitionLba(IEnumerable> partitions, Stream stream, int baseOffset)
+ {
+ stream.Position = baseOffset;
+ foreach (var partition in partitions)
+ {
+ stream.Position = baseOffset + partition.Offset * LbaLength;
+ partition.Lba = Enumerable.Range(0, partition.Count)
+ .Select(x => ArchivePartitionEntry.Read(stream)).ToArray();
+ }
+ }
+
+ private static void ReadUnknownStruct(IEnumerable> partitions, Stream stream, int baseOffset)
+ {
+ foreach (var partition in partitions)
+ {
+ foreach (var lba in partition.Lba)
+ {
+ stream.Position = baseOffset + lba.Offset * 6;
+ lba.UnknownItems = Enumerable.Range(0, lba.Count)
+ .Select(x => ArcEntry.Read(stream)).ToArray();
+ }
+ }
+ }
+ }
+}
diff --git a/OpenKh.Bbs/Bbsa.cs b/OpenKh.Bbs/Bbsa.cs
index 1044a8805..a4c88b984 100644
--- a/OpenKh.Bbs/Bbsa.cs
+++ b/OpenKh.Bbs/Bbsa.cs
@@ -1,253 +1,253 @@
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Xe.BinaryMapper;
-
-namespace OpenKh.Bbs
-{
- public partial class Bbsa
- {
- protected static string[] KnownExtensions = new string[] {
- "Arc", "Bin", "Tm2", "Pmo",
- "Pam", "Pmp", "Pvd", "Bcd",
- "Fep", "Frr", "Ead", "Ese",
- "Lub", "Lad", "L2d", "Pst",
- "Epd", "Olo", "Bep", "Txa",
- "Aac", "Abc", "Scd", "Bsd",
- "Seb", "Ctd", "Ecm", "Ept",
- "Mss", "Nmd", "Ite", "Itb",
- "Itc", "Bdd", "Bdc", "Ngd",
- "Exb", "Gpd", "Exa", "Esd",
- "MTX", "INF", "COD", "CLU",
- "PMF", "ESE", "PTX", ""
- };
-
- protected static Dictionary Paths = new Dictionary
- {
- [0x0050414D] = "arc/map",
- [0x4E455645] = "arc/event",
- [0x00004350] = "arc/pc",
- [0x10004350] = "arc/pc_ven",
- [0x20004350] = "arc/pc_aqua",
- [0x30004350] = "arc/pc_terra",
- [0x4D454E45] = "arc/enemy",
- [0x53534F42] = "arc/boss",
- [0x0043504E] = "arc/npc",
- [0x4D4D4947] = "arc/gimmick",
- [0x50414557] = "arc/weapon",
- [0x4D455449] = "arc/item",
- [0x45464645] = "arc/effect",
- [0x554E454D] = "arc/menu",
- [0x00435445] = "arc/etc",
- [0x00535953] = "arc/system",
- [0x53455250] = "arc/preset",
- [0x41455250] = "arc/preset.alpha",
- [0x55424544] = "arc/debug",
- };
-
- protected static Dictionary PathCategories = new Dictionary
- {
- [0x00] = "arc_",
- [0x80] = "sound/bgm",
- [0xC0] = "lua",
- [0x90] = "sound/se/common",
- [0x91] = "sound/se/event/{1}",
- [0x92] = "sound/se/footstep/{1}",
- [0x93] = "sound/se/enemy",
- [0x94] = "sound/se/weapon",
- [0x95] = "sound/se/act",
- [0xA1] = "sound/voice/{0}/event/{1}",
- [0xAA] = "sound/voice/{0}/battle",
- [0xD0] = "message/{0}/system",
- [0xD1] = "message/{0}/map",
- [0xD2] = "message/{0}/menu",
- [0xD3] = "message/{0}/event",
- [0xD4] = "message/{0}/mission",
- [0xD5] = "message/{0}/npc_talk/{1}",
- [0xD6] = "message/{0}/network",
- [0xD7] = "message/{0}/battledice",
- [0xD8] = "message/{0}/minigame",
- [0xD9] = "message/{0}/shop",
- [0xDA] = "message/{0}/playerselect",
- [0xDB] = "message/{0}/report",
- };
-
- protected static Dictionary PathCategoriesReverse = PathCategories
- .SelectMany(x =>
- Constants.Language.Select((l, i) => new
- {
- Key = (x.Key << 24) | (i << 21),
- Value = x.Value.Replace("{0}", l)
- })
- )
- .SelectMany(x =>
- Constants.Worlds.Select((w, i) => new
- {
- Key = x.Key | (i << 16),
- Value = x.Value.Replace("{1}", w)
- })
- )
- .GroupBy(x => x.Value)
- .ToDictionary(x => x.Key, x => (uint)x.First().Key);
-
- protected static Dictionary PathsReverse =
- Paths.ToDictionary(x => x.Value, x => x.Key);
-
- protected static string[] AllPaths =
- PathsReverse
- .Select(x => (x.Key + '/').ToUpper())
- .Concat(new string[] { string.Empty })
- .ToArray();
-
- protected static string[] KnownExtensionsWithDot =
- KnownExtensions.Select(x => ('.' + x).ToUpper()).ToArray();
-
- protected class Header
- {
- [Data] public int MagicCode { get; set; }
- [Data] public int Version { get; set; }
- [Data] public short PartitionCount { get; set; }
- [Data] public short Unk0a { get; set; }
- [Data] public short Unk0c { get; set; }
- [Data] public short DirectoryCount { get; set; }
- [Data] public int PartitionOffset { get; set; }
- [Data] public int DirectoryOffset { get; set; }
- [Data] public short ArchivePartitionSector { get; set; }
- [Data] public short Archive0Sector { get; set; }
- [Data] public int TotalSectorCount { get; set; }
- [Data] public int Archive1Sector { get; set; }
- [Data] public int Archive2Sector { get; set; }
- [Data] public int Archive3Sector { get; set; }
- [Data] public int Archive4Sector { get; set; }
- public Partition[] Partitions { get; set; }
- }
-
- protected class ArchivePartitionHeader
- {
- [Data] public byte Unknown00 { get; set; }
- [Data] public byte PartitionCount { get; set; }
- [Data] public short Unknown02 { get; set; }
- [Data] public short LbaStartOffset { get; set; }
- [Data] public short UnknownOffset { get; set; }
- public Partition[] Partitions { get; set; }
- }
-
- protected class DirectoryEntry
- {
- public uint FileHash { get; set; }
- public uint Info { get; set; }
- public uint DirectoryHash { get; set; }
- public int Offset => (int)(Info >> 12);
- public int Size => (int)(Info & 0xFFF);
-
- public override string ToString() =>
- $"{DirectoryHash:X08}/{FileHash:X08} {Offset:X05} {Size:X03}";
- }
-
- private const int LbaLength = 8;
- protected readonly Header _header;
- protected readonly ArchivePartitionHeader _header2;
- protected readonly DirectoryEntry[] _directoryEntries;
-
- protected Bbsa(Stream stream)
- {
- _header = BinaryMapping.ReadObject(stream, (int)stream.Position);
- _header.Partitions = ReadPartitions(stream, 0x30, _header.PartitionCount);
- ReadPartitionLba(_header.Partitions, stream, _header.PartitionOffset);
-
- stream.Position = _header.DirectoryOffset;
- var reader = new BinaryReader(stream);
- _directoryEntries = Enumerable.Range(0, _header.DirectoryCount)
- .Select(x => new DirectoryEntry
- {
- FileHash = reader.ReadUInt32(),
- Info = reader.ReadUInt32(),
- DirectoryHash = reader.ReadUInt32()
- }).ToArray();
-
- int header2Offset = _header.ArchivePartitionSector * 0x800;
- stream.Position = header2Offset;
- _header2 = BinaryMapping.ReadObject(stream);
- _header2.Partitions = ReadPartitions(stream, header2Offset + 8, _header2.PartitionCount);
- ReadPartitionLba(_header2.Partitions, stream, header2Offset + _header2.LbaStartOffset);
- ReadUnknownStruct(_header2.Partitions, stream, header2Offset + _header2.UnknownOffset);
- }
-
- public IEnumerable Files
- {
- get
- {
- foreach (var partition in _header.Partitions)
- {
- Paths.TryGetValue(partition.Name, out var folder);
-
- foreach (var lba in partition.Lba)
- {
- NameDictionary.TryGetValue(lba.Hash, out var fileName);
-
- yield return new Entry(
- this,
- lba.Offset,
- lba.Size,
- fileName,
- folder,
- lba.Hash,
- 0);
- }
- }
-
- foreach (var file in _directoryEntries)
- {
- NameDictionary.TryGetValue(file.FileHash, out var fileName);
- NameDictionary.TryGetValue(file.DirectoryHash, out var folderName);
-
- yield return new Entry(
- this,
- file.Offset,
- file.Size,
- fileName,
- folderName,
- file.FileHash,
- file.DirectoryHash);
- }
- }
- }
-
- public int GetOffset(string fileName)
- {
- var directory = Path.GetDirectoryName(fileName).Replace('\\', '/');
- var file = Path.GetFileName(fileName);
- var name = Path.GetFileNameWithoutExtension(file);
-
- if (!PathsReverse.TryGetValue(directory, out var pathId))
- return -1;
-
- var pathInfo = _header.Partitions.FirstOrDefault(x => x.Name == pathId);
- if (pathInfo == null)
- return -1;
-
- var hash = GetHash(name.ToUpper());
- var lba = pathInfo.Lba.FirstOrDefault(x => x.Hash == hash);
- if (lba == null)
- return -1;
-
- return (lba.Offset + _header.Archive0Sector) * 0x800;
- }
-
- public static Bbsa Read(Stream stream) => new Bbsa(stream);
-
- public static string GetDirectoryName(uint hash) =>
- Paths.TryGetValue(hash, out var path) ? path : CalculateFolderName(hash);
-
- public static uint GetDirectoryHash(string directory)
- {
- if (PathsReverse.TryGetValue(directory.ToLower(), out var hash))
- return (uint)hash;
-
- if (PathCategoriesReverse.TryGetValue(directory.ToLower(), out hash))
- return (uint)hash;
-
- return uint.MaxValue;
- }
- }
-}
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Xe.BinaryMapper;
+
+namespace OpenKh.Bbs
+{
+ public partial class Bbsa
+ {
+ protected static string[] KnownExtensions = new string[] {
+ "Arc", "Bin", "Tm2", "Pmo",
+ "Pam", "Pmp", "Pvd", "Bcd",
+ "Fep", "Frr", "Ead", "Ese",
+ "Lub", "Lad", "L2d", "Pst",
+ "Epd", "Olo", "Bep", "Txa",
+ "Aac", "Abc", "Scd", "Bsd",
+ "Seb", "Ctd", "Ecm", "Ept",
+ "Mss", "Nmd", "Ite", "Itb",
+ "Itc", "Bdd", "Bdc", "Ngd",
+ "Exb", "Gpd", "Exa", "Esd",
+ "MTX", "INF", "COD", "CLU",
+ "PMF", "ESE", "PTX", ""
+ };
+
+ protected static Dictionary Paths = new Dictionary
+ {
+ [0x0050414D] = "arc/map",
+ [0x4E455645] = "arc/event",
+ [0x00004350] = "arc/pc",
+ [0x10004350] = "arc/pc_ven",
+ [0x20004350] = "arc/pc_aqua",
+ [0x30004350] = "arc/pc_terra",
+ [0x4D454E45] = "arc/enemy",
+ [0x53534F42] = "arc/boss",
+ [0x0043504E] = "arc/npc",
+ [0x4D4D4947] = "arc/gimmick",
+ [0x50414557] = "arc/weapon",
+ [0x4D455449] = "arc/item",
+ [0x45464645] = "arc/effect",
+ [0x554E454D] = "arc/menu",
+ [0x00435445] = "arc/etc",
+ [0x00535953] = "arc/system",
+ [0x53455250] = "arc/preset",
+ [0x41455250] = "arc/preset.alpha",
+ [0x55424544] = "arc/debug",
+ };
+
+ protected static Dictionary PathCategories = new Dictionary
+ {
+ [0x00] = "arc_",
+ [0x80] = "sound/bgm",
+ [0xC0] = "lua",
+ [0x90] = "sound/se/common",
+ [0x91] = "sound/se/event/{1}",
+ [0x92] = "sound/se/footstep/{1}",
+ [0x93] = "sound/se/enemy",
+ [0x94] = "sound/se/weapon",
+ [0x95] = "sound/se/act",
+ [0xA1] = "sound/voice/{0}/event/{1}",
+ [0xAA] = "sound/voice/{0}/battle",
+ [0xD0] = "message/{0}/system",
+ [0xD1] = "message/{0}/map",
+ [0xD2] = "message/{0}/menu",
+ [0xD3] = "message/{0}/event",
+ [0xD4] = "message/{0}/mission",
+ [0xD5] = "message/{0}/npc_talk/{1}",
+ [0xD6] = "message/{0}/network",
+ [0xD7] = "message/{0}/battledice",
+ [0xD8] = "message/{0}/minigame",
+ [0xD9] = "message/{0}/shop",
+ [0xDA] = "message/{0}/playerselect",
+ [0xDB] = "message/{0}/report",
+ };
+
+ protected static Dictionary PathCategoriesReverse = PathCategories
+ .SelectMany(x =>
+ Constants.Language.Select((l, i) => new
+ {
+ Key = (x.Key << 24) | (i << 21),
+ Value = x.Value.Replace("{0}", l)
+ })
+ )
+ .SelectMany(x =>
+ Constants.Worlds.Select((w, i) => new
+ {
+ Key = x.Key | (i << 16),
+ Value = x.Value.Replace("{1}", w)
+ })
+ )
+ .GroupBy(x => x.Value)
+ .ToDictionary(x => x.Key, x => (uint)x.First().Key);
+
+ protected static Dictionary PathsReverse =
+ Paths.ToDictionary(x => x.Value, x => x.Key);
+
+ protected static string[] AllPaths =
+ PathsReverse
+ .Select(x => (x.Key + '/').ToUpper())
+ .Concat(new string[] { string.Empty })
+ .ToArray();
+
+ protected static string[] KnownExtensionsWithDot =
+ KnownExtensions.Select(x => ('.' + x).ToUpper()).ToArray();
+
+ protected class Header
+ {
+ [Data] public int MagicCode { get; set; }
+ [Data] public int Version { get; set; }
+ [Data] public short PartitionCount { get; set; }
+ [Data] public short Unk0a { get; set; }
+ [Data] public short Unk0c { get; set; }
+ [Data] public short DirectoryCount { get; set; }
+ [Data] public int PartitionOffset { get; set; }
+ [Data] public int DirectoryOffset { get; set; }
+ [Data] public short ArchivePartitionSector { get; set; }
+ [Data] public short Archive0Sector { get; set; }
+ [Data] public int TotalSectorCount { get; set; }
+ [Data] public int Archive1Sector { get; set; }
+ [Data] public int Archive2Sector { get; set; }
+ [Data] public int Archive3Sector { get; set; }
+ [Data] public int Archive4Sector { get; set; }
+ public Partition[] Partitions { get; set; }
+ }
+
+ protected class ArchivePartitionHeader
+ {
+ [Data] public byte Unknown00 { get; set; }
+ [Data] public byte PartitionCount { get; set; }
+ [Data] public short Unknown02 { get; set; }
+ [Data] public short LbaStartOffset { get; set; }
+ [Data] public short UnknownOffset { get; set; }
+ public Partition[] Partitions { get; set; }
+ }
+
+ protected class DirectoryEntry
+ {
+ public uint FileHash { get; set; }
+ public uint Info { get; set; }
+ public uint DirectoryHash { get; set; }
+ public int Offset => (int)(Info >> 12);
+ public int Size => (int)(Info & 0xFFF);
+
+ public override string ToString() =>
+ $"{DirectoryHash:X08}/{FileHash:X08} {Offset:X05} {Size:X03}";
+ }
+
+ private const int LbaLength = 8;
+ protected readonly Header _header;
+ protected readonly ArchivePartitionHeader _header2;
+ protected readonly DirectoryEntry[] _directoryEntries;
+
+ protected Bbsa(Stream stream)
+ {
+ _header = BinaryMapping.ReadObject(stream, (int)stream.Position);
+ _header.Partitions = ReadPartitions(stream, 0x30, _header.PartitionCount);
+ ReadPartitionLba(_header.Partitions, stream, _header.PartitionOffset);
+
+ stream.Position = _header.DirectoryOffset;
+ var reader = new BinaryReader(stream);
+ _directoryEntries = Enumerable.Range(0, _header.DirectoryCount)
+ .Select(x => new DirectoryEntry
+ {
+ FileHash = reader.ReadUInt32(),
+ Info = reader.ReadUInt32(),
+ DirectoryHash = reader.ReadUInt32()
+ }).ToArray();
+
+ int header2Offset = _header.ArchivePartitionSector * 0x800;
+ stream.Position = header2Offset;
+ _header2 = BinaryMapping.ReadObject(stream);
+ _header2.Partitions = ReadPartitions(stream, header2Offset + 8, _header2.PartitionCount);
+ ReadPartitionLba(_header2.Partitions, stream, header2Offset + _header2.LbaStartOffset);
+ ReadUnknownStruct(_header2.Partitions, stream, header2Offset + _header2.UnknownOffset);
+ }
+
+ public IEnumerable Files
+ {
+ get
+ {
+ foreach (var partition in _header.Partitions)
+ {
+ Paths.TryGetValue(partition.Name, out var folder);
+
+ foreach (var lba in partition.Lba)
+ {
+ NameDictionary.TryGetValue(lba.Hash, out var fileName);
+
+ yield return new Entry(
+ this,
+ lba.Offset,
+ lba.Size,
+ fileName,
+ folder,
+ lba.Hash,
+ 0);
+ }
+ }
+
+ foreach (var file in _directoryEntries)
+ {
+ NameDictionary.TryGetValue(file.FileHash, out var fileName);
+ NameDictionary.TryGetValue(file.DirectoryHash, out var folderName);
+
+ yield return new Entry(
+ this,
+ file.Offset,
+ file.Size,
+ fileName,
+ folderName,
+ file.FileHash,
+ file.DirectoryHash);
+ }
+ }
+ }
+
+ public int GetOffset(string fileName)
+ {
+ var directory = Path.GetDirectoryName(fileName).Replace('\\', '/');
+ var file = Path.GetFileName(fileName);
+ var name = Path.GetFileNameWithoutExtension(file);
+
+ if (!PathsReverse.TryGetValue(directory, out var pathId))
+ return -1;
+
+ var pathInfo = _header.Partitions.FirstOrDefault(x => x.Name == pathId);
+ if (pathInfo == null)
+ return -1;
+
+ var hash = GetHash(name.ToUpper());
+ var lba = pathInfo.Lba.FirstOrDefault(x => x.Hash == hash);
+ if (lba == null)
+ return -1;
+
+ return (lba.Offset + _header.Archive0Sector) * 0x800;
+ }
+
+ public static Bbsa Read(Stream stream) => new Bbsa(stream);
+
+ public static string GetDirectoryName(uint hash) =>
+ Paths.TryGetValue(hash, out var path) ? path : CalculateFolderName(hash);
+
+ public static uint GetDirectoryHash(string directory)
+ {
+ if (PathsReverse.TryGetValue(directory.ToLower(), out var hash))
+ return (uint)hash;
+
+ if (PathCategoriesReverse.TryGetValue(directory.ToLower(), out hash))
+ return (uint)hash;
+
+ return uint.MaxValue;
+ }
+ }
+}
diff --git a/OpenKh.Bbs/Bep.cs b/OpenKh.Bbs/Bep.cs
index 823b5dbf6..665a9536f 100644
--- a/OpenKh.Bbs/Bep.cs
+++ b/OpenKh.Bbs/Bep.cs
@@ -1,83 +1,83 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-using Xe.BinaryMapper;
-
-namespace OpenKh.Bbs
-{
- public class Bep
- {
- private const uint MagicCode = 0x50454240;
- private const uint version = 2;
-
- public class Header
- {
- [Data] public uint MagicCode { get; set; }
- [Data] public uint version { get; set; }
- [Data] public uint BaseParametersCount { get; set; }
- [Data] public uint BaseParametersOffset { get; set; }
- [Data] public uint DisappearParametersCount { get; set; }
- [Data] public uint DisappearParametersOffset { get; set; }
- }
-
- public class BaseParameter
- {
- [Data] public ushort BattleLevel { get; set; }
- [Data] public ushort BaseAttack { get; set; }
- [Data] public ushort Defense { get; set; }
- [Data] public byte DamageCeiling { get; set; }
- [Data] public byte DamageFloor { get; set; }
- [Data] public uint BaseHP { get; set; }
- [Data] public uint BaseEXP { get; set; }
- }
-
- public class DisappearParameter
- {
- [Data] public ushort WorldID { get; set; }
- [Data] public ushort RoomID { get; set; }
- [Data] public float Distance { get; set; }
- }
-
- public Header header = new Header();
- public List baseParameters = new List();
- public List disappearParameters = new List();
-
- public static Bep Read(Stream stream)
- {
- Bep bep = new Bep();
- bep.header = BinaryMapping.ReadObject(stream);
-
- stream.Seek(bep.header.BaseParametersOffset, SeekOrigin.Begin);
- bep.baseParameters = new List();
- for(int c = 0; c < bep.header.BaseParametersCount; c++)
- {
- bep.baseParameters.Add(BinaryMapping.ReadObject(stream));
- }
-
- stream.Seek(bep.header.DisappearParametersOffset, SeekOrigin.Begin);
- bep.disappearParameters = new List();
- for (int d = 0; d < bep.header.DisappearParametersCount; d++)
- {
- bep.disappearParameters.Add(BinaryMapping.ReadObject(stream));
- }
-
- return bep;
- }
-
- public static void Write(Stream stream, Bep bep)
- {
- BinaryMapping.WriteObject(stream, bep.header);
-
- for (int c = 0; c < bep.disappearParameters.Count; c++)
- {
- BinaryMapping.WriteObject(stream, bep.baseParameters[c]);
- }
-
- for (int d = 0; d < bep.disappearParameters.Count; d++)
- {
- BinaryMapping.WriteObject(stream, bep.disappearParameters[d]);
- }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using Xe.BinaryMapper;
+
+namespace OpenKh.Bbs
+{
+ public class Bep
+ {
+ private const uint MagicCode = 0x50454240;
+ private const uint version = 2;
+
+ public class Header
+ {
+ [Data] public uint MagicCode { get; set; }
+ [Data] public uint version { get; set; }
+ [Data] public uint BaseParametersCount { get; set; }
+ [Data] public uint BaseParametersOffset { get; set; }
+ [Data] public uint DisappearParametersCount { get; set; }
+ [Data] public uint DisappearParametersOffset { get; set; }
+ }
+
+ public class BaseParameter
+ {
+ [Data] public ushort BattleLevel { get; set; }
+ [Data] public ushort BaseAttack { get; set; }
+ [Data] public ushort Defense { get; set; }
+ [Data] public byte DamageCeiling { get; set; }
+ [Data] public byte DamageFloor { get; set; }
+ [Data] public uint BaseHP { get; set; }
+ [Data] public uint BaseEXP { get; set; }
+ }
+
+ public class DisappearParameter
+ {
+ [Data] public ushort WorldID { get; set; }
+ [Data] public ushort RoomID { get; set; }
+ [Data] public float Distance { get; set; }
+ }
+
+ public Header header = new Header();
+ public List baseParameters = new List();
+ public List disappearParameters = new List();
+
+ public static Bep Read(Stream stream)
+ {
+ Bep bep = new Bep();
+ bep.header = BinaryMapping.ReadObject(stream);
+
+ stream.Seek(bep.header.BaseParametersOffset, SeekOrigin.Begin);
+ bep.baseParameters = new List();
+ for (int c = 0; c < bep.header.BaseParametersCount; c++)
+ {
+ bep.baseParameters.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ stream.Seek(bep.header.DisappearParametersOffset, SeekOrigin.Begin);
+ bep.disappearParameters = new List();
+ for (int d = 0; d < bep.header.DisappearParametersCount; d++)
+ {
+ bep.disappearParameters.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ return bep;
+ }
+
+ public static void Write(Stream stream, Bep bep)
+ {
+ BinaryMapping.WriteObject(stream, bep.header);
+
+ for (int c = 0; c < bep.disappearParameters.Count; c++)
+ {
+ BinaryMapping.WriteObject(stream, bep.baseParameters[c]);
+ }
+
+ for (int d = 0; d < bep.disappearParameters.Count; d++)
+ {
+ BinaryMapping.WriteObject(stream, bep.disappearParameters[d]);
+ }
+ }
+ }
+}
diff --git a/OpenKh.Bbs/Constants.cs b/OpenKh.Bbs/Constants.cs
index 32b7212e1..0aa429b4a 100644
--- a/OpenKh.Bbs/Constants.cs
+++ b/OpenKh.Bbs/Constants.cs
@@ -1,448 +1,448 @@
-namespace OpenKh.Bbs
-{
- public class Constants
- {
- public static readonly string[] Worlds =
- {
- "ex", "dp", "sw", "cd",
- "sb", "yt", "rg", "jb",
- "he", "ls", "di", "pp",
- "dc", "kg", "14", "vs",
- "bd", "wm", "wp", "19",
- "20", "21", "22", "jf",
- };
-
- public static readonly string[] WorldNames =
- {
- "Common",
- "Land of Departure",
- "Dwarf Woodlands",
- "Castle of Dreams",
- "Enchanted Dominion",
- "Mysterious Tower",
- "Radiant Garden",
- "Dark World",
- "Olympus Coliseum",
- "Deep Space",
- "Destiny Island",
- "Never Land",
- "Disney Town",
- "Keyblade Graveyard",
- "Mysterious Badlands (Unused)",
- "Mirage Arena",
- "Command Board",
- "World Map",
- "WP - Winnie the Pooh",
- "19 - Unused",
- "20 - Unused",
- "21 - Unused",
- "22 - Unused",
- "JF - Jump Festa",
- };
-
- public static readonly string[] Language =
- {
- "jp", "en", "fr", "it", "de", "es"
- };
-
- public static readonly string[] Rooms_DP =
- {
- "The Land of Departure",
- "Forecourt",
- "Great Hall",
- "Ventus's Room",
- "Ventus's Room",
- "Mountain Path",
- "Summit",
- "Forecourt",
- "Forecourt",
- "Great Hall",
- "Ruins",
- "Chamber of Waking",
- "Castle Oblivion",
- "Character Selection",
- "Forecourt",
- "Ruins",
- "Mountain Path"
- };
-
- public static readonly string[] Rooms_SW =
- {
- "Dwarf Woodlands",
- "Mine Entrance",
- "The Mine",
- "Vault",
- "Magic Mirror Chamber",
- "Underground Waterway",
- "Courtyard",
- "Flower Glade",
- "Deep Woods",
- "Inside the Mirror",
- "Cottage Clearing",
- "The Cottage",
- "Mountain Trail"
- };
-
- public static readonly string[] Rooms_CD =
- {
- "Castle of Dreams",
- "Cinderella's Room",
- "Mousehole",
- "Wardrobe Room",
- "Entrance",
- "The Chateau",
- "Forest",
- "Palace Courtyard",
- "Corridor",
- "Ballroom",
- "Foyer",
- "Passage",
- "Antechamber",
- "Wardrobe Room",
- "Mousehole",
- "Wardrobe Room"
- };
-
- public static readonly string[] Rooms_SB =
- {
- "Enchanted Dominion",
- "Dungeon Cell",
- "Gates",
- "Maleficent's Throne",
- "Dungeon",
- "Hall",
- "Forbidden Mountain",
- "Waterside",
- "Forest Clearing",
- "Bridge",
- "Bridge",
- "Audience Chamber",
- "Audience Chamber",
- "RESERVED",
- "Hallway",
- "Aurora's Chamber",
- "Tower Room",
- "Hall",
- "Aurora's Chamber",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Hall",
- "Gates"
- };
-
- public static readonly string[] Rooms_YT =
- {
- "The Mysterious Tower",
- "Sorcerer's Chamber",
- "Mysterious Tower",
- "Entrance",
- "Sorcerer's Chamber"
- };
-
- public static readonly string[] Rooms_RG =
- {
- "Radiant Garden",
- "Outer Garden",
- "Entryway",
- "Central Square",
- "Aqueduct",
- "Castle Town",
- "Reactor",
- "Fountain Court",
- "Merlin's House",
- "Gardens",
- "Front Doors",
- "Purification Facility",
- "Outer Gardens",
- "Central Square",
- "Central Square"
- };
-
- public static readonly string[] Rooms_JB =
- {
- "FOR EVENTS ONLY",
- "Louie's Ruins",
- "Court",
- "Path Crossroads",
- "UG Ruins Entrance",
- "UG Ruins Passage 1",
- "UG Ruins Passage 2",
- "UG Courtyard",
- "Jungle Near Ruins",
- "Eminence",
- "Jungle",
- "Man-Village River",
- "Bog",
- "13",
- "14",
- "15",
- "16",
- "17",
- "18",
- "19",
- "Realm of Darkness: Middle Zone",
- "Realm of Darkness: Lower Zone",
- "Realm of Darkness: Upper Zone",
- "The Dark Margin",
- "Cinderella's Darkness Castle",
- "25",
- "26",
- "27",
- "28",
- "29",
- "Destiny Islands (Noon)",
- "Traverse Town 2nd District",
- "Traverse Town 1st District",
- "Destiny Islands (Afternoon)",
- "Destiny Islands (Night)",
- "Traverse Town 3rd District",
- "36",
- "37",
- "38",
- "39",
- "40",
- "41",
- "42",
- "43",
- "44",
- "45",
- "46",
- "47",
- "48",
- "49",
- "Lanes Between",
- "BLANK",
- "Realm of Darkness",
- "FOR wm EVENT"
- };
-
- public static readonly string[] Rooms_HE =
- {
- "Olympus Coliseum",
- "Coliseum Gates",
- "Vestibule",
- "West Bracket",
- "East Bracket",
- "Town Near Thebes",
- "East Bracket"
-
- };
-
- public static readonly string[] Rooms_LS =
- {
- "Deep Space",
- "Prison Block",
- "Turo Transporter",
- "Durgon Transporter",
- "Ship Corridor",
- "Control Room",
- "Containment Pod",
- "Ship Hub",
- "Machinery Bay",
- "Launch Deck",
- "Ship Exterior",
- "Outer Space",
- "Ship Corridor",
- "Lanes Between",
- "Bay Access"
- };
-
- public static readonly string[] Rooms_DI =
- {
- "Destiny Islands",
- "Island Beach",
- "Island Beach",
- "Island Beach",
- "Main Island Beach"
- };
-
- public static readonly string[] Rooms_PP =
- {
- "Neverland",
- "Cove",
- "Cliff",
- "Mermaid Lagoon",
- "Seacoast",
- "Jungle Clearing",
- "Peter's Hideout",
- "Gully",
- "Indian Camp",
- "Rainbow Falls: Base",
- "Rainbow Falls: Ascent",
- "Rainbow Falls: Crest",
- "Skull Rock: Entrance",
- "Skull Rock: Cavern",
- "Night Sky"
- };
-
- public static readonly string[] Rooms_DC =
- {
- "Disney Town",
- "Library",
- "Main Plaza",
- "Fruitball Court",
- "Racecourse A",
- "Raceway",
- "Gizmo Gallery",
- "Pete's Rec Room",
- "Racecourse B",
- "Racecourse C",
- "Racecourse D",
- "Lanes Between",
- "Raceway Registration",
- "Ice Cream",
- "Fruitball",
- "Race: Castle Course"
- };
-
- public static readonly string[] Rooms_KG =
- {
- "Keyblade Graveyard",
- "Badlands",
- "Seat of War",
- "Twister Trench",
- "Eye of the Storm",
- "Eye of the Storm",
- "Eye of the Storm",
- "Fissure",
- "Keyblade Graveyard",
- "Keyblade Graveyard",
- "Keyblade Graveyard",
- "Will's Cage",
- "Keyblade Graveyard",
- "13",
- "14",
- "15",
- "16",
- "17",
- "18",
- "19",
- "20",
- "21",
- "22",
- "23",
- "24",
- "25",
- "26",
- "27",
- "28",
- "29",
- "30",
- "31",
- "32",
- "33",
- "34",
- "35",
- "36",
- "37",
- "38",
- "39",
- "40",
- "41",
- "42",
- "43",
- "44",
- "45",
- "46",
- "47",
- "48",
- "49",
- "Ventus's Mind",
- "Ventus's Mind",
- "Ventus's Mind",
- "Sora's Mind",
- "Terra-Xehanort's Mind",
- "Keyblade Graveyard",
- "Badlands"
- };
-
- public static readonly string[] Rooms_VS =
- {
- "Mirage Arena",
- "Hub",
- "Coliseum",
- "Arena",
- "Badlands",
- "Pinball",
- "Ship Hub",
- "Mousehole",
- "Forest",
- "Skull Rock",
- "Audience Chamber",
- "Forecourt",
- "Summit",
- "Launch Deck",
- "Ship Exterior",
- "Arena",
- "Great Hall (Noon)",
- "Monstro (Interior A)",
- "Monstro (Exterior)",
- "Monstrio (Interior B)",
- "Summit (Broken)"
- };
-
- public static readonly string[] Rooms_BD =
- {
- "Command Board",
- "Land of Departure BG",
- "02",
- "Cinderella BG",
- "04",
- "05",
- "06",
- "07",
- "08",
- "Lilo & Stitch BG",
- "10",
- "Peter Pan BG",
- "Disney Castle BG",
- "13",
- "14",
- "15",
- "16",
- "17",
- "Winnie the Pooh BG",
- "Peter Pan BG"
- };
-
- public static readonly string[] Rooms_WM =
- {
- "World Map",
- "wm01"
- };
-
- public static readonly string[] Rooms_JF =
- {
- "Jump Festa (sw10)",
- "Jump Festa (cd07)",
- "Jump Festa (cd09)",
- "Jump Festa (sb10)",
- "04",
- "05",
- "06",
- "07",
- "08",
- "09",
- "The Town",
- "Poly Partition Test",
- "12"
- };
- }
-}
+namespace OpenKh.Bbs
+{
+ public class Constants
+ {
+ public static readonly string[] Worlds =
+ {
+ "ex", "dp", "sw", "cd",
+ "sb", "yt", "rg", "jb",
+ "he", "ls", "di", "pp",
+ "dc", "kg", "14", "vs",
+ "bd", "wm", "wp", "19",
+ "20", "21", "22", "jf",
+ };
+
+ public static readonly string[] WorldNames =
+ {
+ "Common",
+ "Land of Departure",
+ "Dwarf Woodlands",
+ "Castle of Dreams",
+ "Enchanted Dominion",
+ "Mysterious Tower",
+ "Radiant Garden",
+ "Dark World",
+ "Olympus Coliseum",
+ "Deep Space",
+ "Destiny Island",
+ "Never Land",
+ "Disney Town",
+ "Keyblade Graveyard",
+ "Mysterious Badlands (Unused)",
+ "Mirage Arena",
+ "Command Board",
+ "World Map",
+ "WP - Winnie the Pooh",
+ "19 - Unused",
+ "20 - Unused",
+ "21 - Unused",
+ "22 - Unused",
+ "JF - Jump Festa",
+ };
+
+ public static readonly string[] Language =
+ {
+ "jp", "en", "fr", "it", "de", "es"
+ };
+
+ public static readonly string[] Rooms_DP =
+ {
+ "The Land of Departure",
+ "Forecourt",
+ "Great Hall",
+ "Ventus's Room",
+ "Ventus's Room",
+ "Mountain Path",
+ "Summit",
+ "Forecourt",
+ "Forecourt",
+ "Great Hall",
+ "Ruins",
+ "Chamber of Waking",
+ "Castle Oblivion",
+ "Character Selection",
+ "Forecourt",
+ "Ruins",
+ "Mountain Path"
+ };
+
+ public static readonly string[] Rooms_SW =
+ {
+ "Dwarf Woodlands",
+ "Mine Entrance",
+ "The Mine",
+ "Vault",
+ "Magic Mirror Chamber",
+ "Underground Waterway",
+ "Courtyard",
+ "Flower Glade",
+ "Deep Woods",
+ "Inside the Mirror",
+ "Cottage Clearing",
+ "The Cottage",
+ "Mountain Trail"
+ };
+
+ public static readonly string[] Rooms_CD =
+ {
+ "Castle of Dreams",
+ "Cinderella's Room",
+ "Mousehole",
+ "Wardrobe Room",
+ "Entrance",
+ "The Chateau",
+ "Forest",
+ "Palace Courtyard",
+ "Corridor",
+ "Ballroom",
+ "Foyer",
+ "Passage",
+ "Antechamber",
+ "Wardrobe Room",
+ "Mousehole",
+ "Wardrobe Room"
+ };
+
+ public static readonly string[] Rooms_SB =
+ {
+ "Enchanted Dominion",
+ "Dungeon Cell",
+ "Gates",
+ "Maleficent's Throne",
+ "Dungeon",
+ "Hall",
+ "Forbidden Mountain",
+ "Waterside",
+ "Forest Clearing",
+ "Bridge",
+ "Bridge",
+ "Audience Chamber",
+ "Audience Chamber",
+ "RESERVED",
+ "Hallway",
+ "Aurora's Chamber",
+ "Tower Room",
+ "Hall",
+ "Aurora's Chamber",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Hall",
+ "Gates"
+ };
+
+ public static readonly string[] Rooms_YT =
+ {
+ "The Mysterious Tower",
+ "Sorcerer's Chamber",
+ "Mysterious Tower",
+ "Entrance",
+ "Sorcerer's Chamber"
+ };
+
+ public static readonly string[] Rooms_RG =
+ {
+ "Radiant Garden",
+ "Outer Garden",
+ "Entryway",
+ "Central Square",
+ "Aqueduct",
+ "Castle Town",
+ "Reactor",
+ "Fountain Court",
+ "Merlin's House",
+ "Gardens",
+ "Front Doors",
+ "Purification Facility",
+ "Outer Gardens",
+ "Central Square",
+ "Central Square"
+ };
+
+ public static readonly string[] Rooms_JB =
+ {
+ "FOR EVENTS ONLY",
+ "Louie's Ruins",
+ "Court",
+ "Path Crossroads",
+ "UG Ruins Entrance",
+ "UG Ruins Passage 1",
+ "UG Ruins Passage 2",
+ "UG Courtyard",
+ "Jungle Near Ruins",
+ "Eminence",
+ "Jungle",
+ "Man-Village River",
+ "Bog",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "Realm of Darkness: Middle Zone",
+ "Realm of Darkness: Lower Zone",
+ "Realm of Darkness: Upper Zone",
+ "The Dark Margin",
+ "Cinderella's Darkness Castle",
+ "25",
+ "26",
+ "27",
+ "28",
+ "29",
+ "Destiny Islands (Noon)",
+ "Traverse Town 2nd District",
+ "Traverse Town 1st District",
+ "Destiny Islands (Afternoon)",
+ "Destiny Islands (Night)",
+ "Traverse Town 3rd District",
+ "36",
+ "37",
+ "38",
+ "39",
+ "40",
+ "41",
+ "42",
+ "43",
+ "44",
+ "45",
+ "46",
+ "47",
+ "48",
+ "49",
+ "Lanes Between",
+ "BLANK",
+ "Realm of Darkness",
+ "FOR wm EVENT"
+ };
+
+ public static readonly string[] Rooms_HE =
+ {
+ "Olympus Coliseum",
+ "Coliseum Gates",
+ "Vestibule",
+ "West Bracket",
+ "East Bracket",
+ "Town Near Thebes",
+ "East Bracket"
+
+ };
+
+ public static readonly string[] Rooms_LS =
+ {
+ "Deep Space",
+ "Prison Block",
+ "Turo Transporter",
+ "Durgon Transporter",
+ "Ship Corridor",
+ "Control Room",
+ "Containment Pod",
+ "Ship Hub",
+ "Machinery Bay",
+ "Launch Deck",
+ "Ship Exterior",
+ "Outer Space",
+ "Ship Corridor",
+ "Lanes Between",
+ "Bay Access"
+ };
+
+ public static readonly string[] Rooms_DI =
+ {
+ "Destiny Islands",
+ "Island Beach",
+ "Island Beach",
+ "Island Beach",
+ "Main Island Beach"
+ };
+
+ public static readonly string[] Rooms_PP =
+ {
+ "Neverland",
+ "Cove",
+ "Cliff",
+ "Mermaid Lagoon",
+ "Seacoast",
+ "Jungle Clearing",
+ "Peter's Hideout",
+ "Gully",
+ "Indian Camp",
+ "Rainbow Falls: Base",
+ "Rainbow Falls: Ascent",
+ "Rainbow Falls: Crest",
+ "Skull Rock: Entrance",
+ "Skull Rock: Cavern",
+ "Night Sky"
+ };
+
+ public static readonly string[] Rooms_DC =
+ {
+ "Disney Town",
+ "Library",
+ "Main Plaza",
+ "Fruitball Court",
+ "Racecourse A",
+ "Raceway",
+ "Gizmo Gallery",
+ "Pete's Rec Room",
+ "Racecourse B",
+ "Racecourse C",
+ "Racecourse D",
+ "Lanes Between",
+ "Raceway Registration",
+ "Ice Cream",
+ "Fruitball",
+ "Race: Castle Course"
+ };
+
+ public static readonly string[] Rooms_KG =
+ {
+ "Keyblade Graveyard",
+ "Badlands",
+ "Seat of War",
+ "Twister Trench",
+ "Eye of the Storm",
+ "Eye of the Storm",
+ "Eye of the Storm",
+ "Fissure",
+ "Keyblade Graveyard",
+ "Keyblade Graveyard",
+ "Keyblade Graveyard",
+ "Will's Cage",
+ "Keyblade Graveyard",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "20",
+ "21",
+ "22",
+ "23",
+ "24",
+ "25",
+ "26",
+ "27",
+ "28",
+ "29",
+ "30",
+ "31",
+ "32",
+ "33",
+ "34",
+ "35",
+ "36",
+ "37",
+ "38",
+ "39",
+ "40",
+ "41",
+ "42",
+ "43",
+ "44",
+ "45",
+ "46",
+ "47",
+ "48",
+ "49",
+ "Ventus's Mind",
+ "Ventus's Mind",
+ "Ventus's Mind",
+ "Sora's Mind",
+ "Terra-Xehanort's Mind",
+ "Keyblade Graveyard",
+ "Badlands"
+ };
+
+ public static readonly string[] Rooms_VS =
+ {
+ "Mirage Arena",
+ "Hub",
+ "Coliseum",
+ "Arena",
+ "Badlands",
+ "Pinball",
+ "Ship Hub",
+ "Mousehole",
+ "Forest",
+ "Skull Rock",
+ "Audience Chamber",
+ "Forecourt",
+ "Summit",
+ "Launch Deck",
+ "Ship Exterior",
+ "Arena",
+ "Great Hall (Noon)",
+ "Monstro (Interior A)",
+ "Monstro (Exterior)",
+ "Monstrio (Interior B)",
+ "Summit (Broken)"
+ };
+
+ public static readonly string[] Rooms_BD =
+ {
+ "Command Board",
+ "Land of Departure BG",
+ "02",
+ "Cinderella BG",
+ "04",
+ "05",
+ "06",
+ "07",
+ "08",
+ "Lilo & Stitch BG",
+ "10",
+ "Peter Pan BG",
+ "Disney Castle BG",
+ "13",
+ "14",
+ "15",
+ "16",
+ "17",
+ "Winnie the Pooh BG",
+ "Peter Pan BG"
+ };
+
+ public static readonly string[] Rooms_WM =
+ {
+ "World Map",
+ "wm01"
+ };
+
+ public static readonly string[] Rooms_JF =
+ {
+ "Jump Festa (sw10)",
+ "Jump Festa (cd07)",
+ "Jump Festa (cd09)",
+ "Jump Festa (sb10)",
+ "04",
+ "05",
+ "06",
+ "07",
+ "08",
+ "09",
+ "The Town",
+ "Poly Partition Test",
+ "12"
+ };
+ }
+}
diff --git a/OpenKh.Bbs/Ctd.cs b/OpenKh.Bbs/Ctd.cs
index 35834cc1b..f81a8cb2a 100644
--- a/OpenKh.Bbs/Ctd.cs
+++ b/OpenKh.Bbs/Ctd.cs
@@ -1,201 +1,201 @@
-using OpenKh.Bbs.Messages;
-using OpenKh.Common;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Xe.BinaryMapper;
-
-namespace OpenKh.Bbs
-{
- public class Ctd
- {
- private const int MagicCode = 0x44544340;
- private const int Version = 1;
- private const int HeaderLength = 0x20;
- private const int Entry1Length = 0xC;
- private const int Entry2Length = 0x20;
-
- private class Header
- {
- [Data] public int MagicCode { get; set; }
- [Data] public int Version { get; set; }
- [Data] public short Unknown08 { get; set; }
- [Data] public short Unknown0a { get; set; }
- [Data] public short LayoutCount { get; set; }
- [Data] public short MessageCount { get; set; }
- [Data] public int MessageOffset { get; set; }
- [Data] public int LayoutOffset { get; set; }
- [Data] public int TextOffset { get; set; }
- [Data] public int Unknown1c { get; set; }
- }
-
- private class _Message
- {
- [Data] public short Id { get; set; }
- [Data] public short Unknown02 { get; set; }
- [Data] public int Offset { get; set; }
- [Data] public int Entry2Index { get; set; }
- }
-
- public class Message
- {
- public short Id { get; set; }
- public short Unknown02 { get; set; }
- public int LayoutIndex { get; set; }
-
- public byte[] Data { get; set; }
-
- public string Text
- {
- get => CtdEncoders.International.ToText(Data);
- set => Data = CtdEncoders.International.FromText(value);
- }
-
- public override string ToString() =>
- $"{Id:X04} {Unknown02:X04} {LayoutIndex:X08}: {Text}";
- }
-
- public class Layout
- {
- [Data] public ushort DialogX { get; set; }
- [Data] public ushort DialogY { get; set; }
- [Data] public ushort DialogWidth { get; set; }
- [Data] public ushort DialogHeight { get; set; }
- [Data] public byte DialogAlignment { get; set; }
- [Data] public byte DialogBorders { get; set; }
- [Data] public byte TextAlignment { get; set; }
- [Data] public byte Unknown0b { get; set; }
- [Data] public ushort FontSize { get; set; }
- [Data] public ushort HorizontalSpace { get; set; }
- [Data] public ushort VerticalSpace { get; set; }
- [Data] public ushort TextX { get; set; }
- [Data] public ushort TextY { get; set; }
- [Data] public ushort DialogHook { get; set; }
- [Data] public ushort DialogHookX { get; set; }
- [Data] public ushort Unknown1a { get; set; }
- [Data] public ushort Unknown1c { get; set; }
- [Data] public ushort Unknown1e { get; set; }
- }
-
- public short Unknown { get; set; }
- public List Messages { get; set; }
- public List Layouts { get; set; }
-
- public string GetString(int id)
- {
- var entry = Messages.FirstOrDefault(x => x.Id == id);
- if (entry == null)
- return null;
-
- return entry.Text;
- }
-
- public void Write(Stream stream)
- {
- var messageOffset = HeaderLength;
- var layoutOffset = Helpers.Align(messageOffset + Messages.Count * Entry1Length, 16);
- var textOffset = layoutOffset + Layouts.Count * Entry2Length;
-
- BinaryMapping.WriteObject(stream, new Header
- {
- MagicCode = MagicCode,
- Version = Version,
- Unknown08 = 0,
- Unknown0a = Unknown,
- LayoutCount = (short)Layouts.Count,
- MessageCount = (short)Messages.Count,
- MessageOffset = messageOffset,
- LayoutOffset = layoutOffset,
- TextOffset = textOffset,
- Unknown1c = 0,
- });
-
- stream.Position = messageOffset;
- var textStream = new MemoryStream(4096);
- var nextTextOffset = textOffset;
- foreach (var item in Messages)
- {
- textStream.Write(item.Data, 0, item.Data.Length);
- textStream.WriteByte(0);
-
- BinaryMapping.WriteObject(stream, new _Message
- {
- Id = item.Id,
- Unknown02 = item.Unknown02,
- Offset = nextTextOffset,
- Entry2Index = item.LayoutIndex
- });
-
- nextTextOffset += item.Data.Length + 1;
- }
-
- stream.Position = layoutOffset;
- foreach (var item in Layouts)
- BinaryMapping.WriteObject(stream, item);
-
- stream.Position = textOffset;
- foreach (var entry in Messages)
- {
- stream.Write(entry.Data, 0, entry.Data.Length);
- stream.WriteByte(0);
- }
- }
-
- public Ctd()
- {
- Unknown = 0;
- Messages = new List();
- Layouts = new List();
- }
-
- private Ctd(Stream stream)
- {
- var header = BinaryMapping.ReadObject(stream);
- Unknown = header.Unknown0a;
-
- stream.Position = header.MessageOffset;
- var textEntries = Enumerable.Range(0, header.MessageCount)
- .Select(x => BinaryMapping.ReadObject<_Message>(stream))
- .ToList();
-
- stream.Position = header.LayoutOffset;
- Layouts = Enumerable.Range(0, header.LayoutCount)
- .Select(x => BinaryMapping.ReadObject(stream))
- .ToList();
-
- Messages = textEntries
- .Select(x =>
- {
- stream.SetPosition(x.Offset);
- return new Message
- {
- Id = x.Id,
- Unknown02 = x.Unknown02,
- LayoutIndex = x.Entry2Index,
- Data = ReadUntilTerminator(stream)
- };
- }).ToList();
- }
-
- private byte[] ReadUntilTerminator(Stream stream)
- {
- var byteList = new List(100);
-
- while (stream.Position < stream.Length)
- {
- var ch = stream.ReadByte();
- if (ch <= 0)
- break;
-
- byteList.Add((byte)ch);
- }
-
- return byteList.ToArray();
- }
-
- public static Ctd Read(Stream stream) => new Ctd(stream.SetPosition(0));
-
- public static bool IsValid(Stream stream) =>
- new BinaryReader(stream.SetPosition(0)).ReadInt32() == MagicCode;
- }
-}
+using OpenKh.Bbs.Messages;
+using OpenKh.Common;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Xe.BinaryMapper;
+
+namespace OpenKh.Bbs
+{
+ public class Ctd
+ {
+ private const int MagicCode = 0x44544340;
+ private const int Version = 1;
+ private const int HeaderLength = 0x20;
+ private const int Entry1Length = 0xC;
+ private const int Entry2Length = 0x20;
+
+ private class Header
+ {
+ [Data] public int MagicCode { get; set; }
+ [Data] public int Version { get; set; }
+ [Data] public short Unknown08 { get; set; }
+ [Data] public short Unknown0a { get; set; }
+ [Data] public short LayoutCount { get; set; }
+ [Data] public short MessageCount { get; set; }
+ [Data] public int MessageOffset { get; set; }
+ [Data] public int LayoutOffset { get; set; }
+ [Data] public int TextOffset { get; set; }
+ [Data] public int Unknown1c { get; set; }
+ }
+
+ private class _Message
+ {
+ [Data] public short Id { get; set; }
+ [Data] public short Unknown02 { get; set; }
+ [Data] public int Offset { get; set; }
+ [Data] public int Entry2Index { get; set; }
+ }
+
+ public class Message
+ {
+ public short Id { get; set; }
+ public short Unknown02 { get; set; }
+ public int LayoutIndex { get; set; }
+
+ public byte[] Data { get; set; }
+
+ public string Text
+ {
+ get => CtdEncoders.International.ToText(Data);
+ set => Data = CtdEncoders.International.FromText(value);
+ }
+
+ public override string ToString() =>
+ $"{Id:X04} {Unknown02:X04} {LayoutIndex:X08}: {Text}";
+ }
+
+ public class Layout
+ {
+ [Data] public ushort DialogX { get; set; }
+ [Data] public ushort DialogY { get; set; }
+ [Data] public ushort DialogWidth { get; set; }
+ [Data] public ushort DialogHeight { get; set; }
+ [Data] public byte DialogAlignment { get; set; }
+ [Data] public byte DialogBorders { get; set; }
+ [Data] public byte TextAlignment { get; set; }
+ [Data] public byte Unknown0b { get; set; }
+ [Data] public ushort FontSize { get; set; }
+ [Data] public ushort HorizontalSpace { get; set; }
+ [Data] public ushort VerticalSpace { get; set; }
+ [Data] public ushort TextX { get; set; }
+ [Data] public ushort TextY { get; set; }
+ [Data] public ushort DialogHook { get; set; }
+ [Data] public ushort DialogHookX { get; set; }
+ [Data] public ushort Unknown1a { get; set; }
+ [Data] public ushort Unknown1c { get; set; }
+ [Data] public ushort Unknown1e { get; set; }
+ }
+
+ public short Unknown { get; set; }
+ public List Messages { get; set; }
+ public List Layouts { get; set; }
+
+ public string GetString(int id)
+ {
+ var entry = Messages.FirstOrDefault(x => x.Id == id);
+ if (entry == null)
+ return null;
+
+ return entry.Text;
+ }
+
+ public void Write(Stream stream)
+ {
+ var messageOffset = HeaderLength;
+ var layoutOffset = Helpers.Align(messageOffset + Messages.Count * Entry1Length, 16);
+ var textOffset = layoutOffset + Layouts.Count * Entry2Length;
+
+ BinaryMapping.WriteObject(stream, new Header
+ {
+ MagicCode = MagicCode,
+ Version = Version,
+ Unknown08 = 0,
+ Unknown0a = Unknown,
+ LayoutCount = (short)Layouts.Count,
+ MessageCount = (short)Messages.Count,
+ MessageOffset = messageOffset,
+ LayoutOffset = layoutOffset,
+ TextOffset = textOffset,
+ Unknown1c = 0,
+ });
+
+ stream.Position = messageOffset;
+ var textStream = new MemoryStream(4096);
+ var nextTextOffset = textOffset;
+ foreach (var item in Messages)
+ {
+ textStream.Write(item.Data, 0, item.Data.Length);
+ textStream.WriteByte(0);
+
+ BinaryMapping.WriteObject(stream, new _Message
+ {
+ Id = item.Id,
+ Unknown02 = item.Unknown02,
+ Offset = nextTextOffset,
+ Entry2Index = item.LayoutIndex
+ });
+
+ nextTextOffset += item.Data.Length + 1;
+ }
+
+ stream.Position = layoutOffset;
+ foreach (var item in Layouts)
+ BinaryMapping.WriteObject(stream, item);
+
+ stream.Position = textOffset;
+ foreach (var entry in Messages)
+ {
+ stream.Write(entry.Data, 0, entry.Data.Length);
+ stream.WriteByte(0);
+ }
+ }
+
+ public Ctd()
+ {
+ Unknown = 0;
+ Messages = new List();
+ Layouts = new List();
+ }
+
+ private Ctd(Stream stream)
+ {
+ var header = BinaryMapping.ReadObject(stream);
+ Unknown = header.Unknown0a;
+
+ stream.Position = header.MessageOffset;
+ var textEntries = Enumerable.Range(0, header.MessageCount)
+ .Select(x => BinaryMapping.ReadObject<_Message>(stream))
+ .ToList();
+
+ stream.Position = header.LayoutOffset;
+ Layouts = Enumerable.Range(0, header.LayoutCount)
+ .Select(x => BinaryMapping.ReadObject(stream))
+ .ToList();
+
+ Messages = textEntries
+ .Select(x =>
+ {
+ stream.SetPosition(x.Offset);
+ return new Message
+ {
+ Id = x.Id,
+ Unknown02 = x.Unknown02,
+ LayoutIndex = x.Entry2Index,
+ Data = ReadUntilTerminator(stream)
+ };
+ }).ToList();
+ }
+
+ private byte[] ReadUntilTerminator(Stream stream)
+ {
+ var byteList = new List(100);
+
+ while (stream.Position < stream.Length)
+ {
+ var ch = stream.ReadByte();
+ if (ch <= 0)
+ break;
+
+ byteList.Add((byte)ch);
+ }
+
+ return byteList.ToArray();
+ }
+
+ public static Ctd Read(Stream stream) => new Ctd(stream.SetPosition(0));
+
+ public static bool IsValid(Stream stream) =>
+ new BinaryReader(stream.SetPosition(0)).ReadInt32() == MagicCode;
+ }
+}
diff --git a/OpenKh.Bbs/Epd.cs b/OpenKh.Bbs/Epd.cs
index a72b18030..5250b9182 100644
--- a/OpenKh.Bbs/Epd.cs
+++ b/OpenKh.Bbs/Epd.cs
@@ -1,373 +1,373 @@
-using OpenKh.Common;
-using OpenKh.Common.Utils;
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-using System.Numerics;
-using Xe.BinaryMapper;
-using System.Linq;
-
-namespace OpenKh.Bbs
-{
- public class Epd
- {
- private const uint MagicCode = 0x40455044;
- private const uint version = 9;
-
- public class Header
- {
- [Data] public uint MagicCode { get; set; }
- [Data] public uint version { get; set; }
- }
-
- public class GeneralParameters
- {
- [Data] public uint StatusAilmentsFlag { get; set; }
- [Data] public float Health { get; set; }
- [Data] public float ExperienceMultiplier { get; set; }
- [Data] public uint Size { get; set; }
- [Data] public float PhysicalDamageMultiplier { get; set; }
- [Data] public float FireDamageMultiplier { get; set; }
- [Data] public float IceDamageMultiplier { get; set; }
- [Data] public float ThunderDamageMultiplier { get; set; }
- [Data] public float DarknessDamageMultiplier { get; set; }
- [Data] public float NonElementalDamageMultiplier { get; set; }
- }
-
- public struct StatusAilment
- {
- public bool bFly;
- public bool bSmallDamageReaction;
- public bool bSmallDamageReactionOnly;
- public bool bHitback;
- public bool dummy4;
- public bool dummy5;
- public bool dummy6;
- public bool dummy7;
- public bool dummy8;
- public bool dummy9;
- public bool bPoison;
- public bool bSlow;
- public bool bStop;
- public bool bBind;
- public bool bFaint;
- public bool bFreeze;
- public bool bBurn;
- public bool bConfuse;
- public bool bBlind;
- public bool bDeath;
- public bool bZeroGravity;
- public bool bMini;
- public bool bMagnet;
- public bool bDegen;
- public bool bSleep;
- public bool dummy25;
- public bool dummy26;
- public bool dummy27;
- public bool dummy28;
- public bool dummy29;
- public bool dummy30;
- public bool dummy31;
- }
-
- public class OtherParameters
- {
- [Data] public ushort DamageCeiling { get; set; }
- [Data] public ushort DamageFloor { get; set; }
- [Data] public float fWeight { get; set; }
- [Data] public uint EffectivenessFlag { get; set; }
- [Data] public sbyte PrizeBoxProbability { get; set; }
- [Data(Count = 3)] public byte[] padding { get; set; }
- [Data] public uint TechniqueParameterCount { get; set; }
- [Data] public uint TechniqueParameterOffset { get; set; }
- [Data] public uint DropItemsCount { get; set; }
- [Data] public uint DropItemsOffset { get; set; }
- [Data] public uint ExtraParametersCount { get; set; }
- [Data] public uint ExtraParametersOffset { get; set; }
- }
-
- public struct EffectivenessFlag
- {
- public uint Poison;
- public uint Stop;
- public uint Bind;
- public uint Faint;
- public uint Blind;
- public uint Mini;
- }
-
- public class TechniqueParameters
- {
- [Data] public float TechniquePowerCorrection { get; set; }
- [Data] public byte TechniqueNumber { get; set; }
- [Data] public byte TechniqueKind { get; set; }
- [Data] public byte TechniqueAttribute { get; set; }
- [Data] public byte SuccessRate { get; set; }
- }
-
- public class DropParameters
- {
- [Data] public uint ItemIndex { get; set; }
- [Data] public ushort ItemCount { get; set; }
- [Data] public ushort Probability { get; set; }
- }
-
- public enum DropKind
- {
- ITEM_KIND_HP_SMALL = 0,
- ITEM_KIND_HP_BIG = 1,
- ITEM_KIND_MUNNY_SMALL = 2,
- ITEM_KIND_MUNNY_MIDDLE = 3,
- ITEM_KIND_MUNNY_BIGL = 4,
- ITEM_KIND_FOCUS_SMALL = 5,
- ITEM_KIND_FOCUS_BIG = 6,
- ITEM_KIND_DRAINMIST = 7,
- ITEM_KIND_D_LINK = 8,
- }
-
- public class ExtraParameters
- {
- [Data(Count = 12)] public string ParameterName { get; set; }
- [Data] public float ParameterValue { get; set; }
- }
-
- public enum AttackAttribute
- {
- ATK_ATTR_NONE = 0,
- ATK_ATTR_PHYSICAL = 1,
- ATK_ATTR_FIRE = 2,
- ATK_ATTR_ICE = 3,
- ATK_ATTR_THUNDER = 4,
- ATK_ATTR_DARK = 5,
- ATK_ATTR_ZERO = 6,
- ATK_ATTR_SPECIAL = 7
- }
-
- public enum AttackKind
- {
- ATK_KIND_NONE = 0,
- ATK_KIND_DMG_SMALL = 1,
- ATK_KIND_DMG_BIG = 2,
- ATK_KIND_DMG_BLOW = 3,
- ATK_KIND_DMG_TOSS = 4,
- ATK_KIND_DMG_BEAT = 5,
- ATK_KIND_DMG_FLICK = 6,
- ATK_KIND_POISON = 7,
- ATK_KIND_SLOW = 8,
- ATK_KIND_STOP = 9,
- ATK_KIND_BIND = 10,
- ATK_KIND_FAINT = 11,
- ATK_KIND_FREEZE = 12,
- ATK_KIND_BURN = 13,
- ATK_KIND_CONFUSE = 14,
- ATK_KIND_BLIND = 15,
- ATK_KIND_DEATH = 16,
- ATK_KIND_KILL = 17,
- ATK_KIND_CAPTURE = 18,
- ATK_KIND_MAGNET = 19,
- ATK_KIND_ZEROGRAVITY = 20,
- ATK_KIND_AERO = 21,
- ATK_KIND_TORNADO = 22,
- ATK_KIND_DEGENERATOR = 23,
- ATK_KIND_WITHOUT = 24,
- ATK_KIND_EAT = 25,
- ATK_KIND_TREASURERAID = 26,
- ATK_KIND_SLEEPINGDEATH = 27,
- ATK_KIND_SLEEP = 28,
- ATK_KIND_MAGNET_MUNNY = 29,
- ATK_KIND_MAGNET_HP = 30,
- ATK_KIND_MAGNET_FOCUS = 31,
- ATK_KIND_MINIMUM = 32,
- ATK_KIND_QUAKE = 33,
- ATK_KIND_RECOVER = 34,
- ATK_KIND_DISCOMMAND = 35,
- ATK_KIND_DISPRIZE_M = 36,
- ATK_KIND_DISPRIZE_H = 37,
- ATK_KIND_DISPRIZE_F = 38,
- ATK_KIND_DETONE = 39,
- ATK_KIND_GM_BLOW = 40,
- ATK_KIND_BLAST = 41,
- ATK_KIND_MAGNESPIRAL = 42,
- ATK_KIND_GLACIALARTS = 43,
- ATK_KIND_TRANSCENDENCE = 44,
- ATK_KIND_VENGEANCE = 45,
- ATK_KIND_MAGNEBREAKER = 46,
- ATK_KIND_MAGICIMPULSE_CF = 47,
- ATK_KIND_MAGICIMPULSE_CFB = 48,
- ATK_KIND_MAGICIMPULSE_CFBB = 49,
- ATK_KIND_DMG_RISE = 50,
- ATK_KIND_STUMBLE = 51,
- ATK_KIND_MOUNT = 52,
- ATK_KIND_IMPRISONMENT = 53,
- ATK_KIND_SLOWSTOP = 54,
- ATK_KIND_GATHERING = 55,
- ATK_KIND_EXHAUSTED = 56
- }
-
- public static StatusAilment GetStatusAilment(Epd epd)
- {
- StatusAilment stat = new StatusAilment();
- stat.bFly = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 0);
- stat.bSmallDamageReaction = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 1);
- stat.bSmallDamageReactionOnly = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 2);
- stat.bHitback = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 3);
- stat.bPoison = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 10);
- stat.bSlow = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 11);
- stat.bStop = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 12);
- stat.bBind = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 13);
- stat.bFaint = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 14);
- stat.bFreeze = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 15);
- stat.bBurn = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 16);
- stat.bConfuse = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 17);
- stat.bBlind = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 18);
- stat.bDeath = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 19);
- stat.bZeroGravity = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 20);
- stat.bMini = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 21);
- stat.bMagnet = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 22);
- stat.bDegen = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 23);
- stat.bSleep = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 24);
-
- return stat;
- }
-
- public static uint GetStatusAilmentFromStates(bool Fly, bool SmallDamage, bool SmallDamageOnly, bool Hitback, bool Poison, bool Slow,
- bool Stop, bool Bind, bool Faint, bool Freeze, bool Burn, bool Confuse, bool Blind, bool Death,
- bool ZeroGravity, bool Mini, bool Magnet, bool Degen, bool Sleep)
- {
- uint AilmentFlag = 0;
-
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 0, Fly);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 1, SmallDamage);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 2, SmallDamageOnly);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 3, Hitback);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 10, Poison);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 11, Slow);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 12, Stop);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 13, Bind);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 14, Faint);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 15, Freeze);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 16, Burn);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 17, Confuse);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 18, Blind);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 19, Death);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 20, ZeroGravity);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 21, Mini);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 22, Magnet);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 23, Degen);
- AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 24, Sleep);
-
- return AilmentFlag;
- }
-
- public static uint GetEffectivenessFlagFromStates(uint Poison, uint Stop, uint Bind, uint Faint, uint Blind, uint Minimum)
- {
- uint Effectiveness = 0;
- Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 0, 2, Poison);
- Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 2, 2, Stop);
- Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 4, 2, Bind);
- Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 6, 2, Faint);
- Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 8, 2, Blind);
- Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 10, 2, Minimum);
-
- return Effectiveness;
- }
-
- public static EffectivenessFlag GetEffectivenessFlag(Epd epd)
- {
- EffectivenessFlag flag = new EffectivenessFlag();
- int val = (int)epd.otherParameters.EffectivenessFlag;
- flag.Poison = (uint)BitsUtil.Int.GetBits(val, 0, 2);
- flag.Stop = (uint)BitsUtil.Int.GetBits(val, 2, 2);
- flag.Bind = (uint)BitsUtil.Int.GetBits(val, 4, 2);
- flag.Faint = (uint)BitsUtil.Int.GetBits(val, 6, 2);
- flag.Blind = (uint)BitsUtil.Int.GetBits(val, 8, 2);
- flag.Mini = (uint)BitsUtil.Int.GetBits(val, 10, 2);
-
- return flag;
- }
-
- public Header header;
- public GeneralParameters generalParameters;
- public List AnimationList = new List();
- public OtherParameters otherParameters;
- public List techniqueParameters = new List();
- public List dropParameters = new List();
- public List extraParameters = new List();
-
- public static Epd Read(Stream stream)
- {
- Epd epd = new Epd();
- epd.header = BinaryMapping.ReadObject(stream);
- epd.generalParameters = BinaryMapping.ReadObject(stream);
- BinaryReader r = new BinaryReader(stream);
-
- for(int i = 0; i < 18; i++)
- {
- char[] animName = r.ReadChars(4);
- epd.AnimationList.Add(animName);
- }
- stream.Seek(8, SeekOrigin.Current);
-
-
- epd.otherParameters = BinaryMapping.ReadObject(stream);
-
- stream.Seek(epd.otherParameters.TechniqueParameterOffset, SeekOrigin.Begin);
- for(int t = 0; t < epd.otherParameters.TechniqueParameterCount; t++)
- {
- epd.techniqueParameters.Add(BinaryMapping.ReadObject(stream));
- }
-
- stream.Seek(epd.otherParameters.DropItemsOffset, SeekOrigin.Begin);
- for (int t = 0; t < epd.otherParameters.DropItemsCount; t++)
- {
- epd.dropParameters.Add(BinaryMapping.ReadObject(stream));
- }
-
- stream.Seek(epd.otherParameters.ExtraParametersOffset, SeekOrigin.Begin);
- for (int t = 0; t < epd.otherParameters.ExtraParametersCount; t++)
- {
- epd.extraParameters.Add(BinaryMapping.ReadObject(stream));
- }
-
- return epd;
- }
-
- public static void Write(Stream stream, Epd epd)
- {
- BinaryMapping.WriteObject(stream, epd.header);
- BinaryMapping.WriteObject(stream, epd.generalParameters);
- BinaryWriter w = new BinaryWriter(stream);
-
- foreach(char[] anim in epd.AnimationList)
- {
- w.Write(anim);
- }
-
- stream.Write((uint)0);
- stream.Write((uint)0);
-
- BinaryMapping.WriteObject(stream, epd.otherParameters);
-
- foreach (TechniqueParameters param in epd.techniqueParameters)
- {
- BinaryMapping.WriteObject(stream, param);
- }
-
- foreach (DropParameters param in epd.dropParameters)
- {
- BinaryMapping.WriteObject(stream, param);
- }
-
- foreach (ExtraParameters param in epd.extraParameters)
- {
- BinaryMapping.WriteObject(stream, param);
- }
- }
-
- public static bool IsValid(Stream stream) =>
- stream.Length >= 0x10 &&
- stream.SetPosition(0).ReadUInt32() == MagicCode &&
- stream.SetPosition(4).ReadUInt32() == version;
- }
-}
+using OpenKh.Common;
+using OpenKh.Common.Utils;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using System.Numerics;
+using Xe.BinaryMapper;
+using System.Linq;
+
+namespace OpenKh.Bbs
+{
+ public class Epd
+ {
+ private const uint MagicCode = 0x40455044;
+ private const uint version = 9;
+
+ public class Header
+ {
+ [Data] public uint MagicCode { get; set; }
+ [Data] public uint version { get; set; }
+ }
+
+ public class GeneralParameters
+ {
+ [Data] public uint StatusAilmentsFlag { get; set; }
+ [Data] public float Health { get; set; }
+ [Data] public float ExperienceMultiplier { get; set; }
+ [Data] public uint Size { get; set; }
+ [Data] public float PhysicalDamageMultiplier { get; set; }
+ [Data] public float FireDamageMultiplier { get; set; }
+ [Data] public float IceDamageMultiplier { get; set; }
+ [Data] public float ThunderDamageMultiplier { get; set; }
+ [Data] public float DarknessDamageMultiplier { get; set; }
+ [Data] public float NonElementalDamageMultiplier { get; set; }
+ }
+
+ public struct StatusAilment
+ {
+ public bool bFly;
+ public bool bSmallDamageReaction;
+ public bool bSmallDamageReactionOnly;
+ public bool bHitback;
+ public bool dummy4;
+ public bool dummy5;
+ public bool dummy6;
+ public bool dummy7;
+ public bool dummy8;
+ public bool dummy9;
+ public bool bPoison;
+ public bool bSlow;
+ public bool bStop;
+ public bool bBind;
+ public bool bFaint;
+ public bool bFreeze;
+ public bool bBurn;
+ public bool bConfuse;
+ public bool bBlind;
+ public bool bDeath;
+ public bool bZeroGravity;
+ public bool bMini;
+ public bool bMagnet;
+ public bool bDegen;
+ public bool bSleep;
+ public bool dummy25;
+ public bool dummy26;
+ public bool dummy27;
+ public bool dummy28;
+ public bool dummy29;
+ public bool dummy30;
+ public bool dummy31;
+ }
+
+ public class OtherParameters
+ {
+ [Data] public ushort DamageCeiling { get; set; }
+ [Data] public ushort DamageFloor { get; set; }
+ [Data] public float fWeight { get; set; }
+ [Data] public uint EffectivenessFlag { get; set; }
+ [Data] public sbyte PrizeBoxProbability { get; set; }
+ [Data(Count = 3)] public byte[] padding { get; set; }
+ [Data] public uint TechniqueParameterCount { get; set; }
+ [Data] public uint TechniqueParameterOffset { get; set; }
+ [Data] public uint DropItemsCount { get; set; }
+ [Data] public uint DropItemsOffset { get; set; }
+ [Data] public uint ExtraParametersCount { get; set; }
+ [Data] public uint ExtraParametersOffset { get; set; }
+ }
+
+ public struct EffectivenessFlag
+ {
+ public uint Poison;
+ public uint Stop;
+ public uint Bind;
+ public uint Faint;
+ public uint Blind;
+ public uint Mini;
+ }
+
+ public class TechniqueParameters
+ {
+ [Data] public float TechniquePowerCorrection { get; set; }
+ [Data] public byte TechniqueNumber { get; set; }
+ [Data] public byte TechniqueKind { get; set; }
+ [Data] public byte TechniqueAttribute { get; set; }
+ [Data] public byte SuccessRate { get; set; }
+ }
+
+ public class DropParameters
+ {
+ [Data] public uint ItemIndex { get; set; }
+ [Data] public ushort ItemCount { get; set; }
+ [Data] public ushort Probability { get; set; }
+ }
+
+ public enum DropKind
+ {
+ ITEM_KIND_HP_SMALL = 0,
+ ITEM_KIND_HP_BIG = 1,
+ ITEM_KIND_MUNNY_SMALL = 2,
+ ITEM_KIND_MUNNY_MIDDLE = 3,
+ ITEM_KIND_MUNNY_BIGL = 4,
+ ITEM_KIND_FOCUS_SMALL = 5,
+ ITEM_KIND_FOCUS_BIG = 6,
+ ITEM_KIND_DRAINMIST = 7,
+ ITEM_KIND_D_LINK = 8,
+ }
+
+ public class ExtraParameters
+ {
+ [Data(Count = 12)] public string ParameterName { get; set; }
+ [Data] public float ParameterValue { get; set; }
+ }
+
+ public enum AttackAttribute
+ {
+ ATK_ATTR_NONE = 0,
+ ATK_ATTR_PHYSICAL = 1,
+ ATK_ATTR_FIRE = 2,
+ ATK_ATTR_ICE = 3,
+ ATK_ATTR_THUNDER = 4,
+ ATK_ATTR_DARK = 5,
+ ATK_ATTR_ZERO = 6,
+ ATK_ATTR_SPECIAL = 7
+ }
+
+ public enum AttackKind
+ {
+ ATK_KIND_NONE = 0,
+ ATK_KIND_DMG_SMALL = 1,
+ ATK_KIND_DMG_BIG = 2,
+ ATK_KIND_DMG_BLOW = 3,
+ ATK_KIND_DMG_TOSS = 4,
+ ATK_KIND_DMG_BEAT = 5,
+ ATK_KIND_DMG_FLICK = 6,
+ ATK_KIND_POISON = 7,
+ ATK_KIND_SLOW = 8,
+ ATK_KIND_STOP = 9,
+ ATK_KIND_BIND = 10,
+ ATK_KIND_FAINT = 11,
+ ATK_KIND_FREEZE = 12,
+ ATK_KIND_BURN = 13,
+ ATK_KIND_CONFUSE = 14,
+ ATK_KIND_BLIND = 15,
+ ATK_KIND_DEATH = 16,
+ ATK_KIND_KILL = 17,
+ ATK_KIND_CAPTURE = 18,
+ ATK_KIND_MAGNET = 19,
+ ATK_KIND_ZEROGRAVITY = 20,
+ ATK_KIND_AERO = 21,
+ ATK_KIND_TORNADO = 22,
+ ATK_KIND_DEGENERATOR = 23,
+ ATK_KIND_WITHOUT = 24,
+ ATK_KIND_EAT = 25,
+ ATK_KIND_TREASURERAID = 26,
+ ATK_KIND_SLEEPINGDEATH = 27,
+ ATK_KIND_SLEEP = 28,
+ ATK_KIND_MAGNET_MUNNY = 29,
+ ATK_KIND_MAGNET_HP = 30,
+ ATK_KIND_MAGNET_FOCUS = 31,
+ ATK_KIND_MINIMUM = 32,
+ ATK_KIND_QUAKE = 33,
+ ATK_KIND_RECOVER = 34,
+ ATK_KIND_DISCOMMAND = 35,
+ ATK_KIND_DISPRIZE_M = 36,
+ ATK_KIND_DISPRIZE_H = 37,
+ ATK_KIND_DISPRIZE_F = 38,
+ ATK_KIND_DETONE = 39,
+ ATK_KIND_GM_BLOW = 40,
+ ATK_KIND_BLAST = 41,
+ ATK_KIND_MAGNESPIRAL = 42,
+ ATK_KIND_GLACIALARTS = 43,
+ ATK_KIND_TRANSCENDENCE = 44,
+ ATK_KIND_VENGEANCE = 45,
+ ATK_KIND_MAGNEBREAKER = 46,
+ ATK_KIND_MAGICIMPULSE_CF = 47,
+ ATK_KIND_MAGICIMPULSE_CFB = 48,
+ ATK_KIND_MAGICIMPULSE_CFBB = 49,
+ ATK_KIND_DMG_RISE = 50,
+ ATK_KIND_STUMBLE = 51,
+ ATK_KIND_MOUNT = 52,
+ ATK_KIND_IMPRISONMENT = 53,
+ ATK_KIND_SLOWSTOP = 54,
+ ATK_KIND_GATHERING = 55,
+ ATK_KIND_EXHAUSTED = 56
+ }
+
+ public static StatusAilment GetStatusAilment(Epd epd)
+ {
+ StatusAilment stat = new StatusAilment();
+ stat.bFly = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 0);
+ stat.bSmallDamageReaction = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 1);
+ stat.bSmallDamageReactionOnly = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 2);
+ stat.bHitback = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 3);
+ stat.bPoison = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 10);
+ stat.bSlow = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 11);
+ stat.bStop = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 12);
+ stat.bBind = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 13);
+ stat.bFaint = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 14);
+ stat.bFreeze = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 15);
+ stat.bBurn = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 16);
+ stat.bConfuse = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 17);
+ stat.bBlind = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 18);
+ stat.bDeath = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 19);
+ stat.bZeroGravity = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 20);
+ stat.bMini = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 21);
+ stat.bMagnet = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 22);
+ stat.bDegen = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 23);
+ stat.bSleep = BitsUtil.Int.GetBit((int)epd.generalParameters.StatusAilmentsFlag, 24);
+
+ return stat;
+ }
+
+ public static uint GetStatusAilmentFromStates(bool Fly, bool SmallDamage, bool SmallDamageOnly, bool Hitback, bool Poison, bool Slow,
+ bool Stop, bool Bind, bool Faint, bool Freeze, bool Burn, bool Confuse, bool Blind, bool Death,
+ bool ZeroGravity, bool Mini, bool Magnet, bool Degen, bool Sleep)
+ {
+ uint AilmentFlag = 0;
+
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 0, Fly);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 1, SmallDamage);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 2, SmallDamageOnly);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 3, Hitback);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 10, Poison);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 11, Slow);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 12, Stop);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 13, Bind);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 14, Faint);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 15, Freeze);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 16, Burn);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 17, Confuse);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 18, Blind);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 19, Death);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 20, ZeroGravity);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 21, Mini);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 22, Magnet);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 23, Degen);
+ AilmentFlag = BitsUtil.Int.SetBit(AilmentFlag, 24, Sleep);
+
+ return AilmentFlag;
+ }
+
+ public static uint GetEffectivenessFlagFromStates(uint Poison, uint Stop, uint Bind, uint Faint, uint Blind, uint Minimum)
+ {
+ uint Effectiveness = 0;
+ Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 0, 2, Poison);
+ Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 2, 2, Stop);
+ Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 4, 2, Bind);
+ Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 6, 2, Faint);
+ Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 8, 2, Blind);
+ Effectiveness = BitsUtil.Int.SetBits(Effectiveness, 10, 2, Minimum);
+
+ return Effectiveness;
+ }
+
+ public static EffectivenessFlag GetEffectivenessFlag(Epd epd)
+ {
+ EffectivenessFlag flag = new EffectivenessFlag();
+ int val = (int)epd.otherParameters.EffectivenessFlag;
+ flag.Poison = (uint)BitsUtil.Int.GetBits(val, 0, 2);
+ flag.Stop = (uint)BitsUtil.Int.GetBits(val, 2, 2);
+ flag.Bind = (uint)BitsUtil.Int.GetBits(val, 4, 2);
+ flag.Faint = (uint)BitsUtil.Int.GetBits(val, 6, 2);
+ flag.Blind = (uint)BitsUtil.Int.GetBits(val, 8, 2);
+ flag.Mini = (uint)BitsUtil.Int.GetBits(val, 10, 2);
+
+ return flag;
+ }
+
+ public Header header;
+ public GeneralParameters generalParameters;
+ public List AnimationList = new List();
+ public OtherParameters otherParameters;
+ public List techniqueParameters = new List();
+ public List dropParameters = new List();
+ public List extraParameters = new List();
+
+ public static Epd Read(Stream stream)
+ {
+ Epd epd = new Epd();
+ epd.header = BinaryMapping.ReadObject(stream);
+ epd.generalParameters = BinaryMapping.ReadObject(stream);
+ BinaryReader r = new BinaryReader(stream);
+
+ for (int i = 0; i < 18; i++)
+ {
+ char[] animName = r.ReadChars(4);
+ epd.AnimationList.Add(animName);
+ }
+ stream.Seek(8, SeekOrigin.Current);
+
+
+ epd.otherParameters = BinaryMapping.ReadObject(stream);
+
+ stream.Seek(epd.otherParameters.TechniqueParameterOffset, SeekOrigin.Begin);
+ for (int t = 0; t < epd.otherParameters.TechniqueParameterCount; t++)
+ {
+ epd.techniqueParameters.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ stream.Seek(epd.otherParameters.DropItemsOffset, SeekOrigin.Begin);
+ for (int t = 0; t < epd.otherParameters.DropItemsCount; t++)
+ {
+ epd.dropParameters.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ stream.Seek(epd.otherParameters.ExtraParametersOffset, SeekOrigin.Begin);
+ for (int t = 0; t < epd.otherParameters.ExtraParametersCount; t++)
+ {
+ epd.extraParameters.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ return epd;
+ }
+
+ public static void Write(Stream stream, Epd epd)
+ {
+ BinaryMapping.WriteObject(stream, epd.header);
+ BinaryMapping.WriteObject(stream, epd.generalParameters);
+ BinaryWriter w = new BinaryWriter(stream);
+
+ foreach (char[] anim in epd.AnimationList)
+ {
+ w.Write(anim);
+ }
+
+ stream.Write((uint)0);
+ stream.Write((uint)0);
+
+ BinaryMapping.WriteObject(stream, epd.otherParameters);
+
+ foreach (TechniqueParameters param in epd.techniqueParameters)
+ {
+ BinaryMapping.WriteObject(stream, param);
+ }
+
+ foreach (DropParameters param in epd.dropParameters)
+ {
+ BinaryMapping.WriteObject(stream, param);
+ }
+
+ foreach (ExtraParameters param in epd.extraParameters)
+ {
+ BinaryMapping.WriteObject(stream, param);
+ }
+ }
+
+ public static bool IsValid(Stream stream) =>
+ stream.Length >= 0x10 &&
+ stream.SetPosition(0).ReadUInt32() == MagicCode &&
+ stream.SetPosition(4).ReadUInt32() == version;
+ }
+}
diff --git a/OpenKh.Bbs/Event.cs b/OpenKh.Bbs/Event.cs
index c6fb36d9a..87eabda82 100644
--- a/OpenKh.Bbs/Event.cs
+++ b/OpenKh.Bbs/Event.cs
@@ -1,54 +1,54 @@
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Xe.BinaryMapper;
-
-namespace OpenKh.Bbs
-{
- public class Event
- {
- private const int MagicCode = 1;
-
- private class Header
- {
- [Data] public int MagicCode { get; set; }
- [Data] public int Count { get; set; }
- }
-
- [Data] public ushort Id { get; set; }
- [Data] public ushort EventIndex { get; set; }
- [Data] public byte World { get; set; }
- [Data] public byte Room { get; set; }
- [Data] public byte EventPtn { get; set; }
- [Data] public byte Opt { get; set; }
-
- public static bool IsValid(Stream stream)
- {
- var prevPosition = stream.Position;
- var magicCode = new BinaryReader(stream).ReadInt32();
- stream.Position = prevPosition;
-
- return magicCode == MagicCode;
- }
-
- public static List Read(Stream stream)
- {
- var header = BinaryMapping.ReadObject(stream);
- return Enumerable.Range(0, header.Count)
- .Select(_ => BinaryMapping.ReadObject(stream))
- .ToList();
- }
-
- public static void Write(Stream stream, IEnumerable events)
- {
- var list = events.ToList();
- BinaryMapping.WriteObject(stream, new Header
- {
- MagicCode = MagicCode,
- Count = list.Count
- });
- foreach (var item in list)
- BinaryMapping.WriteObject(stream, item);
- }
- }
-}
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Xe.BinaryMapper;
+
+namespace OpenKh.Bbs
+{
+ public class Event
+ {
+ private const int MagicCode = 1;
+
+ private class Header
+ {
+ [Data] public int MagicCode { get; set; }
+ [Data] public int Count { get; set; }
+ }
+
+ [Data] public ushort Id { get; set; }
+ [Data] public ushort EventIndex { get; set; }
+ [Data] public byte World { get; set; }
+ [Data] public byte Room { get; set; }
+ [Data] public byte EventPtn { get; set; }
+ [Data] public byte Opt { get; set; }
+
+ public static bool IsValid(Stream stream)
+ {
+ var prevPosition = stream.Position;
+ var magicCode = new BinaryReader(stream).ReadInt32();
+ stream.Position = prevPosition;
+
+ return magicCode == MagicCode;
+ }
+
+ public static List Read(Stream stream)
+ {
+ var header = BinaryMapping.ReadObject(stream);
+ return Enumerable.Range(0, header.Count)
+ .Select(_ => BinaryMapping.ReadObject(stream))
+ .ToList();
+ }
+
+ public static void Write(Stream stream, IEnumerable events)
+ {
+ var list = events.ToList();
+ BinaryMapping.WriteObject(stream, new Header
+ {
+ MagicCode = MagicCode,
+ Count = list.Count
+ });
+ foreach (var item in list)
+ BinaryMapping.WriteObject(stream, item);
+ }
+ }
+}
diff --git a/OpenKh.Bbs/FontCharacterInfo.cs b/OpenKh.Bbs/FontCharacterInfo.cs
index dfa9a6582..53c0bb92d 100644
--- a/OpenKh.Bbs/FontCharacterInfo.cs
+++ b/OpenKh.Bbs/FontCharacterInfo.cs
@@ -1,36 +1,36 @@
-using System.Collections.Generic;
-using System.IO;
-using Xe.BinaryMapper;
-
-namespace OpenKh.Bbs
-{
- public class FontCharacterInfo
- {
- [Data] public ushort Id { get; set; }
- [Data] public ushort PositionX { get; set; }
- [Data] public ushort PositionY { get; set; }
- [Data] public byte Palette { get; set; }
- [Data] public byte Width { get; set; }
-
- public static FontCharacterInfo[] Read(Stream stream)
- {
- var characterCount = (int)stream.Length / 8;
- var charactersInfo = new FontCharacterInfo[characterCount];
- stream.Position = 0;
-
- for (var i = 0; i < characterCount; i++)
- charactersInfo[i] = BinaryMapping.ReadObject(stream);
-
- return charactersInfo;
- }
-
- public static void Write(Stream stream, IEnumerable charactersInfo)
- {
- stream.Position = 0;
- foreach (var info in charactersInfo)
- BinaryMapping.WriteObject(stream, info);
-
- stream.SetLength(stream.Position);
- }
- }
-}
+using System.Collections.Generic;
+using System.IO;
+using Xe.BinaryMapper;
+
+namespace OpenKh.Bbs
+{
+ public class FontCharacterInfo
+ {
+ [Data] public ushort Id { get; set; }
+ [Data] public ushort PositionX { get; set; }
+ [Data] public ushort PositionY { get; set; }
+ [Data] public byte Palette { get; set; }
+ [Data] public byte Width { get; set; }
+
+ public static FontCharacterInfo[] Read(Stream stream)
+ {
+ var characterCount = (int)stream.Length / 8;
+ var charactersInfo = new FontCharacterInfo[characterCount];
+ stream.Position = 0;
+
+ for (var i = 0; i < characterCount; i++)
+ charactersInfo[i] = BinaryMapping.ReadObject(stream);
+
+ return charactersInfo;
+ }
+
+ public static void Write(Stream stream, IEnumerable charactersInfo)
+ {
+ stream.Position = 0;
+ foreach (var info in charactersInfo)
+ BinaryMapping.WriteObject(stream, info);
+
+ stream.SetLength(stream.Position);
+ }
+ }
+}
diff --git a/OpenKh.Bbs/FontIconInfo.cs b/OpenKh.Bbs/FontIconInfo.cs
index 2f30c7bdb..0affdbb37 100644
--- a/OpenKh.Bbs/FontIconInfo.cs
+++ b/OpenKh.Bbs/FontIconInfo.cs
@@ -1,59 +1,59 @@
-using OpenKh.Common;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Xe.BinaryMapper;
-
-namespace OpenKh.Bbs
-{
- public class FontIconInfo
- {
- public ushort Key { get; set; }
- public byte Left { get; set; }
- public byte Top { get; set; }
- public byte Right { get; set; }
- public byte Bottom { get; set; }
-
- private class MetaIcon
- {
- [Data] public ushort Key { get; set; }
- [Data] public byte Left { get; set; }
- [Data] public byte Top { get; set; }
- [Data] public byte Right { get; set; }
- [Data] public byte Bottom { get; set; }
- [Data] public short RESERVED { get; set; }
- }
-
- public static IEnumerable Read(Stream stream)
- {
- var count = stream.ReadInt32();
- return Enumerable.Range(0, count)
- .Select(_ => BinaryMapping.ReadObject(stream))
- .Select(x => new FontIconInfo
- {
- Key = x.Key,
- Left = x.Left,
- Top = x.Top,
- Right = x.Right,
- Bottom = x.Bottom
- })
- .ToArray();
- }
-
- public static void Write(Stream stream, IEnumerable fontIconsInfo)
- {
- var myFontIconsInfo = fontIconsInfo.ToArray();
- stream.Write(myFontIconsInfo.Length);
- foreach (var info in myFontIconsInfo)
- BinaryMapping.WriteObject(stream, new MetaIcon
- {
- Key = info.Key,
- Left = info.Left,
- Top = info.Top,
- Right = info.Right,
- Bottom = info.Bottom,
- RESERVED = 0
- });
- }
- }
-}
+using OpenKh.Common;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Xe.BinaryMapper;
+
+namespace OpenKh.Bbs
+{
+ public class FontIconInfo
+ {
+ public ushort Key { get; set; }
+ public byte Left { get; set; }
+ public byte Top { get; set; }
+ public byte Right { get; set; }
+ public byte Bottom { get; set; }
+
+ private class MetaIcon
+ {
+ [Data] public ushort Key { get; set; }
+ [Data] public byte Left { get; set; }
+ [Data] public byte Top { get; set; }
+ [Data] public byte Right { get; set; }
+ [Data] public byte Bottom { get; set; }
+ [Data] public short RESERVED { get; set; }
+ }
+
+ public static IEnumerable Read(Stream stream)
+ {
+ var count = stream.ReadInt32();
+ return Enumerable.Range(0, count)
+ .Select(_ => BinaryMapping.ReadObject(stream))
+ .Select(x => new FontIconInfo
+ {
+ Key = x.Key,
+ Left = x.Left,
+ Top = x.Top,
+ Right = x.Right,
+ Bottom = x.Bottom
+ })
+ .ToArray();
+ }
+
+ public static void Write(Stream stream, IEnumerable fontIconsInfo)
+ {
+ var myFontIconsInfo = fontIconsInfo.ToArray();
+ stream.Write(myFontIconsInfo.Length);
+ foreach (var info in myFontIconsInfo)
+ BinaryMapping.WriteObject(stream, new MetaIcon
+ {
+ Key = info.Key,
+ Left = info.Left,
+ Top = info.Top,
+ Right = info.Right,
+ Bottom = info.Bottom,
+ RESERVED = 0
+ });
+ }
+ }
+}
diff --git a/OpenKh.Bbs/FontInfo.cs b/OpenKh.Bbs/FontInfo.cs
index 12bf19629..6f2ce00ad 100644
--- a/OpenKh.Bbs/FontInfo.cs
+++ b/OpenKh.Bbs/FontInfo.cs
@@ -1,20 +1,20 @@
-using System.IO;
-using Xe.BinaryMapper;
-
-namespace OpenKh.Bbs
-{
- public class FontInfo
- {
- [Data] public short CharacterCount { get; set; }
- [Data] public short ImageWidth { get; set; }
- [Data] public short MaxImageHeight { get; set; }
- [Data] public byte CharacterWidth { get; set; }
- [Data] public byte CharacterHeight { get; set; }
-
- public static FontInfo Read(Stream stream) =>
- BinaryMapping.ReadObject(stream);
-
- public void Write(Stream stream) =>
- BinaryMapping.WriteObject(stream, this);
- }
-}
+using System.IO;
+using Xe.BinaryMapper;
+
+namespace OpenKh.Bbs
+{
+ public class FontInfo
+ {
+ [Data] public short CharacterCount { get; set; }
+ [Data] public short ImageWidth { get; set; }
+ [Data] public short MaxImageHeight { get; set; }
+ [Data] public byte CharacterWidth { get; set; }
+ [Data] public byte CharacterHeight { get; set; }
+
+ public static FontInfo Read(Stream stream) =>
+ BinaryMapping.ReadObject(stream);
+
+ public void Write(Stream stream) =>
+ BinaryMapping.WriteObject(stream, this);
+ }
+}
diff --git a/OpenKh.Bbs/FontsArc.cs b/OpenKh.Bbs/FontsArc.cs
index 06dee6864..09b1bc4ea 100644
--- a/OpenKh.Bbs/FontsArc.cs
+++ b/OpenKh.Bbs/FontsArc.cs
@@ -1,152 +1,152 @@
-using OpenKh.Common;
-using OpenKh.Imaging;
-using System;
-using System.Collections.Generic;
-using System.Drawing;
-using System.IO;
-using System.Linq;
-
-namespace OpenKh.Bbs
-{
- public class FontsArc
- {
- private class Image : IImageRead
- {
- private readonly byte[] _imageData;
- private readonly byte[] _clutData;
-
- internal Image(string name, Arc.Entry mtx, byte[] clut, int width, int maxHeight, PixelFormat pixelFormat)
- {
- Name = name;
- Size = new Size(width, maxHeight);
- PixelFormat = pixelFormat;
-
- var bpp = 0;
- switch (pixelFormat)
- {
- case PixelFormat.Indexed4:
- bpp = 4;
- break;
- case PixelFormat.Indexed8:
- bpp = 8;
- break;
- }
-
- _imageData = new byte[width * maxHeight * bpp / 8];
- Array.Copy(mtx.Data, _imageData, Math.Min(_imageData.Length, mtx.Data.Length));
- _imageData = Unswizzle(_imageData, width * bpp / 8);
- if (pixelFormat == PixelFormat.Indexed4)
- InvertEndianess(_imageData);
-
- _clutData = new byte[clut.Length];
- Array.Copy(clut, _clutData, _clutData.Length);
- }
-
- public string Name { get; }
-
- public Size Size { get; }
-
- public PixelFormat PixelFormat { get; }
-
- public byte[] GetClut() => _clutData;
-
- public byte[] GetData() => _imageData;
- }
-
- public class Font
- {
- public string Name { get; }
- public IImageRead Image1 { get; }
- public IImageRead Image2 { get; }
- public FontInfo Info { get; }
- public FontCharacterInfo[] CharactersInfo { get; }
-
- public Font(IEnumerable entries, string name)
- {
- Name = name;
-
- var mtx = RequireFileEntry(entries, $"{name}.mtx");
- var clu = RequireFileEntry(entries, $"{name}.clu");
- Info = new MemoryStream(RequireFileEntry(entries, $"{name}.inf").Data)
- .Using(stream => FontInfo.Read(stream));
-
- var clut = new byte[0x40];
- Array.Copy(clu.Data, 0, clut, 0, clut.Length);
- Image1 = new Image(name, mtx, clut, Info.ImageWidth, Info.MaxImageHeight, PixelFormat.Indexed4);
-
- Array.Copy(clu.Data, 0x40, clut, 0, clut.Length);
- Image2 = new Image(name, mtx, clut, Info.ImageWidth, Info.MaxImageHeight, PixelFormat.Indexed4);
-
- CharactersInfo = new MemoryStream(RequireFileEntry(entries, $"{name}.cod").Data).Using(stream =>
- FontCharacterInfo.Read(stream));
- }
- }
-
- private readonly IEnumerable _entries;
-
- private FontsArc(Stream stream)
- {
- _entries = Arc.Read(stream);
-
- FontIcon = CreateFontIconImage(_entries, "FontIcon");
- FontCmd = new Font(_entries, "cmdfont");
- FontHelp = new Font(_entries, "helpfont");
- FontMenu = new Font(_entries, "menufont");
- FontMes = new Font(_entries, "mesfont");
- FontNumeral = new Font(_entries, "numeral");
- }
-
- public IImageRead FontIcon { get; }
- public Font FontCmd { get; }
- public Font FontHelp { get; }
- public Font FontMenu { get; }
- public Font FontMes { get; }
- public Font FontNumeral { get; }
-
- private Image CreateFontIconImage(IEnumerable entries, string name)
- {
- var mtx = RequireFileEntry(entries, $"{name}.mtx");
- var clu = RequireFileEntry(entries, $"{name}.clu");
- var inf = new MemoryStream(RequireFileEntry(entries, $"{name}.inf").Data)
- .Using(stream => FontIconInfo.Read(stream));
-
- return new Image(name, mtx, clu.Data, 256, 64, PixelFormat.Indexed8);
- }
-
- private static Arc.Entry RequireFileEntry(IEnumerable entries, string name)
- {
- var entry = entries.FirstOrDefault(x => x.Name == name);
- if (entry == null)
- throw new FileNotFoundException($"ARC does not contain the required file {name}.", name);
-
- return entry;
- }
-
- private static byte[] Unswizzle(byte[] data, int width)
- {
- var dst = new byte[data.Length];
-
- for (var i = 0; i < data.Length; i += 16)
- {
- var srcIndex = i;
- var dstIndex = srcIndex % 0x10;
- dstIndex += srcIndex / 0x10 % 8 * width;
- dstIndex += srcIndex / 0x80 % (width / 16) * 16;
- dstIndex += srcIndex / (width * 8) * width * 8;
-
- Array.Copy(data, srcIndex, dst, dstIndex, 16);
- }
-
- return dst;
- }
-
- private static void InvertEndianess(byte[] data)
- {
- for (var i = 0; i < data.Length; i++)
- data[i] = (byte)(((data[i] & 15) << 4) | (data[i] >> 4));
- }
-
- public static bool IsValid(Stream stream) => Arc.IsValid(stream);
- public static FontsArc Read(Stream stream) => new FontsArc(stream);
- }
-}
+using OpenKh.Common;
+using OpenKh.Imaging;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+
+namespace OpenKh.Bbs
+{
+ public class FontsArc
+ {
+ private class Image : IImageRead
+ {
+ private readonly byte[] _imageData;
+ private readonly byte[] _clutData;
+
+ internal Image(string name, Arc.Entry mtx, byte[] clut, int width, int maxHeight, PixelFormat pixelFormat)
+ {
+ Name = name;
+ Size = new Size(width, maxHeight);
+ PixelFormat = pixelFormat;
+
+ var bpp = 0;
+ switch (pixelFormat)
+ {
+ case PixelFormat.Indexed4:
+ bpp = 4;
+ break;
+ case PixelFormat.Indexed8:
+ bpp = 8;
+ break;
+ }
+
+ _imageData = new byte[width * maxHeight * bpp / 8];
+ Array.Copy(mtx.Data, _imageData, Math.Min(_imageData.Length, mtx.Data.Length));
+ _imageData = Unswizzle(_imageData, width * bpp / 8);
+ if (pixelFormat == PixelFormat.Indexed4)
+ InvertEndianess(_imageData);
+
+ _clutData = new byte[clut.Length];
+ Array.Copy(clut, _clutData, _clutData.Length);
+ }
+
+ public string Name { get; }
+
+ public Size Size { get; }
+
+ public PixelFormat PixelFormat { get; }
+
+ public byte[] GetClut() => _clutData;
+
+ public byte[] GetData() => _imageData;
+ }
+
+ public class Font
+ {
+ public string Name { get; }
+ public IImageRead Image1 { get; }
+ public IImageRead Image2 { get; }
+ public FontInfo Info { get; }
+ public FontCharacterInfo[] CharactersInfo { get; }
+
+ public Font(IEnumerable entries, string name)
+ {
+ Name = name;
+
+ var mtx = RequireFileEntry(entries, $"{name}.mtx");
+ var clu = RequireFileEntry(entries, $"{name}.clu");
+ Info = new MemoryStream(RequireFileEntry(entries, $"{name}.inf").Data)
+ .Using(stream => FontInfo.Read(stream));
+
+ var clut = new byte[0x40];
+ Array.Copy(clu.Data, 0, clut, 0, clut.Length);
+ Image1 = new Image(name, mtx, clut, Info.ImageWidth, Info.MaxImageHeight, PixelFormat.Indexed4);
+
+ Array.Copy(clu.Data, 0x40, clut, 0, clut.Length);
+ Image2 = new Image(name, mtx, clut, Info.ImageWidth, Info.MaxImageHeight, PixelFormat.Indexed4);
+
+ CharactersInfo = new MemoryStream(RequireFileEntry(entries, $"{name}.cod").Data).Using(stream =>
+ FontCharacterInfo.Read(stream));
+ }
+ }
+
+ private readonly IEnumerable _entries;
+
+ private FontsArc(Stream stream)
+ {
+ _entries = Arc.Read(stream);
+
+ FontIcon = CreateFontIconImage(_entries, "FontIcon");
+ FontCmd = new Font(_entries, "cmdfont");
+ FontHelp = new Font(_entries, "helpfont");
+ FontMenu = new Font(_entries, "menufont");
+ FontMes = new Font(_entries, "mesfont");
+ FontNumeral = new Font(_entries, "numeral");
+ }
+
+ public IImageRead FontIcon { get; }
+ public Font FontCmd { get; }
+ public Font FontHelp { get; }
+ public Font FontMenu { get; }
+ public Font FontMes { get; }
+ public Font FontNumeral { get; }
+
+ private Image CreateFontIconImage(IEnumerable entries, string name)
+ {
+ var mtx = RequireFileEntry(entries, $"{name}.mtx");
+ var clu = RequireFileEntry(entries, $"{name}.clu");
+ var inf = new MemoryStream(RequireFileEntry(entries, $"{name}.inf").Data)
+ .Using(stream => FontIconInfo.Read(stream));
+
+ return new Image(name, mtx, clu.Data, 256, 64, PixelFormat.Indexed8);
+ }
+
+ private static Arc.Entry RequireFileEntry(IEnumerable entries, string name)
+ {
+ var entry = entries.FirstOrDefault(x => x.Name == name);
+ if (entry == null)
+ throw new FileNotFoundException($"ARC does not contain the required file {name}.", name);
+
+ return entry;
+ }
+
+ private static byte[] Unswizzle(byte[] data, int width)
+ {
+ var dst = new byte[data.Length];
+
+ for (var i = 0; i < data.Length; i += 16)
+ {
+ var srcIndex = i;
+ var dstIndex = srcIndex % 0x10;
+ dstIndex += srcIndex / 0x10 % 8 * width;
+ dstIndex += srcIndex / 0x80 % (width / 16) * 16;
+ dstIndex += srcIndex / (width * 8) * width * 8;
+
+ Array.Copy(data, srcIndex, dst, dstIndex, 16);
+ }
+
+ return dst;
+ }
+
+ private static void InvertEndianess(byte[] data)
+ {
+ for (var i = 0; i < data.Length; i++)
+ data[i] = (byte)(((data[i] & 15) << 4) | (data[i] >> 4));
+ }
+
+ public static bool IsValid(Stream stream) => Arc.IsValid(stream);
+ public static FontsArc Read(Stream stream) => new FontsArc(stream);
+ }
+}
diff --git a/OpenKh.Bbs/Itb.cs b/OpenKh.Bbs/Itb.cs
index 71349b3fc..d88dcff80 100644
--- a/OpenKh.Bbs/Itb.cs
+++ b/OpenKh.Bbs/Itb.cs
@@ -1,84 +1,84 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-using Xe.BinaryMapper;
-using OpenKh.Common;
-
-namespace OpenKh.Bbs
-{
- public class Itb
- {
- private const uint MagicCode = 0x425449;
- private const ushort version = 1;
-
- public class Header
- {
- [Data] public uint MagicCode { get; set; }
- [Data] public ushort Version { get; set; }
- [Data] public ushort Padding1 { get; set; }
- [Data] public ushort ItemsTotal { get; set; }
- [Data] public ushort Padding { get; set; }
- [Data] public byte ItemCountDP { get; set; }
- [Data] public byte ItemCountSW { get; set; }
- [Data] public byte ItemCountCD { get; set; }
- [Data] public byte ItemCountSB { get; set; }
- [Data] public byte ItemCountYT { get; set; }
- [Data] public byte ItemCountRG { get; set; }
- [Data] public byte ItemCountJB { get; set; }
- [Data] public byte ItemCountHE { get; set; }
- [Data] public byte ItemCountLS { get; set; }
- [Data] public byte ItemCountDI { get; set; }
- [Data] public byte ItemCountPP { get; set; }
- [Data] public byte ItemCountDC { get; set; }
- [Data] public byte ItemCountKG { get; set; }
- [Data] public byte ItemCountVS { get; set; }
- [Data] public byte ItemCountBD { get; set; }
- [Data] public byte ItemCountWM { get; set; }
- }
-
- public class ITBData
- {
- [Data] public ushort TreasureBoxID { get; set; }
- [Data] public ushort ItemID { get; set; }
- [Data] public byte ItemKind { get; set; }
- [Data] public byte WorldID { get; set; }
- [Data] public byte ReportID { get; set; }
- [Data] public byte Padding3 { get; set; }
- }
-
- public Header header = new Header();
- public List AllITB = new List();
-
- public static Itb Read(Stream stream)
- {
- Itb itb = new Itb();
-
- itb.header = BinaryMapping.ReadObject(stream);
-
- itb.AllITB = new List();
-
- for (int i = 0; i < itb.header.ItemsTotal; i++)
- {
- itb.AllITB.Add(BinaryMapping.ReadObject(stream));
- }
-
- return itb;
- }
-
- public static void Write(Stream stream, Itb itb)
- {
- BinaryMapping.WriteObject(stream, itb.header);
-
- for (int i = 0; i < itb.header.ItemsTotal; i++)
- {
- BinaryMapping.WriteObject(stream, itb.AllITB[i]);
- }
- }
-
- public static bool IsValid(Stream stream) =>
- stream.Length >= 0x1C &&
- stream.SetPosition(0).ReadUInt32() == MagicCode &&
- stream.SetPosition(0).ReadUInt16() == version;
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using Xe.BinaryMapper;
+using OpenKh.Common;
+
+namespace OpenKh.Bbs
+{
+ public class Itb
+ {
+ private const uint MagicCode = 0x425449;
+ private const ushort version = 1;
+
+ public class Header
+ {
+ [Data] public uint MagicCode { get; set; }
+ [Data] public ushort Version { get; set; }
+ [Data] public ushort Padding1 { get; set; }
+ [Data] public ushort ItemsTotal { get; set; }
+ [Data] public ushort Padding { get; set; }
+ [Data] public byte ItemCountDP { get; set; }
+ [Data] public byte ItemCountSW { get; set; }
+ [Data] public byte ItemCountCD { get; set; }
+ [Data] public byte ItemCountSB { get; set; }
+ [Data] public byte ItemCountYT { get; set; }
+ [Data] public byte ItemCountRG { get; set; }
+ [Data] public byte ItemCountJB { get; set; }
+ [Data] public byte ItemCountHE { get; set; }
+ [Data] public byte ItemCountLS { get; set; }
+ [Data] public byte ItemCountDI { get; set; }
+ [Data] public byte ItemCountPP { get; set; }
+ [Data] public byte ItemCountDC { get; set; }
+ [Data] public byte ItemCountKG { get; set; }
+ [Data] public byte ItemCountVS { get; set; }
+ [Data] public byte ItemCountBD { get; set; }
+ [Data] public byte ItemCountWM { get; set; }
+ }
+
+ public class ITBData
+ {
+ [Data] public ushort TreasureBoxID { get; set; }
+ [Data] public ushort ItemID { get; set; }
+ [Data] public byte ItemKind { get; set; }
+ [Data] public byte WorldID { get; set; }
+ [Data] public byte ReportID { get; set; }
+ [Data] public byte Padding3 { get; set; }
+ }
+
+ public Header header = new Header();
+ public List AllITB = new List();
+
+ public static Itb Read(Stream stream)
+ {
+ Itb itb = new Itb();
+
+ itb.header = BinaryMapping.ReadObject(stream);
+
+ itb.AllITB = new List();
+
+ for (int i = 0; i < itb.header.ItemsTotal; i++)
+ {
+ itb.AllITB.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ return itb;
+ }
+
+ public static void Write(Stream stream, Itb itb)
+ {
+ BinaryMapping.WriteObject(stream, itb.header);
+
+ for (int i = 0; i < itb.header.ItemsTotal; i++)
+ {
+ BinaryMapping.WriteObject(stream, itb.AllITB[i]);
+ }
+ }
+
+ public static bool IsValid(Stream stream) =>
+ stream.Length >= 0x1C &&
+ stream.SetPosition(0).ReadUInt32() == MagicCode &&
+ stream.SetPosition(0).ReadUInt16() == version;
+ }
+}
diff --git a/OpenKh.Bbs/Itc.cs b/OpenKh.Bbs/Itc.cs
index d9a75b3a7..aad89eed3 100644
--- a/OpenKh.Bbs/Itc.cs
+++ b/OpenKh.Bbs/Itc.cs
@@ -1,84 +1,84 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-using Xe.BinaryMapper;
-using OpenKh.Common;
-
-namespace OpenKh.Bbs
-{
- public class Itc
- {
- private const uint MagicCode = 0x435449;
- private const ushort version = 1;
-
- public class Header
- {
- [Data] public uint MagicCode { get; set; }
- [Data] public ushort Version { get; set; }
- [Data] public ushort Padding1 { get; set; }
- [Data] public ushort ItemsTotal { get; set; }
- [Data] public ushort Padding { get; set; }
- [Data] public byte ItemCountDP { get; set; }
- [Data] public byte ItemCountSW { get; set; }
- [Data] public byte ItemCountCD { get; set; }
- [Data] public byte ItemCountSB { get; set; }
- [Data] public byte ItemCountYT { get; set; }
- [Data] public byte ItemCountRG { get; set; }
- [Data] public byte ItemCountJB { get; set; }
- [Data] public byte ItemCountHE { get; set; }
- [Data] public byte ItemCountLS { get; set; }
- [Data] public byte ItemCountDI { get; set; }
- [Data] public byte ItemCountPP { get; set; }
- [Data] public byte ItemCountDC { get; set; }
- [Data] public byte ItemCountKG { get; set; }
- [Data] public byte ItemCountVS { get; set; }
- [Data] public byte ItemCountBD { get; set; }
- [Data] public byte ItemCountWM { get; set; }
- }
-
- public class ITCData
- {
- [Data] public ushort CollectionID { get; set; }
- [Data] public ushort ItemID { get; set; }
- [Data] public byte WorldID { get; set; }
- [Data] public byte Padding1 { get; set; }
- [Data] public byte Padding2 { get; set; }
- [Data] public byte Padding3 { get; set; }
- }
-
- public Header header = new Header();
- public List AllITC = new List();
-
- public static Itc Read(Stream stream)
- {
- Itc itc = new Itc();
-
- itc.header = BinaryMapping.ReadObject(stream);
-
- itc.AllITC = new List();
-
- for(int i = 0; i < itc.header.ItemsTotal; i++)
- {
- itc.AllITC.Add(BinaryMapping.ReadObject(stream));
- }
-
- return itc;
- }
-
- public static void Write(Stream stream, Itc itc)
- {
- BinaryMapping.WriteObject(stream, itc.header);
-
- for (int i = 0; i < itc.header.ItemsTotal; i++)
- {
- BinaryMapping.WriteObject(stream, itc.AllITC[i]);
- }
- }
-
- public static bool IsValid(Stream stream) =>
- stream.Length >= 0x1C &&
- stream.SetPosition(0).ReadUInt32() == MagicCode &&
- stream.SetPosition(0).ReadUInt16() == version;
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using Xe.BinaryMapper;
+using OpenKh.Common;
+
+namespace OpenKh.Bbs
+{
+ public class Itc
+ {
+ private const uint MagicCode = 0x435449;
+ private const ushort version = 1;
+
+ public class Header
+ {
+ [Data] public uint MagicCode { get; set; }
+ [Data] public ushort Version { get; set; }
+ [Data] public ushort Padding1 { get; set; }
+ [Data] public ushort ItemsTotal { get; set; }
+ [Data] public ushort Padding { get; set; }
+ [Data] public byte ItemCountDP { get; set; }
+ [Data] public byte ItemCountSW { get; set; }
+ [Data] public byte ItemCountCD { get; set; }
+ [Data] public byte ItemCountSB { get; set; }
+ [Data] public byte ItemCountYT { get; set; }
+ [Data] public byte ItemCountRG { get; set; }
+ [Data] public byte ItemCountJB { get; set; }
+ [Data] public byte ItemCountHE { get; set; }
+ [Data] public byte ItemCountLS { get; set; }
+ [Data] public byte ItemCountDI { get; set; }
+ [Data] public byte ItemCountPP { get; set; }
+ [Data] public byte ItemCountDC { get; set; }
+ [Data] public byte ItemCountKG { get; set; }
+ [Data] public byte ItemCountVS { get; set; }
+ [Data] public byte ItemCountBD { get; set; }
+ [Data] public byte ItemCountWM { get; set; }
+ }
+
+ public class ITCData
+ {
+ [Data] public ushort CollectionID { get; set; }
+ [Data] public ushort ItemID { get; set; }
+ [Data] public byte WorldID { get; set; }
+ [Data] public byte Padding1 { get; set; }
+ [Data] public byte Padding2 { get; set; }
+ [Data] public byte Padding3 { get; set; }
+ }
+
+ public Header header = new Header();
+ public List AllITC = new List();
+
+ public static Itc Read(Stream stream)
+ {
+ Itc itc = new Itc();
+
+ itc.header = BinaryMapping.ReadObject(stream);
+
+ itc.AllITC = new List();
+
+ for (int i = 0; i < itc.header.ItemsTotal; i++)
+ {
+ itc.AllITC.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ return itc;
+ }
+
+ public static void Write(Stream stream, Itc itc)
+ {
+ BinaryMapping.WriteObject(stream, itc.header);
+
+ for (int i = 0; i < itc.header.ItemsTotal; i++)
+ {
+ BinaryMapping.WriteObject(stream, itc.AllITC[i]);
+ }
+ }
+
+ public static bool IsValid(Stream stream) =>
+ stream.Length >= 0x1C &&
+ stream.SetPosition(0).ReadUInt32() == MagicCode &&
+ stream.SetPosition(0).ReadUInt16() == version;
+ }
+}
diff --git a/OpenKh.Bbs/Ite.cs b/OpenKh.Bbs/Ite.cs
index 902a079c9..016f5789d 100644
--- a/OpenKh.Bbs/Ite.cs
+++ b/OpenKh.Bbs/Ite.cs
@@ -1,121 +1,121 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.IO;
-using Xe.BinaryMapper;
-using OpenKh.Common;
-
-namespace OpenKh.Bbs
-{
- public class Ite
- {
- private const uint MagicCode = 0x455449;
- private const ushort version = 1;
-
- public class Header
- {
- [Data] public uint MagicCode { get; set; }
- [Data] public ushort Version { get; set; }
- [Data] public ushort Padding1 { get; set; }
- [Data] public ushort WeaponDataCount { get; set; }
- [Data] public ushort FlavorDataCount { get; set; }
- [Data] public ushort KeyItemDataCount { get; set; }
- [Data] public ushort KeyItemHideDataCount { get; set; }
- [Data] public ushort SynthesisDataCount { get; set; }
- [Data] public ushort Padding { get; set; }
- }
-
- public class ITEData
- {
- [Data] public ushort ItemID { get; set; }
- [Data] public byte Padding1 { get; set; }
- [Data] public byte Padding2 { get; set; }
- }
-
- public Header header;
- public List WeaponList = new List();
- public List FlavorList = new List();
- public List KeyItemList = new List();
- public List KeyItemHideList = new List();
- public List SynthesisList = new List();
-
- public static Ite Read(Stream stream)
- {
- Ite ite = new Ite();
-
- ite.header = BinaryMapping.ReadObject(stream);
-
- // Weapon.
- for(int i = 0; i < ite.header.WeaponDataCount; i++)
- {
- ite.WeaponList.Add(BinaryMapping.ReadObject(stream));
- }
-
- // Flavor.
- for (int i = 0; i < ite.header.FlavorDataCount; i++)
- {
- ite.FlavorList.Add(BinaryMapping.ReadObject(stream));
- }
-
- // Key Item.
- for (int i = 0; i < ite.header.KeyItemDataCount; i++)
- {
- ite.KeyItemList.Add(BinaryMapping.ReadObject(stream));
- }
-
- // Key Item Hide.
- for (int i = 0; i < ite.header.KeyItemHideDataCount; i++)
- {
- ite.KeyItemHideList.Add(BinaryMapping.ReadObject(stream));
- }
-
- // Synthesis.
- for (int i = 0; i < ite.header.SynthesisDataCount; i++)
- {
- ite.SynthesisList.Add(BinaryMapping.ReadObject(stream));
- }
-
- return ite;
- }
-
- public static void Write(Stream stream, Ite ite)
- {
- BinaryMapping.WriteObject(stream, ite.header);
-
- // Weapon.
- for (int i = 0; i < ite.header.WeaponDataCount; i++)
- {
- BinaryMapping.WriteObject(stream, ite.WeaponList[i]);
- }
-
- // Flavor.
- for (int i = 0; i < ite.header.FlavorDataCount; i++)
- {
- BinaryMapping.WriteObject(stream, ite.FlavorList[i]);
- }
-
- // Key Item.
- for (int i = 0; i < ite.header.KeyItemDataCount; i++)
- {
- BinaryMapping.WriteObject(stream, ite.KeyItemList[i]);
- }
-
- // Key Item Hide.
- for (int i = 0; i < ite.header.KeyItemHideDataCount; i++)
- {
- BinaryMapping.WriteObject(stream, ite.KeyItemHideList[i]);
- }
-
- // Synthesis.
- for (int i = 0; i < ite.header.SynthesisDataCount; i++)
- {
- BinaryMapping.WriteObject(stream, ite.SynthesisList[i]);
- }
- }
-
- public static bool IsValid(Stream stream) =>
- stream.Length >= 0x1C &&
- stream.SetPosition(0).ReadUInt32() == MagicCode &&
- stream.SetPosition(0).ReadUInt16() == version;
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using Xe.BinaryMapper;
+using OpenKh.Common;
+
+namespace OpenKh.Bbs
+{
+ public class Ite
+ {
+ private const uint MagicCode = 0x455449;
+ private const ushort version = 1;
+
+ public class Header
+ {
+ [Data] public uint MagicCode { get; set; }
+ [Data] public ushort Version { get; set; }
+ [Data] public ushort Padding1 { get; set; }
+ [Data] public ushort WeaponDataCount { get; set; }
+ [Data] public ushort FlavorDataCount { get; set; }
+ [Data] public ushort KeyItemDataCount { get; set; }
+ [Data] public ushort KeyItemHideDataCount { get; set; }
+ [Data] public ushort SynthesisDataCount { get; set; }
+ [Data] public ushort Padding { get; set; }
+ }
+
+ public class ITEData
+ {
+ [Data] public ushort ItemID { get; set; }
+ [Data] public byte Padding1 { get; set; }
+ [Data] public byte Padding2 { get; set; }
+ }
+
+ public Header header;
+ public List WeaponList = new List();
+ public List FlavorList = new List();
+ public List KeyItemList = new List();
+ public List KeyItemHideList = new List();
+ public List SynthesisList = new List();
+
+ public static Ite Read(Stream stream)
+ {
+ Ite ite = new Ite();
+
+ ite.header = BinaryMapping.ReadObject(stream);
+
+ // Weapon.
+ for (int i = 0; i < ite.header.WeaponDataCount; i++)
+ {
+ ite.WeaponList.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ // Flavor.
+ for (int i = 0; i < ite.header.FlavorDataCount; i++)
+ {
+ ite.FlavorList.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ // Key Item.
+ for (int i = 0; i < ite.header.KeyItemDataCount; i++)
+ {
+ ite.KeyItemList.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ // Key Item Hide.
+ for (int i = 0; i < ite.header.KeyItemHideDataCount; i++)
+ {
+ ite.KeyItemHideList.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ // Synthesis.
+ for (int i = 0; i < ite.header.SynthesisDataCount; i++)
+ {
+ ite.SynthesisList.Add(BinaryMapping.ReadObject(stream));
+ }
+
+ return ite;
+ }
+
+ public static void Write(Stream stream, Ite ite)
+ {
+ BinaryMapping.WriteObject(stream, ite.header);
+
+ // Weapon.
+ for (int i = 0; i < ite.header.WeaponDataCount; i++)
+ {
+ BinaryMapping.WriteObject(stream, ite.WeaponList[i]);
+ }
+
+ // Flavor.
+ for (int i = 0; i < ite.header.FlavorDataCount; i++)
+ {
+ BinaryMapping.WriteObject(stream, ite.FlavorList[i]);
+ }
+
+ // Key Item.
+ for (int i = 0; i < ite.header.KeyItemDataCount; i++)
+ {
+ BinaryMapping.WriteObject(stream, ite.KeyItemList[i]);
+ }
+
+ // Key Item Hide.
+ for (int i = 0; i < ite.header.KeyItemHideDataCount; i++)
+ {
+ BinaryMapping.WriteObject(stream, ite.KeyItemHideList[i]);
+ }
+
+ // Synthesis.
+ for (int i = 0; i < ite.header.SynthesisDataCount; i++)
+ {
+ BinaryMapping.WriteObject(stream, ite.SynthesisList[i]);
+ }
+ }
+
+ public static bool IsValid(Stream stream) =>
+ stream.Length >= 0x1C &&
+ stream.SetPosition(0).ReadUInt32() == MagicCode &&
+ stream.SetPosition(0).ReadUInt16() == version;
+ }
+}
diff --git a/OpenKh.Bbs/Messages/CtdEncoders.cs b/OpenKh.Bbs/Messages/CtdEncoders.cs
index cf007e7f9..1ab91f54b 100644
--- a/OpenKh.Bbs/Messages/CtdEncoders.cs
+++ b/OpenKh.Bbs/Messages/CtdEncoders.cs
@@ -1,13 +1,13 @@
-using OpenKh.Bbs.Messages.Internals;
-
-namespace OpenKh.Bbs.Messages
-{
- public static class CtdEncoders
- {
- public static ICtdMessageEncoder International { get; } =
- new InternationalCtdEncoder();
-
- public static ICtdMessageEncoder Japanese { get; } =
- new InternationalCtdEncoder();
- }
-}
+using OpenKh.Bbs.Messages.Internals;
+
+namespace OpenKh.Bbs.Messages
+{
+ public static class CtdEncoders
+ {
+ public static ICtdMessageEncoder International { get; } =
+ new InternationalCtdEncoder();
+
+ public static ICtdMessageEncoder Japanese { get; } =
+ new InternationalCtdEncoder();
+ }
+}
diff --git a/OpenKh.Bbs/Messages/ICtdMessageDecode.cs b/OpenKh.Bbs/Messages/ICtdMessageDecode.cs
index 8c8fe708d..091e12418 100644
--- a/OpenKh.Bbs/Messages/ICtdMessageDecode.cs
+++ b/OpenKh.Bbs/Messages/ICtdMessageDecode.cs
@@ -1,7 +1,7 @@
-namespace OpenKh.Bbs.Messages
-{
- public interface ICtdMessageDecode
- {
- string ToText(byte[] data);
- }
-}
+namespace OpenKh.Bbs.Messages
+{
+ public interface ICtdMessageDecode
+ {
+ string ToText(byte[] data);
+ }
+}
diff --git a/OpenKh.Bbs/Messages/ICtdMessageEncode.cs b/OpenKh.Bbs/Messages/ICtdMessageEncode.cs
index 68fe6527e..9486f08bf 100644
--- a/OpenKh.Bbs/Messages/ICtdMessageEncode.cs
+++ b/OpenKh.Bbs/Messages/ICtdMessageEncode.cs
@@ -1,7 +1,7 @@
-namespace OpenKh.Bbs.Messages
-{
- public interface ICtdMessageEncode
- {
- byte[] FromText(string text);
- }
-}
+namespace OpenKh.Bbs.Messages
+{
+ public interface ICtdMessageEncode
+ {
+ byte[] FromText(string text);
+ }
+}
diff --git a/OpenKh.Bbs/Messages/ICtdMessageEncoder.cs b/OpenKh.Bbs/Messages/ICtdMessageEncoder.cs
index fa973bee3..6dcdbf48a 100644
--- a/OpenKh.Bbs/Messages/ICtdMessageEncoder.cs
+++ b/OpenKh.Bbs/Messages/ICtdMessageEncoder.cs
@@ -1,11 +1,11 @@
-using System.Collections.Generic;
-
-namespace OpenKh.Bbs.Messages
-{
- public interface ICtdMessageEncoder : ICtdMessageDecode, ICtdMessageEncode
- {
- IEnumerable ToUcs(IEnumerable data);
-
- IEnumerable FromUcs(IEnumerable ucs);
- }
-}
+using System.Collections.Generic;
+
+namespace OpenKh.Bbs.Messages
+{
+ public interface ICtdMessageEncoder : ICtdMessageDecode, ICtdMessageEncode
+ {
+ IEnumerable ToUcs(IEnumerable data);
+
+ IEnumerable