Run Script Variable Command (Alternative)

From Final Fantasy Hacktics Wiki
Jump to navigation Jump to search
Alternative programmers annotations here : Run_Script_Variable_Command

Parameters : r4 = Command ID (see notes)
             r5 = 1st Variable ID - Result of this variable will be changed
             r6 = 2nd Value - Might be an immediate or a 2nd Variable
                     If command ID is an even number : 2nd value is used as an immediate
                     If command ID is an odd number : 2nd value is used as a 2nd variable

Store : Result of 1st Variable ID modification at 1st Variable pointer
------------------------------------------------------------------------------------------------
0014a018: 27bdffd0 addiu r29,r29,-0x0030    |
0014a01c: afb20018 sw r18,0x0018(r29)       |
0014a020: 00809021 addu r18,r4,r0           |r18= Command ID
0014a024: afb3001c sw r19,0x001c(r29)       |
0014a028: 00a09821 addu r19,r5,r0           |r19 = Variable ID
0014a02c: afb00010 sw r16,0x0010(r29)       |
0014a030: 00c08021 addu r16,r6,r0           |r16 = 2nd Value
0014a034: 340200be ori r2,r0,0x00be         |r2 = 0xbe (nullification command)
0014a038: afbf002c sw r31,0x002c(r29)       |
0014a03c: afb60028 sw r22,0x0028(r29)       |
0014a040: afb50024 sw r21,0x0024(r29)       |
0014a044: afb40020 sw r20,0x0020(r29)       |
0014a048: 1242001d beq r18,r2,0x0014a0c0    #If Command is not nullification /Else branch directly to 1st Variable loading section
0014a04c: afb10014 sw r17,0x0014(r29)           |
0014a050: 32420001 andi r2,r18,0x0001           |r2 = 0x01 if command is an odd number
0014a054: 14400003 bne r2,r0,0x0014a064         #If Command is an even number (2nd value is an immediate) / Else branch to load 2nd variable
0014a058: 34020021 ori r2,r0,0x0021             |r2 = 0x021
0014a05c: 08052830 j 0x0014a0c0                     >>jump to 1st variable loading section
0014a060: 02008821 addu r17,r16,r0                  |r17 = 2nd value
0014a064: 16020005 bne r16,r2,0x0014a07c        #If 2nd value is 0x21  (Seen here Spell_Quote_determination)
0014a068: 00000000 nop                              |
0014a06c: 0c052923 jal 0x0014a48c                   |-->0014a48c_-_0014a4d4 Weird math altering value at 0x80173c7c, returns r2 with the value
0014a070: 2416ffff addiu r22,r0,-0x0001             |r22 = -0x01
0014a074: 08052831 j 0x0014a0c4                     >>jump to 1st variable loading section
0014a078: 00408821 addu r17,r2,r0                   |r17 = weird value (will be used as 0x21 value)
0014a07c: 0c0528bb jal 0x0014a2ec               #Else 2nd value is variable -->Get Variable's Word Pointer from Variable's_ID Returns r2 = pointer to the word containing the 2nd variable
0014a080: 02002021 addu r4,r16,r0                   |r4 = 2nd variable
0014a084: 02002021 addu r4,r16,r0                   |r4 = 2nd variable
0014a088: 0c0528e7 jal 0x0014a39c                       |-->Get Variable position Return r2 = 2nd variable position in the word (-0x01 if variable is a word)
0014a08c: 00408821 addu r17,r2,r0                   |r17 = 2nd Variable's word pointer
0014a090: 00402821 addu r5,r2,r0                    |r5 = 2nd variable's position
0014a094: 04a00009 bltz r5,0x0014a0bc               #If 2nd Variable is not a word (ID >= 0x80)
0014a098: 2a020360 slti r2,r16,0x0360                   |r2 = 0x01 if 2nd Variable ID < 0x360
0014a09c: 14400002 bne r2,r0,0x0014a0a8                 #If 2nd Variable ID >= 0x360
0014a0a0: 34040001 ori r4,r0,0x0001                     |r4 = 0x01 (Variable length from 0x80 to 0x35f)
0014a0a4: 3404000f ori r4,r0,0x000f                         |r4 = 0x0f (Variable length from 0x360)
0014a0a8: 8e230000 lw r3,0x0000(r17)                    |r3 = 2nd Variable's word
0014a0ac: 00a41004 sllv r2,r4,r5                        |r2 = 2nd Variable's bitmask
0014a0b0: 00431024 and r2,r2,r3                         |r2 = 2nd Variable's word bitmasked
0014a0b4: 08052830 j 0x0014a0c0                         >>jump to 1st variable loading section (keeping r17)
0014a0b8: 00a28806 srlv r17,r2,r5                       |r17 = 2nd Variable value
0014a0bc: 8e310000 lw r17,0x0000(r17)               #Else (2nd Variable is a word) r17 = 2nd Variable value

