diff --git a/CTFAK/CTFAK.csproj b/CTFAK/CTFAK.csproj index d6eded8..8c206c3 100644 --- a/CTFAK/CTFAK.csproj +++ b/CTFAK/CTFAK.csproj @@ -159,6 +159,7 @@ MainForm.cs + diff --git a/CTFAK/GUI/MainForm.Designer.cs b/CTFAK/GUI/MainForm.Designer.cs index b6be12d..323cd3b 100644 --- a/CTFAK/GUI/MainForm.Designer.cs +++ b/CTFAK/GUI/MainForm.Designer.cs @@ -566,9 +566,11 @@ // this.imageViewerInfo.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.imageViewerInfo.BackColor = System.Drawing.Color.FromArgb(((int) (((byte) (64)))), ((int) (((byte) (64)))), ((int) (((byte) (64))))); - this.imageViewerInfo.Location = new System.Drawing.Point(777, 3); + this.imageViewerInfo.Font = new System.Drawing.Font("Courier New", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (204))); + this.imageViewerInfo.Location = new System.Drawing.Point(696, 3); this.imageViewerInfo.Name = "imageViewerInfo"; - this.imageViewerInfo.Size = new System.Drawing.Size(155, 63); + this.imageViewerInfo.RightToLeft = System.Windows.Forms.RightToLeft.Yes; + this.imageViewerInfo.Size = new System.Drawing.Size(236, 63); this.imageViewerInfo.TabIndex = 3; this.imageViewerInfo.Text = "DEBUG"; // diff --git a/CTFAK/GUI/MainForm.cs b/CTFAK/GUI/MainForm.cs index 4b4b74c..fae9365 100644 --- a/CTFAK/GUI/MainForm.cs +++ b/CTFAK/GUI/MainForm.cs @@ -42,6 +42,7 @@ namespace CTFAK.GUI private bool _isAudioPlaying; private SoundPlayer _soundPlayer; + public Label ObjectViewerLabel; public MainForm(Color color) @@ -110,6 +111,12 @@ namespace CTFAK.GUI if (dlg == DialogResult.Yes) Environment.Exit(0); else e.Cancel = true; }; + imageViewerInfo.Parent = imageViewPictureBox; + imageViewerInfo.BackColor=Color.Transparent; + imageViewerInfo.Dock = DockStyle.Right; + + + KeyPreview = true; tabControl1.Selecting += tabControl1_Selecting; } @@ -158,6 +165,9 @@ namespace CTFAK.GUI console.Show(); console.Location = new Point(Location.X + Size.Width - 15, 0); console.Size = new Size(console.Size.Width, Size.Height); + + + } @@ -652,15 +662,20 @@ namespace CTFAK.GUI } else if(common.Parent.ObjectType==7)//Counter { - for (var a = 0; a < common.Counters?.Frames?.Count; a++) + + var count = common.Counters?.Frames?.Count??0; + + for (var a = 0; a < count; a++) { var animFrame = common.Counters.Frames[a]; bank.Images.TryGetValue(animFrame, out var img); - if (img != null) + if (img == null) { - var animFrameNode = new ChunkNode(a.ToString(), img); - objInstNode.Nodes.Add(animFrameNode); + + continue; } + var animFrameNode = new ChunkNode(a.ToString(), img); + objInstNode.Nodes.Add(animFrameNode); } @@ -771,12 +786,57 @@ namespace CTFAK.GUI private void advancedTreeView_AfterSelect(object sender, TreeViewEventArgs e) { + ObjectViewerLabel?.Dispose(); var node = e.Node; - if (((ChunkNode) node).loader is ImageItem) + var loader = ((ChunkNode) node).loader; + string text=String.Empty; + imageViewPictureBox.Image = null; + if (loader is ImageItem img) { - var img = (ImageItem) ((ChunkNode) node).loader; + text += $"Size: {img.Bitmap.Width}x{img.Bitmap.Height}\r\n"; + text += $"Action Point: {img.ActionX}x{img.ActionY}\r\n"; + text += $"Hotspot: {img.XHotspot}x{img.YHotspot}\r\n"; imageViewPictureBox.Image = img.Bitmap; } + else if (loader is ObjectInstance instance) + { + + text += $"Name: {instance.FrameItem.Name}\r\n"; + text += $"Type: {(Constants.ObjectType)instance.FrameItem.ObjectType}\r\n"; + text += $"Position: {instance?.X}x{instance?.Y}\r\n"; + text += $"Size: {instance.FrameItem.GetPreview()?.Bitmap.Width}x{instance.FrameItem.GetPreview()?.Bitmap.Width}\r\n"; + if (instance.FrameItem.Properties.IsCommon) + { + var common = ((ObjectCommon) instance.FrameItem.Properties.Loader); + switch (instance.FrameItem.ObjectType) + { + case 3: + ObjectViewerLabel = new Label(); + var content = string.Empty; + foreach (var par in common.Text.Items) + { + content += $"{par.Value}\r\n"; + content += $"\r\n\r\n\r\n"; + } + ObjectViewerLabel.Text = content; + ObjectViewerLabel.Parent = imageViewPictureBox; + ObjectViewerLabel.Dock = DockStyle.Fill; + ObjectViewerLabel.TextAlign = ContentAlignment.MiddleCenter; + + imageViewPictureBox.Controls.Add(ObjectViewerLabel); + break; + default: + text += "No additional info"; + break; + + } + } + + + + + } + imageViewerInfo.Text = text; } diff --git a/CTFAK/MMFParser/EXE/ChunkList.cs b/CTFAK/MMFParser/EXE/ChunkList.cs index 742c02c..d952e7d 100644 --- a/CTFAK/MMFParser/EXE/ChunkList.cs +++ b/CTFAK/MMFParser/EXE/ChunkList.cs @@ -24,6 +24,7 @@ namespace CTFAK.MMFParser.EXE if (chunk.Id == 26214) { if(!Settings.twofiveplus) chunk.Loader = LoadChunk(chunk); + //LoadChunk(chunk); } else { diff --git a/CTFAK/MMFParser/EXE/Loaders/Banks/FontBank.cs b/CTFAK/MMFParser/EXE/Loaders/Banks/FontBank.cs index 8b0dab7..62f14ed 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Banks/FontBank.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Banks/FontBank.cs @@ -34,5 +34,30 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks { } } + public class FontItem:ChunkLoader + { + public FontItem(ByteReader reader) : base(reader) + { + } + + public FontItem(Chunk chunk) : base(chunk) + { + } + + public override void Read() + { + var handle = Reader.ReadUInt32(); + + } + public override void Print(bool ext) + { + throw new System.NotImplementedException(); + } + + public override string[] GetReadableData() + { + throw new System.NotImplementedException(); + } + } } diff --git a/CTFAK/MMFParser/EXE/Loaders/Banks/ImageBank.cs b/CTFAK/MMFParser/EXE/Loaders/Banks/ImageBank.cs index 4f76332..bd7c832 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Banks/ImageBank.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Banks/ImageBank.cs @@ -301,7 +301,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks } case 8: { - imageReader.Seek(start+Size); + Logger.Log("Reading 32-bit color"); (_colorArray, bytesRead) = ImageHelper.Read32(imageData, _width, _height); break; } diff --git a/CTFAK/MMFParser/EXE/Loaders/ObjectInfo.cs b/CTFAK/MMFParser/EXE/Loaders/ObjectInfo.cs index 0bc4cb7..d6d5e62 100644 --- a/CTFAK/MMFParser/EXE/Loaders/ObjectInfo.cs +++ b/CTFAK/MMFParser/EXE/Loaders/ObjectInfo.cs @@ -126,6 +126,21 @@ namespace CTFAK.MMFParser.EXE.Loaders return bmp; } + + public List GetInstances() + { + var list = new List(); + var frames = Exe.Instance.GameData.Frames; + foreach (var frame in frames) + { + foreach (ObjectInstance instance in frame.Objects.Items) + { + if(instance.ObjectInfo==this.Handle)list.Add(instance); + } + } + + return list; + } } public class ObjectName : StringChunk @@ -165,7 +180,7 @@ namespace CTFAK.MMFParser.EXE.Loaders { Loader = new Backdrop(Reader); } - else if(ObjectType==2|| ObjectType==7) + else { IsCommon = true; Loader = new ObjectCommon(Reader,parent); diff --git a/CTFAK/MMFParser/EXE/Loaders/Objects/Animations.cs b/CTFAK/MMFParser/EXE/Loaders/Objects/Animations.cs index c8cb0c1..6cf1594 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Objects/Animations.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Objects/Animations.cs @@ -20,6 +20,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects var currentPosition = Reader.Tell(); var size = Reader.ReadInt16(); var count = Reader.ReadInt16(); + var offsets = new List(); for (int i = 0; i < count; i++) { @@ -33,6 +34,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects { Reader.Seek(currentPosition+offset); var anim = new Animation(Reader); + anim.Read(); AnimationDict.Add(i,anim); diff --git a/CTFAK/MMFParser/EXE/Loaders/Objects/Counters.cs b/CTFAK/MMFParser/EXE/Loaders/Objects/Counters.cs index bd54888..8283114 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Objects/Counters.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Objects/Counters.cs @@ -60,6 +60,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects public override void Read() { + var size = Reader.ReadUInt32(); var width = Reader.ReadUInt32(); var height = Reader.ReadUInt32(); @@ -77,8 +78,9 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects var inverse = ByteFlag.GetFlag(flags, 8); var font = Reader.ReadUInt16(); if (displayType == 0) return; - else if (displayType == 1 || displayType == 4) + else if (displayType == 1 || displayType == 4|| displayType==50) { + Frames = new List(); var count = Reader.ReadInt16(); for (int i = 0; i < count; i++) @@ -89,7 +91,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects else if (displayType == 2 || displayType == 3 || displayType == 5) { //TODO: Shapes - throw new NotImplementedException(); + Logger.Log("Ignoring unsupported counter type"); } } diff --git a/CTFAK/MMFParser/EXE/Loaders/Objects/ObjectCommon.cs b/CTFAK/MMFParser/EXE/Loaders/Objects/ObjectCommon.cs index 889f93f..3d50987 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Objects/ObjectCommon.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Objects/ObjectCommon.cs @@ -8,9 +8,9 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects { private ushort _valuesOffset; private ushort _stringsOffset; - private byte[] Identifier; - private ushort _fadeinOffset; - private ushort _fadeoutOffset; + private int Identifier; + private uint _fadeinOffset; + private uint _fadeoutOffset; private ushort _movementsOffset; private ushort _animationsOffset; private ushort _systemObjectOffset; @@ -83,6 +83,8 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects public AlterableValues Values; public AlterableStrings Strings; public Movements Movements; + private ushort _unk; + public Text Text; public ObjectCommon(ByteReader reader) : base(reader) @@ -95,7 +97,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects public ObjectCommon(ChunkList.Chunk chunk) : base(chunk) { } - + public override void Read() { @@ -107,115 +109,76 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects _animationsOffset = Reader.ReadUInt16(); _movementsOffset = Reader.ReadUInt16(); var version = Reader.ReadUInt16(); - Reader.Skip(2); //TODO: Find out + _unk = Reader.ReadUInt16(); + _extensionOffset = Reader.ReadUInt16(); _counterOffset = Reader.ReadUInt16(); + Flags.flag = Reader.ReadUInt16(); + _end = Reader.Tell() + (8+1) * 2; + + Reader.Seek(_end); _systemObjectOffset = Reader.ReadUInt16(); + + + _valuesOffset = Reader.ReadUInt16(); + _stringsOffset = Reader.ReadUInt16(); + NewFlags.flag = Reader.ReadUInt16(); + preferences.flag = Reader.ReadUInt16(); + Identifier = Reader.ReadInt32(); + BackColor = Reader.ReadColor(); + _fadeinOffset = Reader.ReadUInt32(); + _fadeoutOffset = Reader.ReadUInt32(); } else { _movementsOffset = Reader.ReadUInt16(); _animationsOffset = Reader.ReadUInt16(); var version = Reader.ReadUInt16(); + //_unk = Reader.ReadUInt16(); + _extensionOffset = Reader.ReadUInt16(); _counterOffset = Reader.ReadUInt16(); - _systemObjectOffset = Reader.ReadUInt16(); - } - - Flags.flag = Reader.ReadUInt32(); - var end = Reader.Tell() + 16; - //Ignoring qualifiers - Reader.Seek(end); - if (Settings.Build == 284) - { + Flags.flag = Reader.ReadUInt16(); + _end = Reader.Tell() + (8+1) * 2; + + Reader.Seek(_end); _systemObjectOffset = Reader.ReadUInt16(); - } - else - { - _extensionOffset = Reader.PeekUInt16(); - } + - _valuesOffset = Reader.ReadUInt16(); - _stringsOffset = Reader.ReadUInt16(); - NewFlags.flag = Reader.ReadUInt32(); - preferences.flag = Reader.ReadUInt32(); - Identifier = Reader.ReadBytes(4); - BackColor = Reader.ReadColor(); - _fadeinOffset = (ushort) Reader.ReadUInt32(); - _fadeoutOffset = (ushort) Reader.ReadUInt32(); - - if (_movementsOffset != 0) - { - Reader.Seek(currentPosition+_movementsOffset); - Movements = new Movements(Reader); - Movements.Read(); - //Console.WriteLine("Movements done"); - } - - - if (_valuesOffset != 0) - { - Reader.Seek(currentPosition + _valuesOffset); - Values = new AlterableValues(Reader); - Values.Read(); - // Console.WriteLine("Values done"); - } - - - if (_stringsOffset != 0) - { - Reader.Seek(currentPosition + _stringsOffset); - Strings = new AlterableStrings(Reader); - Strings.Read(); - // Console.WriteLine("Strings done"); - } - - - if (_animationsOffset != 0&& Parent.ObjectType==2) - { - Reader.Seek(currentPosition + _animationsOffset); - Animations = new Animations(Reader); - Animations.Read(); - // Console.WriteLine("Animations done"); + _valuesOffset = Reader.ReadUInt16(); + _stringsOffset = Reader.ReadUInt16(); + NewFlags.flag = Reader.ReadUInt16(); + preferences.flag = Reader.ReadUInt16(); + Identifier = Reader.ReadInt32(); + BackColor = Reader.ReadColor(); + _fadeinOffset = Reader.ReadUInt32(); + _fadeoutOffset = Reader.ReadUInt32(); } - /*if (_counterOffset != 0) + if (_animationsOffset > 0) { - Reader.Seek(currentPosition + _counterOffset); - var counter = new Counter(Reader); - counter.Read(); - Console.WriteLine("Counters done"); + Reader.Seek(currentPosition+_animationsOffset); + Animations=new Animations(Reader); + Animations.Read(); } - - if (_extensionOffset != 0) - { - var dataSize = Reader.ReadInt32() - 20; - ExtensionVersion = Reader.ReadInt32(); - ExtensionId = Reader.ReadInt32(); - ExtensionPrivate = Reader.ReadInt32(); - if (dataSize != 0) - ExtensionData = Reader.ReadBytes(dataSize); - Console.WriteLine("Extensions Done"); - - }*/ - - if (_systemObjectOffset != 0) + + if (_systemObjectOffset > 0) { - Logger.Log("Reading System Object: "+_systemObjectOffset); Reader.Seek(currentPosition+_systemObjectOffset); - if (Parent.ObjectType == ((int) Constants.ObjectType.Text) || - Parent.ObjectType == ((int) Constants.ObjectType.Question)) + if (Parent.ObjectType == 7) //Counter { - //TODO; Text.read(); + + Counters=new Counters(Reader); + Counters.Read(); } - else if (Parent.ObjectType == ((int) Constants.ObjectType.Score) || - Parent.ObjectType == ((int) Constants.ObjectType.Lives)|| - Parent.ObjectType == ((int) Constants.ObjectType.Counter)) + else if(Parent.ObjectType==3)//Text { - Logger.Log("Counter: "+Parent.Name); - Counters = new Counters(Reader); - Counters.Read(); + + Text = new Text(Reader); + Text.Read(); + } } + // Logger.Log("anims: "+_animationsOffset); // Logger.Log("fadeIn: "+_fadeinOffset); // Logger.Log("fadeOut: "+_fadeoutOffset); diff --git a/CTFAK/MMFParser/EXE/Loaders/Objects/Text.cs b/CTFAK/MMFParser/EXE/Loaders/Objects/Text.cs new file mode 100644 index 0000000..8ebb7a4 --- /dev/null +++ b/CTFAK/MMFParser/EXE/Loaders/Objects/Text.cs @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms.VisualStyles; +using System.Xml.Schema; +using CTFAK.Utils; + +namespace CTFAK.MMFParser.EXE.Loaders.Objects +{ + public class Text:ChunkLoader + { + public int Width; + public int Height; + public List Items; + + public Text(ByteReader reader) : base(reader) + { + } + + public Text(ChunkList.Chunk chunk) : base(chunk) + { + } + + public override void Read() + { + var currentPos = Reader.Tell(); + var size = Reader.ReadInt32(); + Width = Reader.ReadInt32(); + Height = Reader.ReadInt32(); + List itemOffsets = new List(); + var offCount = Reader.ReadInt32(); + for (int i = 0; i < offCount; i++) + { + itemOffsets.Add(Reader.ReadInt32()); + } + Items = new List(); + foreach (int itemOffset in itemOffsets) + { + Reader.Seek(currentPos+itemOffset); + var par = new Paragraph(Reader); + par.Read(); + Items.Add(par); + } + + } + + public override void Print(bool ext) + { + throw new System.NotImplementedException(); + } + + public override string[] GetReadableData() + { + throw new System.NotImplementedException(); + } + } + + public class Paragraph : ChunkLoader + { + public ushort FontHandle; + public BitDict Flags = new BitDict(new string[]{ + "HorizontalCenter", + "RightAligned", + "VerticalCenter", + "BottomAligned", + "None", "None", "None", "None", + "Correct", + "Relief"}); + public string Value; + public Color Color; + + public Paragraph(ByteReader reader) : base(reader) + { + } + + public Paragraph(ChunkList.Chunk chunk) : base(chunk) + { + } + + public override void Read() + { + FontHandle = Reader.ReadUInt16(); + Flags.flag = Reader.ReadUInt16(); + Color = Reader.ReadColor(); + Value = Reader.ReadWideString(); + } + + public override void Print(bool ext) + { + throw new System.NotImplementedException(); + } + + public override string[] GetReadableData() + { + throw new System.NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/CTFAK/MMFParser/EXE/Loaders/Objects/Value.cs b/CTFAK/MMFParser/EXE/Loaders/Objects/Value.cs index 1163858..cc65995 100644 --- a/CTFAK/MMFParser/EXE/Loaders/Objects/Value.cs +++ b/CTFAK/MMFParser/EXE/Loaders/Objects/Value.cs @@ -19,12 +19,15 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects public override void Read() { Items = new List(); - + Reader.ReadUInt16(); var count = Reader.ReadUInt16(); + Logger.Log("Alterable value count "+count); Console.WriteLine(count); for (int i = 0; i < count; i++) { + var item = Reader.ReadInt32(); + Logger.Log($"{i} - {item}"); Items.Add(item); @@ -58,6 +61,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects Items = new List(); var count = Reader.ReadUInt16(); + Logger.Log("Alterable string count "+count); for (int i = 0; i < count; i++) { diff --git a/CTFAK/Utils/ImageHelper.cs b/CTFAK/Utils/ImageHelper.cs index 2cf3d11..6488e75 100644 --- a/CTFAK/Utils/ImageHelper.cs +++ b/CTFAK/Utils/ImageHelper.cs @@ -59,28 +59,27 @@ namespace CTFAK.Utils } public static (byte[], int) Read32(byte[] data, int width, int height) { - byte[] colorArray = new byte[width * height * 4]; + byte[] colorArray = new byte[width * height * 8]; int stride = width * 4; - int pad = GetPadding(width, 3); + int pad = GetPadding(width, 6); int position = 0; - try + for (int y = 0; y < height; y++) { - for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) { - for (int x = 0; x < width; x++) - { - position += 3; - } - position += pad * 3; + + + colorArray[(y * stride) + (x * 4) + 0] = data[position];//+1 + colorArray[(y * stride) + (x * 4) + 1] = data[position + 2];//+3 + colorArray[(y * stride) + (x * 4) + 2] = data[position + 4];//+5 + colorArray[(y * stride) + (x * 4) + 3] = 255; + position += 6; } - } - catch - { - return (Array.Empty(), position); - } + position += pad * 6; + } - return (Array.Empty(), position); + return (colorArray, position);