require(GlobalDependencys:GetDependency("StandardBase"):GetPackageName())

--GAME VARS
fAdditionalFOV = 0

--ControlVars
bFixEnabled = true
bAspectRatio = true
Aspect_Changed = false
bDOF = true
bFOV = true
bHUDScale = true
FOVValue = 90
HUDScaleValue = 1
dummyValue = 15
DefaultScaleValue = 1
Default_AspectRatio = 1.777777791
AspectRatioScale = 1

--PROCESS VARS
Process_FriendlyName = Module:GetFriendlyName()
Process_WindowName = "Horizon Zero Dawn: Complete Edition"
Process_ClassName = "*"
Process_EXEName = "HorizonZeroDawn.exe"

--INJECTION BEHAVIOUR
InjectDelay = 1500
WriteInterval = 500
SearchInterval = 500
SuspendThread = true

--Name                         Manual/Auto/Hybrid  		Steam/Origin/Any                IncludeFile:Configure;Enable;Periodic;Disable;
SupportedVersions = { 		
{"Automatically Detect",       "Manual",  			"Any",	                         "Configure_SignatureScan;Enable_Inject;Periodic;Disable_Inject;"},
}

function Init_Controls()

	DefaultControls.AddHeader("Header_FOV","FOV Fine adjustment",15,70,210,17)
	
	DefaultControls.AddFixedFOVSlider("FOVSlider","FOVSlider_Changed",55,100,125,35,40,160,0,1)
	FOVSlider:SetTickFrequency(15)
	FOVSlider:SetLabel1Text("40")
	FOVSlider:SetLabel2Text("160")

	DefaultControls.AddHeader("Header_HUDScale","HUD Scale Multiplier adjustment",15,155,210,17)
	
	DefaultControls.AddFixedFOVSlider("HUDScaleSlider","HUDScaleSlider_Changed",55,175,125,35,40,160,0,1)
	HUDScaleSlider:SetTickFrequency(15)
	HUDScaleSlider:SetLabel1Text("0.4")
	HUDScaleSlider:SetLabel2Text("1.6")

	DefaultControls.AddHeader("Header_FixesEnableDisable","Individual Fixes",245,70,210,17)
	DefaultControls.AddFixToggle("CKAspectFix_Enable","Aspect Fix","CKAspectFix_Changed",255,101,180,14)
	DefaultControls.AddFixToggle("FOV_Enable","FOV adjustment fix","FOV_Changed",255,121,180,14)
	DefaultControls.AddFixToggle("HUDScale_Enable","HUD Scale adjustment fix","HUDScale_Changed",255,141,180,14)
	DefaultControls.AddFixToggle("CKDOFFix_Enable","Remove DOF","CKDOFFix_Changed",255,161,180,14)

end

function Configure_SignatureScan() 
	
	local tAddress = HackTool:AddAddress("DOF")	
	
	if HackTool:SignatureScan("74 64 41 83 F8 01",tAddress,PAGE_EXECUTE_READ,0x00,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )
	end
	
	local tAddress = HackTool:AddAddress("AspectRatio")
	
	
	if HackTool:SignatureScan("99 99 A9 3F 39 8E E3 3F 00 00",tAddress,PAGE_READONLY,0x00,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )
		tAddress:AddSubOffset("ARatio",0x4)
		
		Default_AspectRatio = tAddress["ARatio"]:ReadFloat()
	
		tAddress["ARatio"]:SetAutoUnprotect(true)
		
		Aspect_Defaults = true
	end
	
	local tAddress = HackTool:AddAddress("AspectRatio2")
	
	if HackTool:SignatureScan("F3 0F 10 8B ?? ?? ?? ?? 0F 57 D2 F3 0F 59",tAddress,PAGE_EXECUTE_READ,0x00,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )
	end
	
	local tAddress = HackTool:AddAddress("AspectRatio3")
	
	if HackTool:SignatureScan("F3 0F 10 80 80 2F 00 00",tAddress,PAGE_EXECUTE_READ,0x00,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )
	end
	
	local tAddress = HackTool:AddAddress("AspectRatio4")
	
	if HackTool:SignatureScan("F3 0F 10 80 84 2F 00 00",tAddress,PAGE_EXECUTE_READ,0x00,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )
	end

	local tAddress = HackTool:AddAddress("AspectRatio5")
	
	if HackTool:SignatureScan("F3 45 0F 11 85 ?? ?? ?? ?? 0F 84",tAddress,PAGE_EXECUTE_READ,0x00,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )
	end
	
	local tAddress = HackTool:AddAddress("AspectRatio6")
	
	if HackTool:SignatureScan("F3 45 0F 11 85 ?? ?? ?? ?? 44 0F",tAddress,PAGE_EXECUTE_READ,0x00,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )
	end
	
	local tAddress = HackTool:AddAddress("FOV")
	
	if HackTool:SignatureScan("F3 0F 2A 88 ?? ?? ?? ?? 0F 28 C1",tAddress,PAGE_EXECUTE_READ,0x00,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else	
		print( tAddress:GetInfo(TYPE_ADDRESS) )		
	end
	
	local tAddress = HackTool:AddAddress("HUDScale")
	
	if HackTool:SignatureScan("F3 0F 5E 05 ?? ?? ?? ?? F3 0F 5D C8 41 0F",tAddress,PAGE_EXECUTE_READ,0x00,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )		
	end
	
	local tAddress = HackTool:AddAddress("HUDScale2")
	
	if HackTool:SignatureScan("8B 88 90 01 00 00 41 89 8D",tAddress,PAGE_EXECUTE_READ,0x00,Process_EXEName) == 0 then	
	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )		
	end
		
	return true

end


