#1 19-08-2010 01:37

Deji
From: UK
Registered: 09-11-2008
Posts: 189
Website

Additional Variables in CLEO

[center][CLEO|Tut]Setting Up An Additional Variables Index[/center]

New (fixed) post: [CLEO|TuT] Additional Variables, (The easier, safer way!)

It's a long topic, so I won't bother to post the whole thing here, but here's the basic code:


[large]New (Globals) Method[/large]

CLEO 4: Allocated Memory
Still gotta fix this one - last time the offset messed up.

CLEO 4: Thread Memory

0AC6: 31@ = label @Variables offset   // :Variables  should, of course, contain blank data
000E: 31@ -= 0xA49984   // we'll be starting at $1, so lets take that off the amount of memory to skip
0016: 31@ /= 4   // share equally between vars.. lol

CLEO 3: Thread Memory

0A9F: 31@ = current_thread_pointer
000A: 31@ += 0x10
0A8D: 31@ = read_memory 31@ size 4 virtual_protect 0
000E: 31@ -= @Variables
000E: 31@ -= 0xA49984
0016: 31@ /= 4

[large]Old (Locals) Method[/large]

Method 1

0A9F: 0@ = current_thread_pointer
0AB1: call_scm_func @MakeNewVars 2 amount 3 this_threads_pointer 0@ use_index 31@  // add 3 new variables, using 31@ as the index

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

0AB1: call_scm_func @ReleaseVars 2 at_index 31@ this_threads_pointer 0@  // free memory
0A93: end_custom_thread

: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

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
0A93: end_custom_thread

: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

Method 3

// (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
0A93: end_custom_thread

: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

Method 1 - CLEO 4 w/ Memory Allocation using SCM Functions (Reccommended)
Method 2 - CLEO 4 w/ Thread Space
Method 3 - CLEO 3 Compatible Code w/ Thread Space

And yes, I don't literally mean "additional variables". Just an easy, direct way to use thread memory as if they were variables.

Last edited by Deji (06-10-2010 20:29)

Offline

#2 19-08-2010 11:52

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: Additional Variables in CLEO

Very nice. Hope it will become widely used and we get rid of those "not enough variables for my script" complaints.

Although I personally would choose Method 2 (storing the variable values directly in the script space), because of possible memory leaking that might be caused by allocating/deallocating new memory blocks too much. I don't know how CLEO 4 handles the memory allocating and hope it's completely bugs free, but still, method 2 is much more safe in my opinion. Also it will work for CLEO 3 as well.

Could you post Method 2 there with some examples for me to pin this topic?

Offline

#3 19-08-2010 12:10

Alien
Registered: 12-10-2008
Posts: 564

Re: Additional Variables in CLEO

Method completely clean in terms of memory leaks. All allocated memory will be released automaticly on next starting new game / exiting.

Last edited by Alien (19-08-2010 12:11)

Offline

#4 19-08-2010 13:18

Deji
From: UK
Registered: 09-11-2008
Posts: 189
Website

Re: Additional Variables in CLEO

Yes, I did originally worry about problems with memory not releasing but I assumed that CLEO 4 released the allocated memory when you restart the game, meaning that overall, the allocate memory option saves a lot more bytes.

Method 2 is fine if it is for a script that doesn't run all the time, but extra bytes that are all set to 00 seems to be useless in a script that is not yet active. However, the thread methods do allow for default values to be set to each variable before starting, which could be useful in some situations.

I've updated the first post with more info.

I also forgot to mention that the array type should, of course, be changed according to which data type you're using.

0093: 34@(31@,1f) = integer 34@(31@,1i) to_float
05AA: 34@(31@,1s) = 'text' // @s = 'short'
06D2: 34@(31@,1v) = "LAPDAN1" // @v = string

Variables are "limitless". The limit is dependant on your system... I'm sure many other coding tricks could come from using these methods. We also don't have to worry as much about limits to using local variables for strings.

The idea of having to define the array size always confused me.. Is there any explanation of how GTA uses this information? You could just use "1" for anything and it would still go to the right variable.

Last edited by Deji (19-08-2010 16:21)

Offline

#5 19-08-2010 22:25

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: Additional Variables in CLEO

The idea of having to define the array size always confused me.. Is there any explanation of how GTA uses this information? You could just use "1" for anything and it would still go to the right variable.

This number is ignored by the game. Any value is appropriate.

Offline

#6 20-08-2010 09:48

Wesser
From: Matera, Italy
Registered: 12-08-2009
Posts: 10

Re: Additional Variables in CLEO

Method 2 and 3 make me confused. Where the game stores variables higher than 33? I believe, it goes forward to the next thread. rolleyes

Method 1 is easier to understand and I guess it's the only one which works properly. tongue

Offline

#7 20-08-2010 13:40

Silent
Registered: 08-05-2010
Posts: 29

Re: Additional Variables in CLEO

Wesser wrote:

Method 2 and 3 make me confused. Where the game stores variables higher than 33? I believe, it goes forward to the next thread. rolleyes

