Skip to content

Commit

Permalink
Fixed reading small mip maps.
Browse files Browse the repository at this point in the history
  • Loading branch information
Atvaark committed May 15, 2016
1 parent ecc2c97 commit 48302bb
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 97 deletions.
10 changes: 5 additions & 5 deletions FtexTool/Dds/DdsPixelFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,14 @@ public static DdsPixelFormat DdsLuminance()
public static int CalculateImageSize(DdsPixelFormat pixelFormat, int width, int height)
{
if (pixelFormat.RgbBitCount > 0)
return (width*height*pixelFormat.RgbBitCount)/8;
return (width * height * pixelFormat.RgbBitCount) / 8;
if (pixelFormat.Equals(DdsPfDxt1()))
return ((width*height*32)/8)/8;
return width * height / 2; // ((width*height*32)/8)/8;
if (pixelFormat.Equals(DdsPfDxt3()))
return ((width*height*32)/4)/8;
return width * height; // ((width*height*32)/4)/8;
if (pixelFormat.Equals(DdsPfDxt5()))
return ((width*height*32)/4)/8;
throw new NotImplementedException("Could not calculate the image size of the current pixel format.");
return width * height; // ((width*height*32)/4)/8;
throw new ArgumentException("Could not calculate the image size of the current pixel format.");
}

public static int GetMinimumImageSize(DdsPixelFormat pixelFormat)
Expand Down
17 changes: 15 additions & 2 deletions FtexTool/ExtensionMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,25 @@ internal static void Assert<T>(this BinaryReader reader, T expected, string mess

private static T ReadValue<T>(BinaryReader reader) where T : struct
{
int size = SizeOf(typeof (T));
int size = SizeOf(typeof(T));
byte[] data = reader.ReadBytes(size);
T actual = ByteArrayToStructure<T>(data);
return actual;
}

internal static int Align(this BinaryWriter writer, int alignment)
{
int alignmentRequired = (int)(writer.BaseStream.Position % alignment);
if (alignmentRequired > 0)
{
int bytesToAdd = alignment - alignmentRequired;
writer.BaseStream.Position += bytesToAdd;
return bytesToAdd;
}

return 0;
}

internal static int SizeOf(this Type type)
{
return Marshal.SizeOf(type);
Expand All @@ -41,7 +54,7 @@ internal static int SizeOf(this Type type)
private static T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
T stuff = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof (T));
T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return stuff;
}
Expand Down
12 changes: 7 additions & 5 deletions FtexTool/Ftex/FtexFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ namespace FtexTool.Ftex
public class FtexFile
{
private const long MagicNumber1 = 4612226451348214854; // FTEX 85 EB 01 40
private const int MagicNumber2 = 0x01000001;
private const int OneInt32 = 1;
private const int ZeroInt32 = 0;
private const byte OneByte = 1;
private const byte ZeroByte = 0;
private readonly Dictionary<int, FtexsFile> _ftexsFiles;
private readonly List<FtexFileMipMapInfo> _mipMapInfos;
Expand All @@ -36,7 +34,9 @@ public FtexFile()
// 0x2 else
public byte NrtFlag { get; set; }
// Flags
// 0 or 17
// 0 (~3%)
// 17 (<1%)
// 273 (~96%)
public short UnknownFlags { get; set; }
public FtexTextureType TextureType { get; set; }
public byte FtexsFileCount { get; set; }
Expand Down Expand Up @@ -171,9 +171,11 @@ public void UpdateOffsets()
foreach (var ftexsFileMipMap in ftexsFile.MipMaps)
{
FtexFileMipMapInfo ftexMipMapInfo = MipMapInfos.ElementAt(mipMapIndex);
ftexMipMapInfo.CompressedFileSize = ftexsFileMipMap.CompressedDataSize;
ftexMipMapInfo.Size = ftexsFileMipMap.IndexBlockSize
+ ftexsFileMipMap.CompressedDataSize
+ ftexsFileMipMap.Alignment;
ftexMipMapInfo.ChunkCount = Convert.ToInt16(ftexsFileMipMap.Chunks.Count());
ftexMipMapInfo.Offset = ftexsFileMipMap.Offset;
ftexMipMapInfo.Offset = (int) ftexsFileMipMap.Offset;
++mipMapIndex;
}
}
Expand Down
6 changes: 3 additions & 3 deletions FtexTool/Ftex/FtexFileMipMapInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class FtexFileMipMapInfo
{
public int Offset { get; set; }
public int DecompressedFileSize { get; set; }
public int CompressedFileSize { get; set; }
public int Size { get; set; }
public byte Index { get; set; }
public byte FtexsFileNumber { get; set; }
public short ChunkCount { get; set; }
Expand All @@ -24,7 +24,7 @@ public void Read(Stream inputStream)
BinaryReader reader = new BinaryReader(inputStream, Encoding.Default, true);
Offset = reader.ReadInt32();
DecompressedFileSize = reader.ReadInt32();
CompressedFileSize = reader.ReadInt32();
Size = reader.ReadInt32();
Index = reader.ReadByte();
FtexsFileNumber = reader.ReadByte();
ChunkCount = reader.ReadInt16();
Expand All @@ -35,7 +35,7 @@ public void Write(Stream outputStream)
BinaryWriter writer = new BinaryWriter(outputStream, Encoding.Default, true);
writer.Write(Offset);
writer.Write(DecompressedFileSize);
writer.Write(CompressedFileSize);
writer.Write(Size);
writer.Write(Index);
writer.Write(FtexsFileNumber);
writer.Write(ChunkCount);
Expand Down
19 changes: 9 additions & 10 deletions FtexTool/FtexDdsConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public static DdsFile ConvertToDds(FtexFile file)
result.Header.PixelFormat = DdsPixelFormat.DdsPfDxt5();
break;
default:
throw new NotImplementedException(String.Format("Unknown PixelFormatType {0}", file.PixelFormatType));
throw new ArgumentException($"Unknown PixelFormatType {file.PixelFormatType}");
}

