Aug 18 2010, 11:54 PM Post #1 | |
Coding like a Rockstar! 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@). |
Aug 18 2010, 11:55 PM Post #2 | |
Coding like a Rockstar! 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. |
Aug 18 2010, 11:55 PM Post #3 | |
Coding like a Rockstar! 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
Cons
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
Cons
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
Cons
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. |
Aug 18 2010, 11:55 PM Post #4 | |
Coding like a Rockstar! 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! -------------------- | CLEO 4.3.22 | A?i?a?o?3D | UI SDK | Black Market Mod 1.0.1 | GInput 0.3 | Cheat Keyboard | Tactile Cheat Activation | Stream Ini Extender 0.7 | SuperVars | ScrDebug | Vigilante Justice: San Andreas | |
Aug 19 2010, 01:43 AM Post #5 | |
Devil's Advocate Posts: 413 From: CA US Joined: 26-July 09 | Cool. -------------------- |
Aug 19 2010, 11:57 AM Post #6 | |
The master of cut retort Posts: 239 From: Warsaw, PL Joined: 21-July 10 | 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 |
Aug 24 2010, 11:49 PM Post #7 | |
Coding like a Rockstar! 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? -------------------- | CLEO 4.3.22 | A?i?a?o?3D | UI SDK | Black Market Mod 1.0.1 | GInput 0.3 | Cheat Keyboard | Tactile Cheat Activation | Stream Ini Extender 0.7 | SuperVars | ScrDebug | Vigilante Justice: San Andreas | |