Get Square root of r4 dealing with 4096

From Final Fantasy Hacktics Wiki
Jump to navigation Jump to search
Parameter : r4 = Input value

Returns : r2 = 0x00 if r4 = 0x00
          if r4 > 0x1000 (4096) : r2 =  (Square root of (r4/4096) )*4096
          if r4 < 0x1000 : r2 =  Square root of (r4 * 4096)
--------------------------------------------------------------------------------------------------
0001c268: 4884f000 mtc2 r4,gtedr30_lzcs          |Move word to coprocessor register gtedr30_lzcs
0001c26c: 00000000 nop                           |
0001c270: 00000000 nop                           |From GTE notes: "Reading LZCR returns the leading 0 count of LZCS if LZCS is positive and the leading 1 count of LZCS if LZCS is negative."
0001c274: 4802f800 mfc2 r2,gtedr31_lzcr          |r2 = r4 number of leading zeros  (Move from coprocessor gtedr31_lzcr)
0001c278: 24010020 addiu r1,r0,0x0020            |r1 = 32
0001c27c: 1041001d beq r2,r1,0x0001c2f4          #If r4 <> 0x00 /Branch if there's 32 leading 0s (r4 = 0x00000000)
0001c280: 00000000 nop                               | 
0001c284: 30480001 andi r8,r2,0x0001                 |r8 = 0s count and 0x01 (0x00 or 0x01)
0001c288: 240afffe addiu r10,r0,-0x0002              |r10 = -0x02 (0xfffffffe)
0001c28c: 004a5024 and r10,r2,r10                    |r10 = even 0s count (down rounded)
0001c290: 24090013 addiu r9,r0,0x0013                |r9 = 0x13 (19)
0001c294: 012a4822 sub r9,r9,r10                     |r9 = 19 - even 0s count (4096 = lowest value with 19 Even zeros)
0001c298: 00094843 sra r9,r9,0x01                    |r9 = (19 - even 0s count)/2    
0001c29c: 214bffe8 addi r11,r10,-0x0018              |r11 > 0x00 if there's more than 24 zeros  (r4 < 0xff)
0001c2a0: 05600003 bltz r11,0x0001c2b0               #If r4 <= 0xff / Branch if r4 > 0xff (less than 24 leading 0's)
0001c2a4: 00000000 nop                                   | 
0001c2a8: 01646004 sllv r12,r4,r11                       |r12 = r4 shifted to let only 24 leading zeros
0001c2ac: 10000003 beq r0,r0,0x0001c2bc                  #Branch if 0 = 0 (why not a jump ?)
0001c2b0: 240b0018 addiu r11,r0,0x0018               #Else (r4 >= 0xff) r11 = 24
0001c2b4: 016a5822 sub r11,r11,r10                       |r11 = 24 - even 0s count
0001c2b8: 01646007 srav r12,r4,r11                       |r12 = r4 shifted to let 24 leading zeros (byted ?)
0001c2bc: 218cffc0 addi r12,r12,-0x0040              |r12 = byted r4 - 0x40
0001c2c0: 000c6040 sll r12,r12,0x01                  |
0001c2c4: 3c0d8003 lui r13,0x8003                    |r13 = 0x80030000
0001c2c8: 01ac6821 addu r13,r13,r12                  |r13 = 0x80030000 + offset (from r4)
0001c2cc: 85adb8b8 lh r13,-0x4748(r13)               |r13 = root square mod    see Square_Root_Mods_Table
0001c2d0: 00000000 nop                               |
0001c2d4: 05200004 bltz r9,0x0001c2e8                #if r9 >= 0 #r4  >= 4096 (sign a value * 4096 ?)
0001c2d8: 00000000 nop                                   | 
0001c2dc: 012d1004 sllv r2,r13,r9                        |r2 = Increased Root square mod  (left shift 19 - r4 leadind 0's count)/2 Half the leading zero before * 4096 (leading 0/2 matches the square root)
0001c2e0: 03e00008 jr r31                                >>Exit
0001c2e4: 00000000 nop                                   |
0001c2e8: 00094822 sub r9,r0,r9                      #Else (r9 < 0) r9 = abs(r9) r4 < 4096
0001c2ec: 03e00008 jr r31                                 >>Exit 
0001c2f0: 012d1006 srlv r2,r13,r9                         |r2 = Decrease Root square mod (right shift r4 leading zeros count - 19)/2 
0001c2f4: 03e00008 jr r31                         #Else (r4 = 0x00)  Exit
0001c2f8: 24020000 addiu r2,r0,0x0000             |r2 = 0x00

Notes

Count the leading zeros of the binary value of r4 (via coprocessor 2)
Down round the count to an even value (look after the first couple of bit that hold a value)
Force r4 to 24(25 if uneven count) leading zeros (so the most left values fit in a byte) - eventually loose the  bits to the right
Use this value to pick up the square root mod
Increase the square root mod if r4 > 0x1000 (by half the leading zeros > 19 (19 zeros is 0x1000))
  #Else decrease the square root mod by half the difference of leading 0 between r4 and 0x1000

Return locations

Battle.bin
0006a89c: 0006a7c0 - 0006aa7c
0006a8e4: 0006a7c0 - 0006aa7c
0006ab48: 0006aa80 - 0006ad14
0006adb0: 0006ad18 - 0006af78
0006adf8: 0006ad18 - 0006af78
00089e70: 00089e20 - 00089f20
00089ea4: 00089e20 - 00089f20
0008a3dc: 0008a35c - 0008a4a8
0008b174: 0008b0c8 - 0008b230
001af520: 001af3dc - 001af598	Maths For Arcing Trajectory
001af760: 001af734 - 001af76c	Give Gravity Impact
001afe78: 001afd90 - 001aff14
001b00e8: 001aff18 - 001b045c	Set and Validate Arc Trajectory - r4 = ((Delta Xmod)^2 + (Delta Y mod)^2)*4096   ((distance between attacker and target)^2)*4096
001b07e0: 001b06d0 - 001b0814
001b0a3c: 001b0818 - 001b0a8c
001b0c4c: 001b0a90 - 001b0c84
001b10d0: 001b0ffc - 001b1538	Bow Arrow Secondary Effect
001b3a1c: 001b3938 - 001b40f4	Linear Projectile secondary effect