ReClass.NET icon indicating copy to clipboard operation
ReClass.NET copied to clipboard

variable sized strings

Open Martinii89 opened this issue 6 years ago • 7 comments

I have the follow structure I want to define as a node. int32 - defining the length of a string string - with the size of the previous int.

I've tried this in a plugin. But the MemorySize don't seem to update when it reads the first int and figures out how long the string is.

class MyString : BaseNode
{
    private int length;

    public override int MemorySize => sizeof(int) + Encoding.UTF8.GuessByteCountPerChar() * length;

    // This does nothing? 
    public override void Update(HotSpot spot)
    {
        base.Update(spot);

        if (spot.Id == 0)
        {
            length = spot.Memory.ReadInt32(Offset);
        }
    }

    public override Size Draw(ViewInfo view, int x, int y)
    {
        ...
        length = view.Memory.ReadInt32(Offset);
        var text = view.Memory.ReadString(Encoding.UTF8, Offset + sizeof(int), length);
        ...
    }
}

Martinii89 avatar May 19 '19 20:05 Martinii89

Could you show the C++ source of the MyString class?

KN4CK3R avatar May 19 '19 20:05 KN4CK3R

It's C#, but here's the whole thing. I just removed the stuff i figured was irrelevant

using ReClassNET.Extensions;
using ReClassNET.Memory;
using ReClassNET.Nodes;
using ReClassNET.UI;
using System.Drawing;
using System.Text;

namespace SamplePluginManaged.Nodes
{
    class UpkString : BaseNode
    {
        private int length;

        public override int MemorySize => sizeof(int) + Encoding.UTF8.GuessByteCountPerChar() * length;

        public override void GetUserInterfaceInfo(out string name, out Image icon)
        {
            name = "UpkString";
            icon = null;
        }
        public override void Update(HotSpot spot)
        {
            base.Update(spot);

            if (spot.Id == 0)
            {
                length = spot.Memory.ReadInt32(Offset);
            }
        }


        public override Size Draw(ViewInfo view, int x, int y)
        {
            if (IsHidden && !IsWrapped)
            {
                return DrawHidden(view, x, y);
            }

            length = view.Memory.ReadInt32(Offset);
            var text = view.Memory.ReadString(Encoding.UTF8, Offset + sizeof(int), length);

            var origX = x;

            AddSelection(view, x, y, view.Font.Height);

            x += TextPadding;
            x = AddIcon(view, x, y, Icons.Text, HotSpot.NoneId, HotSpotType.None);
            x = AddAddressOffset(view, x, y);

            x = AddText(view, x, y, view.Settings.TypeColor, HotSpot.NoneId, "UpkString") + view.Font.Width;
            x = AddText(view, x, y, view.Settings.NameColor, HotSpot.NameId, Name) + view.Font.Width;

            x = AddText(view, x, y, view.Settings.TextColor, HotSpot.NoneId, "= '");
            x = AddText(view, x, y, view.Settings.TextColor, HotSpot.NoneId, text);
            x = AddText(view, x, y, view.Settings.TextColor, HotSpot.NoneId, "'") + view.Font.Width;

            x = AddComment(view, x, y);

            DrawInvalidMemoryIndicatorIcon(view, y);
            AddContextDropDownIcon(view, y);
            AddDeleteIcon(view, y);

            return new Size(x - origX, view.Font.Height);
        }

        public override int CalculateDrawnHeight(ViewInfo view)
        {
            return IsHidden && !IsWrapped ? HiddenHeight : view.Font.Height;
        }
    }
}

Martinii89 avatar May 19 '19 20:05 Martinii89

You misunderstood me. I want to see the code of the class you try to display in ReClass. Looks like UpkString is a class of the Unreal Engine?

KN4CK3R avatar May 19 '19 21:05 KN4CK3R

Well. It's mostly a datafile. So I'm using the binary file plugin. UPK is a file format from the udk engine. There's a lot of instances where there's first a int that defines the length of what follows. So I need to know how to define that as nodes.. Capture

The picture above is trivial. Later on there are long tables of these types of strings. Where it would be unfeasible to manually define the string lengths.

I've attached an example of the datafile

AkAudio_decrypted.zip

Martinii89 avatar May 19 '19 21:05 Martinii89

I'm afraid that's not possible with ReClass because the node size can't change at runtime. This limitation isn't a problem for the normal functionality because a compiled class can't change at runtime. The binary file plugin was just a demonstration what could be done. You found a use case which could not be done. You should use a real binary editor like https://www.sweetscape.com/010editor/ whichs supports this.

KN4CK3R avatar May 19 '19 21:05 KN4CK3R

Is this a fundamental limitation to ReClass. Or something that could be solved? If it would be possible to have a node constructor with access to the memory, we could read the size on creation. Is this within the realm of possibility?

Martinii89 avatar May 19 '19 21:05 Martinii89

untested

public override Size Draw(ViewInfo view, int x, int y)
{
	//...

	var length = view.Memory.ReadInt32(Offset);
	if (this->length != length)
	{
		this->length = length;
		GetParentContainer()?.ChildHasChanged(this);
	}
	var text = view.Memory.ReadString(Encoding.UTF8, Offset + sizeof(int), length);

	//...
}

It's a workaround and I don't want to list all the bad consequences here. 😄

KN4CK3R avatar May 19 '19 21:05 KN4CK3R