No - method 2 and 3 uses thread memory to store higher variables smile

: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

Array is calculated to point this label tongue

Offline

#8 20-08-2010 13:56

TheSiggi
Registered: 23-06-2010
Posts: 3

Re: Additional Variables in CLEO

:wow:
although I never ran out of vars in my ridiculous  mods but anyway i think this opens some other doors for coding smile

nice work Deji:^

Offline

#9 20-08-2010 15:04

Wesser
From: Matera, Italy
Registered: 12-08-2009
Posts: 10

Re: Additional Variables in CLEO

SilentPL, I know about that. My point is where those vars will be stored if we read them by getting the label offset? I thought, they are a part of the closest thread in memory.

Nevermind...

Last edited by Wesser (22-08-2010 09:44)

Offline

#10 23-08-2010 12:21

Seemann
Registered: 07-08-2006
Posts: 2,155

Re: Additional Variables in CLEO

For the methods #2 and #3 I would add extra 00 00 00 00 at the beginning and in the end of the buffer. This is necessary in case if the address of the Variables label is not multiple of 4, so when we divide it by 4, the remainder is lost and 31@ will not point at the beginning of the var buffer. For example:

100: var 33@
104: var 34@
...
1001: 0A93: end_custom_thread
1003: :Variables
1003: 00 00 00 00 
1005: 00 00 00 00
...
//calculating 31@ index
0AC7: 0@ = var 33@ offset       // 0@ = 100
000A: 0@ += 4             // 0@ = 104
0AC6: 1@ = label @Variables offset  // 1@ = 1003
0A8F: 31@ = 1@ - 0@           // 31@ = 1003 - 104 = 899
0016: 31@ /= 4                 // 31@ = -224!

so when we use 34@(31@,1i) it will point at: 104 + 224 * 4 = 1000 but we are expecting it to be 1003. And  34@(31@,1i) = 0 will rewrite an opcode preceeding 0A93 with number 0.

If we add extra bytes the problem will be partially solved. The values will be written in the safe place, not changing the thread code.

//solution #1
hex
   00 00 00 00
end
: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
hex
   00 00 00 00
end

But still, we can't set default values for the variables, because we don't know where they are actually located.

The problem can be fully solved by moving the var buffer at the beginning of the script (its starting address is always multiple of 4) and adding a jump and one byte to skip it (extra 8 bytes, no problem with that).

//solution #2
{$CLEO}
hex
  02 00 01 @code 00
end
: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

:code
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

...other code...
0A93: end_custom_thread

Not so pretty code as before, but we can save this additional code to an external file and include in using $I.

//solution #2 short
{$CLEO}
{$I additional_variables.txt}
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

...other code...
0A93: end_custom_thread
//additional_variables.txt #1
hex
  02 00 01 @code 00
end
: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

:code

or even move 31@ calculating there.

//additional_variables.txt #2
hex
  02 00 01 @code 00
end
: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

:code
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

Last edited by Seemann (23-08-2010 12:55)

Offline

#11 23-08-2010 21:58

Deji
From: UK
Registered: 09-11-2008
Posts: 189
Website

Re: Additional Variables in CLEO

Wow.. you bested me at my own technique smile

I actually never considered the offset not being a multiple of 4. In fact the original code had me multiplying by 4, so there was no problem. Took me a while to realise it had to be divided.

Now I understand the need for buffer in the CLEO 3 techniques of using thread memory. I began to doubt the need for such buffer.

Offline

#12 25-08-2010 00:41

Deji
From: UK
Registered: 09-11-2008
Posts: 189
Website

Re: Additional Variables in CLEO

Seems that CLEO 4 doesn't support these methods when using opcode 0AC8.

0AC8: 34@(31@,1i) = allocate_memory_size 26

However, since the value returned to the var used with 0AC8 is nothing more than an address, here's a simple fix:

0AC8: 0@ = allocate_memory_size 26
0085: 34@(31@,1i) = 0@   // store integer of 0@ to 34@

You can then use the variable as normal:

0AD3: 34@(31@,1i) = format "This text is at 0x%X" 0@

You can also now use the 34@ var with 0AC9 to release the memory... It's only 0AC8 that seems to have this problem... CLEO 4 probably attempts to modify 34@, ignoring the array?

Last edited by Deji (25-08-2010 00:44)

Offline

#13 06-10-2010 20:37

Deji
From: UK
Registered: 09-11-2008
Posts: 189
Website

Re: Additional Variables in CLEO

Okay, over time I've found consistant crashes with the local variables method (although Silent says he hasn't experienced this).


I've posted an alternative with global variables, which seem to be much more stable and have quite a lot more opporunities for use, for me...

See the edit of the first post for the code and the link for some extra examples and a description of the errors in the old method and the pros of the new one.

Maybe this topic should be renamed to just "Additional Variables in CLEO" ?

Last edited by Deji (06-10-2010 20:40)

Offline

Board footer

Powered by FluxBB