Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TEST] Add VI Overclock #11486

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

Sam-Belliveau
Copy link
Contributor

image

image

AUDIO SPEED IS NOT AFFECTED BY VI OVERCLOCK SETTINGS

This is a much more reliable way of inducing a frame skip, and likely will induce much fewer bugs than VI Skip. It's main advantage is being able to increase the framerate, however this will 100% affect game speed when physics is tied to framerate.

I'm going to mark this as draft because it is definitely not usable at the moment.

@JMC47
Copy link
Contributor

JMC47 commented Jan 24, 2023

I'm going to have to be skeptical about this. Most games with frameskip and whatnot won't really go above 60 FPS even with hacks in the past.

@mbc07
Copy link
Member

mbc07 commented Jan 25, 2023

Regarding the UI, current design of this PR makes the Advanced tab even taller than it already is and further exacerbates the problem PR #8785 tries to address. With this PR we'll have enough UI controls related to overclocking to justify a new, dedicated tab, for them...

@Sam-Belliveau Sam-Belliveau changed the title Add VI Overclock [TEST] Add VI Overclock Jan 25, 2023
@SuperSamus
Copy link
Contributor

SuperSamus commented May 1, 2024

If someone wants to toy around with this today, I rebased it here.
(Note that I didn't bother solving Android-related merge conflicts)

@Calinou
Copy link

Calinou commented May 4, 2024

If someone wants to toy around with this today, I rebased it here. (Note that I didn't bother solving Android-related merge conflicts)

I gave this branch a try and it works well to push Star Fox Adventures to 120 FPS (although it ends up triggering the same bug as RenaKunisaki/StarFoxAdventures#9). At least there are no more audio issues, unlike the previous approach where I increased emulation speed and decreased internal game speed.

@SuperSamus
Copy link
Contributor

SuperSamus commented May 5, 2024

I briefly tested it on Skylanders: Spyro's Adventure with the 60 FPS patch1.

The game runs at the same gameplay speed from 33% to 200% (it slows-down/speeds-up below/above that, it seems intentional2), though running it at 120 FPS is insanely demanding (the game is pretty demanding as is...).

Here's some footage at 200% VI overclock (but 50% game speed, because my computer is too weak)3:

SSA-120FPS.mp4

Cutscenes are slightly broken: the characters walk more than they should (though it's only visual). This also happens on the Wii U version too, btw.

Footnotes

  1. The name is a misnomer, the game already runs at 60 FPS normally, but renders everything except the UI at 30 FPS. The patch makes the game render at the same speed it's running, so it's an efficiency gain.

  2. Why would the devs intentionally make sure that the game speeds up above 120 FPS on a Wii game is beyond me. Even the PC version of the game is capped at 60 FPS (do note that the non-Wii/WiiU versions run on the Lux Engine instead of Vicarious Visions Alchemy). Anyway, I couldn't find the part of the code that does this...

  3. If you have déjà vu, it's because I already posted it on Discord.

@SuperSamus
Copy link
Contributor

SuperSamus commented Jun 11, 2024

So, experimented a little more with Skylanders: Spyro's Adventure, to go even further beyond.

Click if you are curious on the technical details

Maintaining high framerates in this game is wack: sometimes it intentionally decides to not run at the framerate I want. The FPS could be close to the VPS, I raise the emulated CPU clock a little, and suddenly the FPS goes down to exactly half the VPS (the specific percentages depend on the game's situation). What is going on?

With the branch watch tool, I found the function called every vblank that makes the physics step and renders: 0x80171b9c.
This function first checks whether 0x9026f6fc is not 0: if true, it proceeds and reduces it by 1, otherwise it does nothing.
So, this variable has only one other setter: the function 0x80171a90, which simply increases it by 1, and does other mysterious stuff.
One weird thing is that, depending on the level of the game (I think?), 0x80171a90 is called one time every frame, or two times every two frames (the latter makes the problem worse, though it also exists in the former).
So, when the game is running at half the VPS, it's simply because 0x80171a90 isn't called as much as it should be. Who calls 0x80171a90?
Bad news: it seems to be something very low level, as it's called through a variable pointer (that also calls a lot of other stuff), and it's surrounded by scary OS syscalls.
And it's not easy to debug either: when pausing the debugger, the behavior is different from only logging the breakpoints.

One thing I could do is remove the check from 0x80171b9c. While it does make the game do a physics step and render when it should, it also makes it do it when it shouldn't.
It's a small side effect though, since it's only visual (you'll see older frames after newer ones), and it can be prevented by overclocking the emulated CPU so that it never/rarely happens. The game looks perfectly stable otherwise, and performs as it should (note that the performance metrics will always say that the FPS are equal to the VPS, which is "true" only if the emulated CPU clock is high enough!).

Later, I noticed later that the lower/upper bound for delta times (see my previous post) weren't "fixed", but depended on another address, 0x8084f230, which is fixed at 1/60 (even in PAL50, I wonder if that's intentional...).
It looks like a "target framerate" address? It's also read in one other place: 0x8000b5b0.
Very curiously, the latter uses it to affect the behavior I described above: if I lower the value, the VI Overclock will have to be higher for the game to start artificially limiting the framerate.
All of this, without the visual problems if the emulated CPU can't keep up.
If the emulated CPU is running the game at full speed, the emulation performance seems to be a lot better if the value matches the VI Overclock. (The "best" performance is the same of the other code.)
You can't use ridiculously low values, or even 0. If you try, the emulator will crash after loading screens (but not if the code is applied after?).

If you want to play this game at higher framerates:

  • Preferably, use the "60 FPS" patch, for efficiency (without it, the game runs two physics steps per frame).
  • Set VI Overclock to the desired target.
  • Preferably, don't use VBI Skip (the game will freeze if too many VBIs are skipped, but it can be unfreezed by lowering the emulated CPU clock).

Use this patch:

$Change target framerate
0484F230 3C088889 # 1/120, replace with 1/VPS set in VI Overclock
*If the value doesn't match 1/VPS, emulation performance will be worse, and the game may refuse to run at the framerate you want. To calculate hex, use https://www.h-schmidt.net/FloatConverter/IEEE754.html

Then, optionally:

$Delta time bounds fix
0409FE44 3C003D4C # High bits of 1/20
0409FE48 6000CCCD # Low bits of 1/20
0409FE4C 9001FFFC # Store to sp - 4
0409FE50 C001FFFC # Load to f0
*Removes lower limit (by writing over it), and forces upper limit to 1/20
Alternative stuff (not recommended) This replaces the target framerate patch, and *requires* the delta time bounds fix: ``` $Force physics/render step 04171BB8 60000000 # Remove check ``` If the emulated CPU clock isn't high enough, you will see older frames. FPS will (falsely) always match VPS.

With this, if you overclock the emulated CPU more than needed, the emulation performance will be worse.

$Change target framerate (dynamic)
2284F230 00000000 # Otherwise crashes
82200000 8084f234 # Load the delta time...
84200000 8084F230 # ...into the target time

@SuperSamus
Copy link
Contributor

SuperSamus commented Jun 11, 2024

Here are the codes for Skylanders: Giants.
Same rules of the other one.
The 60 FPS patch is here.
Use this:

$Change target framerate
22701EEC 0040E8C7 # This address is used for something else during initialization
04701EEC 3C088889 # 1/120, replace with 1/VPS set in VI Overclock
E0000000 80008000
*If the value doesn't match 1/VPS, emulation performance will be worse, and the game may refuse to run at the framerate you want. To calculate hex, use https://www.h-schmidt.net/FloatConverter/IEEE754.html

Then, optionally:

$Delta time bounds fix
040AD180 3C003D4C # High bits of 1/20
040AD184 6000CCCD # Low bits of 1/20
040AD188 9001FFFC # Store to sp - 4
040AD18C C001FFFC # Load to f0
*Removes lower limit (by writing over it), and forces upper limit to 1/20

The speed of the title screen's background is tied to the FPS, for some reason.

Alternative stuff (not recommended) ``` $Force physics/render step 0417E8C8 60000000 # Remove check *If emulated CPU clock isn't high enough, you will see older frames. FPS will (falsely) always match VPS. ```

@SuperSamus
Copy link
Contributor

SuperSamus commented Jun 30, 2024

Skylanders: Swap Force is also able to go to higher framerates, and it doesn't exhibit the weird behavior of the other two games.
There's a bug that softlocks you during sequences where there is a long fall.1 This issue also happens in all other versions of the game.
I found the cause thanks to branch watch, and patched it:2

$Infinite fall fix
C2657438 00000003 # On top of `lfs f0, 0x005C (r29)`
3C004416 9001FFFC # lis r0, 0x4416 (20*30FPS); stw r0, -4(sp)
C001FFFC EC0007B2 # lfs f0, -4(sp); fmuls f0, f0, f30 # f30 is deltaTime
60000000 00000000

(A port of the fix for Cemu is coming soon™, EDIT: cemu-project/cemu_graphic_packs#639)

Footnotes

  1. After 3 seconds of falling, the game teleports you back to where the fall started, softlocking you in a loop.

  2. The reason is because of a failsafe meant in case your character is stuck falling between geometry. The game determines whether you are stuck with a simple method: it calculates the squared distance of your character from the position of the previous frame, then checks whether it's lower than 20². If that's true for 3 seconds, then it teleports you. But if the framerate is higher, your distance is going to be lower than normal, and the game will consider you stuck even when falling at top speed. Ironic... The fix simply consists in changing the value from 20 to 20×30FPS×deltaTime.

@SuperSamus
Copy link
Contributor

SuperSamus commented Jul 25, 2024

Gave it a try on Need For Speed: Nitro (R7XP69).
(Watch at half speed if you have a 60 Hz monitor, obviously.)

NFSNitro-144.mp4

The game was sped up, but I made a code to adjust it:

$Higher FPS
C22FF958 00000003 # Main game speed
3C00XXXX 6000YYYY # Hardcode XXXXYYYY in r0
9001FFFC C021FFFC # Store it in -4(sp), then load it in f1
60000000 00000000
C22040D8 00000003 # Camera at end of race
3C00XXXX 6000YYYY
9001FFFC C021FFFC
60000000 00000000

Replace XXXX and YYYY with the upper and lower bytes (respectively) of 1/VPS.

Examples
$120 FPS
C22FF958 00000003
3C003C08 60008889
9001FFFC C021FFFC
60000000 00000000
C22040D8 00000003
3C003C08 60008889
9001FFFC C021FFFC
60000000 00000000
$144 FPS
C22FF958 00000003
3C003BE3 60008E39
9001FFFC C021FFFC
60000000 00000000
C22040D8 00000003
3C003BE3 60008E39
9001FFFC C021FFFC
60000000 00000000

Multiplayer works too, just use this code to prevent the game from capping to 30 FPS.

Caveats:

  • The menus are sped up.
  • The Beetle (a crap early-game car you are supposed to throw away ASAP), when doing a perfect start, may stall for no apparent reason (it's very inconsistent), giving you a disadvantage at the start of the race. At higher FPS, this happens more frequently, and the car stalls even more when it happens. I couldn't reproduce this on any other car I tested.
Older (simpler) code before EDIT
$Higher FPS
047763B4 XXXXYYYY # Replaces 3C888889

While this address is used for the game speed, it's also read in other places as well.
They don't like when the value is lower than (something between) 1/126-1/130: the game will freeze when loading the race (if the value is set during the race, then the game will freeze a few seconds after).
The more complicated code above only replaces the two relevant reads, thus there's no freeze at higher framerates.

(On an unrelated note: Gecko codes aren't really ideal for these "choose your own value". Cemu's graphics packs are so much nicer...)

QFont vi_bf = font();
vi_bf.setBold(Config::GetActiveLayerForConfig(Config::MAIN_VI_OVERCLOCK_ENABLE) !=
Config::LayerType::Base);
m_vi_clock_override_checkbox->setFont(bf);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bf was probably meant to be vi_bf here.

@SuperSamus SuperSamus mentioned this pull request Sep 1, 2024
@SuperSamus
Copy link
Contributor

Super Mario Sunshine at 120 FPS.

SMS-120.mp4

Unfortunately, it's not really usable.
At 60 FPS (without VBI overclock), sometimes the music doesn't play, or gets stuck on the first note.
At 120 FPS, "sometimes" becomes "more often than not".

This is caused by the VBI frequency specifically. Lowering it before the music plays "solves" the problem (which is how I got the music for the video, it refused to play on the level otherwise). Apparently, this is also hard to fix. Too bad.

The code is a modified 60 FPS code (PAL) from the wiki. With the way this cheat works, 120 FPS is the maximum.

0440DD10 40000000
042F4CB4 60000000
0440BE54 3D23D70A
C20066EC 00000003 # I don't know what this does, so I'm not even sure if I should have changed it.
C2C28028 EC2105B2
EC2105B2 FEC00890
60000000 00000000

@SuperSamus
Copy link
Contributor

SuperSamus commented Sep 5, 2024

Tried Metroid Prime 2 (GC, PAL).

MP2-120.mp4
$120 FPS
0441B710 3C088889
Alternatively
$120 FPS
C2007CE4 00000003
3C003C08 60008889
9001FFFC C021FFFC
60000000 00000000

It has issues though. (All of these happen even without VBI Overclock.)

  • Particle effects are slower, and some don't even animate (e.g. the bomb explosion particle), causing them to never despawn.
  • Also, there's a hole in the beginning where a cutscene starts, Samus jumps, fade in, fade out, Samus is at the bottom.
    At 120 FPS, there's no fade out. Have fun playing blind after the cutscene. Hopefully, it's the only cutscene with problems...
  • Menu navigation is slower.

I don't have the skills to fix those.
I guess there's this for reference? https://github.com/vyuuui/prime-120-fps

On the bright side, at 90 FPS, that cutscene works fine, and bomb particles do despawn.

@SuperSamus
Copy link
Contributor

SuperSamus commented Sep 5, 2024

Pikmin (GC NTSC 1.1) satisfies!

Pikmin-120.mp4

By default, the game doesn't speed up when changing the VBI overclock.

However, there are few (not game breaking) things that are wrong:

  • Cutscene speed Fixed (the 60 FPS code on the wiki already does that, I just changed the value)
  • Pikmin give up going to an object too quickly Fixed (by me)
  • Some particle effects are too fast, and generate too quickly Partially fixed, there are still some effects that are too fast, but less of them
  • Camera rotation (L) is too fast.
  • Some 2D animations are... too fancy (for instance, the ship in the area select rotates too much)
  • Some animations (like pikmin throw) play at a reduced framerate (also happens at 30 FPS, it's just more noticeable)

(Keep in mind that these issues also happen with the 60 FPS patch on the wiki, they are just amplified.)

$120 FPS
04059774 38000001
0405AE7C 38800001
043E8A58 3E800000 # Cutscene speed
04107738 4800000C
040AFDE8 280000F0 # Adjust Pikmin "give up going to object" timer
043E5E30 42F00000 # Fix particle effects' emission rate and speed (at the cost of despawning too fast)
$144 FPS
04059774 38000001
0405AE7C 38800001
043E8A58 3E555555 # Cutscene speed
04107738 4800000C
040AFDE8 28000120 # Adjust Pikmin "give up going to object" timer
043E5E30 43100000 # Fix particle effects' emission rate and speed (at the cost of despawning too fast)

(Also, do note that normally, without cheat codes, some parts of the game (like the main menu) run at 60 FPS, while the main game runs at 30 FPS.)

@SuperSamus
Copy link
Contributor

Crash Nitro Kart... just works perfectly.
No cheat codes, no nothing.

CNK-120.mp4

@SuperSamus
Copy link
Contributor

SuperSamus commented Oct 6, 2024

Pikmin 2 (GC NTSC) 120 FPS code.
Same issues as the 60 FPS code, but doubled.

$120 FPS
04423540 3BC00001 # `setFramerate`: force full FPS
04520430 42F00000 # 120 FPS
045204A8 42F00000 # Menu 120 FPS
0451D804 3FB00000 # Map translation speed 1
C2312B04 00000002 # Map translation speed 2
3C003F00 9001FFFC
C121FFFC 00000000
0451D7B0 3BF5C28F # Map scale speed
04520628 3F811111 # Cutscene delta time
0452062C 20000000
C2010654 00000002 # Quadruple cutscene sections' "frame duration"
5484103A 909F002C
60000000 00000000
C242ED28 00000002 # Cutscene: objects spawn/despawn timing
3C003E80 9001FFFC
C001FFFC 00000000
C24374DC 00000002 # Cutscene: trigger `startFadeblack` a frame earlier (fixes black screen in Day 1 cutscene)
806D9AEC C0230054
FC020840 00000000

Doing it for framerates that aren't $30*2^i$ is a little impractical, due to what's done with C2010654.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

6 participants