SECTION : First Variable Loading Section
0014a0c0: 2416ffff addiu r22,r0,-0x01       |r22 = -0x01
0014a0c4: 0c0528bb jal 0x0014a2ec           |-->Get Variable's Word Pointer from Variable's_ID Returns r2 = pointer to the word containing the 2nd variable
0014a0c8: 02602021 addu r4,r19,r0           |r4 = 1st Variable
0014a0cc: 02602021 addu r4,r19,r0           |r4 = 1st Variable
0014a0d0: 0c0528e7 jal 0x0014a39c           |-->Get Variable position Return r2 = 2nd variable position in the word (-0x01 if variable is a word)
0014a0d4: 0040a821 addu r21,r2,r0           | r21 = pointer to the word containing the 1st variable
0014a0d8: 0040a021 addu r20,r2,r0           |r20 = 1st variable position in the word (-0x01 if variable is a word)
0014a0dc: 0680000a bltz r20,0x0014a108      #If 1st Variable is not a word
0014a0e0: 2a620360 slti r2,r19,0x0360           |r2 = 0x01 if 1st variable ID < 0x360
0014a0e4: 14400002 bne r2,r0,0x0014a0f0         #If 1st Variable ID >= 0x360
0014a0e8: 34040001 ori r4,r0,0x0001             |r4 = 0x01 (Variable length from 0x80 to 0x35f)
0014a0ec: 3404000f ori r4,r0,0x000f                 |r4 = 0x0f (Variable length from 0x360)
0014a0f0: 02841004 sllv r2,r4,r20               |r2 = 1st Variable's bitmask
0014a0f4: 8ea30000 lw r3,0x0000(r21)            |r3 = 1st Variable's word
0014a0f8: 0002b027 nor r22,r0,r2                |r22 = Every Other variables values in the word (will be restored later)
0014a0fc: 00431024 and r2,r2,r3                 |r2 = 1st Variable's word bitmasked
0014a100: 08052843 j 0x0014a10c                 >>Jump 2 lines (keeping r16)
0014a104: 02828006 srlv r16,r2,r20              |r16 = 1st Variable value
0014a108: 8eb00000 lw r16,0x0000(r21)         #Else (1st Variable is a word) r16 = 1st Variable value (whole word)

