More object reader refactoring, fixed issues with text objects, advanced object viewer(still called image viewer)

master
1987kostya 4 years ago
parent 24853e3da3
commit 496cab002f

@ -159,6 +159,7 @@
<DependentUpon>MainForm.cs</DependentUpon> <DependentUpon>MainForm.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="MMFParser\EXE\Loaders\Objects\Movements.cs" /> <Compile Include="MMFParser\EXE\Loaders\Objects\Movements.cs" />
<Compile Include="MMFParser\EXE\Loaders\Objects\Text.cs" />
<Compile Include="MMFParser\Translation\MFAGenerator.cs" /> <Compile Include="MMFParser\Translation\MFAGenerator.cs" />
<Compile Include="MMFParser\Translation\PAME2MFA.cs" /> <Compile Include="MMFParser\Translation\PAME2MFA.cs" />
<Compile Include="MMFParser\EXE\ChunkList.cs" /> <Compile Include="MMFParser\EXE\ChunkList.cs" />

@ -566,9 +566,11 @@
// //
this.imageViewerInfo.Anchor = ((System.Windows.Forms.AnchorStyles) ((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); 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.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.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.TabIndex = 3;
this.imageViewerInfo.Text = "DEBUG"; this.imageViewerInfo.Text = "DEBUG";
// //

@ -42,6 +42,7 @@ namespace CTFAK.GUI
private bool _isAudioPlaying; private bool _isAudioPlaying;
private SoundPlayer _soundPlayer; private SoundPlayer _soundPlayer;
public Label ObjectViewerLabel;
public MainForm(Color color) public MainForm(Color color)
@ -110,6 +111,12 @@ namespace CTFAK.GUI
if (dlg == DialogResult.Yes) Environment.Exit(0); if (dlg == DialogResult.Yes) Environment.Exit(0);
else e.Cancel = true; else e.Cancel = true;
}; };
imageViewerInfo.Parent = imageViewPictureBox;
imageViewerInfo.BackColor=Color.Transparent;
imageViewerInfo.Dock = DockStyle.Right;
KeyPreview = true; KeyPreview = true;
tabControl1.Selecting += tabControl1_Selecting; tabControl1.Selecting += tabControl1_Selecting;
} }
@ -158,6 +165,9 @@ namespace CTFAK.GUI
console.Show(); console.Show();
console.Location = new Point(Location.X + Size.Width - 15, 0); console.Location = new Point(Location.X + Size.Width - 15, 0);
console.Size = new Size(console.Size.Width, Size.Height); console.Size = new Size(console.Size.Width, Size.Height);
} }
@ -652,15 +662,20 @@ namespace CTFAK.GUI
} }
else if(common.Parent.ObjectType==7)//Counter 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]; var animFrame = common.Counters.Frames[a];
bank.Images.TryGetValue(animFrame, out var img); 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) private void advancedTreeView_AfterSelect(object sender, TreeViewEventArgs e)
{ {
ObjectViewerLabel?.Dispose();
var node = e.Node; 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; 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;
} }

@ -24,6 +24,7 @@ namespace CTFAK.MMFParser.EXE
if (chunk.Id == 26214) if (chunk.Id == 26214)
{ {
if(!Settings.twofiveplus) chunk.Loader = LoadChunk(chunk); if(!Settings.twofiveplus) chunk.Loader = LoadChunk(chunk);
//LoadChunk(chunk);
} }
else else
{ {

@ -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();
}
}
} }

@ -301,7 +301,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Banks
} }
case 8: case 8:
{ {
imageReader.Seek(start+Size); Logger.Log("Reading 32-bit color");
(_colorArray, bytesRead) = ImageHelper.Read32(imageData, _width, _height); (_colorArray, bytesRead) = ImageHelper.Read32(imageData, _width, _height);
break; break;
} }

@ -126,6 +126,21 @@ namespace CTFAK.MMFParser.EXE.Loaders
return bmp; return bmp;
} }
public List<ObjectInstance> GetInstances()
{
var list = new List<ObjectInstance>();
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 public class ObjectName : StringChunk
@ -165,7 +180,7 @@ namespace CTFAK.MMFParser.EXE.Loaders
{ {
Loader = new Backdrop(Reader); Loader = new Backdrop(Reader);
} }
else if(ObjectType==2|| ObjectType==7) else
{ {
IsCommon = true; IsCommon = true;
Loader = new ObjectCommon(Reader,parent); Loader = new ObjectCommon(Reader,parent);

@ -20,6 +20,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects
var currentPosition = Reader.Tell(); var currentPosition = Reader.Tell();
var size = Reader.ReadInt16(); var size = Reader.ReadInt16();
var count = Reader.ReadInt16(); var count = Reader.ReadInt16();
var offsets = new List<short>(); var offsets = new List<short>();
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
@ -33,6 +34,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects
{ {
Reader.Seek(currentPosition+offset); Reader.Seek(currentPosition+offset);
var anim = new Animation(Reader); var anim = new Animation(Reader);
anim.Read(); anim.Read();
AnimationDict.Add(i,anim); AnimationDict.Add(i,anim);

@ -60,6 +60,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects
public override void Read() public override void Read()
{ {
var size = Reader.ReadUInt32(); var size = Reader.ReadUInt32();
var width = Reader.ReadUInt32(); var width = Reader.ReadUInt32();
var height = Reader.ReadUInt32(); var height = Reader.ReadUInt32();
@ -77,8 +78,9 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects
var inverse = ByteFlag.GetFlag(flags, 8); var inverse = ByteFlag.GetFlag(flags, 8);
var font = Reader.ReadUInt16(); var font = Reader.ReadUInt16();
if (displayType == 0) return; if (displayType == 0) return;
else if (displayType == 1 || displayType == 4) else if (displayType == 1 || displayType == 4|| displayType==50)
{ {
Frames = new List<int>(); Frames = new List<int>();
var count = Reader.ReadInt16(); var count = Reader.ReadInt16();
for (int i = 0; i < count; i++) 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) else if (displayType == 2 || displayType == 3 || displayType == 5)
{ {
//TODO: Shapes //TODO: Shapes
throw new NotImplementedException(); Logger.Log("Ignoring unsupported counter type");
} }
} }

@ -8,9 +8,9 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects
{ {
private ushort _valuesOffset; private ushort _valuesOffset;
private ushort _stringsOffset; private ushort _stringsOffset;
private byte[] Identifier; private int Identifier;
private ushort _fadeinOffset; private uint _fadeinOffset;
private ushort _fadeoutOffset; private uint _fadeoutOffset;
private ushort _movementsOffset; private ushort _movementsOffset;
private ushort _animationsOffset; private ushort _animationsOffset;
private ushort _systemObjectOffset; private ushort _systemObjectOffset;
@ -83,6 +83,8 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects
public AlterableValues Values; public AlterableValues Values;
public AlterableStrings Strings; public AlterableStrings Strings;
public Movements Movements; public Movements Movements;
private ushort _unk;
public Text Text;
public ObjectCommon(ByteReader reader) : base(reader) public ObjectCommon(ByteReader reader) : base(reader)
@ -107,115 +109,76 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects
_animationsOffset = Reader.ReadUInt16(); _animationsOffset = Reader.ReadUInt16();
_movementsOffset = Reader.ReadUInt16(); _movementsOffset = Reader.ReadUInt16();
var version = Reader.ReadUInt16(); var version = Reader.ReadUInt16();
Reader.Skip(2); //TODO: Find out _unk = Reader.ReadUInt16();
_extensionOffset = Reader.ReadUInt16();
_counterOffset = Reader.ReadUInt16(); _counterOffset = Reader.ReadUInt16();
Flags.flag = Reader.ReadUInt16();
_end = Reader.Tell() + (8+1) * 2;
Reader.Seek(_end);
_systemObjectOffset = Reader.ReadUInt16(); _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 else
{ {
_movementsOffset = Reader.ReadUInt16(); _movementsOffset = Reader.ReadUInt16();
_animationsOffset = Reader.ReadUInt16(); _animationsOffset = Reader.ReadUInt16();
var version = Reader.ReadUInt16(); var version = Reader.ReadUInt16();
//_unk = Reader.ReadUInt16();
_extensionOffset = Reader.ReadUInt16();
_counterOffset = Reader.ReadUInt16(); _counterOffset = Reader.ReadUInt16();
_systemObjectOffset = Reader.ReadUInt16(); Flags.flag = Reader.ReadUInt16();
} _end = Reader.Tell() + (8+1) * 2;
Flags.flag = Reader.ReadUInt32(); Reader.Seek(_end);
var end = Reader.Tell() + 16;
//Ignoring qualifiers
Reader.Seek(end);
if (Settings.Build == 284)
{
_systemObjectOffset = Reader.ReadUInt16(); _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) _valuesOffset = Reader.ReadUInt16();
{ _stringsOffset = Reader.ReadUInt16();
Reader.Seek(currentPosition + _stringsOffset); NewFlags.flag = Reader.ReadUInt16();
Strings = new AlterableStrings(Reader); preferences.flag = Reader.ReadUInt16();
Strings.Read(); Identifier = Reader.ReadInt32();
// Console.WriteLine("Strings done"); BackColor = Reader.ReadColor();
_fadeinOffset = Reader.ReadUInt32();
_fadeoutOffset = Reader.ReadUInt32();
} }
if (_animationsOffset > 0)
if (_animationsOffset != 0&& Parent.ObjectType==2)
{ {
Reader.Seek(currentPosition + _animationsOffset); Reader.Seek(currentPosition+_animationsOffset);
Animations = new Animations(Reader); Animations=new Animations(Reader);
Animations.Read(); Animations.Read();
// Console.WriteLine("Animations done");
} }
/*if (_counterOffset != 0) if (_systemObjectOffset > 0)
{
Reader.Seek(currentPosition + _counterOffset);
var counter = new Counter(Reader);
counter.Read();
Console.WriteLine("Counters done");
}
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)
{ {
Logger.Log("Reading System Object: "+_systemObjectOffset);
Reader.Seek(currentPosition+_systemObjectOffset); Reader.Seek(currentPosition+_systemObjectOffset);
if (Parent.ObjectType == ((int) Constants.ObjectType.Text) || if (Parent.ObjectType == 7) //Counter
Parent.ObjectType == ((int) Constants.ObjectType.Question))
{ {
//TODO; Text.read();
Counters=new Counters(Reader);
Counters.Read();
} }
else if (Parent.ObjectType == ((int) Constants.ObjectType.Score) || else if(Parent.ObjectType==3)//Text
Parent.ObjectType == ((int) Constants.ObjectType.Lives)||
Parent.ObjectType == ((int) Constants.ObjectType.Counter))
{ {
Logger.Log("Counter: "+Parent.Name);
Counters = new Counters(Reader); Text = new Text(Reader);
Counters.Read(); Text.Read();
} }
} }
// Logger.Log("anims: "+_animationsOffset); // Logger.Log("anims: "+_animationsOffset);
// Logger.Log("fadeIn: "+_fadeinOffset); // Logger.Log("fadeIn: "+_fadeinOffset);
// Logger.Log("fadeOut: "+_fadeoutOffset); // Logger.Log("fadeOut: "+_fadeoutOffset);

@ -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<Paragraph> 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<int> itemOffsets = new List<int>();
var offCount = Reader.ReadInt32();
for (int i = 0; i < offCount; i++)
{
itemOffsets.Add(Reader.ReadInt32());
}
Items = new List<Paragraph>();
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();
}
}
}

@ -19,12 +19,15 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects
public override void Read() public override void Read()
{ {
Items = new List<int>(); Items = new List<int>();
Reader.ReadUInt16();
var count = Reader.ReadUInt16(); var count = Reader.ReadUInt16();
Logger.Log("Alterable value count "+count);
Console.WriteLine(count); Console.WriteLine(count);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
var item = Reader.ReadInt32(); var item = Reader.ReadInt32();
Logger.Log($"{i} - {item}");
Items.Add(item); Items.Add(item);
@ -58,6 +61,7 @@ namespace CTFAK.MMFParser.EXE.Loaders.Objects
Items = new List<string>(); Items = new List<string>();
var count = Reader.ReadUInt16(); var count = Reader.ReadUInt16();
Logger.Log("Alterable string count "+count);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {

@ -59,28 +59,27 @@ namespace CTFAK.Utils
} }
public static (byte[], int) Read32(byte[] data, int width, int height) 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 stride = width * 4;
int pad = GetPadding(width, 3); int pad = GetPadding(width, 6);
int position = 0; 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; colorArray[(y * stride) + (x * 4) + 0] = data[position];//+1
} colorArray[(y * stride) + (x * 4) + 1] = data[position + 2];//+3
position += pad * 3; colorArray[(y * stride) + (x * 4) + 2] = data[position + 4];//+5
colorArray[(y * stride) + (x * 4) + 3] = 255;
position += 6;
} }
}
catch
{
return (Array.Empty<byte>(), position);
}
position += pad * 6;
}
return (Array.Empty<byte>(), position); return (colorArray, position);

Loading…
Cancel
Save