# The Legend of Zelda: Tears of The Kingdom 1.4.2 # BID: 5CB42B1CF25469FB Addons: - atmosphere/contents/0100F2C0115B6000/exefs/main.npdm DECLARATIONS: - type: variable name: fps_target value_type: float default_value: 30 evaluate: FPS_TARGET - type: variable name: cutscene_flag value_type: uint8 default_value: 0 - type: variable name: dr_factor value_type: float default_value: 0.001 evaluate: 0.001 * (FPS_TARGET / 30) - type: const name: nanoseconds_in_s value: 1000000000 - type: code name: cutscene_1 instructions: [ [stp, x29, x30, [sp, -16], "!"], [mov, x29, sp], [mov, w2, 1], [adrp, x3, $cutscene_flag], [strb, w2, [x3, $cutscene_flag]], [bl, 0x5f888], #Jump to original BL [ldp, x29, x30, [sp], 16], [ret] ] - type: code name: cutscene_2 instructions: [ [adrp, x3, $cutscene_flag], [strb, w0, [x3, $cutscene_flag]], [b, _setUserInactivityDetectionTimeExtended()], ] - type: code name: blackBackgroundFix instructions: [ [fcmp, s1, 0.0], [b.ne, :goto1], [ldurh, w8, [x25, -6]], [cmp, w8, 5], [b.ne, :goto1], [ldurh, w8, [x25, -8]], [cmp, w8, 5], [b.ne, :goto1], [fmov, s8, 1.0], :goto1, [fmadd, s9, s0, s8, s1], [ret] ] MASTER_WRITE: # Remove double buffer ## REF: A0 2A 40 F9 61 A2 40 39 - type: asm_a64 main_offset: 0xBBF258 instructions: [ [mov, w1, 1] ] # Code Injected, $x1 + 0xD8 - last frametime without compensation long ticks, $x0 + 0x50 - fps target used for calculation int, # $x0 + 0x24 - our fps target used for calculation but as float, originally is stored there 30 FPS int that seems to do nothing outside of this function ## REF: nvnWindowSetPresentInterval - type: asm_a64 main_offset: 0x2D4E68 instructions: [ [adrp, x2, $fps_target], [ldr, s9, [x2, $fps_target]], [mov, x20, x0], [mov, x21, x1], [ldr, x0, [x1, 0xd8]], [bl, _convertTickToTimeSpan()], [mov, w2, $nanoseconds_in_s], [movk, w2, $nanoseconds_in_s, 16], [scvtf, s2, w2], [scvtf, s1, x0], [fdiv, s1, s2, s1], [fcmp, s1, s9], [fcsel, s1, s9, s1, gt], [fmov, s9, 15.0], [fcmp, s1, s9], [fcsel, s1, s9, s1, lt], [fcvtzu, w2, s1], [str, w2, [x20, 0x50]], [str, s1, [x20, 0x24]], [b, 0x2d4f60] ] ## Use our fps target ## REF: 60 52 42 BD 08 4E A8 52 ### Replace LDR S0, [X22,#0x250] - type: asm_a64 main_offset: 0x2D4730 instructions: [ [ldr, s0, [x19, 0x224]] ] ### Replace SCVTF S0, S0 - type: asm_a64 main_offset: 0x2D4748 instructions: [ [nop] ] ## REF: 14 01 40 F9 08 4E A8 52 ### Replace LDR S0, [X22,#0x250] - type: asm_a64 main_offset: 0x37EA5C instructions: [ [ldr, s0, [x22, 0x224]] ] ### Replace SCVTF S0, S0 - type: asm_a64 main_offset: 0x37EA68 instructions: [ [nop] ] # When prerendered cutscene is active write flag to cutscene_flag ## REF: 68 52 40 79 08 01 19 32 68 52 00 79 ## BL to Code Cave 1 - type: asm_a64 main_offset: 0x2B238B4 instructions: [ [bl, _cutscene_1()] ] ## REF: 68 52 40 79 08 79 18 12 68 52 00 79, inside call ## B to Code Cave 2 - type: asm_a64 main_offset: 0x2B210CC instructions: [ [b, _cutscene_2()] ] # Adjust DR timing to factor from dr_factor # REF: 88 02 15 CB 00 01 23 9E - type: asm_a64 main_offset: 0xEED54 instructions: [ [adrp, x8, $dr_factor], [ldr, s1, [x8, $dr_factor]] ] # Fix black background for D-pad menu ## REF: 21 03 5E BC - type: asm_a64 main_offset: 0x387390 instructions: [ [bl, _blackBackgroundFix()], # Jump to Code Cave 3 [fcmp, s0, 0.0] ] ALL_FPS: - type: compare compare_address: [VARIABLE, cutscene_flag] compare_value: 1 compare_type: "==" value_type: refresh_rate value: 30