result.Data = file.Data;
Expand All @@ -63,7 +63,7 @@ public static FtexFile ConvertToFtex(DdsFile file, FtexTextureType textureType,
|| file.Header.PixelFormat.Equals(DdsPixelFormat.DdsPfDxt5()))
result.PixelFormatType = 4;
else
throw new NotImplementedException(String.Format("Unknown PixelFormatType {0}", file.Header.PixelFormat));
throw new ArgumentException($"Unknown PixelFormatType {file.Header.PixelFormat}");

result.Height = Convert.ToInt16(file.Header.Height);
result.Width = Convert.ToInt16(file.Header.Width);
Expand All @@ -72,15 +72,14 @@ public static FtexFile ConvertToFtex(DdsFile file, FtexTextureType textureType,
var mipMapData = GetMipMapData(file);
var mipMaps = GetMipMapInfos(mipMapData, ftexsFileCount);
var ftexsFiles = GetFtexsFiles(mipMaps, mipMapData);
result.MipMapCount = Convert.ToByte(mipMaps.Count());
result.MipMapCount = Convert.ToByte(mipMaps.Count);
result.NrtFlag = 2;
result.AddMipMapInfos(mipMaps);
result.AddFtexsFiles(ftexsFiles);
result.FtexsFileCount = Convert.ToByte(ftexsFiles.Count());
result.AdditionalFtexsFileCount = Convert.ToByte(ftexsFiles.Count() - 1);
result.FtexsFileCount = Convert.ToByte(ftexsFiles.Count);
result.AdditionalFtexsFileCount = Convert.ToByte(ftexsFiles.Count - 1);
result.UnknownFlags = 273; // TODO: Add an argument to set this value.
result.TextureType = textureType;

// TODO: Handle the DDS depth flag.
return result;
}

Expand All @@ -106,14 +105,14 @@ private static List<FtexsFile> GetFtexsFiles(List<FtexFileMipMapInfo> mipMapInfo
FtexsFile ftexsFile = ftexsFiles[mipMapInfo.FtexsFileNumber];
byte[] mipMapData = mipMapDatas[i];
FtexsFileMipMap ftexsFileMipMap = new FtexsFileMipMap();
List<FtexsFileChunk> chunks = GetFtexsChunks(mipMapInfo, mipMapData);
List<FtexsFileChunk> chunks = GetFtexsChunks(mipMapData);
ftexsFileMipMap.AddChunks(chunks);
ftexsFile.AddMipMap(ftexsFileMipMap);
}
return ftexsFiles.Values.ToList();
}

private static List<FtexsFileChunk> GetFtexsChunks(FtexFileMipMapInfo mipMapInfo, byte[] mipMapData)
private static List<FtexsFileChunk> GetFtexsChunks(byte[] mipMapData)
{
List<FtexsFileChunk> ftexsFileChunks = new List<FtexsFileChunk>();
const int maxChunkSize = short.MaxValue / 2 + 1;
Expand All @@ -125,7 +124,7 @@ private static List<FtexsFileChunk> GetFtexsChunks(FtexFileMipMapInfo mipMapInfo
int chunkSize = Math.Min(mipMapData.Length - mipMapDataOffset, maxChunkSize);
byte[] chunkData = new byte[chunkSize];
Array.Copy(mipMapData, mipMapDataOffset, chunkData, 0, chunkSize);
chunk.SetData(chunkData, false, chunkSize);
chunk.SetData(chunkData, false, true);
ftexsFileChunks.Add(chunk);
mipMapDataOffset += chunkSize;
}
Expand Down
39 changes: 33 additions & 6 deletions FtexTool/FtexTool.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
Expand Down Expand Up @@ -76,6 +91,18 @@
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
Expand All @@ -84,11 +111,11 @@
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
11 changes: 3 additions & 8 deletions FtexTool/Ftexs/FtexsFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,10 @@ public byte[] Data
return stream.ToArray();
}
}

