Okay, kids, remember this?
Well.. I kinda got bored of it and wanted to go still
Screw the story, right? What if you break it?..
To get to a function that would bypass this restriction you first start with some brainstorming. Some people will say "find player's XYZ and debug that and see what accesses them when you enter such an area". Well, XYZ are accessed by a lot of functions that your expectation - that when a restricted area drops the message, only 1 piece of code extra from what you have in the debug window will pop - really won't be met. What else can we do? Well, there's a message on screen. It reads "You are leaving the play area". With that in mind, let's scan the memory for an occurrence of that string, then debug that. The string should be accessed ONLY when the message is displayed. Then from what accesses it we can back-trace through code and see what's the trigger/reason this is displayed. The most common way to see if some function you're at does the job is to make it not execute. And that means change the function's prologue with a RET instruction.
So I scanned the memory for the string and found 1 result (yes, your address will be different):
Then I set a breakpoint on access on the first byte of the string in hex dump and went ahead, triggering the message to show on-screen. And I got this:
Now.. if you go to that specific address and set a normal breakpoint, you will see there are a LOT of breaks. Why.. because it's a generic readstring function. What we want to happen is set a conditional breakpoint that gets hit only when OUR string is read. So.. my address is
27CCAE5D1F0. The place where it's read is:
Code: Select all
HorizonZeroDawn.exe+11DD9C - 44 0FB6 0B - movzx r9d,byte ptr [rbx]
First make sure the message is not shown on screen yet (move back a little). Then go to "HorizonZeroDawn.exe+11DD9C", press F5. CE will break. Then right-click, "Set/Change break condition" and type in
RBX == 0x27CCAE5D1F0 (of course, change the address with yours!). Now F9 to resume. If the message was already displayed on screen, then move back so it disappears, then return so it appears again. That's when CE will break again.
When it does break hit Shift+F8
6 times (how did I know? I back-traced the first 5 steps and saw they didn't work how I wanted). You will be here now:
Code: Select all
HorizonZeroDawn.exe+C94AAF - 49 8B D6 - mov rdx,r14
HorizonZeroDawn.exe+C94AB2 - E8 F95296FF - call HorizonZeroDawn.exe+5F9DB0 <-- this is where we exited from
HorizonZeroDawn.exe+C94AB7 - 4C 89 25 02FE4806 - mov [HorizonZeroDawn.exe+71248C0],r12 { (2826A269620) } <-- here
HorizonZeroDawn.exe+C94ABE - 48 83 C4 28 - add rsp,28 { 40 }
HorizonZeroDawn.exe+C94AC2 - 41 5E - pop r14
HorizonZeroDawn.exe+C94AC4 - 41 5C - pop r12
HorizonZeroDawn.exe+C94AC6 - C3 - ret
What Shift+F8 does is:
Now scroll up top to the function's prologue, here:
Code: Select all
HorizonZeroDawn.exe+C949E0 - 41 54 - push r12
HorizonZeroDawn.exe+C949E2 - 41 56 - push r14
HorizonZeroDawn.exe+C949E4 - 48 83 EC 28 - sub rsp,28 { 40 }
HorizonZeroDawn.exe+C949E8 - 48 63 81 38010000 - movsxd rax,dword ptr [rcx+00000138]
HorizonZeroDawn.exe+C949EF - 45 33 E4 - xor r12d,r12d
And place a RET where you see "push r12":
Code: Select all
HorizonZeroDawn.exe+C949E0 - C3 - ret
HorizonZeroDawn.exe+C949E1 - 90 - nop
HorizonZeroDawn.exe+C949E2 - 41 56 - push r14
HorizonZeroDawn.exe+C949E4 - 48 83 EC 28 - sub rsp,28 { 40 }
HorizonZeroDawn.exe+C949E8 - 48 63 81 38010000 - movsxd rax,dword ptr [rcx+00000138]
HorizonZeroDawn.exe+C949EF - 45 33 E4 - xor r12d,r12d
Then you'll see you can walk indefinitely in an area that's restricted, message won't show up and no loading of your latest quick-save.
So this is how I did it.
Here's an example. I am here:
The moment I advance 1-2m forward, I get this:
So I RET the function I mentioned and.. after a while of walking:
What you need to remember is the function is constantly executed when you are out of bounds. That means when you get to where you wanted to go, DON'T restore the code. It will instantly run a quick-load without warning you. First exit the area you know if off limits, then restore/disable the code/script.
You can also go in "black" areas of the map
They're represented like that, but in reality.. nothing black there:
In a similar way I believe you can do this kind of message:
Just know there's an invisible wall that prevents you from moving further, aside from that message showing up (although there's no quick-load of latest save).
BR,
Sun