SECTION : Command Execution 
0014a10c: 340200be ori r2,r0,0x00be         |r2 = 0xbe
0014a110: 16420003 bne r18,r2,0x0014a120    #If Command is 0xbe 
0014a114: 2a4200b2 slti r2,r18,0x00b2       |r2 = 0x01 if Command < 0xb2
0014a118: 0805286e j 0x0014a1b8                 >>jump to recursive control section
0014a11c: 00008021 addu r16,r0,r0               |r16 = 0x00
0014a120: 10400003 beq r2,r0,0x0014a130     #If Command < 0xb2
0014a124: 2a4200b4 slti r2,r18,0x00b4       |r2 = 0x01 if Command < 0xb4
0014a128: 0805286e j 0x0014a1b8                 >>jump to recursive control section
0014a12c: 02118021 addu r16,r16,r17             |r16 = 1st Variable value + 2nd Value
0014a130: 10400003 beq r2,r0,0x0014a140     #If Command <0xb4 
0014a134: 2a4200b6 slti r2,r18,0x00b6       |r2 = 0x01 if command < 0xb6
0014a138: 0805286e j 0x0014a1b8                 >>jump to recursive control section
0014a13c: 02118023 subu r16,r16,r17             |r16 = 1st Variable value - 2nd Value
0014a140: 10400004 beq r2,r0,0x0014a154     #If Command < 0xb6
0014a144: 02110018 mult r16,r17                 |1st Variable value * 2nd Value
0014a148: 00008012 mflo r16                     |r16 = 1st Variable value * 2nd Value
0014a14c: 0805286e j 0x0014a1b8                 >>jump to recursive control section
0014a150: 00000000 nop                          |
0014a154: 2a4200b8 slti r2,r18,0x00b8       |r2 = 0x01 if Command < 0xb8
0014a158: 10400009 beq r2,r0,0x0014a180     #If command < 0xb8
0014a15c: 00000000 nop                          |
0014a160: 16200003 bne r17,r0,0x0014a170        #if 2nd value = 0x00 close current thread /Else branch to division
0014a164: 00000000 nop                              |
0014a168: 0c053256 jal 0x0014c958                   |-->0014c958_-_0014c990 Close running thread and seek a new one - r16 is loaded from new thread (0x10)
0014a16c: 00000000 nop                              |
0014a170: 0211001a div r16,r17                  |1st Variable value / 2nd Value
0014a174: 00008012 mflo r16                     |r16 = 1st Variable value / 2nd Value
0014a178: 0805286e j 0x0014a1b8                 >>jump to recursive control section
0014a17c: 00000000 nop                          |
0014a180: 2a4200ba slti r2,r18,0x00ba       |r2 = 0x01 if Command < 0xba
0014a184: 10400005 beq r2,r0,0x0014a19c     #if Command < 0xba
0014a188: 2a4200bc slti r2,r18,0x00bc       |r2 = 0x01 if command < 0xbc
0014a18c: 0211001a div r16,r17                  |1st Variable value / 2nd Value
0014a190: 00008010 mfhi r16                     |r16 = 1st Variable value / 2nd Value
0014a194: 0805286e j 0x0014a1b8                 >>jump to recursive control section
0014a198: 00000000 nop                          |
0014a19c: 10400003 beq r2,r0,0x0014a1ac     #If command < 0xbc
0014a1a0: 2a4200be slti r2,r18,0x00be       |r2 = 0x01 if command < 0xbe
0014a1a4: 0805286e j 0x0014a1b8                 >>jump to recursive control section
0014a1a8: 02118024 and r16,r16,r17              |r16 = 1st Variable value AND 2nd Variable value
0014a1ac: 10400002 beq r2,r0,0x0014a1b8     #If command < 0xbe
0014a1b0: 00000000 nop                          |
0014a1b4: 02118025 or r16,r16,r17               |r16 = 1st Variable value OR 2nd Variable value

