You are not logged in.
Pages: 1
[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
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
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
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
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
Method 2 and 3 make me confused. Where the game stores variables higher than 33? I believe, it goes forward to the next thread.
Method 1 is easier to understand and I guess it's the only one which works properly.
Offline
Method 2 and 3 make me confused. Where the game stores variables higher than 33? I believe, it goes forward to the next thread.
No - method 2 and 3 uses thread memory to store higher variables
: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
Offline
:wow:
although I never ran out of vars in my ridiculous mods but anyway i think this opens some other doors for coding
nice work Deji:^
Offline
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
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
Wow.. you bested me at my own technique
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
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
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
Pages: 1