Skip to content

Commit

Permalink
Decode ASTC #63
Browse files Browse the repository at this point in the history
  • Loading branch information
UlyssesWu committed Jul 12, 2021
1 parent 0df2422 commit 15ccfd7
Show file tree
Hide file tree
Showing 16 changed files with 348 additions and 43 deletions.
2 changes: 1 addition & 1 deletion FreeMote.Plugins.x64/FreeMote.Plugins.x64.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<ProjectGuid>{7B5BAE81-6779-4404-9E6E-512BE4471AB9}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FreeMote.Plugins.x64</RootNamespace>
<RootNamespace>FreeMote.Plugins</RootNamespace>
<AssemblyName>FreeMote.Plugins.x64</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
Expand Down
5 changes: 2 additions & 3 deletions FreeMote.Plugins/FreeMote.Plugins.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
<Compile Include="Audio\VagFile.cs" />
<Compile Include="Audio\VagFormatter.cs" />
<Compile Include="Audio\XwmaFormatter.cs" />
<Compile Include="Images\AstcFormatter.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
Expand Down Expand Up @@ -118,9 +119,7 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Images\" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>echo There is a bug that some nuget package dll may not have edit date so it won't be copied. If it happens, remove /D and try again.
Expand Down
77 changes: 77 additions & 0 deletions FreeMote.Plugins/Images/AstcFormatter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace FreeMote.Plugins.Images
{
[Export(typeof(IPsbImageFormatter))]
[ExportMetadata("Name", "FreeMote.Astc")]
[ExportMetadata("Author", "Ulysses")]
[ExportMetadata("Comment", "ASTC support.")]
class AstcFormatter : IPsbImageFormatter
{
public AstcFormatter()
{
var toolPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location) ?? "", "Tools");
foreach (var encoderTool in EncoderTools)
{
var tool = Path.Combine(toolPath, encoderTool);
if (File.Exists(tool))
{
ToolPath = tool;
return;
}
}
}

public string ToolPath { get; set; } = null;

public List<string> Extensions { get; } = new() {".astc"};

public static List<string> EncoderTools { get; } = new()
{"astcenc.exe", "astcenc-sse2.exe", "astcenc-sse4.1.exe", "astcenc-avx2.exe"};

public bool CanToBitmap(in byte[] data, Dictionary<string, object> context = null)
{
if (data.Take(4).SequenceEqual(AstcHeader.Magic))
{
return true;
}

return false;
}

public bool CanToBytes(Bitmap bitmap, Dictionary<string, object> context = null)
{
if (string.IsNullOrEmpty(ToolPath))
{
return false;
}

return true;
}

public Bitmap ToBitmap(in byte[] data, Dictionary<string, object> context = null)
{
if (AstcFile.IsAstcHeader(data))
{
var header = AstcFile.ParseAstcHeader(data);

return RL.ConvertToImage(data, header.Height, header.Width, PsbPixelFormat.ASTC_8BPP);
}

return null;
}

public byte[] ToBytes(Bitmap bitmap, Dictionary<string, object> context = null)
{
return null;
}
}
}
2 changes: 1 addition & 1 deletion FreeMote.Psb/FreeMote.Psb.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
<Compile Include="Resources\FlattenArrayMetadata.cs" />
<Compile Include="Resources\IArchData.cs" />
<Compile Include="Resources\ImageMetadata.cs" />
<Compile Include="Resources\WavFormatter.cs" />
<Compile Include="Plugins\WavFormatter.cs" />
<Compile Include="Types\ArchiveType.cs" />
<Compile Include="Types\BaseImageType.cs" />
<Compile Include="Types\FontType.cs" />
Expand Down
5 changes: 5 additions & 0 deletions FreeMote.Psb/IResourceMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public enum PsbCompressType
/// </summary>
Tlg,

/// <summary>
/// ASTC
/// </summary>
Astc,

/// <summary>
/// By extension
/// </summary>
Expand Down
12 changes: 5 additions & 7 deletions FreeMote.Psb/Plugins/FreeMount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,15 @@ public class FreeMount : IDisposable

[Import(AllowDefault = true)] private Lazy<IPsbKeyProvider, IPsbPluginInfo> _keyProvider;

public Dictionary<string, IPsbShell> Shells { get; private set; } = new Dictionary<string, IPsbShell>();
public Dictionary<string, IPsbSpecialType> SpecialTypes { get; private set; } = new Dictionary<string, IPsbSpecialType>();
public Dictionary<string, IPsbShell> Shells { get; private set; } = new();
public Dictionary<string, IPsbSpecialType> SpecialTypes { get; private set; } = new();

public Dictionary<string, IPsbImageFormatter> ImageFormatters { get; private set; } =
new Dictionary<string, IPsbImageFormatter>();
public Dictionary<string, IPsbImageFormatter> ImageFormatters { get; private set; } = new();

