diff --git a/Mods/BreathOfTheWild_FPS++/BOTW FPS2.2/Readme.txt b/Mods/BreathOfTheWild_FPS++/BOTW FPS2.2/Readme.txt new file mode 100644 index 00000000..1c165d8f --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/BOTW FPS2.2/Readme.txt @@ -0,0 +1,4 @@ +Since this work isn't wholy mine anymore I feel it needs a readme. +Thanks to the contributors Crementif and EpigramX and as always Rajkosto for the input early on and for making it possible to begin with. Also thanks to the Cemu dev team for creating such a fun emulator. They recently added a debugger to aid in projects like this and I can't wait to try it out. + +Credits for the Arrow fix go to EpigramX and the initial porting of it to fps++ by Crementif. It's always nice to see people contribute to make something better. I fully welcome others messing around with this and have added comments to all the original code in hope that it is easier to understand. But I suck at comments as much as I suck at code. If you have questions about patching feel free to ask me on discord. I would like to avoid situations where a whole bunch of lines are copy pasted into fps++, where 90% of them don't do anything,claiming it fixes things it doesnt. And fragmenting the user base with regards to which fps++ they should use. \ No newline at end of file diff --git a/Mods/BreathOfTheWild_FPS++/BOTW FPS2.2/patches.txt b/Mods/BreathOfTheWild_FPS++/BOTW FPS2.2/patches.txt new file mode 100644 index 00000000..9d48ed8e --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/BOTW FPS2.2/patches.txt @@ -0,0 +1,261 @@ +[BotwFPSV208] +moduleMatches = 0x6267BFD0 + +#rodata constants +_float.5 = 0x100005E0 +_float1 = 0x10000670 +_float30 = 0x101E7964 +#_float30 = 0x10032238 +_convSub = 0x10000BB0 +_float32 = 0x1021FCEC +_arrowsDiv = 0x1001CCAC +_arrowsDer = 0x1001CB18 +_mapSpeed = 0x1022F880 +0x1031E2C0 = .float 2 + + +#TestCave +codeCaveSize = 0x124 + +_fpsCalc = 0x00000018 +0x00000000 = .float 3 ; Don't edit me! +_lowlimit = 0x00000000 +0x00000004 = .float 62156250 +_busSpeed = 0x00000004 +_averageFPS = 0x00000008 +_speedDiv = 0x0000000C + +0x00000010 = .float ($amount_of_FPS_averaged) +_bufferSize = 0x00000010 +0x00000014 = .int (4*$amount_of_FPS_averaged+4) +_numBytes = 0x00000014 + +0x00000018 = stw r0, 0x78(r30) #orig instruction we are replacing ;ticks between frame are currently in r12. +0x0000001C = xoris r12, r12, 0x8000 #flip the sign bit of int ticks for floating point conversion +0x00000020 = stw r12, 0xD4(r30) #store sign flipped ticks in memory as lower half of double +0x00000024 = lis r12, 0x4330 #create upper half of ticks double +0x00000028 = stw r12, 0xD0(r30) #store it in upper half of memory +0x0000002C = lfd f10, 0xD0(r30) #Load full double ticks into f10 +0x00000030 = lis r12, _convSub@ha #load number to subtract from tick double... +0x00000034 = lfd f12, _convSub@l(r12) #...to create tick float into f12 +0x00000038 = fsub f10, f10, f12 #Do the subtraction +0x0000003C = frsp f10, f10 #round to single precision and tick float is in f10 +0x00000040 = lis r12, _float1@ha #Load float of 1... +0x00000044 = lfs f12, _float1@l(r12) #...into f12 +0x00000048 = fdivs f10, f12, f10 #divide 1 by ticks +0x0000004C = lis r12, _busSpeed@ha #load wii u bus speed... +0x00000050 = lfs f12, _busSpeed@l(r12) #...into f12 +0x00000054 = fmuls f10, f12, f10 #multiply bus speed to have current fps in f10. (1/ticks)*bus speed + +0x00000058 = mr r3, r30 #Make a copy of r30 so we can screw around with it +0x0000005C = addi r3, r3, 0xE0 #Add offset to available memory space +0x00000060 = stw r3, 0xD8(r30) #Save our virgin memory address so we can retrieve it later +0x00000064 = lwz r12, 0xDC(r30) #load counter into r12 +0x00000068 = add r3, r3, r12 #add our counter to the offset for our memory location +0x0000006C = stfsu f10, 0x04(r3) #store current fps to memory location +4 and update efective address into r3 +0x00000070 = lfs f7, 0xE0(r30) #Load fpsSum into f7 +0x00000074 = fadds f10, f10, f7 #Add currentFPS to fpsSum +0x00000078 = addi r12, r12, 0x04 #Incriment counter by 4 +0x0000007C = lis r11, _numBytes@ha +0x00000080 = lwz r11, _numBytes@l(r11) +0x00000084 = cmpw r12, r11 #Compare counter with 0x80(32 address from base memory location) +0x00000088 = bne .+0x0C #If we write our last current fps then +0x0000008C = lis r12, 0 #Zero our counter +0x00000090 = lwz r3, 0xD8(r30) #and reload our virgin memory offset +0x00000094 = stw r12, 0xDC(r30) #Store counter r12 to memory location +0x00000098 = lfs f7, 0x04(r3) #load oldest fps into f7 +0x0000009C = fsubs f10, f10, f7 #Subtract oldest fps from fpsSum +0x000000A0 = stfs f10, 0xE0(r30) #store fpsSum back into it's memory address. +0x000000A4 = lis r12, _bufferSize@ha #load 32 as a float ... +0x000000A8 = lfs f7, _bufferSize@l(r12) #...into f7 +0x000000AC = fdivs f10, f10, f7 #divide fps sum by 32, the number of saved fps values, to get average fps over 32 frames +0x000000B0 = lis r12, _averageFPS@ha #Store averaged fps... +0x000000B4 = stfs f10, _averageFPS@l(r12) #... into _averageFPS variable. + +0x000000B8 = lis r12, _float30@ha #Setting up speed diviser. 30/current fps = game speed. ex 30/60 = .5 game speed +0x000000BC = lfs f12, _float30@l(r12) #load float 30 into f12 +0x000000C0 = fdivs f7, f12, f10 #do the division f10 is our current fps(now averaged) +0x000000C4 = lis r12, _lowlimit@ha #set up a low limit to not set game speed below. here: 10/30 = 3 +0x000000C8 = lfs f12, _lowlimit@l(r12) #Set 3 as the low limit into f12 +0x000000CC = lis r12, _speedDiv@ha #prepare to store game speed into _speedDiv but wait. +0x000000D0 = fcmpu cr0, f7, f12 #compare Compare lowlimit with current working game speed +0x000000D4 = bge .+0x08 #If game speed is not being set below 10 fps... +0x000000D8 = b .+0x08 #then skip the next line +0x000000DC = fmr f7, f12 #else overrite working current speed with low limit as new working current speed +0x000000E0 = stfs f7, _speedDiv@l(r12) #store working current speed into _speedDiv + +0x000000E4 = lis r12, _float30@ha #An attempt to port arrow fix to fps++ +0x000000E8 = lfs f12, _float30@l(r12) #load float30 into f12 +0x000000EC = fmuls f10, f7, f12 #arrowsDiv = 30 * speedDiv +0x000000F0 = lis r12, _arrowsDiv@ha +0x000000F4 = stfs f10, _arrowsDiv@l(r12) #store the results +0x000000F8 = lis r12, _float.5@ha #load float of .5 into f12 +0x000000FC = lfs f12, _float.5@l(r12) +0x00000100 = fdivs f10, f12, f7 #arrowsDer = .5 / speedDiv +0x00000104 = lis r12, _arrowsDer@ha +0x00000108 = stfs f10, _arrowsDer@l(r12) #store the results +0x0000010C = blr #return + +_arrowTimeDrain = 0x00000110 +0x00000110 = lfs f1, 0xFC(r11) +0x00000114 = lis r12, _speedDiv@ha +0x00000118 = lfs f0, _speedDiv@l(r12) +0x0000011C = fmuls f1, f1, f0 +0x00000120 = blr + +#codeChanges +0x031FA97C = bla _fpsCalc +0x03793328 = nop +0x03793334 = nop +0x03793378 = lis r29, _speedDiv@ha +0x03793380 = lfs f0, _speedDiv@L(r29) +0x0379338C = nop +0x03415C1C = lis r12, _speedDiv@ha +0x03415C24 = lfs f0, _speedDiv@l(r12) +0x03415C2C = nop +0x02D90D2C = lis r10, _averageFPS@ha +0x02D90D30 = lfs f11, _averageFPS@l(r10) +0x02D90D88 = lis r10, _averageFPS@ha +0x02D90D8C = lfs f11, _averageFPS@l(r10) +0x02D5F760 = bla _arrowTimeDrain +0x037DC35C = lis r12, _speedDiv@ha #Audio fix +0x037DC360 = lfs f13, _speedDiv@l(r12) +0x02F62B3C = lis r12, _speedDiv@ha #map scroll fix +0x02F62B40 = lfs f0, _speedDiv@l(r12) + + + + +#break all forms of frame limiting +0x031FACD0 = nop ; disable vsync +0x031FACF4 = nop ; disable vsync loop + + + +[BotwFPSv176V192] +moduleMatches = 0xFD091F9F, 0xD472D8A5 + +# rodata constants +_float.5 = 0x100005E0 +_float1 = 0x10000670 +_float30 = 0x101E78F4 +_float32 = 0x1025D1A8 +_convSub = 0x10000BB0 +_arrowsDiv = 0x1001CCAC +_arrowsDer = 0x1001CB18 + + +#TestCave +codeCaveSize = 0x124 + +_fpsCalc = 0x00000018 +0x00000000 = .float 3 ; Don't edit me! +_lowlimit = 0x00000000 +0x00000004 = .float 62156250 +_busSpeed = 0x00000004 +_averageFPS = 0x00000008 +_speedDiv = 0x0000000C + +0x00000010 = .float ($amount_of_FPS_averaged) +_bufferSize = 0x00000010 +0x00000014 = .int (4*$amount_of_FPS_averaged+4) +_numBytes = 0x00000014 + +0x00000018 = stw r0, 0x78(r30) #orig instruction we are replacing ;ticks between frame are currently in r12. +0x0000001C = xoris r12, r12, 0x8000 #flip the sign bit of int ticks for floating point conversion +0x00000020 = stw r12, 0xD4(r30) #store sign flipped ticks in memory as lower half of double +0x00000024 = lis r12, 0x4330 #create upper half of ticks double +0x00000028 = stw r12, 0xD0(r30) #store it in upper half of memory +0x0000002C = lfd f10, 0xD0(r30) #Load full double ticks into f10 +0x00000030 = lis r12, _convSub@ha #load number to subtract from tick double... +0x00000034 = lfd f12, _convSub@l(r12) #...to create tick float into f12 +0x00000038 = fsub f10, f10, f12 #Do the subtraction +0x0000003C = frsp f10, f10 #round to single precision and tick float is in f10 +0x00000040 = lis r12, _float1@ha #Load float of 1... +0x00000044 = lfs f12, _float1@l(r12) #...into f12 +0x00000048 = fdivs f10, f12, f10 #divide 1 by ticks +0x0000004C = lis r12, _busSpeed@ha #load wii u bus speed... +0x00000050 = lfs f12, _busSpeed@l(r12) #...into f12 +0x00000054 = fmuls f10, f12, f10 #multiply bus speed to have current fps in f10. (1/ticks)*bus speed + +0x00000058 = mr r3, r30 #Make a copy of r30 so we can screw around with it +0x0000005C = addi r3, r3, 0xE0 #Add offset to available memory space +0x00000060 = stw r3, 0xD8(r30) #Save our virgin memory address so we can retrieve it later +0x00000064 = lwz r12, 0xDC(r30) #load counter into r12 +0x00000068 = add r3, r3, r12 #add our counter to the offset for our memory location +0x0000006C = stfsu f10, 0x04(r3) #store current fps to memory location +4 and update efective address into r3 +0x00000070 = lfs f7, 0xE0(r30) #Load fpsSum into f7 +0x00000074 = fadds f10, f10, f7 #Add currentFPS to fpsSum +0x00000078 = addi r12, r12, 0x04 #Incriment counter by 4 +0x0000007C = lis r11, _numBytes@ha +0x00000080 = lwz r11, _numBytes@l(r11) +0x00000084 = cmpw r12, r11 #Compare counter with 0x80(32 address from base memory location) +0x00000088 = bne .+0x0C #If we write our last current fps then +0x0000008C = lis r12, 0 #Zero our counter +0x00000090 = lwz r3, 0xD8(r30) #and reload our virgin memory offset +0x00000094 = stw r12, 0xDC(r30) #Store counter r12 to memory location +0x00000098 = lfs f7, 0x04(r3) #load oldest fps into f7 +0x0000009C = fsubs f10, f10, f7 #Subtract oldest fps from fpsSum +0x000000A0 = stfs f10, 0xE0(r30) #store fpsSum back into it's memory address. +0x000000A4 = lis r12, _bufferSize@ha #load 32 as a float ... +0x000000A8 = lfs f7, _bufferSize@l(r12) #...into f7 +0x000000AC = fdivs f10, f10, f7 #divide fps sum by 32, the number of saved fps values, to get average fps over 32 frames +0x000000B0 = lis r12, _averageFPS@ha #Store averaged fps... +0x000000B4 = stfs f10, _averageFPS@l(r12) #... into _averageFPS variable. + +0x000000B8 = lis r12, _float30@ha #Setting up speed diviser. 30/current fps = game speed. ex 30/60 = .5 game speed +0x000000BC = lfs f12, _float30@l(r12) #load float 30 into f12 +0x000000C0 = fdivs f7, f12, f10 #do the division f10 is our current fps(now averaged) +0x000000C4 = lis r12, _lowlimit@ha #set up a low limit to not set game speed below. here: 10/30 = 3 +0x000000C8 = lfs f12, _lowlimit@l(r12) #Set 3 as the low limit into f12 +0x000000CC = lis r12, _speedDiv@ha #prepare to store game speed into _speedDiv but wait. +0x000000D0 = fcmpu cr0, f7, f12 #compare Compare lowlimit with current working game speed +0x000000D4 = bge .+0x08 #If game speed is not being set below 10 fps... +0x000000D8 = b .+0x08 #then skip the next line +0x000000DC = fmr f7, f12 #else overrite working current speed with low limit as new working current speed +0x000000E0 = stfs f7, _speedDiv@l(r12) #store working current speed into _speedDiv + +0x000000E4 = lis r12, _float30@ha #An attempt to port arrow fix to fps++ +0x000000E8 = lfs f12, _float30@l(r12) #load float30 into f12 +0x000000EC = fmuls f10, f7, f12 #arrowsDiv = 30 * speedDiv +0x000000F0 = lis r12, _arrowsDiv@ha +0x000000F4 = stfs f10, _arrowsDiv@l(r12) #store the results +0x000000F8 = lis r12, _float.5@ha #load float of .5 into f12 +0x000000FC = lfs f12, _float.5@l(r12) +0x00000100 = fdivs f10, f12, f7 #arrowsDer = .5 / speedDiv +0x00000104 = lis r12, _arrowsDer@ha +0x00000108 = stfs f10, _arrowsDer@l(r12) #store the results +0x0000010C = blr #return + +_arrowTimeDrain = 0x00000110 +0x00000110 = lfs f1, 0xFC(r11) +0x00000114 = lis r12, _speedDiv@ha +0x00000118 = lfs f0, _speedDiv@l(r12) +0x0000011C = fmuls f1, f1, f0 +0x00000120 = blr + +#codeChanges +0x031F9E80 = bla _fpsCalc +0x03792620 = nop +0x0379262C = nop +0x03792670 = lis r29, _speedDiv@ha +0x03792678 = lfs f0, _speedDiv@l(r29) +0x03792684 = nop +0x03414EF8 = lis r12, _speedDiv@ha +0x03414F00 = lfs f0, _speedDiv@l(r12) +0x03414F08 = nop +0x02D90790 = lis r10, _averageFPS@ha +0x02D90794 = lfs f11, _averageFPS@l(r10) +0x02D907EC = lis r10, _averageFPS@ha +0x02D907F0 = lfs f11, _averageFPS@l(r10) +0x02D5F200 = bla _arrowTimeDrain +0x037DB654 = lis r12, _speedDiv@ha +0x037DB658 = lfs f13, _speedDiv@l(r12) + +# Break all forms of frame limiting +0x031FA1D4 = nop +0x031FA1F8 = nop + + + + diff --git a/Mods/BreathOfTheWild_FPS++/BOTW FPS2.2/rules.txt b/Mods/BreathOfTheWild_FPS++/BOTW FPS2.2/rules.txt new file mode 100644 index 00000000..e3299fed --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/BOTW FPS2.2/rules.txt @@ -0,0 +1,30 @@ +[Definition] +titleIds = 00050000101C9300,00050000101C9400,00050000101C9500 +name = Dynamic (FPS++) +path = "The Legend of Zelda: Breath of the Wild/Mods/FPS++/2.2Testing" +description = Important: Don't enable Static FPS while having FPS++ also enabled! This pack won't work without Cemuhook, make sure to install that! This pack only works when you've properly updated your game (we always recommend the latest updates). Keep in mind that going above 30fps will bring game bugs, so you might want to use the "30FPS" preset. +version = 3 + +[Preset] +name = 32 Frames Averaged +$amount_of_FPS_averaged = 32 + +[Preset] +name = 16 Frames Averaged +$amount_of_FPS_averaged = 16 + +[Preset] +name = 8 Frames Averaged +$amount_of_FPS_averaged = 8 + +[Preset] +name = 6 Frames Averaged +$amount_of_FPS_averaged = 6 + +[Preset] +name = 4 Frames Averaged +$amount_of_FPS_averaged = 4 + +[Preset] +name = 3 Frames Averaged +$amount_of_FPS_averaged = 3 \ No newline at end of file diff --git a/Mods/BreathOfTheWild_FPS++/CPU Occlusion Query/patches.txt b/Mods/BreathOfTheWild_FPS++/CPU Occlusion Query/patches.txt new file mode 100644 index 00000000..35e725d1 --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/CPU Occlusion Query/patches.txt @@ -0,0 +1,11 @@ +[BotwFPSV208] +moduleMatches = 0x6267BFD0 + +#code changes +0x03B25BB0 = lis r3, 0 + +[BotwFPSv176V192] +moduleMatches = 0xFD091F9F, 0xD472D8A5 + +#code changes +0x03B24F14 = li r3, 0 \ No newline at end of file diff --git a/Mods/BreathOfTheWild_FPS++/CPU Occlusion Query/rules.txt b/Mods/BreathOfTheWild_FPS++/CPU Occlusion Query/rules.txt new file mode 100644 index 00000000..12f017c5 --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/CPU Occlusion Query/rules.txt @@ -0,0 +1,6 @@ +[Definition] +titleIds = 00050000101C9300,00050000101C9400,00050000101C9500 +name = CPU Occlusion Query +path = "The Legend of Zelda: Breath of the Wild/Mods/FPS++/CPU Occlusion Query" +description = Changes occlusion querys from gpu type to cpu type. Fixes nvidia npc "ai stutter" when full sync at gx2drawdone is disabled. Does not fix camera rune or random crashes. Use lwzx workaround for random crash fix if you disable drawdone. +version = 3 diff --git a/Mods/BreathOfTheWild_FPS++/FenceBest/patches.txt b/Mods/BreathOfTheWild_FPS++/FenceBest/patches.txt new file mode 100644 index 00000000..000221f0 --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/FenceBest/patches.txt @@ -0,0 +1,30 @@ +[BotwFPSV208] +moduleMatches = 0x6267BFD0 +#cave +codeCaveSize = 0x14 + +_fenceNeg1 = 0x00000000 +0x00000000 = add r6, r12, r0 #orig instruction we are replacing +0x00000004 = cmpwi r6, 500 #check if less than 500 (full sync on those first frames to prevent milk water) +0x00000008 = blt .+0x08 #skip subtract if less than +0x0000000C = subi r6, r6, 1 #do the subtract +0x00000010 = blr #return + +#code changes +0x031FAAFC = bla _fenceNeg1 ;Best fence (make sure GPU is never more than 1 frame ahead) + +[BotwFPSv176V192] +moduleMatches = 0xFD091F9F, 0xD472D8A5 + +#cave +codeCaveSize = 0x14 + +_fenceNeg1 = 0x00000000 +0x00000000 = add r6, r12, r0 #orig instruction we are replacing +0x00000004 = cmpwi r6, 500 #check if less than 500 (full sync on those first frames to prevent milk water) +0x00000008 = blt .+0x08 #skip subtract if less than +0x0000000C = subi r6, r6, 1 #do the subtract +0x00000010 = blr + +#code changes +0x031FA000 = bla _fenceNeg1 \ No newline at end of file diff --git a/Mods/BreathOfTheWild_FPS++/FenceBest/rules.txt b/Mods/BreathOfTheWild_FPS++/FenceBest/rules.txt new file mode 100644 index 00000000..936bf18b --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/FenceBest/rules.txt @@ -0,0 +1,6 @@ +[Definition] +titleIds = 00050000101C9300,00050000101C9400,00050000101C9500 +name = Best Fence +path = "The Legend of Zelda: Breath of the Wild/Mods/FPS++/Best Fence" +description = Subtract 1 from fence value. Original default option that is least likely to cause milk water. No difference from best on high end systems. Incompatible with other fence options. +version = 3 diff --git a/Mods/BreathOfTheWild_FPS++/FenceBetter/patches.txt b/Mods/BreathOfTheWild_FPS++/FenceBetter/patches.txt new file mode 100644 index 00000000..b495dcd3 --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/FenceBetter/patches.txt @@ -0,0 +1,11 @@ +[BotwFPSV208] +moduleMatches = 0x6267BFD0 + +#code changes +0x031FAAE8 = li r0, 1 ;Better fence (make sure GPU is never more than 1 second? ahead) + +[BotwFPSv176V192] +moduleMatches = 0xFD091F9F, 0xD472D8A5 + +#code changes +0x031F9FEC = li r0, 1 \ No newline at end of file diff --git a/Mods/BreathOfTheWild_FPS++/FenceBetter/rules.txt b/Mods/BreathOfTheWild_FPS++/FenceBetter/rules.txt new file mode 100644 index 00000000..469819e6 --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/FenceBetter/rules.txt @@ -0,0 +1,6 @@ +[Definition] +titleIds = 00050000101C9300,00050000101C9400,00050000101C9500 +name = Better Fence +path = "The Legend of Zelda: Breath of the Wild/Mods/FPS++/Better Fence" +description = Ensure fence value is always 1. Better for lower end hardware. If you feel like you are getting framerate capped try this. +version = 3 diff --git a/Mods/BreathOfTheWild_FPS++/FenceSkip/patches.txt b/Mods/BreathOfTheWild_FPS++/FenceSkip/patches.txt new file mode 100644 index 00000000..3163ca4e --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/FenceSkip/patches.txt @@ -0,0 +1,11 @@ +[BotwFPSV208] +moduleMatches = 0x6267BFD0 + +#code changes +0x031FAB00 = nop ; skip fence (no waiting on GPU) + +[BotwFPSv176V192] +moduleMatches = 0xFD091F9F, 0xD472D8A5 + +#code changes +0x031FA004 = nop \ No newline at end of file diff --git a/Mods/BreathOfTheWild_FPS++/FenceSkip/rules.txt b/Mods/BreathOfTheWild_FPS++/FenceSkip/rules.txt new file mode 100644 index 00000000..94592656 --- /dev/null +++ b/Mods/BreathOfTheWild_FPS++/FenceSkip/rules.txt @@ -0,0 +1,6 @@ +[Definition] +titleIds = 00050000101C9300,00050000101C9400,00050000101C9500 +name = Skip Fence +path = "The Legend of Zelda: Breath of the Wild/Mods/FPS++/Skip Fence" +description = Don't call gx2setgpufence. Most likely to cause milk water. Incompatible with other fence options. +version = 3 diff --git a/Mods/BreathOfTheWild_FPS++/Readme.txt b/Mods/BreathOfTheWild_FPS++/Readme.txt deleted file mode 100644 index 4ed85497..00000000 --- a/Mods/BreathOfTheWild_FPS++/Readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -Since this work isn't wholy mine anymore I feel it needs a readme. -Thanks to the contributors Crementif and EpigramX and as always Rajkosto for the input early on and for making it possible to begin with. Also thanks to the Cemu dev team for creating such a fun emulator. They recently added a debugger to aid in projects like this and I can't wait to try it out. - -Credits for the Arrow fix go to EpigramX and the initial porting of it to fps++ by Crementif. It's always nice to see people contribute to make something better. I fully welcome others messing around with this and have added comments to all of the original code in hope that it is easier to understand now. But I suck at comments as much as I suck at code. If you have questions about patching feel free to ask me on discord. I would like to avoid situations where a whole bunch of lines are copy pasted into fps++, where 90% of them don't do anything, claiming it fixes things it doesnt. And fragmenting the user base with regards to which fps++ they should use. \ No newline at end of file diff --git a/Mods/BreathOfTheWild_FPS++/patches.txt b/Mods/BreathOfTheWild_FPS++/patches.txt deleted file mode 100644 index 5744c460..00000000 --- a/Mods/BreathOfTheWild_FPS++/patches.txt +++ /dev/null @@ -1,270 +0,0 @@ -[BotwFPSV208] -moduleMatches = 0x6267BFD0 - -#rodata constants -_float.5 = 0x100005E0 -_float1 = 0x10000670 -_float30 = 0x101E7964 -_convSub = 0x10000BB0 -_float32 = 0x1021FCEC -_arrowsDiv = 0x1001CCAC -_arrowsDer = 0x1001CB18 - -#TestCave -codeCaveSize = 0x12C - -_fpsCalc = 0x00000010 -0x00000000 = .float 2 ; Don't edit me! -_lowlimit = 0x00000000 -0x00000004 = .float 62156250 -_busSpeed = 0x00000004 -_averageFPS = 0x00000008 -_speedDiv = 0x0000000C - # HOW TO CHANGE AMOUNT OF FRAMES TO AVERAGE -0x00000128 = .float 32 #This float can be anything. To change the amount of frames averaged change this float... -_bufferSize = 0x00000128 #...and change the "0x84" on line 74 to this number times 4 plus 4 converted to hex. - #Example using 8 frames. 8 x 4 = 34. 34 + 4 = 38. In hex 0x26 - #So line 74 would change from "cmpwi r12, 0x0C" to "cmpwi r12, 0x26" - - -0x00000010 = stw r0, 0x78(r30) #orig instruction we are replacing ;ticks between frame are currently in r12. -0x00000014 = xoris r12, r12, 0x8000 #flip the sign bit of int ticks for floating point conversion -0x00000018 = stw r12, 0xD4(r30) #store sign flipped ticks in memory as lower half of double -0x0000001C = lis r12, 0x4330 #create upper half of ticks double -0x00000020 = stw r12, 0xD0(r30) #store it in upper half of memory -0x00000024 = lfd f10, 0xD0(r30) #Load full double ticks into f10 -0x00000028 = lis r12, _convSub@ha #load number to subtract from tick double... -0x0000002C = lfd f12, _convSub@l(r12) #...to create tick float into f12 -0x00000030 = fsub f10, f10, f12 #Do the subtraction -0x00000034 = frsp f10, f10 #round to single precision and tick float is in f10 -0x00000038 = lis r12, _float1@ha #Load float of 1... -0x0000003C = lfs f12, _float1@l(r12) #...into f12 -0x00000040 = fdivs f10, f12, f10 #divide 1 by ticks -0x00000044 = lis r12, _busSpeed@ha #load wii u bus speed... -0x00000048 = lfs f12, _busSpeed@l(r12) #...into f12 -0x0000004C = fmuls f10, f12, f10 #multiply bus speed to have current fps in f10. (1/ticks)*bus speed - -0x00000050 = mr r3, r30 #Make a copy of r30 so we can screw around with it -0x00000054 = addi r3, r3, 0xE0 #Add offset to available memory space -0x00000058 = stw r3, 0xD8(r30) #Save our virgin memory address so we can retrieve it later -0x0000005C = lwz r12, 0xDC(r30) #load counter into r12 -0x00000060 = add r3, r3, r12 #add our counter to the offset for our memory location -0x00000064 = stfsu f10, 0x04(r3) #store current fps to memory location +4 and update efective address into r3 -0x00000068 = lfs f7, 0xE0(r30) #Load fpsSum into f7 -0x0000006C = fadds f10, f10, f7 #Add currentFPS to fpsSum -0x00000070 = addi r12, r12, 0x04 #Incriment counter by 4 -0x00000074 = cmpwi r12, 0x84 #Compare counter with 0x80(32 address from base memory location) -0x00000078 = bne .+0x0C #If we write our last current fps then -0x0000007C = lis r12, 0 #Zero our counter -0x00000080 = lwz r3, 0xD8(r30) #and reload our virgin memory offset -0x00000084 = stw r12, 0xDC(r30) #Store counter r12 to memory location -0x00000088 = lfs f7, 0x04(r3) #load oldest fps into f7 -0x0000008C = fsubs f10, f10, f7 #Subtract oldest fps from fpsSum -0x00000090 = stfs f10, 0xE0(r30) #store fpsSum back into it's memory address. -0x00000094 = lis r12, _bufferSize@ha #load 32 as a float ... -0x00000098 = lfs f7, _bufferSize@l(r12) #...into f7 -0x0000009C = fdivs f10, f10, f7 #divide fps sum by 32, the number of saved fps values, to get average fps over 32 frames -0x000000A0 = lis r12, _averageFPS@ha #Store averaged fps... -0x000000A4 = stfs f10, _averageFPS@l(r12) #... into _averageFPS variable. - -0x000000A8 = lis r12, _float30@ha #Setting up speed diviser. 30/current fps = game speed. ex 30/60 = .5 game speed -0x000000AC = lfs f12, _float30@l(r12) #load float 30 into f12 -0x000000B0 = fdivs f7, f12, f10 #do the division f10 is our current fps(now averaged) -0x000000B4 = lis r12, _lowlimit@ha #set up a low limit to not set game speed below. here: 10/30 = 3 -0x000000B8 = lfs f12, _lowlimit@l(r12) #Set 3 as the low limit into f12 -0x000000BC = lis r12, _speedDiv@ha #prepare to store game speed into _speedDiv but wait. -0x000000C0 = fcmpu cr0, f7, f12 #compare Compare lowlimit with current working game speed -0x000000C4 = bge .+0x08 #If game speed is not being set below 10 fps... -0x000000C8 = b .+0x08 #then skip the next line -0x000000CC = fmr f7, f12 #else overrite working current speed with low limit as new working current speed -0x000000D0 = stfs f7, _speedDiv@l(r12) #store working current speed into _speedDiv - -0x000000D4 = lis r12, _float30@ha #An attempt to port arrow fix to fps++ -0x000000D8 = lfs f12, _float30@l(r12) #load float30 into f12 -0x000000DC = fmuls f10, f7, f12 #arrowsDiv = 30 * speedDiv -0x000000E0 = lis r12, _arrowsDiv@ha -0x000000E4 = stfs f10, _arrowsDiv@l(r12) #store the results -0x000000E8 = lis r12, _float.5@ha #load float of .5 into f12 -0x000000EC = lfs f12, _float.5@l(r12) -0x000000F0 = fdivs f10, f12, f7 #arrowsDer = .5 / speedDiv -0x000000F4 = lis r12, _arrowsDer@ha -0x000000F8 = stfs f10, _arrowsDer@l(r12) #store the results -0x000000FC = blr #return - -_fenceNeg1 = 0x00000100 -0x00000100 = add r6, r12, r0 #orig instruction we are replacing -0x00000104 = cmpwi r6, 500 #check if less than 500 (full sync on those first frames to prevent milk water) -0x00000108 = blt .+0x08 #skip subtract if less than -0x0000010C = subi r6, r6, 1 #do the subtract -0x00000110 = blr #return - - -_arrowTimeDrain = 0x00000114 -0x00000114 = lfs f1, 0xFC(r11) -0x00000118 = lis r12, _speedDiv@ha -0x0000011C = lfs f0, _speedDiv@l(r12) -0x00000120 = fmuls f1, f1, f0 -0x00000124 = blr - -#codeChanges -0x031FA97C = bla _fpsCalc -0x03793328 = nop -0x03793334 = nop -0x03793378 = lis r29, _speedDiv@ha -0x03793380 = lfs f0, _speedDiv@L(r29) -0x0379338C = nop -0x03415C1C = lis r12, _speedDiv@ha -0x03415C24 = lfs f0, _speedDiv@l(r12) -0x03415C2C = nop -0x02D90D2C = lis r10, _averageFPS@ha -0x02D90D30 = lfs f11, _averageFPS@l(r10) -0x02D90D88 = lis r10, _averageFPS@ha -0x02D90D8C = lfs f11, _averageFPS@l(r10) -0x02D5F760 = bla _arrowTimeDrain -0x037DC35C = lis r12, _speedDiv@ha #Audio fix -0x037DC360 = lfs f13, _speedDiv@l(r12) - - -#break all forms of frame limiting -0x031FAAFC = bla _fenceNeg1 ;Best fence (make sure GPU is never more than 1 frame ahead) -;0x031FAAE8 = li r0, 1 ;Better fence (make sure GPU is never more than 1 second? ahead) -;0x031FAB00 = nop ; skip fence (no waiting on GPU) -0x031FACD0 = nop ; disable vsync -0x031FACF4 = nop ; disable vsync loop - - - -[BotwFPSv176V192] -moduleMatches = 0xFD091F9F, 0xD472D8A5 - -# rodata constants -_float.5 = 0x100005E0 -_float1 = 0x10000670 -_float30 = 0x101E78F4 -_float32 = 0x1025D1A8 -_convSub = 0x10000BB0 -_arrowsDiv = 0x1001CCAC -_arrowsDer = 0x1001CB18 - - -#TestCave -codeCaveSize = 0x12C - -_fpsCalc = 0x00000010 -0x00000000 = .float 2 ; Don't edit me! -_lowlimit = 0x00000000 -0x00000004 = .float 62156250 -_busSpeed = 0x00000004 -_averageFPS = 0x00000008 -_speedDiv = 0x0000000C - - # HOW TO CHANGE AMOUNT OF FRAMES TO AVERAGE -0x00000128 = .float 32 #This float can be anything. To change the amount of frames averaged change this float... -_bufferSize = 0x00000128 #...and change the "0x84" on line 74 to this number times 4 plus 4 converted to hex. - #Example using 8 frames. 8 x 4 = 34. 34 + 4 = 38. In hex 0x26 - #So line 74 would change from "cmpwi r12, 0x0C" to "cmpwi r12, 0x26" - - -0x00000010 = stw r0, 0x78(r30) #orig instruction we are replacing ;ticks between frame are currently in r12. -0x00000014 = xoris r12, r12, 0x8000 #flip the sign bit of int ticks for floating point conversion -0x00000018 = stw r12, 0xD4(r30) #store sign flipped ticks in memory as lower half of double -0x0000001C = lis r12, 0x4330 #create upper half of ticks double -0x00000020 = stw r12, 0xD0(r30) #store it in upper half of memory -0x00000024 = lfd f10, 0xD0(r30) #Load full double ticks into f10 -0x00000028 = lis r12, _convSub@ha #load number to subtract from tick double... -0x0000002C = lfd f12, _convSub@l(r12) #...to create tick float into f12 -0x00000030 = fsub f10, f10, f12 #Do the subtraction -0x00000034 = frsp f10, f10 #round to single precision and tick float is in f10 -0x00000038 = lis r12, _float1@ha #Load float of 1... -0x0000003C = lfs f12, _float1@l(r12) #...into f12 -0x00000040 = fdivs f10, f12, f10 #divide 1 by ticks -0x00000044 = lis r12, _busSpeed@ha #load wii u bus speed... -0x00000048 = lfs f12, _busSpeed@l(r12) #...into f12 -0x0000004C = fmuls f10, f12, f10 #multiply bus speed to have current fps in f10. (1/ticks)*bus speed - -0x00000050 = mr r3, r30 #Make a copy of r30 so we can screw around with it -0x00000054 = addi r3, r3, 0xE0 #Add offset to available memory space -0x00000058 = stw r3, 0xD8(r30) #Save our virgin memory address so we can retrieve it later -0x0000005C = lwz r12, 0xDC(r30) #load counter into r12 -0x00000060 = add r3, r3, r12 #add our counter to the offset for our memory location -0x00000064 = stfsu f10, 0x04(r3) #store current fps to memory location +4 and update efective address into r3 -0x00000068 = lfs f7, 0xE0(r30) #Load fpsSum into f7 -0x0000006C = fadds f10, f10, f7 #Add currentFPS to fpsSum -0x00000070 = addi r12, r12, 0x04 #Incriment counter by 4 -0x00000074 = cmpwi r12, 0x84 #Compare counter with 0x84(32 address from base memory location) -0x00000078 = bne .+0x0C #If we write our last current fps then -0x0000007C = lis r12, 0 #Zero our counter -0x00000080 = lwz r3, 0xD8(r30) #and reload our virgin memory offset -0x00000084 = stw r12, 0xDC(r30) #Store counter r12 to memory location -0x00000088 = lfs f7, 0x04(r3) #load oldest fps into f7 -0x0000008C = fsubs f10, f10, f7 #Subtract oldest fps from fpsSum -0x00000090 = stfs f10, 0xE0(r30) #store fpsSum back into it's memory address. -0x00000094 = lis r12, _float32@ha #load 32 as a float ... -0x00000098 = lfs f7, _float32@l(r12) #...into f7 -0x0000009C = fdivs f10, f10, f7 #divide fps sum by 32, the number of saved fps values, to get average fps over 32 frames -0x000000A0 = lis r12, _averageFPS@ha #Store averaged fps... -0x000000A4 = stfs f10, _averageFPS@l(r12) #... into _averageFPS variable. - -0x000000A8 = lis r12, _float30@ha #Setting up speed diviser. 30/current fps = game speed. ex 30/60 = .5 game speed -0x000000AC = lfs f12, _float30@l(r12) #load float 30 into f12 -0x000000B0 = fdivs f7, f12, f10 #do the division f10 is our current fps(now averaged) -0x000000B4 = lis r12, _lowlimit@ha #set up a low limit to not set game speed below. here: 10/30 = 3 -0x000000B8 = lfs f12, _lowlimit@l(r12) #Set 3 as the low limit into f12 -0x000000BC = lis r12, _speedDiv@ha #prepare to store game speed into _speedDiv but wait. -0x000000C0 = fcmpu cr0, f7, f12 #compare Compare lowlimit with current working game speed -0x000000C4 = bge .+0x08 #If game speed is not being set below 10 fps... -0x000000C8 = b .+0x08 #then skip the next line -0x000000CC = fmr f7, f12 #else overrite working current speed with low limit as new working current speed -0x000000D0 = stfs f7, _speedDiv@l(r12) #store working current speed into _speedDiv - -0x000000D4 = lis r12, _float30@ha #An attempt to port arrow fix to fps++ -0x000000D8 = lfs f12, _float30@l(r12) #load float30 into f12 -0x000000DC = fmuls f10, f7, f12 #arrowsDiv = 30 * speedDiv -0x000000E0 = lis r12, _arrowsDiv@ha -0x000000E4 = stfs f10, _arrowsDiv@l(r12) #store the results -0x000000E8 = lis r12, _float.5@ha #load float of .5 into f12 -0x000000EC = lfs f12, _float.5@l(r12) -0x000000F0 = fdivs f10, f12, f7 #arrowsDer = .5 / speedDiv -0x000000F4 = lis r12, _arrowsDer@ha -0x000000F8 = stfs f10, _arrowsDer@l(r12) #store the results -0x000000FC = blr #return - -_fenceNeg1 = 0x00000100 -0x00000100 = add r6, r12, r0 #orig instruction we are replacing -0x00000104 = cmpwi r6, 500 #check if less than 500 (full sync on those first frames to prevent milk water) -0x00000108 = blt .+0x08 #skip subtract if less than -0x0000010C = subi r6, r6, 1 #do the subtract -0x00000110 = blr #return - - -_arrowTimeDrain = 0x00000114 -0x00000114 = lfs f1, 0xFC(r11) -0x00000118 = lis r12, _speedDiv@ha -0x0000011C = lfs f0, _speedDiv@l(r12) -0x00000120 = fmuls f1, f1, f0 -0x00000124 = blr - -#codeChanges -0x031F9E80 = bla _fpsCalc -0x03792620 = nop -0x0379262C = nop -0x03792670 = lis r29, _speedDiv@ha -0x03792678 = lfs f0, _speedDiv@l(r29) -0x03792684 = nop -0x03414EF8 = lis r12, _speedDiv@ha -0x03414F00 = lfs f0, _speedDiv@l(r12) -0x03414F08 = nop -0x02D90790 = lis r10, _averageFPS@ha -0x02D90794 = lfs f11, _averageFPS@l(r10) -0x02D907EC = lis r10, _averageFPS@ha -0x02D907F0 = lfs f11, _averageFPS@l(r10) -0x02D5F200 = bla _arrowTimeDrain -0x037DB654 = lis r12, _speedDiv@ha -0x037DB658 = lfs f13, _speedDiv@l(r12) - -# Break all forms of frame limiting -0x031FA000 = bla _fenceNeg1 -;0x031F9FEC = li r0, 1 -;0x031FA004 = nop -0x031FA1D4 = nop -0x031FA1F8 = nop diff --git a/Mods/BreathOfTheWild_FPS++/rules.txt b/Mods/BreathOfTheWild_FPS++/vsync Control/rules.txt similarity index 67% rename from Mods/BreathOfTheWild_FPS++/rules.txt rename to Mods/BreathOfTheWild_FPS++/vsync Control/rules.txt index 269fcd0c..8934de37 100644 --- a/Mods/BreathOfTheWild_FPS++/rules.txt +++ b/Mods/BreathOfTheWild_FPS++/vsync Control/rules.txt @@ -1,8 +1,8 @@ [Definition] titleIds = 00050000101C9300,00050000101C9400,00050000101C9500 -name = Dynamic (FPS++) -path = "The Legend of Zelda: Breath of the Wild/Mods/Dynamic (FPS++)" -description = Important: Don't enable Static FPS while having FPS++ also enabled! This pack won't work without Cemuhook, make sure to install that! This pack only works when you've properly updated your game (we always recommend the latest updates). Keep in mind that going above 30fps will bring game bugs, so you might want to use the "30FPS" preset. +name = Vsync Control +path = "The Legend of Zelda: Breath of the Wild/Mods/FPS++/Vsync Control" +description = Select the fps you want to be your limit with FPS++ version = 3 [Preset] @@ -54,4 +54,4 @@ name = 165FPS (ideal for 165Hz displays) $targetFPS:int = 165 [Control] -vsyncFrequency = $targetFPS +vsyncFrequency = $targetFPS \ No newline at end of file