mirror of
https://github.com/crskycode/GARbro.git
synced 2026-07-08 01:30:18 +08:00
Initial commit.
This commit is contained in:
235
GameRes/Utility.cs
Normal file
235
GameRes/Utility.cs
Normal file
@@ -0,0 +1,235 @@
|
||||
//! \file Utility.cs
|
||||
//! \date Sat Jul 05 02:47:33 2014
|
||||
//! \brief utility class for GameRes assembly.
|
||||
//
|
||||
|
||||
namespace GameRes.Utility
|
||||
{
|
||||
public static class Binary
|
||||
{
|
||||
public static uint BigEndian (uint u)
|
||||
{
|
||||
return (u & 0xff) << 24 | (u & 0xff00) << 8 | (u & 0xff0000) >> 8 | (u & 0xff000000) >> 24;
|
||||
}
|
||||
public static int BigEndian (int i)
|
||||
{
|
||||
return (int)BigEndian ((uint)i);
|
||||
}
|
||||
public static ushort BigEndian (ushort u)
|
||||
{
|
||||
return (ushort)((u & 0xff) << 8 | (u & 0xff00) >> 8);
|
||||
}
|
||||
public static short BigEndian (short i)
|
||||
{
|
||||
return (short)BigEndian ((ushort)i);
|
||||
}
|
||||
public static ulong BigEndian (ulong u)
|
||||
{
|
||||
return (ulong)BigEndian((uint)(u & 0xffffffff)) << 32
|
||||
| (ulong)BigEndian((uint)(u >> 32));
|
||||
}
|
||||
public static long BigEndian (long i)
|
||||
{
|
||||
return (long)BigEndian ((ulong)i);
|
||||
}
|
||||
|
||||
public static bool AsciiEqual (byte[] name1, string name2)
|
||||
{
|
||||
return AsciiEqual (name1, 0, name2);
|
||||
}
|
||||
|
||||
public static bool AsciiEqual (byte[] name1, int offset, string name2)
|
||||
{
|
||||
if (name1.Length-offset < name2.Length)
|
||||
return false;
|
||||
for (int i = 0; i < name2.Length; ++i)
|
||||
if ((char)name1[offset+i] != name2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LittleEndian
|
||||
{
|
||||
public static ushort ToUInt16 (byte[] value, int index)
|
||||
{
|
||||
return (ushort)(value[index] | value[index+1] << 8);
|
||||
}
|
||||
|
||||
public static short ToInt16 (byte[] value, int index)
|
||||
{
|
||||
return (short)(value[index] | value[index+1] << 8);
|
||||
}
|
||||
|
||||
public static uint ToUInt32 (byte[] value, int index)
|
||||
{
|
||||
return (uint)(value[index] | value[index+1] << 8 | value[index+2] << 16 | value[index+3] << 24);
|
||||
}
|
||||
|
||||
public static int ToInt32 (byte[] value, int index)
|
||||
{
|
||||
return (int)ToUInt32 (value, index);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Crc32
|
||||
{
|
||||
/* Table of CRCs of all 8-bit messages. */
|
||||
private static readonly uint[] crc_table = InitializeTable();
|
||||
|
||||
/* Make the table for a fast CRC. */
|
||||
private static uint[] InitializeTable ()
|
||||
{
|
||||
uint[] table = new uint[256];
|
||||
for (uint n = 0; n < 256; n++)
|
||||
{
|
||||
uint c = n;
|
||||
for (int k = 0; k < 8; k++)
|
||||
{
|
||||
if (0 != (c & 1))
|
||||
c = 0xedb88320 ^ (c >> 1);
|
||||
else
|
||||
c = c >> 1;
|
||||
}
|
||||
table[n] = c;
|
||||
}
|
||||
return table;
|
||||
}
|
||||
|
||||
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
|
||||
should be initialized to all 1's, and the transmitted value
|
||||
is the 1's complement of the final running CRC (see the
|
||||
crc() routine below)). */
|
||||
static uint UpdateCrc (uint crc, byte[] buf, int pos, int len)
|
||||
{
|
||||
uint c = crc;
|
||||
for (int n = 0; n < len; n++)
|
||||
c = crc_table[(c ^ buf[pos+n]) & 0xff] ^ (c >> 8);
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Return the CRC of the bytes buf[0..len-1]. */
|
||||
public static uint Compute (byte[] buf, int pos, int len)
|
||||
{
|
||||
return UpdateCrc (0xffffffff, buf, pos, len) ^ 0xffffffff;
|
||||
}
|
||||
|
||||
private uint m_crc = 0xffffffff;
|
||||
public uint Value { get { return m_crc^0xffffffff; } }
|
||||
|
||||
public void Update (byte[] buf, int pos, int len)
|
||||
{
|
||||
m_crc = UpdateCrc (m_crc, buf, pos, len);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Adler32
|
||||
{
|
||||
const uint BASE = 65521; /* largest prime smaller than 65536 */
|
||||
const int NMAX = 5552;
|
||||
|
||||
public static uint Compute (byte[] buf, int pos, int len)
|
||||
{
|
||||
return Update (1, buf, pos, len);
|
||||
}
|
||||
|
||||
private static uint Update (uint adler, byte[] buf, int pos, int len)
|
||||
{
|
||||
/* split Adler-32 into component sums */
|
||||
uint sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (1 == len) {
|
||||
adler += buf[pos];
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 += adler;
|
||||
if (sum2 >= BASE)
|
||||
sum2 -= BASE;
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
while (0 != len--) {
|
||||
adler += buf[pos++];
|
||||
sum2 += adler;
|
||||
}
|
||||
if (adler >= BASE)
|
||||
adler -= BASE;
|
||||
sum2 %= BASE; /* only added so many BASE's */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
/* do length NMAX blocks -- requires just one modulo operation */
|
||||
while (len >= NMAX) {
|
||||
len -= NMAX;
|
||||
int n = NMAX / 16; /* NMAX is divisible by 16 */
|
||||
do {
|
||||
/* 16 sums unrolled */
|
||||
adler += buf[pos]; sum2 += adler;
|
||||
adler += buf[pos+1]; sum2 += adler;
|
||||
adler += buf[pos+2]; sum2 += adler;
|
||||
adler += buf[pos+3]; sum2 += adler;
|
||||
adler += buf[pos+4]; sum2 += adler;
|
||||
adler += buf[pos+5]; sum2 += adler;
|
||||
adler += buf[pos+6]; sum2 += adler;
|
||||
adler += buf[pos+7]; sum2 += adler;
|
||||
adler += buf[pos+8]; sum2 += adler;
|
||||
adler += buf[pos+9]; sum2 += adler;
|
||||
adler += buf[pos+10]; sum2 += adler;
|
||||
adler += buf[pos+11]; sum2 += adler;
|
||||
adler += buf[pos+12]; sum2 += adler;
|
||||
adler += buf[pos+13]; sum2 += adler;
|
||||
adler += buf[pos+14]; sum2 += adler;
|
||||
adler += buf[pos+15]; sum2 += adler;
|
||||
pos += 16;
|
||||
} while (0 != --n);
|
||||
adler %= BASE;
|
||||
sum2 %= BASE;
|
||||
}
|
||||
|
||||
/* do remaining bytes (less than NMAX, still just one modulo) */
|
||||
if (0 != len) { /* avoid modulos if none remaining */
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
adler += buf[pos]; sum2 += adler;
|
||||
adler += buf[pos+1]; sum2 += adler;
|
||||
adler += buf[pos+2]; sum2 += adler;
|
||||
adler += buf[pos+3]; sum2 += adler;
|
||||
adler += buf[pos+4]; sum2 += adler;
|
||||
adler += buf[pos+5]; sum2 += adler;
|
||||
adler += buf[pos+6]; sum2 += adler;
|
||||
adler += buf[pos+7]; sum2 += adler;
|
||||
adler += buf[pos+8]; sum2 += adler;
|
||||
adler += buf[pos+9]; sum2 += adler;
|
||||
adler += buf[pos+10]; sum2 += adler;
|
||||
adler += buf[pos+11]; sum2 += adler;
|
||||
adler += buf[pos+12]; sum2 += adler;
|
||||
adler += buf[pos+13]; sum2 += adler;
|
||||
adler += buf[pos+14]; sum2 += adler;
|
||||
adler += buf[pos+15]; sum2 += adler;
|
||||
pos += 16;
|
||||
}
|
||||
while (0 != len--) {
|
||||
adler += buf[pos++];
|
||||
sum2 += adler;
|
||||
}
|
||||
adler %= BASE;
|
||||
sum2 %= BASE;
|
||||
}
|
||||
|
||||
/* return recombined sums */
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
private uint m_adler = 1;
|
||||
public uint Value { get { return m_adler; } }
|
||||
|
||||
public void Update (byte[] buf, int pos, int len)
|
||||
{
|
||||
m_adler = Update (m_adler, buf, pos, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user