Quantcast

Jump to content

» «
Photo

Help With Advanced Memory Access

14 replies to this topic
Deji
  • Deji

    Coding like a Rockstar!

  • Feroci Racing
  • Joined: 24 Dec 2007
  • None

#1

Posted 01 July 2009 - 07:39 AM

I just wanna know the basics of Advanced Memory Access... That's a rather conflicting sentence but hey...


What I know, is how to use CLEO to read an adress and modify it, keeping in mind the data type etc...

CODE
0A8D: 7@ = read_memory 0x863984 size 4 virtual_protect 1
000B: 7@ += -0.001
0A8C: write_memory 0x863984 size 4 value 7@ virtual_protect 1



But I'm having trouble understanding this kinda stuff...


CODE
0AA5: call 0x5893B0 num_params 4 pop 4 0 0 0 0@


From my understanding, it calls an address and you can set a number of parameters and then edit each one... But what is pop? And could someone possibly give me an example of this opcode in use and tell me what it effects? wink.gif


CODE
0A9F: 0@ = current_thread_pointer
000A: 0@ += 0x10


So, it stores the memory address "pointer" of the thread, right? What does += 0x10 do and why would it be used? Is it to add to the address so you get something relevant in number to it? Say, the address of Jim is 5 add 10 (or 0x10) and you find Bob? tounge.gif


CODE
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0
000E: 0@ -= @LABEL
000A: 0@ += 4
0A8C: write_memory 0@ size 1 value 2@ virtual_protect 0


Eh? How is it possible to use a label in math and what would give someone the logic to minus a thread and plus 4, to get a desired effect? How would I eventually learn how to know what it does?


Maybe I'm complicating things... But I just know that 0x000000 is an address that stores value of game data. Then, we can edit it to edit the corresponding data. Have no clue how the math ties in with it.

So if anyone can help, I'll be greatful wink.gif Thanks.

trickstar34
  • trickstar34

    ATM, Money

  • BUSTED!
  • Joined: 14 Dec 2008

#2

Posted 01 July 2009 - 07:51 AM

I use these to save property statistics to my mod Empire Mode.

I don't know why you are using a label as a parameter, that will ruin your code right there.

Deji
  • Deji

    Coding like a Rockstar!

  • Feroci Racing
  • Joined: 24 Dec 2007
  • None

#3

Posted 01 July 2009 - 08:24 AM

QUOTE (trickstar34 @ Jul 1 2009, 07:51)
I use these to save property statistics to my mod Empire Mode.

I don't know why you are using a label as a parameter, that will ruin your code right there.

That's the thing... I didn't code that. And it doesn't ruin the code...

You've heard of Ryosuke, right? The Japanese and slightly anomynous CLEO coder? A genuis who I've never heard of or see anywhere but he's made a hella lotta amazing mods.

The code with the thread as the parameter is part of his CLEO Mission loader... I've been trying to basically learn from it and figure out how the hell 0662: NOP "AAAAAAAAAAAAA" is turned into user imputted text...

Also, can someone explain this once and for all... What can NOP be used for? I know it's no operation, but surely, if it does nothing... There's no use in it existing, right? And it certainly does something else it wouldn't really be used...


Oh yeah... What I believe this is something to do with memory as well...

CODE
00D6: if
0038:   &0(0@,1i) == 1464816203
004D: jump_if_false @FW_11
0004: &0(0@,1i) = 1464816128


I've learnt alot and am more than ready to learn some more... And I want all of my longest questions answered so my mind can finally be at peace tounge2.gif

trickstar34
  • trickstar34

    ATM, Money

  • BUSTED!
  • Joined: 14 Dec 2008

#4

Posted 01 July 2009 - 08:37 AM

NOP means Not a OPeration, so you can just say things like you own a copyright or something with it.

PatrickW
  • PatrickW

    GTA Juggernaut

  • Inactive Staff
  • Joined: 07 Jan 2004
  • Netherlands
  • Best Script 2013 [DYOM]
    Best Script 2012 [DYOM]

#5

Posted 01 July 2009 - 09:57 AM Edited by PatrickW, 01 July 2009 - 10:31 AM.

