diff --git a/Release/AcbEditor.exe b/Release/AcbEditor.exe index 8fb9001..781643a 100644 Binary files a/Release/AcbEditor.exe and b/Release/AcbEditor.exe differ diff --git a/Release/CsbBuilder.exe b/Release/CsbBuilder.exe index 9f6d189..22cca5d 100644 Binary files a/Release/CsbBuilder.exe and b/Release/CsbBuilder.exe differ diff --git a/Release/CsbEditor.exe b/Release/CsbEditor.exe index 52dce15..ec5ce80 100644 Binary files a/Release/CsbEditor.exe and b/Release/CsbEditor.exe differ diff --git a/Release/SonicAudioLib.dll b/Release/SonicAudioLib.dll index d9985a0..5b9d9f7 100644 Binary files a/Release/SonicAudioLib.dll and b/Release/SonicAudioLib.dll differ diff --git a/Source/CsbEditor/Program.cs b/Source/CsbEditor/Program.cs index 677d6df..8fa4157 100644 --- a/Source/CsbEditor/Program.cs +++ b/Source/CsbEditor/Program.cs @@ -75,18 +75,21 @@ namespace CsbEditor { CriCpkEntry cpkEntry = cpkArchive.GetByPath(sdlName); - using (Stream cpkSource = File.OpenRead(cpkPath)) - using (Stream aaxSource = cpkEntry.Open(cpkSource)) + if (cpkEntry != null) { - aaxArchive.Read(aaxSource); - - foreach (CriAaxEntry entry in aaxArchive) + using (Stream cpkSource = File.OpenRead(cpkPath)) + using (Stream aaxSource = cpkEntry.Open(cpkSource)) { - using (Stream destination = File.Create(Path.Combine(destinationPath.FullName, - entry.Flag == CriAaxEntryFlag.Intro ? "Intro.adx" : "Loop.adx"))) - using (Stream entrySource = entry.Open(aaxSource)) + aaxArchive.Read(aaxSource); + + foreach (CriAaxEntry entry in aaxArchive) { - entrySource.CopyTo(destination); + using (Stream destination = File.Create(Path.Combine(destinationPath.FullName, + entry.Flag == CriAaxEntryFlag.Intro ? "Intro.adx" : "Loop.adx"))) + using (Stream entrySource = entry.Open(aaxSource)) + { + entrySource.CopyTo(destination); + } } } } diff --git a/Source/SonicAudioLib/Archive/CriCpkArchive.cs b/Source/SonicAudioLib/Archive/CriCpkArchive.cs index b4298a4..6d5616d 100644 --- a/Source/SonicAudioLib/Archive/CriCpkArchive.cs +++ b/Source/SonicAudioLib/Archive/CriCpkArchive.cs @@ -564,7 +564,20 @@ namespace SonicAudioLib.Archive public CriCpkEntry GetByPath(string path) { - return entries.FirstOrDefault(entry => ((entry.DirectoryName + "/" + entry.Name) == path)); + string correctedPath = path.Replace('\\', '/'); + + return entries.FirstOrDefault(entry => + { + string search = string.Empty; + if (!string.IsNullOrEmpty(entry.DirectoryName)) + { + search += $"{entry.DirectoryName.Replace('\\', '/')}/"; + } + + search += entry.Name; + + return search == correctedPath; + }); } private DateTime DateTimeFromCpkDateTime(ulong dateTime) diff --git a/Source/SonicAudioLib/CriMw/CriTable.Internal.cs b/Source/SonicAudioLib/CriMw/CriTable.Internal.cs index 3121250..1239976 100644 --- a/Source/SonicAudioLib/CriMw/CriTable.Internal.cs +++ b/Source/SonicAudioLib/CriMw/CriTable.Internal.cs @@ -4,10 +4,13 @@ namespace SonicAudioLib.CriMw { struct CriTableHeader { - public static readonly string Signature = "@UTF"; + public const string Signature = "@UTF"; + public const byte EncodingTypeShiftJis = 0; + public const byte EncodingTypeUtf8 = 1; + public uint Length { get; set; } - public bool FirstBoolean { get; set; } - public bool SecondBoolean { get; set; } + public byte UnknownByte { get; set; } + public byte EncodingType { get; set; } public ushort RowsPosition { get; set; } public uint StringPoolPosition { get; set; } public uint DataPoolPosition { get; set; } @@ -18,7 +21,7 @@ namespace SonicAudioLib.CriMw } [Flags] - enum CriFieldFlag + enum CriFieldFlag : byte { Name = 16, DefaultValue = 32, diff --git a/Source/SonicAudioLib/CriMw/CriTableReader.cs b/Source/SonicAudioLib/CriMw/CriTableReader.cs index 40e5e5c..b95e7f5 100644 --- a/Source/SonicAudioLib/CriMw/CriTableReader.cs +++ b/Source/SonicAudioLib/CriMw/CriTableReader.cs @@ -12,7 +12,8 @@ namespace SonicAudioLib.CriMw private List fields; private Stream source; private CriTableHeader header; - private int rowIndex = -1; + private Encoding encoding; + private long rowIndex = -1; private uint headerPosition; private bool leaveOpen; @@ -56,7 +57,7 @@ namespace SonicAudioLib.CriMw } } - public int CurrentRow + public long CurrentRow { get { @@ -72,6 +73,14 @@ namespace SonicAudioLib.CriMw } } + public Encoding EncodingType + { + get + { + return encoding; + } + } + private void ReadTable() { headerPosition = (uint)source.Position; @@ -102,8 +111,29 @@ namespace SonicAudioLib.CriMw } header.Length = ReadUInt32() + 0x8; - header.FirstBoolean = ReadBoolean(); - header.SecondBoolean = ReadBoolean(); + header.UnknownByte = ReadByte(); + header.EncodingType = ReadByte(); + + if (header.UnknownByte != 0) + { + throw new Exception($"Invalid byte ({header.UnknownByte}. Please report the error with the file."); + } + + // This actually might be a boolean telling the reader that it's using UTF-8 encoding, but idk + switch (header.EncodingType) + { + case CriTableHeader.EncodingTypeShiftJis: + encoding = Encoding.GetEncoding("shift-jis"); + break; + + case CriTableHeader.EncodingTypeUtf8: + encoding = Encoding.UTF8; + break; + + default: + throw new Exception($"Unknown encoding type ({header.EncodingType}). Please report the error with the file."); + } + header.RowsPosition = (ushort)(ReadUInt16() + 0x8); header.StringPoolPosition = ReadUInt32() + 0x8; header.DataPoolPosition = ReadUInt32() + 0x8; @@ -112,11 +142,6 @@ namespace SonicAudioLib.CriMw header.RowLength = ReadUInt16(); header.NumberOfRows = ReadUInt32(); - if (header.FirstBoolean) - { - throw new Exception($"Invalid boolean ({header.FirstBoolean}. Please report the error with the file."); - } - for (ushort i = 0; i < header.NumberOfFields; i++) { CriTableField field = new CriTableField(); @@ -271,7 +296,7 @@ namespace SonicAudioLib.CriMw return true; } - public bool MoveToRow(int rowIndex) + public bool MoveToRow(long rowIndex) { if (rowIndex >= header.NumberOfRows) { @@ -617,7 +642,7 @@ namespace SonicAudioLib.CriMw long previousPosition = source.Position; source.Position = headerPosition + header.StringPoolPosition + stringPosition; - string strResult = EndianStream.ReadCString(source, Encoding.GetEncoding("shift-jis")); + string strResult = EndianStream.ReadCString(source, encoding); source.Position = previousPosition; if (strResult == "" || @@ -675,12 +700,12 @@ namespace SonicAudioLib.CriMw ReadData(out vldPosition, out vldLength); - // SecondBoolean being true, check if utf table + // Some ACB files have the length info set to zero for UTF table fields, so find the correct length if (vldPosition > 0 && vldLength == 0) { source.Position = headerPosition + header.DataPoolPosition + vldPosition; - if (Encoding.ASCII.GetString(ReadBytes(4)) == "@UTF") + if (EndianStream.ReadCString(source, 4) == "@UTF") { vldLength = ReadUInt32() + 8; } diff --git a/Source/SonicAudioLib/CriMw/CriTableWriter.cs b/Source/SonicAudioLib/CriMw/CriTableWriter.cs index 94c0755..5d76c09 100644 --- a/Source/SonicAudioLib/CriMw/CriTableWriter.cs +++ b/Source/SonicAudioLib/CriMw/CriTableWriter.cs @@ -71,8 +71,8 @@ namespace SonicAudioLib.CriMw EndianStream.WriteCString(destination, CriTableHeader.Signature, 4); WriteUInt32(uint.MinValue); - WriteBoolean(false); - WriteBoolean(false); + WriteByte(byte.MinValue); + WriteByte(byte.MinValue); WriteUInt16(ushort.MinValue); WriteUInt32(uint.MinValue); WriteUInt32(uint.MinValue); @@ -112,13 +112,20 @@ namespace SonicAudioLib.CriMw header.Length = (uint)destination.Position - headerPosition; - header.FirstBoolean = false; - header.SecondBoolean = false; + if (settings.EncodingType == Encoding.GetEncoding("shift-jis")) + { + header.EncodingType = CriTableHeader.EncodingTypeShiftJis; + } + + else if (settings.EncodingType == Encoding.UTF8) + { + header.EncodingType = CriTableHeader.EncodingTypeUtf8; + } destination.Position = headerPosition + 4; WriteUInt32(header.Length - 8); - WriteBoolean(header.FirstBoolean); - WriteBoolean(header.SecondBoolean); + WriteByte(header.UnknownByte); + WriteByte(header.EncodingType); WriteUInt16((ushort)(header.RowsPosition - 8)); WriteUInt32(header.StringPoolPosition - 8); WriteUInt32(header.DataPoolPosition - 8); @@ -670,6 +677,11 @@ namespace SonicAudioLib.CriMw set { + if (value != Encoding.UTF8 || value != Encoding.GetEncoding("shift-jis")) + { + return; + } + encodingType = value; } } diff --git a/Source/SonicAudioLib/IO/EndianStream.cs b/Source/SonicAudioLib/IO/EndianStream.cs index c2ecc48..39a4981 100644 --- a/Source/SonicAudioLib/IO/EndianStream.cs +++ b/Source/SonicAudioLib/IO/EndianStream.cs @@ -43,6 +43,16 @@ namespace SonicAudioLib.IO return buffer; } + public static byte[] ReadBytesAt(Stream source, int length, long position) + { + long oldPosition = source.Position; + source.Position = position; + FillBuffer(source, length); + source.Position = oldPosition; + + return buffer; + } + public static void WriteBytes(Stream destination, byte[] value) { destination.Write(value, 0, value.Length);