mirror of
https://github.com/KillzXGaming/Switch-Toolbox
synced 2024-11-27 15:01:06 +00:00
1140 lines
43 KiB
C#
1140 lines
43 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using Switch_Toolbox.Library.IO;
|
|
using System.Text;
|
|
|
|
namespace FirstPlugin
|
|
{
|
|
public enum BlockType : uint
|
|
{
|
|
Invalid = 0x00,
|
|
EndOfFile = 0x01,
|
|
AlignData = 0x02,
|
|
VertexShaderHeader = 0x03,
|
|
VertexShaderProgram = 0x05,
|
|
PixelShaderHeader = 0x06,
|
|
PixelShaderProgram = 0x07,
|
|
GeometryShaderHeader = 0x08,
|
|
GeometryShaderProgram = 0x09,
|
|
}
|
|
|
|
public class GTXHeader
|
|
{
|
|
public uint MajorVersion;
|
|
public uint MinorVersion;
|
|
public uint GpuVersion;
|
|
public uint AlignMode;
|
|
|
|
public void Read(FileReader reader)
|
|
{
|
|
string Signature = reader.ReadString(4, Encoding.ASCII);
|
|
if (Signature != "Gfx2")
|
|
throw new Exception($"Invalid signature {Signature}! Expected Gfx2.");
|
|
|
|
uint HeaderSize = reader.ReadUInt32();
|
|
MajorVersion = reader.ReadUInt32();
|
|
MinorVersion = reader.ReadUInt32();
|
|
GpuVersion = reader.ReadUInt32();
|
|
AlignMode = reader.ReadUInt32();
|
|
uint Reserved = reader.ReadUInt32();
|
|
uint Reserved2 = reader.ReadUInt32();
|
|
}
|
|
public void Write(FileWriter reader)
|
|
{
|
|
}
|
|
}
|
|
public class GTXDataBlock
|
|
{
|
|
public uint MajorVersion;
|
|
public uint MinorVersion;
|
|
public BlockType BlockType;
|
|
public uint Identifier;
|
|
public uint index;
|
|
|
|
public void Read(FileReader reader, GTXHeader header)
|
|
{
|
|
string Signature = reader.ReadString(4, Encoding.ASCII);
|
|
if (Signature != "BLK")
|
|
throw new Exception($"Invalid signature {Signature}! Expected BLK.");
|
|
uint HeaderSize = reader.ReadUInt32();
|
|
|
|
MajorVersion = reader.ReadUInt32(); //Must be 0x01 for 6.x.x
|
|
MinorVersion = reader.ReadUInt32(); //Must be 0x00 for 6.x.x
|
|
BlockType = reader.ReadEnum<BlockType>(false);
|
|
uint DataSize = reader.ReadUInt32();
|
|
Identifier = reader.ReadUInt32();
|
|
index = reader.ReadUInt32();
|
|
}
|
|
}
|
|
public class GTX
|
|
{
|
|
|
|
|
|
|
|
//From https://github.com/jam1garner/Smash-Forge/blob/master/Smash%20Forge/Filetypes/Textures/GTX.cs
|
|
//Todo. Add swizzling back
|
|
public struct GX2Surface
|
|
{
|
|
public int dim;
|
|
public int width;
|
|
public int height;
|
|
public int depth;
|
|
public int numMips;
|
|
public int format;
|
|
public int aa;
|
|
public int use;
|
|
public int resourceFlags;
|
|
public int imageSize;
|
|
public int imagePtr;
|
|
public int pMem;
|
|
public int mipSize;
|
|
public int mipPtr;
|
|
public int tileMode;
|
|
public int swizzle;
|
|
public int alignment;
|
|
public int pitch;
|
|
|
|
public byte[] data;
|
|
|
|
public int[] mipOffset;
|
|
};
|
|
|
|
public enum GX2SurfaceDimension
|
|
{
|
|
GX2_SURFACE_DIM_1D = 0x0,
|
|
GX2_SURFACE_DIM_2D = 0x1,
|
|
GX2_SURFACE_DIM_3D = 0x2,
|
|
GX2_SURFACE_DIM_CUBE = 0x3,
|
|
GX2_SURFACE_DIM_1D_ARRAY = 0x4,
|
|
GX2_SURFACE_DIM_2D_ARRAY = 0x5,
|
|
GX2_SURFACE_DIM_2D_MSAA = 0x6,
|
|
GX2_SURFACE_DIM_2D_MSAA_ARRAY = 0x7,
|
|
GX2_SURFACE_DIM_FIRST = 0x0,
|
|
GX2_SURFACE_DIM_LAST = 0x7,
|
|
};
|
|
public enum GX2SurfaceFormat
|
|
{
|
|
GX2_SURFACE_FORMAT_INVALID = 0x0,
|
|
GX2_SURFACE_FORMAT_TC_R8_UNORM = 0x1,
|
|
GX2_SURFACE_FORMAT_TC_R8_UINT = 0x101,
|
|
GX2_SURFACE_FORMAT_TC_R8_SNORM = 0x201,
|
|
GX2_SURFACE_FORMAT_TC_R8_SINT = 0x301,
|
|
GX2_SURFACE_FORMAT_T_R4_G4_UNORM = 0x2,
|
|
GX2_SURFACE_FORMAT_TCD_R16_UNORM = 0x5,
|
|
GX2_SURFACE_FORMAT_TC_R16_UINT = 0x105,
|
|
GX2_SURFACE_FORMAT_TC_R16_SNORM = 0x205,
|
|
GX2_SURFACE_FORMAT_TC_R16_SINT = 0x305,
|
|
GX2_SURFACE_FORMAT_TC_R16_FLOAT = 0x806,
|
|
GX2_SURFACE_FORMAT_TC_R8_G8_UNORM = 0x7,
|
|
GX2_SURFACE_FORMAT_TC_R8_G8_UINT = 0x107,
|
|
GX2_SURFACE_FORMAT_TC_R8_G8_SNORM = 0x207,
|
|
GX2_SURFACE_FORMAT_TC_R8_G8_SINT = 0x307,
|
|
GX2_SURFACE_FORMAT_TCS_R5_G6_B5_UNORM = 0x8,
|
|
GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM = 0xA,
|
|
GX2_SURFACE_FORMAT_TC_R4_G4_B4_A4_UNORM = 0xB,
|
|
GX2_SURFACE_FORMAT_TC_A1_B5_G5_R5_UNORM = 0xC,
|
|
GX2_SURFACE_FORMAT_TC_R32_UINT = 0x10D,
|
|
GX2_SURFACE_FORMAT_TC_R32_SINT = 0x30D,
|
|
GX2_SURFACE_FORMAT_TCD_R32_FLOAT = 0x80E,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_UNORM = 0xF,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_UINT = 0x10F,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_SNORM = 0x20F,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_SINT = 0x30F,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_FLOAT = 0x810,
|
|
GX2_SURFACE_FORMAT_D_D24_S8_UNORM = 0x11,
|
|
GX2_SURFACE_FORMAT_T_R24_UNORM_X8 = 0x11,
|
|
GX2_SURFACE_FORMAT_T_X24_G8_UINT = 0x111,
|
|
GX2_SURFACE_FORMAT_D_D24_S8_FLOAT = 0x811,
|
|
GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT = 0x816,
|
|
GX2_SURFACE_FORMAT_TCS_R10_G10_B10_A2_UNORM = 0x19,
|
|
GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_UINT = 0x119,
|
|
GX2_SURFACE_FORMAT_T_R10_G10_B10_A2_SNORM = 0x219,
|
|
GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SNORM = 0x219,
|
|
GX2_SURFACE_FORMAT_TC_R10_G10_B10_A2_SINT = 0x319,
|
|
GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM = 0x1A,
|
|
GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_UINT = 0x11A,
|
|
GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SNORM = 0x21A,
|
|
GX2_SURFACE_FORMAT_TC_R8_G8_B8_A8_SINT = 0x31A,
|
|
GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB = 0x41A,
|
|
GX2_SURFACE_FORMAT_TCS_A2_B10_G10_R10_UNORM = 0x1B,
|
|
GX2_SURFACE_FORMAT_TC_A2_B10_G10_R10_UINT = 0x11B,
|
|
GX2_SURFACE_FORMAT_D_D32_FLOAT_S8_UINT_X24 = 0x81C,
|
|
GX2_SURFACE_FORMAT_T_R32_FLOAT_X8_X24 = 0x81C,
|
|
GX2_SURFACE_FORMAT_T_X32_G8_UINT_X24 = 0x11C,
|
|
GX2_SURFACE_FORMAT_TC_R32_G32_UINT = 0x11D,
|
|
GX2_SURFACE_FORMAT_TC_R32_G32_SINT = 0x31D,
|
|
GX2_SURFACE_FORMAT_TC_R32_G32_FLOAT = 0x81E,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UNORM = 0x1F,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_UINT = 0x11F,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SNORM = 0x21F,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_SINT = 0x31F,
|
|
GX2_SURFACE_FORMAT_TC_R16_G16_B16_A16_FLOAT = 0x820,
|
|
GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_UINT = 0x122,
|
|
GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_SINT = 0x322,
|
|
GX2_SURFACE_FORMAT_TC_R32_G32_B32_A32_FLOAT = 0x823,
|
|
GX2_SURFACE_FORMAT_T_BC1_UNORM = 0x31,
|
|
GX2_SURFACE_FORMAT_T_BC1_SRGB = 0x431,
|
|
GX2_SURFACE_FORMAT_T_BC2_UNORM = 0x32,
|
|
GX2_SURFACE_FORMAT_T_BC2_SRGB = 0x432,
|
|
GX2_SURFACE_FORMAT_T_BC3_UNORM = 0x33,
|
|
GX2_SURFACE_FORMAT_T_BC3_SRGB = 0x433,
|
|
GX2_SURFACE_FORMAT_T_BC4_UNORM = 0x34,
|
|
GX2_SURFACE_FORMAT_T_BC4_SNORM = 0x234,
|
|
GX2_SURFACE_FORMAT_T_BC5_UNORM = 0x35,
|
|
GX2_SURFACE_FORMAT_T_BC5_SNORM = 0x235,
|
|
GX2_SURFACE_FORMAT_T_NV12_UNORM = 0x81,
|
|
GX2_SURFACE_FORMAT_FIRST = 0x1,
|
|
GX2_SURFACE_FORMAT_LAST = 0x83F,
|
|
};
|
|
public enum GX2AAMode
|
|
{
|
|
GX2_AA_MODE_1X = 0x0,
|
|
GX2_AA_MODE_2X = 0x1,
|
|
GX2_AA_MODE_4X = 0x2,
|
|
GX2_AA_MODE_8X = 0x3,
|
|
GX2_AA_MODE_FIRST = 0x0,
|
|
GX2_AA_MODE_LAST = 0x3,
|
|
};
|
|
public enum GX2SurfaceUse : uint
|
|
{
|
|
GX2_SURFACE_USE_TEXTURE = 0x1,
|
|
GX2_SURFACE_USE_COLOR_BUFFER = 0x2,
|
|
GX2_SURFACE_USE_DEPTH_BUFFER = 0x4,
|
|
GX2_SURFACE_USE_SCAN_BUFFER = 0x8,
|
|
GX2_SURFACE_USE_FTV = 0x80000000,
|
|
GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE = 0x3,
|
|
GX2_SURFACE_USE_DEPTH_BUFFER_TEXTURE = 0x5,
|
|
GX2_SURFACE_USE_COLOR_BUFFER_FTV = 0x80000002,
|
|
GX2_SURFACE_USE_COLOR_BUFFER_TEXTURE_FTV = 0x80000003,
|
|
GX2_SURFACE_USE_FIRST = 0x1,
|
|
GX2_SURFACE_USE_LAST = 0x8,
|
|
};
|
|
public enum GX2RResourceFlags
|
|
{
|
|
GX2R_RESOURCE_FLAGS_NONE = 0x0,
|
|
GX2R_BIND_NONE = 0x0,
|
|
GX2R_BIND_TEXTURE = 0x1,
|
|
GX2R_BIND_COLOR_BUFFER = 0x2,
|
|
GX2R_BIND_DEPTH_BUFFER = 0x4,
|
|
GX2R_BIND_SCAN_BUFFER = 0x8,
|
|
GX2R_BIND_VERTEX_BUFFER = 0x10,
|
|
GX2R_BIND_INDEX_BUFFER = 0x20,
|
|
GX2R_BIND_UNIFORM_BLOCK = 0x40,
|
|
GX2R_BIND_SHADER_PROGRAM = 0x80,
|
|
GX2R_BIND_STREAM_OUTPUT = 0x100,
|
|
GX2R_BIND_DISPLAY_LIST = 0x200,
|
|
GX2R_BIND_GS_RING = 0x400,
|
|
GX2R_USAGE_NONE = 0x0,
|
|
GX2R_USAGE_CPU_READ = 0x800,
|
|
GX2R_USAGE_CPU_WRITE = 0x1000,
|
|
GX2R_USAGE_GPU_READ = 0x2000,
|
|
GX2R_USAGE_GPU_WRITE = 0x4000,
|
|
GX2R_USAGE_DMA_READ = 0x8000,
|
|
GX2R_USAGE_DMA_WRITE = 0x10000,
|
|
GX2R_USAGE_FORCE_MEM1 = 0x20000,
|
|
GX2R_USAGE_FORCE_MEM2 = 0x40000,
|
|
GX2R_USAGE_MEM_DEFAULT = 0x0,
|
|
GX2R_USAGE_CPU_READWRITE = 0x1800,
|
|
GX2R_USAGE_GPU_READWRITE = 0x6000,
|
|
GX2R_USAGE_NON_CPU_WRITE = 0x14000,
|
|
GX2R_OPTION_NONE = 0x0,
|
|
GX2R_OPTION_IGNORE_IN_USE = 0x80000,
|
|
GX2R_OPTION_FIRST = 0x80000,
|
|
GX2R_OPTION_NO_CPU_INVALIDATE = 0x100000,
|
|
GX2R_OPTION_NO_GPU_INVALIDATE = 0x200000,
|
|
GX2R_OPTION_LOCK_READONLY = 0x400000,
|
|
GX2R_OPTION_NO_TOUCH_DESTROY = 0x800000,
|
|
GX2R_OPTION_LAST = 0x800000,
|
|
GX2R_OPTION_NO_INVALIDATE = 0x300000,
|
|
GX2R_OPTION_MASK = 0xF80000,
|
|
GX2R_RESOURCE_FLAG_RESERVED2 = 0x10000000,
|
|
GX2R_RESOURCE_FLAG_RESERVED1 = 0x20000000,
|
|
GX2R_RESOURCE_FLAG_RESERVED0 = 0x40000000,
|
|
};
|
|
public enum GX2TileMode
|
|
{
|
|
GX2_TILE_MODE_DEFAULT = 0x0,
|
|
GX2_TILE_MODE_LINEAR_SPECIAL = 0x10,
|
|
GX2_TILE_MODE_DEFAULT_FIX2197 = 0x20,
|
|
GX2_TILE_MODE_LINEAR_ALIGNED = 0x1,
|
|
GX2_TILE_MODE_1D_TILED_THIN1 = 0x2,
|
|
GX2_TILE_MODE_1D_TILED_THICK = 0x3,
|
|
GX2_TILE_MODE_2D_TILED_THIN1 = 0x4,
|
|
GX2_TILE_MODE_2D_TILED_THIN2 = 0x5,
|
|
GX2_TILE_MODE_2D_TILED_THIN4 = 0x6,
|
|
GX2_TILE_MODE_2D_TILED_THICK = 0x7,
|
|
GX2_TILE_MODE_2B_TILED_THIN1 = 0x8,
|
|
GX2_TILE_MODE_2B_TILED_THIN2 = 0x9,
|
|
GX2_TILE_MODE_2B_TILED_THIN4 = 0xA,
|
|
GX2_TILE_MODE_2B_TILED_THICK = 0xB,
|
|
GX2_TILE_MODE_3D_TILED_THIN1 = 0xC,
|
|
GX2_TILE_MODE_3D_TILED_THICK = 0xD,
|
|
GX2_TILE_MODE_3B_TILED_THIN1 = 0xE,
|
|
GX2_TILE_MODE_3B_TILED_THICK = 0xF,
|
|
GX2_TILE_MODE_FIRST = 0x0,
|
|
GX2_TILE_MODE_LAST = 0x20,
|
|
};
|
|
|
|
public enum AddrTileMode
|
|
{
|
|
ADDR_TM_LINEAR_GENERAL = 0x0,
|
|
ADDR_TM_LINEAR_ALIGNED = 0x1,
|
|
ADDR_TM_1D_TILED_THIN1 = 0x2,
|
|
ADDR_TM_1D_TILED_THICK = 0x3,
|
|
ADDR_TM_2D_TILED_THIN1 = 0x4,
|
|
ADDR_TM_2D_TILED_THIN2 = 0x5,
|
|
ADDR_TM_2D_TILED_THIN4 = 0x6,
|
|
ADDR_TM_2D_TILED_THICK = 0x7,
|
|
ADDR_TM_2B_TILED_THIN1 = 0x8,
|
|
ADDR_TM_2B_TILED_THIN2 = 0x9,
|
|
ADDR_TM_2B_TILED_THIN4 = 0x0A,
|
|
ADDR_TM_2B_TILED_THICK = 0x0B,
|
|
ADDR_TM_3D_TILED_THIN1 = 0x0C,
|
|
ADDR_TM_3D_TILED_THICK = 0x0D,
|
|
ADDR_TM_3B_TILED_THIN1 = 0x0E,
|
|
ADDR_TM_3B_TILED_THICK = 0x0F,
|
|
ADDR_TM_2D_TILED_XTHICK = 0x10,
|
|
ADDR_TM_3D_TILED_XTHICK = 0x11,
|
|
ADDR_TM_POWER_SAVE = 0x12,
|
|
ADDR_TM_COUNT = 0x13,
|
|
}
|
|
public enum AddrTileType
|
|
{
|
|
ADDR_DISPLAYABLE = 0,
|
|
ADDR_NON_DISPLAYABLE = 1,
|
|
ADDR_DEPTH_SAMPLE_ORDER = 2,
|
|
ADDR_THICK_TILING = 3,
|
|
}
|
|
public enum AddrPipeCfg
|
|
{
|
|
ADDR_PIPECFG_INVALID = 0x0,
|
|
ADDR_PIPECFG_P2 = 0x1,
|
|
ADDR_PIPECFG_P4_8x16 = 0x5,
|
|
ADDR_PIPECFG_P4_16x16 = 0x6,
|
|
ADDR_PIPECFG_P4_16x32 = 0x7,
|
|
ADDR_PIPECFG_P4_32x32 = 0x8,
|
|
ADDR_PIPECFG_P8_16x16_8x16 = 0x9,
|
|
ADDR_PIPECFG_P8_16x32_8x16 = 0xA,
|
|
ADDR_PIPECFG_P8_32x32_8x16 = 0xB,
|
|
ADDR_PIPECFG_P8_16x32_16x16 = 0xC,
|
|
ADDR_PIPECFG_P8_32x32_16x16 = 0xD,
|
|
ADDR_PIPECFG_P8_32x32_16x32 = 0xE,
|
|
ADDR_PIPECFG_P8_32x64_32x32 = 0xF,
|
|
ADDR_PIPECFG_MAX = 0x10,
|
|
}
|
|
public enum AddrFormat
|
|
{
|
|
ADDR_FMT_INVALID = 0x0,
|
|
ADDR_FMT_8 = 0x1,
|
|
ADDR_FMT_4_4 = 0x2,
|
|
ADDR_FMT_3_3_2 = 0x3,
|
|
ADDR_FMT_RESERVED_4 = 0x4,
|
|
ADDR_FMT_16 = 0x5,
|
|
ADDR_FMT_16_FLOAT = 0x6,
|
|
ADDR_FMT_8_8 = 0x7,
|
|
ADDR_FMT_5_6_5 = 0x8,
|
|
ADDR_FMT_6_5_5 = 0x9,
|
|
ADDR_FMT_1_5_5_5 = 0xA,
|
|
ADDR_FMT_4_4_4_4 = 0xB,
|
|
ADDR_FMT_5_5_5_1 = 0xC,
|
|
ADDR_FMT_32 = 0xD,
|
|
ADDR_FMT_32_FLOAT = 0xE,
|
|
ADDR_FMT_16_16 = 0xF,
|
|
ADDR_FMT_16_16_FLOAT = 0x10,
|
|
ADDR_FMT_8_24 = 0x11,
|
|
ADDR_FMT_8_24_FLOAT = 0x12,
|
|
ADDR_FMT_24_8 = 0x13,
|
|
ADDR_FMT_24_8_FLOAT = 0x14,
|
|
ADDR_FMT_10_11_11 = 0x15,
|
|
ADDR_FMT_10_11_11_FLOAT = 0x16,
|
|
ADDR_FMT_11_11_10 = 0x17,
|
|
ADDR_FMT_11_11_10_FLOAT = 0x18,
|
|
ADDR_FMT_2_10_10_10 = 0x19,
|
|
ADDR_FMT_8_8_8_8 = 0x1A,
|
|
ADDR_FMT_10_10_10_2 = 0x1B,
|
|
ADDR_FMT_X24_8_32_FLOAT = 0x1C,
|
|
ADDR_FMT_32_32 = 0x1D,
|
|
ADDR_FMT_32_32_FLOAT = 0x1E,
|
|
ADDR_FMT_16_16_16_16 = 0x1F,
|
|
ADDR_FMT_16_16_16_16_FLOAT = 0x20,
|
|
ADDR_FMT_RESERVED_33 = 0x21,
|
|
ADDR_FMT_32_32_32_32 = 0x22,
|
|
ADDR_FMT_32_32_32_32_FLOAT = 0x23,
|
|
ADDR_FMT_RESERVED_36 = 0x24,
|
|
ADDR_FMT_1 = 0x25,
|
|
ADDR_FMT_1_REVERSED = 0x26,
|
|
ADDR_FMT_GB_GR = 0x27,
|
|
ADDR_FMT_BG_RG = 0x28,
|
|
ADDR_FMT_32_AS_8 = 0x29,
|
|
ADDR_FMT_32_AS_8_8 = 0x2A,
|
|
ADDR_FMT_5_9_9_9_SHAREDEXP = 0x2B,
|
|
ADDR_FMT_8_8_8 = 0x2C,
|
|
ADDR_FMT_16_16_16 = 0x2D,
|
|
ADDR_FMT_16_16_16_FLOAT = 0x2E,
|
|
ADDR_FMT_32_32_32 = 0x2F,
|
|
ADDR_FMT_32_32_32_FLOAT = 0x30,
|
|
ADDR_FMT_BC1 = 0x31,
|
|
ADDR_FMT_BC2 = 0x32,
|
|
ADDR_FMT_BC3 = 0x33,
|
|
ADDR_FMT_BC4 = 0x34,
|
|
ADDR_FMT_BC5 = 0x35,
|
|
ADDR_FMT_BC6 = 0x36,
|
|
ADDR_FMT_BC7 = 0x37,
|
|
ADDR_FMT_32_AS_32_32_32_32 = 0x38,
|
|
ADDR_FMT_APC3 = 0x39,
|
|
ADDR_FMT_APC4 = 0x3A,
|
|
ADDR_FMT_APC5 = 0x3B,
|
|
ADDR_FMT_APC6 = 0x3C,
|
|
ADDR_FMT_APC7 = 0x3D,
|
|
ADDR_FMT_CTX1 = 0x3E,
|
|
ADDR_FMT_RESERVED_63 = 0x3F,
|
|
};
|
|
|
|
private static byte[] formatHwInfo = {
|
|
0x00, 0x00, 0x00, 0x01, 0x08, 0x03, 0x00, 0x01, 0x08, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
|
|
0x00, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00, 0x10, 0x03, 0x00, 0x01, 0x10, 0x03, 0x00, 0x01,
|
|
0x10, 0x0B, 0x00, 0x01, 0x10, 0x01, 0x00, 0x01, 0x10, 0x03, 0x00, 0x01, 0x10, 0x03, 0x00, 0x01,
|
|
0x10, 0x03, 0x00, 0x01, 0x20, 0x03, 0x00, 0x00, 0x20, 0x07, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00,
|
|
0x20, 0x03, 0x00, 0x01, 0x20, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
|
|
0x00, 0x00, 0x00, 0x01, 0x20, 0x0B, 0x00, 0x01, 0x20, 0x0B, 0x00, 0x01, 0x20, 0x0B, 0x00, 0x01,
|
|
0x40, 0x05, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00,
|
|
0x40, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00,
|
|
0x10, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
|
|
0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
|
|
0x60, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x01, 0x80, 0x01, 0x00, 0x01, 0x80, 0x01, 0x00, 0x01,
|
|
0x40, 0x01, 0x00, 0x01, 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
|
|
|
|
|
|
|
|
/*---------------------------------------
|
|
*
|
|
* Code ported from AboodXD's GTX Extractor https://github.com/aboood40091/GTX-Extractor/blob/master/gtx_extract.py
|
|
*
|
|
* With help by Aelan!
|
|
*
|
|
*---------------------------------------*/
|
|
|
|
/*var s_textureFormats[] = {
|
|
// internalFormat, gxFormat, glFormat, fourCC, nutFormat, name, bpp, compressed
|
|
{ FORMAT_RGBA_8888, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GL_RGBA8, 0x00000000, 0x11, "RGBA_8888", 0x20, 0 },
|
|
{ FORMAT_ABGR_8888, GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM, GL_RGBA8, 0x00000000, 0x0E, "ABGR_8888 (WIP)", 0x20, 0 },
|
|
{ FORMAT_DXT1, GX2_SURFACE_FORMAT_T_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0x31545844, 0x00, "DXT1", 0x40, 1 },
|
|
{ FORMAT_DXT3, GX2_SURFACE_FORMAT_T_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0x33545844, 0x01, "DXT3", 0x80, 1 },
|
|
{ FORMAT_DXT5, GX2_SURFACE_FORMAT_T_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0x35545844, 0x02, "DXT5", 0x80, 1 },
|
|
{ FORMAT_ATI1, GX2_SURFACE_FORMAT_T_BC4_UNORM, GL_COMPRESSED_RED_RGTC1, 0x31495441, 0x15, "ATI1", 0x40, 1 },
|
|
{ FORMAT_ATI2, GX2_SURFACE_FORMAT_T_BC5_UNORM, GL_COMPRESSED_RG_RGTC2, 0x32495441, 0x16, "ATI2", 0x80, 1 },
|
|
{ FORMAT_INVALID, GX2_SURFACE_FORMAT_INVALID, 0, 0xFFFFFFFF, 0x00, nullptr, 0x00, 0 }
|
|
};*/
|
|
|
|
|
|
public static byte[] swizzleBC(byte[] data, int width, int height, int format, int tileMode, int pitch, int swizzle)
|
|
{
|
|
GX2Surface sur = new GX2Surface();
|
|
sur.width = width;
|
|
sur.height = height;
|
|
sur.tileMode = tileMode;
|
|
sur.format = format;
|
|
sur.swizzle = swizzle;
|
|
sur.pitch = pitch;
|
|
sur.data = data;
|
|
sur.imageSize = data.Length;
|
|
//return swizzleBC(sur);
|
|
return swizzleSurface(sur, (GX2SurfaceFormat)sur.format != GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM &
|
|
(GX2SurfaceFormat)sur.format != GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_SRGB);
|
|
}
|
|
|
|
public static int getBPP(int i)
|
|
{
|
|
switch ((GX2SurfaceFormat)i)
|
|
{
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM:
|
|
return 0x10;
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_TCS_R8_G8_B8_A8_UNORM:
|
|
return 0x20;
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM:
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM:
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB:
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM:
|
|
return 0x40;
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_UNORM:
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_UNORM:
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_UNORM:
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC2_SRGB:
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC3_SRGB:
|
|
case GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC5_SNORM:
|
|
return 0x80;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public static byte[] swizzleSurface(GX2Surface surface, bool isCompressed)
|
|
{
|
|
byte[] original = new byte[surface.data.Length];
|
|
|
|
surface.data.CopyTo(original, 0);
|
|
|
|
int swizzle = ((surface.swizzle >> 8) & 1) + (((surface.swizzle >> 9) & 3) << 1);
|
|
int blockSize;
|
|
int width = surface.width;
|
|
int height = surface.height;
|
|
|
|
int format = getBPP(surface.format);
|
|
Console.WriteLine(((GX2SurfaceFormat)surface.format).ToString());
|
|
|
|
if (isCompressed)
|
|
{
|
|
width /= 4;
|
|
height /= 4;
|
|
|
|
if ((GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_UNORM ||
|
|
(GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC1_SRGB ||
|
|
(GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_UNORM ||
|
|
(GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_T_BC4_SNORM)
|
|
{
|
|
blockSize = 8;
|
|
}
|
|
else
|
|
{
|
|
blockSize = 16;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*if ((GX2SurfaceFormat)surface.format == GX2SurfaceFormat.GX2_SURFACE_FORMAT_TC_R5_G5_B5_A1_UNORM)
|
|
{
|
|
blockSize = format / 4;
|
|
}
|
|
else*/
|
|
blockSize = format / 8;
|
|
}
|
|
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int pos = surfaceAddrFromCoordMacroTiled(x, y, format, surface.pitch, swizzle);
|
|
int pos_ = (y * width + x) * blockSize;
|
|
|
|
for (int k = 0; k < blockSize; k++)
|
|
{
|
|
if (pos + k >= original.Length || pos_ + k >= surface.data.Length)
|
|
{
|
|
Console.WriteLine("Break Point " + pos_ + " " + pos);
|
|
break;
|
|
}
|
|
surface.data[pos_ + k] = original[pos + k];
|
|
}
|
|
}
|
|
}
|
|
return surface.data;
|
|
}
|
|
|
|
public static int surfaceAddrFromCoordMacroTiled(int x, int y, int bpp, int pitch, int swizzle)
|
|
{
|
|
int pixelIndex = computePixelIndexWithinMicroTile(x, y, bpp);
|
|
int elemOffset = (bpp * pixelIndex) >> 3;
|
|
|
|
int pipe = computePipeFromCoordWoRotation(x, y);
|
|
int bank = computeBankFromCoordWoRotation(x, y);
|
|
int bankPipe = ((pipe + 2 * bank) ^ swizzle) % 9;
|
|
|
|
pipe = bankPipe % 2;
|
|
bank = bankPipe / 2;
|
|
|
|
int macroTileBytes = (bpp * 512 + 7) >> 3;
|
|
int macroTileOffset = (x / 32 + pitch / 32 * (y / 16)) * macroTileBytes;
|
|
|
|
int unk1 = elemOffset + (macroTileOffset >> 3);
|
|
int unk2 = unk1 & ~0xFF;
|
|
|
|
return (unk2 << 3) | (0xFF & unk1) | (pipe << 8) | (bank << 9);
|
|
}
|
|
|
|
public static int computePixelIndexWithinMicroTile(int x, int y, int bpp)
|
|
{
|
|
int bits = ((x & 4) << 1) | ((y & 2) << 3) | ((y & 4) << 3);
|
|
|
|
if (bpp == 0x20 || bpp == 0x60)
|
|
{
|
|
bits |= (x & 1) | (x & 2) | ((y & 1) << 2);
|
|
}
|
|
else if (bpp == 0x40)
|
|
{
|
|
bits |= (x & 1) | ((y & 1) << 1) | ((x & 2) << 1);
|
|
}
|
|
else if (bpp == 0x80)
|
|
{
|
|
bits |= (y & 1) | ((x & 1) << 1) | ((x & 2) << 1);
|
|
}
|
|
|
|
return bits;
|
|
}
|
|
|
|
public static int getFormatBpp(int format)
|
|
{
|
|
int hwFormat = format & 0x3F;
|
|
return formatHwInfo[hwFormat * 4];
|
|
}
|
|
|
|
public static int computeSurfaceThickness(AddrTileMode tileMode)
|
|
{
|
|
switch (tileMode)
|
|
{
|
|
case AddrTileMode.ADDR_TM_1D_TILED_THICK:
|
|
case AddrTileMode.ADDR_TM_2D_TILED_THICK:
|
|
case AddrTileMode.ADDR_TM_2B_TILED_THICK:
|
|
case AddrTileMode.ADDR_TM_3D_TILED_THICK:
|
|
case AddrTileMode.ADDR_TM_3B_TILED_THICK:
|
|
{
|
|
return 4;
|
|
}
|
|
case AddrTileMode.ADDR_TM_2D_TILED_XTHICK:
|
|
case AddrTileMode.ADDR_TM_3D_TILED_XTHICK:
|
|
{
|
|
return 8;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
public static int isThickMacroTiled(AddrTileMode tileMode)
|
|
{
|
|
switch (tileMode)
|
|
{
|
|
case AddrTileMode.ADDR_TM_2D_TILED_THICK:
|
|
case AddrTileMode.ADDR_TM_2B_TILED_THICK:
|
|
case AddrTileMode.ADDR_TM_3D_TILED_THICK:
|
|
case AddrTileMode.ADDR_TM_3B_TILED_THICK:
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static int isBankSwappedTileMode(AddrTileMode tileMode)
|
|
{
|
|
switch (tileMode)
|
|
{
|
|
case AddrTileMode.ADDR_TM_2B_TILED_THIN1:
|
|
case AddrTileMode.ADDR_TM_2B_TILED_THIN2:
|
|
case AddrTileMode.ADDR_TM_2B_TILED_THIN4:
|
|
case AddrTileMode.ADDR_TM_2B_TILED_THICK:
|
|
case AddrTileMode.ADDR_TM_3B_TILED_THIN1:
|
|
case AddrTileMode.ADDR_TM_3B_TILED_THICK:
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public static int computeSurfaceRotationFromTileMode(AddrTileMode tileMode)
|
|
{
|
|
switch ((int)tileMode)
|
|
{
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
{
|
|
return 2;
|
|
}
|
|
case 12:
|
|
case 13:
|
|
case 14:
|
|
case 15:
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static int computePipeFromCoordWoRotation(int x, int y)
|
|
{
|
|
int pipe = ((y >> 3) ^ (x >> 3)) & 1;
|
|
return pipe;
|
|
}
|
|
|
|
public static int computeBankFromCoordWoRotation(int x, int y)
|
|
{
|
|
int bankBit0 = ((y / (16 * 2)) ^ (x >> 3)) & 1;
|
|
int bank = bankBit0 | 2 * (((y / (8 * 2)) ^ (x >> 4)) & 1);
|
|
|
|
return bank;
|
|
}
|
|
|
|
public static int computeMacroTileAspectRatio(AddrTileMode tileMode)
|
|
{
|
|
switch (tileMode)
|
|
{
|
|
case AddrTileMode.ADDR_TM_2B_TILED_THIN1:
|
|
case AddrTileMode.ADDR_TM_3D_TILED_THIN1:
|
|
case AddrTileMode.ADDR_TM_3B_TILED_THIN1:
|
|
{
|
|
return 1;
|
|
}
|
|
case AddrTileMode.ADDR_TM_2D_TILED_THIN2:
|
|
case AddrTileMode.ADDR_TM_2B_TILED_THIN2:
|
|
{
|
|
return 2;
|
|
}
|
|
case AddrTileMode.ADDR_TM_2D_TILED_THIN4:
|
|
case AddrTileMode.ADDR_TM_2B_TILED_THIN4:
|
|
{
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
public static int computeSurfaceBankSwappedWidth(AddrTileMode tileMode, int bpp, int numSamples, int pitch, int pSlicesPerTile)
|
|
{
|
|
int bankSwapWidth = 0;
|
|
int numBanks = 4;
|
|
int numPipes = 2;
|
|
int swapSize = 256;
|
|
int rowSize = 2048;
|
|
int splitSize = 2048;
|
|
int groupSize = 256;
|
|
int slicesPerTile = 1;
|
|
int bytesPerSample = 8 * bpp & 0x1FFFFFFF;
|
|
int samplesPerTile = splitSize / bytesPerSample;
|
|
|
|
if ((splitSize / bytesPerSample) != 0)
|
|
{
|
|
slicesPerTile = numSamples / samplesPerTile;
|
|
if ((numSamples / samplesPerTile) == 0)
|
|
{
|
|
slicesPerTile = 1;
|
|
}
|
|
}
|
|
|
|
if (pSlicesPerTile != 0)
|
|
{
|
|
pSlicesPerTile = slicesPerTile;
|
|
}
|
|
|
|
if (isThickMacroTiled(tileMode) == 1)
|
|
{
|
|
numSamples = 4;
|
|
}
|
|
|
|
int bytesPerTileSlice = numSamples * bytesPerSample / slicesPerTile;
|
|
|
|
if (isBankSwappedTileMode(tileMode) == 1)
|
|
{
|
|
int v7;
|
|
int v8;
|
|
int v9;
|
|
|
|
int factor = computeMacroTileAspectRatio(tileMode);
|
|
int swapTiles = (swapSize >> 1) / bpp;
|
|
|
|
if (swapTiles != 0)
|
|
{
|
|
v9 = swapTiles;
|
|
}
|
|
else
|
|
{
|
|
v9 = 1;
|
|
}
|
|
|
|
int swapWidth = v9 * 8 * numBanks;
|
|
int heightBytes = numSamples * factor * numPipes * bpp / slicesPerTile;
|
|
int swapMax = numPipes * numBanks * rowSize / heightBytes;
|
|
int swapMin = groupSize * 8 * numBanks / bytesPerTileSlice;
|
|
|
|
if (swapMax >= swapWidth)
|
|
{
|
|
if (swapMin <= swapWidth)
|
|
{
|
|
v7 = swapWidth;
|
|
}
|
|
else
|
|
{
|
|
v7 = swapMin;
|
|
}
|
|
|
|
v8 = v7;
|
|
}
|
|
else
|
|
{
|
|
v8 = swapMax;
|
|
}
|
|
|
|
bankSwapWidth = v8;
|
|
|
|
while (bankSwapWidth >= (2 * pitch))
|
|
{
|
|
bankSwapWidth >>= 1;
|
|
}
|
|
}
|
|
|
|
return bankSwapWidth;
|
|
}
|
|
|
|
public static int computePixelIndexWithinMicroTile(int x, int y, int z, int bpp, AddrTileMode tileMode, int microTileType)
|
|
{
|
|
int pixelBit0 = 0;
|
|
int pixelBit1 = 0;
|
|
int pixelBit2 = 0;
|
|
int pixelBit3 = 0;
|
|
int pixelBit4 = 0;
|
|
int pixelBit5 = 0;
|
|
int pixelBit6 = 0;
|
|
int pixelBit7 = 0;
|
|
int pixelBit8 = 0;
|
|
int thickness = computeSurfaceThickness(tileMode);
|
|
|
|
if (microTileType == 3)
|
|
{
|
|
pixelBit0 = x & 1;
|
|
pixelBit1 = y & 1;
|
|
pixelBit2 = z & 1;
|
|
pixelBit3 = (x & 2) >> 1;
|
|
pixelBit4 = (y & 2) >> 1;
|
|
pixelBit5 = (z & 2) >> 1;
|
|
pixelBit6 = (x & 4) >> 2;
|
|
pixelBit7 = (y & 4) >> 2;
|
|
}
|
|
else
|
|
{
|
|
if (microTileType != 0)
|
|
{
|
|
pixelBit0 = x & 1;
|
|
pixelBit1 = y & 1;
|
|
pixelBit2 = (x & 2) >> 1;
|
|
pixelBit3 = (y & 2) >> 1;
|
|
pixelBit4 = (x & 4) >> 2;
|
|
pixelBit5 = (y & 4) >> 2;
|
|
}
|
|
else
|
|
{
|
|
if (bpp == 0x08)
|
|
{
|
|
pixelBit0 = x & 1;
|
|
pixelBit1 = (x & 2) >> 1;
|
|
pixelBit2 = (x & 4) >> 2;
|
|
pixelBit3 = (y & 2) >> 1;
|
|
pixelBit4 = y & 1;
|
|
pixelBit5 = (y & 4) >> 2;
|
|
}
|
|
else if (bpp == 0x10)
|
|
{
|
|
pixelBit0 = x & 1;
|
|
pixelBit1 = (x & 2) >> 1;
|
|
pixelBit2 = (x & 4) >> 2;
|
|
pixelBit3 = y & 1;
|
|
pixelBit4 = (y & 2) >> 1;
|
|
pixelBit5 = (y & 4) >> 2;
|
|
}
|
|
else if (bpp == 0x20 || bpp == 0x60)
|
|
{
|
|
pixelBit0 = x & 1;
|
|
pixelBit1 = (x & 2) >> 1;
|
|
pixelBit2 = y & 1;
|
|
pixelBit3 = (x & 4) >> 2;
|
|
pixelBit4 = (y & 2) >> 1;
|
|
pixelBit5 = (y & 4) >> 2;
|
|
}
|
|
else if (bpp == 0x40)
|
|
{
|
|
pixelBit0 = x & 1;
|
|
pixelBit1 = y & 1;
|
|
pixelBit2 = (x & 2) >> 1;
|
|
pixelBit3 = (x & 4) >> 2;
|
|
pixelBit4 = (y & 2) >> 1;
|
|
pixelBit5 = (y & 4) >> 2;
|
|
}
|
|
else if (bpp == 0x80)
|
|
{
|
|
pixelBit0 = y & 1;
|
|
pixelBit1 = x & 1;
|
|
pixelBit2 = (x & 2) >> 1;
|
|
pixelBit3 = (x & 4) >> 2;
|
|
pixelBit4 = (y & 2) >> 1;
|
|
pixelBit5 = (y & 4) >> 2;
|
|
}
|
|
else
|
|
{
|
|
pixelBit0 = x & 1;
|
|
pixelBit1 = (x & 2) >> 1;
|
|
pixelBit2 = y & 1;
|
|
pixelBit3 = (x & 4) >> 2;
|
|
pixelBit4 = (y & 2) >> 1;
|
|
pixelBit5 = (y & 4) >> 2;
|
|
}
|
|
}
|
|
|
|
if (thickness > 1)
|
|
{
|
|
pixelBit6 = z & 1;
|
|
pixelBit7 = (z & 2) >> 1;
|
|
}
|
|
}
|
|
|
|
if (thickness == 8)
|
|
{
|
|
pixelBit8 = (z & 4) >> 2;
|
|
}
|
|
|
|
return pixelBit0 |
|
|
(pixelBit8 << 8) |
|
|
(pixelBit7 << 7) |
|
|
(pixelBit6 << 6) |
|
|
(pixelBit5 << 5) |
|
|
(pixelBit4 << 4) |
|
|
(pixelBit3 << 3) |
|
|
(pixelBit2 << 2) |
|
|
(pixelBit1 << 1);
|
|
}
|
|
|
|
public static int surfaceAddrFromCoordMacroTiled(
|
|
int x, int y, int slice, int sample, int bpp,
|
|
int pitch, int height, int numSamples, AddrTileMode tileMode,
|
|
int isDepth, int tileBase, int compBits,
|
|
int pipeSwizzle, int bankSwizzle
|
|
)
|
|
{
|
|
const int numPipes = 2;
|
|
const int numBanks = 4;
|
|
const int numGroupBits = 8;
|
|
const int numPipeBits = 1;
|
|
const int numBankBits = 2;
|
|
|
|
int microTileThickness = computeSurfaceThickness(tileMode);
|
|
int microTileBits = numSamples * bpp * (microTileThickness * (8 * 8));
|
|
int microTileBytes = microTileBits >> 3;
|
|
int microTileType = (isDepth == 1) ? 1 : 0;
|
|
int pixelIndex = computePixelIndexWithinMicroTile(x, y, slice, bpp, tileMode, microTileType);
|
|
|
|
int sampleOffset;
|
|
int pixelOffset;
|
|
if (isDepth == 1)
|
|
{
|
|
if (compBits != 0 && compBits != bpp)
|
|
{
|
|
sampleOffset = tileBase + compBits * sample;
|
|
pixelOffset = numSamples * compBits * pixelIndex;
|
|
}
|
|
else
|
|
{
|
|
sampleOffset = bpp * sample;
|
|
pixelOffset = numSamples * compBits * pixelIndex;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sampleOffset = sample * (microTileBits / numSamples);
|
|
pixelOffset = bpp * pixelIndex;
|
|
}
|
|
|
|
int elemOffset = pixelOffset + sampleOffset;
|
|
int bytesPerSample = microTileBytes / numSamples;
|
|
|
|
int samplesPerSlice;
|
|
int numSampleSplits;
|
|
int sampleSlice;
|
|
|
|
if (numSamples <= 1 || microTileBytes <= 2048)
|
|
{
|
|
samplesPerSlice = numSamples;
|
|
numSampleSplits = 1;
|
|
sampleSlice = 0;
|
|
}
|
|
else
|
|
{
|
|
samplesPerSlice = 2048 / bytesPerSample;
|
|
numSampleSplits = numSamples / samplesPerSlice;
|
|
numSamples = samplesPerSlice;
|
|
sampleSlice = elemOffset / (microTileBits / numSampleSplits);
|
|
elemOffset %= microTileBits / numSampleSplits;
|
|
}
|
|
|
|
elemOffset >>= 3;
|
|
|
|
int pipe = computePipeFromCoordWoRotation(x, y);
|
|
int bank = computeBankFromCoordWoRotation(x, y);
|
|
int bankPipe = pipe + numPipes * bank;
|
|
int rotation = computeSurfaceRotationFromTileMode(tileMode);
|
|
int swizzle = pipeSwizzle + numPipes * bankSwizzle;
|
|
int sliceIn = slice;
|
|
|
|
if (isThickMacroTiled(tileMode) == 1)
|
|
{
|
|
sliceIn >>= 2;
|
|
}
|
|
|
|
bankPipe ^= numPipes * sampleSlice * ((numBanks >> 1) + 1) ^ (swizzle + sliceIn * rotation);
|
|
bankPipe %= numPipes * numBanks;
|
|
pipe = bankPipe % numPipes;
|
|
bank = bankPipe / numPipes;
|
|
|
|
int sliceBytes = (height * pitch * microTileThickness * bpp * numSamples + 7) / 8;
|
|
int sliceOffset = sliceBytes * ((sampleSlice + numSampleSplits * slice) / microTileThickness);
|
|
int macroTilePitch = 8 * 4; // m_banks
|
|
int macroTileHeight = 8 * 2; // m_pipes
|
|
int v18 = (int)tileMode - 5;
|
|
|
|
if ((int)tileMode == 5 || (int)tileMode == 9)
|
|
{
|
|
macroTilePitch >>= 1;
|
|
macroTileHeight *= 2;
|
|
}
|
|
else if ((int)tileMode == 6 || (int)tileMode == 10)
|
|
{
|
|
macroTilePitch >>= 2;
|
|
macroTileHeight *= 4;
|
|
}
|
|
|
|
int macroTilesPerRow = pitch / macroTilePitch;
|
|
int macroTileBytes = (numSamples * microTileThickness * bpp * macroTileHeight * macroTilePitch + 7) >> 3;
|
|
int macroTileIndexX = x / macroTilePitch;
|
|
int macroTileIndexY = y / macroTileHeight;
|
|
int macroTileOffset = (x / macroTilePitch + pitch / macroTilePitch * (y / macroTileHeight)) * macroTileBytes;
|
|
|
|
int bankSwapWidth;
|
|
int swapIndex;
|
|
int bankMask;
|
|
|
|
byte[] bankSwapOrder = { 0, 1, 3, 2 };
|
|
switch ((int)tileMode)
|
|
{
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
case 11:
|
|
case 14:
|
|
case 15:
|
|
{
|
|
bankSwapWidth = computeSurfaceBankSwappedWidth(tileMode, bpp, numSamples, pitch, 0);
|
|
swapIndex = macroTilePitch * macroTileIndexX / bankSwapWidth;
|
|
bankMask = 3; // m_banks-1
|
|
bank ^= bankSwapOrder[swapIndex & bankMask];
|
|
}
|
|
break;
|
|
}
|
|
|
|
int p4 = pipe << numGroupBits;
|
|
int p5 = bank << (numPipeBits + numGroupBits);
|
|
int numSwizzleBits = numBankBits + numPipeBits;
|
|
int unk1 = (macroTileOffset + sliceOffset) >> numSwizzleBits;
|
|
int unk2 = ~((1 << numGroupBits) - 1);
|
|
int unk3 = (elemOffset + unk1) & unk2;
|
|
int groupMask = (1 << numGroupBits) - 1;
|
|
int offset1 = macroTileOffset + sliceOffset;
|
|
int unk4 = elemOffset + (offset1 >> numSwizzleBits);
|
|
|
|
int subOffset1 = unk3 << numSwizzleBits;
|
|
int subOffset2 = groupMask & unk4;
|
|
|
|
return subOffset1 | subOffset2 | p4 | p5;
|
|
}
|
|
|
|
public static byte[] swizzleBC(GX2Surface surface)
|
|
{
|
|
//std::vector<u8> result;
|
|
//List<byte> result = new List<byte>();
|
|
|
|
//result.resize(surface->imageSize);
|
|
|
|
//u8 *data = (u8*)surface->imagePtr;
|
|
byte[] data = surface.data;
|
|
byte[] result = new byte[surface.imageSize];
|
|
|
|
int width = surface.width / 4;
|
|
int height = surface.height / 4;
|
|
|
|
for (int y = 0; y < height; ++y)
|
|
{
|
|
for (int x = 0; x < width; ++x)
|
|
{
|
|
int bpp = getFormatBpp(surface.format);
|
|
int pos = 0;
|
|
|
|
switch (surface.tileMode)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
{
|
|
// pos = surfaceAddrFromCoordLinear(
|
|
// x, y, 0, 0, bpp,
|
|
// surface->pitch, height, surface->depth, 0
|
|
// );
|
|
|
|
//printf("Unsupported tilemode %d\n", surface->tileMode);
|
|
//exit(1);
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
case 3:
|
|
{
|
|
// pos = surfaceAddrFromCoordMicroTiled(
|
|
// x, y, 0, bpp, surface->pitch, height,
|
|
// surface->tileMode, 0, 0, 0, 0
|
|
// );
|
|
|
|
//printf("Unsupported tilemode %d\n", surface->tileMode);
|
|
//exit(1);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
pos = surfaceAddrFromCoordMacroTiled(
|
|
x, y, 0, 0, bpp, surface.pitch, height,
|
|
1, (AddrTileMode)surface.tileMode, 0, 0, 0,
|
|
(surface.swizzle >> 8) & 1,
|
|
(surface.swizzle >> 9) & 3
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
|
|
int q = y * width + x;
|
|
switch (surface.format)
|
|
{
|
|
case 0x31:
|
|
case 0x34:
|
|
case 0x234:
|
|
case 0x431:
|
|
{
|
|
System.Array.Copy(data, pos, result, q * 8, 8);
|
|
//memcpy(result.data() + q*8, data+pos, 8);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
{
|
|
System.Array.Copy(data, pos, result, q * 16, 16);
|
|
//memcpy(result.data() + q*16, data+pos, 16);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
|
|
//memcpy(data, result.data(), result.size());
|
|
}
|
|
}
|
|
}
|