From 6796997420a57c01c2758cd9a5340dd784dc794a Mon Sep 17 00:00:00 2001 From: 1987kostya Date: Mon, 25 Jan 2021 23:54:20 +0600 Subject: [PATCH] MMF1.5 Partial Support --- CTFAK/GUI/MainForm.cs | 19 ++-- CTFAK/MMFParser/EXE/ChunkList.cs | 62 ++++++++++--- CTFAK/MMFParser/EXE/EXE.cs | 4 + CTFAK/MMFParser/EXE/GameData.cs | 2 +- CTFAK/MMFParser/EXE/Loaders/AppHeader.cs | 38 ++++---- .../MMFParser/EXE/Loaders/Banks/ImageBank.cs | 90 +++++++++++-------- .../MMFParser/EXE/Loaders/Banks/SoundBank.cs | 3 +- CTFAK/MMFParser/EXE/Loaders/Events/Events.cs | 2 +- CTFAK/MMFParser/EXE/Loaders/Frame.cs | 56 ++++++++---- CTFAK/MMFParser/EXE/Loaders/FrameItems.cs | 2 +- CTFAK/MMFParser/EXE/Loaders/ObjectInfo.cs | 6 +- .../MMFParser/EXE/Loaders/Objects/Backdrop.cs | 24 +++-- .../EXE/Loaders/Objects/ObjectCommon.cs | 45 ++++++++-- CTFAK/MMFParser/EXE/Loaders/StringChunk.cs | 1 + CTFAK/MMFParser/EXE/PackData.cs | 7 +- CTFAK/MMFParser/MFA/Loaders/ChunkList.cs | 52 ++++++++++- CTFAK/MMFParser/MFA/Loaders/Frame.cs | 2 +- CTFAK/MMFParser/MFA/Loaders/FrameItem.cs | 2 +- .../MFA/Loaders/mfachunks/ObjectLoader.cs | 4 +- CTFAK/MMFParser/OLD/Loaders/AppHeader.cs | 1 + CTFAK/MMFParser/OLD/Loaders/Controls.cs | 8 +- CTFAK/MMFParser/Translation/PAME2MFA.cs | 17 ++-- CTFAK/Program.cs | 3 +- CTFAK/Utils/BitDict.cs | 3 +- CTFAK/Utils/Decompressor.cs | 24 +++-- CTFAK/Utils/ImageHelper.cs | 71 +++++++++++++++ 26 files changed, 408 insertions(+), 140 deletions(-) diff --git a/CTFAK/GUI/MainForm.cs b/CTFAK/GUI/MainForm.cs index 942b1bb..3e6dbbe 100644 --- a/CTFAK/GUI/MainForm.cs +++ b/CTFAK/GUI/MainForm.cs @@ -304,6 +304,10 @@ namespace CTFAK.GUI var frameItem = items.ItemDict[key]; var objNode = new ChunkNode($"{(Constants.ObjectType) frameItem.ObjectType} - {frameItem.Name}", frameItem); + foreach (ChunkList.Chunk chunk in frameItem.Chunks) + { + objNode.Nodes.Add(new ChunkNode(chunk.Name, chunk)); + } newNode.Nodes.Add(objNode); } } @@ -314,12 +318,6 @@ namespace CTFAK.GUI musicsButton.Visible = true; GameInfo.Visible = true; loadingLabel.Visible = false; - - InitPackDataTab(); - InitImages(); - InitSounds(); - InitKeyTab(); - InitPlugins(); var toLog = ""; toLog += $"{Properties.Locale.ChunkNames.title}: {Exe.Instance.GameData.Name}\n"; toLog += $"{Properties.Locale.ChunkNames.copyright}: {Exe.Instance.GameData.Copyright}\n"; @@ -333,6 +331,13 @@ namespace CTFAK.GUI toLog += $"{Properties.GlobalStrings.frameitemCount}: {Exe.Instance.GameData.Frameitems?.NumberOfItems}\n"; toLog += $"{Properties.GlobalStrings.frameCount}: {Exe.Instance.GameData.Frames.Count}\n"; toLog += $"Chunks Count: {Exe.Instance.GameData.GameChunks.Chunks.Count}\n"; + GameInfo.Text = toLog; + InitPackDataTab(); + InitImages(); + InitSounds(); + InitKeyTab(); + InitPlugins(); + if (Exe.Instance.GameData.GameChunks.GetChunk() != null) Exe.Instance.GameData.GameChunks.GetChunk().OnImageSaved += UpdateImageBar; if (Exe.Instance.GameData.GameChunks.GetChunk() != null) @@ -341,7 +346,7 @@ namespace CTFAK.GUI Exe.Instance.GameData.GameChunks.GetChunk().OnMusicSaved += UpdateMusicBar; - GameInfo.Text = toLog; + Loaded = true; } diff --git a/CTFAK/MMFParser/EXE/ChunkList.cs b/CTFAK/MMFParser/EXE/ChunkList.cs index 0da8479..b4cb6f4 100644 --- a/CTFAK/MMFParser/EXE/ChunkList.cs +++ b/CTFAK/MMFParser/EXE/ChunkList.cs @@ -52,6 +52,7 @@ namespace CTFAK.MMFParser.EXE chunk.Verbose = Verbose; chunk.Read(reader); chunk.Loader = LoadOld(chunk); + Chunks.Add(chunk); if (reader.Tell() >= reader.Size()) break; if (chunk.Id == 32639) break; //LAST chunkID } @@ -93,13 +94,8 @@ namespace CTFAK.MMFParser.EXE Flag = (ChunkFlags) exeReader.ReadInt16(); Size = exeReader.ReadInt32(); - if((Id!=26214&&Id!=26216)) //To prevent RAM from commiting suicide - { - RawData = exeReader.ReadBytes(Size); - exeReader.BaseStream.Position -= Size; - //Saving raw data cuz why not - } - if(Settings.Old) Logger.Log("Reading old chunk"+(Constants.ChunkNames)Id); + + // if(Settings.Old) Logger.Log("Reading old chunk"+(Constants.ChunkNames)Id); switch (Flag) { @@ -113,8 +109,11 @@ namespace CTFAK.MMFParser.EXE if (!Settings.Old) ChunkData = Decompressor.Decompress(exeReader, out DecompressedSize); else { - Int32 decompSize = exeReader.ReadInt32(); - ChunkData = Decompressor.decompressOld(exeReader, Size, decompSize); + var start = exeReader.Tell(); + var decompSize = exeReader.ReadInt32(); + var buff = exeReader.ReadBytes(Size); + ChunkData = Decompressor.decompressOld(buff, Size, decompSize); + exeReader.Seek(start+Size); } break; case ChunkFlags.NotCompressed: @@ -312,9 +311,50 @@ namespace CTFAK.MMFParser.EXE ChunkLoader loader = null; switch (chunk.Id) { - case 8739: - loader = new AppHeader(chunk); + case 8740: + loader = new AppName(chunk); + break; + case 8741: + loader = new AppAuthor(chunk); + break; + case 8745: + loader = new FrameItems(chunk); + break; + case 17477: + loader = new ObjectName(chunk); + break; + case 17476: + loader = new ObjectHeader(chunk); + break; + case 17478: + loader = new ObjectProperties(chunk); + return loader; + case 13107: + loader = new Frame(chunk); + break; + case 8750: + loader = new EditorFilename(chunk); + break; + case 8751: + loader = new TargetFilename(chunk); + break; + case 13109: + loader = new FrameName(chunk); break; + case 13108: + loader = new FrameHeader(chunk); + break; + case 13112: + loader = new ObjectInstances(chunk); + break; + case 26214: + // loader = new ImageBank(chunk); + break; + case 26216: + // loader = new SoundBank(chunk); + break; + + } loader?.Read(); return loader; diff --git a/CTFAK/MMFParser/EXE/EXE.cs b/CTFAK/MMFParser/EXE/EXE.cs index b8eba71..4d8c8e7 100644 --- a/CTFAK/MMFParser/EXE/EXE.cs +++ b/CTFAK/MMFParser/EXE/EXE.cs @@ -64,6 +64,10 @@ namespace CTFAK.MMFParser.EXE Logger.Log("First Short: " + firstShort.ToString("X2"), true, ConsoleColor.Yellow); if (firstShort == 0x7777) Settings.Old = false; else if (firstShort == 0x222c) Settings.Old = true; + else + { + Logger.Log(firstShort.ToString("x8")); + } if (!Settings.Old) { PackData = new PackData(); diff --git a/CTFAK/MMFParser/EXE/GameData.cs b/CTFAK/MMFParser/EXE/GameData.cs index 31e5ac2..d3aadf8 100644 --- a/CTFAK/MMFParser/EXE/GameData.cs +++ b/CTFAK/MMFParser/EXE/GameData.cs @@ -51,7 +51,7 @@ namespace CTFAK.MMFParser.EXE public void Read(ByteReader exeReader) { string magic = exeReader.ReadAscii(4); //Reading header - + Logger.Log("MAGIC HEADER: "+magic); //Checking for header if (magic == Constants.UnicodeGameHeader) Constants.IsUnicode = true;//PAMU else if (magic == Constants.GameHeader) Constants.IsUnicode = false;//PAME diff --git a/CTFAK/MMFParser/EXE/Loaders/AppHeader.cs b/CTFAK/MMFParser/EXE/Loaders/AppHeader.cs index ab5d743..2191c67 100644 --- a/CTFAK/MMFParser/EXE/Loaders/AppHeader.cs +++ b/CTFAK/MMFParser/EXE/Loaders/AppHeader.cs @@ -59,28 +59,28 @@ namespace CTFAK.MMFParser.EXE.Loaders public override void Read() { - Size = Reader.ReadInt32(); - Flags.flag=(uint) Reader.ReadInt16(); - - NewFlags.flag = (uint) Reader.ReadInt16(); - var graphicsMode = Reader.ReadInt16(); - var otherflags = Reader.ReadInt16(); - //TODO: Add OtherFlags - - WindowWidth = Reader.ReadInt16(); - WindowHeight = Reader.ReadInt16(); - InitialScore = (int) (Reader.ReadUInt32() ^ 0xffffffff); - InitialLives = (int) (Reader.ReadUInt32() ^ 0xffffffff); + { + if (!Settings.Old) Size = Reader.ReadInt32(); + Flags.flag=(uint) Reader.ReadInt16(); + + NewFlags.flag = (uint) Reader.ReadInt16(); + var graphicsMode = Reader.ReadInt16(); + var otherflags = Reader.ReadInt16(); + WindowWidth = Reader.ReadInt16(); + WindowHeight = Reader.ReadInt16(); + InitialScore = (int) (Reader.ReadUInt32() ^ 0xffffffff); + InitialLives = (int) (Reader.ReadUInt32() ^ 0xffffffff); + // var controls = new Controls(Reader); + // controls.Read(); + BorderColor = Reader.ReadColor(); + NumberOfFrames = Reader.ReadInt32(); + + FrameRate = Reader.ReadInt32(); + var windowsMenuIndex = Reader.ReadSByte(); + } - var controls = new Controls(Reader); - controls.Read(); - - BorderColor = Reader.ReadColor(); - NumberOfFrames = Reader.ReadInt32(); - FrameRate = Reader.ReadInt32(); - var windowsMenuIndex = Reader.ReadSByte(); } public override void Print(bool ext) diff --git a/CTFAK/MMFParser/EXE/Loaders/Banks/ImageBank.cs b/CTFAK/MMFParser/EXE/Loaders/Banks/ImageBank.cs index 09e12fb..2d5d0be 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Banks/ImageBank.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Banks/ImageBank.cs @@ -183,39 +183,31 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks Reader.Seek(Position); ByteReader imageReader; if (!Settings.twofiveplus) - imageReader = Debug ? Reader : Decompressor.DecompressAsReader(Reader, out var a); - else imageReader = Reader; - long start = imageReader.Tell(); - - - if (Settings.twofiveplus) { - var unk = imageReader.ReadBytes(4); - if (unk.GetHex(4) != "FF FF FF FF ") + if (Settings.Old) { - Logger.Log(Reader.Tell().ToString()); - Size = (int) BitConverter.ToUInt32(unk,0); - _references = imageReader.ReadInt32(); - _checksum = (int) imageReader.ReadUInt32(); + var decompSize = Reader.ReadInt32(); + imageReader =new ByteReader(Decompressor.decompressOld(Reader.ReadBytes((int) Reader.Size()), (int) Reader.Size(), decompSize)); } else { - Size = (int) imageReader.ReadInt32(); - _references = imageReader.ReadInt32(); - _checksum = (int) imageReader.ReadUInt32(); - } - - Logger.Log("Size: "+Size); - Logger.Log("References: "+_references); - Logger.Log("Checksum: "+_checksum); - + imageReader = Debug ? Reader : Decompressor.DecompressAsReader(Reader, out var a); + } } - else + else imageReader = Reader; + long start = imageReader.Tell(); + + + //return; + if (Settings.twofiveplus) imageReader.Skip(4); + if (Settings.Old) { - _checksum = imageReader.ReadInt32(); - _references = imageReader.ReadInt32(); - Size = (int) imageReader.ReadUInt32(); + _checksum = imageReader.ReadInt16(); } + else _checksum = imageReader.ReadInt32(); + + _references = imageReader.ReadInt32(); + Size = (int) imageReader.ReadUInt32(); imageReader.Seek(start+ _checksum);//to prevent bugs @@ -229,14 +221,29 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks Reader.Seek(Position); ByteReader imageReader; if (!Settings.twofiveplus) - imageReader = Debug ? Reader : Decompressor.DecompressAsReader(Reader, out var a); + { + if (Settings.Old) + { + var decompSize = Reader.ReadInt32(); + imageReader =new ByteReader(Decompressor.decompressOld(Reader.ReadBytes((int) Reader.Size()), (int) Reader.Size(), decompSize)); + } + else + { + imageReader = Debug ? Reader : Decompressor.DecompressAsReader(Reader, out var a); + } + } else imageReader = Reader; long start = imageReader.Tell(); //return; if (Settings.twofiveplus) imageReader.Skip(4); - _checksum = imageReader.ReadInt32(); + if (Settings.Old) + { + _checksum = imageReader.ReadInt16(); + } + else _checksum = imageReader.ReadInt32(); + _references = imageReader.ReadInt32(); Size = (int) imageReader.ReadUInt32(); if (Debug) @@ -250,12 +257,12 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks Flags.flag = imageReader.ReadByte(); - imageReader.Skip(2); + if(!Settings.Old)imageReader.Skip(2); XHotspot = imageReader.ReadInt16(); YHotspot = imageReader.ReadInt16(); ActionX = imageReader.ReadInt16(); ActionY = imageReader.ReadInt16(); - _transparent = imageReader.ReadColor(); + if(!Settings.Old)_transparent = imageReader.ReadColor(); // Logger.Log($"Loading image {Handle.ToString(),4} Size: {_width,4}x{_height,4}"); byte[] imageData; if (Settings.twofiveplus) Flags["LZX"] = false; @@ -277,11 +284,12 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks if (Flags["RLE"] || Flags["RLEW"] || Flags["RLET"]) { - + Reader.Seek(start+Size); + return; } else { - + switch (_graphicMode) { case 4: @@ -307,7 +315,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks } default: { - Logger.Log("Unknown Color Mode"); + Logger.Log("Unknown Color Mode: " + _graphicMode); break; } @@ -328,21 +336,25 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks } } } - if (Settings.Build > 283) // No idea, but this is not working with old games + if (!Settings.Old) { - if (_transparent != null) + if (Settings.Build > 283) // No idea, but this is not working with old games { - for (int i = 0; i < (_height * _width * 4) - 3; i++) + if (_transparent != null) { - if (_colorArray[i + 1] == _transparent.R && _colorArray[i + 2] == _transparent.G && - _colorArray[i + 3] == _transparent.B) + for (int i = 0; i < (_height * _width * 4) - 3; i++) { - _colorArray[i] = _transparent.A; + if (_colorArray[i + 1] == _transparent.R && _colorArray[i + 2] == _transparent.G && + _colorArray[i + 3] == _transparent.B) + { + _colorArray[i] = _transparent.A; + } } } } } - + // Logger.Log("ImageSize: "+_colorArray.Length); + // Save($@"DUMP\\{Handle}-test.png"); return; } diff --git a/CTFAK/MMFParser/EXE/Loaders/Banks/SoundBank.cs b/CTFAK/MMFParser/EXE/Loaders/Banks/SoundBank.cs index 61f8d44..781f5c8 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Banks/SoundBank.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Banks/SoundBank.cs @@ -112,11 +112,10 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks public class SoundItem : SoundBase { - public bool Compressed; public int Checksum; public int References; public int Flags; - public bool IsCompressed = true; + public bool IsCompressed = false; public override void Read() diff --git a/CTFAK/MMFParser/EXE/Loaders/Events/Events.cs b/CTFAK/MMFParser/EXE/Loaders/Events/Events.cs index afe94ba..ded0742 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Events/Events.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Events/Events.cs @@ -258,7 +258,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Events { var num = cond.Num; if (num == -42) num = -27; - if (Settings.Build >= 290) + // if (Settings.Build >= 290) { if (num == -28||num == -29||num == -30||num == -31||num == -32||num == -33||num == -34||num == -35||num == -36||num == -37||num == -38||num == -39) num = -8; } diff --git a/CTFAK/MMFParser/EXE/Loaders/Frame.cs b/CTFAK/MMFParser/EXE/Loaders/Frame.cs index cb35b60..7813bc1 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Frame.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Frame.cs @@ -61,7 +61,7 @@ namespace CTFAK.MMFParser.EXE.Loaders public override void Print(bool ext) { - Logger.Log($"Frame: {_name}", true, ConsoleColor.Green); + Logger.Log($"Frame: {Name}", true, ConsoleColor.Green); Logger.Log($" Password: {Password}", true, ConsoleColor.Green); Logger.Log($" Size: {Width}x{Height}", true, ConsoleColor.Green); Logger.Log($" Objects: {_objects.CountOfObjects}", true, ConsoleColor.Green); @@ -95,10 +95,11 @@ namespace CTFAK.MMFParser.EXE.Loaders _password = Chunks.GetChunk(); _palette = Chunks.GetChunk(); _layers = Chunks.GetChunk(); + //layerEffects _objects = Chunks.GetChunk(); _events = Chunks.GetChunk(); _movementTimer = Chunks.GetChunk(); - + //frameEffects _fadeIn = Chunks.PopChunk(); _fadeOut = Chunks.PopChunk(); @@ -113,7 +114,7 @@ namespace CTFAK.MMFParser.EXE.Loaders public int VirtHeight => _virtualSize.Bottom; public int MovementTimer => _movementTimer.Value; public string Name => _name?.Value ?? "UNK"; - public string Password => _password.Value; + public string Password => _password?.Value ?? ""; public Color Background => _header.Background; public List Objects => _objects?.Items ?? null; public List Palette => _palette?.Items ?? new Color[256].ToList(); @@ -170,10 +171,21 @@ namespace CTFAK.MMFParser.EXE.Loaders public override void Read() { - Width = Reader.ReadInt32(); - Height = Reader.ReadInt32(); - Background = Reader.ReadColor(); - Flags.flag = Reader.ReadUInt32(); + if (Settings.Old) + { + Width = Reader.ReadInt16(); + Height = Reader.ReadInt16(); + Background = Reader.ReadColor(); + Flags.flag = (uint) Reader.ReadInt16(); + } + else + { + Width = Reader.ReadInt32(); + Height = Reader.ReadInt32(); + Background = Reader.ReadColor(); + Flags.flag = Reader.ReadUInt32(); + } + @@ -229,7 +241,6 @@ namespace CTFAK.MMFParser.EXE.Loaders public int Y; public short ParentType; public short Layer; - public string Name; public short ParentHandle; public ObjectInstance(ByteReader reader) : base(reader) @@ -244,16 +255,25 @@ namespace CTFAK.MMFParser.EXE.Loaders { Handle = (ushort) Reader.ReadInt16(); ObjectInfo = (ushort) Reader.ReadInt16(); - X = Reader.ReadInt32(); - Y = Reader.ReadInt32(); - ParentType = Reader.ReadInt16(); - ParentHandle = Reader.ReadInt16(); - Layer = Reader.ReadInt16(); - var reserved = Reader.ReadInt16(); + if (Settings.Old) + { + X = Reader.ReadInt16(); + Y = Reader.ReadUInt16(); + ParentType = Reader.ReadInt16(); + ParentHandle = Reader.ReadInt16(); + } + else + { + X = Reader.ReadInt32(); + Y = Reader.ReadInt32(); + ParentType = Reader.ReadInt16(); + ParentHandle = Reader.ReadInt16(); + Layer = Reader.ReadInt16(); + var reserved = Reader.ReadInt16(); + } + //------------------------- - if (FrameItem != null) Name = FrameItem.Name; - else Name = $"UNKNOWN-{Handle}"; } @@ -264,7 +284,9 @@ namespace CTFAK.MMFParser.EXE.Loaders if (Program.CleanData.GameChunks.GetChunk() == null) return null; return Program.CleanData.GameChunks.GetChunk().FromHandle(ObjectInfo); } - } + } + + public string Name => FrameItem.Name; public override void Print(bool ext) { diff --git a/CTFAK/MMFParser/EXE/Loaders/FrameItems.cs b/CTFAK/MMFParser/EXE/Loaders/FrameItems.cs index 1431b0b..c0cc83c 100644 --- a/CTFAK/MMFParser/EXE/Loaders/FrameItems.cs +++ b/CTFAK/MMFParser/EXE/Loaders/FrameItems.cs @@ -33,7 +33,7 @@ namespace CTFAK.MMFParser.EXE.Loaders var item = new ObjectInfo(Reader); item.Read(); ItemDict.Add(item.Handle, item); - Names.Add(item.Name); + // Names.Add(item.Name); // Logger.Log($"Found FrameItem: '{item.Name}' with handle ({item.Handle})", true, ConsoleColor.Magenta); } GameData.TestItems = this; diff --git a/CTFAK/MMFParser/EXE/Loaders/ObjectInfo.cs b/CTFAK/MMFParser/EXE/Loaders/ObjectInfo.cs index 18a0c5f..275d883 100644 --- a/CTFAK/MMFParser/EXE/Loaders/ObjectInfo.cs +++ b/CTFAK/MMFParser/EXE/Loaders/ObjectInfo.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using CTFAK.MMFParser.EXE.Loaders.Banks; using CTFAK.MMFParser.EXE.Loaders.Objects; using CTFAK.Utils; @@ -33,10 +34,11 @@ namespace CTFAK.MMFParser.EXE.Loaders var infoChunks = new ChunkList(); infoChunks.Verbose = false; infoChunks.Read(Reader); - + _header = infoChunks.GetChunk(); _name = infoChunks.GetChunk(); _properties = infoChunks.GetChunk(); + _properties.ReadNew((int) ObjectType,this); } @@ -153,8 +155,8 @@ namespace CTFAK.MMFParser.EXE.Loaders { Handle = Reader.ReadInt16(); ObjectType = Reader.ReadInt16(); - Int16 reserved = Reader.ReadInt16(); Flags = Reader.ReadUInt16(); + Int16 reserved = Reader.ReadInt16(); InkEffect = Reader.ReadByte(); InkEffectParameter = Reader.ReadByte(); } diff --git a/CTFAK/MMFParser/EXE/Loaders/Objects/Backdrop.cs b/CTFAK/MMFParser/EXE/Loaders/Objects/Backdrop.cs index db4d2e3..1e1e1c3 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Objects/Backdrop.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Objects/Backdrop.cs @@ -37,12 +37,24 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects public override void Read() { - Size = Reader.ReadInt32(); - ObstacleType = (Obstacle) Reader.ReadInt16(); - CollisionType = (Collision) Reader.ReadInt16(); - Width = Reader.ReadInt32(); - Height = Reader.ReadInt32(); - Image = Reader.ReadInt16(); + if (Settings.Old) + { + Size = Reader.ReadInt32(); + ObstacleType = (Obstacle) Reader.ReadInt16(); + CollisionType = (Collision) Reader.ReadInt16(); + Image = Reader.ReadInt16(); + } + else + { + Size = Reader.ReadInt32(); + ObstacleType = (Obstacle) Reader.ReadInt16(); + CollisionType = (Collision) Reader.ReadInt16(); + Width = Reader.ReadInt32(); + Height = Reader.ReadInt32(); + Image = Reader.ReadInt16(); + + } + } diff --git a/CTFAK/MMFParser/EXE/Loaders/Objects/ObjectCommon.cs b/CTFAK/MMFParser/EXE/Loaders/Objects/ObjectCommon.cs index 674f675..89c5dbd 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Objects/ObjectCommon.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Objects/ObjectCommon.cs @@ -21,7 +21,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects public Animations Animations; - private BitDict preferences = new BitDict(new string[] + public BitDict Preferences = new BitDict(new string[] { "Backsave", "ScrollingIndependant", @@ -104,7 +104,35 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects public override void Read() { - var currentPosition = Reader.Tell(); + if (Settings.Old) + { + var currentPosition = Reader.Tell(); + var size = Reader.ReadInt16(); + var checksum = Reader.ReadInt16(); + _movementsOffset = (ushort) Reader.ReadInt16(); + _animationsOffset = (ushort) Reader.ReadInt16(); + var version = Reader.ReadInt16(); + _counterOffset = (ushort) Reader.ReadInt16(); + _systemObjectOffset = (ushort) Reader.ReadInt16(); + var ocVariable = Reader.ReadInt32(); + Flags.flag = (uint) Reader.ReadInt16(); + var end = Reader.Tell() + 8 * 2;//maybe its 9*2 + Reader.Seek(end); + + _extensionOffset = (ushort) Reader.ReadInt16(); + _valuesOffset = (ushort) Reader.ReadInt16(); + NewFlags.flag = (uint) Reader.ReadInt16(); + Preferences.flag = (uint) Reader.ReadInt16(); + Identifier = Reader.ReadInt16(); + BackColor = Reader.ReadColor(); + _fadeinOffset = (uint) Reader.ReadInt32(); + _fadeoutOffset = (uint) Reader.ReadInt32(); + + + } + else + { + var currentPosition = Reader.Tell(); var size = Reader.ReadInt32(); if (Settings.Build >= 284) { @@ -139,7 +167,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects _valuesOffset = Reader.ReadUInt16(); _stringsOffset = Reader.ReadUInt16(); NewFlags.flag = Reader.ReadUInt16(); - preferences.flag = Reader.ReadUInt16(); + Preferences.flag = Reader.ReadUInt16(); Identifier = Reader.ReadInt32(); BackColor = Reader.ReadColor(); _fadeinOffset = Reader.ReadUInt32(); @@ -157,10 +185,10 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects Movements=new Movements(Reader); Movements.Read(); } - + if (_systemObjectOffset > 0) { - Reader.Seek(currentPosition+_systemObjectOffset); + Reader.Seek(currentPosition + _systemObjectOffset); switch (Parent.ObjectType) { //Text @@ -170,10 +198,10 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects break; //Counter case Constants.ObjectType.Counter: - Counters=new Counters(Reader); + Counters = new Counters(Reader); Counters.Read(); break; - + } } @@ -201,6 +229,9 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects Counter.Read(); } + + } + // Logger.Log("anims: "+_animationsOffset); // Logger.Log("fadeIn: "+_fadeinOffset); // Logger.Log("fadeOut: "+_fadeoutOffset); diff --git a/CTFAK/MMFParser/EXE/Loaders/StringChunk.cs b/CTFAK/MMFParser/EXE/Loaders/StringChunk.cs index 85b46f0..fe7f48b 100644 --- a/CTFAK/MMFParser/EXE/Loaders/StringChunk.cs +++ b/CTFAK/MMFParser/EXE/Loaders/StringChunk.cs @@ -13,6 +13,7 @@ namespace CTFAK.MMFParser.EXE.Loaders { Reader = new ByteReader(Chunk.ChunkData); Value = Reader.ReadUniversal(); + // Print(false); } public override void Print(bool ext) diff --git a/CTFAK/MMFParser/EXE/PackData.cs b/CTFAK/MMFParser/EXE/PackData.cs index 8fb3db6..f5705c4 100644 --- a/CTFAK/MMFParser/EXE/PackData.cs +++ b/CTFAK/MMFParser/EXE/PackData.cs @@ -25,13 +25,16 @@ namespace CTFAK.MMFParser.EXE exeReader.Seek((int)(start + dataSize - 32)); var uheader = exeReader.ReadAscii(4); + Logger.Log("SUPERHEADER: "+uheader); if(uheader=="PAMU")Settings.Unicode = true; else if(uheader=="PAME")Settings.Unicode = false; exeReader.Seek(start + 16); uint formatVersion = exeReader.ReadUInt32(); - Debug.Assert(exeReader.ReadInt32()==0); - Debug.Assert(exeReader.ReadInt32()==0); + var check = exeReader.ReadInt32(); + Debug.Assert(check==0); + check = exeReader.ReadInt32(); + Debug.Assert(check==0); uint count = exeReader.ReadUInt32(); diff --git a/CTFAK/MMFParser/MFA/Loaders/ChunkList.cs b/CTFAK/MMFParser/MFA/Loaders/ChunkList.cs index a64ce3d..c965d87 100644 --- a/CTFAK/MMFParser/MFA/Loaders/ChunkList.cs +++ b/CTFAK/MMFParser/MFA/Loaders/ChunkList.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Windows.Forms; using System.Windows.Forms.VisualStyles; using CTFAK.MMFParser.EXE; using CTFAK.Utils; @@ -108,8 +109,15 @@ namespace CTFAK.MMFParser.MFA.Loaders case 33: Loader = new FrameVirtualRect(dataReader); break; + case 56: + Loader=new GlobalObject(dataReader); + break; + case 72: + Loader = new Opacity(dataReader); + break; default: Loader = null; + // Logger.Log($"{Id} - {Data.GetHex()}"); break; } @@ -140,6 +148,26 @@ namespace CTFAK.MMFParser.MFA.Loaders } } + + public class Opacity : MFAChunkLoader + { + public int Value; + + public Opacity(ByteReader dataReader) : base(dataReader){} + + + public override void Read() + { + Value = Reader.ReadInt32(); + } + + public override void Write(ByteWriter Writer) + { + Value = 255; + Writer.WriteInt32(Value); + } + } + public class FrameVirtualRect:MFAChunkLoader { public int Left; @@ -147,9 +175,6 @@ namespace CTFAK.MMFParser.MFA.Loaders public int Right; public int Bottom; public FrameVirtualRect(ByteReader reader) : base(reader){} - - - public override void Read() { Left = Reader.ReadInt32(); @@ -165,7 +190,28 @@ namespace CTFAK.MMFParser.MFA.Loaders Writer.WriteInt32(Top); Writer.WriteInt32(Right); Writer.WriteInt32(Bottom); + } + } + public class GlobalObject:MFAChunkLoader + { + public byte[] Value; + + public GlobalObject(ByteReader reader) : base(reader) + { + } + public override void Read() + { + Value = Reader.ReadBytes(12); + for(int i=0;i { @@ -105,7 +106,7 @@ namespace CTFAK Settings.DumpImages = dumpImages; Settings.DumpSounds = dumpSounds; Settings.Verbose = verbose; - if (path.EndsWith(".exe")) + if (path.ToLower().EndsWith(".exe")) { var exeReader = new ByteReader(path, FileMode.Open); diff --git a/CTFAK/Utils/BitDict.cs b/CTFAK/Utils/BitDict.cs index 72dc606..c652d24 100644 --- a/CTFAK/Utils/BitDict.cs +++ b/CTFAK/Utils/BitDict.cs @@ -46,7 +46,8 @@ namespace CTFAK.Utils public static string ToDebugString(IDictionary dictionary) { - return string.Join(";", dictionary.Select(kv => kv.Key + "=" + kv.Value).ToArray()); + // return string.Join(";", dictionary.Select(kv => kv.Key + "=" + kv.Value).ToArray()); + return string.Join("\n", dictionary.Select(kv => kv.Key + "=" + kv.Value).ToArray()); } public override string ToString() diff --git a/CTFAK/Utils/Decompressor.cs b/CTFAK/Utils/Decompressor.cs index bbf7949..8801b90 100644 --- a/CTFAK/Utils/Decompressor.cs +++ b/CTFAK/Utils/Decompressor.cs @@ -1,7 +1,10 @@ using System; +using System.Drawing; using System.IO; using System.IO.Compression; +using System.Runtime.InteropServices; using Joveler.Compression.ZLib; +using zlib; using DeflateStream = System.IO.Compression.DeflateStream; using GZipStream = Joveler.Compression.ZLib.GZipStream; @@ -9,6 +12,8 @@ namespace CTFAK.Utils { public static class Decompressor { + [DllImport("TinflateDecompress.dll")] + public static extern int decompress(IntPtr source, int source_size, IntPtr output, int output_size); public static byte[] Decompress(ByteReader exeReader, out int decompressed) { Int32 decompSize = exeReader.ReadInt32(); @@ -40,17 +45,18 @@ namespace CTFAK.Utils return decompressedData; } - public static byte[] decompressOld(ByteReader reader, int size, int decompSize) + public static byte[] decompressOld(byte[] buff,int size,int decompSize) { - ZLibDecompressOptions decompOpts = new ZLibDecompressOptions(); - MemoryStream compressedStream = new MemoryStream(reader.ReadBytes(size)); - MemoryStream decompressedStream = new MemoryStream(); + var originalBuff = Marshal.AllocHGlobal(size); + Marshal.Copy(buff,0,originalBuff,buff.Length); + var outputBuff = Marshal.AllocHGlobal(decompSize); + decompress(originalBuff, size, outputBuff, decompSize); + Marshal.FreeHGlobal(originalBuff); + byte[] data = new byte[decompSize]; + Marshal.Copy(outputBuff,data,0,decompSize); + Marshal.FreeHGlobal(outputBuff); + return data; - byte[] decompressedData = decompressedStream.GetBuffer(); - // Trimming array to decompSize, - // because ZlibStream always pads to 0x100 - Array.Resize(ref decompressedData, decompSize); - return decompressedData; } diff --git a/CTFAK/Utils/ImageHelper.cs b/CTFAK/Utils/ImageHelper.cs index 6488e75..942bd86 100644 --- a/CTFAK/Utils/ImageHelper.cs +++ b/CTFAK/Utils/ImageHelper.cs @@ -134,6 +134,77 @@ namespace CTFAK.Utils return alpha; } + public static (byte[], int) ReadRLE(byte[] data, int width, int height, int pointSize) + { + var pad = GetPadding(width, pointSize); + var currentPosition = 0; + var i = 0; + var pos = 0; + var points= new byte[width * height * 4]; + while (true) + { + var command = data[currentPosition]; + currentPosition += 1; + if (command == 0) break; + if (command > 128) + { + command -= 128; + for (int j = 0; j < command; j++) + { + if ((pos & (width + pad)) < width) + { + { + UInt16 newShort = (ushort) (data[currentPosition] | data[currentPosition + 1] << 8); + byte r = (byte) ((newShort & 31744) >> 10); + byte g = (byte) ((newShort & 992) >> 5); + byte b = (byte) ((newShort & 31)); + + r = (byte) (r << 3); + g = (byte) (g << 3); + b = (byte) (b << 3); + points[i] = r; + points[i + 1] = g; + points[i + 2] = b; + points[i + 3] = 255; + } + + i += 1; + } + + pos += 1; + currentPosition += 2; + + } + } + else + { + if((pos)%(width+pad)> 10); + byte g = (byte) ((newShort & 992) >> 5); + byte b = (byte) ((newShort & 31)); + + r = (byte) (r << 3); + g = (byte) (g << 3); + b = (byte) (b << 3); + points[i] = r; + points[i + 1] = g; + points[i + 2] = b; + points[i + 3] = 255; + i += 1; + } + pos += 1; + } + + currentPosition += 2; + } + + return (points, currentPosition); + + + } + public static int GetPadding(int width, int pointSize, int bytes = 2) { int pad = bytes - ((width * pointSize) % bytes);