public int CompressedDataSize
{
get { return MipMaps.Sum(mipMap => mipMap.CompressedDataSize); }
}

public void Read(Stream inputStream, short chunkCount)

public void Read(Stream inputStream, short chunkCount, int baseOffset)
{
FtexsFileMipMap mipMap = FtexsFileMipMap.ReadFtexsFileMipMap(inputStream, chunkCount);
FtexsFileMipMap mipMap = FtexsFileMipMap.ReadFtexsFileMipMap(inputStream, chunkCount, baseOffset);
AddMipMap(mipMap);
}

Expand Down
46 changes: 23 additions & 23 deletions FtexTool/Ftexs/FtexsFileChunk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace FtexTool.Ftexs
public class FtexsFileChunk
{
public const int IndexSize = 8;
private const int OffsetBitMask = 0xFFFF;
public const uint RelativeOffsetValue = 0x80000000;

public short CompressedChunkSize
{
Expand All @@ -23,40 +23,39 @@ public short ChunkSize
public byte[] ChunkData { get; private set; }
public byte[] CompressedChunkData { get; private set; }

public static FtexsFileChunk ReadFtexsFileChunk(Stream inputStream, bool absoluteOffset)
public static FtexsFileChunk ReadFtexsFileChunk(Stream inputStream, int baseOffset)
{
FtexsFileChunk result = new FtexsFileChunk();
result.Read(inputStream, absoluteOffset);
result.Read(inputStream, baseOffset);
return result;
}

public void Read(Stream inputStream, bool absoluteOffset)
public void Read(Stream inputStream, int baseOffset)
{
BinaryReader reader = new BinaryReader(inputStream, Encoding.Default, true);
BinaryReader reader = new BinaryReader(inputStream, Encoding.ASCII, true);
short compressedChunkSize = reader.ReadInt16();
short decompressedChunkSize = reader.ReadInt16();
Offset = reader.ReadUInt32();

long indexEndPosition = reader.BaseStream.Position;

if (absoluteOffset)
if (Offset > RelativeOffsetValue)
{
reader.BaseStream.Position = Offset;
reader.BaseStream.Position = baseOffset + (Offset - RelativeOffsetValue);
}
else
{
// HACK: result.Offset could be 0x80000008
reader.BaseStream.Position = indexEndPosition + (Offset & OffsetBitMask) - IndexSize;
reader.BaseStream.Position = baseOffset + Offset;
}

byte[] data = reader.ReadBytes(compressedChunkSize);
bool dataCompressed = compressedChunkSize != decompressedChunkSize;
SetData(data, dataCompressed, decompressedChunkSize);
SetData(data, dataCompressed, false);

reader.BaseStream.Position = indexEndPosition;
}

public void Write(Stream outputStream)
public void WriteIndex(Stream outputStream)
{
BinaryWriter writer = new BinaryWriter(outputStream, Encoding.Default, true);
writer.Write(CompressedChunkSize);
Expand All @@ -77,26 +76,27 @@ public void WriteData(Stream outputStream, bool writeCompressedData)
}
}

public void SetData(byte[] chunkData, bool compressed, long decompressedSize)
public void SetData(byte[] chunkData, bool compressed, bool forWriting)
{
// TODO: Refactor this whole method.
// - Only keep the uncompressed in memory.
if (compressed)
{
CompressedChunkData = chunkData;
try
ChunkData = ZipUtility.Inflate(chunkData);
}
else
{
byte[] compressedChunkData = ZipUtility.Deflate(chunkData);
if (forWriting && compressedChunkData.Length >= chunkData.Length)
{
ChunkData = ZipUtility.Inflate(chunkData);
CompressedChunkData = chunkData;
}
catch (Exception)
else
{
// BUG: Smaller TPP mipmaps fail to load at them moment.
// This catch block allows unpacking of the textures, but should
// be removed once the unpacking issue has been resolved.
ChunkData = new byte[decompressedSize];
CompressedChunkData = compressedChunkData;
}
}
else
{
CompressedChunkData = ZipUtility.Deflate(chunkData);

ChunkData = chunkData;
}
}
Expand Down
Loading

0 comments on commit 48302bb

Please sign in to comment.