From b6655d54d0765862acdd06a75e17e76039a135b6 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Sat, 12 Sep 2015 07:37:34 +1000 Subject: [PATCH] Add simple .zip reader (For reading texture packs), partially addresses #44. --- ClassicalSharp/ClassicalSharp.csproj | 6 +- .../{Utils => TexturePack}/TerrainAtlas1D.cs | 0 .../{Utils => TexturePack}/TerrainAtlas2D.cs | 0 ClassicalSharp/TexturePack/ZipExtractor.cs | 70 +++++++++++++++++++ 4 files changed, 74 insertions(+), 2 deletions(-) rename ClassicalSharp/{Utils => TexturePack}/TerrainAtlas1D.cs (100%) rename ClassicalSharp/{Utils => TexturePack}/TerrainAtlas2D.cs (100%) create mode 100644 ClassicalSharp/TexturePack/ZipExtractor.cs diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index aa01ed9d1..d87dbf9f3 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -159,11 +159,12 @@ + + + - - @@ -190,6 +191,7 @@ + diff --git a/ClassicalSharp/Utils/TerrainAtlas1D.cs b/ClassicalSharp/TexturePack/TerrainAtlas1D.cs similarity index 100% rename from ClassicalSharp/Utils/TerrainAtlas1D.cs rename to ClassicalSharp/TexturePack/TerrainAtlas1D.cs diff --git a/ClassicalSharp/Utils/TerrainAtlas2D.cs b/ClassicalSharp/TexturePack/TerrainAtlas2D.cs similarity index 100% rename from ClassicalSharp/Utils/TerrainAtlas2D.cs rename to ClassicalSharp/TexturePack/TerrainAtlas2D.cs diff --git a/ClassicalSharp/TexturePack/ZipExtractor.cs b/ClassicalSharp/TexturePack/ZipExtractor.cs new file mode 100644 index 000000000..ce2b1e20f --- /dev/null +++ b/ClassicalSharp/TexturePack/ZipExtractor.cs @@ -0,0 +1,70 @@ +using System; +using System.IO; +using System.IO.Compression; +using System.Text; + +namespace ClassicalSharp.TexturePack { + + public sealed class ZipExtractor { + + static Encoding enc = Encoding.ASCII; + public void Extract( Stream stream ) { + + BinaryReader reader = new BinaryReader( stream ); + while( true ) { + uint sig = reader.ReadUInt32(); + if( sig == 0x04034b50 ) { // local file header + ReadLocalFileHeader( reader ); + } else if( sig == 0x02014b50 ) { // central directory header + break; + } else { + throw new NotSupportedException( "Unsupported signature: " + sig.ToString( "X8" ) ); + } + } + } + + void ReadLocalFileHeader( BinaryReader reader ) { + ushort versionNeeded = reader.ReadUInt16(); + ushort flags = reader.ReadUInt16(); + ushort compressionMethod = reader.ReadUInt16(); + reader.ReadUInt32(); // last modified + reader.ReadUInt32(); // CRC 32 + int compressedSize = reader.ReadInt32(); + int uncompressedSize = reader.ReadInt32(); + ushort fileNameLen = reader.ReadUInt16(); + ushort extraFieldLen = reader.ReadUInt16(); + string fileName = enc.GetString( reader.ReadBytes( fileNameLen ) ); + reader.ReadBytes( extraFieldLen ); + + if( versionNeeded > 20 ) + Utils.LogWarning( "May not be able to properly extract a .zip enty with a version later than 2.0" ); + + byte[] data = DecompressEntry( reader, compressionMethod, compressedSize, uncompressedSize ); + if( data != null ) + HandleZipEntry( fileName, data ); + } + + byte[] DecompressEntry( BinaryReader reader, ushort compressionMethod, int compressedSize, int uncompressedSize ) { + if( compressionMethod == 0 ) { // Store/Raw + return reader.ReadBytes( uncompressedSize ); + } else if( compressionMethod == 8 ) { // Deflate + byte[] data = new byte[uncompressedSize]; + int index = 0, read = 0; + DeflateStream deflater = new DeflateStream( reader.BaseStream, CompressionMode.Decompress ); + while( index < uncompressedSize && + ( read = deflater.Read( data, index, data.Length - index ) ) > 0 ) { + index += read; + } + return data; + } else { + Utils.LogWarning( "Unsupported .zip entry compression method: " + compressionMethod ); + reader.ReadBytes( compressedSize ); + return null; + } + } + + void HandleZipEntry( string filename, byte[] data ) { + Console.WriteLine( filename ); + } + } +}