Skip to content

Commit

Permalink
refactor: various refactoring and fixing
Browse files Browse the repository at this point in the history
* refactor(io): rename IO primitives to follow .NET BCL BinaryPrimitives naming convention, althought the endianness situation will always be confusing
* fix(io): revert broken varint "optimization", it's not even that hot path lol
* refactor(lingo): rename NewArgList instruction to PushUint
* refactor(lingo): throw unsupported exception for 80-bit extended precision floating points in the constants
* fix(afterburner): fix FileCompressionTypes reading. credits to projectorrays
* fix(afterburner): fixed some incomplete logic I have left while messing around
* refactor(shockwavefile): invert ifs in the main parsing entrypoint to reduce nesting
  • Loading branch information
PaulusParssinen committed Mar 12, 2024
1 parent 426c321 commit 3d729c6
Show file tree
Hide file tree
Showing 62 changed files with 928 additions and 891 deletions.
33 changes: 19 additions & 14 deletions Shockky.Sandbox/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,25 @@
Console.Title = "Shockky.Sandbox";

//TODO: Verbose and Quiet levels, and rest of the resources of course
var inputArgument = new Argument<IEnumerable<System.IO.FileInfo>>("input")
{
Arity = ArgumentArity.OneOrMore,
Description = "Director movie (.d[ixc]r) or external cast (.c[sxc]t) file(s)."
}.ExistingOnly();

var outputOption = new Option<DirectoryInfo>("--output",
getDefaultValue: () => new DirectoryInfo("Output/"),
description: "Directory for the extracted resources")
.LegalFilePathsOnly();

var rootCommand = new RootCommand()
{
new Argument<IEnumerable<System.IO.FileInfo>>("input")
{
Arity = ArgumentArity.OneOrMore,
Description = "Director movie (.dir, .dxt, .dcr) or external cast (.cst, .cxt, .cct) file(s)."
}.ExistingOnly(),

new Option<DirectoryInfo>("--output",
getDefaultValue: () => new DirectoryInfo("Output/"),
description: "Directory for the extracted resources")
.LegalFilePathsOnly()
inputArgument,
outputOption
};
//rootCommand.SetHandler<IEnumerable<System.IO.FileInfo>, bool, DirectoryInfo>(HandleExtractCommand);

rootCommand.SetHandler(HandleExtractCommand,
inputArgument, outputOption);

return rootCommand.Invoke(args);

Expand Down Expand Up @@ -76,7 +81,7 @@ static System.Drawing.Color[] ReadPalette(string fileName)
};
}