function Enable_Inject() 

	local Variables = HackTool:AllocateMemory("Variables",0)
	Variables:PushFloat("FOV")
	Variables:PushFloat("HUDScale")
	Variables:PushFloat("DUMMYValue")
	Variables:PushFloat("ScaleValue")
	Variables:PushFloat("AspectRatioScale")
	Variables:PushFloat("DefaultAspectRatio")
	Variables:Allocate()
	
	Variables["DUMMYValue"]:WriteFloat(dummyValue)
	Variables["ScaleValue"]:WriteFloat(DefaultScaleValue)
	Variables["DefaultAspectRatio"]:WriteFloat(Default_AspectRatio)
	
	local AspectRatio = DisplayInfo:GetAspectRatio()
	AspectRatioScale = Default_AspectRatio / AspectRatio
	
	Variables["AspectRatioScale"]:WriteFloat(AspectRatioScale)
	
	WriteFOV()
	WriteHUDScale()
	
	local asm = [[
	
			
		(codecave:jmp)AspectRatio2,AspectRatio2_cc:
			movss xmm1,[(allocation)Variables->AspectRatioScale]
			jmp %returnaddress%
			%end%
		
		(codecave:jmp)AspectRatio3,AspectRatio3_cc:
			movss xmm0,[(allocation)Variables->AspectRatioScale]
			jmp %returnaddress%
			%end%
	
		(codecave:jmp)AspectRatio4,AspectRatio4_cc:
			movss xmm0,[(allocation)Variables->ScaleValue]
			jmp %returnaddress%
			%end%
		
		(codecave:jmp)AspectRatio5,AspectRatio5_cc:
			movss xmm8,[(allocation)Variables->ScaleValue]
			%originalcode%
			jmp %returnaddress%
			%end%
		
		(codecave:jmp)AspectRatio6,AspectRatio6_cc:
			movss xmm8,[(allocation)Variables->DefaultAspectRatio]
			%originalcode%
			jmp %returnaddress%
			%end%
		
		(codecave:jmp)FOV,FOV_cc:
			movss xmm1,[(allocation)Variables->FOV]
			cvtps2dq xmm1,xmm1
			movss [rax+00000340],xmm1
			%originalcode%
			jmp %returnaddress%
			%end%
	
			;	HorizonZeroDawn.exe+119438F: 0F 57 C9                    - xorps xmm1,xmm1
			; ---------- INJECTING HERE ----------
			;	HorizonZeroDawn.exe+1194392: F3 0F 2A 88 54 01 00 00     - cvtsi2ss xmm1,[rax+00000154]
			; ---------- DONE INJECTING  ----------
			;	HorizonZeroDawn.exe+119439A: 0F 28 C1                    - movaps xmm0,xmm1

		(codecave:jmp)HUDScale,HUDScale_cc:
			%originalcode%
			movss xmm0,[(allocation)Variables->DUMMYValue]
			movss xmm1,[(allocation)Variables->HUDScale]
			jmp %returnaddress%
			%end%
			
			;	HorizonZeroDawn.exe+13C78C0: F3 0F 5E 05 54 ED 6D 00     - divss xmm0,[HorizonZeroDawn.exe+1AA661C]
			; ---------- INJECTING HERE ----------
			;	HorizonZeroDawn.exe+13C78C8: F3 0F 5D C8                 - minss xmm1,xmm0
			; ---------- DONE INJECTING  ----------
			;	HorizonZeroDawn.exe+13C78CC: 41 0F 2E 8D 7C 04 00 00     - ucomiss xmm1,[r13+0000047C]
			

		(codecave:jmp)HUDScale2,HUDScale2_cc:
			mov ecx,[(allocation)Variables->ScaleValue]
			jmp %returnaddress%
			%end%
			
			;	HorizonZeroDawn.exe+13C78FF: 48 8B 05 0A 4F D8 05        - mov rax,[HorizonZeroDawn.exe+714C810]
			; ---------- INJECTING HERE ----------
			;	HorizonZeroDawn.exe+13C7906: 8B 88 90 01 00 00           - mov ecx,[rax+00000190]
			; ---------- DONE INJECTING  ----------
			;	HorizonZeroDawn.exe+13C790C: 41 89 8D 80 04 00 00        - mov [r13+00000480],ecx
			
		(codecave)DOF,DOF_cc:
			jmp $$1														   $ctx=1
			%end%
			
			;	HorizonZeroDawn.exe+71DC38: 45 85 C0                    - test r8d,r8d
			; ---------- INJECTING HERE ----------
			;	HorizonZeroDawn.exe+71DC3B: 74 64                       - je HorizonZeroDawn.exe+71DCA1
			; ---------- DONE INJECTING  ----------
			;	HorizonZeroDawn.exe+71DC3D: 41 83 F8 01                 - cmp r8d,01
			

	]]
	
	if HackTool:CompileAssembly(asm,"FOV") == nil then
		return ErrorOccurred("Assembly compilation failed...")
	else
		Toggle_CodeCave("DOF_cc",bDOF)
		Toggle_CodeCave("AspectRatio2_cc",bAspectRatio)
		Toggle_CodeCave("AspectRatio3_cc",bAspectRatio)
		Toggle_CodeCave("AspectRatio4_cc",bAspectRatio)
		Toggle_CodeCave("AspectRatio5_cc",bAspectRatio)
		Toggle_CodeCave("AspectRatio6_cc",bAspectRatio)
		Toggle_CodeCave("FOV_cc",bFOV)
		Toggle_CodeCave("HUDScale_cc",bHUDScale)
		Toggle_CodeCave("HUDScale2_cc",bHUDScale)
		
		if bAspectRatio then
			WriteAspectRatio()
		end
	end	
	
end

