Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
302
Ultima/Textures.cs
Normal file
302
Ultima/Textures.cs
Normal file
@@ -0,0 +1,302 @@
|
||||
#region References
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
#endregion
|
||||
|
||||
namespace Ultima
|
||||
{
|
||||
public sealed class Textures
|
||||
{
|
||||
private static FileIndex m_FileIndex = new FileIndex("Texidx.mul", "Texmaps.mul", 0x4000, 10);
|
||||
private static Bitmap[] m_Cache = new Bitmap[0x4000];
|
||||
private static bool[] m_Removed = new bool[0x4000];
|
||||
private static readonly Hashtable m_patched = new Hashtable();
|
||||
|
||||
private static byte[] m_StreamBuffer;
|
||||
|
||||
private struct CheckSums
|
||||
{
|
||||
public byte[] checksum;
|
||||
public int pos;
|
||||
public int length;
|
||||
public int index;
|
||||
}
|
||||
|
||||
private static List<CheckSums> checksums;
|
||||
|
||||
/// <summary>
|
||||
/// ReReads texmaps
|
||||
/// </summary>
|
||||
public static void Reload()
|
||||
{
|
||||
m_FileIndex = new FileIndex("Texidx.mul", "Texmaps.mul", 0x4000, 10);
|
||||
m_Cache = new Bitmap[0x4000];
|
||||
m_Removed = new bool[0x4000];
|
||||
m_patched.Clear();
|
||||
}
|
||||
|
||||
public static int GetIdxLength()
|
||||
{
|
||||
return (int)(m_FileIndex.IdxLength / 12);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes Texture <see cref="m_Removed" />
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
public static void Remove(int index)
|
||||
{
|
||||
m_Removed[index] = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces Texture
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="bmp"></param>
|
||||
public static void Replace(int index, Bitmap bmp)
|
||||
{
|
||||
m_Cache[index] = bmp;
|
||||
m_Removed[index] = false;
|
||||
if (m_patched.Contains(index))
|
||||
{
|
||||
m_patched.Remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests if index is valid Texture
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TestTexture(int index)
|
||||
{
|
||||
int length, extra;
|
||||
bool patched;
|
||||
if (m_Removed[index])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_Cache[index] != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool valid = m_FileIndex.Valid(index, out length, out extra, out patched);
|
||||
if ((!valid) || (length == 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Bitmap of Texture
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public static Bitmap GetTexture(int index)
|
||||
{
|
||||
bool patched;
|
||||
return GetTexture(index, out patched);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns Bitmap of Texture with verdata bool
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="patched"></param>
|
||||
/// <returns></returns>
|
||||
public static unsafe Bitmap GetTexture(int index, out bool patched)
|
||||
{
|
||||
if (m_patched.Contains(index))
|
||||
{
|
||||
patched = (bool)m_patched[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
patched = false;
|
||||
}
|
||||
if (m_Removed[index])
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (m_Cache[index] != null)
|
||||
{
|
||||
return m_Cache[index];
|
||||
}
|
||||
|
||||
int length, extra;
|
||||
Stream stream = m_FileIndex.Seek(index, out length, out extra, out patched);
|
||||
if (stream == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (patched)
|
||||
{
|
||||
m_patched[index] = true;
|
||||
}
|
||||
|
||||
int size = extra == 0 ? 64 : 128;
|
||||
|
||||
var bmp = new Bitmap(size, size, Settings.PixelFormat);
|
||||
BitmapData bd = bmp.LockBits(
|
||||
new Rectangle(0, 0, size, size), ImageLockMode.WriteOnly, Settings.PixelFormat);
|
||||
|
||||
var line = (ushort*)bd.Scan0;
|
||||
int delta = bd.Stride >> 1;
|
||||
|
||||
int max = size * size * 2;
|
||||
|
||||
if (m_StreamBuffer == null || m_StreamBuffer.Length < max)
|
||||
{
|
||||
m_StreamBuffer = new byte[max];
|
||||
}
|
||||
stream.Read(m_StreamBuffer, 0, max);
|
||||
|
||||
fixed (byte* data = m_StreamBuffer)
|
||||
{
|
||||
var bindat = (ushort*)data;
|
||||
for (int y = 0; y < size; ++y, line += delta)
|
||||
{
|
||||
ushort* cur = line;
|
||||
ushort* end = cur + size;
|
||||
|
||||
while (cur < end)
|
||||
{
|
||||
*cur++ = (ushort)(*bindat++ ^ 0x8000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bmp.UnlockBits(bd);
|
||||
|
||||
stream.Close();
|
||||
if (!Files.CacheData)
|
||||
{
|
||||
return m_Cache[index] = bmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
return bmp;
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe void Save(string path)
|
||||
{
|
||||
string idx = Path.Combine(path, "texidx.mul");
|
||||
string mul = Path.Combine(path, "texmaps.mul");
|
||||
checksums = new List<CheckSums>();
|
||||
using (
|
||||
FileStream fsidx = new FileStream(idx, FileMode.Create, FileAccess.Write, FileShare.Write),
|
||||
fsmul = new FileStream(mul, FileMode.Create, FileAccess.Write, FileShare.Write))
|
||||
{
|
||||
var memidx = new MemoryStream();
|
||||
var memmul = new MemoryStream();
|
||||
using (BinaryWriter binidx = new BinaryWriter(memidx), binmul = new BinaryWriter(memmul))
|
||||
{
|
||||
var sha = new SHA256Managed();
|
||||
//StreamWriter Tex = new StreamWriter(new FileStream("d:/texlog.txt", FileMode.Create, FileAccess.ReadWrite));
|
||||
for (int index = 0; index < GetIdxLength(); ++index)
|
||||
{
|
||||
if (m_Cache[index] == null)
|
||||
{
|
||||
m_Cache[index] = GetTexture(index);
|
||||
}
|
||||
|
||||
Bitmap bmp = m_Cache[index];
|
||||
if ((bmp == null) || (m_Removed[index]))
|
||||
{
|
||||
binidx.Write(-1); // lookup
|
||||
binidx.Write(0); // length
|
||||
binidx.Write(-1); // extra
|
||||
}
|
||||
else
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
bmp.Save(ms, ImageFormat.Bmp);
|
||||
byte[] checksum = sha.ComputeHash(ms.ToArray());
|
||||
CheckSums sum;
|
||||
if (compareSaveImages(checksum, out sum))
|
||||
{
|
||||
binidx.Write(sum.pos); //lookup
|
||||
binidx.Write(sum.length);
|
||||
binidx.Write(0);
|
||||
//Tex.WriteLine(System.String.Format("0x{0:X4} : 0x{1:X4} 0x{2:X4}", index, (int)sum.pos, (int)sum.length));
|
||||
//Tex.WriteLine(System.String.Format("0x{0:X4} -> 0x{1:X4}", sum.index, index));
|
||||
continue;
|
||||
}
|
||||
BitmapData bd = bmp.LockBits(
|
||||
new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, Settings.PixelFormat);
|
||||
var line = (ushort*)bd.Scan0;
|
||||
int delta = bd.Stride >> 1;
|
||||
|
||||
binidx.Write((int)binmul.BaseStream.Position); //lookup
|
||||
var length = (int)binmul.BaseStream.Position;
|
||||
|
||||
for (int Y = 0; Y < bmp.Height; ++Y, line += delta)
|
||||
{
|
||||
ushort* cur = line;
|
||||
for (int X = 0; X < bmp.Width; ++X)
|
||||
{
|
||||
binmul.Write((ushort)(cur[X] ^ 0x8000));
|
||||
}
|
||||
}
|
||||
int start = length;
|
||||
length = (int)binmul.BaseStream.Position - length;
|
||||
binidx.Write(length);
|
||||
binidx.Write((bmp.Width == 64 ? 0 : 1));
|
||||
bmp.UnlockBits(bd);
|
||||
var s = new CheckSums
|
||||
{
|
||||
pos = start,
|
||||
length = length,
|
||||
checksum = checksum,
|
||||
index = index
|
||||
};
|
||||
//Tex.WriteLine(System.String.Format("0x{0:X4} : 0x{1:X4} 0x{2:X4}", index, start, length));
|
||||
checksums.Add(s);
|
||||
}
|
||||
}
|
||||
memidx.WriteTo(fsidx);
|
||||
memmul.WriteTo(fsmul);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool compareSaveImages(byte[] newchecksum, out CheckSums sum)
|
||||
{
|
||||
sum = new CheckSums();
|
||||
for (int i = 0; i < checksums.Count; ++i)
|
||||
{
|
||||
byte[] cmp = checksums[i].checksum;
|
||||
if (((cmp == null) || (newchecksum == null)) || (cmp.Length != newchecksum.Length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool valid = true;
|
||||
for (int j = 0; j < cmp.Length; ++j)
|
||||
{
|
||||
if (cmp[j] != newchecksum[j])
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid)
|
||||
{
|
||||
sum = checksums[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user