Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


C# - RPM iterations slow as hell with this method! Solution?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
maxmadx
How do I cheat?
Reputation: 0

Joined: 22 May 2012
Posts: 3

PostPosted: Sat Dec 01, 2012 9:26 pm    Post subject: C# - RPM iterations slow as hell with this method! Solution? Reply with quote

I have been working on this for months and although it is finished it is too slow and therefore not practical to use Sad This is not a cheat as such, I am using it to read the values stored in a grid of 200x200 boxes. As an example, the values in the first 3 boxes on the top row were set as: 1, 0, 1. Using cheat-engine with type set as 'array of bytes', the following data is presented -setting length as '10'.:

01 00 04 00 00 00 04 44 01 00

The values for each box are 4 bytes apart as shown above in the data structure.

Currently, I am using a trainer class I found on this forum to call the read process memory function (byte) in iteration adding each result to a List which is later converted to an array (representing the first row), and this is repeated for each row of the grid until I have an array for each row in the grid (effectively creating a local snapshot of the grid at any time this is performed. e.g. array1{1,0,1} could be produced calling the class 3 times capturing a row of 3 boxes.

Because I have to read the entire grid, it means I have to call the function 40,000 (200x200) times! which delays the process by up to 30 seconds. Seeing how fast cheat-engine can read millions of addresses I am sure there is a much faster way to achieve this.


Here is the function being called (sorry I couldn't find the post again to give credits). You can see that the ReadProcessMemoryByte value is 2 which is to read the integer value. I thought I could change this to 1,000 which would read the 200 boxes (including 4 byte separations), and then iterate through the big long number cutting out each 4th number (if that makes sense) locally. 1 readprocessmemory of 1,000 bytes should be a hell of a lot faster than 1,000 readprocessmemory calls right?! But No matter what I change this to it only shows '1' in the above example.


Code:
public static byte ReadPointerByte(string EXENAME, int Pointer, int[] Offset)
    {
        byte Value = 0;
        checked
        {
            try
            {
                Process[] Proc = Process.GetProcessesByName(EXENAME);
                if (Proc.Length != 0)
                {
                    int Bytes = 0;
                    int Handle = OpenProcess(PROCESS_ALL_ACCESS, 0, Proc[0].Id);
                    if (Handle != 0)
                    {
                        foreach (int i in Offset)
                        {
                            ReadProcessMemoryInteger((int)Handle, Pointer, ref Pointer, 4, ref Bytes);
                            Pointer += i;
                        }
                        ReadProcessMemoryByte((int)Handle, Pointer, ref Value, 2, ref Bytes);
                        CloseHandle(Handle);
                    }
                }
            }
            catch
            { }
        }
        return Value;
    }



I would be very grateful to ANYONE who has more information.
[/code]
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25833
Location: The netherlands

PostPosted: Sat Dec 01, 2012 9:53 pm    Post subject: Reply with quote

ReadProcessMemory calls are slow.
Imagine it is programmed like this
Code:

Sleep(10000000000000
Copy(destination,source,size)
Return

So try to limit the number of calls to readprocessmemory as much as possible. Either by reading all the processmemory first using as big blocks as you can, or at least cache all your reads to 4KB blocks that contain the full page of the blocks you've read, and always first lookup if that block has been cached or not, and only if you have to call RPM

And the reason changing the 2 to something higher doesn't work is because the rest of your code hasn't been designed to work with the extra data

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
maxmadx
How do I cheat?
Reputation: 0

Joined: 22 May 2012
Posts: 3

PostPosted: Sat Dec 01, 2012 10:03 pm    Post subject: Reply with quote

Dark Byte wrote:
ReadProcessMemory calls are slow.
Imagine it is programmed like this
Code:

Sleep(10000000000000
Copy(destination,source,size)
Return

So try to limit the number of calls to readprocessmemory as much as possible. Either by reading all the processmemory first using as big blocks as you can, or at least cache all your reads to 4KB blocks that contain the full page of the blocks you've read, and always first lookup if that block has been cached or not, and only if you have to call RPM

And the reason changing the 2 to something higher doesn't work is because the rest of your code hasn't been designed to work with the extra data


Hi,

The speed increase advice sounds promising. The increase of '2' to '1000' was what I am hoping to accomplish by increasing the RPM block of code and just read once. I might be a little too beginner to implement a solution based on the general guidance, can you recommend any sources of learning to properly accomplish the steps you recommended? I posted some questions on stackoverflow and have not got anywhere since july unfortunately.

Just to add that the grid updates every few seconds, so I am constantly needing to update my numbers.

btw, here is the vastly reduced testing code I wrote to display the result of changing '2' to a higher number (I created this simpler project to avoid complications with my other code and to simply test if I could read a bigger block of memory and see how easy it is to manipulate after being read):

with a grid of: 1,0,1 as talked about in the last post:

//some code at start to RPM the start of the structure. then:
X1.Add(ValueX); // Add read byte to list
byte[] X1ToInt = X1.ToArray(); //convert to array
int[] MYConvertedBytes = X1ToInt.Select(x => (int)x).ToArray();//convert to int array
string TestString = MYConvertedBytes[0].ToString();//convert to string
label1.Text = TestString;
//display

Leaving bytes length as '2' shows value '1' in the text label (form).
Changing it to another higher number still shows '1'. Then when the number is too high, maybe over 150 then there is an exception. I have verified that the '1' displayed is from the memory location I am targeting and not a miscellaneous byte that the RPM code produces.
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 205

Joined: 25 Jan 2006
Posts: 8587
Location: 127.0.0.1

PostPosted: Sun Dec 02, 2012 2:37 pm    Post subject: Reply with quote

You're better off not using classes for reading/writing memory that you find online. Most of them are poor implementations of the API in C# with a zillion wrappers that are unneeded.

Another thing, you already obtained the process using Process.GetProcessesByName, you do not need OpenProcess. The Process class already exposes a fully qualified handle that you can use with the API.

Code:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(
    IntPtr hProcess,
    IntPtr lpBaseAddress,
    [In, Out] byte[] lpBuffer,
    UInt32 nSize,
    ref IntPtr lpNumberOfBytesRead
    );

var procs = Process.GetProcessesByName( "file.exe" );
var buffer = new byte[2048];
var read = new IntPtr(0);
ReadProcessMemory( procs[0].Handle, lpAddress, buffer, (uint)buffer.Length, ref read );


This is a small example, without error checking just to show you how to do things with a bigger buffer. This will read 2048 bytes at once.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
maxmadx
How do I cheat?
Reputation: 0

Joined: 22 May 2012
Posts: 3

PostPosted: Mon Dec 03, 2012 1:37 pm    Post subject: Reply with quote

Wiccaan wrote:
You're better off not using classes for reading/writing memory that you find online. Most of them are poor implementations of the API in C# with a zillion wrappers that are unneeded.

Another thing, you already obtained the process using Process.GetProcessesByName, you do not need OpenProcess. The Process class already exposes a fully qualified handle that you can use with the API.

Code:

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory(
    IntPtr hProcess,
    IntPtr lpBaseAddress,
    [In, Out] byte[] lpBuffer,
    UInt32 nSize,
    ref IntPtr lpNumberOfBytesRead
    );

var procs = Process.GetProcessesByName( "file.exe" );
var buffer = new byte[2048];
var read = new IntPtr(0);
ReadProcessMemory( procs[0].Handle, lpAddress, buffer, (uint)buffer.Length, ref read );


This is a small example, without error checking just to show you how to do things with a bigger buffer. This will read 2048 bytes at once.


Hey thanks for this, I will try it out at the end of next week. Thanks again.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites