First Person View [Vega] Play the match with the view similar to a first person shooter!!! Have fun! First person view is disabled during special attack cut scenes or else glitches may occur. X = Slot (which player is effected by code) 0 = 1P 1 = 2P/COM NTSC-U Rev1 040003EC 40490FDB 040003F0 3FC90FDB 04045268 60000000 04044A9C 60000000 0404535C 60000000 04045368 60000000 04045388 60000000 04045394 60000000 C20453A4 00000017 801B000C 2C00000X 408200A4 7F63DB78 3C008004 60002BD4 7C0903A6 4E800421 2C030000 41820088 38630960 E3DF0030 C3FF0038 11A00850 13CDF796 E1A30000 F1BF0020 11AD6CE0 11806A10 3D808000 E16C03EC ED41082A ED2C02B2 ED295828 FD204A10 ED4A02B2 ED0902B2 108C58C0 4084000C EFFF402A 48000008 EFFF4028 D3FF0008 ED010828 FC8D4040 ED6B4828 ED6B02B2 4184000C EDBE582A 48000008 EDBE5828 13CDF460 F3DF0000 D03F001C 60000000 00000000 Code creator: Vega Sources~ RAM Writes: The following addresses are nopped 0x80045268 prevents sub routine call that writes Camera XYZs under normal conditions 0x80044A9C prevents sub routine call that writes Camera XYZs when camera flies back toward your view in the TV screen 0x8004535C prevents sub routine call that writes Camera Long/Lat 0x80045368 prevents sub routine call that writes Camera Long/Lat 0x80045388 prevents sub routine call that writes Camera Long/Lat 0x80045394 prevents sub routine call that writes Camera Long/Lat ##For involving cut scenes, nop 0x80045160 and 80045260. Not recommended, glitches may occur. ASM: #START ASSEMBLY #Address #NTSC-U = 800453A4 #Pi = 0x40490FDB #Half Pi = 0x3FC90FDB #r0 & r3 thru r10 safe, r27 thru r31 safe #f1 always equals 1.0 #f30 and f31 safe #r27 = Master Pointer #MP + 0xC = Slot #r31 = Camera XYZ (Semi-Mod, fully modifiable due to RAM Write Nops) #r31 + 0x20 = Camera Long/Lat Rotation (Semi-Mod, fully modifiable due to RAM Write Nops) #r31 + 0x30 = Copy of Char XYZ (not modifiable, just a copy, there are multiple copies all over memory just as an fyi). The Y coordinate isn't the "true" reading (true-reading = whats in memory at the modifiable spot), its essentially the Y reading but it seems (at quick glance) to always be higher up in Y coord compared to true/modifiable Y coord (lesser float value). #The following is a diagram to show the Camera X and Z Coordinates that need to be written based on how the character is laterally rotated. Camera Y Coordinate is easy to calculate, it's just the Character Y Coordiante minus 1.0. # #The game uses a Pi Scale for Lateral Rotation values (fyi for Longitude too). When you are facing exactly north (in a lateral sense), you are at -0/0. If you turn around 180 degress exactly you are at -Pi/Pi. Turning counter-clockwise decrements the Lateral float value (starting at north 0), and you end up at -Pi. If you keep turning (past 180 degrees), you will then be at Pi and the Lat float value will then increment til you hit 0 (north again). # #Pi = 3.14 on the diagram, simply using 3.14 for personal ease of use #Half-Pi = 1.6, once against personal preference # #Left to Right on the graph is the X coordinate (in game moving Left to Right). #North and South of the graph is the Z Coordinate (in game, moving Forard and Back respectively) # #Y Coordinate (moving Up and Down in game) isn't shown. # #The two asterisks at the center of the diagram represent your eyeballs and they are looking north. Keep in mind though that when the game starts the Match, you are actually almost 180 degrees turned around facing South. Why ps2 devs, why? Lol # #To have a proper first person view no matter what Lateral spin you have, the X and Z values need to be adjusted accordingly to your the character's Lateral Rotation value. I use the constant Pi (3.14) as part of the custom equations I came up with to calculate X and Z values. # #The X and Z values listed in the diagram of the 8 angle examples shown are NOT final. They need a final multiply by 4 to keep the "insides" of the character body from showing for a majority of the movement in the game. # # 0X, 3.14 Z # -0, 0 #-1.6X, 1.6Z | 1.6 X, 1.6 Z # -0.8 | 0.8 # | # | #-3.14X, 0Z *|* 3.14X, 0Z #-1.6 ------------------------- 1.6 # | # | #-1.6X, -1.6Z | 1.6X, -1.6Z # -2.3 | 2.3 # | # 0X, -3.14Z # -3.14, 3.14 # #Usign the diagram below plus the multiplying by 4 that we need, here are the formulae # #Zcam = Camera Z Coordinate that will be written #Zchar = Current Character Z Coordinate #Xcam = Camera x coordinate that will be written #Xchar = Current character x coordinate #Ycam = Camera Y coordinate that will be written #Ychar = current character Y coordinate (non-true) value # #Find Camera Z Coordinate~ # #Note: abs = Absolute Value of # #If absLat < 1.6, Zcam = Zchar + 4*{abs[(absLat*2) - 3.14]} # #If absLat >= 1.6 , Zcam = Zchar - 4*{abs[(absLat*2) - 3.14]} #NOTE We don't need the absolute value of the bracket result, as value will always be zero/positive, but I added it to the equation to show that both equations are nearly identical # #NOTE: The results within the curly brackets {} is known as Zadj. We need that to calculate X. # # #--- # #Find X~ # #If lat is neg, Xcam = Xchar - 4*[(3.14 - Zadj)] #If lat is pos, Xcam = Xchar + 4*[(3.14 - Zadj)] # #--- # #Find Y~ # #Ycam = Ychar - 1.0 # # #For Camera longitude and latitude values, we simply use the character values (basic copy-paste) #User Slot Select Check lwz r0, 0xC (r27) cmpwi r0, 0 #1P used for compilation, adjust this accordingly bne- original_instruction #We already have MP available so we can call GetGeometryPointer. Call it now because if null pointer is returned, we do NOT want code to execute. Function call is safe to do without stack backup because we are hooked near epilogue and Parent function does not read back r3 return value. Yay. mr r3, r27 lis r0, 0x8004 ori r0, r0, 0x2BD4 mtctr r0 bctrl cmpwi r3, 0 beq- original_instruction #We have GeometryPointer in r3, now add 0x960 (2400) to get CharSemiModLongLatRotation pointer. We must do this because upcoming paired singel load only works with 12-bit signed ranges for SIMM. Please also note, that this is NOT an arbitrary addition, this is exactly how the game gets the Character Long/Lat Rotation pointer. addi r3, r3, 0x0960 #Load Character X coord & Y coord (non-true) psq_l f30, 0x30 (r31), 0, 0 #Load Character Z coord lfs f31, 0x38 (r31) #Set f13 as -1.0, have to use ps_neg as we need result in ps1 of f13. Using fneg leaves ps1 result undefined. ps_neg f13, f1 #Subtract 1.0 from non-true Y Coord (this makes you go up the Y coord visually). Make sure X coord is not effected in the subtraction ps_sum1 f30, f13, f30, f30 #Load Character Long/Lat Rotation Values psq_l f13, 0 (r3), 0, 0 #Store Character Long/Lat Rotation Value as Camera Long/Lat's psq_st f13, 0x20 (r31), 0, 0 #Get absolute value of Lat, we need Lat in ps0 & ps1 now. Long value can be wiped. ps_merge11 f13, f13, f13 ps_abs f12, f13 #Do formula on how to update Z camera coord #Note 3.14 simply is for Pi #Note 1.6 simply is for Half-Pi #If absLat < 1.6, Z = Z + 4*{abs[(absLat*2) - 3.14]} #If absLat >= 1.6 , Z = Z - 4*{abs[(absLat*2) - 3.14]} #NOTE We don't need the absolute value of the bracket result, as value will always be zero/positive, but I added it to the equation to show that both equations are almost identical #NOTE: sub-total thats calculated within the curly brackets is called Zadj #Load f11 as pi (ps0) and halfpi (ps1) #Load f10 as 2.0 lis r12, 0x8000 psq_l f11, 0x03EC (r12), 0, 0 fadds f10, f1, f1 #Do 4*{abs[(absLat*2) - 3.14]} fmuls f9, f12, f10 fsubs f9, f9, f11 fabs f9, f9 #f9 now = Zadj #Set f10 to 4.0 to then do the multiply by 4 part fmuls f10, f10, f10 fmuls f8, f9, f10 #Do absLat check (f12 ps1) against Half Pi (f11 ps1) ps_cmpo1 cr1, f12, f11 bge- cr1, subtract_from_Z #Do Z + Zadj fadds f31, f31, f8 b write_cam_Z #Do Z - Zadj subtract_from_Z: fsubs f31, f31, f8 #Write new Cam Z Coordinate write_cam_Z: stfs f31, 0x8 (r31) #We can now calc new Cam X Coord since we have Zadj value #If lat is neg, X = X - 4*[(3.14 - Zadj)] #If lat is pos, X = X + 4*[(3.14 - Zadj)] fsubs f8, f1, f1 #Subtracting f1 by itself will result in 0 fcmpo cr1, f13, f8 #Do 4*[3.14 - Zadj] first fsubs f11, f11, f9 fmuls f11, f11, f10 #Branch blt- cr1, subtract_from_X #Add f11 result to X, place temp result in f13. Due to ps1 being overwritten, we can't store result directly to f30 fadds f13, f30, f11 b write_XandY #Subtract f11 result from X, place temp result in f13. Due to ps1 being overwritten, we can't store result directly to f30 subtract_from_X: fsubs f13, f30, f11 #Y was replaced in f13, but it's still present in f30. Merge f13 (X ps0) and f30 (Y ps1) together write_XandY: ps_merge01 f30, f13, f30 psq_st f30, 0 (r31), 0, 0 #Holy crap, we did it. Original instruction. original_instruction: stfs f1, 0x001C (r31) #END ASSEMBLY