XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Buffers.Binary;

namespace XFEEDToolBox.Core.Rendering;

/// <summary>DX10 DDS cube exported from an original game shader resource; no synthetic image generation.</summary>
public sealed record GameSkyboxCube(int Size,int Format,int RowPitch,byte[][] Faces)
{
    public static GameSkyboxCube Read(string path)
    {
        var info=new FileInfo(path);if(info.Length is <148 or >128*1024*1024)throw new InvalidDataException("游戏天空立方体大小无效。");
        return Parse(File.ReadAllBytes(path));
    }
    public static GameSkyboxCube Parse(ReadOnlySpan<byte> bytes)
    {
        static int U(ReadOnlySpan<byte> b,int at)=>BinaryPrimitives.ReadInt32LittleEndian(b.Slice(at,4));
        if(bytes.Length<148||!bytes[..4].SequenceEqual("DDS "u8)||U(bytes,4)!=124||U(bytes,76)!=32||!bytes.Slice(84,4).SequenceEqual("DX10"u8))throw new InvalidDataException("游戏天空立方体的 DDS 头无效。");
        var size=U(bytes,12);var format=U(bytes,128);
        if(size<16||size>2048||size!=U(bytes,16)||U(bytes,28)>1||U(bytes,132)!=3||(U(bytes,136)&4)==0||U(bytes,140)!=1)throw new InvalidDataException("游戏天空资源不是受支持的完整立方体。");
        var block=format is 71 or 72 or 74 or 75 or 77 or 78 or 80 or 81 or 83 or 84 or 95 or 96 or 98 or 99;
        var stride=format switch{2=>16,10=>8,28 or 29 or 26 or 67 or 87 or 91=>4,71 or 72 or 80 or 81=>8,74 or 75 or 77 or 78 or 83 or 84 or 95 or 96 or 98 or 99=>16,_=>throw new InvalidDataException("游戏天空立方体的纹理格式尚不支持。")};
        var row=(block?(size+3)/4:size)*stride;var faceBytes=row*(block?(size+3)/4:size);
        if(bytes.Length!=148+faceBytes*6)throw new InvalidDataException("游戏天空立方体的六个面不完整。");
        var faces=new byte[6][];for(var i=0;i<6;i++)faces[i]=bytes.Slice(148+i*faceBytes,faceBytes).ToArray();
        return new(size,format,row,faces);
    }
}