Coding

 Reply to this postStart new topic

[CLEO|Tut]Additional Variables (34@+)

Deji
post Aug 18 2010, 11:54 PM
Post #1


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



Additional Variables


It's hard to explain in a title, but I'm not using the term "Additional Variables" literally here.

This combines methods from the Using Thread memory and Changing Memory Without CLEO topics. I highly reccommend reading these first if you're not an advanced coder and want to understand the technique used here as from now on, I will assume you know most of what is in those topics.


So.. As we know, special arrays can be used to change memory within range of the SCM Block. We're also able to create thread memory and use it to store things that we don't have enough variables for.

San Andreas, by default; has a local variable range of 0@-33@ in a common, non-mission thread. By using both thread memory and array techniques, we can make it easier for ourselves to use thread memory, by allowing ourselves to use variables 34@ and higher.

These variables, however, will not actually be "extra variables". In fact, we still can't simply use variable 34@ without causing memory to write to the wrong place or a crash. We must use arrays to position the variable structure to our thread memory.

Even better, we can use CLEO 4 to create dynamic memory, meaning we don't have to waste so much memory by creating threads containing blank hex.


Even so, I'll explain the ways to do this through CLEO 4 allocated memory, CLEO 4 thread memory and CLEO 3 thread memory. In the end, you'll be able to write scripts like this:

SANNY
0006: 34@(31@,1i) = 1337
0006: 35@(31@,1i) = 1001
0006: 36@(31@,1i) = 8008

while true
    wait 0
    0AD1: show_formatted_text_highpriority "34: %d, 35: %d, 36: %d" time 1 34@(31@,1i) 35@(31@,1i) 36@(31@,1i)
    // prints "34: 1337, 35: 1001, 36: 8008"
end


31@ is an index and the key to how this whole thing works. You could also use any other variable, but I chose 31@ since if you really need more variables... 0@ would already have been heavily used. You should keep the variable you use as the index untouched. If you mess with it, you may no longer be able to use it as an index var without re-doing the code.


In these examples, I will show you how to set up an index in order to use 7 extra variables (34@-40@).
Go to the top of the page
 
+Quote Post
Deji
post Aug 18 2010, 11:55 PM
Post #2


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



Method 1 - CLEO 4 Allocated Memory (the best way)

For this method, I've made a SCM Function.

Index Setup Code
SANNY
0A9F: 0@ = current_thread_pointer
0AB1: call_scm_func @MakeNewVars 2 amount 7 this_threads_pointer 0@ use_index 31@


Index Release Code
SANNY
0A9F: 0@ = current_thread_pointer
0AB1: call_scm_func @ReleaseVars 2 at_index 31@ this_threads_pointer 0@


SCM Functions
SANNY
:MakeNewVars
0012: 0@ *= 4           // amount * size of variables
0AC8: 0@ = malloc 0@    // allocate the right size to contain the vars
000A: 1@ += 0xC4        // get to var 34@
0A8F: 0@ = 0@ - 1@      // get the offset to the allocated memory
0016: 0@ /= 4           // divide by variable/array size to get the index
0AB2: ret 1 0@          // return the index

:ReleaseVars
0012: 0@ *= 4           // get the offset from the index
000A: 1@ += 0xC4        // get to var 34@
0A8E: 0@ = 0@ + 1@      // get the pointer to the allocated memory
0AC9: free_malloc 0@    // release the memory/variables.. whatever
0AB2: ret 0


Method 2 - CLEO 4 Thread Memory

Variable Space
SANNY
:Variables
hex
   00 00 00 00  // 34@
   00 00 00 00  // 35@
   00 00 00 00  // 36@
   00 00 00 00  // 37@
   00 00 00 00  // 38@
   00 00 00 00  // 39@
   00 00 00 00  // 40@
end


Index Setup Code
SANNY
0AC7: 0@ = var 33@ offset             // get the pointer to the last usable variable
000A: 0@ += 4                         // go the pointer to the next (inexistant) variable (34@)
0AC6: 1@ = label @Variables offset    // get the pointer to the thread to store the new variables data
0A8F: 31@ = 1@ - 0@                   // get the offset from variable 34@ to the memory
0016: 31@ /= 4                        // divide by array size to get the index


Very simple. We are just making it so that the array brings the variable down (or up) to where our memory is. Technically, we could do the same by using the right variable number, like 41232@ or -41232@. But in practice, this isn't possible!

Method 3 - CLEO 3 Opcodes and Thread Memory

Variable Space
SANNY
:Variables
hex
   00 00 00 00  // 34@
   00 00 00 00  // 35@
   00 00 00 00  // 36@
   00 00 00 00  // 37@
   00 00 00 00  // 38@
   00 00 00 00  // 39@
   00 00 00 00  // 40@
end


Index Setup Code
SANNY
// (longer version of the CLEO 4 code)
0A9F: 0@ = current_thread_pointer
0A8E: 1@ = 0@ + 0x10
0A8D: 1@ = read_memory 1@ size 4 virtual_protect 0
000E: 1@ -= @Variables
000A: 0@ += 0xC4
0A8F: 31@ = 1@ - 0@
0016: 31@ /= 4


This setup code is a bit longer than the CLEO 4 Thread Memory one, but does exactly the same thing. CLEO 4 just adds extra opcodes ot make the task more simple.
Go to the top of the page
 
+Quote Post
Deji
post Aug 18 2010, 11:55 PM
Post #3


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



