Find Unit Abilities or Skillsets

From Final Fantasy Hacktics Wiki
Jump to navigation Jump to search
#   ROUTINE: FIND UNIT ABILITIES OR SKILLSETS
#       Finds abilities or skillsets available to a unit       
#
#       Parameters:
#           r4          = (formationUnitIndex)  Index of unit on formation screen (*0x8018ba20)
#           r5          = (jobID)               Job ID
#           r6          = (slot)                Type of list to generate (skillset or ability type)  (Action = 0, Reaction = 1, Support = 2, Movement = 3)
#           r7          = (outputArray)         Array to write abilities or skillsets into
#           *(sp + 16)  = (mode)                Determines behavior mode of routine
#                                                   0 = Stores learned abilities and abilities that could be learned with JP
#                                                   1 = Stores learned abilities or skillsets; Returns skillsets if slot = 0
#                                                   2 = Stores learned abilities and abilities that the unit has enough JP to learn
#                                                   3 = Doesn't store anything
#       Returns:
#           r2          = Number of output abilities or skillsets

801228f0: 27bdffc0 addiu r29,r29,-0x0040        
801228f4: afb20020 sw r18,0x0020(r29)
801228f8: 00c09021 addu r18,r6,r0                   #   slot
801228fc: afb60030 sw r22,0x0030(r29)
80122900: 00e0b021 addu r22,r7,r0                   #   outputArray
80122904: afb40028 sw r20,0x0028(r29)
80122908: 0080a021 addu r20,r4,r0                   #   formationUnitIndex
8012290c: afb30024 sw r19,0x0024(r29)
80122910: 8fb30050 lw r19,0x0050(r29)               #   mode
80122914: 34020001 ori r2,r0,0x0001                 #   1
80122918: afbf0038 sw r31,0x0038(r29)
8012291c: afb70034 sw r23,0x0034(r29)
80122920: afb5002c sw r21,0x002c(r29)
80122924: afb1001c sw r17,0x001c(r29)
80122928: 16620009 bne r19,r2,0x80122950            #   if ((mode == 1)
8012292c: afb00018 sw r16,0x0018(r29)
80122930: 16400008 bne r18,r0,0x80122954            #       and (slot == 0)) 
80122934: 00058400 sll r16,r5,0x10                  #   {
80122938: 00042400 sll r4,r4,0x10
8012293c: 00042403 sra r4,r4,0x10
80122940: 0c0489e4 jal 0x80122790                   #       return Get known skillsets (formationUnitIndex, outputArray);
80122944: 02c02821 addu r5,r22,r0
80122948: 08048afc j 0x80122bf0
8012294c: 00000000 nop                              #   }
80122950: 00058400 sll r16,r5,0x10
80122954: 00108403 sra r16,r16,0x10
80122958: 0c0489db jal 0x8012276c                   #   skillsetID = Get job's skillset (jobID);
8012295c: 02002021 addu r4,r16,r0
80122960: 00408821 addu r17,r2,r0                   #   skillsetID
80122964: 0c0488ee jal 0x801223b8                   #   jobIndex = Get Generic Job Index (jobID);
80122968: 02002021 addu r4,r16,r0
8012296c: 02202021 addu r4,r17,r0
80122970: 0c0488f9 jal 0x801223e4                   #   jobID = Find Job By Skillset (skillsetID);
80122974: 0040b821 addu r23,r2,r0
80122978: 2403ffff addiu r3,r0,-0x0001
8012297c: 1443000a bne r2,r3,0x801229a8             #   if (jobID == -1) {
80122980: 02202021 addu r4,r17,r0
80122984: 00141400 sll r2,r20,0x10
80122988: 00021383 sra r2,r2,0x0e                   #       formationUnitIndex * 4
8012298c: 3c01801d lui r1,0x801d
80122990: 00220821 addu r1,r1,r2
80122994: 8c22d5ec lw r2,-0x2a14(r1)                #       formationUnit = *formationUnits[formationUnitIndex]
80122998: 00000000 nop
8012299c: 9451005e lhu r17,0x005e(r2)               #       skillsetID = formationUnit.primarySkillset
801229a0: 00000000 nop
801229a4: 02202021 addu r4,r17,r0
                                                    #   }
801229a8: 0c01698e jal 0x8005a638                   #   abilityList = Store Skillset's Abilities (skillsetID, 0x0f);
801229ac: 3405000f ori r5,r0,0x000f
801229b0: 16400004 bne r18,r0,0x801229c4
801229b4: 00408021 addu r16,r2,r0                   #   abilityList
                                                    #   lowerRangeAbilityID = 1
                                                    #   upperRangeAbilityID = 0x1fd
                                                    #   if (slot == 0)  {           // Action
801229b8: 34030001 ori r3,r0,0x0001                 #       lowerRangeAbilityID = 1
801229bc: 08048a80 j 0x80122a00
801229c0: 340201a5 ori r2,r0,0x01a5                 #       upperRangeAbilityID = 0x1a5
801229c4: 34020001 ori r2,r0,0x0001
801229c8: 16420004 bne r18,r2,0x801229dc            #   } else if (slot == 1) {     // Reaction
801229cc: 34020002 ori r2,r0,0x0002
801229d0: 340301a6 ori r3,r0,0x01a6                 #       lowerRangeAbilityID = 0x1a6
801229d4: 08048a80 j 0x80122a00
801229d8: 340201c5 ori r2,r0,0x01c5                 #       upperRangeAbilityID = 0x1c5
801229dc: 16420004 bne r18,r2,0x801229f0            #   } else if (slot == 2) {     // Support
801229e0: 34020003 ori r2,r0,0x0003
801229e4: 340301c6 ori r3,r0,0x01c6                 #       lowerRangeAbilityID = 0x1c6
801229e8: 08048a80 j 0x80122a00
801229ec: 340201e5 ori r2,r0,0x01e5                 #       upperRangeAbilityID = 0x1e5
801229f0: 16420002 bne r18,r2,0x801229fc            #   } else if (slot == 3) {     // Movement
801229f4: 34030001 ori r3,r0,0x0001
801229f8: 340301e6 ori r3,r0,0x01e6                 #       lowerRangeAbilityID = 0x1e6
                                                    #   }
801229fc: 340201fd ori r2,r0,0x01fd                 
80122a00: 00009021 addu r18,r0,r0                   #   abilityListIndex = 0
80122a04: 00603021 addu r6,r3,r0                    #   lowerRangeAbilityID
80122a08: 00402821 addu r5,r2,r0                    #   upperRangeAbilityID
80122a0c: 02002021 addu r4,r16,r0                   #   abilityPtr = &abilityList[0]
                                                    #   do {
80122a10: 84830000 lh r3,0x0000(r4)                 #       abilityID = *abilityPtr
80122a14: 00000000 nop
80122a18: 0066102a slt r2,r3,r6
80122a1c: 14400003 bne r2,r0,0x80122a2c             #       if ((abilityID < lowerRangeAbilityID)
80122a20: 00a3102a slt r2,r5,r3
80122a24: 10400002 beq r2,r0,0x80122a30             #           or (abilityID >= upperRangeAbilityID) 
80122a28: 00000000 nop                              #       {
80122a2c: a4800000 sh r0,0x0000(r4)                 #           *abilityPtr = 0     // Blank out ability
                                                    #       }
80122a30: 26520001 addiu r18,r18,0x0001             #       abilityListIndex = abilityListIndex + 1
80122a34: 2a420018 slti r2,r18,0x0018
80122a38: 1440fff5 bne r2,r0,0x80122a10
80122a3c: 24840002 addiu r4,r4,0x0002               #       abilityPtr = abilityPtr + 2
                                                    #   } while (abilityListIndex < 24);
80122a40: 00008821 addu r17,r0,r0                   #   numStoredAbilities = 0
80122a44: 00009021 addu r18,r0,r0                   #   abilityListIndex = 0
80122a48: 00141400 sll r2,r20,0x10
80122a4c: 3c03801d lui r3,0x801d
80122a50: 2463d5ec addiu r3,r3,-0x2a14              #   formationUnits
80122a54: 00021383 sra r2,r2,0x0e                   #   formationUnitIndex * 4
80122a58: 00431021 addu r2,r2,r3                    #   formationUnitPtr = formationUnits[formationUnitIndex]
80122a5c: 0040a821 addu r21,r2,r0                   #   formationUnitPtr
80122a60: 0200a021 addu r20,r16,r0                  #   abilityPtr = &abilityList[0]   
80122a64: 02c08021 addu r16,r22,r0                  #   outputPtr = outputArray   
80122a68: 00172400 sll r4,r23,0x10
80122a6c: 00042403 sra r4,r4,0x10                   #   jobID
80122a70: 00041040 sll r2,r4,0x01                   #   jobID * 2
80122a74: 00442021 addu r4,r2,r4                    #   jobID * 3
80122a78: 8ea30000 lw r3,0x0000(r21)                #   formationUnit = *formationUnitPtr
80122a7c: 2484007a addiu r4,r4,0x007a               #   (jobID * 3) + 0x7a
80122a80: 00431021 addu r2,r2,r3                    #   formationUnit + (jobID * 2)
80122a84: 945700be lhu r23,0x00be(r2)               #   jobJP = *(formationUnit + (jobID * 2) + 0xbe)
80122a88: 0c04ac6d jal 0x8012b1b4                   #   Store Combined Bit Value Pointer (formationUnit + (jobID * 3) + 0x7a);      // Stores pointer to learned ability data for current job
80122a8c: 00832021 addu r4,r4,r3
                                                    #   for (; abilityListIndex < 24; abilityListIndex++) {
80122a90: 8ea20000 lw r2,0x0000(r21)                #       formationUnit = *formationUnitPtr
80122a94: 00000000 nop
80122a98: 84440024 lh r4,0x0024(r2)                 #       formationUnit.jobID
80122a9c: 0c0482e4 jal 0x80120b90                   #       isSpecialMonster = Special monster check (formationUnit.jobID);
80122aa0: 00000000 nop
80122aa4: 1440000e bne r2,r0,0x80122ae0             
80122aa8: 34030001 ori r3,r0,0x0001                 #       isAbilityLearned = true
                                                    #       if (isSpecialMonster == false) {
80122aac: 8ea20000 lw r2,0x0000(r21)                #           formationUnit = *formationUnitPtr
80122ab0: 00000000 nop
80122ab4: 8442003e lh r2,0x003e(r2)                 #           formationUnit.isPrimarySkillsetMonster
80122ab8: 00000000 nop
80122abc: 10400005 beq r2,r0,0x80122ad4             #           if ((formationUnit.isPrimarySkillsetMonster) {
80122ac0: 2a420003 slti r2,r18,0x0003
80122ac4: 10400044 beq r2,r0,0x80122bd8             #               if (abilityListIndex >= 3) { break; }    // Exit the loop
80122ac8: 34020003 ori r2,r0,0x0003
80122acc: 08048ab8 j 0x80122ae0
80122ad0: 00000000 nop                              #           } else {
80122ad4: 0c04ac7b jal 0x8012b1ec                   #               isAbilityLearned = Get Combined Bit Value From Stored Pointer (1);
80122ad8: 34040001 ori r4,r0,0x0001
80122adc: 00401821 addu r3,r2,r0                    #               isAbilityLearned
                                                    #           }
                                                    #       }
80122ae0: 86850000 lh r5,0x0000(r20)                #       abilityID = *abilityPtr
80122ae4: 00000000 nop
80122ae8: 10a00036 beq r5,r0,0x80122bc4
80122aec: 00a02021 addu r4,r5,r0                    #       abilityStoreValue = abilityID
                                                    #       if (abilityID == 0) { continue; }               // Go to next iteration
80122af0: 1660000f bne r19,r0,0x80122b30            #       if (mode == 0) {
80122af4: 34020001 ori r2,r0,0x0001
80122af8: 1460000b bne r3,r0,0x80122b28             #           if (isAbilityLearned) {       
80122afc: 000510c0 sll r2,r5,0x03                   #               abilityID * 8
80122b00: 3c018006 lui r1,0x8006
80122b04: 00220821 addu r1,r1,r2
80122b08: 9022ebf3 lbu r2,-0x140d(r1)               #               abilities[abilityID].miscFlags
80122b0c: 00000000 nop
80122b10: 000211c2 srl r2,r2,0x07                   #               canLearnWithJP = abilities[abilityID].miscFlags >> 7
80122b14: 14400003 bne r2,r0,0x80122b24             #               if (canLearnWithJP == false) {
80122b18: 00000000 nop
80122b1c: 08048aca j 0x80122b28
80122b20: 34844000 ori r4,r4,0x4000                 #                   abilityStoreValue = abilityStoreValue | 0x4000
                                                    #               } else {
80122b24: 34846000 ori r4,r4,0x6000                 #                   abilityStoreValue = abilityStoreValue | 0x6000
                                                    #               }
                                                    #           }
80122b28: 08048aef j 0x80122bbc
80122b2c: a6040000 sh r4,0x0000(r16)                #           *outputPtr = abilityStoreValue
                                                    