SECTION : Preemptive recursive call section - (clear variable 0x00, Check variable 0x1fc and might abort routine)
0014a1b8: 3c028016 lui r2,0x8016            |r2 = 0x80160000
0014a1bc: 904260a3 lbu r2,0x60a3(r2)        |r2 = [0x801660a3] - recursive call control (avoid infinite recursive call)
0014a1c0: 00000000 nop                      |
0014a1c4: 1440002d bne r2,r0,0x0014a27c     #if [0x801660a3] = 0x00 (not recursive call from below section) /Else Branch to store result section
0014a1c8: 2a6203c0 slti r2,r19,0x03c0           |r2 = 0x01 if Variable ID < 0x3c0
0014a1cc: 1440000a bne r2,r0,0x0014a1f8         #If 1st Variable ID >= 0x3c0 (proposition / jobs)
0014a1d0: 34020001 ori r2,r0,0x0001                 |r2 = 0x01
0014a1d4: 3c018016 lui r1,0x8016                    |
0014a1d8: a02260a3 sb r2,0x60a3(r1)                 |Store 0x01 in 0x801660a3 - Avoid infinite loop (jal below, leads here a second time)
0014a1dc: 0c04ed64 jal 0x0013b590                   |-->Get_Script_Variable  Return here with Variable (from r5)  - Clear Variable 0x00 
0014a1e0: 02602021 addu r4,r19,r0                   |r4 = 1st Variable ID
0014a1e4: 2c42000c sltiu r2,r2,0x000c               |r2 = 0x01 if returned value < 0x0c
0014a1e8: 3c018016 lui r1,0x8016                    |
0014a1ec: a02060a3 sb r0,0x60a3(r1)                 |Store 0x00 in 0x801660a3
0014a1f0: 10400033 beq r2,r0,0x0014a2c0             {{f/Cond|Branch to  End  If r2 = 0x00}}
0014a1f4: 00000000 nop                                  |
0014a1f8: 3c028016 lui r2,0x8016                |r2 = 0x80160000
0014a1fc: 904260a3 lbu r2,0x60a3(r2)            |r2 = [0x801660a3] - recursive call control (avoid infinite recursive call)
0014a200: 00000000 nop                          |
0014a204: 1440001d bne r2,r0,0x0014a27c         #if [0x801660a3] = 0x00 (not recursive call from below section) /Else Branch to store result section
0014a208: 34020001 ori r2,r0,0x0001                 |r2 = 0x01
0014a20c: 3c018016 lui r1,0x8016                    |
0014a210: a02260a3 sb r2,0x60a3(r1)                 |Store 0x01 in 0x801660a3
0014a214: 0c04ed64 jal 0x0013b590                   |-->Get_Script_Variable  returns r2 =  0x1fc value
0014a218: 340401fc ori r4,r0,0x01fc                 |r4 = 0x1fc
0014a21c: 3c018016 lui r1,0x8016                    |
0014a220: a02060a3 sb r0,0x60a3(r1)                 |Store 0x00 in 0x801660a3
0014a224: 10400015 beq r2,r0,0x0014a27c             #If 0x1fc value <> 0x00 /Else Branch to store result section
0014a228: 2662ff90 addiu r2,r19,-0x0070                 |r2 = Variable ID - 0x70
0014a22c: 2c420020 sltiu r2,r2,0x0020                   |r2 = 0x01 if Variable ID was between 0x70 and 0x8f (events stuff ?)
0014a230: 14400012 bne r2,r0,0x0014a27c                 #If Variable ID was not between 0x70 and 0x8f
0014a234: 2662fe04 addiu r2,r19,-0x01fc                     |r2 = Variable ID - 1fc
0014a238: 2c420004 sltiu r2,r2,0x0004                       |r2 = 0x01 if variable ID is between 0x1fc and 0x1ff
0014a23c: 1440000f bne r2,r0,0x0014a27c                     #If Variable ID is not between 0x1fc and 0x1ff
0014a240: 34020066 ori r2,r0,0x0066                             |r2 = 0x66
0014a244: 1262000d beq r19,r2,0x0014a27c                        #If Variable ID <> 0x66
0014a248: 2662ffce addiu r2,r19,-0x0032                             |r2 = Variable ID - 0x32
0014a24c: 2c420008 sltiu r2,r2,0x0008                               |r2 = 0x01 if Variable ID is between 0x32 and 0x39
0014a250: 1440000a bne r2,r0,0x0014a27c                             #If Variable is not between 0x32 and 0x39
0014a254: 2a62002c slti r2,r19,0x002c                                   |r2 = 0x01 if variable is < 0x2c
0014a258: 14400008 bne r2,r0,0x0014a27c                                 #If Variable is >= 0x2c
0014a25c: 34020030 ori r2,r0,0x0030                                         |r2 = 0x30
0014a260: 12620006 beq r19,r2,0x0014a27c                                    #If Variable <> 0x30
0014a264: 2662ffaa addiu r2,r19,-0x0056                                         |r2 = Variable ID - 0x56
0014a268: 2c420005 sltiu r2,r2,0x0005                                           |r2 = 0x01 if Variable is between 0x56 and 0x5A
0014a26c: 14400003 bne r2,r0,0x0014a27c                                         #If Variable is not between 0x56 and 0x5a
0014a270: 34020053 ori r2,r0,0x0053                                                 |r2 = 0x53
0014a274: 16620012 bne r19,r2,0x0014a2c0                                            #If Variable is 0x53 - Stay /Else branch to  End  (nothing stored)
0014a278: 00000000 nop                                                                  