0AA5
0AA5 is used to call a function of the GTA executable, that is normally not accessible from SCM. The first parameter is the address of the function, the second is the number of actual parameters to be passed to the function, and the third parameter is the number of parameters that need to be cleaned up after the function has been executed. After that follow the actual parameters that are passed to the function. Normally the the second and the third parameter should be equal, as most functions in the executable require you the clean up all parameters afterwards.

An example would be:
CODE
0AA5: call 0x718600 num_params 2 pop 2 0@ $TEXTCUR

Which copies a string from the location identified by the second parameter ($TEXTCUR) to the location identiefied by the 1st parameter (0@). You should keep in mind that the function address depends on the version of the executable you have, so typically you should use 0AA9 to determine if you have the original version or not, and depending on that use a different function address.
(This example comes from our DYOM mission mod, where we use it to display custom texts and allow entry of custom texts)

0A9F
This opcode returns you the memory address of the Thread-Structure in memory. In a thread structure, all relevant data for a specific thread is stored, such as the current instruction pointer, gosub-stack, and the local variables.
At offset 0x10, the instruction pointer is located. So by adding 0x10 to the thread-pointer, you get the address of the instruction pointer of the current thread.

Labels
Labels are translated under the hood into a integer value, that indicates the address of the following instruction in memory.

0662: NOP
This is indeed an opcode that does nothing, as the name suggests, but the nice thing about it, is that is accepts a String variable as a parameter (which is of course not used during the "doing nothing" tounge.gif ). But what that parameter does do, is occupy memory in your code-space, that you can later manipulate by the memory-access opcodes. The same can be achieved by HEX..END. In DYOM we use both methods to store all the custom texts in memory and manipulate them.

Deji
  • Deji

    Coding like a Rockstar!

  • Feroci Racing
  • Joined: 24 Dec 2007
  • None

#6

Posted 01 July 2009 - 10:33 PM

Thanks, helpful post. I have a few questions though...

QUOTE (PatrickW)
0A9F
This opcode returns you the memory address of the Thread-Structure in memory. In a thread structure, all relevant data for a specific thread is stored, such as the current instruction pointer, gosub-stack, and the local variables.
At offset 0x10, the instruction pointer is located. So by adding 0x10 to the thread-pointer, you get the address of the instruction pointer of the current thread.


Is there any sort of list I can use as a guide to what number means what or do I have to figure that out manually?


QUOTE (PatrickW)
0662: NOP
This is indeed an opcode that does nothing, as the name suggests, but the nice thing about it, is that is accepts a String variable as a parameter (which is of course not used during the "doing nothing" tounge.gif ). But what that parameter does do, is occupy memory in your code-space, that you can later manipulate by the memory-access opcodes. The same can be achieved by HEX..END. In DYOM we use both methods to store all the custom texts in memory and manipulate them.



So basically, it can store information without actually using variables? Is it possible that I could get an example of this in action? smile.gif



I think I've got a better understanding. In theory, would this code work? Or have I misunderstood anything?

CODE
:THREAD
0662: NOP "DUCK_cower"
0A9F: 0@ = current_thread_pointer
000A: 0@ += 0x // And then whatever pointer could be used to get the NOP inside the thread pointer?
0A8D: 1@ = read_memory 0@ size 8 virtual_protect 0
0605: actor $PLAYER_ACTOR perform_animation_sequence 1@ IFP_file "PED" 4.0 loop 0 0 0 0 time -1
0A93: end_custom_thread


Assuming that's what you meant when you said about the nop values smile.gif

PatrickW
  • PatrickW

    GTA Juggernaut

  • Inactive Staff
  • Joined: 07 Jan 2004
  • Netherlands
  • Best Script 2013 [DYOM]
    Best Script 2012 [DYOM]

#7

Posted 02 July 2009 - 12:11 AM

QUOTE (Deji @ Jul 2 2009, 00:33)
Thanks, helpful post. I have a few questions though...

QUOTE (PatrickW)
0A9F
This opcode returns you the memory address of the Thread-Structure in memory. In a thread structure, all relevant data for a specific thread is stored, such as the current instruction pointer, gosub-stack, and the local variables.
At offset 0x10, the instruction pointer is located. So by adding 0x10 to the thread-pointer, you get the address of the instruction pointer of the current thread.