function Periodic()

	local AspectRatio = HackTool:GetAddress("AspectRatio")	
	local Variables = HackTool:GetAllocation("Variables")
	
	if AspectRatio and AspectRatio["ARatio"] then
		PluginViewport:AppendStatusMessage( string.format("\r\n===== Fix informations =====\r\nCutscenes aspect ratio %.2f\r\n", AspectRatio["ARatio"]:ReadFloat() ) )
	end
	
end

function Disable_Inject()
	
	RestoreAspectDefault()
	CleanUp()
	
end

function CKDOFFix_Changed(Sender)
	bDOF = Toggle_CheckFix(Sender)
	Toggle_CodeCave("DOF_cc",bDOF)
end

function CKAspectFix_Changed(Sender)
	bAspectRatio = Toggle_CheckFix(Sender)
	Toggle_CodeCave("AspectRatio2_cc",bAspectRatio)
	Toggle_CodeCave("AspectRatio3_cc",bAspectRatio)
	Toggle_CodeCave("AspectRatio4_cc",bAspectRatio)
	Toggle_CodeCave("AspectRatio5_cc",bAspectRatio)
	Toggle_CodeCave("AspectRatio6_cc",bAspectRatio)

	if bAspectRatio == true then
		WriteAspectRatio()
    else
		RestoreAspectDefault()
	end
	
	ForceUpdate()
end

function WriteAspectRatio()

	local AspectRatio = HackTool:GetAddress("AspectRatio")
	
	if AspectRatio and AspectRatio["ARatio"] then
		AspectRatio["ARatio"]:WriteFloat(DisplayInfo:GetAspectRatio())
	end
	
end

function RestoreAspectDefault()

	local AspectRatio = HackTool:GetAddress("AspectRatio")
	if AspectRatio and AspectRatio["ARatio"] and Aspect_Defaults == true then
		AspectRatio["ARatio"]:WriteFloat(Default_AspectRatio)
		
		print("Restored AspectRatio defaults")
	end

	Aspect_Changed = false

end

function FOV_Changed(Sender)
	bFOV = Toggle_CheckFix(Sender)
	Toggle_CodeCave("FOV_cc",bFOV)
	
	if bFOV then
		local FOV = FOVSlider:GetPosition()
		FOVValue = FOV
	end
	WriteFOV()
	ForceUpdate()
	
end

function FOVSlider_Changed(Sender)

	local FOV = Sender:GetPosition()
	local Variables = HackTool:GetAllocation("Variables")
	lblFOVSlider.Caption:SetCaption( string.format("Value: %.0f",FOV) )
	
	if bFOV then
		FOVValue = FOV
		WriteFOV()
	end
	
	ForceUpdate()

end

function HUDScale_Changed(Sender)

	bHUDScale = Toggle_CheckFix(Sender)
	bHUDScale2 = Toggle_CheckFix(Sender)
	Toggle_CodeCave("HUDScale_cc",bHUDScale)
	Toggle_CodeCave("HUDScale2_cc",bHUDScale)
	
	WriteHUDScale()
	ForceUpdate()

end

function HUDScaleSlider_Changed(Sender)
	local HUDScale = Sender:GetPosition()
	HUDScale = HUDScale / 100
	lblHUDScaleSlider.Caption:SetCaption( string.format("Value : %.2f",(HUDScale)))
	
	if bHUDScale then
		HUDScaleValue = HUDScale
		WriteHUDScale()
	end
	
	ForceUpdate()	
end

function WriteFOV()
	local Variables = HackTool:GetAllocation("Variables")
	
	if Variables and Variables["FOV"] then
		Variables["FOV"]:WriteFloat(FOVValue)
	end
	
end

function WriteHUDScale()

	local Variables = HackTool:GetAllocation("Variables")
	
	if Variables and Variables["HUDScale"] then
		Variables["HUDScale"]:WriteFloat(HUDScaleValue)
	end

end

function ResolutionChanged() 

end

function Init()	

	Init_BaseControls()
	Init_Controls()
	
end

function DeInit()

	DisableFix()
	
end
