diff --git a/BurnOutSharp/External/libgsf/GsfClipData.cs b/BurnOutSharp/External/libgsf/GsfClipData.cs index 2cca089e..c60fc935 100644 --- a/BurnOutSharp/External/libgsf/GsfClipData.cs +++ b/BurnOutSharp/External/libgsf/GsfClipData.cs @@ -21,6 +21,7 @@ using System; using System.IO; +using static LibGSF.GsfUtils; namespace LibGSF { @@ -173,7 +174,7 @@ namespace LibGSF byte[] data = DataBlob.Data; - uint value = BitConverter.ToUInt32(data, 0); + uint value = GSF_LE_GET_GUINT32(data, 0); switch (value) { diff --git a/BurnOutSharp/External/libgsf/GsfDocMetaData.cs b/BurnOutSharp/External/libgsf/GsfDocMetaData.cs index 1e2ec20b..44fbad5a 100644 --- a/BurnOutSharp/External/libgsf/GsfDocMetaData.cs +++ b/BurnOutSharp/External/libgsf/GsfDocMetaData.cs @@ -27,6 +27,7 @@ using System.Text; using LibGSF.Input; using LibGSF.Output; using static LibGSF.GsfMSOleUtils; +using static LibGSF.GsfUtils; namespace LibGSF { @@ -195,11 +196,11 @@ namespace LibGSF * 08 - 23 Class Identifier Usually Format ID * 24 - 27 Section count Should be at least 1 */ - ushort os = BitConverter.ToUInt16(data, 6); - ushort version = BitConverter.ToUInt16(data, 2); + ushort os = GSF_LE_GET_GUINT16(data, 6); + ushort version = GSF_LE_GET_GUINT16(data, 2); uint num_sections = BitConverter.ToUInt32(data, 24); - if (BitConverter.ToUInt16(data, 0) != 0xfffe + if (GSF_LE_GET_GUINT16(data, 0) != 0xfffe || (version != 0 && version != 1) || os > 2 || num_sections > input.Size / 20 @@ -408,7 +409,7 @@ namespace LibGSF /// /// A kludge to differentiate DocumentSummary from Summary - /// true on success + /// True on success /// Since: 1.14.24 public bool WriteToMSOLE(GsfOutput output, bool doc_not_component) { @@ -466,7 +467,7 @@ namespace LibGSF state.CharSize = CodePageCharSize(state.CodePage); // Write stream header - buf = BitConverter.GetBytes((uint)(state.Dict != null ? 2 : 1)); + GSF_LE_SET_GUINT32(buf, 0, (uint)(state.Dict != null ? 2 : 1)); if (!output.Write(header.Length, header) || !output.Write(4, buf)) { state.IConvHandle = null; @@ -477,7 +478,7 @@ namespace LibGSF } // Write section header(s) - buf = BitConverter.GetBytes((uint)(state.Dict != null ? 0x44 : 0x30)); + GSF_LE_SET_GUINT32(buf, 0, (uint)(state.Dict != null ? 0x44 : 0x30)); if (!output.Write(16, doc_not_component ? DocumentGUID : ComponentGUID) || !output.Write(4, buf)) { state.IConvHandle = null; @@ -489,7 +490,7 @@ namespace LibGSF if (state.Dict != null) { - buf = BitConverter.GetBytes((uint)0); + GSF_LE_SET_GUINT32(buf, 0, 0); if (!output.Write(UserGUID.Length, UserGUID) || !output.Write(4, buf)) // Bogus position, fix it later { state.IConvHandle = null; @@ -513,7 +514,7 @@ namespace LibGSF if (state.Dict != null) { long baseOffset = state.Output.CurrentOffset; - buf = BitConverter.GetBytes((uint)baseOffset); + GSF_LE_SET_GUINT32(buf, 0, (uint)baseOffset); if (!state.Output.Seek(0x40, SeekOrigin.Begin) || !output.Write(4, buf) || !state.Output.Seek(0, SeekOrigin.End) diff --git a/BurnOutSharp/External/libgsf/GsfMSOleUtils.cs b/BurnOutSharp/External/libgsf/GsfMSOleUtils.cs index 67c0ae39..a75f8892 100644 --- a/BurnOutSharp/External/libgsf/GsfMSOleUtils.cs +++ b/BurnOutSharp/External/libgsf/GsfMSOleUtils.cs @@ -28,6 +28,7 @@ using System.Text; using LibGSF.Input; using LibGSF.Output; using static LibGSF.GsfMetaNames; +using static LibGSF.GsfUtils; namespace LibGSF { @@ -784,7 +785,7 @@ namespace LibGSF if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed)) return null; - uint n = BitConverter.ToUInt32(data, dataPtr); + uint n = GSF_LE_GET_GUINT32(data, dataPtr); dataPtr += bytes_needed; int size1 = PropMinSize(type); @@ -826,7 +827,7 @@ namespace LibGSF if (!NEED_RECS(2, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = BitConverter.ToInt16(data, dataPtr); + res = GSF_LE_GET_GINT16(data, dataPtr); dataPtr += bytes_needed; break; @@ -835,7 +836,7 @@ namespace LibGSF if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = BitConverter.ToInt32(data, dataPtr); + res = GSF_LE_GET_GINT32(data, dataPtr); dataPtr += bytes_needed; break; @@ -844,7 +845,7 @@ namespace LibGSF if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = BitConverter.ToSingle(data, dataPtr); + res = GSF_LE_GET_FLOAT(data, dataPtr); dataPtr += bytes_needed; break; @@ -853,7 +854,7 @@ namespace LibGSF if (!NEED_RECS(8, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = BitConverter.ToDouble(data, dataPtr); + res = GSF_LE_GET_DOUBLE(data, dataPtr); dataPtr += bytes_needed; break; @@ -863,7 +864,7 @@ namespace LibGSF return null; // CHEAT : just store as an int64 for now - res = BitConverter.ToInt64(data, dataPtr); + res = GSF_LE_GET_GINT64(data, dataPtr); break; // 64-bit floating-point number representing the number of days @@ -905,7 +906,7 @@ namespace LibGSF return null; res = null; - type = (GsfMSOLEVariantType)BitConverter.ToUInt32(data, dataPtr); + type = (GsfMSOLEVariantType)GSF_LE_GET_GUINT32(data, dataPtr); dataPtr += bytes_needed; return PropertyParse(type, data, ref dataPtr, data_end); @@ -914,7 +915,7 @@ namespace LibGSF if (!NEED_RECS(1, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = data[dataPtr]; + res = GSF_LE_GET_GUINT8(data, dataPtr); dataPtr += bytes_needed; break; @@ -923,7 +924,7 @@ namespace LibGSF if (!NEED_RECS(1, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = (sbyte)data[dataPtr]; + res = GSF_LE_GET_GINT8(data, dataPtr); dataPtr += bytes_needed; break; @@ -932,7 +933,7 @@ namespace LibGSF if (!NEED_RECS(2, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = BitConverter.ToUInt16(data, dataPtr); + res = GSF_LE_GET_GUINT16(data, dataPtr); dataPtr += bytes_needed; break; @@ -941,7 +942,7 @@ namespace LibGSF if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = BitConverter.ToUInt32(data, dataPtr); + res = GSF_LE_GET_GUINT32(data, dataPtr); dataPtr += bytes_needed; break; @@ -950,7 +951,7 @@ namespace LibGSF if (!NEED_RECS(8, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = BitConverter.ToInt64(data, dataPtr); + res = GSF_LE_GET_GINT64(data, dataPtr); dataPtr += bytes_needed; break; @@ -959,7 +960,7 @@ namespace LibGSF if (!NEED_RECS(8, 1, dataPtr, data_end, ref bytes_needed)) return null; - res = BitConverter.ToUInt64(data, dataPtr); + res = GSF_LE_GET_GUINT64(data, dataPtr); dataPtr += bytes_needed; break; @@ -972,7 +973,7 @@ namespace LibGSF if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed)) return null; - len = BitConverter.ToUInt32(data, dataPtr); + len = GSF_LE_GET_GUINT32(data, dataPtr); dataPtr += bytes_needed; if (len >= 0x10000) @@ -1024,7 +1025,7 @@ namespace LibGSF if (!NEED_RECS(4, 1, dataPtr, data_end, ref bytes_needed)) return null; - len = BitConverter.ToUInt32(data, dataPtr); + len = GSF_LE_GET_GUINT32(data, dataPtr); dataPtr += bytes_needed; if (!NEED_RECS(len, 2, dataPtr, data_end, ref bytes_needed)) @@ -1070,7 +1071,7 @@ namespace LibGSF return null; // ft * 100ns since Jan 1 1601 - ulong ft = BitConverter.ToUInt64(data, dataPtr); + ulong ft = GSF_LE_GET_GUINT64(data, dataPtr); res = DateTime.FromFileTime((long)ft); dataPtr += bytes_needed; break; @@ -1206,7 +1207,7 @@ namespace LibGSF } int dataPtr = 0; // data[0] - GsfMSOLEVariantType type = (GsfMSOLEVariantType)BitConverter.ToUInt32(data, dataPtr); + GsfMSOLEVariantType type = (GsfMSOLEVariantType)GSF_LE_GET_GUINT32(data, dataPtr); dataPtr += 4; // Dictionary is magic @@ -1228,8 +1229,8 @@ namespace LibGSF if (end - dataPtr < 8) return false; - id = BitConverter.ToUInt32(data, dataPtr); - len = BitConverter.ToUInt32(data, dataPtr + 4); + id = GSF_LE_GET_GUINT32(data, dataPtr); + len = GSF_LE_GET_GUINT32(data, dataPtr + 4); if (len >= 0x10000) return false; @@ -1341,7 +1342,7 @@ namespace LibGSF return false; } - uint clip_size = BitConverter.ToUInt32(data, dataPtr); + uint clip_size = GSF_LE_GET_GUINT32(data, dataPtr); if (clip_size < 4) { @@ -1360,7 +1361,7 @@ namespace LibGSF return false; } - GsfClipFormat clip_format = (GsfClipFormat)BitConverter.ToInt32(data, dataPtr); + GsfClipFormat clip_format = (GsfClipFormat)GSF_LE_GET_GINT32(data, dataPtr); dataPtr += 4; switch (clip_format) @@ -1631,7 +1632,8 @@ namespace LibGSF long baseOffset = Output.CurrentOffset; // Skip past the size+count and id/offset pairs - byte[] buf = BitConverter.GetBytes((uint)0); + byte[] buf = new byte[8]; + GSF_LE_SET_GUINT32(buf, 0, 0); for (int j = 0; j < 1 + 1 + 2 * count; j++) { Output.Write(4, buf); @@ -1647,9 +1649,9 @@ namespace LibGSF { offsets[0].Id = 1; offsets[0].Offset = Output.CurrentOffset; - buf = BitConverter.GetBytes((uint)GsfMSOLEVariantType.VT_I2); - byte[] buf2 = BitConverter.GetBytes(CodePage); - Output.Write(4, buf); Output.Write(4, buf2); + GSF_LE_SET_GUINT32(buf, 0, (uint)GsfMSOLEVariantType.VT_I2); + GSF_LE_SET_GUINT32(buf, 4, (uint)CodePage); + Output.Write(8, buf); i++; } @@ -1658,7 +1660,7 @@ namespace LibGSF { offsets[1].Id = 0; offsets[1].Offset = Output.CurrentOffset; - buf = BitConverter.GetBytes((uint)Dict.Count); + GSF_LE_SET_GUINT32(buf, 4, (uint)Dict.Count); Output.Write(4, buf); foreach (var kvp in Dict) { @@ -1722,17 +1724,15 @@ namespace LibGSF long len = Output.CurrentOffset - baseOffset; Output.Seek(baseOffset, SeekOrigin.Begin); - buf = BitConverter.GetBytes(len); - Output.Write(4, buf); - buf = BitConverter.GetBytes(count); - Output.Write(4, buf); + GSF_LE_SET_GUINT32(buf, 0, (uint)len); + GSF_LE_SET_GUINT32(buf, 0, count); + Output.Write(8, buf); for (i = 0; i < count; i++) { - buf = BitConverter.GetBytes(offsets[i].Id); - Output.Write(4, buf); - buf = BitConverter.GetBytes(offsets[i].Offset - baseOffset); - Output.Write(4, buf); + GSF_LE_SET_GUINT32(buf, 0, offsets[i].Id); + GSF_LE_SET_GUINT32(buf, 0, (uint)(offsets[i].Offset - baseOffset)); + Output.Write(8, buf); } return Output.Seek(0, SeekOrigin.End); @@ -1860,7 +1860,10 @@ namespace LibGSF private void WriteDictionaryEntry(string name, uint id) { - byte[] buf = BitConverter.GetBytes(id); + byte[] buf = new byte[4]; + + // TODO: `id` is a pointer not a value + GSF_LE_SET_GUINT32(buf, 0, id); Output.Write(4, buf); WriteString(name); } @@ -1877,7 +1880,7 @@ namespace LibGSF GsfMSOLEVariantType type = ValueToMSOLEVariant(value, map); if (!suppress_type) { - buf = BitConverter.GetBytes((uint)type); + GSF_LE_SET_GUINT32(buf, 0, (uint)type); Output.Write(4, buf); } @@ -1887,7 +1890,7 @@ namespace LibGSF int n = vector.Length; bool res; - buf = BitConverter.GetBytes(n); + GSF_LE_SET_GINT32(buf, 0, n); res = Output.Write(4, buf); for (int i = 0; i < n; i++) { @@ -1902,36 +1905,36 @@ namespace LibGSF { case GsfMSOLEVariantType.VT_BOOL: if ((bool)value) - buf = BitConverter.GetBytes(0xffffffff); + GSF_LE_SET_GUINT32(buf, 0, 0xffffffff); else - buf = BitConverter.GetBytes(0); + GSF_LE_SET_GINT32(buf, 0, 0); return Output.Write(4, buf); case GsfMSOLEVariantType.VT_UI1: - buf = BitConverter.GetBytes((int)(byte)value); + GSF_LE_SET_GUINT32(buf, 0, (uint)value); return Output.Write(4, buf); case GsfMSOLEVariantType.VT_I2: - buf = BitConverter.GetBytes((short)value); - byte[] buf2 = BitConverter.GetBytes((short)0); - return Output.Write(2, buf) && Output.Write(2, buf2); + GSF_LE_SET_GINT16(buf, 0, (short)value); + GSF_LE_SET_GUINT16(buf, 2, 0); + return Output.Write(4, buf); case GsfMSOLEVariantType.VT_I4: - buf = BitConverter.GetBytes((int)value); + GSF_LE_SET_GINT32(buf, 0, (int)value); return Output.Write(4, buf); case GsfMSOLEVariantType.VT_UI2: case GsfMSOLEVariantType.VT_UI4: - buf = BitConverter.GetBytes((uint)value); + GSF_LE_SET_GUINT32(buf, 0, (uint)value); return Output.Write(4, buf); case GsfMSOLEVariantType.VT_R4: - buf = BitConverter.GetBytes((float)value); + GSF_LE_SET_FLOAT(buf, 0, (float)value); return Output.Write(4, buf); case GsfMSOLEVariantType.VT_R8: - buf = BitConverter.GetBytes((double)value); + GSF_LE_SET_DOUBLE(buf, 0, (double)value); return Output.Write(8, buf); case GsfMSOLEVariantType.VT_LPSTR: @@ -1940,8 +1943,7 @@ namespace LibGSF case GsfMSOLEVariantType.VT_FILETIME: { DateTime ts = (DateTime)value; - ulong ft = (ulong)ts.ToFileTime(); - buf = BitConverter.GetBytes(ft); + GSF_LE_SET_GUINT64(buf, 0, (ulong)ts.ToFileTime()); return Output.Write(8, buf); } @@ -1985,13 +1987,13 @@ namespace LibGSF } // *Bytes*, not characters, including the termination, but not the padding. - buf = BitConverter.GetBytes(bytes_written + CharSize); + GSF_LE_SET_GUINT32(buf, 0, (uint)(bytes_written + CharSize)); res = Output.Write(4, buf); res = res && Output.Write(bytes_written, ctxt); - buf = BitConverter.GetBytes((uint)0); - res = res && Output.Write((int)CharSize, buf); + GSF_LE_SET_GUINT32(buf, 0, 0); + res = res && Output.Write(CharSize, buf); if (CharSize > 1) { diff --git a/BurnOutSharp/External/libgsf/GsfUtils.cs b/BurnOutSharp/External/libgsf/GsfUtils.cs new file mode 100644 index 00000000..22378405 --- /dev/null +++ b/BurnOutSharp/External/libgsf/GsfUtils.cs @@ -0,0 +1,266 @@ +/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * gsf-utils.c: + * + * Copyright (C) 2002-2006 Jody Goldberg (jody@gnome.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2.1 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +using System; + +namespace LibGSF +{ + /// + /// Do this the ugly way so that we don't have to worry about alignment + /// + internal static class GsfUtils + { + #region GET + + /// + /// Interpret binary data as an unsigned 8-bit integer in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static byte GSF_LE_GET_GUINT8(byte[] data, int p) + => data[p]; + + /// + /// Interpret binary data as an unsigned 16-bit integer in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static ushort GSF_LE_GET_GUINT16(byte[] data, int p) + => (ushort)((data[p] << 0) + | (data[p + 1] << 8)); + + /// + /// Interpret binary data as an unsigned 32-bit integer in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static uint GSF_LE_GET_GUINT32(byte[] data, int p) + => (uint)((data[p] << 0) + | (data[p + 1] << 8) + | (data[p + 2] << 16) + | (data[p + 3] << 24)); + + /// + /// Interpret binary data as an unsigned 64-bit integer in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static ulong GSF_LE_GET_GUINT64(byte[] data, int p) + => (uint)((data[p] << 0) + | (data[p + 1] << 8) + | (data[p + 2] << 16) + | (data[p + 3] << 24) + | (data[p + 4] << 32) + | (data[p + 5] << 40) + | (data[p + 6] << 48) + | (data[p + 7] << 56)); + + /// + /// Interpret binary data as a signed 8-bit integer in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static sbyte GSF_LE_GET_GINT8(byte[] data, int p) => (sbyte)GSF_LE_GET_GINT8(data, p); + + /// + /// Interpret binary data as a signed 16-bit integer in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static short GSF_LE_GET_GINT16(byte[] data, int p) => (short)GSF_LE_GET_GUINT16(data, p); + + /// + /// Interpret binary data as a signed 32-bit integer in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static int GSF_LE_GET_GINT32(byte[] data, int p) => (int)GSF_LE_GET_GUINT32(data, p); + + /// + /// Interpret binary data as a signed 64-bit integer in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static long GSF_LE_GET_GINT64(byte[] data, int p) => (long)GSF_LE_GET_GUINT64(data, p); + + /// + /// Interpret binary data as a float in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static float GSF_LE_GET_FLOAT(byte[] data, int p) + { + byte[] temp = new ReadOnlySpan(data, p, 4).ToArray(); + if (!BitConverter.IsLittleEndian) + Array.Reverse(temp); + + return BitConverter.ToSingle(temp, 0); + } + + /// + /// Interpret binary data as a double in little endian order. + /// + /// Storage + /// Pointer to storage + /// Interpreted data + public static double GSF_LE_GET_DOUBLE(byte[] data, int p) + { + byte[] temp = new ReadOnlySpan(data, p, 8).ToArray(); + if (!BitConverter.IsLittleEndian) + Array.Reverse(temp); + + return BitConverter.ToDouble(temp, 0); + } + + #endregion + + #region SET + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// 8-bit unsigned integer + public static void GSF_LE_SET_GUINT8(byte[] data, int p, byte dat) + { + data[p] = (byte)(dat & 0xff); + } + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// 16-bit unsigned integer + public static void GSF_LE_SET_GUINT16(byte[] data, int p, ushort dat) + { + data[p + 0] = (byte)(dat & 0xff); + data[p + 1] = (byte)((dat >> 8) & 0xff); + } + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// 32-bit unsigned integer + public static void GSF_LE_SET_GUINT32(byte[] data, int p, uint dat) + { + data[p + 0] = (byte)(dat & 0xff); + data[p + 1] = (byte)((dat >> 8) & 0xff); + data[p + 2] = (byte)((dat >> 16) & 0xff); + data[p + 3] = (byte)((dat >> 24) & 0xff); + } + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// 64-bit unsigned integer + public static void GSF_LE_SET_GUINT64(byte[] data, int p, ulong dat) + { + data[p + 0] = (byte)(dat & 0xff); + data[p + 1] = (byte)((dat >> 8) & 0xff); + data[p + 2] = (byte)((dat >> 16) & 0xff); + data[p + 3] = (byte)((dat >> 24) & 0xff); + data[p + 4] = (byte)((dat >> 32) & 0xff); + data[p + 5] = (byte)((dat >> 40) & 0xff); + data[p + 6] = (byte)((dat >> 48) & 0xff); + data[p + 7] = (byte)((dat >> 56) & 0xff); + } + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// 8-bit signed integer + public static void GSF_LE_SET_GINT8(byte[] data, int p, sbyte dat) => GSF_LE_SET_GUINT8(data, p, (byte)dat); + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// 16-bit signed integer + public static void GSF_LE_SET_GINT16(byte[] data, int p, short dat) => GSF_LE_SET_GUINT16(data, p, (ushort)dat); + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// 32-bit signed integer + public static void GSF_LE_SET_GINT32(byte[] data, int p, int dat) => GSF_LE_SET_GUINT32(data, p, (uint)dat); + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// 64-bit signed integer + public static void GSF_LE_SET_GINT64(byte[] data, int p, long dat) => GSF_LE_SET_GUINT64(data, p, (ulong)dat); + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// Float to be stored + public static void GSF_LE_SET_FLOAT(byte[] data, int p, float dat) + { + byte[] temp = BitConverter.GetBytes(dat); + if (!BitConverter.IsLittleEndian) + Array.Reverse(temp); + + Array.Copy(temp, 0, data, p, 4); + } + + /// + /// Store in little endian order in memory pointed to by . + /// + /// Storage + /// Pointer to storage + /// Double to be stored + public static void GSF_LE_SET_DOUBLE(byte[] data, int p, double dat) + { + byte[] temp = BitConverter.GetBytes(dat); + if (!BitConverter.IsLittleEndian) + Array.Reverse(temp); + + Array.Copy(temp, 0, data, p, 8); + } + + #endregion + + } +} diff --git a/BurnOutSharp/External/libgsf/Input/GsfInfileMSOle.cs b/BurnOutSharp/External/libgsf/Input/GsfInfileMSOle.cs index d355f0db..40ad9aec 100644 --- a/BurnOutSharp/External/libgsf/Input/GsfInfileMSOle.cs +++ b/BurnOutSharp/External/libgsf/Input/GsfInfileMSOle.cs @@ -30,6 +30,7 @@ using System.IO; using System.Linq; using System.Text; using static LibGSF.GsfMSOleImpl; +using static LibGSF.GsfUtils; namespace LibGSF.Input { @@ -39,9 +40,7 @@ namespace LibGSF.Input public uint[] Block { get; set; } = null; - public int BlockPointer { get; set; } = 0; - - public int NumBlocks { get; set; } + public uint NumBlocks { get; set; } #endregion @@ -60,12 +59,13 @@ namespace LibGSF.Input /// An optional guess as to how many blocks are in the file /// The first block in the list. /// Where to store the result. - /// true on error. + /// True on error. public static bool Create(MSOleBAT metabat, int size_guess, uint block, out MSOleBAT res) { // NOTE : Only use size as a suggestion, sometimes it is wrong uint[] bat = new uint[size_guess]; int batPtr = 0; // bat[0] + byte[] used = new byte[1 + metabat.NumBlocks / 8]; while (block < metabat.NumBlocks) @@ -82,7 +82,7 @@ namespace LibGSF.Input res = new MSOleBAT { - NumBlocks = bat.Length, + NumBlocks = (uint)bat.Length, Block = bat, }; @@ -107,7 +107,50 @@ namespace LibGSF.Input NumBlocks = 0; Block = null; - BlockPointer = 0; + } + + #endregion + } + + public class MSOleDirent + { + #region Properties + + public string Name { get; set; } + + public GsfMSOleSortingKey Key { get; set; } + + public int Index { get; set; } + + public int Size { get; set; } + + public bool UseSmallBlock { get; set; } + + public uint FirstBlock { get; set; } + + public bool IsDirectory { get; set; } + + public List Children { get; set; } + + /// + /// 16 byte GUID used by some apps + /// + public byte[] ClassID { get; set; } = new byte[16]; + + public DateTime? ModTime { get; set; } + + #endregion + + #region Functions + + private void Free() + { + foreach (MSOleDirent child in Children) + { + child.Free(); + } + + Children = null; } #endregion @@ -117,13 +160,13 @@ namespace LibGSF.Input { #region Classes - public class MSOLEInfoPrivateStruct + public class MSOleInfoBlock { public MSOleBAT Bat { get; set; } public int Shift { get; set; } - public uint Filter { get; set; } + public int Filter { get; set; } public int Size { get; set; } } @@ -132,9 +175,9 @@ namespace LibGSF.Input #region Properties - public MSOLEInfoPrivateStruct BigBlock { get; set; } + public MSOleInfoBlock BigBlock { get; set; } - public MSOLEInfoPrivateStruct SmallBlock { get; set; } + public MSOleInfoBlock SmallBlock { get; set; } public long MaxBlock { get; set; } @@ -143,11 +186,11 @@ namespace LibGSF.Input /// public uint Threshold { get; set; } - public uint SbatStart { get; set; } + public uint SBatStart { get; set; } public uint NumSbat { get; set; } - public MSOLEDirectoryEntry RootDir { get; set; } + public MSOleDirent RootDir { get; set; } public GsfInput SmallBlockFile { get; set; } @@ -180,50 +223,6 @@ namespace LibGSF.Input #endregion } - public class MSOLEDirectoryEntry - { - #region Properties - - public string Name { get; set; } - - public GsfMSOleSortingKey Key { get; set; } - - public int Index { get; set; } - - public int Size { get; set; } - - public bool UseSmallBlock { get; set; } - - public uint FirstBlock { get; set; } - - public bool IsDirectory { get; set; } - - public List Children { get; set; } - - /// - /// 16 byte GUID used by some apps - /// - public byte[] ClassID { get; set; } = new byte[16]; - - public DateTime? ModTime { get; set; } - - #endregion - - #region Functions - - private void Free() - { - foreach (MSOLEDirectoryEntry child in Children) - { - child.Free(); - } - - Children = null; - } - - #endregion - } - public class GsfInfileMSOle : GsfInfile { #region Properties @@ -232,17 +231,49 @@ namespace LibGSF.Input public MSOleInfo Info { get; private set; } = null; - public MSOLEDirectoryEntry DirectoryEntry { get; private set; } + public MSOleDirent DirectoryEntry { get; private set; } public MSOleBAT Bat { get; private set; } public long CurBlock { get; private set; } = BAT_MAGIC_UNUSED; + /// Actually `{ byte[] Buf, long BufSize }` public byte[] Stream { get; private set; } #endregion - #region Destructor + #region Constructor and Destructor + + /// + /// Private constructor + /// + private GsfInfileMSOle() { } + + /// + /// Opens the root directory of an MS OLE file. + /// + /// GsfInput + /// Optional place to store an error + /// The new ole file handler + /// This adds a reference to . + public static GsfInfile Create(GsfInput source, ref Exception err) + { + GsfInfileMSOle ole = new GsfInfileMSOle + { + Input = source, + Size = 0, + }; + + long calling_pos = source.CurrentOffset; + if (ole.InitInfo(ref err)) + { + // We do this so other kinds of archives can be tried. + source.Seek(calling_pos, SeekOrigin.Begin); + return null; + } + + return ole; + } /// /// Destructor @@ -348,7 +379,7 @@ namespace LibGSF.Input /// public override GsfInput ChildByIndex(int i, ref Exception error) { - foreach (MSOLEDirectoryEntry dirent in DirectoryEntry.Children) + foreach (MSOleDirent dirent in DirectoryEntry.Children) { if (i-- <= 0) return CreateChild(dirent, ref error); @@ -360,7 +391,7 @@ namespace LibGSF.Input /// public override string NameByIndex(int i) { - foreach (MSOLEDirectoryEntry dirent in DirectoryEntry.Children) + foreach (MSOleDirent dirent in DirectoryEntry.Children) { if (i-- <= 0) return dirent.Name; @@ -372,7 +403,7 @@ namespace LibGSF.Input /// public override GsfInput ChildByName(string name, ref Exception error) { - foreach (MSOLEDirectoryEntry dirent in DirectoryEntry.Children) + foreach (MSOleDirent dirent in DirectoryEntry.Children) { if (dirent.Name != null && dirent.Name == name) return CreateChild(dirent, ref error); @@ -393,38 +424,12 @@ namespace LibGSF.Input return DirectoryEntry.Children.Count; } - /// - /// Opens the root directory of an MS OLE file. - /// - /// GsfInput - /// Optional place to store an error - /// The new ole file handler - /// This adds a reference to . - public static GsfInfile Create(GsfInput source, ref Exception err) - { - GsfInfileMSOle ole = new GsfInfileMSOle - { - Input = source, - Size = 0, - }; - - long calling_pos = source.CurrentOffset; - if (ole.InitInfo(ref err)) - { - // We do this so other kinds of archives can be tried. - source.Seek(calling_pos, SeekOrigin.Begin); - return null; - } - - return ole; - } - /// /// Retrieves the 16 byte indentifier (often a GUID in MS Windows apps) /// stored within the directory associated with @ole and stores it in . /// /// 16 byte identifier (often a GUID in MS Windows apps) - /// true on success + /// True on success public bool GetClassID(byte[] res) { if (DirectoryEntry == null) @@ -472,9 +477,9 @@ namespace LibGSF.Input /// either from the OLE header, or a meta-bat block. /// /// A pointer to the element after the last position filled - private uint[] ReadMetabat(uint[] bats, int batsPtr, int max_bat, uint[] metabat, int metabatPtr, int metabat_end) + private uint[] ReadMetabat(uint[] bats, int batsPtr, int max_bat, uint[] metabat, int metabat_end) { - for (; metabatPtr < metabat_end; metabatPtr++) + for (int metabatPtr = 0; metabatPtr < metabat_end; metabatPtr++) { if (metabat[metabatPtr] != BAT_MAGIC_UNUSED) { @@ -482,11 +487,10 @@ namespace LibGSF.Input if (bat == null) return null; - int batPtr = 0; // bat[0] - int end = batPtr + Info.BigBlock.Size; - for (; batPtr < end; batPtr += BAT_INDEX_SIZE, batsPtr++) + int end = Info.BigBlock.Size; + for (int batPtr = 0; batPtr < end; batPtr += BAT_INDEX_SIZE, batsPtr++) { - bats[batsPtr] = BitConverter.ToUInt32(bat, batPtr); + bats[batsPtr] = GSF_LE_GET_GUINT32(bat, batPtr); if (bats[batsPtr] >= max_bat && bats[batsPtr] < BAT_MAGIC_METABAT) { Console.Error.WriteLine($"Invalid metabat item {bats[batsPtr]}"); @@ -518,7 +522,7 @@ namespace LibGSF.Input { for (; (num_bytes -= BAT_INDEX_SIZE) >= 0; srcPtr += BAT_INDEX_SIZE) { - dst[dstPtr++] = BitConverter.ToUInt32(src, srcPtr); + dst[dstPtr++] = GSF_LE_GET_GUINT32(src, srcPtr); } } @@ -538,21 +542,21 @@ namespace LibGSF.Input if (Info.SmallBlock.Bat.Block != null) return null; - if (MSOleBAT.Create(Info.BigBlock.Bat, (int)Info.NumSbat, Info.SbatStart, out MSOleBAT meta_sbat)) + if (MSOleBAT.Create(Info.BigBlock.Bat, (int)Info.NumSbat, Info.SBatStart, out MSOleBAT meta_sbat)) return null; - Info.SmallBlock.Bat.NumBlocks = meta_sbat.NumBlocks * (Info.BigBlock.Size / BAT_INDEX_SIZE); + Info.SmallBlock.Bat.NumBlocks = (uint)(meta_sbat.NumBlocks * (Info.BigBlock.Size / BAT_INDEX_SIZE)); Info.SmallBlock.Bat.Block = new uint[Info.SmallBlock.Bat.NumBlocks]; - ReadMetabat(Info.SmallBlock.Bat.Block, 0, Info.SmallBlock.Bat.NumBlocks, meta_sbat.Block, 0, meta_sbat.NumBlocks); + ReadMetabat(Info.SmallBlock.Bat.Block, 0, (int)Info.SmallBlock.Bat.NumBlocks, meta_sbat.Block, (int)meta_sbat.NumBlocks); return Info.SmallBlockFile; } - private static int DirectoryEntryCompare(MSOLEDirectoryEntry a, MSOLEDirectoryEntry b) => SortingKeyCompare(a.Key, b.Key); + private static int DirectoryEntryCompare(MSOleDirent a, MSOleDirent b) => SortingKeyCompare(a.Key, b.Key); private static DateTime? DateTimeFromFileTime(ulong ft) => ft == 0 ? (DateTime?)null : DateTime.FromFileTime((long)ft); - private GsfInput CreateChild(MSOLEDirectoryEntry dirent, ref Exception err) + private GsfInput CreateChild(MSOleDirent dirent, ref Exception err) { GsfInfileMSOle child = PartiallyDuplicate(ref err); if (child == null) @@ -587,7 +591,7 @@ namespace LibGSF.Input if (dirent.UseSmallBlock) { metabat = info.SmallBlock.Bat; - size_guess = dirent.Size >> (int)info.SmallBlock.Shift; + size_guess = dirent.Size >> info.SmallBlock.Shift; sb_file = GetSmallBlockFile(); if (sb_file == null) { @@ -598,7 +602,7 @@ namespace LibGSF.Input else { metabat = info.BigBlock.Bat; - size_guess = dirent.Size >> (int)info.BigBlock.Shift; + size_guess = dirent.Size >> info.BigBlock.Shift; } if (MSOleBAT.Create(metabat, size_guess + 1, dirent.FirstBlock, out MSOleBAT tempBat)) @@ -639,7 +643,7 @@ namespace LibGSF.Input /// /// Parse dirent number and recursively handle its siblings and children. /// parent is optional. - private MSOLEDirectoryEntry CreateDirectoryEntry(uint entry, MSOLEDirectoryEntry parent, bool[] seen_before) + private MSOleDirent CreateDirectoryEntry(uint entry, MSOleDirent parent, bool[] seen_before) { if (entry >= DIRENT_MAGIC_END) return null; @@ -663,7 +667,7 @@ namespace LibGSF.Input int dataPtr = 0; // data[0] dataPtr += (int)((DIRENT_SIZE * entry) % Info.BigBlock.Size); - byte type = data[dataPtr + DIRENT_TYPE]; + byte type = GSF_LE_GET_GUINT8(data, dataPtr + DIRENT_TYPE); if (type != DIRENT_TYPE_DIR && type != DIRENT_TYPE_FILE && type != DIRENT_TYPE_ROOTDIR) { Console.Error.WriteLine($"Unknown stream type 0x{type:x}"); @@ -678,13 +682,13 @@ namespace LibGSF.Input } // It looks like directory (and root directory) sizes are sometimes bogus - uint size = BitConverter.ToUInt32(data, dataPtr + DIRENT_FILE_SIZE); + uint size = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_FILE_SIZE); if (!(type == DIRENT_TYPE_DIR || type == DIRENT_TYPE_ROOTDIR || size <= (uint)Input.Size)) return null; - ulong ft = BitConverter.ToUInt64(data, dataPtr + DIRENT_MODIFY_TIME); + ulong ft = GSF_LE_GET_GUINT64(data, dataPtr + DIRENT_MODIFY_TIME); - MSOLEDirectoryEntry dirent = new MSOLEDirectoryEntry + MSOleDirent dirent = new MSOleDirent { Index = (int)entry, Size = (int)size, @@ -696,14 +700,14 @@ namespace LibGSF.Input // Root dir is always big block dirent.UseSmallBlock = parent != null && (size < Info.Threshold); - dirent.FirstBlock = BitConverter.ToUInt32(data, dataPtr + DIRENT_FIRSTBLOCK); + dirent.FirstBlock = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_FIRSTBLOCK); dirent.IsDirectory = (type != DIRENT_TYPE_FILE); dirent.Children = null; - uint prev = BitConverter.ToUInt32(data, dataPtr + DIRENT_PREV); - uint next = BitConverter.ToUInt32(data, dataPtr + DIRENT_NEXT); - uint child = BitConverter.ToUInt32(data, dataPtr + DIRENT_CHILD); - ushort name_len = BitConverter.ToUInt16(data, dataPtr + DIRENT_NAME_LEN); + uint prev = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_PREV); + uint next = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_NEXT); + uint child = GSF_LE_GET_GUINT32(data, dataPtr + DIRENT_CHILD); + ushort name_len = GSF_LE_GET_GUINT16(data, dataPtr + DIRENT_NAME_LEN); dirent.Name = null; if (0 < name_len && name_len <= DIRENT_MAX_NAME_SIZE) @@ -717,6 +721,7 @@ namespace LibGSF.Input try { end = new UTF8Encoding(false, true).GetCharCount(data); } catch { end = -1; } + // TODO: Read original code and rewrite this if (end == -1 || (end + 1) != name_len) { byte[] direntNameBytes = Encoding.Convert(Encoding.ASCII, Encoding.UTF8, data, 0, end); @@ -777,7 +782,7 @@ namespace LibGSF.Input /// Read an OLE header and do some sanity checking /// along the way. /// - /// true on error setting if it is supplied. + /// True on error setting if it is supplied. private bool InitInfo(ref Exception err) { byte[] header; @@ -785,21 +790,21 @@ namespace LibGSF.Input // Check the header byte[] signature = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }; if (Input.Seek(0, SeekOrigin.Begin) - || null == (header = Input.Read(OLE_HEADER_SIZE, null)) + || (header = Input.Read(OLE_HEADER_SIZE, null)) == null || !header.Take(signature.Length).SequenceEqual(signature)) { err = new Exception("No OLE2 signature"); return true; } - ushort bb_shift = BitConverter.ToUInt16(header, OLE_HEADER_BB_SHIFT); - ushort sb_shift = BitConverter.ToUInt16(header, OLE_HEADER_SB_SHIFT); - uint num_bat = BitConverter.ToUInt32(header, OLE_HEADER_NUM_BAT); - uint num_sbat = BitConverter.ToUInt32(header, OLE_HEADER_NUM_SBAT); - uint threshold = BitConverter.ToUInt32(header, OLE_HEADER_THRESHOLD); - uint dirent_start = BitConverter.ToUInt32(header, OLE_HEADER_DIRENT_START); - uint metabat_block = BitConverter.ToUInt32(header, OLE_HEADER_METABAT_BLOCK); - uint num_metabat = BitConverter.ToUInt32(header, OLE_HEADER_NUM_METABAT); + ushort bb_shift = GSF_LE_GET_GUINT16(header, OLE_HEADER_BB_SHIFT); + ushort sb_shift = GSF_LE_GET_GUINT16(header, OLE_HEADER_SB_SHIFT); + uint num_bat = GSF_LE_GET_GUINT32(header, OLE_HEADER_NUM_BAT); + uint num_sbat = GSF_LE_GET_GUINT32(header, OLE_HEADER_NUM_SBAT); + uint threshold = GSF_LE_GET_GUINT32(header, OLE_HEADER_THRESHOLD); + uint dirent_start = GSF_LE_GET_GUINT32(header, OLE_HEADER_DIRENT_START); + uint metabat_block = GSF_LE_GET_GUINT32(header, OLE_HEADER_METABAT_BLOCK); + uint num_metabat = GSF_LE_GET_GUINT32(header, OLE_HEADER_NUM_METABAT); // Some sanity checks // 1) There should always be at least 1 BAT block @@ -814,22 +819,22 @@ namespace LibGSF.Input MSOleInfo info = new MSOleInfo { RefCount = 1, - BigBlock = new MSOleInfo.MSOLEInfoPrivateStruct + BigBlock = new MSOleInfo.MSOleInfoBlock { Shift = bb_shift, Size = 1 << bb_shift, - Filter = (uint)(1 << bb_shift) - 1, + Filter = (1 << bb_shift) - 1, Bat = new MSOleBAT(), }, - SmallBlock = new MSOleInfo.MSOLEInfoPrivateStruct + SmallBlock = new MSOleInfo.MSOleInfoBlock { Shift = sb_shift, Size = 1 << sb_shift, - Filter = (uint)(1 << sb_shift) - 1, + Filter = (1 << sb_shift) - 1, Bat = new MSOleBAT(), }, Threshold = threshold, - SbatStart = BitConverter.ToUInt32(header, OLE_HEADER_SBAT_START), + SBatStart = GSF_LE_GET_GUINT32(header, OLE_HEADER_SBAT_START), NumSbat = num_sbat, MaxBlock = (Input.Size - OLE_HEADER_SIZE + (1 << bb_shift) - 1) / (1 << bb_shift), SmallBlockFile = null, @@ -837,7 +842,7 @@ namespace LibGSF.Input Info = info; - if (info.NumSbat == 0 && info.SbatStart != BAT_MAGIC_END_OF_CHAIN && info.SbatStart != BAT_MAGIC_UNUSED) + if (info.NumSbat == 0 && info.SBatStart != BAT_MAGIC_END_OF_CHAIN && info.SBatStart != BAT_MAGIC_UNUSED) Console.Error.WriteLine("There are not supposed to be any blocks in the small block allocation table, yet there is a link to some. Ignoring it."); uint[] metabat = null; @@ -847,7 +852,7 @@ namespace LibGSF.Input // Very rough heuristic, just in case if (num_bat < info.MaxBlock && info.NumSbat < info.MaxBlock) { - info.BigBlock.Bat.NumBlocks = (int)(num_bat * (info.BigBlock.Size / BAT_INDEX_SIZE)); + info.BigBlock.Bat.NumBlocks = (uint)(num_bat * (info.BigBlock.Size / BAT_INDEX_SIZE)); info.BigBlock.Bat.Block = new uint[info.BigBlock.Bat.NumBlocks]; metabat = new uint[Math.Max(info.BigBlock.Size, OLE_HEADER_SIZE)]; @@ -858,7 +863,7 @@ namespace LibGSF.Input if (last > OLE_HEADER_METABAT_SIZE) last = OLE_HEADER_METABAT_SIZE; - ptr = ReadMetabat(info.BigBlock.Bat.Block, 0, info.BigBlock.Bat.NumBlocks, metabat, 0, (int)last); + ptr = ReadMetabat(info.BigBlock.Bat.Block, 0, (int)info.BigBlock.Bat.NumBlocks, metabat, (int)last); num_bat -= last; } else @@ -906,7 +911,7 @@ namespace LibGSF.Input num_bat -= last; } - ptr = ReadMetabat(ptr, ptrPtr, info.BigBlock.Bat.NumBlocks, metabat, 0, (int)last); + ptr = ReadMetabat(ptr, ptrPtr, (int)info.BigBlock.Bat.NumBlocks, metabat, (int)last); } bool fail = (ptr == null); diff --git a/BurnOutSharp/External/libgsf/Input/GsfInfileMSVBA.cs b/BurnOutSharp/External/libgsf/Input/GsfInfileMSVBA.cs index ac1d67f5..e6083032 100644 --- a/BurnOutSharp/External/libgsf/Input/GsfInfileMSVBA.cs +++ b/BurnOutSharp/External/libgsf/Input/GsfInfileMSVBA.cs @@ -30,6 +30,7 @@ using System; using System.Collections.Generic; using System.Text; +using static LibGSF.GsfUtils; namespace LibGSF.Input { @@ -251,8 +252,8 @@ namespace LibGSF.Input return false; } - tag = BitConverter.ToUInt16(inflated_data, ptr); - uint len = BitConverter.ToUInt32(inflated_data, ptr + 2); + tag = GSF_LE_GET_GUINT16(inflated_data, ptr); + uint len = GSF_LE_GET_GUINT32(inflated_data, ptr + 2); ptr += 6; if ((ptr + len) > end) @@ -286,7 +287,7 @@ namespace LibGSF.Input break; } - element_count = BitConverter.ToUInt16(inflated_data, ptr); + element_count = GSF_LE_GET_GUINT16(inflated_data, ptr); break; // Dependencies @@ -315,7 +316,7 @@ namespace LibGSF.Input break; } - ExtractModuleSource(elem_stream, BitConverter.ToUInt32(inflated_data, ptr)); + ExtractModuleSource(elem_stream, GSF_LE_GET_GUINT32(inflated_data, ptr)); elem_stream = null; element_count--; break; diff --git a/BurnOutSharp/External/libgsf/Input/GsfInfileZip.cs b/BurnOutSharp/External/libgsf/Input/GsfInfileZip.cs index ec5108f2..3e86c0d7 100644 --- a/BurnOutSharp/External/libgsf/Input/GsfInfileZip.cs +++ b/BurnOutSharp/External/libgsf/Input/GsfInfileZip.cs @@ -27,6 +27,7 @@ using System.IO; using System.Text; using ComponentAce.Compression.Libs.zlib; using static ComponentAce.Compression.Libs.zlib.zlibConst; +using static LibGSF.GsfUtils; using static LibGSF.GsfZipImpl; namespace LibGSF.Input @@ -394,7 +395,7 @@ namespace LibGSF.Input for (int s = (int)(p + maplen - 1); (s >= p); s--, trailer_offset--) { - if (data[s] == sig1 && p + maplen - 1 - s > size - 2 && BitConverter.ToUInt32(data, s) == sig) + if (data[s] == sig1 && p + maplen - 1 - s > size - 2 && GSF_LE_GET_GUINT32(data, s) == sig) return --trailer_offset; } @@ -433,8 +434,8 @@ namespace LibGSF.Input return null; } - ExtraFieldTags ftyp = (ExtraFieldTags)BitConverter.ToUInt16(extra, extraPtr); - uint flen = BitConverter.ToUInt16(extra, extraPtr + 2); + ExtraFieldTags ftyp = (ExtraFieldTags)GSF_LE_GET_GUINT16(extra, extraPtr); + uint flen = GSF_LE_GET_GUINT16(extra, extraPtr + 2); if (flen > elen - 4) { pflen = 0; @@ -463,14 +464,14 @@ namespace LibGSF.Input byte[] data = header; if (Source.Seek(offset, SeekOrigin.Begin) || Source.Read(ZIP_DIRENT_SIZE, header) != null - || BitConverter.ToUInt32(data, 0) != ZIP_DIRENT_SIGNATURE) + || GSF_LE_GET_GUINT32(data, 0) != ZIP_DIRENT_SIGNATURE) { return null; } - ushort name_len = BitConverter.ToUInt16(header, ZIP_DIRENT_NAME_SIZE); - ushort extras_len = BitConverter.ToUInt16(header, ZIP_DIRENT_EXTRAS_SIZE); - ushort comment_len = BitConverter.ToUInt16(header, ZIP_DIRENT_COMMENT_SIZE); + ushort name_len = GSF_LE_GET_GUINT16(header, ZIP_DIRENT_NAME_SIZE); + ushort extras_len = GSF_LE_GET_GUINT16(header, ZIP_DIRENT_EXTRAS_SIZE); + ushort comment_len = GSF_LE_GET_GUINT16(header, ZIP_DIRENT_COMMENT_SIZE); int vlen = name_len + extras_len + comment_len; // Read variable part @@ -482,36 +483,36 @@ namespace LibGSF.Input int extraPtr = 0; // extra[0]; bool zip64 = (extra != null); - uint flags = BitConverter.ToUInt32(header, ZIP_DIRENT_FLAGS); - GsfZipCompressionMethod compression_method = (GsfZipCompressionMethod)BitConverter.ToUInt16(header, ZIP_DIRENT_COMPR_METHOD); - uint dostime = BitConverter.ToUInt32(header, ZIP_DIRENT_DOSTIME); - uint crc32 = BitConverter.ToUInt32(header, ZIP_DIRENT_CRC32); - long csize = BitConverter.ToUInt32(header, ZIP_DIRENT_CSIZE); - long usize = BitConverter.ToUInt32(header, ZIP_DIRENT_USIZE); - long off = BitConverter.ToUInt32(header, ZIP_DIRENT_OFFSET); - uint disk_start = BitConverter.ToUInt16(header, ZIP_DIRENT_DISKSTART); + uint flags = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_FLAGS); + GsfZipCompressionMethod compression_method = (GsfZipCompressionMethod)GSF_LE_GET_GUINT16(header, ZIP_DIRENT_COMPR_METHOD); + uint dostime = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_DOSTIME); + uint crc32 = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_CRC32); + long csize = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_CSIZE); + long usize = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_USIZE); + long off = GSF_LE_GET_GUINT32(header, ZIP_DIRENT_OFFSET); + uint disk_start = GSF_LE_GET_GUINT16(header, ZIP_DIRENT_DISKSTART); if (usize == 0xffffffffu && elen >= 8) { - usize = (long)BitConverter.ToUInt64(extra, extraPtr); + usize = (long)GSF_LE_GET_GUINT64(extra, extraPtr); extraPtr += 8; elen -= 8; } if (csize == 0xffffffffu && elen >= 8) { - csize = (long)BitConverter.ToUInt64(extra, extraPtr); + csize = (long)GSF_LE_GET_GUINT64(extra, extraPtr); extraPtr += 8; elen -= 8; } if (off == 0xffffffffu && elen >= 8) { - off = (long)BitConverter.ToUInt64(extra, extraPtr); + off = (long)GSF_LE_GET_GUINT64(extra, extraPtr); extraPtr += 8; elen -= 8; } if (disk_start == 0xffffu && elen >= 4) { - disk_start = BitConverter.ToUInt32(extra, extraPtr); + disk_start = GSF_LE_GET_GUINT32(extra, extraPtr); extraPtr += 4; elen -= 4; } @@ -557,7 +558,7 @@ namespace LibGSF.Input /// Read zip headers and do some sanity checking /// along the way. /// - /// true on error setting Err. + /// True on error setting Err. private bool ReadDirectoryEntries() { // Find and check the trailing header @@ -577,17 +578,17 @@ namespace LibGSF.Input int data = ZIP_ZIP64_LOCATOR_SIZE; // locator + ZIP_ZIP64_LOCATOR_SIZE - ulong entries = BitConverter.ToUInt16(locator, data + ZIP_TRAILER_ENTRIES); - ulong dir_pos = BitConverter.ToUInt32(locator, data + ZIP_TRAILER_DIR_POS); + ulong entries = GSF_LE_GET_GUINT16(locator, data + ZIP_TRAILER_ENTRIES); + ulong dir_pos = GSF_LE_GET_GUINT32(locator, data + ZIP_TRAILER_DIR_POS); - if (BitConverter.ToUInt32(locator, 0) == ZIP_ZIP64_LOCATOR_SIGNATURE) + if (GSF_LE_GET_GUINT32(locator, 0) == ZIP_ZIP64_LOCATOR_SIGNATURE) { Zip64 = true; data = 0; // locator[0] - uint disk = BitConverter.ToUInt32(locator, data + ZIP_ZIP64_LOCATOR_DISK); - ulong zip64_eod_offset = BitConverter.ToUInt64(locator, data + ZIP_ZIP64_LOCATOR_OFFSET); - uint disks = BitConverter.ToUInt32(locator, data + ZIP_ZIP64_LOCATOR_DISKS); + uint disk = GSF_LE_GET_GUINT32(locator, data + ZIP_ZIP64_LOCATOR_DISK); + ulong zip64_eod_offset = GSF_LE_GET_GUINT64(locator, data + ZIP_ZIP64_LOCATOR_OFFSET); + uint disks = GSF_LE_GET_GUINT32(locator, data + ZIP_ZIP64_LOCATOR_DISKS); if (disk != 0 || disks != 1) { @@ -602,14 +603,14 @@ namespace LibGSF.Input } locator = Source.Read(ZIP_TRAILER64_SIZE, null); - if (locator == null || BitConverter.ToUInt32(locator, data) != ZIP_TRAILER64_SIGNATURE) + if (locator == null || GSF_LE_GET_GUINT32(locator, data) != ZIP_TRAILER64_SIGNATURE) { Err = new Exception("Broken zip file structure"); return true; } - entries = BitConverter.ToUInt64(locator, data + ZIP_TRAILER64_ENTRIES); - dir_pos = BitConverter.ToUInt64(locator, data + ZIP_TRAILER64_DIR_POS); + entries = GSF_LE_GET_GUINT64(locator, data + ZIP_TRAILER64_ENTRIES); + dir_pos = GSF_LE_GET_GUINT64(locator, data + ZIP_TRAILER64_DIR_POS); } Info = new ZipInfo() @@ -651,7 +652,7 @@ namespace LibGSF.Input /// Read zip headers and do some sanity checking /// along the way. /// - /// true on error setting Err. + /// True on error setting Err. private bool InitInfo() { bool ret = ReadDirectoryEntries(); @@ -684,10 +685,10 @@ namespace LibGSF.Input { err = "Error reading zip header"; } - else if (BitConverter.ToUInt32(data, 0) != ZIP_HEADER_SIGNATURE) + else if (GSF_LE_GET_GUINT32(data, 0) != ZIP_HEADER_SIGNATURE) { err = "Error incorrect zip header"; - Console.Error.WriteLine("Header is 0x%x\n", BitConverter.ToUInt32(data, 0)); + Console.Error.WriteLine("Header is 0x%x\n", GSF_LE_GET_GUINT32(data, 0)); Console.Error.WriteLine("Expected 0x%x\n", ZIP_HEADER_SIGNATURE); } @@ -697,11 +698,11 @@ namespace LibGSF.Input return true; } - uint name_len = BitConverter.ToUInt16(data, ZIP_HEADER_NAME_SIZE); - uint extras_len = BitConverter.ToUInt16(data, ZIP_HEADER_EXTRAS_SIZE); + uint name_len = GSF_LE_GET_GUINT16(data, ZIP_HEADER_NAME_SIZE); + uint extras_len = GSF_LE_GET_GUINT16(data, ZIP_HEADER_EXTRAS_SIZE); dirent.DataOffset = dirent.Offset + ZIP_HEADER_SIZE + name_len + extras_len; - RestLen = dirent.UncompressedSize; + RestLen = dirent.UncompressedSize; CRestLen = dirent.CompressedSize; if (dirent.CompressionMethod != GsfZipCompressionMethod.GSF_ZIP_STORED) diff --git a/BurnOutSharp/External/libgsf/Input/GsfInput.cs b/BurnOutSharp/External/libgsf/Input/GsfInput.cs index c6a197cf..9bd77e38 100644 --- a/BurnOutSharp/External/libgsf/Input/GsfInput.cs +++ b/BurnOutSharp/External/libgsf/Input/GsfInput.cs @@ -26,6 +26,7 @@ using System.Linq; using System.Text; using LibGSF.Output; using static LibGSF.GsfMSOleUtils; +using static LibGSF.GsfUtils; namespace LibGSF.Input { @@ -113,7 +114,7 @@ namespace LibGSF.Input /// /// Are we at the end of the file? /// - /// true if the input is at the eof. + /// True if the input is at the eof. public bool EOF() => CurrentOffset >= Size; /// @@ -174,7 +175,7 @@ namespace LibGSF.Input /// Determines whether the offset is relative to the beginning or /// the end of the stream, or to the current location. /// - /// true on error. + /// True on error. public virtual bool Seek(long offset, SeekOrigin whence) { long pos = offset; @@ -203,7 +204,7 @@ namespace LibGSF.Input } /// The (fs-sys encoded) filename - /// true if the assignment was ok. + /// True if the assignment was ok. public bool SetNameFromFilename(string filename) { string name = null; @@ -222,7 +223,7 @@ namespace LibGSF.Input /// Emulate forward seeks by reading. /// /// Absolute position to seek to - /// true if the emulation failed. + /// True if the emulation failed. public bool SeekEmulate(long pos) { if (pos < CurrentOffset) @@ -245,7 +246,7 @@ namespace LibGSF.Input /// output.Seek(0, SeekOrigin.Begin) first, if applicable. /// /// A non-null GsfOutput - /// true on success + /// True on success public bool Copy(GsfOutput output) { if (output == null) @@ -389,7 +390,7 @@ namespace LibGSF.Input shift = 4; } - ushort token = BitConverter.ToUInt16(tmp, 0); + ushort token = GSF_LE_GET_GUINT16(tmp, 0); ushort len = (ushort)((token & ((1 << (int)shift) - 1)) + 3); uint distance = (uint)(token >> (int)shift); clean = true; @@ -445,7 +446,6 @@ namespace LibGSF.Input /// /// Decompresses VBA stream. /// - /// Stream to read from /// Offset into it for start byte of compressed stream /// Size of the returned array /// Whenever add or not null at the end of array @@ -470,7 +470,7 @@ namespace LibGSF.Input if (tmp == null) break; - ushort chunk_hdr = BitConverter.ToUInt16(tmp, 0); + ushort chunk_hdr = GSF_LE_GET_GUINT16(tmp, 0); offset += 2; GsfInput chunk; diff --git a/BurnOutSharp/External/libgsf/Input/GsfInputGZip.cs b/BurnOutSharp/External/libgsf/Input/GsfInputGZip.cs index 4aca363f..d692a94d 100644 --- a/BurnOutSharp/External/libgsf/Input/GsfInputGZip.cs +++ b/BurnOutSharp/External/libgsf/Input/GsfInputGZip.cs @@ -24,6 +24,7 @@ using System; using System.IO; using ComponentAce.Compression.Libs.zlib; using static ComponentAce.Compression.Libs.zlib.zlibConst; +using static LibGSF.GsfUtils; namespace LibGSF.Input { @@ -334,7 +335,7 @@ namespace LibGSF.Input if (data[2] != Z_DEFLATED) return true; - uint modutime = BitConverter.ToUInt32(data, 4); + uint modutime = GSF_LE_GET_GUINT32(data, 4); if (modutime != 0) { DateTime modtime = DateTimeOffset.FromUnixTimeSeconds(modutime).DateTime; @@ -352,7 +353,7 @@ namespace LibGSF.Input } // FIXME, but how? The size read here is modulo 2^32. - UncompressedSize = BitConverter.ToUInt32(data, 0); + UncompressedSize = GSF_LE_GET_GUINT32(data, 0); if (UncompressedSize / 1000 > Source.Size) { @@ -369,7 +370,7 @@ namespace LibGSF.Input if ((data = Source.Read(2, null)) == null) return true; - len = BitConverter.ToUInt16(data, 0); + len = GSF_LE_GET_GUINT16(data, 0); if (Source.Read((int)len, null) == null) return true; } diff --git a/BurnOutSharp/External/libgsf/Input/GsfStructuredBlob.cs b/BurnOutSharp/External/libgsf/Input/GsfStructuredBlob.cs index 2d8b2554..7997f559 100644 --- a/BurnOutSharp/External/libgsf/Input/GsfStructuredBlob.cs +++ b/BurnOutSharp/External/libgsf/Input/GsfStructuredBlob.cs @@ -183,7 +183,7 @@ namespace LibGSF.Input /// Dumps structured blob @blob onto the . Will fail if the output is /// not an Outfile and blob has multiple streams. /// - /// true on success. + /// True on success. public bool Write(GsfOutfile container) { if (container == null) diff --git a/BurnOutSharp/External/libgsf/Output/GsfOutfileMSOle.cs b/BurnOutSharp/External/libgsf/Output/GsfOutfileMSOle.cs index 0f5b188a..d2dea292 100644 --- a/BurnOutSharp/External/libgsf/Output/GsfOutfileMSOle.cs +++ b/BurnOutSharp/External/libgsf/Output/GsfOutfileMSOle.cs @@ -26,6 +26,7 @@ using System.Linq; using System.Text; using LibGSF.Input; using static LibGSF.GsfMSOleImpl; +using static LibGSF.GsfUtils; namespace LibGSF.Output { @@ -194,18 +195,12 @@ namespace LibGSF.Output byte[] buf = Enumerable.Repeat(0xFF, OLE_HEADER_SIZE).ToArray(); Array.Copy(default_header, buf, default_header.Length); - byte[] temp = BitConverter.GetBytes((ushort)ole.BigBlock.Shift); - Array.Copy(temp, 0, buf, OLE_HEADER_BB_SHIFT, temp.Length); - - temp = BitConverter.GetBytes((ushort)ole.SmallBlock.Shift); - Array.Copy(temp, 0, buf, OLE_HEADER_SB_SHIFT, temp.Length); + GSF_LE_SET_GUINT16(buf, OLE_HEADER_BB_SHIFT, (ushort)ole.BigBlock.Shift); + GSF_LE_SET_GUINT16(buf, OLE_HEADER_SB_SHIFT, (ushort)ole.SmallBlock.Shift); // 4k sector OLE files seen in the wild have version 4 if (ole.BigBlock.Size == 4096) - { - BitConverter.GetBytes((ushort)4); - Array.Copy(temp, 0, buf, OLE_HEADER_MAJOR_VER, temp.Length); - } + GSF_LE_SET_GUINT16(buf, OLE_HEADER_MAJOR_VER, 4); sink.Write(OLE_HEADER_SIZE, buf); @@ -433,7 +428,7 @@ namespace LibGSF.Output /// Write to the directory associated with ole. /// /// Identifier (often a GUID in MS Windows apps) - /// true on success. + /// True on success. public bool SetClassID(byte[] clsid) { if (Type != MSOleOutfileType.MSOLE_DIR) @@ -661,38 +656,28 @@ namespace LibGSF.Output // Be wary about endianness for (int j = 0; j < name_len; j++) { - byte[] nameUtf16Temp = BitConverter.GetBytes((ushort)nameUtf16[j]); - Array.Copy(nameUtf16Temp, 0, buf, j * 2, 2); + GSF_LE_SET_GUINT16(buf, j * 2, nameUtf16[j]); } name_len++; } - byte[] writeTemp = BitConverter.GetBytes((ushort)(name_len * 2)); - Array.Copy(writeTemp, 0, buf, DIRENT_NAME_LEN, writeTemp.Length); + GSF_LE_SET_GUINT16(buf, DIRENT_NAME_LEN, (ushort)(name_len * 2)); if (child.Root == child) { - buf[DIRENT_TYPE] = DIRENT_TYPE_ROOTDIR; - - writeTemp = BitConverter.GetBytes((uint)((sb_data_size > 0) ? (uint)sb_data_start : BAT_MAGIC_END_OF_CHAIN)); - Array.Copy(writeTemp, 0, buf, DIRENT_FIRSTBLOCK, writeTemp.Length); - - writeTemp = BitConverter.GetBytes((uint)(sb_data_size)); - Array.Copy(writeTemp, 0, buf, DIRENT_FILE_SIZE, writeTemp.Length); + GSF_LE_SET_GUINT8(buf, DIRENT_TYPE, DIRENT_TYPE_ROOTDIR); + GSF_LE_SET_GUINT32(buf, DIRENT_FIRSTBLOCK, (sb_data_size > 0) ? (uint)sb_data_start : BAT_MAGIC_END_OF_CHAIN); + GSF_LE_SET_GUINT32(buf, DIRENT_FILE_SIZE, (uint)sb_data_size); // Write the class id Array.Copy(child.ClassID, 0, buf, DIRENT_CLSID, child.ClassID.Length); } else if (child.Type == MSOleOutfileType.MSOLE_DIR) { - buf[DIRENT_TYPE] = DIRENT_TYPE_DIR; - - writeTemp = BitConverter.GetBytes((uint)(BAT_MAGIC_END_OF_CHAIN)); - Array.Copy(writeTemp, 0, buf, DIRENT_FIRSTBLOCK, writeTemp.Length); - - writeTemp = BitConverter.GetBytes((uint)(0)); - Array.Copy(writeTemp, 0, buf, DIRENT_FILE_SIZE, writeTemp.Length); + GSF_LE_SET_GUINT8(buf, DIRENT_TYPE, DIRENT_TYPE_DIR); + GSF_LE_SET_GUINT32(buf, DIRENT_FIRSTBLOCK, BAT_MAGIC_END_OF_CHAIN); + GSF_LE_SET_GUINT32(buf, DIRENT_FILE_SIZE, 0); // Write the class id Array.Copy(child.ClassID, 0, buf, DIRENT_CLSID, child.ClassID.Length); @@ -703,20 +688,15 @@ namespace LibGSF.Output if (size != child.Parent.CurrentSize) Console.Error.WriteLine("File too big"); - buf[DIRENT_TYPE] = DIRENT_TYPE_FILE; - - writeTemp = BitConverter.GetBytes((uint)(child.FirstBlock)); - Array.Copy(writeTemp, 0, buf, DIRENT_FIRSTBLOCK, writeTemp.Length); - - writeTemp = BitConverter.GetBytes((uint)(size)); - Array.Copy(writeTemp, 0, buf, DIRENT_FILE_SIZE, writeTemp.Length); + GSF_LE_SET_GUINT8(buf, DIRENT_TYPE, DIRENT_TYPE_FILE); + GSF_LE_SET_GUINT32(buf, DIRENT_FIRSTBLOCK, (uint)child.FirstBlock); + GSF_LE_SET_GUINT32(buf, DIRENT_FILE_SIZE, size); } - writeTemp = BitConverter.GetBytes((ulong)(child.ModTime?.ToFileTime() ?? 0)); - Array.Copy(writeTemp, 0, buf, DIRENT_MODIFY_TIME, writeTemp.Length); + GSF_LE_SET_GUINT64(buf, DIRENT_MODIFY_TIME, (ulong)(child.ModTime?.ToFileTime() ?? 0)); // Make everything black (red == 0) - buf[DIRENT_COLOUR] = 1; + GSF_LE_SET_GUINT8(buf, DIRENT_COLOUR, 1); GsfOutfileMSOle tmp = child.Container as GsfOutfileMSOle; next = DIRENT_MAGIC_END; @@ -739,11 +719,8 @@ namespace LibGSF.Output } // Make linked list rather than tree, only use next - writeTemp = BitConverter.GetBytes((uint)(DIRENT_MAGIC_END)); - Array.Copy(writeTemp, 0, buf, DIRENT_PREV, writeTemp.Length); - - writeTemp = BitConverter.GetBytes((uint)(next)); - Array.Copy(writeTemp, 0, buf, DIRENT_NEXT, writeTemp.Length); + GSF_LE_SET_GUINT32(buf, DIRENT_PREV, DIRENT_MAGIC_END); + GSF_LE_SET_GUINT32(buf, DIRENT_NEXT, next); uint child_index = DIRENT_MAGIC_END; if (child.Type == MSOleOutfileType.MSOLE_DIR && child.Content_Dir_Children != null) @@ -752,8 +729,7 @@ namespace LibGSF.Output child_index = (uint)first.ChildIndex; } - writeTemp = BitConverter.GetBytes((uint)(child_index)); - Array.Copy(writeTemp, 0, buf, DIRENT_CHILD, writeTemp.Length); + GSF_LE_SET_GUINT32(buf, DIRENT_CHILD, child_index); Sink.Write(DIRENT_SIZE, buf); } @@ -830,40 +806,27 @@ namespace LibGSF.Output if (BigBlock.Size == 4096) { // Set _cSectDir for 4k sector files - outerTemp = BitConverter.GetBytes((uint)(num_dirent_blocks)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); - + GSF_LE_SET_GUINT32(buf, 0, (uint)num_dirent_blocks); Sink.Seek(OLE_HEADER_CSECTDIR, SeekOrigin.Begin); Sink.Write(4, buf); } + GSF_LE_SET_GUINT32(buf, 0, (uint)num_bat); + GSF_LE_SET_GUINT32(buf, 4, (uint)dirent_start); Sink.Seek(OLE_HEADER_NUM_BAT, SeekOrigin.Begin); - outerTemp = BitConverter.GetBytes((uint)(num_bat)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); - Sink.Write(4, buf); - outerTemp = BitConverter.GetBytes((uint)(dirent_start)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); - Sink.Write(4, buf); + Sink.Write(8, buf); + GSF_LE_SET_GUINT32(buf, 0x0, (num_sbat > 0) ? (uint)sbat_start : BAT_MAGIC_END_OF_CHAIN); + GSF_LE_SET_GUINT32(buf, 0x4, (uint)num_sbat); + GSF_LE_SET_GUINT32(buf, 0x8, xbat_pos); + GSF_LE_SET_GUINT32(buf, 0xc, (uint)num_xbat); Sink.Seek(OLE_HEADER_SBAT_START, SeekOrigin.Begin); - outerTemp = BitConverter.GetBytes((uint)((num_sbat > 0) ? (uint)sbat_start : BAT_MAGIC_END_OF_CHAIN)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); - Sink.Write(4, buf); - outerTemp = BitConverter.GetBytes((uint)(num_sbat)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); - Sink.Write(4, buf); - outerTemp = BitConverter.GetBytes((uint)(xbat_pos)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); - Sink.Write(4, buf); - outerTemp = BitConverter.GetBytes((uint)(num_xbat)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); - Sink.Write(4, buf); + Sink.Write(0x10, buf); // Write initial Meta-BAT for (int i = 0; i < blocks; i++) { - outerTemp = BitConverter.GetBytes((uint)(bat_start + i)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); + GSF_LE_SET_GUINT32(buf, 0, (uint)(bat_start + i)); Sink.Write(BAT_INDEX_SIZE, buf); } @@ -878,8 +841,7 @@ namespace LibGSF.Output blocks = (int)((num_bat > metabat_size) ? metabat_size : num_bat); for (int j = 0; j < blocks; j++) { - outerTemp = BitConverter.GetBytes((uint)(bat_start + j)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); + GSF_LE_SET_GUINT32(buf, 0, (uint)(bat_start + j)); Sink.Write(BAT_INDEX_SIZE, buf); } @@ -893,8 +855,7 @@ namespace LibGSF.Output xbat_pos++; } - outerTemp = BitConverter.GetBytes((uint)(xbat_pos)); - Array.Copy(outerTemp, 0, buf, 0, outerTemp.Length); + GSF_LE_SET_GUINT32(buf, 0, xbat_pos); Sink.Write(BAT_INDEX_SIZE, buf); } } diff --git a/BurnOutSharp/External/libgsf/Output/GsfOutfileZip.cs b/BurnOutSharp/External/libgsf/Output/GsfOutfileZip.cs index 4ad3d736..90e1ecb7 100644 --- a/BurnOutSharp/External/libgsf/Output/GsfOutfileZip.cs +++ b/BurnOutSharp/External/libgsf/Output/GsfOutfileZip.cs @@ -26,6 +26,7 @@ using System.IO; using System.Text; using ComponentAce.Compression.Libs.zlib; using static ComponentAce.Compression.Libs.zlib.zlibConst; +using static LibGSF.GsfUtils; using static LibGSF.GsfZipImpl; namespace LibGSF.Output @@ -321,7 +322,7 @@ namespace LibGSF.Output if (zip64_here) { - List tmp = new List(); + byte[] tmp = new byte[8]; // We could unconditionally store the offset here, but // zipinfo has a known bug in which it fails to account @@ -329,110 +330,119 @@ namespace LibGSF.Output // and the local headers. So we try to make them the // same. - tmp.AddRange(BitConverter.GetBytes((ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_ZIP64))); - tmp.AddRange(BitConverter.GetBytes((ushort)((2 + (offset_in_zip64 ? 1 : 0) * 8)))); - tmp.AddRange(BitConverter.GetBytes((ulong)(dirent.UncompressedSize))); - tmp.AddRange(BitConverter.GetBytes((ulong)(dirent.CompressedSize))); + GSF_LE_SET_GUINT16(tmp, 0, (ushort)ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_ZIP64); + GSF_LE_SET_GUINT16(tmp, 2, (ushort)(2 + (offset_in_zip64 ? 1 : 0) * 8)); + extras.AddRange(new ReadOnlySpan(tmp, 0, 4).ToArray()); + GSF_LE_SET_GUINT64(tmp, 0, (ulong)dirent.UncompressedSize); + extras.AddRange(new ReadOnlySpan(tmp, 0, 8).ToArray()); + GSF_LE_SET_GUINT64(tmp, 0, (ulong)dirent.CompressedSize); + extras.AddRange(new ReadOnlySpan(tmp, 0, 8).ToArray()); if (offset_in_zip64) - tmp.AddRange(BitConverter.GetBytes((ulong)(dirent.Offset))); - - extras.AddRange(tmp); + { + GSF_LE_SET_GUINT64(tmp, 0, (ulong)dirent.Offset); + extras.AddRange(new ReadOnlySpan(tmp, 0, 8).ToArray()); + } } else if (dirent.Zip64 == null) { - List tmp = new List(); + byte[] tmp = new byte[8]; // Match the local header. - tmp.AddRange(BitConverter.GetBytes((ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_IGNORE))); - tmp.AddRange(BitConverter.GetBytes((ushort)(2 * 8))); - tmp.AddRange(BitConverter.GetBytes((ulong)(0))); - tmp.AddRange(BitConverter.GetBytes((ulong)(0))); - - extras.AddRange(tmp); + GSF_LE_SET_GUINT16(tmp, 0, (ushort)ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_IGNORE); + GSF_LE_SET_GUINT16(tmp, 2, 2 * 8); + extras.AddRange(new ReadOnlySpan(tmp, 0, 4).ToArray()); + GSF_LE_SET_GUINT64(tmp, 0, 0); + extras.AddRange(new ReadOnlySpan(tmp, 0, 8).ToArray()); + GSF_LE_SET_GUINT64(tmp, 0, 0); + extras.AddRange(new ReadOnlySpan(tmp, 0, 8).ToArray()); } if (ZIP_ADD_UNIXTIME_FIELD && dirent.ModifiedTime != null && !SpecialMimetypeDirectoryEntry(dirent)) { // Clearly a year 2038 problem here. - List tmp = new List(); + byte[] tmp = new byte[4]; - tmp.AddRange(BitConverter.GetBytes((ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_UNIXTIME))); - tmp.AddRange(BitConverter.GetBytes((ushort)(5))); - tmp.Add(1); - tmp.AddRange(BitConverter.GetBytes((uint)(new DateTimeOffset(dirent.ModifiedTime ?? DateTime.UtcNow).ToUnixTimeSeconds()))); - - extras.AddRange(tmp); + GSF_LE_SET_GUINT16(tmp, 0, (ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_UNIXTIME)); + GSF_LE_SET_GUINT16(tmp, 2, 5); + extras.AddRange(new ReadOnlySpan(tmp, 0, 4).ToArray()); + tmp[0] = 1; + extras.AddRange(new ReadOnlySpan(tmp, 0, 1).ToArray()); + GSF_LE_SET_GUINT32(tmp, 0, (uint)new DateTimeOffset(dirent.ModifiedTime ?? DateTime.UtcNow).ToUnixTimeSeconds()); + extras.AddRange(new ReadOnlySpan(tmp, 0, 4).ToArray()); } - List buf = new List(ZIP_DIRENT_SIZE); + byte[] buf = new byte[ZIP_DIRENT_SIZE]; - buf.AddRange(BitConverter.GetBytes((uint)(ZIP_DIRENT_SIGNATURE))); - buf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_UNIX << 8) + extract))); - buf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract))); - buf.AddRange(BitConverter.GetBytes((ushort)(dirent.Flags))); - buf.AddRange(BitConverter.GetBytes((ushort)(dirent.CompressionMethod))); - buf.AddRange(BitConverter.GetBytes((uint)(dirent.DosTime))); - buf.AddRange(BitConverter.GetBytes((uint)(dirent.CRC32))); - buf.AddRange(BitConverter.GetBytes((uint)(zip64_here ? uint.MaxValue : dirent.CompressedSize))); - buf.AddRange(BitConverter.GetBytes((uint)(zip64_here ? uint.MaxValue : dirent.UncompressedSize))); - buf.AddRange(BitConverter.GetBytes((ushort)(nlen))); - buf.AddRange(BitConverter.GetBytes((ushort)(extras.Count))); - buf.AddRange(BitConverter.GetBytes((ushort)(0))); - buf.AddRange(BitConverter.GetBytes((ushort)(0))); - buf.AddRange(BitConverter.GetBytes((ushort)(0))); + GSF_LE_SET_GUINT32(buf, 0, ZIP_DIRENT_SIGNATURE); + GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_ENCODER, (ushort)(((int)OSCodes.ZIP_OS_UNIX << 8) + extract)); + GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_EXTRACT, (ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract)); + GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_FLAGS, (ushort)dirent.Flags); + GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_COMPR_METHOD, (ushort)dirent.CompressionMethod); + GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_DOSTIME, dirent.DosTime); + GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_CRC32, dirent.CRC32); + GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_CSIZE, (uint)(zip64_here ? uint.MaxValue : dirent.CompressedSize)); + GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_USIZE, (uint)(zip64_here ? uint.MaxValue : dirent.UncompressedSize)); + GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_NAME_SIZE, (ushort)nlen); + GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_EXTRAS_SIZE, (ushort)extras.Count); + GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_COMMENT_SIZE, 0); + GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_DISKSTART, 0); + GSF_LE_SET_GUINT16(buf, ZIP_DIRENT_FILE_TYPE, 0); // Hardcode file mode 644 - buf.AddRange(BitConverter.GetBytes((uint)(0100644u << 16))); - buf.AddRange(BitConverter.GetBytes((uint)(offset_in_zip64 ? uint.MaxValue : dirent.Offset))); + GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_FILE_MODE, 0100644u << 16); + GSF_LE_SET_GUINT32(buf, ZIP_DIRENT_OFFSET, (uint)(offset_in_zip64 ? uint.MaxValue : dirent.Offset)); // Stuff everything into buf so we can do just one write. - buf.AddRange(extras); - buf.AddRange(Encoding.ASCII.GetBytes(dirent.Name)); + List header = new List(); + header.AddRange(buf); + header.AddRange(extras); + header.AddRange(Encoding.ASCII.GetBytes(dirent.Name)); - return Sink.Write(buf.Count, buf.ToArray()); + return Sink.Write(header.Count, header.ToArray()); } private bool TrailerWrite(int entries, long dirpos, long dirsize) { - List buf = new List(ZIP_TRAILER_SIZE); + byte[] buf = new byte[ZIP_TRAILER_SIZE]; - buf.AddRange(BitConverter.GetBytes((uint)(ZIP_TRAILER_SIGNATURE))); - buf.AddRange(BitConverter.GetBytes((ushort)(Math.Min(entries, ushort.MaxValue)))); - buf.AddRange(BitConverter.GetBytes((ushort)(Math.Min(dirsize, ushort.MaxValue)))); - buf.AddRange(BitConverter.GetBytes((ushort)(Math.Min(dirpos, ushort.MaxValue)))); + GSF_LE_SET_GUINT32(buf, 0, ZIP_TRAILER_SIGNATURE); + GSF_LE_SET_GUINT16(buf, ZIP_TRAILER_ENTRIES, (ushort)Math.Min(entries, ushort.MaxValue)); + GSF_LE_SET_GUINT16(buf, ZIP_TRAILER_TOTAL_ENTRIES, (ushort)Math.Min(entries, ushort.MaxValue)); + GSF_LE_SET_GUINT32(buf, ZIP_TRAILER_DIR_SIZE, (uint)Math.Min(dirsize, uint.MaxValue)); + GSF_LE_SET_GUINT32(buf, ZIP_TRAILER_DIR_POS, (uint)Math.Min(dirpos, uint.MaxValue)); - return Sink.Write(buf.Count, buf.ToArray()); + return Sink.Write(buf.Length, buf); } private bool Trailer64Write(int entries, long dirpos, long dirsize) { - List buf = new List(ZIP_TRAILER64_SIZE); + byte[] buf = new byte[ZIP_TRAILER64_SIZE]; byte extract = 45; - buf.AddRange(BitConverter.GetBytes((uint)(ZIP_TRAILER64_SIGNATURE))); - buf.AddRange(BitConverter.GetBytes((ulong)(ZIP_TRAILER64_SIZE - 12))); - buf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_UNIX << 8) + extract))); - buf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract))); - buf.AddRange(BitConverter.GetBytes((uint)(0))); - buf.AddRange(BitConverter.GetBytes((uint)(0))); - buf.AddRange(BitConverter.GetBytes((uint)(entries))); - buf.AddRange(BitConverter.GetBytes((uint)(entries))); - buf.AddRange(BitConverter.GetBytes((ulong)(dirsize))); - buf.AddRange(BitConverter.GetBytes((ulong)(dirpos))); + GSF_LE_SET_GUINT32(buf, 0, ZIP_TRAILER64_SIGNATURE); + GSF_LE_SET_GUINT64(buf, ZIP_TRAILER64_RECSIZE, ZIP_TRAILER64_SIZE - 12); + GSF_LE_SET_GUINT16(buf, ZIP_TRAILER64_ENCODER, (ushort)(((int)OSCodes.ZIP_OS_UNIX << 8) + extract)); + GSF_LE_SET_GUINT16(buf, ZIP_TRAILER64_EXTRACT, (ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract)); + GSF_LE_SET_GUINT32(buf, ZIP_TRAILER64_DISK, 0); + GSF_LE_SET_GUINT32(buf, ZIP_TRAILER64_DIR_DISK, 0); + GSF_LE_SET_GUINT32(buf, ZIP_TRAILER64_ENTRIES, (uint)entries); + GSF_LE_SET_GUINT32(buf, ZIP_TRAILER64_TOTAL_ENTRIES, (uint)entries); + GSF_LE_SET_GUINT64(buf, ZIP_TRAILER64_DIR_SIZE, (ulong)dirsize); + GSF_LE_SET_GUINT64(buf, ZIP_TRAILER64_DIR_POS, (ulong)dirpos); - return Sink.Write(buf.Count, buf.ToArray()); + return Sink.Write(buf.Length, buf); } private bool Zip64LocatorWrite(long trailerpos) { - List buf = new List(ZIP_ZIP64_LOCATOR_SIZE); + byte[] buf = new byte[ZIP_ZIP64_LOCATOR_SIZE]; - buf.AddRange(BitConverter.GetBytes((uint)(ZIP_ZIP64_LOCATOR_SIGNATURE))); - buf.AddRange(BitConverter.GetBytes((uint)(0))); - buf.AddRange(BitConverter.GetBytes((ulong)(trailerpos))); - buf.AddRange(BitConverter.GetBytes((uint)(1))); + GSF_LE_SET_GUINT32(buf, 0, ZIP_ZIP64_LOCATOR_SIGNATURE); + GSF_LE_SET_GUINT32(buf, ZIP_ZIP64_LOCATOR_DISK, 0); + GSF_LE_SET_GUINT64(buf, ZIP_TRAILER64_DIR_POS, (ulong)trailerpos); + GSF_LE_SET_GUINT32(buf, ZIP_ZIP64_LOCATOR_DISKS, 1); - return Sink.Write(buf.Count, buf.ToArray()); + return Sink.Write(buf.Length, buf); } private static int OffsetOrdering(GsfOutfileZip a, GsfOutfileZip b) @@ -569,13 +579,13 @@ namespace LibGSF.Output private bool HeaderWrite() { - List hbuf = new List(ZIP_HEADER_SIZE); + byte[] hbuf = new byte[ZIP_HEADER_SIZE]; GsfZipDirectoryEntry dirent = VDir.DirectoryEntry; string name = dirent.Name; int nlen = name.Length; - hbuf.AddRange(BitConverter.GetBytes((uint)(ZIP_HEADER_SIGNATURE))); + GSF_LE_SET_GUINT32(hbuf, 0, ZIP_HEADER_SIGNATURE); if (SinkIsSeekable == null) { @@ -584,12 +594,12 @@ namespace LibGSF.Output // try to seek back onto it. If seeking back fails, just // don't rewrite it. - if (!Sink.Write(4, hbuf.ToArray())) + if (!Sink.Write(4, hbuf)) return false; SinkIsSeekable = Sink.Seek(dirent.Offset, SeekOrigin.Begin); if (SinkIsSeekable == false) - hbuf.Clear(); + hbuf = new byte[ZIP_HEADER_SIZE]; } // Now figure out if we need a DDESC record. @@ -633,47 +643,51 @@ namespace LibGSF.Output // Auto or forced if (dirent.Zip64 != false) { - List tmp = new List(); + byte[] tmp = new byte[8]; ExtraFieldTags typ = real_zip64 ? ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_ZIP64 : ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_IGNORE; - tmp.AddRange(BitConverter.GetBytes((ushort)(typ))); - tmp.AddRange(BitConverter.GetBytes((ushort)(2 * 8))); - tmp.AddRange(BitConverter.GetBytes((ulong)(usize))); - tmp.AddRange(BitConverter.GetBytes((ulong)(csize))); - - extras.AddRange(tmp); + GSF_LE_SET_GUINT16(tmp, 0, (ushort)typ); + GSF_LE_SET_GUINT16(tmp, 2, 2 * 8); + extras.AddRange(new ReadOnlySpan(tmp, 0, 4).ToArray()); + GSF_LE_SET_GUINT64(tmp, 0, (ulong)usize); + extras.AddRange(new ReadOnlySpan(tmp, 0, 8).ToArray()); + GSF_LE_SET_GUINT64(tmp, 0, (ulong)csize); + extras.AddRange(new ReadOnlySpan(tmp, 0, 8).ToArray()); } if (ZIP_ADD_UNIXTIME_FIELD && dirent.ModifiedTime != null && !SpecialMimetypeDirectoryEntry(dirent)) { - List tmp = new List(); + byte[] tmp = new byte[4]; // Clearly a year 2038 problem here. - tmp.AddRange(BitConverter.GetBytes((ushort)(ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_UNIXTIME))); - tmp.AddRange(BitConverter.GetBytes((ushort)(5))); - tmp.Add(1); - tmp.AddRange(BitConverter.GetBytes((uint)(new DateTimeOffset(dirent.ModifiedTime ?? DateTime.UtcNow).ToUnixTimeSeconds()))); - - extras.AddRange(tmp); + GSF_LE_SET_GUINT16(tmp, 0, (ushort)ExtraFieldTags.ZIP_DIRENT_EXTRA_FIELD_UNIXTIME); + GSF_LE_SET_GUINT16(tmp, 2, 5); + extras.AddRange(new ReadOnlySpan(tmp, 0, 4).ToArray()); + tmp[0] = 1; + extras.AddRange(new ReadOnlySpan(tmp, 0, 1).ToArray()); + GSF_LE_SET_GUINT32(tmp, 0, (uint)new DateTimeOffset(dirent.ModifiedTime ?? DateTime.UtcNow).ToUnixTimeSeconds()); + extras.AddRange(new ReadOnlySpan(tmp, 0, 4).ToArray()); } - hbuf.AddRange(BitConverter.GetBytes((ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract))); - hbuf.AddRange(BitConverter.GetBytes((ushort)(dirent.Flags))); - hbuf.AddRange(BitConverter.GetBytes((ushort)(dirent.CompressionMethod))); - hbuf.AddRange(BitConverter.GetBytes((uint)(dirent.DosTime))); - hbuf.AddRange(BitConverter.GetBytes((uint)(crc32))); - hbuf.AddRange(BitConverter.GetBytes((uint)(real_zip64 && !has_ddesc ? uint.MaxValue : csize))); - hbuf.AddRange(BitConverter.GetBytes((uint)(real_zip64 && !has_ddesc ? uint.MaxValue : usize))); - hbuf.AddRange(BitConverter.GetBytes((ushort)(nlen))); - hbuf.AddRange(BitConverter.GetBytes((ushort)(extras.Count))); + GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_EXTRACT, (ushort)(((int)OSCodes.ZIP_OS_MSDOS << 8) + extract)); + GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_FLAGS, (ushort)dirent.Flags); + GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_COMP_METHOD, (ushort)dirent.CompressionMethod); + GSF_LE_SET_GUINT32(hbuf, ZIP_HEADER_DOSTIME, dirent.DosTime); + GSF_LE_SET_GUINT32(hbuf, ZIP_HEADER_CRC32, crc32); + GSF_LE_SET_GUINT32(hbuf, ZIP_HEADER_CSIZE, (uint)(real_zip64 && !has_ddesc ? uint.MaxValue : csize)); + GSF_LE_SET_GUINT32(hbuf, ZIP_HEADER_USIZE, (uint)(real_zip64 && !has_ddesc ? uint.MaxValue : usize)); + GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_NAME_SIZE, (ushort)nlen); + GSF_LE_SET_GUINT16(hbuf, ZIP_HEADER_EXTRAS_SIZE, (ushort)extras.Count); // Stuff everything into buf so we can do just one write. - hbuf.AddRange(extras); - hbuf.AddRange(Encoding.ASCII.GetBytes(name)); + List header = new List(); + header.AddRange(hbuf); + header.AddRange(extras); + header.AddRange(Encoding.ASCII.GetBytes(name)); - bool ret = Sink.Write(hbuf.Count, hbuf.ToArray()); + bool ret = Sink.Write(header.Count, header.ToArray()); if (real_zip64) dirent.Zip64 = true; @@ -784,7 +798,7 @@ namespace LibGSF.Output /// private bool DataDescriptorWrite() { - List buf = new List(Math.Max(ZIP_DDESC_SIZE, ZIP_DDESC64_SIZE)); + byte[] buf = new byte[Math.Max(ZIP_DDESC_SIZE, ZIP_DDESC64_SIZE)]; GsfZipDirectoryEntry dirent = VDir.DirectoryEntry; int size; @@ -792,22 +806,22 @@ namespace LibGSF.Output if (dirent.Zip64 != false) { - buf.AddRange(BitConverter.GetBytes((uint)(ZIP_DDESC64_SIGNATURE))); - buf.AddRange(BitConverter.GetBytes((uint)(dirent.CRC32))); - buf.AddRange(BitConverter.GetBytes((ulong)(dirent.CompressedSize))); - buf.AddRange(BitConverter.GetBytes((ulong)(dirent.UncompressedSize))); + GSF_LE_SET_GUINT32(buf, 0, ZIP_DDESC64_SIGNATURE); + GSF_LE_SET_GUINT32(buf, ZIP_DDESC64_CRC32, dirent.CRC32); + GSF_LE_SET_GUINT64(buf, ZIP_DDESC64_CSIZE, (ulong)dirent.CompressedSize); + GSF_LE_SET_GUINT64(buf, ZIP_DDESC64_USIZE, (ulong)dirent.UncompressedSize); size = ZIP_DDESC64_SIZE; } else { - buf.AddRange(BitConverter.GetBytes((uint)(ZIP_DDESC_SIGNATURE))); - buf.AddRange(BitConverter.GetBytes((uint)(dirent.CRC32))); - buf.AddRange(BitConverter.GetBytes((uint)(dirent.CompressedSize))); - buf.AddRange(BitConverter.GetBytes((uint)(dirent.UncompressedSize))); + GSF_LE_SET_GUINT32(buf, 0, ZIP_DDESC_SIGNATURE); + GSF_LE_SET_GUINT32(buf, ZIP_DDESC_CRC32, dirent.CRC32); + GSF_LE_SET_GUINT32(buf, ZIP_DDESC_CSIZE, (uint)dirent.CompressedSize); + GSF_LE_SET_GUINT32(buf, ZIP_DDESC_USIZE, (uint)dirent.UncompressedSize); size = ZIP_DDESC_SIZE; } - if (!Sink.Write(size, buf.ToArray())) + if (!Sink.Write(size, buf)) return false; return true; diff --git a/BurnOutSharp/External/libgsf/Output/GsfOutput.cs b/BurnOutSharp/External/libgsf/Output/GsfOutput.cs index ef76a92a..fa98c601 100644 --- a/BurnOutSharp/External/libgsf/Output/GsfOutput.cs +++ b/BurnOutSharp/External/libgsf/Output/GsfOutput.cs @@ -134,7 +134,7 @@ namespace LibGSF.Output return false; } - /// true if the wrapping succeeded. + /// True if the wrapping succeeded. public bool Wrap(object wrapper) { if (wrapper == null) @@ -164,7 +164,7 @@ namespace LibGSF.Output /// /// The printf-style format string /// The arguments for @format - /// true if successful, false if not + /// True if successful, false if not public bool PrintF(string format, params string[] va) => VPrintF(format, va) >= 0; /// diff --git a/BurnOutSharp/External/libgsf/Output/GsfOutputGZip.cs b/BurnOutSharp/External/libgsf/Output/GsfOutputGZip.cs index 6fbd1540..8ecd556d 100644 --- a/BurnOutSharp/External/libgsf/Output/GsfOutputGZip.cs +++ b/BurnOutSharp/External/libgsf/Output/GsfOutputGZip.cs @@ -25,6 +25,7 @@ using System.IO; using System.Text; using ComponentAce.Compression.Libs.zlib; using static ComponentAce.Compression.Libs.zlib.zlibConst; +using static LibGSF.GsfUtils; namespace LibGSF.Output { @@ -174,11 +175,11 @@ namespace LibGSF.Output if (!Raw) { - List buf = new List(); + byte[] buf = new byte[8]; - buf.AddRange(BitConverter.GetBytes((uint)(CRC))); - buf.AddRange(BitConverter.GetBytes((uint)(ISize))); - if (!Sink.Write(8, buf.ToArray())) + GSF_LE_SET_GUINT32(buf, 0, CRC); + GSF_LE_SET_GUINT32(buf, 4, (uint)(ISize)); + if (!Sink.Write(8, buf)) return false; } } @@ -214,7 +215,7 @@ namespace LibGSF.Output private bool OutputHeader() { - List buf = new List(3 + 1 + 4 + 2); + byte[] buf = new byte[3 + 1 + 4 + 2]; DateTime? modtime = ModTime; ulong mtime = (ulong)(modtime != null ? new DateTimeOffset(modtime.Value).ToUnixTimeSeconds() : 0); @@ -223,14 +224,13 @@ namespace LibGSF.Output // FIXME: What to do about gz extension ... ? int nlen = 0; // name ? strlen (name) : 0; - buf.AddRange(new byte[] { 0x1f, 0x8b, 0x08 }); - + Array.Copy(new byte[] { 0x1f, 0x8b, 0x08 }, buf, 3); if (nlen > 0) - buf.Add(GZIP_ORIGINAL_NAME); + buf[3] = GZIP_ORIGINAL_NAME; - buf.AddRange(BitConverter.GetBytes((uint)(mtime))); - buf.Add(3); // UNIX - bool ret = Sink.Write(buf.Count, buf.ToArray()); + GSF_LE_SET_GUINT32(buf, 4, (uint)mtime); + buf[9] = 3; // UNIX + bool ret = Sink.Write(buf.Length, buf); if (ret && name != null && nlen > 0) ret = Sink.Write(nlen, Encoding.ASCII.GetBytes(name));