Is there any sort of list I can use as a guide to what number means what or do I have to figure that out manually?

You can find information about the lay-out of the thread structure here.
There you'll see that I made a mistake in my initial answer.. the IP counter isn't located at offset 0x10. but at offset 0x14 (=20).

The general idea of your example is correct, but it's a bit more complex than that. Maybe I'll write a tutorial about it sometime. Unless you have a very good reason, you should use normal variables to store your data, and only use this stuff if there is no other option. For DYOM we had to use it to be able to support ingame entry of custom texts, and to use those texts.

Deji
  • Deji

    Coding like a Rockstar!

  • Feroci Racing
  • Joined: 24 Dec 2007
  • None

#8

Posted 02 July 2009 - 02:07 AM

QUOTE (PatrickW @ Jul 2 2009, 00:11)
QUOTE (Deji @ Jul 2 2009, 00:33)
Thanks, helpful post. I have a few questions though...

QUOTE (PatrickW)
0A9F
This opcode returns you the memory address of the Thread-Structure in memory. In a thread structure, all relevant data for a specific thread is stored, such as the current instruction pointer, gosub-stack, and the local variables.
At offset 0x10, the instruction pointer is located. So by adding 0x10 to the thread-pointer, you get the address of the instruction pointer of the current thread.


Is there any sort of list I can use as a guide to what number means what or do I have to figure that out manually?

You can find information about the lay-out of the thread structure here.
There you'll see that I made a mistake in my initial answer.. the IP counter isn't located at offset 0x10. but at offset 0x14 (=20).

The general idea of your example is correct, but it's a bit more complex than that. Maybe I'll write a tutorial about it sometime. Unless you have a very good reason, you should use normal variables to store your data, and only use this stuff if there is no other option. For DYOM we had to use it to be able to support ingame entry of custom texts, and to use those texts.

Well, that code was just to get a basic idea of what I'm doing. And the abillity to manage text in game is something I've been wanting for a while for my CLEO Trainer so that the user can customize their Custom CS slot names and so that the "Save Name" script I made works better... Currently you have to edit the fxt, load up the game and then the trainer uses what is in the fxt entry as the save name, but I wanted it to be as "noob" friendly as all the .exe trainers... It's kinda the main goal at the moment smile.gif

I was also working on a keyboard script that I would've been releasing with source and then I suddenly realised "Wait, how am I going to store over 50 characters in 32 variables and how would I combine them into one string?".

For the variables I was originally going to use arrays and I don't know whats wrong with this:

CODE
1@v[1] = "A"


But Sanny says it's illegal lol.gif Must only work on Globals, right? I could easily spoof it as a mission to gain all the other variables as well, but it'd be pretty inconvinient if I wanted to use these scripts to do stuff in a mission or something.

And for combining two longstrings to make one longstring... I have no idea where to start. I was hoping there'd be some magic somewhere that could give me the abillity to do mess around with strings like this.

If I could do that, the next step for me would be getting the name of a running CLEO Thread whilst only knowing the pathname... Then my trainer would be flawless tounge2.gif

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#9

Posted 02 July 2009 - 06:45 AM

QUOTE (Deji @ Jul 1 2009, 22:33)

I think I've got a better understanding. In theory, would this code work? Or have I misunderstood anything?

CODE
:THREAD
0662: NOP "DUCK_cower"
0A9F: 0@ = current_thread_pointer
000A: 0@ += 0x // And then whatever pointer could be used to get the NOP inside the thread pointer?
0A8D: 1@ = read_memory 0@ size 8 virtual_protect 0
0605: actor $PLAYER_ACTOR perform_animation_sequence 1@ IFP_file "PED" 4.0 loop 0 0 0 0 time -1
0A93: end_custom_thread

the anim opcodes requires long string or long string variables as param
06D2: 28@v = "BEACH"// 16-byte strings
06D1: v$1225 = "LAY_BAC_LOOP"// 16-byte strings
its not the same like short strings for text
05AA: 81@s = 'CRA3_DD'
and I think you need to transform the result of read_memory into a short string variable to can use it with a text opcode
just speculation, my skills in memory coding are low

