From c581283c9adb21933a13ecc537169d872d83a6a4 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Fri, 31 Oct 2014 18:47:19 +1300 Subject: [PATCH] Add the TS map importer. --- .../FileFormats/LZOCompression.cs | 280 +++++++++++ OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + OpenRA.Mods.TS/OpenRA.Mods.TS.csproj | 1 + .../UtilityCommands/ImportTSMapCommand.cs | 443 ++++++++++++++++++ 4 files changed, 725 insertions(+) create mode 100644 OpenRA.Mods.Common/FileFormats/LZOCompression.cs create mode 100644 OpenRA.Mods.TS/UtilityCommands/ImportTSMapCommand.cs diff --git a/OpenRA.Mods.Common/FileFormats/LZOCompression.cs b/OpenRA.Mods.Common/FileFormats/LZOCompression.cs new file mode 100644 index 0000000000..1861c86c9a --- /dev/null +++ b/OpenRA.Mods.Common/FileFormats/LZOCompression.cs @@ -0,0 +1,280 @@ +#region Copyright notice +/* C# port of the crude minilzo source version 2.06 by Frank Razenberg + + Beware, you should never want to see C# code like this. You were warned. + I simply ran the MSVC preprocessor on the original source, changed the datatypes + to their C# counterpart and fixed changed some control flow stuff to amend for + the different goto semantics between C and C#. + + Original copyright notice is included below. +*/ + +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library 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 General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#endregion + +using System; + +namespace OpenRA.Mods.Common.FileFormats +{ + public static class LZOCompression + { + static unsafe int LZO1xDecompress(byte* @in, uint inLen, byte* @out, ref uint outLen, void* wrkmem) + { + byte* op; + byte* ip; + uint t; + byte* mPos; + byte* ipEnd = @in + inLen; + outLen = 0; + op = @out; + ip = @in; + bool gtFirstLiteralRun = false; + bool gtMatchDone = false; + if (*ip > 17) + { + t = (uint)(*ip++ - 17); + if (t < 4) + MatchNext(ref op, ref ip, ref t); + else + { + do { *op++ = *ip++; } while (--t > 0); + gtFirstLiteralRun = true; + } + } + + while (true) + { + if (gtFirstLiteralRun) + { + gtFirstLiteralRun = false; + goto first_literal_run; + } + + t = *ip++; + if (t >= 16) + goto match; + + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + } + + t += (uint)(15 + *ip++); + } + + *(uint*)op = *(uint*)ip; + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do + { + *(uint*)op = *(uint*)ip; + op += 4; ip += 4; t -= 4; + } + while (t >= 4); + + if (t > 0) + do { *op++ = *ip++; } while (--t > 0); + } + else + do { *op++ = *ip++; } while (--t > 0); + } + + first_literal_run: + t = *ip++; + if (t >= 16) + goto match; + + mPos = op - (1 + 0x0800); + mPos -= t >> 2; + mPos -= *ip++ << 2; + + *op++ = *mPos++; *op++ = *mPos++; *op++ = *mPos; + gtMatchDone = true; + + match: + do + { + if (gtMatchDone) + { + gtMatchDone = false; + goto match_done; + } + + if (t >= 64) + { + mPos = op - 1; + mPos -= (t >> 2) & 7; + mPos -= *ip++ << 3; + t = (t >> 5) - 1; + + CopyMatch(ref op, ref mPos, ref t); + goto match_done; + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + } + + t += (uint)(31 + *ip++); + } + + mPos = op - 1; + mPos -= (*(ushort*)(void*)ip) >> 2; + ip += 2; + } + else if (t >= 16) + { + mPos = op; + mPos -= (t & 8) << 11; + t &= 7; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + } + + t += (uint)(7 + *ip++); + } + + mPos -= (*(ushort*)ip) >> 2; + ip += 2; + if (mPos == op) + goto eof_found; + mPos -= 0x4000; + } + else + { + mPos = op - 1; + mPos -= t >> 2; + mPos -= *ip++ << 2; + *op++ = *mPos++; *op++ = *mPos; + goto match_done; + } + + if (t >= 2 * 4 - (3 - 1) && (op - mPos) >= 4) + { + *(uint*)op = *(uint*)mPos; + op += 4; mPos += 4; t -= 4 - (3 - 1); + do + { + *(uint*)op = *(uint*)mPos; + op += 4; mPos += 4; t -= 4; + } while (t >= 4); + if (t > 0) + do { *op++ = *mPos++; } while (--t > 0); + } + else + { + // copy_match: + *op++ = *mPos++; *op++ = *mPos++; + do { *op++ = *mPos++; } while (--t > 0); + } + + match_done: + t = (uint)(ip[-2] & 3); + if (t == 0) + break; + + // match_next: + *op++ = *ip++; + if (t > 1) + { + *op++ = *ip++; + if (t > 2) + *op++ = *ip++; + } + + t = *ip++; + } while (true); + } + + eof_found: + outLen = (uint)(op - @out); + return ip == ipEnd ? 0 : (ip < ipEnd ? (-8) : (-4)); + } + + static unsafe void MatchNext(ref byte* op, ref byte* ip, ref uint t) + { + do { *op++ = *ip++; } while (--t > 0); + t = *ip++; + } + + static unsafe void CopyMatch(ref byte* op, ref byte* mPos, ref uint t) + { + *op++ = *mPos++; *op++ = *mPos++; + do { *op++ = *mPos++; } while (--t > 0); + } + + public static void DecodeInto(byte[] src, uint srcOffset, uint srcLength, byte[] dest, uint destOffset, ref uint destLength) + { + unsafe + { + fixed (byte* r = src, w = dest, wrkmem = new byte[IntPtr.Size * 16384]) + { + LZO1xDecompress(r + srcOffset, srcLength, w + destOffset, ref destLength, wrkmem); + } + } + } + } +} diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index d79458f8e0..b7e0c38437 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -727,6 +727,7 @@ + diff --git a/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj b/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj index 26839244af..8231450619 100644 --- a/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj +++ b/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj @@ -76,6 +76,7 @@ +