mirror of
				https://github.com/hedge-dev/UnleashedRecomp.git
				synced 2025-10-30 07:11:05 +00:00 
			
		
		
		
	Aspect ratio adjustments. (Part 1) (#90)
* Map CSD structures by full path. * Initial work for unstretching & aligning to edges. * Add extend flag, fix cast lookups. * Add right extend flag. * Fill the flags map with a bunch of casts. * Implement unstretching. * Set more title casts to unscretch. * Add some more flags. * Move CSD patches to its own file. * Replace CSD vertex shaders to get rid of pixel snapping. * Snap to pixel on the CPU. * Current work trying to get 3D screen position casts working correctly. * Fix and properly align font, handle most 3D screen positions. * Add stretch flags for background casts. * Use 4:3 as the base aspect ratio instead of 16:9. * Replicate the game's 4:3 downscaling behavior. * World map now identical to original 4:3. * Replace camera aspect ratio/field of view logic. * Make original 4:3 scaling a separate option, use custom behavior for auto. * Keep UI scale same only above Steam Deck aspect ratio. * Release paths when the YNCP file gets freed. * Add more path flags. * Interpolate to original 4:3 scale. * Scaling animation offset to prevent offscreen casts from showing up in ultrawide. * Queue draw calls without actually executing anything to extract the corner. * Clean unnecessary hooks. * Add result screen modifiers. * Stretch loading primitive 2D. * Scale DoF correctly at different aspect ratios. * Remove stretch option. * Make aspect ratio a global variable. * Ultrawide patch for HUD 3D items. * Fix world map 3D to 2D projection. * Right align world map info box. * Set medal positions. * Respect center option in more places. * Implement the aspect ratio option. * Use viewport dimensions for snapping CSD pixels. * Fix DoF fix not using viewport height. * Implement aspect ratio patches for 2D drop ring emitter. * Implement inspire letterbox. * Add cutscene aspect ratio option. * Shift subtitles by aspect ratio. * Fix crash in earth restoration cutscenes. * Offset scale patches for Tornado Defense. * Scale new record arrow casts. * Expose aspect ratio variables globally. * Properly center the achievements menu. * 4:3 scaling for options menu. * Fix procedural filtering logic in ImGui pixel shader. * Fix button guide offset. * UI scaling for installer. * Remove grid snaps in the installer. * Handle center UI scale option for rings going to HUD. * Remove unnecessary diff. * Revert temporary changes. * Fix typo.
This commit is contained in:
		
							parent
							
								
									95bd71a23e
								
							
						
					
					
						commit
						d56b823b00
					
				
					 22 changed files with 1757 additions and 167 deletions
				
			
		| 
						 | 
					@ -152,6 +152,7 @@ set(SWA_PATCHES_CXX_SOURCES
 | 
				
			||||||
    "patches/ui/CTitleStateIntro_patches.cpp"
 | 
					    "patches/ui/CTitleStateIntro_patches.cpp"
 | 
				
			||||||
    "patches/ui/CTitleStateMenu_patches.cpp"
 | 
					    "patches/ui/CTitleStateMenu_patches.cpp"
 | 
				
			||||||
    "patches/ui/frontend_listener.cpp"
 | 
					    "patches/ui/frontend_listener.cpp"
 | 
				
			||||||
 | 
					    "patches/aspect_ratio_patches.cpp"
 | 
				
			||||||
    "patches/audio_patches.cpp"
 | 
					    "patches/audio_patches.cpp"
 | 
				
			||||||
    "patches/camera_patches.cpp"
 | 
					    "patches/camera_patches.cpp"
 | 
				
			||||||
    "patches/fps_patches.cpp"
 | 
					    "patches/fps_patches.cpp"
 | 
				
			||||||
| 
						 | 
					@ -380,6 +381,8 @@ endfunction()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
compile_vertex_shader(copy_vs)
 | 
					compile_vertex_shader(copy_vs)
 | 
				
			||||||
compile_pixel_shader(csd_filter_ps)
 | 
					compile_pixel_shader(csd_filter_ps)
 | 
				
			||||||
 | 
					compile_vertex_shader(csd_no_tex_vs)
 | 
				
			||||||
 | 
					compile_vertex_shader(csd_vs)
 | 
				
			||||||
compile_pixel_shader(enhanced_motion_blur_ps)
 | 
					compile_pixel_shader(enhanced_motion_blur_ps)
 | 
				
			||||||
compile_pixel_shader(gaussian_blur_3x3)
 | 
					compile_pixel_shader(gaussian_blur_3x3)
 | 
				
			||||||
compile_pixel_shader(gaussian_blur_5x5)
 | 
					compile_pixel_shader(gaussian_blur_5x5)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@ enum class ImGuiCallback : int32_t
 | 
				
			||||||
    SetScale = -4,
 | 
					    SetScale = -4,
 | 
				
			||||||
    SetMarqueeFade = -5,
 | 
					    SetMarqueeFade = -5,
 | 
				
			||||||
    SetOutline = -6,
 | 
					    SetOutline = -6,
 | 
				
			||||||
 | 
					    SetProceduralOrigin = -7,
 | 
				
			||||||
    // -8 is ImDrawCallback_ResetRenderState, don't use!
 | 
					    // -8 is ImDrawCallback_ResetRenderState, don't use!
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,6 +59,11 @@ union ImGuiCallbackData
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        float outline;
 | 
					        float outline;
 | 
				
			||||||
    } setOutline;
 | 
					    } setOutline;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        float proceduralOrigin[2];
 | 
				
			||||||
 | 
					    } setProceduralOrigin;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern ImGuiCallbackData* AddImGuiCallback(ImGuiCallback callback);
 | 
					extern ImGuiCallbackData* AddImGuiCallback(ImGuiCallback callback);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										67
									
								
								UnleashedRecomp/gpu/shader/csd_no_tex_vs.hlsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								UnleashedRecomp/gpu/shader/csd_no_tex_vs.hlsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,67 @@
 | 
				
			||||||
 | 
					#include "../../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __spirv__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define g_ViewportSize vk::RawBufferLoad<float4>(g_PushConstants.VertexShaderConstants + 2880, 0x10)
 | 
				
			||||||
 | 
					#define g_Z vk::RawBufferLoad<float4>(g_PushConstants.VertexShaderConstants + 3936, 0x10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cbuffer VertexShaderConstants : register(b0, space4)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    float4 g_ViewportSize : packoffset(c180);
 | 
				
			||||||
 | 
					    float4 g_Z : packoffset(c246);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cbuffer SharedConstants : register(b2, space4)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DEFINE_SHARED_CONSTANTS();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main(
 | 
				
			||||||
 | 
						[[vk::location(0)]] in float4 iPosition0 : POSITION0,
 | 
				
			||||||
 | 
						[[vk::location(8)]] in float4 iColor0 : COLOR0,
 | 
				
			||||||
 | 
						out float4 oPos : SV_Position,
 | 
				
			||||||
 | 
						out float4 oTexCoord0 : TEXCOORD0,
 | 
				
			||||||
 | 
						out float4 oTexCoord1 : TEXCOORD1,
 | 
				
			||||||
 | 
						out float4 oTexCoord2 : TEXCOORD2,
 | 
				
			||||||
 | 
						out float4 oTexCoord3 : TEXCOORD3,
 | 
				
			||||||
 | 
						out float4 oTexCoord4 : TEXCOORD4,
 | 
				
			||||||
 | 
						out float4 oTexCoord5 : TEXCOORD5,
 | 
				
			||||||
 | 
						out float4 oTexCoord6 : TEXCOORD6,
 | 
				
			||||||
 | 
						out float4 oTexCoord7 : TEXCOORD7,
 | 
				
			||||||
 | 
						out float4 oTexCoord8 : TEXCOORD8,
 | 
				
			||||||
 | 
						out float4 oTexCoord9 : TEXCOORD9,
 | 
				
			||||||
 | 
						out float4 oTexCoord10 : TEXCOORD10,
 | 
				
			||||||
 | 
						out float4 oTexCoord11 : TEXCOORD11,
 | 
				
			||||||
 | 
						out float4 oTexCoord12 : TEXCOORD12,
 | 
				
			||||||
 | 
						out float4 oTexCoord13 : TEXCOORD13,
 | 
				
			||||||
 | 
						out float4 oTexCoord14 : TEXCOORD14,
 | 
				
			||||||
 | 
						out float4 oTexCoord15 : TEXCOORD15,
 | 
				
			||||||
 | 
						out float4 oColor0 : COLOR0,
 | 
				
			||||||
 | 
						out float4 oColor1 : COLOR1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    oPos.xy = (iPosition0.xy - 0.5) * g_ViewportSize.zw * float2(2.0, -2.0) + float2(-1.0, 1.0);
 | 
				
			||||||
 | 
					    oPos.z = g_Z.x;
 | 
				
			||||||
 | 
					    oPos.w = 1.0;
 | 
				
			||||||
 | 
					    oTexCoord0 = iColor0.wxyz;
 | 
				
			||||||
 | 
					    oTexCoord1 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord2 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord3 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord4 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord5 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord6 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord7 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord8 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord9 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord10 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord11 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord12 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord13 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord14 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord15 = 0.0;
 | 
				
			||||||
 | 
					    oColor0 = 0.0;
 | 
				
			||||||
 | 
					    oColor1 = 0.0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										69
									
								
								UnleashedRecomp/gpu/shader/csd_vs.hlsl
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								UnleashedRecomp/gpu/shader/csd_vs.hlsl
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,69 @@
 | 
				
			||||||
 | 
					#include "../../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __spirv__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define g_ViewportSize vk::RawBufferLoad<float4>(g_PushConstants.VertexShaderConstants + 2880, 0x10)
 | 
				
			||||||
 | 
					#define g_Z vk::RawBufferLoad<float4>(g_PushConstants.VertexShaderConstants + 3936, 0x10)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cbuffer VertexShaderConstants : register(b0, space4)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    float4 g_ViewportSize : packoffset(c180);
 | 
				
			||||||
 | 
					    float4 g_Z : packoffset(c246);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cbuffer SharedConstants : register(b2, space4)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						DEFINE_SHARED_CONSTANTS();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void main(
 | 
				
			||||||
 | 
						[[vk::location(0)]] in float4 iPosition0 : POSITION0,
 | 
				
			||||||
 | 
						[[vk::location(8)]] in float4 iColor0 : COLOR0,
 | 
				
			||||||
 | 
						[[vk::location(4)]] in float4 iTexCoord0 : TEXCOORD0,
 | 
				
			||||||
 | 
						out float4 oPos : SV_Position,
 | 
				
			||||||
 | 
						out float4 oTexCoord0 : TEXCOORD0,
 | 
				
			||||||
 | 
						out float4 oTexCoord1 : TEXCOORD1,
 | 
				
			||||||
 | 
						out float4 oTexCoord2 : TEXCOORD2,
 | 
				
			||||||
 | 
						out float4 oTexCoord3 : TEXCOORD3,
 | 
				
			||||||
 | 
						out float4 oTexCoord4 : TEXCOORD4,
 | 
				
			||||||
 | 
						out float4 oTexCoord5 : TEXCOORD5,
 | 
				
			||||||
 | 
						out float4 oTexCoord6 : TEXCOORD6,
 | 
				
			||||||
 | 
						out float4 oTexCoord7 : TEXCOORD7,
 | 
				
			||||||
 | 
						out float4 oTexCoord8 : TEXCOORD8,
 | 
				
			||||||
 | 
						out float4 oTexCoord9 : TEXCOORD9,
 | 
				
			||||||
 | 
						out float4 oTexCoord10 : TEXCOORD10,
 | 
				
			||||||
 | 
						out float4 oTexCoord11 : TEXCOORD11,
 | 
				
			||||||
 | 
						out float4 oTexCoord12 : TEXCOORD12,
 | 
				
			||||||
 | 
						out float4 oTexCoord13 : TEXCOORD13,
 | 
				
			||||||
 | 
						out float4 oTexCoord14 : TEXCOORD14,
 | 
				
			||||||
 | 
						out float4 oTexCoord15 : TEXCOORD15,
 | 
				
			||||||
 | 
						out float4 oColor0 : COLOR0,
 | 
				
			||||||
 | 
						out float4 oColor1 : COLOR1)
 | 
				
			||||||
 | 
					{    
 | 
				
			||||||
 | 
					    oPos.xy = (iPosition0.xy - 0.5) * g_ViewportSize.zw * float2(2.0, -2.0) + float2(-1.0, 1.0);
 | 
				
			||||||
 | 
					    oPos.z = g_Z.x;
 | 
				
			||||||
 | 
					    oPos.w = 1.0;
 | 
				
			||||||
 | 
					    oTexCoord0 = iColor0.wxyz;
 | 
				
			||||||
 | 
					    oTexCoord1.xy = iTexCoord0.xy;
 | 
				
			||||||
 | 
					    oTexCoord1.zw = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord2 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord3 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord4 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord5 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord6 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord7 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord8 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord9 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord10 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord11 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord12 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord13 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord14 = 0.0;
 | 
				
			||||||
 | 
					    oTexCoord15 = 0.0;
 | 
				
			||||||
 | 
					    oColor0 = 0.0;
 | 
				
			||||||
 | 
					    oColor1 = 0.0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -5,12 +5,17 @@
 | 
				
			||||||
#define g_Gamma vk::RawBufferLoad<float3>(g_PushConstants.SharedConstants + 0)
 | 
					#define g_Gamma vk::RawBufferLoad<float3>(g_PushConstants.SharedConstants + 0)
 | 
				
			||||||
#define g_TextureDescriptorIndex vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 12)
 | 
					#define g_TextureDescriptorIndex vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 12)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define g_ViewportOffset vk::RawBufferLoad<int2>(g_PushConstants.SharedConstants + 16)
 | 
				
			||||||
 | 
					#define g_ViewportSize vk::RawBufferLoad<int2>(g_PushConstants.SharedConstants + 24)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cbuffer SharedConstants : register(b2, space4)
 | 
					cbuffer SharedConstants : register(b2, space4)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    float3 g_Gamma : packoffset(c0.x);
 | 
					    float3 g_Gamma;
 | 
				
			||||||
    uint g_TextureDescriptorIndex : packoffset(c0.w);
 | 
					    uint g_TextureDescriptorIndex;
 | 
				
			||||||
 | 
					    int2 g_ViewportOffset;
 | 
				
			||||||
 | 
					    int2 g_ViewportSize;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -18,7 +23,12 @@ cbuffer SharedConstants : register(b2, space4)
 | 
				
			||||||
float4 main(in float4 position : SV_Position) : SV_Target
 | 
					float4 main(in float4 position : SV_Position) : SV_Target
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Texture2D<float4> texture = g_Texture2DDescriptorHeap[g_TextureDescriptorIndex];
 | 
					    Texture2D<float4> texture = g_Texture2DDescriptorHeap[g_TextureDescriptorIndex];
 | 
				
			||||||
    float4 color = texture.Load(int3(position.xy, 0));
 | 
					    
 | 
				
			||||||
 | 
					    int2 movedPosition = int2(position.xy) - g_ViewportOffset;
 | 
				
			||||||
 | 
					    bool boxed = any(movedPosition < 0) || any(movedPosition >= g_ViewportSize);
 | 
				
			||||||
 | 
					    if (boxed) movedPosition = 0;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    float4 color = boxed ? 0.0 : texture.Load(int3(movedPosition, 0));
 | 
				
			||||||
    color.rgb = pow(color.rgb, g_Gamma);
 | 
					    color.rgb = pow(color.rgb, g_Gamma);
 | 
				
			||||||
    return color;
 | 
					    return color;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,11 @@ float4 main(in float4 iPosition : SV_Position, in float4 iTexCoord0 : TEXCOORD0)
 | 
				
			||||||
    Texture2D<float4> texture = g_Texture2DDescriptorHeap[s0_Texture2DDescriptorIndex];
 | 
					    Texture2D<float4> texture = g_Texture2DDescriptorHeap[s0_Texture2DDescriptorIndex];
 | 
				
			||||||
    SamplerState samplerState = g_SamplerDescriptorHeap[s0_SamplerDescriptorIndex];
 | 
					    SamplerState samplerState = g_SamplerDescriptorHeap[s0_SamplerDescriptorIndex];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    float scale = g_ViewportSize.y / 360.0;
 | 
					    float scale;
 | 
				
			||||||
 | 
					    if ((g_ViewportSize.x * g_ViewportSize.w) >= (16.0 / 9.0))
 | 
				
			||||||
 | 
					        scale = g_ViewportSize.y / 360.0;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        scale = g_ViewportSize.x / 640.0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    float2 offsets[3];
 | 
					    float2 offsets[3];
 | 
				
			||||||
    offsets[0] = g_offsets(0).xy * scale;
 | 
					    offsets[0] = g_offsets(0).xy * scale;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ struct PushConstants
 | 
				
			||||||
    float2 InverseDisplaySize;
 | 
					    float2 InverseDisplaySize;
 | 
				
			||||||
    float2 Origin;
 | 
					    float2 Origin;
 | 
				
			||||||
    float2 Scale;
 | 
					    float2 Scale;
 | 
				
			||||||
 | 
					    float2 ProceduralOrigin;
 | 
				
			||||||
    float Outline;
 | 
					    float Outline;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,10 +65,10 @@ float4 PixelAntialiasing(float2 uvTexspace)
 | 
				
			||||||
    uvTexspace = (uvTexspace - seam) / fwidth(uvTexspace) + seam;
 | 
					    uvTexspace = (uvTexspace - seam) / fwidth(uvTexspace) + seam;
 | 
				
			||||||
    uvTexspace = clamp(uvTexspace, seam - 0.5, seam + 0.5);
 | 
					    uvTexspace = clamp(uvTexspace, seam - 0.5, seam + 0.5);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (g_PushConstants.InverseDisplaySize.x < g_PushConstants.InverseDisplaySize.y)
 | 
					    if ((g_PushConstants.InverseDisplaySize.y / g_PushConstants.InverseDisplaySize.x) >= (4.0 / 3.0))
 | 
				
			||||||
        uvTexspace *= min(1.0, g_PushConstants.InverseDisplaySize.y * 720.0f);
 | 
					        uvTexspace *= g_PushConstants.InverseDisplaySize.y * 720.0f;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        uvTexspace *= min(1.0, g_PushConstants.InverseDisplaySize.x * 1280.0f);
 | 
					        uvTexspace *= g_PushConstants.InverseDisplaySize.x * 960.0f;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return SampleLinear(uvTexspace);
 | 
					    return SampleLinear(uvTexspace);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -81,7 +81,7 @@ float median(float r, float g, float b)
 | 
				
			||||||
float4 main(in Interpolators interpolators) : SV_Target
 | 
					float4 main(in Interpolators interpolators) : SV_Target
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    float4 color = interpolators.Color;
 | 
					    float4 color = interpolators.Color;
 | 
				
			||||||
    color *= PixelAntialiasing(interpolators.Position.xy - 0.5);
 | 
					    color *= PixelAntialiasing(interpolators.Position.xy - (g_PushConstants.ProceduralOrigin + 0.5));
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (g_PushConstants.Texture2DDescriptorIndex != 0)
 | 
					    if (g_PushConstants.Texture2DDescriptorIndex != 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,7 @@
 | 
				
			||||||
#include <ui/options_menu.h>
 | 
					#include <ui/options_menu.h>
 | 
				
			||||||
#include <ui/sdl_listener.h>
 | 
					#include <ui/sdl_listener.h>
 | 
				
			||||||
#include <ui/game_window.h>
 | 
					#include <ui/game_window.h>
 | 
				
			||||||
 | 
					#include <patches/aspect_ratio_patches.h>
 | 
				
			||||||
#include <user/config.h>
 | 
					#include <user/config.h>
 | 
				
			||||||
#include <xxHashMap.h>
 | 
					#include <xxHashMap.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +39,8 @@
 | 
				
			||||||
#ifdef SWA_D3D12
 | 
					#ifdef SWA_D3D12
 | 
				
			||||||
#include "shader/copy_vs.hlsl.dxil.h"
 | 
					#include "shader/copy_vs.hlsl.dxil.h"
 | 
				
			||||||
#include "shader/csd_filter_ps.hlsl.dxil.h"
 | 
					#include "shader/csd_filter_ps.hlsl.dxil.h"
 | 
				
			||||||
 | 
					#include "shader/csd_no_tex_vs.hlsl.dxil.h"
 | 
				
			||||||
 | 
					#include "shader/csd_vs.hlsl.dxil.h"
 | 
				
			||||||
#include "shader/enhanced_motion_blur_ps.hlsl.dxil.h"
 | 
					#include "shader/enhanced_motion_blur_ps.hlsl.dxil.h"
 | 
				
			||||||
#include "shader/gamma_correction_ps.hlsl.dxil.h"
 | 
					#include "shader/gamma_correction_ps.hlsl.dxil.h"
 | 
				
			||||||
#include "shader/gaussian_blur_3x3.hlsl.dxil.h"
 | 
					#include "shader/gaussian_blur_3x3.hlsl.dxil.h"
 | 
				
			||||||
| 
						 | 
					@ -55,6 +58,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "shader/copy_vs.hlsl.spirv.h"
 | 
					#include "shader/copy_vs.hlsl.spirv.h"
 | 
				
			||||||
#include "shader/csd_filter_ps.hlsl.spirv.h"
 | 
					#include "shader/csd_filter_ps.hlsl.spirv.h"
 | 
				
			||||||
 | 
					#include "shader/csd_no_tex_vs.hlsl.spirv.h"
 | 
				
			||||||
 | 
					#include "shader/csd_vs.hlsl.spirv.h"
 | 
				
			||||||
#include "shader/enhanced_motion_blur_ps.hlsl.spirv.h"
 | 
					#include "shader/enhanced_motion_blur_ps.hlsl.spirv.h"
 | 
				
			||||||
#include "shader/gamma_correction_ps.hlsl.spirv.h"
 | 
					#include "shader/gamma_correction_ps.hlsl.spirv.h"
 | 
				
			||||||
#include "shader/gaussian_blur_3x3.hlsl.spirv.h"
 | 
					#include "shader/gaussian_blur_3x3.hlsl.spirv.h"
 | 
				
			||||||
| 
						 | 
					@ -1163,6 +1168,7 @@ struct ImGuiPushConstants
 | 
				
			||||||
    ImVec2 inverseDisplaySize{};
 | 
					    ImVec2 inverseDisplaySize{};
 | 
				
			||||||
    ImVec2 origin{ 0.0f, 0.0f };
 | 
					    ImVec2 origin{ 0.0f, 0.0f };
 | 
				
			||||||
    ImVec2 scale{ 1.0f, 1.0f };
 | 
					    ImVec2 scale{ 1.0f, 1.0f };
 | 
				
			||||||
 | 
					    ImVec2 proceduralOrigin{ 0.0f, 0.0f };
 | 
				
			||||||
    float outline{};
 | 
					    float outline{};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1345,6 +1351,20 @@ static void CheckSwapChain()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (g_swapChainValid)
 | 
					    if (g_swapChainValid)
 | 
				
			||||||
        g_swapChainValid = g_swapChain->acquireTexture(g_acquireSemaphores[g_frame].get(), &g_backBufferIndex);
 | 
					        g_swapChainValid = g_swapChain->acquireTexture(g_acquireSemaphores[g_frame].get(), &g_backBufferIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (g_needsResize)
 | 
				
			||||||
 | 
					        Video::ComputeViewportDimensions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (g_aspectRatio >= NARROW_ASPECT_RATIO)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        g_backBuffer->width = Video::s_viewportWidth * 720 / Video::s_viewportHeight;
 | 
				
			||||||
 | 
					        g_backBuffer->height = 720;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        g_backBuffer->width = 960;
 | 
				
			||||||
 | 
					        g_backBuffer->height = Video::s_viewportHeight * 960 / Video::s_viewportWidth;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void BeginCommandList()
 | 
					static void BeginCommandList()
 | 
				
			||||||
| 
						 | 
					@ -1358,13 +1378,14 @@ static void BeginCommandList()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (g_swapChainValid)
 | 
					    if (g_swapChainValid)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        bool applyingGammaCorrection = Config::XboxColorCorrection || abs(Config::Brightness - 0.5f) > 0.001f;
 | 
					        uint32_t width = Video::s_viewportWidth;
 | 
				
			||||||
 | 
					        uint32_t height = Video::s_viewportHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (applyingGammaCorrection)
 | 
					        bool usingIntermediaryTexture = (width != g_swapChain->getWidth()) || (height != g_swapChain->getHeight()) ||
 | 
				
			||||||
 | 
					            Config::XboxColorCorrection || (abs(Config::Brightness - 0.5f) > 0.001f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (usingIntermediaryTexture)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            uint32_t width = g_swapChain->getWidth();
 | 
					 | 
				
			||||||
            uint32_t height = g_swapChain->getHeight();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (g_intermediaryBackBufferTextureWidth != width ||
 | 
					            if (g_intermediaryBackBufferTextureWidth != width ||
 | 
				
			||||||
                g_intermediaryBackBufferTextureHeight != height)
 | 
					                g_intermediaryBackBufferTextureHeight != height)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -1647,6 +1668,7 @@ void Video::CreateHostDevice(const char *sdlVideoDriver)
 | 
				
			||||||
    g_backBuffer->format = BACKBUFFER_FORMAT;
 | 
					    g_backBuffer->format = BACKBUFFER_FORMAT;
 | 
				
			||||||
    g_backBuffer->textureHolder = g_device->createTexture(RenderTextureDesc::Texture2D(1, 1, 1, BACKBUFFER_FORMAT, RenderTextureFlag::RENDER_TARGET));
 | 
					    g_backBuffer->textureHolder = g_device->createTexture(RenderTextureDesc::Texture2D(1, 1, 1, BACKBUFFER_FORMAT, RenderTextureFlag::RENDER_TARGET));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Video::ComputeViewportDimensions();
 | 
				
			||||||
    CheckSwapChain();
 | 
					    CheckSwapChain();
 | 
				
			||||||
    BeginCommandList();
 | 
					    BeginCommandList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2044,6 +2066,8 @@ static void DrawImGui()
 | 
				
			||||||
    ImGui::End();
 | 
					    ImGui::End();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ImGui::GetIO().DisplaySize = { float(Video::s_viewportWidth), float(Video::s_viewportHeight) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AchievementMenu::Draw();
 | 
					    AchievementMenu::Draw();
 | 
				
			||||||
    OptionsMenu::Draw();
 | 
					    OptionsMenu::Draw();
 | 
				
			||||||
    AchievementOverlay::Draw();
 | 
					    AchievementOverlay::Draw();
 | 
				
			||||||
| 
						 | 
					@ -2148,6 +2172,9 @@ static void ProcDrawImGui(const RenderCommand& cmd)
 | 
				
			||||||
                case ImGuiCallback::SetOutline:
 | 
					                case ImGuiCallback::SetOutline:
 | 
				
			||||||
                    setPushConstants(&pushConstants.outline, &callbackData->setOutline, sizeof(callbackData->setOutline));
 | 
					                    setPushConstants(&pushConstants.outline, &callbackData->setOutline, sizeof(callbackData->setOutline));
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					                case ImGuiCallback::SetProceduralOrigin:
 | 
				
			||||||
 | 
					                    setPushConstants(&pushConstants.proceduralOrigin, &callbackData->setProceduralOrigin, sizeof(callbackData->setProceduralOrigin));
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    assert(false && "Unknown ImGui callback type.");
 | 
					                    assert(false && "Unknown ImGui callback type.");
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
| 
						 | 
					@ -2325,6 +2352,11 @@ static void ProcExecuteCommandList(const RenderCommand& cmd)
 | 
				
			||||||
                float gammaG;
 | 
					                float gammaG;
 | 
				
			||||||
                float gammaB;
 | 
					                float gammaB;
 | 
				
			||||||
                uint32_t textureDescriptorIndex;
 | 
					                uint32_t textureDescriptorIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                int32_t viewportOffsetX;
 | 
				
			||||||
 | 
					                int32_t viewportOffsetY;
 | 
				
			||||||
 | 
					                int32_t viewportWidth;
 | 
				
			||||||
 | 
					                int32_t viewportHeight;
 | 
				
			||||||
            } constants;
 | 
					            } constants;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (Config::XboxColorCorrection)
 | 
					            if (Config::XboxColorCorrection)
 | 
				
			||||||
| 
						 | 
					@ -2347,6 +2379,11 @@ static void ProcExecuteCommandList(const RenderCommand& cmd)
 | 
				
			||||||
            constants.gammaB = 1.0f / std::clamp(constants.gammaB + offset, 0.1f, 4.0f);
 | 
					            constants.gammaB = 1.0f / std::clamp(constants.gammaB + offset, 0.1f, 4.0f);
 | 
				
			||||||
            constants.textureDescriptorIndex = g_intermediaryBackBufferTextureDescriptorIndex;
 | 
					            constants.textureDescriptorIndex = g_intermediaryBackBufferTextureDescriptorIndex;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            constants.viewportOffsetX = (int32_t(g_swapChain->getWidth()) - int32_t(Video::s_viewportWidth)) / 2;
 | 
				
			||||||
 | 
					            constants.viewportOffsetY = (int32_t(g_swapChain->getHeight()) - int32_t(Video::s_viewportHeight)) / 2;
 | 
				
			||||||
 | 
					            constants.viewportWidth = Video::s_viewportWidth;
 | 
				
			||||||
 | 
					            constants.viewportHeight = Video::s_viewportHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            auto &framebuffer = g_backBuffer->framebuffers[swapChainTexture];
 | 
					            auto &framebuffer = g_backBuffer->framebuffers[swapChainTexture];
 | 
				
			||||||
            if (!framebuffer)
 | 
					            if (!framebuffer)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
| 
						 | 
					@ -2369,8 +2406,8 @@ static void ProcExecuteCommandList(const RenderCommand& cmd)
 | 
				
			||||||
            commandList->setGraphicsDescriptorSet(g_textureDescriptorSet.get(), 0);
 | 
					            commandList->setGraphicsDescriptorSet(g_textureDescriptorSet.get(), 0);
 | 
				
			||||||
            SetRootDescriptor(g_uploadAllocators[g_frame].allocate<false>(&constants, sizeof(constants), 0x100), 2);
 | 
					            SetRootDescriptor(g_uploadAllocators[g_frame].allocate<false>(&constants, sizeof(constants), 0x100), 2);
 | 
				
			||||||
            commandList->setFramebuffer(framebuffer.get());
 | 
					            commandList->setFramebuffer(framebuffer.get());
 | 
				
			||||||
            commandList->setViewports(RenderViewport(0.0f, 0.0f, g_intermediaryBackBufferTextureWidth, g_intermediaryBackBufferTextureHeight));
 | 
					            commandList->setViewports(RenderViewport(0.0f, 0.0f, g_swapChain->getWidth(), g_swapChain->getHeight()));
 | 
				
			||||||
            commandList->setScissors(RenderRect(0, 0, g_intermediaryBackBufferTextureWidth, g_intermediaryBackBufferTextureHeight));
 | 
					            commandList->setScissors(RenderRect(0, 0, g_swapChain->getWidth(), g_swapChain->getHeight()));
 | 
				
			||||||
            commandList->drawInstanced(6, 1, 0, 0);
 | 
					            commandList->drawInstanced(6, 1, 0, 0);
 | 
				
			||||||
            commandList->barriers(RenderBarrierStage::GRAPHICS, RenderTextureBarrier(swapChainTexture, RenderTextureLayout::PRESENT));
 | 
					            commandList->barriers(RenderBarrierStage::GRAPHICS, RenderTextureBarrier(swapChainTexture, RenderTextureLayout::PRESENT));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -2419,6 +2456,61 @@ static GuestSurface* GetBackBuffer()
 | 
				
			||||||
    return g_backBuffer;
 | 
					    return g_backBuffer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GuestSurface* Video::GetBackBuffer()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return g_backBuffer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Video::ComputeViewportDimensions()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t width = g_swapChain->getWidth();
 | 
				
			||||||
 | 
					    uint32_t height = g_swapChain->getHeight();
 | 
				
			||||||
 | 
					    float aspectRatio = float(width) / float(height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (Config::AspectRatio)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    case EAspectRatio::Wide:
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (aspectRatio > WIDE_ASPECT_RATIO)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            s_viewportWidth = height * 16 / 9;
 | 
				
			||||||
 | 
					            s_viewportHeight = height;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            s_viewportWidth = width;
 | 
				
			||||||
 | 
					            s_viewportHeight = width * 9 / 16;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case EAspectRatio::Narrow:
 | 
				
			||||||
 | 
					    case EAspectRatio::OriginalNarrow:
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (aspectRatio > NARROW_ASPECT_RATIO)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            s_viewportWidth = height * 4 / 3;
 | 
				
			||||||
 | 
					            s_viewportHeight = height;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            s_viewportWidth = width;
 | 
				
			||||||
 | 
					            s_viewportHeight = width * 3 / 4;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        s_viewportWidth = width;
 | 
				
			||||||
 | 
					        s_viewportHeight = height;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AspectRatioPatches::ComputeOffsets();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static RenderFormat ConvertFormat(uint32_t format)
 | 
					static RenderFormat ConvertFormat(uint32_t format)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    switch (format)
 | 
					    switch (format)
 | 
				
			||||||
| 
						 | 
					@ -2587,13 +2679,13 @@ static void FlushViewport()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (renderingToBackBuffer)
 | 
					        if (renderingToBackBuffer)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            uint32_t width = g_swapChain->getWidth();
 | 
					            float width = Video::s_viewportWidth;
 | 
				
			||||||
            uint32_t height = g_swapChain->getHeight();
 | 
					            float height = Video::s_viewportHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            viewport.x *= width / 1280.0f;
 | 
					            viewport.x *= width / g_backBuffer->width;
 | 
				
			||||||
            viewport.y *= height / 720.0f;    
 | 
					            viewport.y *= height / g_backBuffer->height;
 | 
				
			||||||
            viewport.width *= width / 1280.0f;
 | 
					            viewport.width *= width / g_backBuffer->width;
 | 
				
			||||||
            viewport.height *= height / 720.0f;
 | 
					            viewport.height *= height / g_backBuffer->height;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (viewport.minDepth > viewport.maxDepth)
 | 
					        if (viewport.minDepth > viewport.maxDepth)
 | 
				
			||||||
| 
						 | 
					@ -2614,13 +2706,13 @@ static void FlushViewport()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (renderingToBackBuffer)
 | 
					        if (renderingToBackBuffer)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            uint32_t width = g_swapChain->getWidth();
 | 
					            uint32_t width = Video::s_viewportWidth;
 | 
				
			||||||
            uint32_t height = g_swapChain->getHeight();
 | 
					            uint32_t height = Video::s_viewportHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            scissorRect.left = scissorRect.left * width / 1280;
 | 
					            scissorRect.left = scissorRect.left * width / g_backBuffer->width;
 | 
				
			||||||
            scissorRect.top = scissorRect.top * height / 720;
 | 
					            scissorRect.top = scissorRect.top * height / g_backBuffer->height;
 | 
				
			||||||
            scissorRect.right = scissorRect.right * width / 1280;
 | 
					            scissorRect.right = scissorRect.right * width / g_backBuffer->width;
 | 
				
			||||||
            scissorRect.bottom = scissorRect.bottom * height / 720;
 | 
					            scissorRect.bottom = scissorRect.bottom * height / g_backBuffer->height;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        commandList->setScissors(scissorRect);
 | 
					        commandList->setScissors(scissorRect);
 | 
				
			||||||
| 
						 | 
					@ -4160,6 +4252,12 @@ static GuestShader* CreateShader(const be<uint32_t>* function, ResourceType reso
 | 
				
			||||||
        if (findResult->guestShader == nullptr)
 | 
					        if (findResult->guestShader == nullptr)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            shader = g_userHeap.AllocPhysical<GuestShader>(resourceType);
 | 
					            shader = g_userHeap.AllocPhysical<GuestShader>(resourceType);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (hash == 0xB1086A4947A797DE)
 | 
				
			||||||
 | 
					                shader->shader = CREATE_SHADER(csd_no_tex_vs);
 | 
				
			||||||
 | 
					            else if (hash == 0xB4CAFC034A37C8A8)
 | 
				
			||||||
 | 
					                shader->shader = CREATE_SHADER(csd_vs);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
                shader->shaderCacheEntry = findResult;
 | 
					                shader->shaderCacheEntry = findResult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            findResult->guestShader = shader;
 | 
					            findResult->guestShader = shader;
 | 
				
			||||||
| 
						 | 
					@ -4289,7 +4387,7 @@ static void ProcSetPixelShader(const RenderCommand& cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                size_t height = round(g_swapChain->getHeight() * Config::ResolutionScale);
 | 
					                size_t height = round(Video::s_viewportHeight * Config::ResolutionScale);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (height > 1440)
 | 
					                if (height > 1440)
 | 
				
			||||||
                    shaderIndex = GAUSSIAN_BLUR_9X9;
 | 
					                    shaderIndex = GAUSSIAN_BLUR_9X9;
 | 
				
			||||||
| 
						 | 
					@ -4719,6 +4817,8 @@ static bool LoadTexture(GuestTexture& texture, const uint8_t* data, size_t dataS
 | 
				
			||||||
        texture.descriptorIndex = g_textureDescriptorAllocator.allocate();
 | 
					        texture.descriptorIndex = g_textureDescriptorAllocator.allocate();
 | 
				
			||||||
        g_textureDescriptorSet->setTexture(texture.descriptorIndex, texture.texture, RenderTextureLayout::SHADER_READ, texture.textureView.get());
 | 
					        g_textureDescriptorSet->setTexture(texture.descriptorIndex, texture.texture, RenderTextureLayout::SHADER_READ, texture.textureView.get());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        texture.width = ddsDesc.width;
 | 
				
			||||||
 | 
					        texture.height = ddsDesc.height;
 | 
				
			||||||
        texture.viewDimension = viewDesc.dimension;
 | 
					        texture.viewDimension = viewDesc.dimension;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct Slice
 | 
					        struct Slice
 | 
				
			||||||
| 
						 | 
					@ -4929,8 +5029,10 @@ void SetShadowResolutionMidAsmHook(PPCRegister& r11)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void SetResolution(be<uint32_t>* device)
 | 
					static void SetResolution(be<uint32_t>* device)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t width = uint32_t(round(g_swapChain->getWidth() * Config::ResolutionScale));
 | 
					    Video::ComputeViewportDimensions();
 | 
				
			||||||
    uint32_t height = uint32_t(round(g_swapChain->getHeight() * Config::ResolutionScale));
 | 
					
 | 
				
			||||||
 | 
					    uint32_t width = uint32_t(round(Video::s_viewportWidth * Config::ResolutionScale));
 | 
				
			||||||
 | 
					    uint32_t height = uint32_t(round(Video::s_viewportHeight * Config::ResolutionScale));
 | 
				
			||||||
    device[46] = width == 0 ? 880 : width;
 | 
					    device[46] = width == 0 ? 880 : width;
 | 
				
			||||||
    device[47] = height == 0 ? 720 : height;
 | 
					    device[47] = height == 0 ? 720 : height;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -6409,10 +6511,14 @@ void VideoConfigValueChangedCallback(IConfigDef* config)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    // Config options that require internal resolution resize
 | 
					    // Config options that require internal resolution resize
 | 
				
			||||||
    g_needsResize |=
 | 
					    g_needsResize |=
 | 
				
			||||||
 | 
					        config == &Config::AspectRatio ||
 | 
				
			||||||
        config == &Config::ResolutionScale ||
 | 
					        config == &Config::ResolutionScale ||
 | 
				
			||||||
        config == &Config::AntiAliasing ||
 | 
					        config == &Config::AntiAliasing ||
 | 
				
			||||||
        config == &Config::ShadowResolution;
 | 
					        config == &Config::ShadowResolution;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (g_needsResize)
 | 
				
			||||||
 | 
					        Video::ComputeViewportDimensions();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
    // Config options that require pipeline recompilation
 | 
					    // Config options that require pipeline recompilation
 | 
				
			||||||
    bool shouldRecompile =
 | 
					    bool shouldRecompile =
 | 
				
			||||||
        config == &Config::AntiAliasing ||
 | 
					        config == &Config::AntiAliasing ||
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,11 +15,16 @@ using namespace plume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Video
 | 
					struct Video
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    static inline uint32_t s_viewportWidth;
 | 
				
			||||||
 | 
					    static inline uint32_t s_viewportHeight;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static void CreateHostDevice(const char *sdlVideoDriver);
 | 
					    static void CreateHostDevice(const char *sdlVideoDriver);
 | 
				
			||||||
    static void WaitOnSwapChain();
 | 
					    static void WaitOnSwapChain();
 | 
				
			||||||
    static void Present();
 | 
					    static void Present();
 | 
				
			||||||
    static void StartPipelinePrecompilation();
 | 
					    static void StartPipelinePrecompilation();
 | 
				
			||||||
    static void WaitForGPU();
 | 
					    static void WaitForGPU();
 | 
				
			||||||
 | 
					    static struct GuestSurface* GetBackBuffer();
 | 
				
			||||||
 | 
					    static void ComputeViewportDimensions();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct GuestSamplerState
 | 
					struct GuestSamplerState
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,7 @@ CONFIG_DEFINE_LOCALE(ControlTutorial)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_DEFINE_LOCALE(AchievementNotifications)
 | 
					CONFIG_DEFINE_LOCALE(AchievementNotifications)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    { ELanguage::English, { "Achievement Notifications", "Show notifications for unlocking achievements.\n\nAchievements will still\nbe rewarded with notifications disabled." } }
 | 
					    { ELanguage::English, { "Achievement Notifications", "Show notifications for unlocking achievements.\n\nAchievements will still be rewarded with notifications disabled." } }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_DEFINE_LOCALE(TimeOfDayTransition)
 | 
					CONFIG_DEFINE_LOCALE(TimeOfDayTransition)
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@ CONFIG_DEFINE_ENUM_LOCALE(EControllerIcons)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ELanguage::English,
 | 
					        ELanguage::English,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            { EControllerIcons::Auto,        { "AUTO", "Auto: the game will determine which icons\nto use based on the current input device." } },
 | 
					            { EControllerIcons::Auto,        { "AUTO", "Auto: the game will determine which icons to use based on the current input device." } },
 | 
				
			||||||
            { EControllerIcons::Xbox,        { "XBOX", "" } },
 | 
					            { EControllerIcons::Xbox,        { "XBOX", "" } },
 | 
				
			||||||
            { EControllerIcons::PlayStation, { "PLAYSTATION", "" } }
 | 
					            { EControllerIcons::PlayStation, { "PLAYSTATION", "" } }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -188,7 +188,8 @@ CONFIG_DEFINE_ENUM_LOCALE(EAspectRatio)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ELanguage::English,
 | 
					        ELanguage::English,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            { EAspectRatio::Auto, { "AUTO", "Auto: the aspect ratio will dynamically adjust to the window size." } }
 | 
					            { EAspectRatio::Auto, { "AUTO", "Auto: the aspect ratio will dynamically adjust to the window size." } },
 | 
				
			||||||
 | 
					            { EAspectRatio::OriginalNarrow, { "ORIGINAL 4:3", "" } }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -205,7 +206,7 @@ CONFIG_DEFINE_LOCALE(Fullscreen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_DEFINE_LOCALE(VSync)
 | 
					CONFIG_DEFINE_LOCALE(VSync)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    { ELanguage::English, { "V-Sync", "Synchronize the game\nto the refresh rate of\nthe display to prevent screen tearing." } }
 | 
					    { ELanguage::English, { "V-Sync", "Synchronize the game to the refresh rate of the display to prevent screen tearing." } }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_DEFINE_LOCALE(FPS)
 | 
					CONFIG_DEFINE_LOCALE(FPS)
 | 
				
			||||||
| 
						 | 
					@ -283,7 +284,7 @@ CONFIG_DEFINE_ENUM_LOCALE(EMotionBlur)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            { EMotionBlur::Off,      { "OFF", "" } },
 | 
					            { EMotionBlur::Off,      { "OFF", "" } },
 | 
				
			||||||
            { EMotionBlur::Original, { "ORIGINAL", "" } },
 | 
					            { EMotionBlur::Original, { "ORIGINAL", "" } },
 | 
				
			||||||
            { EMotionBlur::Enhanced, { "ENHANCED", "Enhanced: uses more samples for smoother motion blur at the cost\nof performance." } }
 | 
					            { EMotionBlur::Enhanced, { "ENHANCED", "Enhanced: uses more samples for smoother motion blur at the cost of performance." } }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -293,6 +294,22 @@ CONFIG_DEFINE_LOCALE(XboxColorCorrection)
 | 
				
			||||||
    { ELanguage::English, { "Xbox Color Correction", "Use the warm tint from the Xbox version of the game." } }
 | 
					    { ELanguage::English, { "Xbox Color Correction", "Use the warm tint from the Xbox version of the game." } }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONFIG_DEFINE_LOCALE(CutsceneAspectRatio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    { ELanguage::English, { "Cutscene Aspect Ratio", "" } }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONFIG_DEFINE_ENUM_LOCALE(ECutsceneAspectRatio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ELanguage::English,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            { ECutsceneAspectRatio::Original, { "ORIGINAL", "" } },
 | 
				
			||||||
 | 
					            { ECutsceneAspectRatio::Unlocked, { "UNLOCKED", "" } },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_DEFINE_LOCALE(UIScaleMode)
 | 
					CONFIG_DEFINE_LOCALE(UIScaleMode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    { ELanguage::English, { "UI Scale Mode", "Change how the UI scales to the display." } }
 | 
					    { ELanguage::English, { "UI Scale Mode", "Change how the UI scales to the display." } }
 | 
				
			||||||
| 
						 | 
					@ -303,7 +320,6 @@ CONFIG_DEFINE_ENUM_LOCALE(EUIScaleMode)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ELanguage::English,
 | 
					        ELanguage::English,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            { EUIScaleMode::Stretch, { "STRETCH", "Stretch: the UI will stretch to the display." } },
 | 
					 | 
				
			||||||
            { EUIScaleMode::Edge,    { "EDGE", "Edge: the UI will anchor to the edges of the display." } },
 | 
					            { EUIScaleMode::Edge,    { "EDGE", "Edge: the UI will anchor to the edges of the display." } },
 | 
				
			||||||
            { EUIScaleMode::Centre,  { "CENTER", "Center: the UI will anchor to the center of the display." } },
 | 
					            { EUIScaleMode::Centre,  { "CENTER", "Center: the UI will anchor to the center of the display." } },
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1165
									
								
								UnleashedRecomp/patches/aspect_ratio_patches.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1165
									
								
								UnleashedRecomp/patches/aspect_ratio_patches.cpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										16
									
								
								UnleashedRecomp/patches/aspect_ratio_patches.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								UnleashedRecomp/patches/aspect_ratio_patches.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline constexpr float NARROW_ASPECT_RATIO = 4.0f / 3.0f;
 | 
				
			||||||
 | 
					inline constexpr float WIDE_ASPECT_RATIO = 16.0f / 9.0f;
 | 
				
			||||||
 | 
					inline constexpr float STEAM_DECK_ASPECT_RATIO = 16.0f / 10.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline float g_aspectRatio;
 | 
				
			||||||
 | 
					inline float g_aspectRatioOffsetX;
 | 
				
			||||||
 | 
					inline float g_aspectRatioOffsetY;
 | 
				
			||||||
 | 
					inline float g_aspectRatioScale;
 | 
				
			||||||
 | 
					inline float g_narrowOffsetScale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct AspectRatioPatches
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static void ComputeOffsets();
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -1,41 +1,41 @@
 | 
				
			||||||
#include <api/SWA.h>
 | 
					#include <api/SWA.h>
 | 
				
			||||||
#include <ui/game_window.h>
 | 
					#include <ui/game_window.h>
 | 
				
			||||||
#include <user/config.h>
 | 
					#include <user/config.h>
 | 
				
			||||||
 | 
					#include <gpu/video.h>
 | 
				
			||||||
 | 
					#include "camera_patches.h"
 | 
				
			||||||
 | 
					#include "aspect_ratio_patches.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
constexpr float m_baseAspectRatio = 16.0f / 9.0f;
 | 
					void CameraAspectRatioMidAsmHook(PPCRegister& r30, PPCRegister& r31)
 | 
				
			||||||
 | 
					 | 
				
			||||||
bool CameraAspectRatioMidAsmHook(PPCRegister& r31)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto pCamera = (SWA::CCamera*)g_memory.Translate(r31.u32);
 | 
					    r30.u32 = 0;
 | 
				
			||||||
    auto newAspectRatio = (float)GameWindow::s_width / (float)GameWindow::s_height;
 | 
					
 | 
				
			||||||
 | 
					    auto camera = (SWA::CCamera*)g_memory.Translate(r31.u32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Dynamically adjust horizontal aspect ratio to window dimensions.
 | 
					    // Dynamically adjust horizontal aspect ratio to window dimensions.
 | 
				
			||||||
    pCamera->m_HorzAspectRatio = newAspectRatio;
 | 
					    camera->m_HorzAspectRatio = g_aspectRatio;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (auto s_pVertAspectRatio = (be<float>*)g_memory.Translate(0x82028FE0))
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        // Dynamically adjust vertical aspect ratio for VERT+.
 | 
					 | 
				
			||||||
        *s_pVertAspectRatio = 2.0f * atan(tan(45.0f / 2.0f) * (m_baseAspectRatio / newAspectRatio));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Jump to 4:3 code for VERT+ adjustments if using a narrow aspect ratio.
 | 
					 | 
				
			||||||
    return newAspectRatio < m_baseAspectRatio;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool CameraBoostAspectRatioMidAsmHook(PPCRegister& r31, PPCRegister& f0, PPCRegister& f10, PPCRegister& f12)
 | 
					float AdjustFieldOfView(float fieldOfView, float aspectRatio)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto pCamera = (SWA::CCamera*)g_memory.Translate(r31.u32);
 | 
					    if (Config::AspectRatio == EAspectRatio::OriginalNarrow)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (GameWindow::s_width < GameWindow::s_height)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        pCamera->m_VertFieldOfView = pCamera->m_HorzFieldOfView + f10.f64;
 | 
					        // Replicate the original incorrect field of view formula if requested. 
 | 
				
			||||||
 | 
					        fieldOfView *= NARROW_ASPECT_RATIO;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else if (aspectRatio < WIDE_ASPECT_RATIO)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        pCamera->m_VertFieldOfView = (f12.f64 / f0.f64) + f10.f64;
 | 
					        // Use proper VERT+ otherwise for narrow aspect ratios.
 | 
				
			||||||
 | 
					        fieldOfView = 2.0 * atan(tan(0.5 * fieldOfView) / aspectRatio * WIDE_ASPECT_RATIO);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return true;
 | 
					    return fieldOfView;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CameraFieldOfViewMidAsmHook(PPCRegister& r31, PPCRegister& f31)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    auto camera = (SWA::CCamera*)g_memory.Translate(r31.u32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    f31.f64 = AdjustFieldOfView(f31.f64, camera->m_HorzAspectRatio);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PPC_FUNC_IMPL(__imp__sub_824697B0);
 | 
					PPC_FUNC_IMPL(__imp__sub_824697B0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								UnleashedRecomp/patches/camera_patches.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								UnleashedRecomp/patches/camera_patches.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern float AdjustFieldOfView(float fieldOfView, float aspectRatio);
 | 
				
			||||||
| 
						 | 
					@ -134,8 +134,8 @@ static void DrawHeaderContainer(const char* text)
 | 
				
			||||||
        ? Lerp(1, 0, colourMotion)
 | 
					        ? Lerp(1, 0, colourMotion)
 | 
				
			||||||
        : Lerp(0, 1, colourMotion);
 | 
					        : Lerp(0, 1, colourMotion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImVec2 min = { Scale(containerMarginX), Scale(136) };
 | 
					    ImVec2 min = { Scale(g_aspectRatioOffsetX + containerMarginX), Scale(g_aspectRatioOffsetY + 136) };
 | 
				
			||||||
    ImVec2 max = { min.x + textMarginX * 2 + textSize.x + Scale(5), Scale(196) };
 | 
					    ImVec2 max = { min.x + textMarginX * 2 + textSize.x + Scale(5), Scale(g_aspectRatioOffsetY + 196) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DrawPauseHeaderContainer(g_upWindow.get(), min, max, alpha);
 | 
					    DrawPauseHeaderContainer(g_upWindow.get(), min, max, alpha);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -568,8 +568,8 @@ static void DrawContentContainer()
 | 
				
			||||||
        ? Hermite(604, 573, motion)
 | 
					        ? Hermite(604, 573, motion)
 | 
				
			||||||
        : Hermite(573, 604, motion);
 | 
					        : Hermite(573, 604, motion);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImVec2 min = { Scale(minX), Scale(minY) };
 | 
					    ImVec2 min = { Scale(g_aspectRatioOffsetX + minX), Scale(g_aspectRatioOffsetY + minY) };
 | 
				
			||||||
    ImVec2 max = { Scale(maxX), Scale(maxY) };
 | 
					    ImVec2 max = { Scale(g_aspectRatioOffsetX + maxX), Scale(g_aspectRatioOffsetY + maxY) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Transparency fade animation.
 | 
					    // Transparency fade animation.
 | 
				
			||||||
    auto alpha = g_isClosing
 | 
					    auto alpha = g_isClosing
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -229,11 +229,8 @@ void ButtonGuide::Draw()
 | 
				
			||||||
    auto drawList = ImGui::GetForegroundDrawList();
 | 
					    auto drawList = ImGui::GetForegroundDrawList();
 | 
				
			||||||
    auto& res = ImGui::GetIO().DisplaySize;
 | 
					    auto& res = ImGui::GetIO().DisplaySize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto regionMarginX = Scale(g_sideMargins);
 | 
					    ImVec2 regionMin = { Scale(g_aspectRatioOffsetX + g_sideMargins), Scale(g_aspectRatioOffsetY * 2.0f + 720.0f - 102.0f) };
 | 
				
			||||||
    auto regionHeight = Scale(102);
 | 
					    ImVec2 regionMax = { Scale(g_aspectRatioOffsetX + 1280.0f - g_sideMargins), Scale(g_aspectRatioOffsetY * 2.0f + 720.0f) };
 | 
				
			||||||
 | 
					 | 
				
			||||||
    ImVec2 regionMin = { regionMarginX, res.y - regionHeight };
 | 
					 | 
				
			||||||
    ImVec2 regionMax = { res.x - regionMarginX, res.y };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto textMarginX = Scale(57);
 | 
					    auto textMarginX = Scale(57);
 | 
				
			||||||
    auto textMarginY = Scale(8);
 | 
					    auto textMarginY = Scale(8);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
#include <gpu/video.h>
 | 
					#include <gpu/video.h>
 | 
				
			||||||
#include <app.h>
 | 
					#include <app.h>
 | 
				
			||||||
#include <version.h>
 | 
					#include <version.h>
 | 
				
			||||||
 | 
					#include <patches/aspect_ratio_patches.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PIXELS_TO_UV_COORDS(textureWidth, textureHeight, x, y, width, height) \
 | 
					#define PIXELS_TO_UV_COORDS(textureWidth, textureHeight, x, y, width, height) \
 | 
				
			||||||
    std::make_tuple(ImVec2((float)x / (float)textureWidth, (float)y / (float)textureHeight), \
 | 
					    std::make_tuple(ImVec2((float)x / (float)textureWidth, (float)y / (float)textureHeight), \
 | 
				
			||||||
| 
						 | 
					@ -95,29 +96,26 @@ inline void ResetOutline()
 | 
				
			||||||
    SetOutline(0.0f);
 | 
					    SetOutline(0.0f);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Aspect ratio aware.
 | 
					inline void SetProceduralOrigin(ImVec2 proceduralOrigin)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    auto callbackData = AddImGuiCallback(ImGuiCallback::SetProceduralOrigin);
 | 
				
			||||||
 | 
					    callbackData->setProceduralOrigin.proceduralOrigin[0] = proceduralOrigin.x;
 | 
				
			||||||
 | 
					    callbackData->setProceduralOrigin.proceduralOrigin[1] = proceduralOrigin.y;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline void ResetProceduralOrigin()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SetProceduralOrigin({ 0.0f, 0.0f });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline float Scale(float size)
 | 
					inline float Scale(float size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto& io = ImGui::GetIO();
 | 
					    auto& io = ImGui::GetIO();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (io.DisplaySize.x > io.DisplaySize.y)
 | 
					    if (g_aspectRatio >= NARROW_ASPECT_RATIO)
 | 
				
			||||||
        return size * std::max(1.0f, io.DisplaySize.y / 720.0f);
 | 
					        return size * (io.DisplaySize.y / 720.0f);
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        return size * std::max(1.0f, io.DisplaySize.x / 1280.0f);
 | 
					        return size * (io.DisplaySize.x / 960.0f);
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Not aspect ratio aware. Will stretch.
 | 
					 | 
				
			||||||
inline float ScaleX(float x)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    auto& io = ImGui::GetIO();
 | 
					 | 
				
			||||||
    return x * io.DisplaySize.x / 1280.0f;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Not aspect ratio aware. Will stretch.
 | 
					 | 
				
			||||||
inline float ScaleY(float y)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    auto& io = ImGui::GetIO();
 | 
					 | 
				
			||||||
    return y * io.DisplaySize.y / 720.0f;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
inline double ComputeMotion(double duration, double offset, double total)
 | 
					inline double ComputeMotion(double duration, double offset, double total)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include <hid/hid.h>
 | 
					#include <hid/hid.h>
 | 
				
			||||||
#include <hid/hid_detail.h>
 | 
					#include <hid/hid_detail.h>
 | 
				
			||||||
#include <locale/locale.h>
 | 
					#include <locale/locale.h>
 | 
				
			||||||
 | 
					#include <patches/aspect_ratio_patches.h>
 | 
				
			||||||
#include <ui/imgui_utils.h>
 | 
					#include <ui/imgui_utils.h>
 | 
				
			||||||
#include <ui/button_guide.h>
 | 
					#include <ui/button_guide.h>
 | 
				
			||||||
#include <ui/message_window.h>
 | 
					#include <ui/message_window.h>
 | 
				
			||||||
| 
						 | 
					@ -447,8 +448,8 @@ static void DrawLeftImage()
 | 
				
			||||||
    GuestTexture *guestTexture = g_installTextures[installTextureIndex % g_installTextures.size()].get();
 | 
					    GuestTexture *guestTexture = g_installTextures[installTextureIndex % g_installTextures.size()].get();
 | 
				
			||||||
    auto &res = ImGui::GetIO().DisplaySize;
 | 
					    auto &res = ImGui::GetIO().DisplaySize;
 | 
				
			||||||
    auto drawList = ImGui::GetForegroundDrawList();
 | 
					    auto drawList = ImGui::GetForegroundDrawList();
 | 
				
			||||||
    ImVec2 min = { Scale(IMAGE_X), Scale(IMAGE_Y) };
 | 
					    ImVec2 min = { Scale(g_aspectRatioOffsetX + IMAGE_X), Scale(g_aspectRatioOffsetY + IMAGE_Y) };
 | 
				
			||||||
    ImVec2 max = { Scale(IMAGE_X + IMAGE_WIDTH), Scale(IMAGE_Y + IMAGE_HEIGHT) };
 | 
					    ImVec2 max = { min.x + Scale(IMAGE_WIDTH), min.y + Scale(IMAGE_HEIGHT) };
 | 
				
			||||||
    drawList->AddImage(guestTexture, min, max, ImVec2(0, 0), ImVec2(1, 1), IM_COL32(255, 255, 255, a));
 | 
					    drawList->AddImage(guestTexture, min, max, ImVec2(0, 0), ImVec2(1, 1), IM_COL32(255, 255, 255, a));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -511,7 +512,7 @@ static void DrawHeaderIcons()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto drawList = ImGui::GetForegroundDrawList();
 | 
					    auto drawList = ImGui::GetForegroundDrawList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    float iconsPosX = 253.0f;
 | 
					    float iconsPosX = g_aspectRatioOffsetX + 253.0f;
 | 
				
			||||||
    float iconsPosY = 79.0f;
 | 
					    float iconsPosY = 79.0f;
 | 
				
			||||||
    float iconsScale = 58;
 | 
					    float iconsScale = 58;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -577,7 +578,7 @@ static void DrawScanlineBars()
 | 
				
			||||||
    // Installer text
 | 
					    // Installer text
 | 
				
			||||||
    const std::string &headerText = Localise(g_currentPage == WizardPage::Installing ? "Installer_Header_Installing" : "Installer_Header_Installer");
 | 
					    const std::string &headerText = Localise(g_currentPage == WizardPage::Installing ? "Installer_Header_Installing" : "Installer_Header_Installer");
 | 
				
			||||||
    auto alphaMotion = ComputeMotionInstaller(g_appearTime, g_disappearTime, TITLE_ANIMATION_TIME, TITLE_ANIMATION_DURATION);
 | 
					    auto alphaMotion = ComputeMotionInstaller(g_appearTime, g_disappearTime, TITLE_ANIMATION_TIME, TITLE_ANIMATION_DURATION);
 | 
				
			||||||
    DrawTextWithOutline(g_dfsogeistdFont, Scale(42.0f), { Scale(285.0f), Scale(57.0f) }, IM_COL32(255, 195, 0, 255 * alphaMotion), headerText.c_str(), 4, IM_COL32(0, 0, 0, 255 * alphaMotion), IMGUI_SHADER_MODIFIER_TITLE_BEVEL);
 | 
					    DrawTextWithOutline(g_dfsogeistdFont, Scale(42.0f), { Scale(g_aspectRatioOffsetX + 285.0f), Scale(57.0f) }, IM_COL32(255, 195, 0, 255 * alphaMotion), headerText.c_str(), 4, IM_COL32(0, 0, 0, 255 * alphaMotion), IMGUI_SHADER_MODIFIER_TITLE_BEVEL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Top bar line
 | 
					    // Top bar line
 | 
				
			||||||
    drawList->AddLine
 | 
					    drawList->AddLine
 | 
				
			||||||
| 
						 | 
					@ -601,11 +602,6 @@ static void DrawScanlineBars()
 | 
				
			||||||
    DrawVersionString(g_newRodinFont, IM_COL32(255, 255, 255, 70 * alphaMotion));
 | 
					    DrawVersionString(g_newRodinFont, IM_COL32(255, 255, 255, 70 * alphaMotion));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static float AlignToNextGrid(float value)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return floor(value / GRID_SIZE) * GRID_SIZE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void DrawContainer(ImVec2 min, ImVec2 max, bool isTextArea)
 | 
					static void DrawContainer(ImVec2 min, ImVec2 max, bool isTextArea)
 | 
				
			||||||
{   
 | 
					{   
 | 
				
			||||||
    auto &res = ImGui::GetIO().DisplaySize;
 | 
					    auto &res = ImGui::GetIO().DisplaySize;
 | 
				
			||||||
| 
						 | 
					@ -641,8 +637,9 @@ static void DrawDescriptionContainer()
 | 
				
			||||||
    auto drawList = ImGui::GetForegroundDrawList();
 | 
					    auto drawList = ImGui::GetForegroundDrawList();
 | 
				
			||||||
    auto fontSize = Scale(26.0f);
 | 
					    auto fontSize = Scale(26.0f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImVec2 descriptionMin = { Scale(AlignToNextGrid(CONTAINER_X)), Scale(AlignToNextGrid(CONTAINER_Y)) };
 | 
					    ImVec2 descriptionMin = { Scale(g_aspectRatioOffsetX + CONTAINER_X), Scale(g_aspectRatioOffsetY + CONTAINER_Y) };
 | 
				
			||||||
    ImVec2 descriptionMax = { Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH)), Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT)) };
 | 
					    ImVec2 descriptionMax = { Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH), Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT) };
 | 
				
			||||||
 | 
					    SetProceduralOrigin(descriptionMin);
 | 
				
			||||||
    DrawContainer(descriptionMin, descriptionMax, true);
 | 
					    DrawContainer(descriptionMin, descriptionMax, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char descriptionText[512];
 | 
					    char descriptionText[512];
 | 
				
			||||||
| 
						 | 
					@ -692,8 +689,8 @@ static void DrawDescriptionContainer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ImVec2 imageMin = 
 | 
					        ImVec2 imageMin = 
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            /* X */ Scale(CONTAINER_X) + (Scale(CONTAINER_WIDTH) / 2) - (imageScale / 2) - (hedgeDevTextSize.x / 2) - hedgeDevTextMarginX,
 | 
					            /* X */ Scale(g_aspectRatioOffsetX + CONTAINER_X) + (Scale(CONTAINER_WIDTH) / 2) - (imageScale / 2) - (hedgeDevTextSize.x / 2) - hedgeDevTextMarginX,
 | 
				
			||||||
            /* Y */ Scale(CONTAINER_Y) + (Scale(CONTAINER_HEIGHT) / 2) - (imageScale / 2) + imageMarginY
 | 
					            /* Y */ Scale(g_aspectRatioOffsetY + CONTAINER_Y) + (Scale(CONTAINER_HEIGHT) / 2) - (imageScale / 2) + imageMarginY
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ImVec2 imageMax = { imageMin.x + imageScale, imageMin.y + imageScale };
 | 
					        ImVec2 imageMax = { imageMin.x + imageScale, imageMin.y + imageScale };
 | 
				
			||||||
| 
						 | 
					@ -713,9 +710,9 @@ static void DrawDescriptionContainer()
 | 
				
			||||||
        auto marqueeTextMarginX = Scale(5);
 | 
					        auto marqueeTextMarginX = Scale(5);
 | 
				
			||||||
        auto marqueeTextMarginY = Scale(15);
 | 
					        auto marqueeTextMarginY = Scale(15);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ImVec2 textPos = { descriptionMax.x, Scale(CONTAINER_Y) + Scale(CONTAINER_HEIGHT) - marqueeTextSize.y - marqueeTextMarginY };
 | 
					        ImVec2 textPos = { descriptionMax.x, Scale(g_aspectRatioOffsetY + CONTAINER_Y) + Scale(CONTAINER_HEIGHT) - marqueeTextSize.y - marqueeTextMarginY };
 | 
				
			||||||
        ImVec2 textMin = { Scale(CONTAINER_X), textPos.y };
 | 
					        ImVec2 textMin = { Scale(g_aspectRatioOffsetX + CONTAINER_X), textPos.y };
 | 
				
			||||||
        ImVec2 textMax = { Scale(CONTAINER_X) + Scale(CONTAINER_WIDTH), Scale(CONTAINER_Y) + Scale(CONTAINER_HEIGHT) };
 | 
					        ImVec2 textMax = { Scale(g_aspectRatioOffsetX + CONTAINER_X) + Scale(CONTAINER_WIDTH), Scale(g_aspectRatioOffsetY + CONTAINER_Y) + Scale(CONTAINER_HEIGHT) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SetMarqueeFade(textMin, textMax, Scale(32));
 | 
					        SetMarqueeFade(textMin, textMax, Scale(32));
 | 
				
			||||||
        DrawTextWithMarquee(g_seuratFont, fontSize, textPos, textMin, textMax, IM_COL32_WHITE, CREDITS_TEXT, g_appearTime, 0.9, Scale(250));
 | 
					        DrawTextWithMarquee(g_seuratFont, fontSize, textPos, textMin, textMax, IM_COL32_WHITE, CREDITS_TEXT, g_appearTime, 0.9, Scale(250));
 | 
				
			||||||
| 
						 | 
					@ -723,7 +720,7 @@ static void DrawDescriptionContainer()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImVec2 sideMin = { descriptionMax.x, descriptionMin.y };
 | 
					    ImVec2 sideMin = { descriptionMax.x, descriptionMin.y };
 | 
				
			||||||
    ImVec2 sideMax = { Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH + SIDE_CONTAINER_WIDTH)), descriptionMax.y };
 | 
					    ImVec2 sideMax = { res.x, descriptionMax.y };
 | 
				
			||||||
    DrawContainer(sideMin, sideMax, false);
 | 
					    DrawContainer(sideMin, sideMax, false);
 | 
				
			||||||
    drawList->PopClipRect();
 | 
					    drawList->PopClipRect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -741,6 +738,8 @@ static void DrawDescriptionContainer()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ButtonGuide::Close();
 | 
					        ButtonGuide::Close();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ResetProceduralOrigin();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void DrawButtonContainer(ImVec2 min, ImVec2 max, int baser, int baseg, float alpha)
 | 
					static void DrawButtonContainer(ImVec2 min, ImVec2 max, int baser, int baseg, float alpha)
 | 
				
			||||||
| 
						 | 
					@ -846,16 +845,16 @@ static void ComputeButtonColumnCoordinates(ButtonColumn buttonColumn, float &min
 | 
				
			||||||
    switch (buttonColumn)
 | 
					    switch (buttonColumn)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
    case ButtonColumnLeft:
 | 
					    case ButtonColumnLeft:
 | 
				
			||||||
        minX = Scale(AlignToNextGrid(CONTAINER_X) + CONTAINER_BUTTON_GAP);
 | 
					        minX = Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_BUTTON_GAP);
 | 
				
			||||||
        maxX = Scale(AlignToNextGrid(CONTAINER_X) + CONTAINER_BUTTON_GAP + CONTAINER_BUTTON_WIDTH);
 | 
					        maxX = Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_BUTTON_GAP + CONTAINER_BUTTON_WIDTH);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case ButtonColumnMiddle:
 | 
					    case ButtonColumnMiddle:
 | 
				
			||||||
        minX = Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH / 2.0f) - CONTAINER_BUTTON_WIDTH / 2.0f);
 | 
					        minX = Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH / 2.0f - CONTAINER_BUTTON_WIDTH / 2.0f);
 | 
				
			||||||
        maxX = Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH / 2.0f) + CONTAINER_BUTTON_WIDTH / 2.0f);
 | 
					        maxX = Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH / 2.0f + CONTAINER_BUTTON_WIDTH / 2.0f);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case ButtonColumnRight:
 | 
					    case ButtonColumnRight:
 | 
				
			||||||
        minX = Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH) - CONTAINER_BUTTON_GAP - CONTAINER_BUTTON_WIDTH);
 | 
					        minX = Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH - CONTAINER_BUTTON_GAP - CONTAINER_BUTTON_WIDTH);
 | 
				
			||||||
        maxX = Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH) - CONTAINER_BUTTON_GAP);
 | 
					        maxX = Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH - CONTAINER_BUTTON_GAP);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -867,8 +866,8 @@ static void DrawSourceButton(ButtonColumn buttonColumn, float yRatio, const char
 | 
				
			||||||
    ComputeButtonColumnCoordinates(buttonColumn, minX, maxX);
 | 
					    ComputeButtonColumnCoordinates(buttonColumn, minX, maxX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    float minusY = (CONTAINER_BUTTON_GAP + BUTTON_HEIGHT) * yRatio;
 | 
					    float minusY = (CONTAINER_BUTTON_GAP + BUTTON_HEIGHT) * yRatio;
 | 
				
			||||||
    ImVec2 min = { minX, Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) - CONTAINER_BUTTON_GAP - BUTTON_HEIGHT - minusY) };
 | 
					    ImVec2 min = { minX, Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT - CONTAINER_BUTTON_GAP - BUTTON_HEIGHT - minusY) };
 | 
				
			||||||
    ImVec2 max = { maxX, Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) - CONTAINER_BUTTON_GAP - minusY) };
 | 
					    ImVec2 max = { maxX, Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT - CONTAINER_BUTTON_GAP - minusY) };
 | 
				
			||||||
    DrawButton(min, max, sourceText, true, sourceSet, buttonPressed);
 | 
					    DrawButton(min, max, sourceText, true, sourceSet, buttonPressed);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -881,8 +880,8 @@ static void DrawProgressBar(float progressRatio)
 | 
				
			||||||
    const uint32_t innerColor1 = IM_COL32(0, 32, 0, 255 * alpha);
 | 
					    const uint32_t innerColor1 = IM_COL32(0, 32, 0, 255 * alpha);
 | 
				
			||||||
    float xPadding = Scale(6.0f);
 | 
					    float xPadding = Scale(6.0f);
 | 
				
			||||||
    float yPadding = Scale(3.0f);
 | 
					    float yPadding = Scale(3.0f);
 | 
				
			||||||
    ImVec2 min = { Scale(AlignToNextGrid(CONTAINER_X) + BOTTOM_X_GAP), Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) + BOTTOM_Y_GAP) };
 | 
					    ImVec2 min = { Scale(g_aspectRatioOffsetX + CONTAINER_X) + BOTTOM_X_GAP, Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT + BOTTOM_Y_GAP) };
 | 
				
			||||||
    ImVec2 max = { Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH) - BOTTOM_X_GAP), Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) + BOTTOM_Y_GAP + BUTTON_HEIGHT) };
 | 
					    ImVec2 max = { Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH - BOTTOM_X_GAP), Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT + BOTTOM_Y_GAP + BUTTON_HEIGHT) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DrawButtonContainer(min, max, 0, 0, alpha);
 | 
					    DrawButtonContainer(min, max, 0, 0, alpha);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1069,8 +1068,8 @@ static void DrawLanguagePicker()
 | 
				
			||||||
            ComputeButtonColumnCoordinates((i < 3) ? ButtonColumnLeft : ButtonColumnRight, minX, maxX);
 | 
					            ComputeButtonColumnCoordinates((i < 3) ? ButtonColumnLeft : ButtonColumnRight, minX, maxX);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            float minusY = (CONTAINER_BUTTON_GAP + BUTTON_HEIGHT) * (float(i % 3));
 | 
					            float minusY = (CONTAINER_BUTTON_GAP + BUTTON_HEIGHT) * (float(i % 3));
 | 
				
			||||||
            ImVec2 min = { minX, Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) - CONTAINER_BUTTON_GAP - BUTTON_HEIGHT - minusY) };
 | 
					            ImVec2 min = { minX, Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT - CONTAINER_BUTTON_GAP - BUTTON_HEIGHT - minusY) };
 | 
				
			||||||
            ImVec2 max = { maxX, Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) - CONTAINER_BUTTON_GAP - minusY) };
 | 
					            ImVec2 max = { maxX, Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT - CONTAINER_BUTTON_GAP - minusY) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // TODO: The active button should change its style to show an enabled toggle if it matches the current language.
 | 
					            // TODO: The active button should change its style to show an enabled toggle if it matches the current language.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1095,8 +1094,8 @@ static void DrawSourcePickers()
 | 
				
			||||||
        ImVec2 textSize = ComputeTextSize(g_dfsogeistdFont, addFilesText.c_str(), 20.0f, squashRatio, ADD_BUTTON_MAX_TEXT_WIDTH);
 | 
					        ImVec2 textSize = ComputeTextSize(g_dfsogeistdFont, addFilesText.c_str(), 20.0f, squashRatio, ADD_BUTTON_MAX_TEXT_WIDTH);
 | 
				
			||||||
        textSize.x += BUTTON_TEXT_GAP;
 | 
					        textSize.x += BUTTON_TEXT_GAP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ImVec2 min = { Scale(AlignToNextGrid(CONTAINER_X) + BOTTOM_X_GAP), Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) + BOTTOM_Y_GAP) };
 | 
					        ImVec2 min = { Scale(g_aspectRatioOffsetX + CONTAINER_X + BOTTOM_X_GAP), Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT + BOTTOM_Y_GAP) };
 | 
				
			||||||
        ImVec2 max = { Scale(AlignToNextGrid(CONTAINER_X) + BOTTOM_X_GAP + textSize.x * squashRatio), Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) + BOTTOM_Y_GAP + BUTTON_HEIGHT) };
 | 
					        ImVec2 max = { Scale(g_aspectRatioOffsetX + CONTAINER_X + BOTTOM_X_GAP + textSize.x * squashRatio), Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT + BOTTOM_Y_GAP + BUTTON_HEIGHT) };
 | 
				
			||||||
        DrawButton(min, max, addFilesText.c_str(), false, true, buttonPressed, ADD_BUTTON_MAX_TEXT_WIDTH);
 | 
					        DrawButton(min, max, addFilesText.c_str(), false, true, buttonPressed, ADD_BUTTON_MAX_TEXT_WIDTH);
 | 
				
			||||||
        if (buttonPressed)
 | 
					        if (buttonPressed)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					@ -1231,8 +1230,8 @@ static void DrawNextButton()
 | 
				
			||||||
        ImVec2 textSize = ComputeTextSize(g_newRodinFont, buttonText.c_str(), 20.0f, squashRatio, NEXT_BUTTON_MAX_TEXT_WIDTH);
 | 
					        ImVec2 textSize = ComputeTextSize(g_newRodinFont, buttonText.c_str(), 20.0f, squashRatio, NEXT_BUTTON_MAX_TEXT_WIDTH);
 | 
				
			||||||
        textSize.x += BUTTON_TEXT_GAP;
 | 
					        textSize.x += BUTTON_TEXT_GAP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ImVec2 min = { Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH) - textSize.x * squashRatio - BOTTOM_X_GAP), Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) + BOTTOM_Y_GAP) };
 | 
					        ImVec2 min = { Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH - textSize.x * squashRatio - BOTTOM_X_GAP), Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT + BOTTOM_Y_GAP) };
 | 
				
			||||||
        ImVec2 max = { Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH) - BOTTOM_X_GAP), Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) + BOTTOM_Y_GAP + BUTTON_HEIGHT) };
 | 
					        ImVec2 max = { Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH - BOTTOM_X_GAP), Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT + BOTTOM_Y_GAP + BUTTON_HEIGHT) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool buttonPressed = false;
 | 
					        bool buttonPressed = false;
 | 
				
			||||||
        DrawButton(min, max, buttonText.c_str(), false, nextButtonEnabled, buttonPressed, NEXT_BUTTON_MAX_TEXT_WIDTH);
 | 
					        DrawButton(min, max, buttonText.c_str(), false, nextButtonEnabled, buttonPressed, NEXT_BUTTON_MAX_TEXT_WIDTH);
 | 
				
			||||||
