Difference between revisions of "VC Arrays"

From GTAMods Wiki
Jump to navigation Jump to search
m (categorized properly)
m
 
(5 intermediate revisions by 4 users not shown)
Line 1: Line 1:
=Arrays in Vice City=
+
There are currently three methods of creating arrays in [[Vice City]] scripts.  The first one ([[User:Barton Waterduck|Barton Waterduck]]'s method) has been largely deprecated now due to the fact that, although simple to use in his [[Mission Builder]]s (using pseudo commands), the generated code was large and complicated.
 
 
There are currently three methods of creating arrays.  The first one (Barton Waterduck's method) has been largely depricated now due to the fact that, although simple to use in his builders (using psuedo commands), the generated code was large and complicated.
 
  
 
==Barton Waterduck's Arrays==
 
==Barton Waterduck's Arrays==
Line 7: Line 5:
 
Example of array code in the builder (note: this feature was introduced about v1.3):
 
Example of array code in the builder (note: this feature was introduced about v1.3):
  
 +
<source lang="scm">
 
  DEFINE ARRAY $my_array size 2 type INTEGER
 
  DEFINE ARRAY $my_array size 2 type INTEGER
  // Integer arrays were also used for storing ingame objects.
+
  // Integer arrays were also used for storing in-game objects.
 
   
 
   
 
  :label_my_code_0
 
  :label_my_code_0
Line 20: Line 19:
 
  SET_ARRAY $my_array
 
  SET_ARRAY $my_array
 
  $my_array += 1
 
  $my_array += 1
  0002: jump ££label_my_code_1
+
  0002: jump
 +
</source>
  
Example of this code compiled and decomplied:
+
Example of this code compiled and decompiled:
  
 +
<source lang="scm">
 
  :label_my_array_get_0
 
  :label_my_array_get_0
 
  00D6: if 0
 
  00D6: if 0
 
         $my_array_index == 0
 
         $my_array_index == 0
  004D: jump_if_false ££label_my_array_get_1
+
  004D: jump_if_false
 
       $my_array = $my_array_data_0
 
       $my_array = $my_array_data_0
 
  0051: return
 
  0051: return
Line 34: Line 35:
 
  00D6: if 0
 
  00D6: if 0
 
         $my_array_index == 1
 
         $my_array_index == 1
  004D: jump_if_false ££label_my_array_get_2
+
  004D: jump_if_false
 
       $my_array = $my_array_data_1
 
       $my_array = $my_array_data_1
 
  0051: return
 
  0051: return
Line 44: Line 45:
 
  00D6: if 0
 
  00D6: if 0
 
         $my_array_index == 0
 
         $my_array_index == 0
  004D: jump_if_false ££label_my_array_get_1
+
  004D: jump_if_false
 
       $my_array_data_0 = $my_array
 
       $my_array_data_0 = $my_array
 
  0051: return
 
  0051: return
Line 51: Line 52:
 
  00D6: if 0
 
  00D6: if 0
 
         $my_array_index == 1
 
         $my_array_index == 1
  004D: jump_if_false ££label_my_array_get_2
+
  004D: jump_if_false
 
       $my_array_data_1 = $my_array
 
       $my_array_data_1 = $my_array
 
  0051: return
 
  0051: return
Line 59: Line 60:
 
   
 
   
 
  :label_my_code_1
 
  :label_my_code_1
  0050: gosub ££label_my_array_get_0
+
  0050: gosub
 
  // Get the data from the array at position $my_array_index.
 
  // Get the data from the array at position $my_array_index.
 
   
 
   
Line 65: Line 66:
 
  // Do whatever with it.
 
  // Do whatever with it.
 
   
 
   
  0050: gosub ££label_my_array_get_1
+
  0050: gosub
 
  // Store it again
 
  // Store it again
 
   
 
   
 
  $my_array += 1
 
  $my_array += 1
  0002: jump ££label_my_code_1
+
  0002: jump
 +
</source>
  
This method of array is still most notably used in PatrickW's Marina Carpark Mod.
+
This method of array is most notably used in [[User:PatrickW|PatrickW]]'s [[Marina Carpark]] Mod.
  
 
==CyQ's Arrays==
 
==CyQ's Arrays==
  
The second method of simulating arrays is CyQ's method.  This uses one exploit of the SCM scripting engine in that parameters can be (in almost every OpCode, alot of the defining OpCodes are strangely limited) variables. It also uses the fact that an address, once compiled, is merely an offset from the start of the file (or mission). CyQ arrays calculate the address of a piece of code, store it in a variable then jump to the contents of that variable.
+
The second method of simulating arrays is [[User:CyQ|CyQ]]'s method.  This uses one exploit of the [[Mission Scripting (Overview)|SCM scripting engine]] in that parameters can be variables (in almost every [[OpCode]], a lot of the defining OpCodes are strangely limited). It also uses the fact that an address, once compiled, is merely an offset from the start of the file (or mission). CyQ arrays calculate the address of a piece of code, store it in a variable then [[jump]] to the contents of that variable.
  
Note:  This method requires detailed SCM knowledge to use due to the byte counting and files including this can (reputably) not be decompiled properly (at least by MB). A basic example which you can use to make arrays is explained below:
+
Note:  This method requires detailed [[SCM]] knowledge to use due to the byte counting and files including this can (reputably) not be decompiled properly (at least by VC [[Mission Builder]]). A basic example which you can use to make arrays is explained below:
  
 
To retrieve data.  $var0 - $var2 are the globals where the data is stored.  0@ is the local variable we will work on in the script.
 
To retrieve data.  $var0 - $var2 are the globals where the data is stored.  0@ is the local variable we will work on in the script.
  
 +
<source lang="scm">
 
  :getlabel
 
  :getlabel
  008B: 0@ = $var0   //these are the values we want to return from the array
+
  008B: 0@ = $var0 // these are the values we want to return from the array
  0051: reutrn
+
  0051: return
  008B: 0@ = $var1   //the space that the 008B and the 0051 opcodes take up in total is 10 bytes because:
+
  008B: 0@ = $var1 // the space that the 008B and the 0051 opcodes take up in total is 10 bytes because:
  0051: return     //opcode(2 bytes) + ptype(1 byte) + localvar(2 bytes) + ptype(1 byte) + var(2 bytes) + opcode(2 bytes) = 10
+
  0051: return // opcode(2 bytes) + ptype(1 byte) + localvar(2 bytes) + ptype(1 byte) + var(2 bytes) + opcode(2 bytes) = 10
  008B: 0@ = $var2
+
  008B: 0@ = $var2
  0051: return
+
  0051: return
 
   
 
   
  <Here is where the code will start>
+
  // <Here is where the code will start>
  008B: 1@ = $index   //if we want the second value then $index = 1 (because for the first value $index = 0)
+
  008B: 1@ = $index // if we want the second value then $index = 1 (because for the first value $index = 0)
  0012: 1@ *= 10       //10 * 1 = 10 (10 because the 008B + 0051 opcodes take up 10 bytes in this case)
+
  0012: 1@ *= 10 //10 * 1 = 10 (10 because the 008B + 0051 opcodes take up 10 bytes in this case)
  000A: 1@ +=  ££getlabel //add the value of ££label to 1@
+
  000A: 1@ +=  // add the value of to 1@
  0050: gosub 1@       //gosub to ££label + 10, so 0@ returns $var1 (the variable numbers match their array index).
+
  0050: gosub 1@ // gosub to + 10, so 0@ returns $var1 (the variable numbers match their array index).
  <Here is where your processing happens>
+
  // <Here is where your processing happens>
 +
</source>
  
 
To store data.
 
To store data.
  
 +
<source lang="scm">
 
  :setlabel
 
  :setlabel
  0088: $var0 = 0@   //these are the values we want to store to the array.
+
  0088: $var0 = 0@ // these are the values we want to store to the array.
  0051: reutrn
+
  0051: return
  0088: $var1 = 0@  
+
  0088: $var1 = 0@  
  0051: return
+
  0051: return
  0088: $var2 = 0@
+
  0088: $var2 = 0@
  0051: return
+
  0051: return
 
   
 
   
  <Here is where your processing happens>
+
  // <Here is where your processing happens>
  008B: 1@ = $index   
+
  008B: 1@ = $index   
  0012: 1@ *= 10     
+
  0012: 1@ *= 10     
  000A: 1@ += ££setlabel
+
  000A: 1@ +=
  0050: gosub 1@     // Same as before only we save the data not retrieve it.
+
  0050: gosub 1@ // Same as before only we save the data not retrieve it.
  <Here is where the code will end>
+
  // <Here is where the code will end>
 +
</source>
  
This method creates an offset from a label based on the index passed to it and a constant representing the number of bytes per short code block when compiled (for more detail on this please see the [[VC_SCM|Vice City SCM Format]] article).  The drawback with this method is that you have to create all the variable writing blocks yourself (although with copy and paste this doesn't take long).
+
This method creates an offset from a [[label]] based on the index passed to it and a constant representing the number of bytes per short code block when compiled (for more detail on this please see the [[VC_SCM|Vice City SCM Format]] article).  The drawback with this method is that you have to create all the variable writing blocks yourself (although with copy and paste this doesn't take long).
  
This method of array (and other implementations of the variable jumping exploit) are most notably found in the original Myriad Islands VC SCM (ironically written by Barton Waterduck).
+
This method of array (and other implementations of the variable jumping exploit) are most notably found in the original [[Myriad Islands]] VC SCM (ironically written by [[User:Barton Waterduck|Barton Waterduck]]).
  
 
==Y_Less's Arrays==
 
==Y_Less's Arrays==
  
Possibly the most difficult and complex implementation of arrays, it is the most accurate representation of arrays (with the index actually changing the array pointer) but it was more created as a 'this is possible' piece than an actual feasable piece.
+
Possibly the most difficult and complex implementation of arrays, it is the most accurate representation of arrays (with the index actually changing the array pointer) but it was more created as a 'this is possible' piece than an actual feasible piece.
  
It uses standard variable storage to store special numbers at consecutive points in the variable block.  These numbers, once as HEX characters in memory will look like compiled SCM code which will be runable and will bypass the Mission Builder limitation of restricting DMA variables to remain within the variable block.  The code in here contains the array index and when code updates the pointer, the actual DMA address of the variable is altered (this is after preprocessing of the index value, similar to multiplying and adding an address in CyQ's arrays).
+
It uses standard variable storage to store special numbers at consecutive points in the variable block.  These numbers, once as HEX characters in memory will look like compiled [[SCM]] code which will be able to run and will bypass the [[Mission Builder]] limitation of restricting DMA variables to remain within the variable block.  The code in here contains the array index and when code updates the pointer, the actual DMA address of the variable is altered (this is after preprocessing of the index value, similar to multiplying and adding an address in [[User:CyQ|CyQ]]'s arrays).
  
The concepts behind it however (code rewriting, still in development by y-less) are more useful with uses such as variable text and code hooking.
+
The concepts behind it however (code rewriting, still in development by [[User:Y_Less|Y_Less]]) are more useful with uses such as variable text and code hooking.
  
The most notable use of code rewriting (as these arrays are never used in real life) is Demarest's Darkpactor code, which uses code developed by him and y-less to rewrite threads to run the darkpact code, unlike in older versions where you had to physically swap SCMs after adding the code.
+
The most notable use of code rewriting (as these arrays are never used in real life) is [[User:Demarest|Demarest]]'s [[Darkpactor]] code, which uses code developed by him and Y_Less to rewrite threads to run the [[Darkpact]] code, unlike in older versions where you had to physically swap SCMs after adding the code.
  
[[Category:GTA_VC]][[Category:Code Snippets]]
+
[[Category:GTA VC]][[Category:Code Snippets]]

Latest revision as of 15:40, 3 February 2009

There are currently three methods of creating arrays in Vice City scripts. The first one (Barton Waterduck's method) has been largely deprecated now due to the fact that, although simple to use in his Mission Builders (using pseudo commands), the generated code was large and complicated.

Barton Waterduck's Arrays

Example of array code in the builder (note: this feature was introduced about v1.3):

Example of this code compiled and decompiled:

This method of array is most notably used in PatrickW's Marina Carpark Mod.

CyQ's Arrays

The second method of simulating arrays is CyQ's method. This uses one exploit of the SCM scripting engine in that parameters can be variables (in almost every OpCode, a lot of the defining OpCodes are strangely limited). It also uses the fact that an address, once compiled, is merely an offset from the start of the file (or mission). CyQ arrays calculate the address of a piece of code, store it in a variable then jump to the contents of that variable.

Note: This method requires detailed SCM knowledge to use due to the byte counting and files including this can (reputably) not be decompiled properly (at least by VC Mission Builder). A basic example which you can use to make arrays is explained below:

To retrieve data. $var0 - $var2 are the globals where the data is stored. 0@ is the local variable we will work on in the script.

To store data.

This method creates an offset from a label based on the index passed to it and a constant representing the number of bytes per short code block when compiled (for more detail on this please see the Vice City SCM Format article). The drawback with this method is that you have to create all the variable writing blocks yourself (although with copy and paste this doesn't take long).

This method of array (and other implementations of the variable jumping exploit) are most notably found in the original Myriad Islands VC SCM (ironically written by Barton Waterduck).

Y_Less's Arrays

Possibly the most difficult and complex implementation of arrays, it is the most accurate representation of arrays (with the index actually changing the array pointer) but it was more created as a 'this is possible' piece than an actual feasible piece.

It uses standard variable storage to store special numbers at consecutive points in the variable block. These numbers, once as HEX characters in memory will look like compiled SCM code which will be able to run and will bypass the Mission Builder limitation of restricting DMA variables to remain within the variable block. The code in here contains the array index and when code updates the pointer, the actual DMA address of the variable is altered (this is after preprocessing of the index value, similar to multiplying and adding an address in CyQ's arrays).

The concepts behind it however (code rewriting, still in development by Y_Less) are more useful with uses such as variable text and code hooking.

The most notable use of code rewriting (as these arrays are never used in real life) is Demarest's Darkpactor code, which uses code developed by him and Y_Less to rewrite threads to run the Darkpact code, unlike in older versions where you had to physically swap SCMs after adding the code.