static void HandleExtractCommand(IEnumerable<System.IO.FileInfo> input, bool images, DirectoryInfo output)
static void HandleExtractCommand(IEnumerable<System.IO.FileInfo> input, DirectoryInfo output)
{
output.Create();

Expand Down Expand Up @@ -124,7 +129,7 @@ static void HandleExtractCommand(IEnumerable<System.IO.FileInfo> input, bool ima
if (bitmapProperties.Rectangle.IsEmpty)
continue;

string outputFilePath = Path.Combine(fileOutputDirectory.FullName, member.Metadata?.Name ?? resourceId.Id.ToString());
string outputFilePath = Path.Combine(fileOutputDirectory.FullName, member.Metadata?.Entries.Name ?? resourceId.Id.ToString());

if (bitmapProperties.PaletteRef.MemberNum > 0 && bitmapProperties.PaletteRef.MemberNum < castAssociationTable.Members.Length)
{
Expand All @@ -150,7 +155,7 @@ static void HandleExtractCommand(IEnumerable<System.IO.FileInfo> input, bool ima
if (!TryExtractBitmapResource(outputFilePath, bitmapProperties, bitmapData, palette))
continue;
}
Console.WriteLine($"({bitmapProperties.PaletteRef.CastLib}, {bitmapProperties.PaletteRef.MemberNum}) {member.Metadata?.Name}:");
Console.WriteLine($"({bitmapProperties.PaletteRef.CastLib}, {bitmapProperties.PaletteRef.MemberNum}) {member.Metadata?.Entries.Name}:");
Console.WriteLine($" BitDepth: {bitmapProperties.BitDepth}");
}
Console.WriteLine();
Expand Down
18 changes: 9 additions & 9 deletions Shockky.SourceGeneration.Tests/InstructionGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public sealed class Return : IInstruction

public void WriteTo(global::Shockky.IO.ShockwaveWriter output)
{
output.Write((byte)OP);
output.WriteByte((byte)OP);
}
}
""";
Expand Down Expand Up @@ -57,18 +57,18 @@ public void WriteTo(global::Shockky.IO.ShockwaveWriter output)

if (Immediate <= byte.MaxValue)
{
output.Write(op);
output.Write((byte)Immediate);
output.WriteByte(op);
output.WriteByte((byte)Immediate);
}
else if (Immediate <= ushort.MaxValue)
{
output.Write((byte)(op + 0x40));
output.Write((ushort)Immediate);
output.WriteByte((byte)(op + 0x40));
output.WriteUInt16LittleEndian((ushort)Immediate);
}
else
{
output.Write((byte)(op + 0x80));
output.Write(Immediate);
output.WriteByte((byte)(op + 0x80));
output.WriteInt32LittleEndian(Immediate);
}
}
}
Expand All @@ -87,8 +87,8 @@ public static IInstruction Read(ref global::Shockky.IO.ShockwaveReader input)
int immediate = op >> 6 switch
{
1 => input.ReadByte(),
2 => input.ReadInt16(),
3 => input.ReadInt32(),
2 => input.ReadInt16LittleEndian(),
3 => input.ReadInt32LittleEndian(),
_ => 0
};

Expand Down
18 changes: 9 additions & 9 deletions Shockky.SourceGeneration/InstructionGenerator.Syntax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,22 @@ public int GetSize()

if (Immediate <= byte.MaxValue)
{
output.Write(op);
output.Write((byte)Immediate);
output.WriteByte(op);
output.WriteByte((byte)Immediate);
}
else if (Immediate <= ushort.MaxValue)
{
output.Write((byte)(op + 0x40));
output.Write((ushort)Immediate);
output.WriteByte((byte)(op + 0x40));
output.WriteUInt16LittleEndian((ushort)Immediate);
}
else
{
output.Write((byte)(op + 0x80));
output.Write(Immediate);
output.WriteByte((byte)(op + 0x80));
output.WriteInt32LittleEndian(Immediate);
}
""", true);
}
else writer.WriteLine("output.Write((byte)OP);");
else writer.WriteLine("output.WriteByte((byte)OP);");
}
}
}
Expand All @@ -100,8 +100,8 @@ internal static void WriteInstructionReadSyntax(IndentedTextWriter writer, Immut
int immediate = op >> 6 switch
{
1 => input.ReadByte(),
2 => input.ReadInt16(),
3 => input.ReadInt32(),
2 => input.ReadInt16LittleEndian(),
3 => input.ReadInt32LittleEndian(),
_ => 0
};
""", true);
Expand Down
26 changes: 13 additions & 13 deletions Shockky.Tests/IO/ShockwaveReaderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,18 @@ public void Read_ValidVarInts()

ShockwaveReader input = new(encodedValueBuffer);

Assert.Equal(0, input.ReadVarInt());
Assert.Equal(1, input.ReadVarInt());
Assert.Equal(127, input.ReadVarInt());
Assert.Equal(128, input.ReadVarInt());
Assert.Equal(8192, input.ReadVarInt());
Assert.Equal(16383, input.ReadVarInt());
Assert.Equal(16384, input.ReadVarInt());
Assert.Equal(2097151, input.ReadVarInt());
Assert.Equal(2097152, input.ReadVarInt());
Assert.Equal(134217728, input.ReadVarInt());
Assert.Equal(268435455, input.ReadVarInt());
Assert.Equal(8192, input.ReadVarInt());
Assert.Equal(13371337, input.ReadVarInt());
Assert.Equal(0, input.Read7BitEncodedInt());
Assert.Equal(1, input.Read7BitEncodedInt());
Assert.Equal(127, input.Read7BitEncodedInt());
Assert.Equal(128, input.Read7BitEncodedInt());
Assert.Equal(8192, input.Read7BitEncodedInt());
Assert.Equal(16383, input.Read7BitEncodedInt());
Assert.Equal(16384, input.Read7BitEncodedInt());
Assert.Equal(2097151, input.Read7BitEncodedInt());
Assert.Equal(2097152, input.Read7BitEncodedInt());
Assert.Equal(134217728, input.Read7BitEncodedInt());
Assert.Equal(268435455, input.Read7BitEncodedInt());
Assert.Equal(8192, input.Read7BitEncodedInt());
Assert.Equal(13371337, input.Read7BitEncodedInt());
}
}
42 changes: 21 additions & 21 deletions Shockky.Tests/IO/ShockwaveWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ public void Write_VariableInteger_AreEqual(int value)
{
Span<byte> buffer = stackalloc byte[ShockwaveWriter.GetVarIntSize(value)];

var output = new ShockwaveWriter(buffer, isBigEndian: false);
var input = new ShockwaveReader(buffer, isBigEndian: false);
var output = new ShockwaveWriter(buffer, reverseEndianness: false);
var input = new ShockwaveReader(buffer, reverseEndianness: false);

output.WriteVarInt(value);
output.Write7BitEncodedInt(value);

Assert.Equal(value, input.ReadVarInt());
Assert.Equal(value, input.Read7BitEncodedInt());
Assert.False(input.IsDataAvailable);
}

Expand All @@ -50,24 +50,24 @@ private void Write_NumericValues_AreEqual(bool isBigEndian)
var output = new ShockwaveWriter(buffer, isBigEndian);
var input = new ShockwaveReader(buffer, isBigEndian);

output.Write((byte)42);
output.Write((short)4242);
output.WriteBE((short)4242);
output.Write((ushort)4242);
output.WriteBE((ushort)4242);
output.Write(123456789);
output.WriteBE(123456789);
output.Write((uint)123456789);
output.WriteBE((uint)123456789);
output.WriteByte((byte)42);
output.WriteInt16LittleEndian((short)4242);
output.WriteInt16BigEndian((short)4242);
output.WriteUInt16LittleEndian((ushort)4242);
output.WriteUInt16BigEndian((ushort)4242);
output.WriteInt32LittleEndian(123456789);
output.WriteInt32BigEndian(123456789);
output.WriteUInt32LittleEndian((uint)123456789);
output.WriteUInt32BigEndian((uint)123456789);

Assert.Equal(42, input.ReadByte());
Assert.Equal(4242, input.ReadInt16());
Assert.Equal(4242, input.ReadBEInt16());
Assert.Equal((ushort)4242, input.ReadUInt16());
Assert.Equal((ushort)4242, input.ReadBEUInt16());
Assert.Equal(123456789, input.ReadInt32());
Assert.Equal(123456789, input.ReadBEInt32());
Assert.Equal((uint)123456789, input.ReadUInt32());
Assert.Equal((uint)123456789, input.ReadBEUInt32());
Assert.Equal(4242, input.ReadInt16LittleEndian());
Assert.Equal(4242, input.ReadInt16BigEndian());
Assert.Equal((ushort)4242, input.ReadUInt16LittleEndian());
Assert.Equal((ushort)4242, input.ReadUInt16BigEndian());
Assert.Equal(123456789, input.ReadInt32LittleEndian());
Assert.Equal(123456789, input.ReadInt32BigEndian());
Assert.Equal((uint)123456789, input.ReadUInt32LittleEndian());
Assert.Equal((uint)123456789, input.ReadUInt32BigEndian());
}
}
28 changes: 17 additions & 11 deletions Shockky/IO/Compression/ZLib.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

namespace Shockky.IO;

internal static class ZLib
public static class ZLib
{
public static readonly Guid MoaId = new(0xAC99E904, 0x0070, 0x0B36, 0x00, 0x00, 0x08, 0x00, 0x07, 0x37, 0x7A, 0x34);

// 🙏 Summoning circle 🙏
//
// 🕯 🕯 🕯
Expand All @@ -13,21 +15,25 @@ internal static class ZLib
//
// 🕯 🕯
// 🕯 🕯 🕯
internal static unsafe int Decompress(ReadOnlySpan<byte> input, Span<byte> output)
internal static unsafe void DecompressUnsafe(ReadOnlySpan<byte> input, Span<byte> output)
{
fixed (byte* inputPtr = &input[0])
fixed (byte* inputPtr = input)
{
using var stream = new UnmanagedMemoryStream(inputPtr, input.Length);
using var zlibStream = new ZLibStream(stream, CompressionMode.Decompress);

int totalRead = 0;
while (totalRead < output.Length)
{
int bytesRead = zlibStream.Read(output.Slice(totalRead));
if (bytesRead == 0) break;
totalRead += bytesRead;
}
return totalRead;
zlibStream.ReadExactly(output);
}
}

// TODO: Isn't this GC hole lmao
internal static unsafe ZLibShockwaveReader CreateDeflateReaderUnsafe(ref ShockwaveReader input)
{
int dataRemaining = input.Length - input.Position;
fixed (byte* bufferPtr = input.ReadBytes(dataRemaining))
{
var stream = new UnmanagedMemoryStream(bufferPtr, input.Length);
return new ZLibShockwaveReader(stream, input.ReverseEndianness, leaveOpen: false);
}
}
}
31 changes: 13 additions & 18 deletions Shockky/IO/Compression/ZLibShockwaveReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,19 @@

namespace Shockky.IO;

public sealed class ZLibShockwaveReader : BinaryReader
public sealed class ZLibShockwaveReader(Stream innerStream, bool isBigEndian, bool leaveOpen)
: BinaryReader(new ZLibStream(innerStream, CompressionMode.Decompress, leaveOpen))
{
private readonly bool _isBigEndian;
private readonly bool _isBigEndian = isBigEndian;

public ZLibShockwaveReader(Stream innerStream, bool isBigEndian, bool leaveOpen)
: base(new ZLibStream(innerStream, CompressionMode.Decompress, leaveOpen))
{
_isBigEndian = isBigEndian;
}

public int ReadVarInt()
public new int Read7BitEncodedInt()
{
int value = 0;
byte b;
do
{
b = ReadByte();
value = (value << 7) + (b & 0x7F);
value = (value << 7) | (b & 0x7F);
}
while (b >> 7 != 0);
return value;
Expand All @@ -38,21 +33,21 @@ public string ReadCString()
return builder.ToString();
}

public new short ReadInt16()
public short ReadInt16LittleEndian()
{
return _isBigEndian ? BinaryPrimitives.ReverseEndianness(base.ReadInt16()) : base.ReadInt16();
return _isBigEndian ? BinaryPrimitives.ReverseEndianness(ReadInt16()) : ReadInt16();
}
public short ReadBEInt16()
public short ReadInt16BigEndian()
{
return _isBigEndian ? base.ReadInt16() : BinaryPrimitives.ReverseEndianness(base.ReadInt16());
return _isBigEndian ? ReadInt16() : BinaryPrimitives.ReverseEndianness(ReadInt16());
}

public new int ReadInt32()
public int ReadInt32LittleEndian()
{
return _isBigEndian ? BinaryPrimitives.ReverseEndianness(base.ReadInt32()) : base.ReadInt32();
return _isBigEndian ? BinaryPrimitives.ReverseEndianness(ReadInt32()) : ReadInt32();
}
public int ReadBEInt32()
public int ReadInt32BigEndian()
{
return _isBigEndian ? base.ReadInt32() : BinaryPrimitives.ReverseEndianness(base.ReadInt32());
return _isBigEndian ? ReadInt32() : BinaryPrimitives.ReverseEndianness(ReadInt32());
}
}
Loading

0 comments on commit 3d729c6

Please sign in to comment.