SECTION : Store results in right location
0014a27c: 0680000b bltz r20,0x0014a2ac      #If 1st Variable is not a word (ID >=0x80)
0014a280: 2a620360 slti r2,r19,0x0360           |r2 = 0x01 if Variable ID < 0x360
0014a284: 14400002 bne r2,r0,0x0014a290         #If Variable ID > 0x360
0014a288: 34040001 ori r4,r0,0x0001             |r4 = 0x01
0014a28c: 3404000f ori r4,r0,0x000f                 |r4 = 0x0f
0014a290: 02048024 and r16,r16,r4               |r16 = Variable value with size control (value won't exceed size)
0014a294: 8ea20000 lw r2,0x0000(r21)            |r2 = Word containing variable
0014a298: 02908004 sllv r16,r16,r20             |r16 = Variable value in the right postion for his word
0014a29c: 02c21024 and r2,r22,r2                |r2 = Word containing variable without the variable value
0014a2a0: 02021025 or r2,r16,r2                 |r2 = Word updated with new variable value
0014a2a4: 080528b0 j 0x0014a2c0                 >>jump to END 
0014a2a8: aea20000 sw r2,0x0000(r21)            |Store updated word
0014a2ac: 34020019 ori r2,r0,0x0019         #Else (Variable is a word) r2 = 0x19
0014a2b0: 16620003 bne r19,r2,0x0014a2c0        #If Variable ID = 0x19
0014a2b4: aeb00000 sw r16,0x0000(r21)           |Store update Variable value at variable location
0014a2b8: 3c018016 lui r1,0x8016                    |r1 = 0x80160000
0014a2bc: ac305ef4 sw r16,0x5ef4(r1)                |Store result at 0x80165ef4 (Calculator ability Type ?)
0014a2c0: 8fbf002c lw r31,0x002c(r29)       END
0014a2c4: 8fb60028 lw r22,0x0028(r29)       
0014a2c8: 8fb50024 lw r21,0x0024(r29)       
0014a2cc: 8fb40020 lw r20,0x0020(r29)       
0014a2d0: 8fb3001c lw r19,0x001c(r29)       
0014a2d4: 8fb20018 lw r18,0x0018(r29)       
0014a2d8: 8fb10014 lw r17,0x0014(r29)       
0014a2dc: 8fb00010 lw r16,0x0010(r29)       
0014a2e0: 27bd0030 addiu r29,r29,0x0030     
0014a2e4: 03e00008 jr r31                   
0014a2e8: 00000000 nop

Notes

Complex routine doing not such complex things... (while Variable ID is < 0x400 - after it's events and i can't tell yet)

1st Variable will be loaded and might be altered, depending of command ID.(math or logic).
2nd value will be used to change 1st variable value. 2nd value might be an immediate or a variable.
If the command ID is an even number : 2nd value is used as an immediate
If commande ID is an odd number : 2nd value is used as a 2nd variable

Variable have a different length depending of their ID, could be a word or a bit. That's why this routine looks so complicated.

Change the variable value depending of Command (Command are found here Event_Instructions)
- 0xbe is a nullification : 1st variable become 0x00 (do not check 2nd value)
- 0xb0 0xb1 : 1st Variable + 2nd value
- 0xb2 0xb3 : 1st Variable - 2nd value
- 0xb4 0xb5 : 1st Variable * 2nd value
- 0xb6 0xb7 : 1st Variable / 2nd value  
            - there's a check here. if 2nd value is 0x00 call 0014c958_-_0014c990 change thread (every register might change)
- 0xb8 0xb9 : Reminder of 1st Variable / 2nd value 
- 0xba 0xbb : 1st Variable AND 2nd value
- 0xbc 0xbd : 1st Variable OR 2nd value 

There's 2 recursive calls (via Get_Script_Variable)
- first one will clear variable 0x00
- second one depend of 1st variable ID
     - If >= 0x3c0 (propositions/job  - events ?) - depends from where this routine were called
     - Else : returns variable 0x1fc value
          - If = 0x00 : go on
          - If not : check some variable ID and might abort routine
			  
Store the new Variable value on Variable pointer

Return location

0013b600: Get_Script_Variable
0013b614: Get_Script_Variable
0013b6a4: Set_r5_as_New_Variable_Value r4 = 0xbe
0013b6b8: Set_r5_as_New_Variable_Value r4 = 0xb0
00143da8: 00143bd0_-_00145f74  -  Event_Instruction_Main_Routine_1