QUOTE (Deji @ Jul 2 2009, 02:07)
For the variables I was originally going to use arrays and I don't know whats wrong with this:
CODE
1@v[1] = "A"



the array construct is wrong, index in brackets are only used with globals
to use locals as indexed array definition use just the expression of a simple local and for following definitions use locals in ascending order
read array tut
fourthermore your exemple shows now a long string variable which can not be used for text opcodes (please correct me if Im wrong)

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#10

Posted 02 July 2009 - 09:49 AM

QUOTE (PatrickW @ Jul 1 2009, 09:57)


Labels
Labels are translated under the hood into a integer value, that indicates the address of the following instruction in memory.


but sanny wont compile if that label dont exist as label in the script
he give the error message: ciro jump

I often tried seemans text exemple but without success
CODE
{$CLEO}

// this opcodes is used to make this thread to be executed once
0A95: enable_thread_saving

// calculates absolute address of the text (opcode 0900) in game memory
0A9F: 0@ = current_thread_pointer
0@ += 0x10
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0
0@ -= @TEXT_PTR  // as all offsets are local (with negative values)

// skips 0900 and datatype bytes, 0@ points directly to the text
0@ += 4

// call ShowTextBox script
0A92: "ShowTextBox.s" 0@
0A93: end_custom_thread      

// custom text
:TEXT_PTR
0900: "if you see this message, CLEO 3 works normally!"

// just a null-terminator
0000: NOP


I understand it so that I should make 2 scripts
the second as ShowTextBox.s
CODE
{$CLEO .cs}
:TEXT_PTR
03A4: name_thread 'CText'

0900: "if you see this message, CLEO 3 works normally!"

// just a null-terminator
0000: NOP
0A93: end_custom_thread


But sanny dont compile the first script because TEXT_PTR dont exist there as label
Whats wrong?

PatrickW
  • PatrickW

    GTA Juggernaut

  • Inactive Staff
  • Joined: 07 Jan 2004
  • Netherlands
  • Best Script 2013 [DYOM]
    Best Script 2012 [DYOM]

#11

Posted 02 July 2009 - 01:09 PM Edited by PatrickW, 02 July 2009 - 01:13 PM.

I'm working on a CLEO mod that lets players enter their custom licenseplate text in game, which will than appeara on their car. It contains text-entry and also examples of storing data in code-space. (Useful when you need to store larger amounts of data in a CLEO.)

It also shows how the code-space stored strings can be used as parameter for calls to exe-routines, and how it can be used everywhere where you would normally need a gxt/fxt entry.

I'll release the fully documented sources also, so that should explain these questions. I should be able to release that in the next couple of days.

@ZAZ: Both your scripts compile without a problem here.

Deji
  • Deji

    Coding like a Rockstar!

  • Feroci Racing
  • Joined: 24 Dec 2007
  • None

#12

Posted 02 July 2009 - 02:04 PM

QUOTE (ZAZ @ Jul 2 2009, 06:45)
QUOTE (Deji @ Jul 2 2009, 02:07)
For the variables I was originally going to use arrays and I don't know whats wrong with this:
CODE
1@v[1] = "A"



the array construct is wrong, index in brackets are only used with globals
to use locals as indexed array definition use just the expression of a simple local and for following definitions use locals in ascending order
read array tut
fourthermore your exemple shows now a long string variable which can not be used for text opcodes (please correct me if Im wrong)

Thought so... I used long string along with the hope to combine and display the text in-game... If I used shortstring gxt/fxt entries, that would cause me some errors if I wanted to use other kinds of code to use the text (e.g licence plate text) then I would need longstring instead of shortstring. However for some things I've found ways to force the game to use a shortstring as if it were longstring.


Could arrays be used in any way to combine 2 longstrings?


About your errors on the showtextbox.s thing, have you tried configuring Sanny to not show you those errors?


QUOTE (PatrickW)
I'm working on a CLEO mod that lets players enter their custom licenseplate text in game, which will than appeara on their car. It contains text-entry and also examples of storing data in code-space. (Useful when you need to store larger amounts of data in a CLEO.)