80122b30: 16620005 bne r19,r2,0x80122b48            #       } else if (mode == 1) {
80122b34: 00000000 nop
80122b38: 10600022 beq r3,r0,0x80122bc4             #           if (isAbilityLearned == false) { continue; }        // Go to next iteration
80122b3c: 00000000 nop
80122b40: 08048aef j 0x80122bbc
80122b44: a6040000 sh r4,0x0000(r16)                #           *outputPtr = abilityStoreValue
80122b48: 34020002 ori r2,r0,0x0002
80122b4c: 16620016 bne r19,r2,0x80122ba8            #       } else if (mode == 2) {
80122b50: 00000000 nop
80122b54: 14600011 bne r3,r0,0x80122b9c             #           if (isAbilityLearned == false) {
80122b58: 000518c0 sll r3,r5,0x03                   #               abilityID * 8
80122b5c: 3c018006 lui r1,0x8006
80122b60: 00230821 addu r1,r1,r3
80122b64: 9022ebf3 lbu r2,-0x140d(r1)               #               abilities[abilityID].miscFlags
80122b68: 00000000 nop
80122b6c: 000211c2 srl r2,r2,0x07                   #               canLearnWithJP = abilities[abilityID].miscFlags >> 7
80122b70: 14400014 bne r2,r0,0x80122bc4
80122b74: 00171400 sll r2,r23,0x10
80122b78: 3c018006 lui r1,0x8006
80122b7c: 00230821 addu r1,r1,r3
80122b80: 9423ebf0 lhu r3,-0x1410(r1)               #               abilities[abilityID].jpCost
80122b84: 00021403 sra r2,r2,0x10                   #               jobJP
80122b88: 0043102a slt r2,r2,r3                     
80122b8c: 10400004 beq r2,r0,0x80122ba0             #               if (jobJP < abilities[abilityID].jpCost) {
80122b90: 00000000 nop
80122b94: 08048ae8 j 0x80122ba0
80122b98: 34844000 ori r4,r4,0x4000                 #                   abilityStoreValue = abilityStoreValue | 0x4000
                                                    #               }
                                                    #           } else {
80122b9c: 34841000 ori r4,r4,0x1000                 #               abilityStoreValue = abilityStoreValue | 0x1000
                                                    #           }
80122ba0: 08048aef j 0x80122bbc
80122ba4: a6040000 sh r4,0x0000(r16)                #           *outputPtr = abilityStoreValue
80122ba8: 34020003 ori r2,r0,0x0003                 #       } else if (mode == 3) {
80122bac: 16620005 bne r19,r2,0x80122bc4            #           continue;
80122bb0: 00000000 nop                              
80122bb4: 14600003 bne r3,r0,0x80122bc4             #       } else if (isAbilityLearned == false) {
80122bb8: 00000000 nop                              #           continue;
                                                    #       }
80122bbc: 26100002 addiu r16,r16,0x0002             #       outputPtr = outputPtr + 2
80122bc0: 26310001 addiu r17,r17,0x0001             #       numStoredAbilities = numStoredAbilities + 1
80122bc4: 26520001 addiu r18,r18,0x0001             #       (abilityListIndex = abilityListIndex + 1)
80122bc8: 2a420018 slti r2,r18,0x0018
80122bcc: 1440ffb0 bne r2,r0,0x80122a90
80122bd0: 26940002 addiu r20,r20,0x0002             #       abilityPtr = abilityPtr + 2
                                                    #   }
80122bd4: 34020003 ori r2,r0,0x0003
80122bd8: 12620004 beq r19,r2,0x80122bec            #   if (mode != 3) {
80122bdc: 00111040 sll r2,r17,0x01                  #       numStoredAbilities * 2
80122be0: 00561021 addu r2,r2,r22                   #       outputArray + (numStoredAbilities * 2)
80122be4: 2403ffff addiu r3,r0,-0x0001
80122be8: a4430000 sh r3,0x0000(r2)                 #       outputArray[numStoredAbilities] = -1        // Sentinel value at end of array
                                                    #   }
80122bec: 02201021 addu r2,r17,r0                   #   return numStoredAbilities;
80122bf0: 8fbf0038 lw r31,0x0038(r29)
80122bf4: 8fb70034 lw r23,0x0034(r29)
80122bf8: 8fb60030 lw r22,0x0030(r29)
80122bfc: 8fb5002c lw r21,0x002c(r29)
80122c00: 8fb40028 lw r20,0x0028(r29)
80122c04: 8fb30024 lw r19,0x0024(r29)
80122c08: 8fb20020 lw r18,0x0020(r29)
80122c0c: 8fb1001c lw r17,0x001c(r29)
80122c10: 8fb00018 lw r16,0x0018(r29)
80122c14: 27bd0040 addiu r29,r29,0x0040
80122c18: 03e00008 jr r31
80122c1c: 00000000 nop

Return Locations

00122ca0 : Get Equipable RSM
00122cc4 : Get Equipable RSM
0011a40c : Prep Job Wheel and Skillset Display
0011f774 : Learn Abilities Menu
0011f9c0 : Learn Abilities Menu
0011fb28 : Learn Abilities Menu
0011f06c : 0011f040 - 0011f08c
0011a40c : 0011a378 - 0011a4e0
0011fef0 : 0011fd28 - 001200f4
00120020 : 0011fd28 - 001200f4
0011f774 : 0011f5f0 - 0011fc14
0011f9c0 : 0011f5f0 - 0011fc14
0011fb28 : 0011f5f0 - 0011fc14
0011e8a0 : 0011e630 - 0011ed14