public Dictionary<string, IPsbAudioFormatter> AudioFormatters { get; private set; } =
new Dictionary<string, IPsbAudioFormatter>();
public Dictionary<string, IPsbAudioFormatter> AudioFormatters { get; private set; } = new();

private CompositionContainer _container;
private Dictionary<IPsbPlugin, IPsbPluginInfo> _plugins = new Dictionary<IPsbPlugin, IPsbPluginInfo>();
private readonly Dictionary<IPsbPlugin, IPsbPluginInfo> _plugins = new();
private int _maxShellSigLength = 4;

private static FreeMount _mount = null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using FreeMote.Plugins;
using FreeMote.Psb;

namespace FreeMote.Psb
namespace FreeMote.Plugins
{
[Export(typeof(IPsbAudioFormatter))]
[ExportMetadata("Name", "FreeMote.Wav")]
Expand Down
56 changes: 38 additions & 18 deletions FreeMote.Psb/PsbExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@ public static PsbCompressType CompressType(this PsbSpec spec)
}
}

/// <summary>
/// <paramref name="compress"/> to its file extension
/// </summary>
/// <param name="compress"></param>
/// <returns></returns>
public static string ToExtensionString(this PsbCompressType compress)
{
switch (compress)
{
case PsbCompressType.Tlg:
return ".tlg";
case PsbCompressType.Astc:
return ".astc";
case PsbCompressType.RL:
return ".rl";
default:
return "";
}
}

private static bool ApplyDefaultMotionMetadata(PSB psb, PsbDictionary metadata)
{
List<(string Chara, string Motion)> knownMotions = new List<(string Chara, string Motion)>
Expand Down Expand Up @@ -74,7 +94,7 @@ public static bool FixMotionMetadata(this PSB psb)
}

var realMotion = realChara["motion"] as PsbDictionary;

if (realMotion == null || realMotion.Count == 0) //motion not exist and nothing can replace it
{
return ApplyDefaultMotionMetadata(psb, dic);
Expand Down Expand Up @@ -109,8 +129,8 @@ public static bool TryGetCanvasSize(this PSB psb, out int width, out int height)
&& pm["boundsBottom"] is PsbNumber b && pm["boundsTop"] is PsbNumber t &&
pm["boundsLeft"] is PsbNumber l && pm["boundsRight"] is PsbNumber r)
{
height = (int) Math.Abs(b.AsFloat - t.AsFloat);
width = (int) Math.Abs(r.AsFloat - l.AsFloat);
height = (int)Math.Abs(b.AsFloat - t.AsFloat);
width = (int)Math.Abs(r.AsFloat - l.AsFloat);
return true;
}

Expand Down Expand Up @@ -218,7 +238,7 @@ public static IPsbValue Children(this IPsbValue col, string name)
/// <returns></returns>
public static int GetInt(this IPsbValue col)
{
return ((PsbNumber) col).AsInt;
return ((PsbNumber)col).AsInt;
}