It also shows how the code-space stored strings can be used as parameter for calls to exe-routines, and how it can be used everywhere where you would normally need a gxt/fxt entry.

I'll release the fully documented sources also, so that should explain these questions. I should be able to release that in the next couple of days.


Great, I've been trying to implement licence plate editing... I just didn't know how to let the user customize the string before applying it to the car.


Anyway, thanks to you all. Your posts have been helpful wink.gif

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#13

Posted 02 July 2009 - 02:07 PM

Patrick, you missunderstood.
The first script is the template of seeman but dont work as one script.

it includes
CODE
0A92: "ShowTextBox.s" 0@

what means that I must have a second script with text
but what should be the content of that script?
Im shure it should be the scriptpart below of 0A93: end_custom_thread

So I must split the template in 2 scripts:

1. this first one dont have the label TEXT_PTR anymore
CODE
{$CLEO}

// this opcodes is used to make this thread to be executed once
0A95: enable_thread_saving

// calculates absolute address of the text (opcode 0900) in game memory
0A9F: 0@ = current_thread_pointer
0@ += 0x10
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0
0@ -= @TEXT_PTR  // as all offsets are local (with negative values)

// skips 0900 and datatype bytes, 0@ points directly to the text
0@ += 4

// call ShowTextBox script
0A92: "ShowTextBox.s" 0@
0A93: end_custom_thread


2. second one
CODE
// custom text
:TEXT_PTR
0900: "if you see this message, CLEO 3 works normally!"

// just a null-terminator
0000: NOP
0A95: enable_thread_saving


PatrickW
  • PatrickW

    GTA Juggernaut

  • Inactive Staff
  • Joined: 07 Jan 2004
  • Netherlands
  • Best Script 2013 [DYOM]
    Best Script 2012 [DYOM]

#14

Posted 02 July 2009 - 03:06 PM Edited by PatrickW, 02 July 2009 - 03:08 PM.

oooh, I misread indeed.

The first script your give should be one script, the part below "0A93: end_custom_thread" is the storage space for the string, and should be in the script itself.

The second script "ShowTextBox.s" is in the "CLEO3/cleo_examples" folder of the regular Sannybuilder distribution.
CODE
// shows a custom text passed to the thread as parameter

{$CLEO .s}

wait 0
0AA9: is_game_version_original
jf @V11
0AA5: call 0x588BE0 num_params 4 pop 4 0 0 0 0@
0A93: end_custom_thread
:V11
0AA5: call 0x5893B0 num_params 4 pop 4 0 0 0 0@
0A93: end_custom_thread

Both the .cs file compiled from the first script and the .s compiled from this script should be in the CLEO folder.


But splitting it up in two scripts isn't really necessary, this should also work as one file:
CODE
{$CLEO}

wait 5000

// this opcodes is used to make this thread to be executed once
0A95: enable_thread_saving

// calculates absolute address of the text (opcode 0900) in game memory
0A9F: 0@ = current_thread_pointer
0@ += 0x10
0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0
0@ -= @TEXT_PTR // as all offsets are local (with negative values)

// skips 0900 and datatype bytes, 0@ points directly to the text
0@ += 4

// call ShowTextBox routine
if 0AA9: is_game_version_original
then
0AA5: call 0x588BE0 num_params 4 pop 4 0 0 0 0@
else
0AA5: call 0x5893B0 num_params 4 pop 4 0 0 0 0@
end
wait 5000

0A93: end_custom_thread

// custom text
:TEXT_PTR
0900: "if you see this message, CLEO 3 works normally!"

// just a null-terminator
0000: NOP

ZAZ
  • ZAZ

    Kernlochbohrer

  • Members
  • Joined: 10 Jan 2005
  • European-Union

#15

Posted 02 July 2009 - 03:30 PM

QUOTE (PatrickW @ Jul 2 2009, 15:06)

The second script "ShowTextBox.s" is in the "CLEO3/cleo_examples" folder of the regular Sannybuilder distribution.

OMG I didnt saw that the ShowTextBox.s have the same name as the 0A92: "ShowTextBox.s" 0@ of the other script.
Thanks it works smile.gif




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users