Get Angle Value via ArcTan Table

From Final Fantasy Hacktics Wiki
Jump to navigation Jump to search
Parameters: r4 = value noted as delta Y   
            r5 = value noted as delta X

Returns: r2 = 0x00 if r4 = 0x00 and r5 = 0x00
         r2 = (Degre Angle value * 1024)/90 (from 0x8002fee8 table + offset) - see notes
------------------------------------------------------------------------------------------------------------
0001d8e8: 00003021 addu r6,r0,r0                 |r6 = 0x00
0001d8ec: 04a10003 bgez r5,0x0001d8fc            #If Delta X < 0x00 (Target is to the west)
0001d8f0: 00003821 addu r7,r0,r0                 |r7 = 0x00
0001d8f4: 34060001 ori r6,r0,0x0001                  |r6 = 0x01
0001d8f8: 00052823 subu r5,r0,r5                     |r5 = positive value of delta X 
0001d8fc: 04810003 bgez r4,0x0001d90c            #If Delta Y < 0x00 (Target is to the North)
0001d900: 00000000 nop                               | 
0001d904: 34070001 ori r7,r0,0x0001                  |r7 = 0x01
0001d908: 00042023 subu r4,r0,r4                     |r4 = positive value of delta Y mod
0001d90c: 14a00005 bne r5,r0,0x0001d924          #If Delta X  = 0x00  (Attacker and target are on a north south axe)
0001d910: 0085102a slt r2,r4,r5                  |r2 = 1 if Delta Y  < Delta X 
0001d914: 14800003 bne r4,r0,0x0001d924              #if Delta Y  = 0x00 (attacker and target are on same coordinates)
0001d918: 00000000 nop                                   | 
0001d91c: 08007698 j 0x0001da60                          >> Jump to End
0001d920: 00001021 addu r2,r0,r0                         |r2 = 0x00
0001d924: 10400024 beq r2,r0,0x0001d9b8          #If Delta X  > Delta Y  
0001d928: 3c027fe0 lui r2,0x7fe0                 |r2 = 0x7fe0
0001d92c: 00821024 and r2,r4,r2                      |r2 <> 0x00 if Delta Y > 0x00200000 (delta Y is a positive value so < 0x80000000)
0001d930: 1040000e beq r2,r0,0x0001d96c              #if delta Y >= 0x200000 (note that delta X is > delta Y)
0001d934: 00051283 sra r2,r5,0x0a                    |r2 = delta X/ 1024 
0001d938: 0082001a div r4,r2                             |delta Y mod / (delta X /1024)
0001d93c: 14400002 bne r2,r0,0x0001d948                  #if r2 = 0x00 (div by 0) not possible in theory
0001d940: 00000000 nop                                       | 
0001d944: 0007000d break 0x00001c00                          |Set breakpoint (Crash with psxfin)
0001d948: 2401ffff addiu r1,r0,-0x0001                   |r1 = -0x01
0001d94c: 14410004 bne r2,r1,0x0001d960                  #If r2 = -0x01 (??)  not possible
0001d950: 3c018000 lui r1,0x8000                             |r1 = 0x80000000
0001d954: 14810002 bne r4,r1,0x0001d960                      #if Delta Y = 0x80000000
0001d958: 00000000 nop                                           |
0001d95c: 0006000d break 0x00001800                              |break (lo = -0x01)
0001d960: 00002012 mflo r4                               |Else (r2 > 0x00) r4 = delta Y / (Delta X /1024)
0001d964: 08007669 j 0x0001d9a4                          >>jump to ArcTan Mod loading section
0001d968: 00041040 sll r2,r4,0x01                        |r2 = (delta Y  / (Delta X /1024)) * 2
0001d96c: 00041280 sll r2,r4,0x0a                    #Else (Delta Y < 0x00200000) r2 = delta Y *1024
0001d970: 0045001a div r2,r5                         |(delta Y *1024)/delta X 
0001d974: 14a00002 bne r5,r0,0x0001d980              #If delta X= 0x00
0001d978: 00000000 nop                                   | 
0001d97c: 0007000d break 0x00001c00                      | Break (no div by zero)
0001d980: 2401ffff addiu r1,r0,-0x0001               |r1 = -0x01
0001d984: 14a10004 bne r5,r1,0x0001d998              #if delta X = -0x01
0001d988: 3c018000 lui r1,0x8000                         |r1 = 0x80000000
0001d98c: 14410002 bne r2,r1,0x0001d998                  #if delta Y * 1024 = 0x80000000
0001d990: 00000000 nop                                   |   
0001d994: 0006000d break 0x00001800                          |break
0001d998: 00002012 mflo r4                           #Else (no delta X mod aberration ?) r4 = (delta Y *1024)/delta X
0001d99c: 00000000 nop                               |
0001d9a0: 00041040 sll r2,r4,0x01                    |r2 = ((delta Y*1024)/delta X )*2
0001d9a4: 3c018003 lui r1,0x8003                     |r1 = 0x80030000
0001d9a8: 00220821 addu r1,r1,r2                     |r1 = 0x80030000 + r2 
0001d9ac: 8423fee8 lh r3,-0x0118(r1)                 |r3 = ArcTan Mod
0001d9b0: 08007691 j 0x0001da44                      >>jump
0001d9b4: 00000000 nop                               |
0001d9b8: 00a21024 and r2,r5,r2                  |Else (delta Y > Delta X) r2 = delta X and 0x7fe00000
0001d9bc: 1040000e beq r2,r0,0x0001d9f8          #if r2 <> 0x00 (delta X >= 0x00200000)
0001d9c0: 00041283 sra r2,r4,0x0a                |r2 = Delta Y / 1024
0001d9c4: 00a2001a div r5,r2                         |Delta X / (Delta Y/1024)
0001d9c8: 14400002 bne r2,r0,0x0001d9d4              #If delta Y/1024 = 0x00
0001d9cc: 00000000 nop                                   | 
0001d9d0: 0007000d break 0x00001c00                      |Break (div by 0x00)
0001d9d4: 2401ffff addiu r1,r0,-0x0001               |r1 = -0x01
0001d9d8: 14410004 bne r2,r1,0x0001d9ec              #if delta Y/1024 = -0x01 (??)
0001d9dc: 3c018000 lui r1,0x8000                         |r1 = 0x80000000
0001d9e0: 14a10002 bne r5,r1,0x0001d9ec                  #If Delta X = 0x80000000
0001d9e4: 00000000 nop                                       | 
0001d9e8: 0006000d break 0x00001800                          |Break
0001d9ec: 00002012 mflo r4                           |r4 = Delta X / (Delta Y/1024)
0001d9f0: 0800768c j 0x0001da30                      >>jump to ArcTan Mod loading section
0001d9f4: 00041040 sll r2,r4,0x01                    |r2 = Delta X / (Delta Y/1024)*2
0001d9f8: 00051280 sll r2,r5,0x0a                |Else delta X < 0x00200000) r2 = delta X *1024
0001d9fc: 0044001a div r2,r4                     |(delta X*1024)/delta Y
0001da00: 14800002 bne r4,r0,0x0001da0c          #if Delta Y = 0x00
0001da04: 00000000 nop                               | 
0001da08: 0007000d break 0x00001c00                  |Break
0001da0c: 2401ffff addiu r1,r0,-0x0001           |r1 = -0x01
0001da10: 14810004 bne r4,r1,0x0001da24          #if Delta Y = -0x01
0001da14: 3c018000 lui r1,0x8000                     |r1 = 0x80000000
0001da18: 14410002 bne r2,r1,0x0001da24              #if Delta X*1024 = 0x80000000
0001da1c: 00000000 nop                                   | 
0001da20: 0006000d break 0x00001800                      |break
0001da24: 00002012 mflo r4                       |r4 = (delta X/1024)/delta Y
0001da28: 00000000 nop                           |
0001da2c: 00041040 sll r2,r4,0x01                |r2 = ((delta X/1024)/delta Y)*2
0001da30: 3c018003 lui r1,0x8003                 |r1 = 0x80030000
0001da34: 00220821 addu r1,r1,r2                 |r1 = 0x80030000 + r2 
0001da38: 8423fee8 lh r3,-0x0118(r1)             |r3 = ArcTan Mod 
0001da3c: 34020400 ori r2,r0,0x0400              |r2 = 0x0400 (1024)
0001da40: 00431823 subu r3,r2,r3                 |r3 = ArcTan Mod -1024
0001da44: 10c00002 beq r6,r0,0x0001da50          #If Target is to the west
0001da48: 34020800 ori r2,r0,0x0800              |r2 = 0x800 (2048)
0001da4c: 00431823 subu r3,r2,r3                     |r3 = 2024 - arctan mod
0001da50: 10e00003 beq r7,r0,0x0001da60          #If Target is to the north
0001da54: 00601021 addu r2,r3,r0                 |r2 = ArcTan mod
0001da58: 00031823 subu r3,r0,r3                     |r3 = -ArcTan
0001da5c: 00601021 addu r2,r3,r0                     |r2 = -ArcTan
0001da60: 03e00008 jr r31                        End
0001da64: 00000000 nop

Notes

Returns r2 = (Degre Angle value * 1024)/90 (from 0x8002ffe8 table + offset) 
   East is 0°
   South is 90°
   West is 180°
   North is - 90°
		
Offset for loading value :
   if r5 > r4 and r4 >=0x00200000 : [r4/(r5/1024)]*2  which is (r4/r5)*2048 (without taking account of rounding stuff)
   if r5 > r4 and r4 < 0x00200000 : [(r4*1024)/r5]*2  which is (r4/r5)*2048
   if r4 > r5 and r5 >=0x00200000 : [r5/(r4/1024)]*2  which is (r5/r4)*2048
   if r4 > r4 and r5 < 0x00200000 : [(r5*1024)/r4]*2  which is (r5/r4)*2048

Dividing by the greatest value allow to get the tangent of an angle < 45° (Table hold values from 0 to 45°)

Return locations

Battle.bin
000726ec: 00072674_-_00072708
00072880: Movement/action_direction_setting?
00148160: 00148084_-_00148280
00149844: 0014978c_-_001498f8
001a5f5c: 001a6010_-_001a601c
001a80b8: 001a7f5c_-_001a8668
001a80f4: 001a7f5c_-_001a8668
001afb84: Set_Arcing_Trajectory
001afe8c: 001afd90_-_001aff14
001b00fc: Set_and_Validate_Arc_Trajectory
001b09f0: 001b0818_-_001b0a8c
001b10e8: 001b0ffc - 001b1538
001b113c: 001b0ffc - 001b1538
001b12e0: 001b0ffc - 001b1538 
001b262c: 001b1c04 - 001b27d8
001b3718: 001b33d4 - 001b381c
001b3750: 001b33d4 - 001b381c 
001b3de4: 001b3938 - 001b40f4
001b3e1c: 001b3938 - 001b40f4