/// <summary>
Expand Down Expand Up @@ -453,7 +473,7 @@ public static IPsbValue FindByMmoPath(this IPsbCollection psbObj, string path)
{
//var dd = dic.Value.FirstOrDefault();
var children =
(PsbList) (dic.ContainsKey("layerChildren") ? dic["layerChildren"] : dic["children"]);
(PsbList)(dic.ContainsKey("layerChildren") ? dic["layerChildren"] : dic["children"]);
currentObj = children.FirstOrDefault(c =>
c is PsbDictionary d && d.ContainsKey("label") && d["label"] is PsbString s &&
s.Value == current);
Expand Down Expand Up @@ -547,27 +567,27 @@ public static void SaveAsMdfFile(this PSB psb, string path, uint? key = null)
if (key == null)
{
adler.Update(bytes);
checksum = (uint) adler.Checksum;
checksum = (uint)adler.Checksum;
}

MemoryStream ms = new MemoryStream(bytes);
using (Stream fs = new FileStream(path, FileMode.Create))
{
if (key != null)
{
MemoryStream nms = new MemoryStream((int) ms.Length);
MemoryStream nms = new MemoryStream((int)ms.Length);
PsbFile.Encode(key.Value, EncodeMode.Encrypt, EncodePosition.Auto, ms, nms);
ms.Dispose();
ms = nms;
var pos = ms.Position;
adler.Update(ms);
checksum = (uint) adler.Checksum;
checksum = (uint)adler.Checksum;
ms.Position = pos;
}

BinaryWriter bw = new BinaryWriter(fs);
bw.WriteStringZeroTrim(MdfFile.Signature);
bw.Write((uint) ms.Length);
bw.Write((uint)ms.Length);
//bw.Write(ZlibCompress.Compress(ms));
ZlibCompress.CompressToBinaryWriter(bw, ms);
bw.WriteBE(checksum);
Expand All @@ -591,27 +611,27 @@ public static byte[] SaveAsMdf(this PSB psb, uint? key = null)
if (key == null)
{
adler.Update(bytes);
checksum = (uint) adler.Checksum;
checksum = (uint)adler.Checksum;
}

MemoryStream ms = new MemoryStream(bytes);
using (MemoryStream fs = new MemoryStream())
{
if (key != null)
{
MemoryStream nms = new MemoryStream((int) ms.Length);
MemoryStream nms = new MemoryStream((int)ms.Length);
PsbFile.Encode(key.Value, EncodeMode.Encrypt, EncodePosition.Auto, ms, nms);
ms.Dispose();
ms = nms;
var pos = ms.Position;
adler.Update(ms);
checksum = (uint) adler.Checksum;
checksum = (uint)adler.Checksum;
ms.Position = pos;
}

BinaryWriter bw = new BinaryWriter(fs);
bw.WriteStringZeroTrim(MdfFile.Signature);
bw.Write((uint) ms.Length);
bw.Write((uint)ms.Length);
//bw.Write(ZlibCompress.Compress(ms));
ZlibCompress.CompressToBinaryWriter(bw, ms);
bw.WriteBE(checksum);
Expand Down Expand Up @@ -723,7 +743,7 @@ public static int GetSize(this uint i)
//FIXED: Treat uint as int to prevent overconfidence
if (i <= Int32.MaxValue)
{
return GetSize((int) i);
return GetSize((int)i);
}

var l = i.ToString("X").Length;
Expand Down Expand Up @@ -895,7 +915,7 @@ public static uint UnzipUInt(this byte[] b, int start, byte size)

//optimized with Span<T>
Span<byte> span = stackalloc byte[4];
for (int i = 0; i < Math.Min(size, (byte) 4); i++)
for (int i = 0; i < Math.Min(size, (byte)4); i++)
{
span[i] = b[start + i];
}
Expand Down Expand Up @@ -927,7 +947,7 @@ public static string ArchiveInfoGetFileNameRemoveSuffix(string fileName, string

return fileName;
}

/// <summary>
/// Append suffix for file name in archive info file_info
/// </summary>
Expand Down Expand Up @@ -977,7 +997,7 @@ public static string ArchiveInfoGetSuffix(PSB psb)

return suffix;
}

/// <summary>
/// Get package name from a string like {package name}_info.psb.m
/// </summary>
Expand Down Expand Up @@ -1013,7 +1033,7 @@ public static string ArchiveInfoGetPackageName(string fileName)
/// <returns>null if input is null; <see cref="String.Empty"/> if no second extension</returns>
internal static string GetSecondExtension(this string path)
{
return Path.GetExtension(Path.GetFileNameWithoutExtension(path))?.ToLowerInvariant();
return Path.GetExtension(Path.GetFileNameWithoutExtension(path))?.ToLowerInvariant();
}
}

Expand Down
36 changes: 27 additions & 9 deletions FreeMote.Psb/Resources/ImageMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -214,19 +214,37 @@ public Bitmap ToImage()
/// <param name="bmp"></param>
public void SetData(Bitmap bmp)
{
switch (Compress)
bool converted = false;

switch (PixelFormat)
{
case PsbCompressType.RL:
Data = RL.CompressImage(bmp, PixelFormat);
break;
case PsbCompressType.Tlg:
Data = FreeMount.CreateContext().BitmapToResource(".tlg", bmp);
break;
default:
Data = RL.GetPixelBytesFromImage(bmp, PixelFormat);
case PsbPixelFormat.ASTC_8BPP:
Data = FreeMount.CreateContext().BitmapToResource(PsbCompressType.Astc.ToExtensionString(), bmp);
if (Data != null)
{
converted = true;
}
break;
}

if (!converted)
{
switch (Compress)
{
case PsbCompressType.RL:
Data = RL.CompressImage(bmp, PixelFormat);
break;
case PsbCompressType.Tlg:
Data = FreeMount.CreateContext().BitmapToResource(PsbCompressType.Tlg.ToExtensionString(), bmp);
break;
case PsbCompressType.Astc:
Data = FreeMount.CreateContext().BitmapToResource(PsbCompressType.Astc.ToExtensionString(), bmp);
break;
default:
Data = RL.GetPixelBytesFromImage(bmp, PixelFormat);
break;
}
}
if (PixelFormat.UsePalette())
{
PalData = bmp.Palette.GetPaletteBytes(PalettePixelFormat);
Expand Down
1 change: 1 addition & 0 deletions FreeMote.Psb/Types/ImageType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ private static ImageMetadata GenerateTachieResMetadata(PsbDictionary d, PsbResou
Part = label,
Resource = r,
};

return md;
}
}
Expand Down
1 change: 1 addition & 0 deletions FreeMote.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Abgr/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Adpcm/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Argb/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ASTC/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Atrac/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bgra/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Consts/@EntryIndexedValue">True</s:Boolean>
Expand Down
Loading

0 comments on commit 15ccfd7

Please sign in to comment.