Usage


Choose any method. Here is my reccommendation:

CLEO 3: Method 3
CLEO 4: Method 1
CLEO 4 (small script): Method 2

Method 1
Pro's
  • Easy
  • Optimized
  • Quick
  • Amount of variables is configurable


Cons
  • Uses SCM Functions (although could easily be implemented in other ways to advanced users)


Usage
Call the SCM Function @MakeNewVars, passing the amount of extra variables you want (variables start from 34@), the pointer to the current thread (as obtained by 0A9F). The last parameter should be a variable, which will be used to contain the index.

Use variables freely (see the "Variable Usage" section).

Although it is not required.. After finishing with the variables, you can call @ReleaseVars to free the game memory. Pass the index var and the current threads pointer.

You shouldn't call @MakeNewVars twice! If you need to store the index in another variable (for some reason), use 0085.

Treat the index variable just like the handle of an actor. You can store it in another variable to use and you should release it when you're done with it.


Method 2
Pro's
  • Fairly simple


Cons
  • Uses a lot of game memory
  • No ability to release it and free memory
  • A bit more complex for some users
  • Harder to fit into a script


Usage
SANNY
0AC7: 0@ = var 33@ offset
000A: 0@ += 4
0AC6: 1@ = label @Variables offset
0A8F: 31@ = 1@ - 0@
0016: 31@ /= 4


31@ is the index here. Feel free to change it to something else and use variables freely (see the "Variable Usage" section).

You can change @Variables to whatever you want. Just make sure it is a thread with plenty of free data on!

The thread should look like this:
SANNY
:Variables
hex
  00 00 00 00
  00 00 00 00
  00 00 00 00
end

Each row of 00's (four 00's per variable) is one extra variable, so we can add ones we need and remove ones we don't need.

It starts from 34@, so in this example.. We have extra vars 34@, 35@ and 36@.


Method 3
Pro's
  • Supports CLEO 3


Cons
  • Most complex
  • Uses a lot of game memory
  • No ability to release it and free memory
  • A bit more complex for some users
  • Harder to fit into a script


Usage
SANNY
0A9F: 0@ = current_thread_pointer
0085: 1@ = 0@
000A: 1@ += 0x10
0A8D: 1@ = read_memory 1@ size 4 virtual_protect 0
000E: 1@ -= @Variables
000A: 0@ += 0x3C
0A90: 2@ = 34 * 4
005A: 0@ += 2@
0A8F: 31@ = 1@ - 0@
0016: 31@ /= 4


See "Method 2" for info.
Go to the top of the page
 
+Quote Post
Deji
post Aug 18 2010, 11:55 PM
Post #4


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



Using Variables


Is really simple now we've done the setting up!

SANNY
009A: 34@(31@,1i) = create_actor_pedtype 4 model #MALE01 at 2488.5933 -1664.223 13.3437
0762: AS_actor 34@(31@,1i) dies
01C2: remove_references_to_actor 34@(31@,1i)


These variables can be used for anything a normal variable can. The 1i part of the array should stay the same, unless you are storing strings and such...

SANNY
05AA: 34@(31@,1s) = 'STRING'


Notice the 'i' for "integer" has become 's' for "string". Simple. Remember that they work the same as normal variables, with a 4 byte limit, so strings over 4 bytes will spill into the next variable and so on...

SANNY
05AA: 34@(31@,1s) = 'VAR1VAR2'
// 34@(31@,1s) == VAR1
// 35@(31@,1s) == VAR2


N'joy!


--------------------
Go to the top of the page
 
+Quote Post
Adler
post Aug 19 2010, 01:43 AM
Post #5


Devil's Advocate

Group Icon

Posts: 413
From: CA US
Joined: 26-July 09



Cool.


--------------------
Go to the top of the page
 
+Quote Post
Silent
post Aug 19 2010, 11:57 AM
Post #6


The master of cut retort

Group Icon

Posts: 239
From: Warsaw, PL
Joined: 21-July 10



QUOTE (Deji @ Aug 19 2010, 01:55 AM) *
Notice the 'i' for "integer" has become 's' for "string". Simple. Remember that they work the same as normal variables, with a 4 byte limit, so strings over 4 bytes will spill into the next variable and so on...

SANNY
05AA: 34@(31@,1s) = 'VAR1VAR2'
// 34@(31@,1s) == VAR1
// 35@(31@,1s) == VAR2


N'joy!


Also 'i' must be replaced to 'f', when variable is used to store floats, for example:

SANNY
00A0: store_actor $PLAYER_ACTOR position_to 34@(31@,1f) 35@(31@,1f) 36@(31@,1f)


You can store long strings also, with 'v' index:

SANNY
06D2: 34@(31@,1v) = "Hello, world!" // @v = string
// 34@(31@,1v) == Hell
// 35@(31@,1v) == o, w
// 36@(31@,1v) == orld
// 37@(31@,1v) == !


Very nice article, by the way biggrin.gif
Go to the top of the page
 
+Quote Post
Deji
post Aug 24 2010, 11:49 PM
Post #7


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



See my post here for explanation and fix regarding a crash caused when using these variables with 0AC8.

I might try seeing if there's any other tricks I can muster up using these techniques... Multi-dimensional arrays, perhaps? tongue.gif


--------------------
Go to the top of the page
 
+Quote Post
Reply to this postStart new topic

1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members: