mirror of
https://github.com/Ultra-NX/UltraNX.git
synced 2025-12-13 18:33:55 +00:00
213 lines
5.5 KiB
YAML
213 lines
5.5 KiB
YAML
# Pokémon Legends: Z-A 1.0.1
|
|
# BID: 7222E13ECF6ADB32
|
|
|
|
DECLARATIONS:
|
|
-
|
|
type: variable
|
|
name: frametick
|
|
value_type: uint64
|
|
default_value: 0
|
|
-
|
|
type: const
|
|
name: max_delta
|
|
value: 66666667
|
|
-
|
|
type: variable
|
|
name: min_delta
|
|
value_type: uint64
|
|
default_value: 33333334
|
|
evaluate: "(FRAMETIME_TARGET * 1000000) + 1"
|
|
-
|
|
type: variable
|
|
name: fps_target
|
|
value_type: uint32
|
|
default_value: 30
|
|
evaluate: FPS_TARGET
|
|
-
|
|
type: const
|
|
name: 60FPSInNanoseconds
|
|
value: 16666667
|
|
-
|
|
type: const
|
|
name: 30FPSInNanoseconds
|
|
value: 33333334
|
|
-
|
|
type: variable
|
|
name: frametime
|
|
value_type: uint64
|
|
default_value: 0
|
|
-
|
|
type: variable
|
|
name: roll_flag
|
|
value_type: uint32
|
|
default_value: 0
|
|
-
|
|
type: variable
|
|
name: interval_pointer
|
|
value_type: uint64
|
|
default_value: 0
|
|
-
|
|
type: code
|
|
name: dynamicFPS
|
|
instructions: [
|
|
[stp, x29, x30, [sp, -16], "!"],
|
|
[mov, x29, sp],
|
|
[blr, x8],
|
|
[mrs, x11, cntpct_el0],
|
|
[adrp, x10, $frametick],
|
|
[ldr, x12, [x10, $frametick]],
|
|
[str, x11, [x10, $frametick]],
|
|
[mov, x10, x12],
|
|
[cbz, x10, :goto1],
|
|
[sub, x10, x11, x10],
|
|
[mov, x11, 625],
|
|
[mul, x10, x10, x11],
|
|
[mov, x11, 12],
|
|
[udiv, x10, x10, x11],
|
|
[mov, x12, $max_delta],
|
|
[movk, x12, $max_delta, 16],
|
|
[cmp, x10, x12],
|
|
[csel, x10, x10, x12, lt],
|
|
[adrp, x11, $min_delta],
|
|
[ldr, x11, [x11, $min_delta]],
|
|
[cmp, x10, x11],
|
|
[csel, x2, x10, x11, gt],
|
|
[adrp, x10, $fps_target],
|
|
[ldr, w10, [x10, $fps_target]],
|
|
[cmp, w10, 60],
|
|
[csel, x2, x11, x2, eq],
|
|
[adrp, x10, $frametime],
|
|
[str, x2, [x10, $frametime]],
|
|
[mov, x12, $30FPSInNanoseconds],
|
|
[movk, x12, $30FPSInNanoseconds, 16],
|
|
[mov, w13, 0x100],
|
|
[cmp, x2, x12],
|
|
[b.lt, :goto1],
|
|
[mov, w13, 0x101],
|
|
:goto1, [adrp, x10, $interval_pointer],
|
|
[ldr, x10, [x10, $interval_pointer]],
|
|
[strh, w13, [x10]],
|
|
[adrp, x10, $roll_flag],
|
|
[ldr, w11, [x10, $roll_flag]],
|
|
[cmp, w11, 0],
|
|
[b.eq, :goto2],
|
|
[sub, w11, w11, 1],
|
|
[str, w11, [x10, $roll_flag]],
|
|
:goto2, [ldp, x29, x30, [sp], 16],
|
|
[ret]
|
|
]
|
|
-
|
|
type: code
|
|
name: readDynamicFPS
|
|
instructions: [
|
|
[adrp, x10, $frametime],
|
|
[ldr, x11, [x10, $frametime]],
|
|
[cmp, x11, 0],
|
|
[csel, x2, x2, x11, eq],
|
|
[adrp, x10, $roll_flag],
|
|
[ldr, w10, [x10, $roll_flag]],
|
|
[cmp, w10, 0],
|
|
[adrp, x10, $min_delta],
|
|
[ldr, x10, [x10, $min_delta]],
|
|
[csel, x2, x2, x10, eq],
|
|
[adrp, x10, 0x5F0C000],
|
|
[add, x10, x10, 0x600], # Offset where is written flag when ladder is in use
|
|
[ldrb, w10, [x10]],
|
|
[mov, x12, $60FPSInNanoseconds],
|
|
[movk, x12, $60FPSInNanoseconds, 16], # Climbing animation expects from us animation to be multiplication of 1/60s, otherwise climbing speed is uneven and eventually we fall
|
|
[mov, x13, $30FPSInNanoseconds],
|
|
[movk, x13, $30FPSInNanoseconds, 16],
|
|
[cmp, x11, x13],
|
|
[csel, x11, x12, x13, lt],
|
|
[cmp, w10, 0],
|
|
[csel, x2, x2, x11, eq],
|
|
[br, x3]
|
|
]
|
|
-
|
|
type: code
|
|
name: setTo60FPSMode
|
|
instructions: [
|
|
[str, x0, [x26, 0x40]],
|
|
[add, x0, x0, 0x20],
|
|
[adrp, x8, $interval_pointer],
|
|
[str, x0, [x8, $interval_pointer]],
|
|
[mov, w8, 0x101],
|
|
[strh, w8, [x0]],
|
|
[sub, x0, x0, 0x20],
|
|
[ret]
|
|
]
|
|
-
|
|
type: const
|
|
name: rollFixTiming
|
|
value: 20000001
|
|
-
|
|
type: code
|
|
name: rollFix
|
|
instructions: [
|
|
[ldr, x8, [x0, 0x120]],
|
|
[tbnz, x8, 1, +8], # Bit 1 = ladder/rolling
|
|
[b, :goto1],
|
|
[adrp, x22, $frametime],
|
|
[ldr, x22, [x22, $frametime]],
|
|
[mov, x21, $rollFixTiming],
|
|
[movk, x21, $rollFixTiming, 16],
|
|
[cmp, x22, x21],
|
|
[b.gt, :goto1], # If our FPS target is not above 50, don't do anything
|
|
[mov, w21, 3],
|
|
[adrp, x22, $fps_target],
|
|
[ldr, w22, [x22, $fps_target]],
|
|
[udiv, w22, w22, w21], # Divide FPS target by 3 to get amount of frames necessary for rolling animation to not stuck our character
|
|
[adrp, x19, $roll_flag],
|
|
[str, w22, [x19, $roll_flag]],
|
|
:goto1, [ret]
|
|
]
|
|
MASTER_WRITE:
|
|
# Roll Fix, thanks to Fl4sh9174 for address
|
|
-
|
|
type: asm_a64
|
|
main_offset: 0x2962A74
|
|
instructions: [
|
|
[bl, _rollFix()]
|
|
]
|
|
# Restore original 30 FPS lock
|
|
-
|
|
type: asm_a64
|
|
main_offset: 0x175E864
|
|
instructions: [
|
|
[mov, w1, 2]
|
|
]
|
|
# Dynamic Resolution
|
|
## REF: 21 D8 61 5E 21 18 68 1E 00 18 61 1E, replace ADRP + ADD + LDR above it
|
|
-
|
|
type: asm_a64
|
|
main_offset: 0xD5AB0
|
|
instructions: [
|
|
[adrp, x9, $min_delta],
|
|
[ldr, d1, [x9, $min_delta]],
|
|
[nop]
|
|
]
|
|
# Calculate frame time by replacing call to nvnQueuePresentTexture
|
|
-
|
|
type: asm_a64
|
|
main_offset: 0x175F154
|
|
instructions: [
|
|
[bl, _dynamicFPS()]
|
|
]
|
|
# Replace reading hardcoded values
|
|
## REF: 02 D9 62 F8 08 00 40 F9 03 09 40 F9 60 00 1F D6, last REF. Check two other results if anything will go wrong somewhere
|
|
-
|
|
type: asm_a64
|
|
main_offset: 0x2891B08
|
|
instructions: [
|
|
[b, _readDynamicFPS()]
|
|
]
|
|
# Force game to start in 60 FPS mode for better game thread synchronization (writing 0 to 0x20) + enable constantly updating speed (writing 1 to 0x21)
|
|
## REF: 40 23 00 F9 08 04 40 F9
|
|
-
|
|
type: asm_a64
|
|
main_offset: 0x19DD334
|
|
instructions: [
|
|
[bl, _setTo60FPSMode()]
|
|
]
|
|
|