using System.IO.Compression;
using System.Security.Cryptography;
using System.Text.Json;
using XFEEDToolBox.Core.Models;
namespace XFEEDToolBox.Core.Rendering;
public sealed record GalaxyOriginalSpriteMip(int Offset,int SliceBytes,int Size,int RowPitch,int DepthPitch);
/// <summary>Exact original BC1 diffuse array; the original BackgroundStars shader is separate.</summary>
public sealed class GalaxyOriginalSpriteArray
{
public const int Width=512,Height=512,Layers=28,MipCount=10;
private readonly byte[] payload;
public ReadOnlyMemory<byte> Payload=>payload;
public IReadOnlyList<GalaxyOriginalSpriteMip> Mips {get;}
public string SourceSha256 {get;}
public string PayloadSha256 {get;}
internal GalaxyOriginalSpriteArray(JsonElement metadata,byte[] data)
{
SourceSha256=metadata.GetProperty("sourceArchiveSha256").GetString()!;
PayloadSha256=metadata.GetProperty("payloadSha256").GetString()!;
if(metadata.GetProperty("width").GetInt32()!=Width||metadata.GetProperty("height").GetInt32()!=Height||
metadata.GetProperty("layers").GetInt32()!=Layers||metadata.GetProperty("mipCount").GetInt32()!=MipCount||
data.Length!=5074944||Convert.ToHexStringLower(SHA256.HashData(data))!=PayloadSha256)
throw new InvalidDataException("原星图点纹理校验失败。");
var mips=JsonSerializer.Deserialize<GalaxyOriginalSpriteMip[]>(metadata.GetProperty("mips"),ToolboxSettings.JsonOptions)??[];
if(mips.Length!=MipCount)throw new InvalidDataException("原星图点纹理层级无效。");
var end=0;
for(var i=0;i<mips.Length;i++)
{
var mip=mips[i];var blockWidth=Math.Max(1,(Width>>i)+3>>2);var blockHeight=Math.Max(1,(Height>>i)+3>>2);
if(mip.Offset!=end||mip.Size!=mip.SliceBytes*Layers||mip.RowPitch<blockWidth*8||mip.SliceBytes<mip.RowPitch*blockHeight)
throw new InvalidDataException("原星图点纹理布局无效。");
end=checked(end+mip.Size);
}
if(end!=data.Length)throw new InvalidDataException("原星图点纹理数据不完整。");
payload=data;Mips=Array.AsReadOnly(mips);
}
}
public static class GalaxyOriginalStarSprites
{
public const int DefaultLayer=13;
public static GalaxyOriginalSpriteArray Reference {get;}=Read();
// Original Territory/Activities vtable+58 getter 3B32DD0; these are its
// own state indices, not the public power-state string enumeration.
public static int TerritoryLayer(int stateIndex)=>stateIndex switch{2=>16,3=>21,4=>18,5=>19,6=>22,7=>23,_=>15};
private static GalaxyOriginalSpriteArray Read()
{
var assembly=typeof(GalaxyOriginalStarSprites).Assembly;
using var metadata=assembly.GetManifestResourceStream("XFEEDToolBox.Core.Rendering.original-star-sprites.json")!;
using var json=JsonDocument.Parse(metadata);
using var compressed=assembly.GetManifestResourceStream("XFEEDToolBox.Core.Rendering.original-star-sprites.bc1.gz")!;
using var gzip=new GZipStream(compressed,CompressionMode.Decompress);var data=new byte[5074944];gzip.ReadExactly(data);
if(gzip.ReadByte()!=-1)throw new InvalidDataException("原星图点纹理数据超出范围。");
return new(json.RootElement,data);
}
}
using System.IO.Compression;
using System.Security.Cryptography;
using System.Text.Json;
using XFEEDToolBox.Core.Models;
namespace XFEEDToolBox.Core.Rendering;
public sealed record GalaxyOriginalSpriteMip(int Offset,int SliceBytes,int Size,int RowPitch,int DepthPitch);
/// <summary>Exact original BC1 diffuse array; the original BackgroundStars shader is separate.</summary>
public sealed class GalaxyOriginalSpriteArray
{
public const int Width=512,Height=512,Layers=28,MipCount=10;
private readonly byte[] payload;
public ReadOnlyMemory<byte> Payload=>payload;
public IReadOnlyList<GalaxyOriginalSpriteMip> Mips {get;}
public string SourceSha256 {get;}
public string PayloadSha256 {get;}
internal GalaxyOriginalSpriteArray(JsonElement metadata,byte[] data)
{
SourceSha256=metadata.GetProperty("sourceArchiveSha256").GetString()!;
PayloadSha256=metadata.GetProperty("payloadSha256").GetString()!;
if(metadata.GetProperty("width").GetInt32()!=Width||metadata.GetProperty("height").GetInt32()!=Height||
metadata.GetProperty("layers").GetInt32()!=Layers||metadata.GetProperty("mipCount").GetInt32()!=MipCount||
data.Length!=5074944||Convert.ToHexStringLower(SHA256.HashData(data))!=PayloadSha256)
throw new InvalidDataException("原星图点纹理校验失败。");
var mips=JsonSerializer.Deserialize<GalaxyOriginalSpriteMip[]>(metadata.GetProperty("mips"),ToolboxSettings.JsonOptions)??[];
if(mips.Length!=MipCount)throw new InvalidDataException("原星图点纹理层级无效。");
var end=0;
for(var i=0;i<mips.Length;i++)
{
var mip=mips[i];var blockWidth=Math.Max(1,(Width>>i)+3>>2);var blockHeight=Math.Max(1,(Height>>i)+3>>2);
if(mip.Offset!=end||mip.Size!=mip.SliceBytes*Layers||mip.RowPitch<blockWidth*8||mip.SliceBytes<mip.RowPitch*blockHeight)
throw new InvalidDataException("原星图点纹理布局无效。");
end=checked(end+mip.Size);
}
if(end!=data.Length)throw new InvalidDataException("原星图点纹理数据不完整。");
payload=data;Mips=Array.AsReadOnly(mips);
}
}
public static class GalaxyOriginalStarSprites
{
public const int DefaultLayer=13;
public static GalaxyOriginalSpriteArray Reference {get;}=Read();
// Original Territory/Activities vtable+58 getter 3B32DD0; these are its
// own state indices, not the public power-state string enumeration.
public static int TerritoryLayer(int stateIndex)=>stateIndex switch{2=>16,3=>21,4=>18,5=>19,6=>22,7=>23,_=>15};
private static GalaxyOriginalSpriteArray Read()
{
var assembly=typeof(GalaxyOriginalStarSprites).Assembly;
using var metadata=assembly.GetManifestResourceStream("XFEEDToolBox.Core.Rendering.original-star-sprites.json")!;
using var json=JsonDocument.Parse(metadata);
using var compressed=assembly.GetManifestResourceStream("XFEEDToolBox.Core.Rendering.original-star-sprites.bc1.gz")!;
using var gzip=new GZipStream(compressed,CompressionMode.Decompress);var data=new byte[5074944];gzip.ReadExactly(data);
if(gzip.ReadByte()!=-1)throw new InvalidDataException("原星图点纹理数据超出范围。");
return new(json.RootElement,data);
}
}