mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-23 09:34:35 -05:00
122 lines
4.2 KiB
C#
122 lines
4.2 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Drawing.Imaging;
|
|
using System.IO;
|
|
using System.Text;
|
|
using ClassicalSharp.TexturePack;
|
|
|
|
namespace Launcher2 {
|
|
|
|
public sealed class ZipWriter {
|
|
|
|
BinaryWriter writer;
|
|
Stream stream;
|
|
public ZipWriter( Stream stream ) {
|
|
this.stream = stream;
|
|
writer = new BinaryWriter( stream );
|
|
}
|
|
|
|
internal ZipEntry[] entries;
|
|
internal int entriesCount;
|
|
|
|
public void WriteZipEntry( ZipEntry entry, byte[] data ) {
|
|
entry.CompressedDataSize = (int)entry.UncompressedDataSize;
|
|
entry.LocalHeaderOffset = (int)stream.Position;
|
|
entries[entriesCount++] = entry;
|
|
WriteLocalFileEntry( entry, data, data.Length );
|
|
}
|
|
|
|
public void WriteNewImage( Bitmap bmp, string filename ) {
|
|
MemoryStream data = new MemoryStream();
|
|
bmp.Save( data, ImageFormat.Png );
|
|
byte[] buffer = data.GetBuffer();
|
|
WriteNewEntry( filename, buffer, (int)data.Length );
|
|
}
|
|
|
|
public void WriteNewString( string text, string filename ) {
|
|
byte[] data = Encoding.ASCII.GetBytes( text );
|
|
WriteNewEntry( filename, data, data.Length );
|
|
}
|
|
|
|
public void WriteNewEntry( string filename, byte[] data, int dataLength ) {
|
|
ZipEntry entry = new ZipEntry();
|
|
entry.UncompressedDataSize = dataLength;
|
|
entry.Crc32 = CRC32( data, dataLength );
|
|
entry.CompressedDataSize = dataLength;
|
|
entry.LocalHeaderOffset = (int)stream.Position;
|
|
|
|
entry.Filename = filename;
|
|
entries[entriesCount++] = entry;
|
|
WriteLocalFileEntry( entry, data, dataLength );
|
|
}
|
|
|
|
public void WriteCentralDirectoryRecords() {
|
|
int dirOffset = (int)stream.Position;
|
|
for( int i = 0; i < entriesCount; i++ ) {
|
|
WriteCentralDirectoryHeaderEntry( entries[i] );
|
|
}
|
|
int dirSize = (int)( stream.Position - dirOffset );
|
|
WriteEndOfCentralDirectoryRecord( (ushort)entriesCount, dirSize, dirOffset );
|
|
}
|
|
|
|
void WriteLocalFileEntry( ZipEntry entry, byte[] data, int length ) {
|
|
writer.Write( 0x04034b50 ); // signature
|
|
writer.Write( (ushort)20 ); // version needed
|
|
writer.Write( (ushort)0 ); // bitflags
|
|
writer.Write( (ushort)0 ); // compression method
|
|
writer.Write( 0 ); // last modified
|
|
writer.Write( entry.Crc32 );
|
|
writer.Write( entry.CompressedDataSize );
|
|
writer.Write( entry.UncompressedDataSize );
|
|
writer.Write( (ushort)entry.Filename.Length );
|
|
writer.Write( (ushort)0 ); // extra field length
|
|
for( int i = 0; i < entry.Filename.Length; i++ )
|
|
writer.Write( (byte)entry.Filename[i] );
|
|
|
|
writer.Write( data, 0, length );
|
|
}
|
|
|
|
void WriteCentralDirectoryHeaderEntry( ZipEntry entry ) {
|
|
writer.Write( 0x02014b50 ); // signature
|
|
writer.Write( (ushort)20 ); // version
|
|
writer.Write( (ushort)20 ); // version needed
|
|
writer.Write( (ushort)0 ); // bitflags
|
|
writer.Write( (ushort)0 ); // compression method
|
|
writer.Write( 0 ); // last modified
|
|
writer.Write( entry.Crc32 );
|
|
writer.Write( entry.CompressedDataSize );
|
|
writer.Write( entry.UncompressedDataSize );
|
|
|
|
writer.Write( (ushort)entry.Filename.Length );
|
|
writer.Write( (ushort)0 ); // extra field length
|
|
writer.Write( (ushort)0 ); // file comment length
|
|
writer.Write( (ushort)0 ); // disk number
|
|
writer.Write( (ushort)0 ); // internal attributes
|
|
writer.Write( 0 ); // external attributes
|
|
writer.Write( entry.LocalHeaderOffset );
|
|
for( int i = 0; i < entry.Filename.Length; i++ )
|
|
writer.Write( (byte)entry.Filename[i] );
|
|
}
|
|
|
|
void WriteEndOfCentralDirectoryRecord( ushort entries, int centralDirSize, int centralDirOffset ) {
|
|
writer.Write( 0x06054b50 ); // signature
|
|
writer.Write( (ushort)0 ); // disk number
|
|
writer.Write( (ushort)0 ); // disk number of start
|
|
writer.Write( entries ); // disk entries
|
|
writer.Write( entries ); // total entries
|
|
writer.Write( centralDirSize );
|
|
writer.Write( centralDirOffset );
|
|
writer.Write( (ushort)0 ); // comment length
|
|
}
|
|
|
|
static uint CRC32( byte[] data, int length ) {
|
|
uint crc = 0xffffffffU;
|
|
for( int i = 0; i < length; i++ ) {
|
|
crc ^= data[i];
|
|
for( int j = 0; j < 8; j++ )
|
|
crc = (crc >> 1) ^ (crc & 1) * 0xEDB88320;
|
|
}
|
|
return crc ^ 0xffffffffU;
|
|
}
|
|
}
|
|
}
|