| 
						 | 
					@ -1317,10 +1316,10 @@ static void DrawHorizontalBorder(bool bottomBorder)
 | 
				
			||||||
    const uint32_t FADE_COLOR_RIGHT = IM_COL32(155, 225, 155, 0);
 | 
					    const uint32_t FADE_COLOR_RIGHT = IM_COL32(155, 225, 155, 0);
 | 
				
			||||||
    auto drawList = ImGui::GetForegroundDrawList();
 | 
					    auto drawList = ImGui::GetForegroundDrawList();
 | 
				
			||||||
    double borderScale = 1.0 - ComputeMotionInstaller(g_appearTime, g_disappearTime, CONTAINER_LINE_ANIMATION_TIME, CONTAINER_LINE_ANIMATION_DURATION);
 | 
					    double borderScale = 1.0 - ComputeMotionInstaller(g_appearTime, g_disappearTime, CONTAINER_LINE_ANIMATION_TIME, CONTAINER_LINE_ANIMATION_DURATION);
 | 
				
			||||||
    float midX = Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH / 5));
 | 
					    float midX = Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH / 5);
 | 
				
			||||||
    float minX = std::lerp(Scale(AlignToNextGrid(CONTAINER_X) - BORDER_SIZE - BORDER_OVERSHOOT), midX, borderScale);
 | 
					    float minX = std::lerp(Scale(g_aspectRatioOffsetX + CONTAINER_X - BORDER_SIZE - BORDER_OVERSHOOT), midX, borderScale);
 | 
				
			||||||
    float maxX = std::lerp(Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH + SIDE_CONTAINER_WIDTH) + BORDER_OVERSHOOT), midX, borderScale);
 | 
					    float maxX = std::lerp(Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH + SIDE_CONTAINER_WIDTH + BORDER_OVERSHOOT), midX, borderScale);
 | 
				
			||||||
    float minY = bottomBorder ? Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT)) : Scale(AlignToNextGrid(CONTAINER_Y) - BORDER_SIZE);
 | 
					    float minY = bottomBorder ? Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT) : Scale(g_aspectRatioOffsetY + CONTAINER_Y - BORDER_SIZE);
 | 
				
			||||||
    float maxY = minY + Scale(BORDER_SIZE);
 | 
					    float maxY = minY + Scale(BORDER_SIZE);
 | 
				
			||||||
    drawList->AddRectFilledMultiColor
 | 
					    drawList->AddRectFilledMultiColor
 | 
				
			||||||
    (
 | 
					    (
 | 
				
			||||||
| 
						 | 
					@ -1349,11 +1348,11 @@ static void DrawVerticalBorder(bool rightBorder)
 | 
				
			||||||
    const uint32_t FADE_COLOR = IM_COL32(155, rightBorder ? 225 : 155, 155, 0);
 | 
					    const uint32_t FADE_COLOR = IM_COL32(155, rightBorder ? 225 : 155, 155, 0);
 | 
				
			||||||
    auto drawList = ImGui::GetForegroundDrawList();
 | 
					    auto drawList = ImGui::GetForegroundDrawList();
 | 
				
			||||||
    double borderScale = 1.0 - ComputeMotionInstaller(g_appearTime, g_disappearTime, CONTAINER_LINE_ANIMATION_TIME, CONTAINER_LINE_ANIMATION_DURATION);
 | 
					    double borderScale = 1.0 - ComputeMotionInstaller(g_appearTime, g_disappearTime, CONTAINER_LINE_ANIMATION_TIME, CONTAINER_LINE_ANIMATION_DURATION);
 | 
				
			||||||
    float minX = rightBorder ? Scale(AlignToNextGrid(CONTAINER_X + CONTAINER_WIDTH)) : Scale(AlignToNextGrid(CONTAINER_X) - BORDER_SIZE);
 | 
					    float minX = rightBorder ? Scale(g_aspectRatioOffsetX + CONTAINER_X + CONTAINER_WIDTH) : Scale(g_aspectRatioOffsetX + CONTAINER_X - BORDER_SIZE);
 | 
				
			||||||
    float maxX = minX + Scale(BORDER_SIZE);
 | 
					    float maxX = minX + Scale(BORDER_SIZE);
 | 
				
			||||||
    float midY = Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT / 2));
 | 
					    float midY = Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT / 2);
 | 
				
			||||||
    float minY = std::lerp(Scale(AlignToNextGrid(CONTAINER_Y) - BORDER_OVERSHOOT), midY, borderScale);
 | 
					    float minY = std::lerp(Scale(g_aspectRatioOffsetY + CONTAINER_Y - BORDER_OVERSHOOT), midY, borderScale);
 | 
				
			||||||
    float maxY = std::lerp(Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) + BORDER_OVERSHOOT), midY, borderScale);
 | 
					    float maxY = std::lerp(Scale(g_aspectRatioOffsetY + CONTAINER_Y + CONTAINER_HEIGHT + BORDER_OVERSHOOT), midY, borderScale);
 | 
				
			||||||
    drawList->AddRectFilledMultiColor
 | 
					    drawList->AddRectFilledMultiColor
 | 
				
			||||||
    (
 | 
					    (
 | 
				
			||||||
        { minX, minY },
 | 
					        { minX, minY },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,9 +42,15 @@ static constexpr double CONTAINER_FULL_DURATION = CONTAINER_BACKGROUND_TIME + CO
 | 
				
			||||||
static constexpr double CONTAINER_CATEGORY_TIME = (CONTAINER_INNER_TIME + CONTAINER_BACKGROUND_TIME) / 2.0;
 | 
					static constexpr double CONTAINER_CATEGORY_TIME = (CONTAINER_INNER_TIME + CONTAINER_BACKGROUND_TIME) / 2.0;
 | 
				
			||||||
static constexpr double CONTAINER_CATEGORY_DURATION = 12.0;
 | 
					static constexpr double CONTAINER_CATEGORY_DURATION = 12.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
constexpr float COMMON_PADDING_POS_Y = 118.0f;
 | 
					static constexpr float CONTAINER_POS_Y = 118.0f;
 | 
				
			||||||
constexpr float COMMON_PADDING_POS_X = 30.0f;
 | 
					
 | 
				
			||||||
constexpr float INFO_CONTAINER_POS_X = 870.0f;
 | 
					static constexpr float SETTINGS_WIDE_GRID_COUNT = 90.0f;
 | 
				
			||||||
 | 
					static constexpr float INFO_WIDE_GRID_COUNT = 42.0f;
 | 
				
			||||||
 | 
					static constexpr float PADDING_WIDE_GRID_COUNT = 3.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static constexpr float SETTINGS_NARROW_GRID_COUNT = 70.0f;
 | 
				
			||||||
 | 
					static constexpr float INFO_NARROW_GRID_COUNT = 34.0f;
 | 
				
			||||||
 | 
					static constexpr float PADDING_NARROW_GRID_COUNT = 1.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static constexpr int32_t g_categoryCount = 4;
 | 
					static constexpr int32_t g_categoryCount = 4;
 | 
				
			||||||
static int32_t g_categoryIndex;
 | 
					static int32_t g_categoryIndex;
 | 
				
			||||||
| 
						 | 
					@ -151,12 +157,18 @@ static void DrawScanlineBars()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE);
 | 
					    SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    float optionsX;
 | 
				
			||||||
 | 
					    if (g_aspectRatio >= WIDE_ASPECT_RATIO)
 | 
				
			||||||
 | 
					        optionsX = g_aspectRatioOffsetX;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        optionsX = (1.0f - g_narrowOffsetScale) * -20.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Options text
 | 
					    // Options text
 | 
				
			||||||
    DrawTextWithOutline
 | 
					    DrawTextWithOutline
 | 
				
			||||||
    (
 | 
					    (
 | 
				
			||||||
        g_dfsogeistdFont,
 | 
					        g_dfsogeistdFont,
 | 
				
			||||||
        Scale(48.0f),
 | 
					        Scale(48.0f),
 | 
				
			||||||
        { Scale(122.0f), Scale(56.0f) },
 | 
					        { Scale(optionsX + 122.0f), Scale(56.0f) },
 | 
				
			||||||
        IM_COL32(255, 190, 33, 255),
 | 
					        IM_COL32(255, 190, 33, 255),
 | 
				
			||||||
        Localise("Options_Header_Name").c_str(),
 | 
					        Localise("Options_Header_Name").c_str(),
 | 
				
			||||||
        4,
 | 
					        4,
 | 
				
			||||||
| 
						 | 
					@ -187,7 +199,7 @@ static void DrawScanlineBars()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static float AlignToNextGrid(float value)
 | 
					static float AlignToNextGrid(float value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return floor(value / GRID_SIZE) * GRID_SIZE;
 | 
					    return round(value / GRID_SIZE) * GRID_SIZE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void DrawContainer(ImVec2 min, ImVec2 max)
 | 
					static void DrawContainer(ImVec2 min, ImVec2 max)
 | 
				
			||||||
| 
						 | 
					@ -306,8 +318,11 @@ static bool DrawCategories()
 | 
				
			||||||
    auto clipRectMin = drawList->GetClipRectMin();
 | 
					    auto clipRectMin = drawList->GetClipRectMin();
 | 
				
			||||||
    auto clipRectMax = drawList->GetClipRectMax();
 | 
					    auto clipRectMax = drawList->GetClipRectMax();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr float NARROW_PADDING_GRID_COUNT = 1.5f;
 | 
				
			||||||
 | 
					    constexpr float WIDE_PADDING_GRID_COUNT = 3.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    float gridSize = Scale(GRID_SIZE);
 | 
					    float gridSize = Scale(GRID_SIZE);
 | 
				
			||||||
    float textPadding = gridSize * 3.0f;
 | 
					    float textPadding = gridSize * Lerp(NARROW_PADDING_GRID_COUNT, WIDE_PADDING_GRID_COUNT, g_narrowOffsetScale);
 | 
				
			||||||
    float tabPadding = gridSize;
 | 
					    float tabPadding = gridSize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    float size = Scale(32.0f);
 | 
					    float size = Scale(32.0f);
 | 
				
			||||||
| 
						 | 
					@ -449,8 +464,11 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
 | 
				
			||||||
    auto clipRectMax = drawList->GetClipRectMax();
 | 
					    auto clipRectMax = drawList->GetClipRectMax();
 | 
				
			||||||
    auto& padState = SWA::CInputState::GetInstance()->GetPadState();
 | 
					    auto& padState = SWA::CInputState::GetInstance()->GetPadState();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constexpr float OPTION_NARROW_GRID_COUNT = 36.0f;
 | 
				
			||||||
 | 
					    constexpr float OPTION_WIDE_GRID_COUNT = 54.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto gridSize = Scale(GRID_SIZE);
 | 
					    auto gridSize = Scale(GRID_SIZE);
 | 
				
			||||||
    auto optionWidth = gridSize * 54.0f;
 | 
					    auto optionWidth = gridSize * floor(Lerp(OPTION_NARROW_GRID_COUNT, OPTION_WIDE_GRID_COUNT, g_narrowOffsetScale));
 | 
				
			||||||
    auto optionHeight = gridSize * 5.5f;
 | 
					    auto optionHeight = gridSize * 5.5f;
 | 
				
			||||||
    auto optionPadding = gridSize * 0.5f;
 | 
					    auto optionPadding = gridSize * 0.5f;
 | 
				
			||||||
    auto valueWidth = Scale(192.0f);
 | 
					    auto valueWidth = Scale(192.0f);
 | 
				
			||||||
| 
						 | 
					@ -917,6 +935,7 @@ static void DrawConfigOptions()
 | 
				
			||||||
            DrawConfigOption(rowCount++, yOffset, &Config::GITextureFiltering, true);
 | 
					            DrawConfigOption(rowCount++, yOffset, &Config::GITextureFiltering, true);
 | 
				
			||||||
            DrawConfigOption(rowCount++, yOffset, &Config::MotionBlur, true);
 | 
					            DrawConfigOption(rowCount++, yOffset, &Config::MotionBlur, true);
 | 
				
			||||||
            DrawConfigOption(rowCount++, yOffset, &Config::XboxColorCorrection, true);
 | 
					            DrawConfigOption(rowCount++, yOffset, &Config::XboxColorCorrection, true);
 | 
				
			||||||
 | 
					            DrawConfigOption(rowCount++, yOffset, &Config::CutsceneAspectRatio, true);
 | 
				
			||||||
            DrawConfigOption(rowCount++, yOffset, &Config::UIScaleMode, true);
 | 
					            DrawConfigOption(rowCount++, yOffset, &Config::UIScaleMode, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					@ -998,13 +1017,11 @@ static void DrawConfigOptions()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void DrawSettingsPanel()
 | 
					static void DrawSettingsPanel(ImVec2 settingsMin, ImVec2 settingsMax)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto drawList = ImGui::GetForegroundDrawList();
 | 
					    auto drawList = ImGui::GetForegroundDrawList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImVec2 settingsMin = { Scale(AlignToNextGrid(COMMON_PADDING_POS_X)), Scale(AlignToNextGrid(COMMON_PADDING_POS_Y)) };
 | 
					    SetProceduralOrigin(settingsMin);
 | 
				
			||||||
    ImVec2 settingsMax = { Scale(AlignToNextGrid(INFO_CONTAINER_POS_X - COMMON_PADDING_POS_X)), Scale(AlignToNextGrid(720.0f - COMMON_PADDING_POS_Y)) };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    DrawContainer(settingsMin, settingsMax);
 | 
					    DrawContainer(settingsMin, settingsMax);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (DrawCategories())
 | 
					    if (DrawCategories())
 | 
				
			||||||
| 
						 | 
					@ -1018,31 +1035,34 @@ static void DrawSettingsPanel()
 | 
				
			||||||
        ResetSelection();
 | 
					        ResetSelection();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ResetProceduralOrigin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Pop clip rect from DrawContainer
 | 
					    // Pop clip rect from DrawContainer
 | 
				
			||||||
    drawList->PopClipRect();
 | 
					    drawList->PopClipRect();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void DrawInfoPanel()
 | 
					static void DrawInfoPanel(ImVec2 infoMin, ImVec2 infoMax)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto drawList = ImGui::GetForegroundDrawList();
 | 
					    auto drawList = ImGui::GetForegroundDrawList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImVec2 infoMin = { Scale(AlignToNextGrid(INFO_CONTAINER_POS_X)), Scale(AlignToNextGrid(COMMON_PADDING_POS_Y)) };
 | 
					    SetProceduralOrigin(infoMin);
 | 
				
			||||||
    ImVec2 infoMax = { Scale(AlignToNextGrid(1280.0f - COMMON_PADDING_POS_X)), Scale(AlignToNextGrid(720.0f - COMMON_PADDING_POS_Y)) };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    DrawContainer(infoMin, infoMax);
 | 
					    DrawContainer(infoMin, infoMax);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto clipRectMin = drawList->GetClipRectMin();
 | 
					    auto clipRectMin = drawList->GetClipRectMin();
 | 
				
			||||||
    auto clipRectMax = drawList->GetClipRectMax();
 | 
					    auto clipRectMax = drawList->GetClipRectMax();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ImVec2 thumbnailMax = { clipRectMax.x, clipRectMin.y + Scale(198.0f) };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (g_selectedItem)
 | 
					    if (g_selectedItem)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto desc = g_selectedItem->GetDescription(Config::Language);
 | 
					        auto desc = g_selectedItem->GetDescription(Config::Language);
 | 
				
			||||||
        auto thumbnail = GetThumbnail(g_selectedItem);
 | 
					        auto thumbnail = GetThumbnail(g_selectedItem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (thumbnail)
 | 
					        float aspectRatio = float(thumbnail->width) / thumbnail->height;
 | 
				
			||||||
            drawList->AddImage(thumbnail, clipRectMin, thumbnailMax);
 | 
					        float thumbnailHeight = (clipRectMax.x - clipRectMin.x) / aspectRatio;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ImVec2 thumbnailMin = { clipRectMin.x, clipRectMin.y + Scale(GRID_SIZE / 2.0f) };
 | 
				
			||||||
 | 
					        ImVec2 thumbnailMax = { clipRectMax.x, thumbnailMin.y + thumbnailHeight };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        drawList->AddImage(thumbnail, thumbnailMin, thumbnailMax);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (g_inaccessibleReason)
 | 
					        if (g_inaccessibleReason)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
| 
						 | 
					@ -1057,8 +1077,8 @@ static void DrawInfoPanel()
 | 
				
			||||||
                auto resScale = round(*(float*)g_selectedItem->GetValue() * 1000) / 1000;
 | 
					                auto resScale = round(*(float*)g_selectedItem->GetValue() * 1000) / 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                std::snprintf(buf, sizeof(buf), desc.c_str(),
 | 
					                std::snprintf(buf, sizeof(buf), desc.c_str(),
 | 
				
			||||||
                    (int)((float)GameWindow::s_width * resScale),
 | 
					                    (int)((float)Video::s_viewportWidth * resScale),
 | 
				
			||||||
                    (int)((float)GameWindow::s_height * resScale));
 | 
					                    (int)((float)Video::s_viewportHeight * resScale));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                desc = buf;
 | 
					                desc = buf;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1080,6 +1100,8 @@ static void DrawInfoPanel()
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ResetProceduralOrigin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Pop clip rect from DrawContainer
 | 
					    // Pop clip rect from DrawContainer
 | 
				
			||||||
    drawList->PopClipRect();
 | 
					    drawList->PopClipRect();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1197,8 +1219,25 @@ void OptionsMenu::Draw()
 | 
				
			||||||
            drawList->AddRectFilled({ 0.0f, 0.0f }, res, IM_COL32(0, 0, 0, 223));
 | 
					            drawList->AddRectFilled({ 0.0f, 0.0f }, res, IM_COL32(0, 0, 0, 223));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        DrawScanlineBars();
 | 
					        DrawScanlineBars();
 | 
				
			||||||
        DrawSettingsPanel();
 | 
					
 | 
				
			||||||
        DrawInfoPanel();
 | 
					        float settingsGridCount = floor(Lerp(SETTINGS_NARROW_GRID_COUNT, SETTINGS_WIDE_GRID_COUNT, g_narrowOffsetScale));
 | 
				
			||||||
 | 
					        float paddingGridCount = Lerp(PADDING_NARROW_GRID_COUNT, PADDING_WIDE_GRID_COUNT, g_narrowOffsetScale);
 | 
				
			||||||
 | 
					        float infoGridCount = floor(Lerp(INFO_NARROW_GRID_COUNT, INFO_WIDE_GRID_COUNT, g_narrowOffsetScale));
 | 
				
			||||||
 | 
					        float totalGridCount = settingsGridCount + paddingGridCount + infoGridCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        float offsetX = g_aspectRatioOffsetX + (1280.0f - ((GRID_SIZE * totalGridCount) - 1)) / 2.0f;
 | 
				
			||||||
 | 
					        float minY = Scale(g_aspectRatioOffsetY + CONTAINER_POS_Y);
 | 
				
			||||||
 | 
					        float maxY = Scale(g_aspectRatioOffsetY + (720.0f - CONTAINER_POS_Y + 1.0f));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DrawSettingsPanel(
 | 
				
			||||||
 | 
					            { Scale(offsetX), minY },
 | 
				
			||||||
 | 
					            { Scale(offsetX + settingsGridCount * GRID_SIZE), maxY }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DrawInfoPanel(
 | 
				
			||||||
 | 
					            { Scale(offsetX + (settingsGridCount + paddingGridCount) * GRID_SIZE), minY },
 | 
				
			||||||
 | 
					            { Scale(offsetX + totalGridCount * GRID_SIZE), maxY }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (g_isStage)
 | 
					        if (g_isStage)
 | 
				
			||||||
            DrawFadeTransition();
 | 
					            DrawFadeTransition();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,15 +148,17 @@ CONFIG_DEFINE_ENUM_TEMPLATE(EWindowState)
 | 
				
			||||||
enum class EAspectRatio : uint32_t
 | 
					enum class EAspectRatio : uint32_t
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Auto,
 | 
					    Auto,
 | 
				
			||||||
    Square,
 | 
					    Wide,
 | 
				
			||||||
    Widescreen
 | 
					    Narrow,
 | 
				
			||||||
 | 
					    OriginalNarrow
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_DEFINE_ENUM_TEMPLATE(EAspectRatio)
 | 
					CONFIG_DEFINE_ENUM_TEMPLATE(EAspectRatio)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    { "Auto", EAspectRatio::Auto },
 | 
					    { "Auto", EAspectRatio::Auto },
 | 
				
			||||||
    { "4:3",  EAspectRatio::Square },
 | 
					    { "16:9", EAspectRatio::Wide },
 | 
				
			||||||
    { "16:9", EAspectRatio::Widescreen }
 | 
					    { "4:3",  EAspectRatio::Narrow },
 | 
				
			||||||
 | 
					    { "Original 4:3",  EAspectRatio::OriginalNarrow },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class ETripleBuffering : uint32_t
 | 
					enum class ETripleBuffering : uint32_t
 | 
				
			||||||
| 
						 | 
					@ -256,16 +258,26 @@ CONFIG_DEFINE_ENUM_TEMPLATE(EMotionBlur)
 | 
				
			||||||
    { "Enhanced", EMotionBlur::Enhanced }
 | 
					    { "Enhanced", EMotionBlur::Enhanced }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum class ECutsceneAspectRatio : uint32_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Original,
 | 
				
			||||||
 | 
					    Unlocked
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONFIG_DEFINE_ENUM_TEMPLATE(ECutsceneAspectRatio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    { "Original", ECutsceneAspectRatio::Original },
 | 
				
			||||||
 | 
					    { "Unlocked", ECutsceneAspectRatio::Unlocked }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum class EUIScaleMode : uint32_t
 | 
					enum class EUIScaleMode : uint32_t
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    Stretch,
 | 
					 | 
				
			||||||
    Edge,
 | 
					    Edge,
 | 
				
			||||||
    Centre
 | 
					    Centre
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_DEFINE_ENUM_TEMPLATE(EUIScaleMode)
 | 
					CONFIG_DEFINE_ENUM_TEMPLATE(EUIScaleMode)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    { "Stretch", EUIScaleMode::Stretch },
 | 
					 | 
				
			||||||
    { "Edge",    EUIScaleMode::Edge },
 | 
					    { "Edge",    EUIScaleMode::Edge },
 | 
				
			||||||
    { "Centre",  EUIScaleMode::Centre },
 | 
					    { "Centre",  EUIScaleMode::Centre },
 | 
				
			||||||
    { "Center",  EUIScaleMode::Centre }
 | 
					    { "Center",  EUIScaleMode::Centre }
 | 
				
			||||||
| 
						 | 
					@ -661,6 +673,7 @@ public:
 | 
				
			||||||
    CONFIG_DEFINE_ENUM("Video", EDepthOfFieldQuality, DepthOfFieldQuality, EDepthOfFieldQuality::Auto);
 | 
					    CONFIG_DEFINE_ENUM("Video", EDepthOfFieldQuality, DepthOfFieldQuality, EDepthOfFieldQuality::Auto);
 | 
				
			||||||
    CONFIG_DEFINE_ENUM_LOCALISED("Video", EMotionBlur, MotionBlur, EMotionBlur::Original);
 | 
					    CONFIG_DEFINE_ENUM_LOCALISED("Video", EMotionBlur, MotionBlur, EMotionBlur::Original);
 | 
				
			||||||
    CONFIG_DEFINE_LOCALISED("Video", bool, XboxColorCorrection, false);
 | 
					    CONFIG_DEFINE_LOCALISED("Video", bool, XboxColorCorrection, false);
 | 
				
			||||||
 | 
					    CONFIG_DEFINE_ENUM_LOCALISED("Video", ECutsceneAspectRatio, CutsceneAspectRatio, ECutsceneAspectRatio::Original);
 | 
				
			||||||
    CONFIG_DEFINE_ENUM_LOCALISED("Video", EUIScaleMode, UIScaleMode, EUIScaleMode::Edge);
 | 
					    CONFIG_DEFINE_ENUM_LOCALISED("Video", EUIScaleMode, UIScaleMode, EUIScaleMode::Edge);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CONFIG_DEFINE_HIDDEN("Exports", bool, AllowCancellingUnleash, false);
 | 
					    CONFIG_DEFINE_HIDDEN("Exports", bool, AllowCancellingUnleash, false);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,16 +91,14 @@ registers = ["r11"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[midasm_hook]]
 | 
					[[midasm_hook]]
 | 
				
			||||||
name = "CameraAspectRatioMidAsmHook"
 | 
					name = "CameraAspectRatioMidAsmHook"
 | 
				
			||||||
address = 0x82468E84
 | 
					address = 0x82468E78
 | 
				
			||||||
registers = ["r31"]
 | 
					registers = ["r30", "r31"]
 | 
				
			||||||
jump_address_on_true = 0x82468E88
 | 
					 | 
				
			||||||
jump_address_on_false = 0x82468EE0
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[midasm_hook]]
 | 
					[[midasm_hook]]
 | 
				
			||||||
name = "CameraBoostAspectRatioMidAsmHook"
 | 
					name = "CameraFieldOfViewMidAsmHook"
 | 
				
			||||||
address = 0x8246BDA0
 | 
					address = 0x82468EDC
 | 
				
			||||||
registers = ["r31", "f0", "f10", "f12"]
 | 
					registers = ["r31", "f31"]
 | 
				
			||||||
jump_address_on_true = 0x8246BDAC
 | 
					jump_address = 0x82468EE0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[midasm_hook]]
 | 
					[[midasm_hook]]
 | 
				
			||||||
name = "ResetScoreOnRestartMidAsmHook"
 | 
					name = "ResetScoreOnRestartMidAsmHook"
 | 
				
			||||||
| 
						 | 
					@ -590,3 +588,78 @@ jump_address = 0x82B723BC
 | 
				
			||||||
name = "DisableDLCIconMidAsmHook"
 | 
					name = "DisableDLCIconMidAsmHook"
 | 
				
			||||||
address = 0x825756B0
 | 
					address = 0x825756B0
 | 
				
			||||||
jump_address_on_true = 0x825756E0
 | 
					jump_address_on_true = 0x825756E0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "MakeCsdProjectMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x825E4120
 | 
				
			||||||
 | 
					registers = ["r3", "r29"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "RenderCsdCastNodeMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x830C6A58
 | 
				
			||||||
 | 
					registers = ["r10", "r27"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "RenderCsdCastMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x830C6A98
 | 
				
			||||||
 | 
					registers = ["r4"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "ComputeScreenPositionMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x82923204
 | 
				
			||||||
 | 
					registers = ["f1", "f2"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "ComputeScreenPositionMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x82AD7914
 | 
				
			||||||
 | 
					registers = ["f1", "f2"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "WorldMapInfoMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x8257AF34
 | 
				
			||||||
 | 
					registers = ["r4"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "AddPrimitive2DMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x824DB3E4
 | 
				
			||||||
 | 
					registers = ["r3"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "ObjGetItemFieldOfViewMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x82692934
 | 
				
			||||||
 | 
					registers = ["r1", "f1"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "WorldMapProjectionMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x82574E00
 | 
				
			||||||
 | 
					registers = ["v63", "v62"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "ViewRingFieldOfViewMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x825EBDF0
 | 
				
			||||||
 | 
					registers = ["r1", "f1"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "ViewRingYMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x825EBF1C
 | 
				
			||||||
 | 
					registers = ["f0"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "ViewRingXMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x825EBF68
 | 
				
			||||||
 | 
					registers = ["f0", "v62"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "InspireLetterboxTopMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x82B8AB78
 | 
				
			||||||
 | 
					registers = ["r3"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "InspireLetterboxBottomMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x82B8ABAC
 | 
				
			||||||
 | 
					registers = ["r3"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[midasm_hook]]
 | 
				
			||||||
 | 
					name = "InspireSubtitleMidAsmHook"
 | 
				
			||||||
 | 
					address = 0x82B949B0
 | 
				
			||||||
 | 
					registers = ["r3"]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue