Remove StreamDataReader/Writer and use OMI.EndianAwareBinaryreader/Writer

This commit is contained in:
miku-666
2023-04-06 14:15:34 +02:00
parent 3aa5a3818a
commit a5a408a30e
10 changed files with 206 additions and 332 deletions
+50 -41
View File
@@ -1,57 +1,66 @@
using System.IO;
using System.Text;
using OMI;
using OMI.Workers;
using PckStudio.Classes.FileTypes;
namespace PckStudio.Classes.IO.CSMB
{
internal class CSMBFileReader : StreamDataReader<CSMBFile>
internal class CSMBFileReader : IDataFormatReader<CSMBFile>, IDataFormatReader
{
public static CSMBFile Read(Stream stream)
{
return new CSMBFileReader().ReadFromStream(stream);
}
private CSMBFileReader() : base(false)
private CSMBFileReader()
{ }
protected override CSMBFile ReadFromStream(Stream stream)
public CSMBFile FromFile(string filename)
{
CSMBFile BinFile = new CSMBFile();
ReadInt(stream);
int NumOfParts = ReadInt(stream);
for(int i = 0; i < NumOfParts; i++)
{
CSMBPart part = new CSMBPart();
part.Name = ReadString(stream);
part.Parent = (CSMBParentPart)ReadInt(stream);
part.posX = ReadFloat(stream);
part.posY = ReadFloat(stream);
part.posZ = ReadFloat(stream);
part.sizeX = ReadFloat(stream);
part.sizeY = ReadFloat(stream);
part.sizeZ = ReadFloat(stream);
part.uvX = ReadInt(stream);
part.uvY = ReadInt(stream);
part.MirrorTexture = ReadBool(stream);
part.HideWArmour = ReadBool(stream);
part.Inflation = ReadFloat(stream);
BinFile.Parts.Add(part);
}
int NumOfOffsets = ReadInt(stream);
for (int i = 0; i < NumOfOffsets; i++)
{
CSMBOffset offset = new CSMBOffset();
offset.offsetPart = (CSMBOffsetPart)ReadInt(stream);
offset.VerticalOffset = ReadFloat(stream);
BinFile.Offsets.Add(offset);
}
return BinFile;
throw new System.NotImplementedException();
}
private string ReadString(Stream stream)
public CSMBFile FromStream(Stream stream)
{
short strlen = ReadShort(stream);
return ReadString(stream, strlen, Encoding.ASCII);
CSMBFile csmbFile = new CSMBFile();
using (var reader = new EndiannessAwareBinaryReader(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian))
{
reader.ReadInt32();
int numOfParts = reader.ReadInt32();
for (int i = 0; i < numOfParts; i++)
{
CSMBPart part = new CSMBPart();
part.Name = ReadString(reader);
part.Parent = (CSMBParentPart)reader.ReadInt32();
part.posX = reader.ReadSingle();
part.posY = reader.ReadSingle();
part.posZ = reader.ReadSingle();
part.sizeX = reader.ReadSingle();
part.sizeY = reader.ReadSingle();
part.sizeZ = reader.ReadSingle();
part.uvX = reader.ReadInt32();
part.uvY = reader.ReadInt32();
part.MirrorTexture = reader.ReadBoolean();
part.HideWArmour = reader.ReadBoolean();
part.Inflation = reader.ReadSingle();
csmbFile.Parts.Add(part);
}
int numOfOffsets = reader.ReadInt32();
for (int i = 0; i < numOfOffsets; i++)
{
CSMBOffset offset = new CSMBOffset();
offset.offsetPart = (CSMBOffsetPart)reader.ReadInt32();
offset.VerticalOffset = reader.ReadSingle();
csmbFile.Offsets.Add(offset);
}
}
return csmbFile;
}
private string ReadString(EndiannessAwareBinaryReader reader)
{
ushort strlen = reader.ReadUInt16();
return reader.ReadString(strlen);
}
object IDataFormatReader.FromStream(Stream stream) => FromStream(stream);
object IDataFormatReader.FromFile(string filename) => FromFile(filename);
}
}
+36 -32
View File
@@ -1,54 +1,58 @@
using System.IO;
using System.Text;
using PckStudio.Classes.FileTypes;
using OMI.Workers;
using OMI;
namespace PckStudio.Classes.IO.CSMB
{
internal class CSMBFileWriter : StreamDataWriter
internal class CSMBFileWriter : IDataFormatWriter
{
CSMBFile _CSMB;
public static void Write(Stream stream, CSMBFile file)
{
new CSMBFileWriter(file).WriteToStream(stream);
}
public CSMBFileWriter(CSMBFile csmb) : base(false)
public CSMBFileWriter(CSMBFile csmb)
{
_CSMB = csmb;
}
protected override void WriteToStream(Stream stream)
public void WriteToFile(string filename)
{
WriteInt(stream, 0);
WriteInt(stream, _CSMB.Parts.Count);
foreach(CSMBPart part in _CSMB.Parts)
using(var fs = File.OpenWrite(filename))
{
WriteString(stream, part.Name);
WriteInt(stream, (int)part.Parent);
WriteFloat(stream, part.posX);
WriteFloat(stream, part.posY);
WriteFloat(stream, part.posZ);
WriteFloat(stream, part.sizeX);
WriteFloat(stream, part.sizeY);
WriteFloat(stream, part.sizeZ);
WriteInt(stream, part.uvX);
WriteInt(stream, part.uvY);
WriteBool(stream, part.MirrorTexture);
WriteBool(stream, part.HideWArmour);
WriteFloat(stream, part.Inflation);
}
WriteInt(stream, _CSMB.Offsets.Count);
foreach (CSMBOffset offset in _CSMB.Offsets)
{
WriteInt(stream, (int)offset.offsetPart);
WriteFloat(stream, offset.VerticalOffset);
WriteToStream(fs);
}
}
private void WriteString(Stream stream, string s)
public void WriteToStream(Stream stream)
{
WriteShort(stream, (short)s.Length);
WriteString(stream, s, Encoding.ASCII);
using (var writer = new EndiannessAwareBinaryWriter(stream, Encoding.ASCII, leaveOpen: true, Endianness.LittleEndian))
{
writer.Write(0);
writer.Write(_CSMB.Parts.Count);
foreach (CSMBPart part in _CSMB.Parts)
{
writer.Write((short)part.Name.Length);
writer.WriteString(part.Name);
writer.Write((int)part.Parent);
writer.Write(part.posX);
writer.Write(part.posY);
writer.Write(part.posZ);
writer.Write(part.sizeX);
writer.Write(part.sizeY);
writer.Write(part.sizeZ);
writer.Write(part.uvX);
writer.Write(part.uvY);
writer.Write(part.MirrorTexture);
writer.Write(part.HideWArmour);
writer.Write(part.Inflation);
}
writer.Write(_CSMB.Offsets.Count);
foreach (CSMBOffset offset in _CSMB.Offsets)
{
writer.Write((int)offset.offsetPart);
writer.Write(offset.VerticalOffset);
}
}
}
}
}
+58 -33
View File
@@ -1,6 +1,9 @@
using PckStudio.Classes.FileTypes;
using OMI;
using OMI.Workers;
using PckStudio.Classes.FileTypes;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
@@ -14,55 +17,73 @@ namespace PckStudio.Classes.IO.PCK
{ }
}
internal class PCKAudioFileReader : StreamDataReader<PCKAudioFile>
internal class PCKAudioFileReader : IDataFormatReader<PCKAudioFile>, IDataFormatReader
{
private PCKAudioFile _file;
private Endianness _endianness;
private List<string> LUT = new List<string>();
private List<PCKAudioFile.AudioCategory.EAudioType> _OriginalAudioTypeOrder = new List<PCKAudioFile.AudioCategory.EAudioType>();
public static PCKAudioFile Read(Stream stream, bool isLittleEndian)
public PCKAudioFileReader(Endianness endianness)
{
return new PCKAudioFileReader(isLittleEndian).ReadFromStream(stream);
_endianness = endianness;
}
private PCKAudioFileReader(bool isLittleEndian) : base(isLittleEndian)
public PCKAudioFile FromFile(string filename)
{
if(File.Exists(filename))
{
PCKAudioFile file;
using(var fs = File.OpenRead(filename))
{
file = FromStream(fs);
}
return file;
}
throw new FileNotFoundException(filename);
}
protected override PCKAudioFile ReadFromStream(Stream stream)
public PCKAudioFile FromStream(Stream stream)
{
int pck_type = ReadInt(stream);
if (pck_type > 0xf00000) // 03 00 00 00 == true
throw new OverflowException(nameof(pck_type));
if (pck_type > 1)
throw new InvalidAudioPckException(nameof(pck_type));
_file = new PCKAudioFile();
ReadLookUpTable(stream);
ReadCategories(stream);
ReadCategorySongs(stream);
using (var reader = new EndiannessAwareBinaryReader(stream,
_endianness == Endianness.BigEndian
? Encoding.BigEndianUnicode
: Encoding.Unicode,
leaveOpen: true, _endianness))
{
int pck_type = reader.ReadInt32();
if (pck_type > 0xf00000) // 03 00 00 00 == true
throw new OverflowException(nameof(pck_type));
if (pck_type > 1)
throw new InvalidAudioPckException(nameof(pck_type));
_file = new PCKAudioFile();
ReadLookUpTable(reader);
ReadCategories(reader);
ReadCategorySongs(reader);
}
return _file;
}
private void ReadLookUpTable(Stream stream)
private void ReadLookUpTable(EndiannessAwareBinaryReader reader)
{
int count = ReadInt(stream);
int count = reader.ReadInt32();
LUT = new List<string>(count);
for (int i = 0; i < count; i++)
{
int index = ReadInt(stream);
LUT.Insert(index, ReadString(stream));
int index = reader.ReadInt32();
string value = ReadString(reader);
LUT.Insert(index, value);
}
}
private void ReadCategories(Stream stream)
private void ReadCategories(EndiannessAwareBinaryReader reader)
{
int categoryEntryCount = ReadInt(stream);
int categoryEntryCount = reader.ReadInt32();
for (; 0 < categoryEntryCount; categoryEntryCount--)
{
var parameterType = (PCKAudioFile.AudioCategory.EAudioParameterType)ReadInt(stream);
var audioType = (PCKAudioFile.AudioCategory.EAudioType)ReadInt(stream);
string name = ReadString(stream);
var parameterType = (PCKAudioFile.AudioCategory.EAudioParameterType)reader.ReadInt32();
var audioType = (PCKAudioFile.AudioCategory.EAudioType)reader.ReadInt32();
string name = ReadString(reader);
// AddCategory puts the file's categories out of order and causes some songs to be put in the wrong categories
// This is my simple fix for the issue.
_OriginalAudioTypeOrder.Add(audioType);
@@ -70,17 +91,17 @@ namespace PckStudio.Classes.IO.PCK
}
}
private void ReadCategorySongs(Stream stream)
private void ReadCategorySongs(EndiannessAwareBinaryReader reader)
{
List<string> credits = new List<string>();
List<string> creditIds = new List<string>();
foreach (var c in _OriginalAudioTypeOrder)
{
int audioCount = ReadInt(stream);
int audioCount = reader.ReadInt32();
for (; 0 < audioCount; audioCount--)
{
string key = LUT[ReadInt(stream)];
string value = ReadString(stream);
string key = LUT[reader.ReadInt32()];
string value = ReadString(reader);
switch (key)
{
case "CUENAME":
@@ -104,12 +125,16 @@ namespace PckStudio.Classes.IO.PCK
}
}
private string ReadString(Stream stream)
private string ReadString(EndiannessAwareBinaryReader reader)
{
int len = ReadInt(stream);
string s = ReadString(stream, len, IsUsingLittleEndian ? Encoding.Unicode : Encoding.BigEndianUnicode);
ReadInt(stream); // padding
int len = reader.ReadInt32();
string s = reader.ReadString(len);
reader.ReadInt32(); // padding
return s;
}
object IDataFormatReader.FromStream(Stream stream) => FromStream(stream);
object IDataFormatReader.FromFile(string filename) => FromFile(filename);
}
}
+48 -34
View File
@@ -1,14 +1,17 @@
using PckStudio.Classes.FileTypes;
using OMI;
using OMI.Workers;
using PckStudio.Classes.FileTypes;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace PckStudio.Classes.IO.PCK
{
internal class PCKAudioFileWriter : StreamDataWriter
internal class PCKAudioFileWriter : IDataFormatWriter
{
private PCKAudioFile _file;
private Endianness _endianness;
private static readonly List<string> LUT = new List<string>
{
"CUENAME",
@@ -16,71 +19,82 @@ namespace PckStudio.Classes.IO.PCK
"CREDITID"
};
public static void Write(Stream stream, PCKAudioFile file, bool isLittleEndian)
{
new PCKAudioFileWriter(file, isLittleEndian).WriteToStream(stream);
}
private PCKAudioFileWriter(PCKAudioFile file, bool isLittleEndian) : base(isLittleEndian)
public PCKAudioFileWriter(PCKAudioFile file, Endianness endianness)
{
_file = file;
_endianness = endianness;
}
protected override void WriteToStream(Stream stream)
public void WriteToFile(string filename)
{
WriteInt(stream, _file.type);
WriteLookUpTable(stream);
WriteCategories(stream);
WriteCategorySongs(stream);
using(var fs = File.OpenWrite(filename))
{
WriteToStream(fs);
}
}
private void WriteString(Stream stream, string s)
public void WriteToStream(Stream stream)
{
WriteInt(stream, s.Length);
WriteString(stream, s, IsUsingLittleEndian ? Encoding.Unicode : Encoding.BigEndianUnicode);
WriteInt(stream, 0); // padding
using (var writer = new EndiannessAwareBinaryWriter(stream,
_endianness == Endianness.BigEndian
? Encoding.BigEndianUnicode
: Encoding.Unicode,
leaveOpen: true, _endianness))
{
writer.Write(_file.type);
WriteLookUpTable(writer);
WriteCategories(writer);
WriteCategorySongs(writer);
}
}
private void WriteLookUpTable(Stream stream)
private void WriteString(EndiannessAwareBinaryWriter writer, string s)
{
WriteInt(stream, 3);
writer.Write(s.Length);
writer.WriteString(s);
writer.Write(0); // padding
}
private void WriteLookUpTable(EndiannessAwareBinaryWriter writer)
{
writer.Write(3);
for (int i = 0; i < 3; i++)
{
WriteInt(stream, i);
WriteString(stream, LUT[i]);
writer.Write(i);
WriteString(writer, LUT[i]);
}
}
private void WriteCategories(Stream stream)
private void WriteCategories(EndiannessAwareBinaryWriter writer)
{
WriteInt(stream, _file.Categories.Length);
writer.Write(_file.Categories.Length);
foreach (var category in _file.Categories)
{
WriteInt(stream, (int)category.parameterType);
WriteInt(stream, (int)category.audioType);
WriteString(stream, category.Name);
writer.Write((int)category.parameterType);
writer.Write((int)category.audioType);
WriteString(writer, category.Name);
}
}
private void WriteCategorySongs(Stream stream)
private void WriteCategorySongs(EndiannessAwareBinaryWriter writer)
{
bool addCredit = true;
foreach (var category in _file.Categories)
{
WriteInt(stream, category.SongNames.Count + (addCredit ? _file.Credits.Count * 2 : 0));
writer.Write(category.SongNames.Count + (addCredit ? _file.Credits.Count * 2 : 0));
foreach (var name in category.SongNames)
{
WriteInt(stream, LUT.IndexOf("CUENAME"));
WriteString(stream, name);
writer.Write(LUT.IndexOf("CUENAME"));
WriteString(writer, name);
}
if (addCredit)
{
foreach (var credit in _file.Credits)
{
WriteInt(stream, LUT.IndexOf("CREDIT"));
WriteString(stream, credit.Value);
WriteInt(stream, LUT.IndexOf("CREDITID"));
WriteString(stream, credit.Key);
writer.Write(LUT.IndexOf("CREDIT"));
WriteString(writer, credit.Value);
writer.Write(LUT.IndexOf("CREDITID"));
WriteString(writer, credit.Key);
}
}
addCredit = false;
-92
View File
@@ -1,92 +0,0 @@
/* Copyright (c) 2022-present miku-666
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1.The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
using PckStudio.Classes.FileTypes;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PckStudio.Classes.IO
{
public abstract class StreamDataReader<T>
{
private static bool useLittleEndian;
protected static bool IsUsingLittleEndian => useLittleEndian;
protected abstract T ReadFromStream(Stream stream);
protected StreamDataReader(bool useLittleEndian)
{
StreamDataReader<T>.useLittleEndian = useLittleEndian;
}
protected static string ReadString(Stream stream, int length, Encoding encoding)
{
byte[] buffer = ReadBytes(stream, length << Convert.ToInt32(encoding is UnicodeEncoding));
return encoding.GetString(buffer).TrimEnd('\0');
}
protected static byte[] ReadBytes(Stream stream, int count)
{
byte[] buffer = new byte[count];
stream.Read(buffer, 0, count);
return buffer;
}
protected static bool ReadBool(Stream stream)
{
return stream.ReadByte() != 0;
}
protected static ushort ReadUShort(Stream stream) => (ushort)ReadShort(stream);
protected static short ReadShort(Stream stream)
{
byte[] bytes = ReadBytes(stream, 2);
if (BitConverter.IsLittleEndian && !useLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToInt16(bytes, 0);
}
protected static uint ReadUInt(Stream stream) => (uint)ReadInt(stream);
protected static int ReadInt(Stream stream)
{
byte[] buffer = ReadBytes(stream, 4);
if (BitConverter.IsLittleEndian && !useLittleEndian)
Array.Reverse(buffer);
return BitConverter.ToInt32(buffer, 0);
}
protected static ulong ReadULong(Stream stream) => (ulong)ReadLong(stream);
protected static long ReadLong(Stream stream)
{
byte[] buffer = ReadBytes(stream, 8);
if (BitConverter.IsLittleEndian && !useLittleEndian)
Array.Reverse(buffer);
return BitConverter.ToInt64(buffer, 0);
}
protected static float ReadFloat(Stream stream)
{
byte[] buffer = ReadBytes(stream, 4);
if (BitConverter.IsLittleEndian && !useLittleEndian)
Array.Reverse(buffer);
return BitConverter.ToSingle(buffer, 0);
}
}
}
-89
View File
@@ -1,89 +0,0 @@
/* Copyright (c) 2022-present miku-666
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1.The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
**/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PckStudio.Classes.IO
{
public abstract class StreamDataWriter
{
private static bool useLittleEndian;
protected static bool IsUsingLittleEndian => useLittleEndian;
protected StreamDataWriter(bool littleEndian)
{
useLittleEndian = littleEndian;
}
protected abstract void WriteToStream(Stream stream);
protected static void WriteBool(Stream stream, bool state)
{
stream.WriteByte((byte)(state ? 1 : 0));
}
protected static void WriteUShort(Stream stream, ushort value) => WriteShort(stream, (short)value);
protected static void WriteShort(Stream stream, short value)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian && !useLittleEndian)
Array.Reverse(bytes);
WriteBytes(stream, bytes, 2);
}
protected static void WriteUInt(Stream stream, uint value) => WriteInt(stream, (int)value);
protected static void WriteInt(Stream stream, int value)
{
byte[] buffer = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian && !useLittleEndian)
Array.Reverse(buffer);
WriteBytes(stream, buffer, 4);
}
protected static void WriteULong(Stream stream, ulong value) => WriteLong(stream, (long)value);
protected static void WriteLong(Stream stream, long value)
{
byte[] buffer = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian && !useLittleEndian)
Array.Reverse(buffer);
WriteBytes(stream, buffer, 8);
}
protected static void WriteString(Stream stream, string s, Encoding encoding)
=> WriteBytes(stream, encoding.GetBytes(s));
protected static void WriteBytes(Stream stream, byte[] bytes) => WriteBytes(stream, bytes, bytes.Length);
protected static void WriteBytes(Stream stream, byte[] bytes, int count)
{
stream.Write(bytes, 0, count);
}
protected static void WriteFloat(Stream stream, float value)
{
byte[] buffer = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian && !useLittleEndian)
Array.Reverse(buffer);
WriteBytes(stream, buffer, 4);
}
}
}
+4 -2
View File
@@ -64,7 +64,8 @@ namespace PckStudio.Forms.Editor
audioPCK = file;
using (var stream = new MemoryStream(file.Data))
{
audioFile = PCKAudioFileReader.Read(stream, isLittleEndian);
var reader = new PCKAudioFileReader(isLittleEndian ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian);
audioFile = reader.FromStream(stream);
}
SetUpTree();
@@ -396,7 +397,8 @@ namespace PckStudio.Forms.Editor
using (var stream = new MemoryStream())
{
PCKAudioFileWriter.Write(stream, audioFile, _isLittleEndian);
var writer = new PCKAudioFileWriter(audioFile, _isLittleEndian ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian);
writer.WriteToStream(stream);
audioPCK.SetData(stream.ToArray());
}
DialogResult = DialogResult.OK;
+9 -6
View File
@@ -839,12 +839,15 @@ namespace PckStudio
audioPck.AddCategory(PCKAudioFile.AudioCategory.EAudioType.Overworld);
audioPck.AddCategory(PCKAudioFile.AudioCategory.EAudioType.Nether);
audioPck.AddCategory(PCKAudioFile.AudioCategory.EAudioType.End);
PckFile.FileData pckFileData = currentPCK.CreateNewFile("audio.pck", PckFile.FileData.FileType.AudioFile);
using (var stream = new MemoryStream())
{
PCKAudioFileWriter.Write(stream, audioPck, isLittle);
pckFileData.SetData(stream.ToArray());
}
PckFile.FileData pckFileData = currentPCK.CreateNewFile("audio.pck", PckFile.FileData.FileType.AudioFile, () =>
{
using (var stream = new MemoryStream())
{
var writer = new PCKAudioFileWriter(audioPck, isLittle ? OMI.Endianness.LittleEndian : OMI.Endianness.BigEndian);
writer.WriteToStream(stream);
return stream.ToArray();
}
});
return pckFileData;
}
-2
View File
@@ -187,8 +187,6 @@
<Compile Include="Classes\Utils\ARC\ARCUtil.cs" />
<Compile Include="Classes\Extentions\ImageExtentions.cs" />
<Compile Include="Classes\Utils\SkinANIM.cs" />
<Compile Include="Classes\IO\StreamDataReader.cs" />
<Compile Include="Classes\IO\StreamDataWriter.cs" />
<Compile Include="Classes\Models\DefaultModels\Steve64x32Model.cs" />
<Compile Include="Classes\Models\DefaultModels\ModelBase.cs" />
<Compile Include="Classes\Models\DefaultModels\Texture.cs" />
+1 -1