Skip to content

Instantly share code, notes, and snippets.

@FransBouma
Last active December 1, 2016 15:35
Show Gist options
  • Save FransBouma/0bd2e816bfa31d8be29c0906512b6262 to your computer and use it in GitHub Desktop.
Save FransBouma/0bd2e816bfa31d8be29c0906512b6262 to your computer and use it in GitHub Desktop.
Darksiders II CT. Thread-based camera movement based on look vector. Based on DET/Jim2Point0's table.
<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="21">
<CheatEntries>
<CheatEntry>
<ID>10992</ID>
<Description>"Camera system. Toggle: INS. Enable first to use fov/freecam"</Description>
<LastState/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>//----------------------------------------------------------
// Reworked Darksiders II cheat table with free camera / timestop / FoV
// By Otis / Infuse Project
//
// Based on DeadEndThrill's original CT with hacks for free camera / timestop / FoV (by Jim2Point0, Duncan Harris and others)
// this table contains a thread based camera movement system which moves the camera based on the camera look vector direction
// so pressing e.g. 'left' (numpad 4) is moving the camera left, you're no longer moving over the world x/y/z axis which don't align with
// the camera direction in most cases.
//
// I've commented a lot of code in this table. For seasoned assembly programmers these comments might sound like 'water is wet' statements,
// but they might help the novice assembly programmer out what's going on (as SIMD programmer isn't straightforward!) :)
// The features are enabled / disabled by two child scripts, one for the FoV and one for the camera hook.
// This is done so the thread loop can run at almost full speed scanning keys and it's also easier to enable e.g. FoV without the
// camera.
//----------------------------------------------------------
[ENABLE]
globalalloc(OwnCode, 2048) // alloc memory for our code, once.
createthread(MainThread) // creates a new thread in the attached process and starts at MainThread.
// make sure it terminates when [DISABLE] is ran, otherwise a new one will be
// created when you re-enable the camera system. In this table, this is done by
// the _disableThread byte, which is set to 1 when the thread has to terminate
// and which is checked two times in the thread (begin/end).
//----------------------------------------------------------
// Code labels
label(MainThread)
// Data labels
label(_disableThread)
label(_cameraStruct)
label(_cameraX)
label(_cameraY)
label(_cameraZ)
label(_cameraW)
label(_fovEnabled)
label(_altPressed)
label(_ctrlPressed)
// Symbols. Registering them allows you to use them in the CE UI.
registersymbol(_disableThread)
registersymbol(_cameraStruct)
registersymbol(_cameraX)
registersymbol(_cameraY)
registersymbol(_cameraZ)
registersymbol(_fovEnabled)
registersymbol(_altPressed)
registersymbol(MainThread)
// overwrite inside the darksiders2 process the following address with a jmp to our code which grabs the FoV address
// which is in the register EAX.
"Darksiders2.exe"+EB34C:
jmp GrabCameraStructAddress
ReturnAfterFoVGrab:
OwnCode:
// FoV
// new code to grab FoV address, which is inside the camera struct we need.
GrabCameraStructAddress:
mov [_cameraStruct],eax
cmp byte [_fovEnabled], 1
jz @f // continue at next unnamed label (which is @@)
fstp dword ptr [eax+4C] // original code, fov not enabled.
@@:
pop esi // original code
leave // original code
jmp ReturnAfterFoVGrab // continue with original game code.
//---------------------------------------------------------
// Code
MainThread:
// 32bit so use this approach to wait a couple of ms. If 64bit, you need: mov rcx, milliseconds
push #25
call Sleep
// check if the thread can die
cmp byte [_disableThread], 1
je MainThread_End // disabled, die
// check if the camera struct is already available. If not, loop to the beginning of the thread,
// which will be a sleep call. We do this as the thread can be created before the hook is set in the process.
cmp dword ptr [_cameraStruct], 0
je MainThread
// check if one of the keys is pressed
// keys supported:
// Camera pos: num8 (forward), num4 (backward), num6 (right), num4 (left), num9 (up), num3 (down)
// FoV : substract (decrease FoV), add (increase FoV). Enable/disable depends on separate script (see table)
// We'll do this one at a time, as it doesn't matter if we e.g. check up+left or first up and then left
// Camera position manipulation keys are ignored if camera is disabled (using another script in this CT)
// We'll check with GetKeyState, and not GetAsyncKeyState, as GetAsyncKeyState can fail if CE is on a different monitor
// than the game. Win32 uses stdcall, so arguments are pushed on the stack in right-to-left order
// and result is stored in EAX.
// FoV keys
@@:
push 6D // numpad substract (VK_SUBSTRACT)
call GetKeyState
test ax, 8000
jz @f
// key pressed, do fov decrease
call DoFoVDecrease
@@:
push 6B // numpad add (VK_ADD)
call GetKeyState
test ax, 8000
jz @f
// key pressed, do fov inccrease
call DoFoVIncrease
@@:
// Free camera movement keys
// first check if the free camera is enabled. Enabling is done by a different script. Check if cameraX is set,
// if it's not, we skip all camera keys.
cmp [_cameraX], 0
je MainThread_EndLoop
// camera enabled, we can proceed with handling camera movement keys
// Check if alt is pressed. If so, we'll speed up the movement. We'll store the bit for later
push 12 // Alt (VK_MENU)
call GetKeyState
and eax, 8000 // high bit is either set (key is pressed) or not (key isn't pressed). Rest of bits is garbage, so clear them
shr ax, F // so we simply shift right 15 bits, which moves the high bit to the LSB
mov [_altPressed], ax
// Check if ctrl is pressed. If so, we'll slow down the movement. Same code as Alt. We'll store the bit for later
push 11 // Ctrl (VK_CONTROL)
call GetKeyState
and eax, 8000
shr ax, F
mov [_ctrlPressed], ax
push 68 // numpad 8 (VK_NUMPAD8)
call GetKeyState
test ax, 8000
jz @f
// up is pressed, perform camera move forward.
call MoveCameraForward
@@:
push 62 // numpad 2 (VK_NUMPAS2)
call GetKeyState
test ax, 8000
jz @f
// down is pressed, perform camera move backwards
call MoveCameraBackwards
@@:
push 64 // numpad 4 (VK_NUMPAD4)
call GetKeyState
test ax, 8000
jz @f
// left is pressed, perform camera move sideways
call MoveCameraSidewaysLeft
@@:
push 66 // numpad 6 (VK_NUMPAD6)
call GetKeyState
test ax, 8000
jz @f
// right is pressed, perform camera move sideways
call MoveCameraSidewaysRight
@@:
push 69 // numpad 9 (VK_NUMPAD9)
call GetKeyState
test ax, 8000
jz @f
// z up is pressed, perform camera move upwards along Z axis
xor ebx, ebx // if ebx is set to 0 for this function it will move up, otherwise down
call MoveCameraUpDown
@@:
push 63 // numpad 3 (VK_NUMPAD3)
call GetKeyState
test ax, 8000
jz @f
// z down is pressed, perform camera move downwards along Z axis
mov ebx, 1
call MoveCameraUpDown
@@:
MainThread_EndLoop:
// check if the thread can die
cmp byte [_disableThread], 1
jne MainThread // not disabled, so loop!
MainThread_End:
// end
ret
//-------------------------------------------------------------
// camera movement code
// We're using a normalized (vector with length 1.0) vector to move the camera.
// this vector is at [_cameraStruct]+A0, with vX, vY, vZ, W. The 'W' isn't used, but as the
// SIMD instructions load 128bits into the registers, they'll load the 4th dword too.
//
// Finding this vector is rather easy, once you know where the camera struct is in memory. Often if you find the FoV value address, the
// camera struct is near that spot. To verify that, view memory in CE and view the FoV address, changing the view to floats (ctrl-9).
// Then rotate the camera left / right. This should make the values at that memory location change. When you stop moving,
// the values should stay the same. Check if you see values between -1.0 and 1.0. There are often multiple times sets of those, as
// projection matrices are also often found near the FoV in the camera struct. If you have located a candidate vector with 3 values
// next to each other between -1.0 and 1.0, try to rotate the camera in the x/y plane (horizontally). This should change only the
// first two. Rotating the camera up/down should change the 3rd as well as the first two.
//
// The vector is the camera look vector so we can use that to manipulate the camera coordinates:
// Forward means we're moving in the direction of the vector (X, Y and Z updated)
// Left/Right means we're moving in the x/y plane in the direction orthogonal on the look vector (X, Y updated, Z is left alone)
// Backwards means we're moving in the opposite direction of the vector (X, Y and Z updated)
// The vector uses (-x, -y, z) compared to the world/geometry coordinates. This means that
// if the vector is aligned with the x axis looking at the positive x of the world, it's vX component is negative. Same for vY.
// If you think 'Why is this bozo doing a sub when he wants to add?!', that's why ;)
MoveCameraForward:
push eax
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0. This vector uses -x,-y compared to the world coordinates.
mov eax, [_cameraStruct]
add eax, a0 // normalized vector is at [_cameraStruct+A0]: vX, vY, vZ, vW
movups xmm1, [eax] // load normalized vector into xmm1 (vX, vY, vZ, vW)
call SizeLookVector // will apply alt/ctrl to vector in xmm1 so it makes movement either faster or slower.
subps xmm0, xmm1 // sub the vector from the camera pos, as we're moving in the direction of the vector, but the vector uses -x, -y. If it would have used x, y, we should have used addps
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated pos back into the camera values.
pop eax
ret
MoveCameraBackwards:
push eax
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0.
mov eax, [_cameraStruct]
add eax, a0 // normalized vector is at [_cameraStruct+A0]: vX, vY, vZ, vW
movups xmm1, [eax] // load normalized vector into xmm1 (vX, vY, vZ, vW)
call SizeLookVector // will apply alt/ctrl to vector in xmm1 so it makes movement either faster or slower.
addps xmm0, xmm1 // add the vector from the camera pos, as we're moving in the opposite direction of the vector, but the vector uses -x, -y. If it would have used x, y, we should have used subps
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated position back into the camera position values.
pop eax
ret
// move left &amp; right will use the x/y portion of the normalized vector and set z to 0. This gives a vector in the x/y plane
// which potentially isn't of length 1 so we have to normalize it again.
// To refresh your memory concerning xmm regs: [0|1|2|3] are the parts. so vX is placed in the lower element (0), vY in (1) etc.
// I use it this way as CE displays xmm registers in that order in the debugger.
// so shuffle commands have their bits backwards compared to the order of the xmm elements: 33 22 11 00
// Clear? thought so :)
MoveCameraSidewaysLeft:
push eax
call GetCameraVectorAsXYVector // will load camera vector into xmm1, move it to x/y plane, normalize it
// move left means we have to rotate the x/y vector 90 degrees counter-clockwize. This is simple: new vector is (-vY, vX).
// first move the elements to the right position
shufps xmm1, xmm1, E1 // shuffle using: 11 10 00 01. xmm1 now contains (vY, vX, 0, vW)
xorps xmm2, xmm2 // set the value of xmm2 to 0
subss xmm2, xmm1 // substract 1st value of xmm1, which is vY, from 0
movss xmm1, xmm2 // move -vY from xmm2's first element into xmm1. xmm1 now contains (-vY, vX, 0, vW)
call SizeLookVector
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0.
subps xmm0, xmm1 // add the vector we calculated to the camera position. But x/y are negative aligned, remember? So we do sub! It should now move left
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated position back into the camera position values.
pop eax
ret
MoveCameraSidewaysRight:
push eax
call GetCameraVectorAsXYVector // will load camera vector into xmm1, move it to x/y plane, normalize it
// move right means we have to rotate the x/y vector 90 degrees clockwize. This is simple: new vector is (vY, -vX).
xorps xmm2, xmm2 // set the value of xmm2 to 0
subss xmm2, xmm1 // substract 1st value of xmm1, which is vX, from 0
movss xmm1, xmm2 // move -vX from xmm2's first element into xmm1. xmm1 now contains (-vX, vY, 0, vW)
shufps xmm1, xmm1, E1 // shuffle using: 11 10 00 01. xmm1 now contains (vY, -vX, 0, vW)
call SizeLookVector
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0.
subps xmm0, xmm1 // add the vector we calculated to the camera position. But x/y are negative aligned, remember? So we do sub! It should now move right
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated position back into the camera position values.
pop eax
ret
// Camera up / down movement is done by first creating a vector (0, 0, 1.0) as look vector, size it with the size code, and
// simply add it to the camera coords for up and sub it from the camera coords for down. Z is aligned with world coordinates Z.
// In: ebx: 0==up, not 0==down
MoveCameraUpDown:
push eax
call GetZVector // xmm1 now contains (0, 0, 1.0, 0)
call SizeLookVector // size it based on alt/ctrl keys
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0.
test ebx, ebx // check whether the register is set to 0. If so, we'll move up, otherwise we'll move down
je MoveCameraUpDown_Up
subps xmm0, xmm1 // sub the vector we calculated from the camera position. Z is aligned with the world axis, so we use sub
jmp MoveCameraUpDown_Store
MoveCameraUpDown_Up:
addps xmm0, xmm1 // add the vector we calculated to the camera position. Z is aligned with the world axis, so we use add (finally, some sanity!)
MoveCameraUpDown_Store:
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated position back into the camera position values.
pop eax
ret
// returns in xmm1 a vector (0, 0, 1.0, 0).
// in: nothin'
// out: the vector (0, 0, 1.0, 0)
// Changes: xmm1
GetZVector:
push eax
xorps xmm1, xmm1 // set the value of xmm1 to 0
mov eax, (float)1.0
movd xmm1, eax // move 1.0 into xmm1. Which now contains 1.0, 0, 0, 0
shufps xmm1, xmm1, 45 // shuffle xmm1 so the 1.0 is placed at the 3rd element, which is Z. So we'll use: 01 00 01 01
pop eax
ret
// Loads the camera vector into xmm1, will reset vZ to 0 and will normalize the vector (vX, vY) to length 1.0.
// It's a bit dirty, as it will fail with the vector pointing along the Z axis and x/y being 0.0, but the game doesn't allow that
// In: nothin'
// Out: xmm1: normalized camera vector in x/y plane with vZ set to 0.0.
// Changes: xmm2, xmm3
GetCameraVectorAsXYVector:
push eax
mov eax, [_cameraStruct]
add eax, a0 // normalized vector is at [_cameraStruct+A0]: vX, vY, vZ, vW
movups xmm1, [eax] // load normalized vector into xmm1 (vX, vY, vZ, vW)
xorps xmm2, xmm2 // reset xmm2 to 0, all 4 components
mov eax, -1
movd xmm2, eax // the 1st element (index 0) contains -1 (ffffffff).
shufps xmm2, xmm2, 10 // shuffle using: 00 01 00 00 all 4 elements are now filled with -1 except the 3rd (which contains Z)
andps xmm1, xmm2 // this will set the 3rd element (vZ) to 0, keep all other elements. xmm1 now contains (vX, vY, 0, vW)
// we now have to normalize the vector in xmm1, as it's not really a length of 1, as x/y are smaller if z isn't 0. This is
// done with the formula: vX=vX/length, vY=vY/length. Length = sqrt(x*x+y*y). So first we'll calculate the length.
// this is simple, we multiply xmm1 with itself. Of course in another register as we need xmm1 later.
movaps xmm2, xmm1 // xmm2 now contains xmm1's values
mulps xmm2, xmm2 // multiply xmm2 with itself, which means vX=vX*vX, vY=vY*vY, 0*0, vW=vW*vW (but we don't care about that)
movaps xmm3, xmm2 // move the values of xmm2 in xmm3 so we can move vY*vY to the slot 0 to add it to vX*vX
shufps xmm3, xmm3, E1 // shuffle using 11 10 00 01 so end result is vY*vY, vX*vX, 0, vW*vW
addss xmm2, xmm3 // adds the slot 0 values of xmm3 and xmm2 which means xmm2 now contains vX*vX + vY*vY.
sqrtss xmm2, xmm2 // square root the slot 0 value, so it now contains sqrt(vX*vX + vY*vY).
shufps xmm2, xmm2, 0 // shuffle the sqrt result to all slots0, 1 and 2 so we can div x and y (and z, but will result in 0) in one go.
// so use 00 00 00 00 to avoid div by 0 in the next statement.
divps xmm1, xmm2 // div xmm1 with xmm2, which means vX/sqrt(vX*vX+vY*vY), vY/sqrt(vX*vX+vY*vY), 0, vW
pop eax
ret
//------------------------------------------------------------
// Will multiply the camera vector with a scalar to size it up (if alt is pressed) or down (if ctrl is pressed)
// If no alt/ctrl is pressed, we size it with the scalar 2.0 to make moving around more pleasant
// in : xmm1 (vX, vY, vZ, vW)
// changes: xmm7
SizeLookVector:
push ebx
cmp byte [_altPressed], 1
jne @f
// alt pressed. Multiply with 10.0
mov ebx, (float)10.0
jmp SizeLookVector_Calc
@@:
cmp byte [_ctrlPressed], 1
jne @f
// ctrl pressed. Multiply with 0.5
mov ebx, (float)0.5
jmp SizeLookVector_Calc
@@:
// default scalar sizing
mov ebx, (float)2.0
SizeLookVector_Calc:
movd xmm7, ebx // load the factor to multiply with into xmm7. This is a scalar, xmm registers contain 4 of them
shufps xmm7, xmm7, 0 // so we shuffle the first element to be placed in all 4.
mulps xmm1, xmm7 // multiply the vector in xmm1 with the 4 values in xmm7, so vX=vX*xmm7[0], vY=vY*xmm7[1] etc.
SizeLookVector_End:
pop ebx
ret
//------------------------------------------------------------
// FoV code
DoFoVIncrease:
cmp byte [_fovEnabled], 1
je @f
// not enabled, nothing to do.
ret
@@:
push eax
push ebx
mov eax, [_cameraStruct]
add eax, 4c // FoV value is at offset 4C
movss xmm0, [eax]
mov ebx, (float)1.0 // load the register with 1.0 float, and move it using this register into xmm1
movd xmm1, ebx
addss xmm0, xmm1 // add the 1.0 to the value.
movss [eax], xmm0 // store the new value back into the address.
pop ebx
pop eax
ret
DoFoVDecrease:
cmp byte [_fovEnabled], 1
je @f
// not enabled, nothing to do.
ret
@@:
push eax
push ebx
mov eax, [_cameraStruct]
add eax, 4c // FoV value is at offset 4C
movss xmm0, [eax]
mov ebx, (float)1.0 // load the register with 1.0 float, and move it using this register into xmm1
movd xmm1, ebx
subss xmm0, xmm1 // sub the 1.0 from the value
movss [eax], xmm0 // store the new value back into the address.
pop ebx
pop eax
ret
//-----------------------------------------------------------
// Local data
_cameraStruct:
dd 0
_cameraX:
dd 0
_cameraY:
dd 0
_cameraZ:
dd 0
_cameraW: // not used, but here to make the camera pos 128 so we can use xmm registers to work on xyz in 1 op
dd 0
_disableThread:
db 0
_fovEnabled:
db 0
_altPressed:
dw 0
_ctrlPressed:
dw 0
[DISABLE]
//-----------------------------------------------------------
// Local data
_disableThread:
db 1 // set it to 1 hard-coded, which will exit the thread.
_cameraStruct:
dd 0
_cameraX:
dd 0
_cameraY:
dd 0
_cameraZ:
dd 0
_cameraW: // not used, but here to make the camera pos 128 so we can use xmm registers to work on xyz in 1 op
dd 0
// unregister symbols, as they're no longer needed
unregistersymbol(_disableThread)
unregistersymbol(_cameraStruct)
unregistersymbol(_freeCameraEnabled)
unregistersymbol(MainThread)
unregistersymbol(_cameraX)
unregistersymbol(_cameraY)
unregistersymbol(_cameraZ)
unregistersymbol(_fovEnabled)
unregistersymbol(_altPressed)
// replace overwritten memory of FoV address grab code with original code
"Darksiders2.exe"+EB34C:
fstp dword ptr [eax+4C]
pop esi
leave
</AssemblerScript>
<Hotkeys>
<Hotkey>
<Action>Toggle Activation</Action>
<Keys>
<Key>45</Key>
</Keys>
<ID>0</ID>
</Hotkey>
</Hotkeys>
<CheatEntries>
<CheatEntry>
<ID>10998</ID>
<Description>"FoV. Toggle: HOME. Inc/Dec: Numpad + / Numpad -"</Description>
<LastState/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>//-----------------------------------------
// By Otis / Infuse Project
// This simple script sets a flag which is allocated by the main script in the camera system.
// By setting this flag the main camera system enables/disables the usage of the FoV keys.
// This is done this way as toggling features on/off is otherwise required to be done in the camera system thread
// which polls the key states on the keyboard on a high frequency (e.g. every 50ms) which is a bit cumbersome
// for toggles as it requires to release the key within that time interval, it otherwise switches on/off again
// within the same keypress. Doing it this way simply lets CE using normal windows key input do the toggling which is
// not having this problem.
[ENABLE]
_fovEnabled:
db 1
[DISABLE]
_fovEnabled:
db 0
</AssemblerScript>
<Hotkeys>
<Hotkey>
<Action>Toggle Activation</Action>
<Keys>
<Key>36</Key>
</Keys>
<ID>0</ID>
</Hotkey>
</Hotkeys>
</CheatEntry>
<CheatEntry>
<ID>10996</ID>
<Description>"Free camera. Toggle: Num0. Num2/8:Y, Num4/6:X, Num3/9:Z"</Description>
<LastState/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>[ENABLE]
alloc(newmem,2048)
label(returnhere)
label(exit)
label(originalcode)
label(newmem2)
label(returnhere2)
label(exit2)
label(originalcode2)
label(newmem3)
label(returnhere3)
label(exit3)
label(originalcode3)
label(CameraManipulate)
registersymbol(CameraManipulate)
////////////////////////////////////
newmem:
CameraManipulate:
cmp [_cameraX],0
je originalcode
push edx
mov edx,[_cameraX]
mov [edi+30],edx
pop edx
fld dword ptr [ebp-3C]
jmp exit
originalcode:
push edx
mov edx,[edi+30]
mov [_cameraX],edx
pop edx
fstp dword ptr [edi+30]
fld dword ptr [ebp-3C]
jmp exit
exit:
jmp returnhere
////////////////////////////////////
newmem2:
cmp [_cameraY],0
je originalcode2
push edx
mov edx,[_cameraY]
mov [edi+34],edx
pop edx
fld dword ptr [ebp-38]
jmp exit2
originalcode2:
push edx
mov edx,[edi+34]
mov [_cameraY],edx
pop edx
fstp dword ptr [edi+34]
fld dword ptr [ebp-38]
jmp exit2
exit2:
jmp returnhere2
////////////////////////////////////
newmem3:
cmp [_cameraZ],0
je originalcode3
push edx
mov edx,[_cameraZ]
mov [edi+38],edx
pop edx
fld dword ptr [ebp-68]
jmp exit3
originalcode3:
push edx
mov edx,[edi+38]
mov [_cameraZ],edx
pop edx
fstp dword ptr [edi+38]
fld dword ptr [ebp-68]
jmp exit3
exit3:
jmp returnhere3
"Darksiders2.exe"+6A9B9F:
jmp newmem
nop
returnhere:
"Darksiders2.exe"+6A9BA5:
jmp newmem2
nop
returnhere2:
"Darksiders2.exe"+6A9BAB:
jmp newmem3
nop
returnhere3:
[DISABLE]
// reset camera pointer for X to 0 so the key thread knows camera is disabled.
_cameraX:
dd 0
_cameraY:
dd 0
_cameraZ:
dd 0
_cameraW:
dd 0
dealloc(newmem)
"Darksiders2.exe"+6A9B9F:
fstp dword ptr [edi+30]
fld dword ptr [ebp-3C]
//
"Darksiders2.exe"+6A9BA5:
fstp dword ptr [edi+34]
fld dword ptr [ebp-38]
//
"Darksiders2.exe"+6A9BAB:
fstp dword ptr [edi+38]
fld dword ptr [ebp-68]
unregistersymbol(CameraManipulate)
</AssemblerScript>
<Hotkeys>
<Hotkey>
<Action>Toggle Activation</Action>
<Keys>
<Key>96</Key>
</Keys>
<ID>0</ID>
</Hotkey>
</Hotkeys>
<CheatEntries>
<CheatEntry>
<ID>11001</ID>
<Description>"Alt: speed up. Ctrl: Slow down"</Description>
<LastState Value="" RealAddress="00000000"/>
<Color>0000FF</Color>
<GroupHeader>1</GroupHeader>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
</CheatEntry>
<CheatEntry>
<ID>10990</ID>
<Description>"Timestop DEL"</Description>
<LastState/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
originalcode:
cmp dword ptr [esi+000000F8],00
exit:
jmp returnhere
"Darksiders2.exe"+747090:
nop
nop
nop
nop
nop
nop
nop
returnhere:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Darksiders2.exe"+747090:
cmp dword ptr [esi+000000F8],00
//Alt: db 83 BE F8 00 00 00 00
</AssemblerScript>
<Hotkeys>
<Hotkey>
<Action>Toggle Activation</Action>
<Keys>
<Key>46</Key>
</Keys>
<ID>0</ID>
</Hotkey>
</Hotkeys>
</CheatEntry>
<CheatEntry>
<ID>1</ID>
<Description>"Character"</Description>
<LastState Value="" RealAddress="00000000"/>
<GroupHeader>1</GroupHeader>
<CheatEntries>
<CheatEntry>
<ID>11</ID>
<Description>"Boatman Coins"</Description>
<VariableType>4 Bytes</VariableType>
<Address>"Darksiders2.exe"+01460148</Address>
<Offsets>
<Offset>20</Offset>
<Offset>3BC</Offset>
<Offset>18</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>12</ID>
<Description>"Gilt"</Description>
<VariableType>4 Bytes</VariableType>
<Address>"Darksiders2.exe"+01460F54</Address>
<Offsets>
<Offset>28</Offset>
<Offset>8</Offset>
<Offset>10</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>13</ID>
<Description>"Health"</Description>
<VariableType>Float</VariableType>
<Address>"Darksiders2.exe"+01460F58</Address>
<Offsets>
<Offset>664</Offset>
<Offset>6C</Offset>
<Offset>4</Offset>
<Offset>40</Offset>
<Offset>150</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>15</ID>
<Description>"Reaper Energy"</Description>
<VariableType>Float</VariableType>
<Address>Darksiders2.exe+1460F58</Address>
<Offsets>
<Offset>66C</Offset>
<Offset>6C</Offset>
<Offset>4</Offset>
<Offset>40</Offset>
<Offset>150</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>14</ID>
<Description>"Wrath"</Description>
<VariableType>Float</VariableType>
<Address>"Darksiders2.exe"+01460F58</Address>
<Offsets>
<Offset>668</Offset>
<Offset>6C</Offset>
<Offset>4</Offset>
<Offset>40</Offset>
<Offset>150</Offset>
</Offsets>
</CheatEntry>
</CheatEntries>
</CheatEntry>
<CheatEntry>
<ID>10991</ID>
<Description>"Based on CT from http://www.deadendthrills.com/forum/discussion/263/guide-darksiders-2"</Description>
<LastState Value="" RealAddress="00000000"/>
<GroupHeader>1</GroupHeader>
<CheatEntries>
<CheatEntry>
<ID>10999</ID>
<Description>"Code for camera hooks/FoV/Timestop: DET &amp; Jim2Point0"</Description>
<LastState Value="" RealAddress="00000000"/>
<GroupHeader>1</GroupHeader>
</CheatEntry>
<CheatEntry>
<ID>11000</ID>
<Description>"Code for camera movement: Otis / Infuse Project"</Description>
<LastState Value="" RealAddress="00000000"/>
<GroupHeader>1</GroupHeader>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
<CheatCodes>
<CodeEntry>
<Description>Code :mov [esi+48],al</Description>
<Address>00B470C6</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>7470C6</ModuleNameOffset>
<Before>
<Byte>40</Byte>
<Byte>EB</Byte>
<Byte>02</Byte>
<Byte>33</Byte>
<Byte>C0</Byte>
</Before>
<Actual>
<Byte>88</Byte>
<Byte>46</Byte>
<Byte>48</Byte>
</Actual>
<After>
<Byte>84</Byte>
<Byte>C0</Byte>
<Byte>0F</Byte>
<Byte>84</Byte>
<Byte>BE</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp dword ptr [ecx+000000F8],00</Description>
<Address>00B458CF</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>7458CF</ModuleNameOffset>
<Before>
<Byte>79</Byte>
<Byte>14</Byte>
<Byte>00</Byte>
<Byte>74</Byte>
<Byte>21</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>B9</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>18</Byte>
<Byte>56</Byte>
<Byte>8D</Byte>
<Byte>B1</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp dword ptr [esi+000000F8],00</Description>
<Address>004CFFEF</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>CFFEF</ModuleNameOffset>
<Before>
<Byte>88</Byte>
<Byte>48</Byte>
<Byte>34</Byte>
<Byte>EB</Byte>
<Byte>26</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>BE</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>13</Byte>
<Byte>85</Byte>
<Byte>FF</Byte>
<Byte>74</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp [eax+000000F8],ecx</Description>
<Address>004E53DB</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>E53DB</ModuleNameOffset>
<Before>
<Byte>05</Byte>
<Byte>F2</Byte>
<Byte>FF</Byte>
<Byte>33</Byte>
<Byte>C9</Byte>
</Before>
<Actual>
<Byte>39</Byte>
<Byte>88</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>0F</Byte>
<Byte>9F</Byte>
<Byte>C0</Byte>
<Byte>C3</Byte>
<Byte>55</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp dword ptr [esi+000000F8],00</Description>
<Address>00B47004</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>747004</ModuleNameOffset>
<Before>
<Byte>8A</Byte>
<Byte>3D</Byte>
<Byte>02</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>BE</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7E</Byte>
<Byte>49</Byte>
<Byte>D8</Byte>
<Byte>96</Byte>
<Byte>FC</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp dword ptr [esi+000000F8],00</Description>
<Address>00B47090</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>747090</ModuleNameOffset>
<Before>
<Byte>50</Byte>
<Byte>58</Byte>
<Byte>88</Byte>
<Byte>45</Byte>
<Byte>EF</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>BE</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>2B</Byte>
<Byte>8B</Byte>
<Byte>46</Byte>
<Byte>10</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :nop </Description>
<Address>00B47090</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>747090</ModuleNameOffset>
<Before>
<Byte>50</Byte>
<Byte>58</Byte>
<Byte>88</Byte>
<Byte>45</Byte>
<Byte>EF</Byte>
</Before>
<Actual>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>2B</Byte>
<Byte>8B</Byte>
<Byte>46</Byte>
<Byte>10</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :cmp dword ptr [esi+000000F8],00</Description>
<Address>00B47090</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>747090</ModuleNameOffset>
<Before>
<Byte>50</Byte>
<Byte>58</Byte>
<Byte>88</Byte>
<Byte>45</Byte>
<Byte>EF</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>BE</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>2B</Byte>
<Byte>8B</Byte>
<Byte>46</Byte>
<Byte>10</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :mov [esi+48],al</Description>
<Address>00B470C6</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>7470C6</ModuleNameOffset>
<Before>
<Byte>40</Byte>
<Byte>EB</Byte>
<Byte>02</Byte>
<Byte>33</Byte>
<Byte>C0</Byte>
</Before>
<Actual>
<Byte>88</Byte>
<Byte>46</Byte>
<Byte>48</Byte>
</Actual>
<After>
<Byte>84</Byte>
<Byte>C0</Byte>
<Byte>0F</Byte>
<Byte>84</Byte>
<Byte>BE</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :mov [esi+000000C0],al</Description>
<Address>00D435AA</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>9435AA</ModuleNameOffset>
<Before>
<Byte>C4</Byte>
<Byte>10</Byte>
<Byte>8A</Byte>
<Byte>45</Byte>
<Byte>08</Byte>
</Before>
<Actual>
<Byte>88</Byte>
<Byte>86</Byte>
<Byte>C0</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>E8</Byte>
<Byte>21</Byte>
<Byte>57</Byte>
<Byte>07</Byte>
<Byte>00</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :cmp [esi+000000C0],bl</Description>
<Address>00D4353D</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>94353D</ModuleNameOffset>
<Before>
<Byte>E8</Byte>
<Byte>5E</Byte>
<Byte>ED</Byte>
<Byte>FF</Byte>
<Byte>FF</Byte>
</Before>
<Actual>
<Byte>38</Byte>
<Byte>9E</Byte>
<Byte>C0</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>74</Byte>
<Byte>14</Byte>
<Byte>8B</Byte>
<Byte>06</Byte>
<Byte>8B</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :or dword ptr [esi+000000BC],01</Description>
<Address>00D43522</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>943522</ModuleNameOffset>
<Before>
<Byte>38</Byte>
<Byte>5D</Byte>
<Byte>08</Byte>
<Byte>74</Byte>
<Byte>09</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>8E</Byte>
<Byte>BC</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>01</Byte>
</Actual>
<After>
<Byte>EB</Byte>
<Byte>07</Byte>
<Byte>83</Byte>
<Byte>A6</Byte>
<Byte>BC</Byte>
</After>
</CodeEntry>
</CheatCodes>
<UserdefinedSymbols>
<SymbolEntry>
<Name>pHealth</Name>
<Address>34760000</Address>
</SymbolEntry>
<SymbolEntry>
<Name>tHealth</Name>
<Address>34760010</Address>
</SymbolEntry>
<SymbolEntry>
<Name>pSkillPts</Name>
<Address>04E80020</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB4_jmp</Name>
<Address>00723165</Address>
</SymbolEntry>
<SymbolEntry>
<Name>pWrath</Name>
<Address>04100020</Address>
</SymbolEntry>
<SymbolEntry>
<Name>pCurrency</Name>
<Address>05010000</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB2_jmp</Name>
<Address>00726238</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB5_jmp</Name>
<Address>00811E9C</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB3_jmp</Name>
<Address>0078347E</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB1_jmp</Name>
<Address>007248D2</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB6_jmp</Name>
<Address>00761711</Address>
</SymbolEntry>
<SymbolEntry>
<Name>OwnCode</Name>
<Address>0B150000</Address>
</SymbolEntry>
<SymbolEntry>
<Name>_fovAddress</Name>
<Address>345A00F1</Address>
</SymbolEntry>
</UserdefinedSymbols>
<Comments>Info about this table:
</Comments>
</CheatTable>
<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="21">
<CheatEntries>
<CheatEntry>
<ID>10992</ID>
<Description>"Camera system. Toggle: INS. Enable first to use fov/freecam"</Description>
<LastState/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>//----------------------------------------------------------
// Reworked Darksiders II cheat table with free camera / timestop / FoV
// By Otis / Infuse Project
//
// Based on DeadEndThrill's original CT with hacks for free camera / timestop / FoV (by Jim2Point0, Duncan Harris and others)
// this table contains a thread based camera movement system which moves the camera based on the camera look vector direction
// so pressing e.g. 'left' (numpad 4) is moving the camera left, you're no longer moving over the world x/y/z axis which don't align with
// the camera direction in most cases.
//
// I've commented a lot of code in this table. For seasoned assembly programmers these comments might sound like 'water is wet' statements,
// but they might help the novice assembly programmer out what's going on (as SIMD programmer isn't straightforward!) :)
// The features are enabled / disabled by two child scripts, one for the FoV and one for the camera hook.
// This is done so the thread loop can run at almost full speed scanning keys and it's also easier to enable e.g. FoV without the
// camera.
//----------------------------------------------------------
[ENABLE]
globalalloc(OwnCode, 2048) // alloc memory for our code, once.
createthread(MainThread) // creates a new thread in the attached process and starts at MainThread.
// make sure it terminates when [DISABLE] is ran, otherwise a new one will be
// created when you re-enable the camera system. In this table, this is done by
// the _disableThread byte, which is set to 1 when the thread has to terminate
// and which is checked two times in the thread (begin/end).
//----------------------------------------------------------
// Code labels
label(MainThread)
// Data labels
label(_disableThread)
label(_cameraStruct)
label(_cameraX)
label(_cameraY)
label(_cameraZ)
label(_cameraW)
label(_fovEnabled)
label(_altPressed)
label(_ctrlPressed)
// Symbols. Registering them allows you to use them in the CE UI.
registersymbol(_disableThread)
registersymbol(_cameraStruct)
registersymbol(_cameraX)
registersymbol(_cameraY)
registersymbol(_cameraZ)
registersymbol(_fovEnabled)
registersymbol(_altPressed)
registersymbol(MainThread)
// overwrite inside the darksiders2 process the following address with a jmp to our code which grabs the FoV address
// which is in the register EAX.
"Darksiders2.exe"+EB34C:
jmp GrabCameraStructAddress
ReturnAfterFoVGrab:
OwnCode:
// FoV
// new code to grab FoV address, which is inside the camera struct we need.
GrabCameraStructAddress:
mov [_cameraStruct],eax
cmp byte [_fovEnabled], 1
jz @f // continue at next unnamed label (which is @@)
fstp dword ptr [eax+4C] // original code, fov not enabled.
@@:
pop esi // original code
leave // original code
jmp ReturnAfterFoVGrab // continue with original game code.
//---------------------------------------------------------
// Code
MainThread:
// 32bit so use this approach to wait a couple of ms. If 64bit, you need: mov rcx, milliseconds
push #25
call Sleep
// check if the thread can die
cmp byte [_disableThread], 1
je MainThread_End // disabled, die
// check if the camera struct is already available. If not, loop to the beginning of the thread,
// which will be a sleep call. We do this as the thread can be created before the hook is set in the process.
cmp dword ptr [_cameraStruct], 0
je MainThread
// check if one of the keys is pressed
// keys supported:
// Camera pos: num8 (forward), num4 (backward), num6 (right), num4 (left), num9 (up), num3 (down)
// FoV : substract (decrease FoV), add (increase FoV). Enable/disable depends on separate script (see table)
// We'll do this one at a time, as it doesn't matter if we e.g. check up+left or first up and then left
// Camera position manipulation keys are ignored if camera is disabled (using another script in this CT)
// We'll check with GetKeyState, and not GetAsyncKeyState, as GetAsyncKeyState can fail if CE is on a different monitor
// than the game. Win32 uses stdcall, so arguments are pushed on the stack in right-to-left order
// and result is stored in EAX.
// FoV keys
@@:
push 6D // numpad substract (VK_SUBSTRACT)
call GetKeyState
test ax, 8000
jz @f
// key pressed, do fov decrease
call DoFoVDecrease
@@:
push 6B // numpad add (VK_ADD)
call GetKeyState
test ax, 8000
jz @f
// key pressed, do fov inccrease
call DoFoVIncrease
@@:
// Free camera movement keys
// first check if the free camera is enabled. Enabling is done by a different script. Check if cameraX is set,
// if it's not, we skip all camera keys.
cmp [_cameraX], 0
je MainThread_EndLoop
// camera enabled, we can proceed with handling camera movement keys
// Check if alt is pressed. If so, we'll speed up the movement. We'll store the bit for later
push 12 // Alt (VK_MENU)
call GetKeyState
and eax, 8000 // high bit is either set (key is pressed) or not (key isn't pressed). Rest of bits is garbage, so clear them
shr ax, F // so we simply shift right 15 bits, which moves the high bit to the LSB
mov [_altPressed], ax
// Check if ctrl is pressed. If so, we'll slow down the movement. Same code as Alt. We'll store the bit for later
push 11 // Ctrl (VK_CONTROL)
call GetKeyState
and eax, 8000
shr ax, F
mov [_ctrlPressed], ax
push 68 // numpad 8 (VK_NUMPAD8)
call GetKeyState
test ax, 8000
jz @f
// up is pressed, perform camera move forward.
call MoveCameraForward
@@:
push 62 // numpad 2 (VK_NUMPAS2)
call GetKeyState
test ax, 8000
jz @f
// down is pressed, perform camera move backwards
call MoveCameraBackwards
@@:
push 64 // numpad 4 (VK_NUMPAD4)
call GetKeyState
test ax, 8000
jz @f
// left is pressed, perform camera move sideways
call MoveCameraSidewaysLeft
@@:
push 66 // numpad 6 (VK_NUMPAD6)
call GetKeyState
test ax, 8000
jz @f
// right is pressed, perform camera move sideways
call MoveCameraSidewaysRight
@@:
push 69 // numpad 9 (VK_NUMPAD9)
call GetKeyState
test ax, 8000
jz @f
// z up is pressed, perform camera move upwards along Z axis
xor ebx, ebx // if ebx is set to 0 for this function it will move up, otherwise down
call MoveCameraUpDown
@@:
push 63 // numpad 3 (VK_NUMPAD3)
call GetKeyState
test ax, 8000
jz @f
// z down is pressed, perform camera move downwards along Z axis
mov ebx, 1
call MoveCameraUpDown
@@:
MainThread_EndLoop:
// check if the thread can die
cmp byte [_disableThread], 1
jne MainThread // not disabled, so loop!
MainThread_End:
// end
ret
//-------------------------------------------------------------
// camera movement code
// We're using a normalized (vector with length 1.0) vector to move the camera.
// this vector is at [_cameraStruct]+A0, with vX, vY, vZ, W. The 'W' isn't used, but as the
// SIMD instructions load 128bits into the registers, they'll load the 4th dword too.
//
// Finding this vector is rather easy, once you know where the camera struct is in memory. Often if you find the FoV value address, the
// camera struct is near that spot. To verify that, view memory in CE and view the FoV address, changing the view to floats (ctrl-9).
// Then rotate the camera left / right. This should make the values at that memory location change. When you stop moving,
// the values should stay the same. Check if you see values between -1.0 and 1.0. There are often multiple times sets of those, as
// projection matrices are also often found near the FoV in the camera struct. If you have located a candidate vector with 3 values
// next to each other between -1.0 and 1.0, try to rotate the camera in the x/y plane (horizontally). This should change only the
// first two. Rotating the camera up/down should change the 3rd as well as the first two.
//
// The vector is the camera look vector so we can use that to manipulate the camera coordinates:
// Forward means we're moving in the direction of the vector (X, Y and Z updated)
// Left/Right means we're moving in the x/y plane in the direction orthogonal on the look vector (X, Y updated, Z is left alone)
// Backwards means we're moving in the opposite direction of the vector (X, Y and Z updated)
// The vector uses (-x, -y, z) compared to the world/geometry coordinates. This means that
// if the vector is aligned with the x axis looking at the positive x of the world, it's vX component is negative. Same for vY.
// If you think 'Why is this bozo doing a sub when he wants to add?!', that's why ;)
MoveCameraForward:
push eax
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0. This vector uses -x,-y compared to the world coordinates.
mov eax, [_cameraStruct]
add eax, a0 // normalized vector is at [_cameraStruct+A0]: vX, vY, vZ, vW
movups xmm1, [eax] // load normalized vector into xmm1 (vX, vY, vZ, vW)
call SizeLookVector // will apply alt/ctrl to vector in xmm1 so it makes movement either faster or slower.
subps xmm0, xmm1 // sub the vector from the camera pos, as we're moving in the direction of the vector, but the vector uses -x, -y. If it would have used x, y, we should have used addps
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated pos back into the camera values.
pop eax
ret
MoveCameraBackwards:
push eax
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0.
mov eax, [_cameraStruct]
add eax, a0 // normalized vector is at [_cameraStruct+A0]: vX, vY, vZ, vW
movups xmm1, [eax] // load normalized vector into xmm1 (vX, vY, vZ, vW)
call SizeLookVector // will apply alt/ctrl to vector in xmm1 so it makes movement either faster or slower.
addps xmm0, xmm1 // add the vector from the camera pos, as we're moving in the opposite direction of the vector, but the vector uses -x, -y. If it would have used x, y, we should have used subps
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated position back into the camera position values.
pop eax
ret
// move left &amp; right will use the x/y portion of the normalized vector and set z to 0. This gives a vector in the x/y plane
// which potentially isn't of length 1 so we have to normalize it again.
// To refresh your memory concerning xmm regs: [0|1|2|3] are the parts. so vX is placed in the lower element (0), vY in (1) etc.
// I use it this way as CE displays xmm registers in that order in the debugger.
// so shuffle commands have their bits backwards compared to the order of the xmm elements: 33 22 11 00
// Clear? thought so :)
MoveCameraSidewaysLeft:
push eax
call GetCameraVectorAsXYVector // will load camera vector into xmm1, move it to x/y plane, normalize it
// move left means we have to rotate the x/y vector 90 degrees counter-clockwize. This is simple: new vector is (-vY, vX).
// first move the elements to the right position
shufps xmm1, xmm1, E1 // shuffle using: 11 10 00 01. xmm1 now contains (vY, vX, 0, vW)
xorps xmm2, xmm2 // set the value of xmm2 to 0
subss xmm2, xmm1 // substract 1st value of xmm1, which is vY, from 0
movss xmm1, xmm2 // move -vY from xmm2's first element into xmm1. xmm1 now contains (-vY, vX, 0, vW)
call SizeLookVector
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0.
subps xmm0, xmm1 // add the vector we calculated to the camera position. But x/y are negative aligned, remember? So we do sub! It should now move left
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated position back into the camera position values.
pop eax
ret
MoveCameraSidewaysRight:
push eax
call GetCameraVectorAsXYVector // will load camera vector into xmm1, move it to x/y plane, normalize it
// move right means we have to rotate the x/y vector 90 degrees clockwize. This is simple: new vector is (vY, -vX).
xorps xmm2, xmm2 // set the value of xmm2 to 0
subss xmm2, xmm1 // substract 1st value of xmm1, which is vX, from 0
movss xmm1, xmm2 // move -vX from xmm2's first element into xmm1. xmm1 now contains (-vX, vY, 0, vW)
shufps xmm1, xmm1, E1 // shuffle using: 11 10 00 01. xmm1 now contains (vY, -vX, 0, vW)
call SizeLookVector
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0.
subps xmm0, xmm1 // add the vector we calculated to the camera position. But x/y are negative aligned, remember? So we do sub! It should now move right
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated position back into the camera position values.
pop eax
ret
// Camera up / down movement is done by first creating a vector (0, 0, 1.0) as look vector, size it with the size code, and
// simply add it to the camera coords for up and sub it from the camera coords for down. Z is aligned with world coordinates Z.
// In: ebx: 0==up, not 0==down
MoveCameraUpDown:
push eax
call GetZVector // xmm1 now contains (0, 0, 1.0, 0)
call SizeLookVector // size it based on alt/ctrl keys
movups xmm0, [_cameraX] // load camera X, Y, Z, W into xmm0.
test ebx, ebx // check whether the register is set to 0. If so, we'll move up, otherwise we'll move down
je MoveCameraUpDown_Up
subps xmm0, xmm1 // sub the vector we calculated from the camera position. Z is aligned with the world axis, so we use sub
jmp MoveCameraUpDown_Store
MoveCameraUpDown_Up:
addps xmm0, xmm1 // add the vector we calculated to the camera position. Z is aligned with the world axis, so we use add (finally, some sanity!)
MoveCameraUpDown_Store:
mov eax, _cameraX
movups [eax], xmm0 // move the newly calculated position back into the camera position values.
pop eax
ret
// returns in xmm1 a vector (0, 0, 1.0, 0).
// in: nothin'
// out: the vector (0, 0, 1.0, 0)
// Changes: xmm1
GetZVector:
push eax
xorps xmm1, xmm1 // set the value of xmm1 to 0
mov eax, (float)1.0
movd xmm1, eax // move 1.0 into xmm1. Which now contains 1.0, 0, 0, 0
shufps xmm1, xmm1, 45 // shuffle xmm1 so the 1.0 is placed at the 3rd element, which is Z. So we'll use: 01 00 01 01
pop eax
ret
// Loads the camera vector into xmm1, will reset vZ to 0 and will normalize the vector (vX, vY) to length 1.0.
// It's a bit dirty, as it will fail with the vector pointing along the Z axis and x/y being 0.0, but the game doesn't allow that
// In: nothin'
// Out: xmm1: normalized camera vector in x/y plane with vZ set to 0.0.
// Changes: xmm2, xmm3
GetCameraVectorAsXYVector:
push eax
mov eax, [_cameraStruct]
add eax, a0 // normalized vector is at [_cameraStruct+A0]: vX, vY, vZ, vW
movups xmm1, [eax] // load normalized vector into xmm1 (vX, vY, vZ, vW)
xorps xmm2, xmm2 // reset xmm2 to 0, all 4 components
mov eax, -1
movd xmm2, eax // the 1st element (index 0) contains -1 (ffffffff).
shufps xmm2, xmm2, 10 // shuffle using: 00 01 00 00 all 4 elements are now filled with -1 except the 3rd (which contains Z)
andps xmm1, xmm2 // this will set the 3rd element (vZ) to 0, keep all other elements. xmm1 now contains (vX, vY, 0, vW)
// we now have to normalize the vector in xmm1, as it's not really a length of 1, as x/y are smaller if z isn't 0. This is
// done with the formula: vX=vX/length, vY=vY/length. Length = sqrt(x*x+y*y). So first we'll calculate the length.
// this is simple, we multiply xmm1 with itself. Of course in another register as we need xmm1 later.
movaps xmm2, xmm1 // xmm2 now contains xmm1's values
mulps xmm2, xmm2 // multiply xmm2 with itself, which means vX=vX*vX, vY=vY*vY, 0*0, vW=vW*vW (but we don't care about that)
movaps xmm3, xmm2 // move the values of xmm2 in xmm3 so we can move vY*vY to the slot 0 to add it to vX*vX
shufps xmm3, xmm3, E1 // shuffle using 11 10 00 01 so end result is vY*vY, vX*vX, 0, vW*vW
addss xmm2, xmm3 // adds the slot 0 values of xmm3 and xmm2 which means xmm2 now contains vX*vX + vY*vY.
sqrtss xmm2, xmm2 // square root the slot 0 value, so it now contains sqrt(vX*vX + vY*vY).
shufps xmm2, xmm2, 0 // shuffle the sqrt result to all slots0, 1 and 2 so we can div x and y (and z, but will result in 0) in one go.
// so use 00 00 00 00 to avoid div by 0 in the next statement.
divps xmm1, xmm2 // div xmm1 with xmm2, which means vX/sqrt(vX*vX+vY*vY), vY/sqrt(vX*vX+vY*vY), 0, vW
pop eax
ret
//------------------------------------------------------------
// Will multiply the camera vector with a scalar to size it up (if alt is pressed) or down (if ctrl is pressed)
// If no alt/ctrl is pressed, we size it with the scalar 2.0 to make moving around more pleasant
// in : xmm1 (vX, vY, vZ, vW)
// changes: xmm7
SizeLookVector:
push ebx
cmp byte [_altPressed], 1
jne @f
// alt pressed. Multiply with 10.0
mov ebx, (float)10.0
jmp SizeLookVector_Calc
@@:
cmp byte [_ctrlPressed], 1
jne @f
// ctrl pressed. Multiply with 0.5
mov ebx, (float)0.5
jmp SizeLookVector_Calc
@@:
// default scalar sizing
mov ebx, (float)2.0
SizeLookVector_Calc:
movd xmm7, ebx // load the factor to multiply with into xmm7. This is a scalar, xmm registers contain 4 of them
shufps xmm7, xmm7, 0 // so we shuffle the first element to be placed in all 4.
mulps xmm1, xmm7 // multiply the vector in xmm1 with the 4 values in xmm7, so vX=vX*xmm7[0], vY=vY*xmm7[1] etc.
SizeLookVector_End:
pop ebx
ret
//------------------------------------------------------------
// FoV code
DoFoVIncrease:
cmp byte [_fovEnabled], 1
je @f
// not enabled, nothing to do.
ret
@@:
push eax
push ebx
mov eax, [_cameraStruct]
add eax, 4c // FoV value is at offset 4C
movss xmm0, [eax]
mov ebx, (float)1.0 // load the register with 1.0 float, and move it using this register into xmm1
movd xmm1, ebx
addss xmm0, xmm1 // add the 1.0 to the value.
movss [eax], xmm0 // store the new value back into the address.
pop ebx
pop eax
ret
DoFoVDecrease:
cmp byte [_fovEnabled], 1
je @f
// not enabled, nothing to do.
ret
@@:
push eax
push ebx
mov eax, [_cameraStruct]
add eax, 4c // FoV value is at offset 4C
movss xmm0, [eax]
mov ebx, (float)1.0 // load the register with 1.0 float, and move it using this register into xmm1
movd xmm1, ebx
subss xmm0, xmm1 // sub the 1.0 from the value
movss [eax], xmm0 // store the new value back into the address.
pop ebx
pop eax
ret
//-----------------------------------------------------------
// Local data
_cameraStruct:
dd 0
_cameraX:
dd 0
_cameraY:
dd 0
_cameraZ:
dd 0
_cameraW: // not used, but here to make the camera pos 128 so we can use xmm registers to work on xyz in 1 op
dd 0
_disableThread:
db 0
_fovEnabled:
db 0
_altPressed:
dw 0
_ctrlPressed:
dw 0
[DISABLE]
//-----------------------------------------------------------
// Local data
_disableThread:
db 1 // set it to 1 hard-coded, which will exit the thread.
_cameraStruct:
dd 0
_cameraX:
dd 0
_cameraY:
dd 0
_cameraZ:
dd 0
_cameraW: // not used, but here to make the camera pos 128 so we can use xmm registers to work on xyz in 1 op
dd 0
// unregister symbols, as they're no longer needed
unregistersymbol(_disableThread)
unregistersymbol(_cameraStruct)
unregistersymbol(_freeCameraEnabled)
unregistersymbol(MainThread)
unregistersymbol(_cameraX)
unregistersymbol(_cameraY)
unregistersymbol(_cameraZ)
unregistersymbol(_fovEnabled)
unregistersymbol(_altPressed)
// replace overwritten memory of FoV address grab code with original code
"Darksiders2.exe"+EB34C:
fstp dword ptr [eax+4C]
pop esi
leave
</AssemblerScript>
<Hotkeys>
<Hotkey>
<Action>Toggle Activation</Action>
<Keys>
<Key>45</Key>
</Keys>
<ID>0</ID>
</Hotkey>
</Hotkeys>
<CheatEntries>
<CheatEntry>
<ID>10998</ID>
<Description>"FoV. Toggle: HOME. Inc/Dec: Numpad + / Numpad -"</Description>
<LastState/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>//-----------------------------------------
// By Otis / Infuse Project
// This simple script sets a flag which is allocated by the main script in the camera system.
// By setting this flag the main camera system enables/disables the usage of the FoV keys.
// This is done this way as toggling features on/off is otherwise required to be done in the camera system thread
// which polls the key states on the keyboard on a high frequency (e.g. every 50ms) which is a bit cumbersome
// for toggles as it requires to release the key within that time interval, it otherwise switches on/off again
// within the same keypress. Doing it this way simply lets CE using normal windows key input do the toggling which is
// not having this problem.
[ENABLE]
_fovEnabled:
db 1
[DISABLE]
_fovEnabled:
db 0
</AssemblerScript>
<Hotkeys>
<Hotkey>
<Action>Toggle Activation</Action>
<Keys>
<Key>36</Key>
</Keys>
<ID>0</ID>
</Hotkey>
</Hotkeys>
</CheatEntry>
<CheatEntry>
<ID>10996</ID>
<Description>"Free camera. Toggle: Num0. Num2/8:Y, Num4/6:X, Num3/9:Z"</Description>
<LastState/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>[ENABLE]
alloc(newmem,2048)
label(returnhere)
label(exit)
label(originalcode)
label(newmem2)
label(returnhere2)
label(exit2)
label(originalcode2)
label(newmem3)
label(returnhere3)
label(exit3)
label(originalcode3)
label(CameraManipulate)
registersymbol(CameraManipulate)
////////////////////////////////////
newmem:
CameraManipulate:
cmp [_cameraX],0
je originalcode
push edx
mov edx,[_cameraX]
mov [edi+30],edx
pop edx
fld dword ptr [ebp-3C]
jmp exit
originalcode:
push edx
mov edx,[edi+30]
mov [_cameraX],edx
pop edx
fstp dword ptr [edi+30]
fld dword ptr [ebp-3C]
jmp exit
exit:
jmp returnhere
////////////////////////////////////
newmem2:
cmp [_cameraY],0
je originalcode2
push edx
mov edx,[_cameraY]
mov [edi+34],edx
pop edx
fld dword ptr [ebp-38]
jmp exit2
originalcode2:
push edx
mov edx,[edi+34]
mov [_cameraY],edx
pop edx
fstp dword ptr [edi+34]
fld dword ptr [ebp-38]
jmp exit2
exit2:
jmp returnhere2
////////////////////////////////////
newmem3:
cmp [_cameraZ],0
je originalcode3
push edx
mov edx,[_cameraZ]
mov [edi+38],edx
pop edx
fld dword ptr [ebp-68]
jmp exit3
originalcode3:
push edx
mov edx,[edi+38]
mov [_cameraZ],edx
pop edx
fstp dword ptr [edi+38]
fld dword ptr [ebp-68]
jmp exit3
exit3:
jmp returnhere3
"Darksiders2.exe"+6A9B9F:
jmp newmem
nop
returnhere:
"Darksiders2.exe"+6A9BA5:
jmp newmem2
nop
returnhere2:
"Darksiders2.exe"+6A9BAB:
jmp newmem3
nop
returnhere3:
[DISABLE]
// reset camera pointer for X to 0 so the key thread knows camera is disabled.
_cameraX:
dd 0
_cameraY:
dd 0
_cameraZ:
dd 0
_cameraW:
dd 0
dealloc(newmem)
"Darksiders2.exe"+6A9B9F:
fstp dword ptr [edi+30]
fld dword ptr [ebp-3C]
//
"Darksiders2.exe"+6A9BA5:
fstp dword ptr [edi+34]
fld dword ptr [ebp-38]
//
"Darksiders2.exe"+6A9BAB:
fstp dword ptr [edi+38]
fld dword ptr [ebp-68]
unregistersymbol(CameraManipulate)
</AssemblerScript>
<Hotkeys>
<Hotkey>
<Action>Toggle Activation</Action>
<Keys>
<Key>96</Key>
</Keys>
<ID>0</ID>
</Hotkey>
</Hotkeys>
</CheatEntry>
</CheatEntries>
</CheatEntry>
<CheatEntry>
<ID>10990</ID>
<Description>"Timestop DEL"</Description>
<LastState/>
<VariableType>Auto Assembler Script</VariableType>
<AssemblerScript>[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
originalcode:
cmp dword ptr [esi+000000F8],00
exit:
jmp returnhere
"Darksiders2.exe"+747090:
nop
nop
nop
nop
nop
nop
nop
returnhere:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Darksiders2.exe"+747090:
cmp dword ptr [esi+000000F8],00
//Alt: db 83 BE F8 00 00 00 00
</AssemblerScript>
<Hotkeys>
<Hotkey>
<Action>Toggle Activation</Action>
<Keys>
<Key>46</Key>
</Keys>
<ID>0</ID>
</Hotkey>
</Hotkeys>
</CheatEntry>
<CheatEntry>
<ID>1</ID>
<Description>"Character"</Description>
<LastState Value="" RealAddress="00000000"/>
<GroupHeader>1</GroupHeader>
<CheatEntries>
<CheatEntry>
<ID>11</ID>
<Description>"Boatman Coins"</Description>
<LastState Value="15" RealAddress="2F92E9CC"/>
<VariableType>4 Bytes</VariableType>
<Address>"Darksiders2.exe"+01460148</Address>
<Offsets>
<Offset>20</Offset>
<Offset>3BC</Offset>
<Offset>18</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>12</ID>
<Description>"Gilt"</Description>
<LastState Value="24020" RealAddress="12D83AC8"/>
<VariableType>4 Bytes</VariableType>
<Address>"Darksiders2.exe"+01460F54</Address>
<Offsets>
<Offset>28</Offset>
<Offset>8</Offset>
<Offset>10</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>13</ID>
<Description>"Health"</Description>
<LastState Value="1719" RealAddress="131CB104"/>
<VariableType>Float</VariableType>
<Address>"Darksiders2.exe"+01460F58</Address>
<Offsets>
<Offset>664</Offset>
<Offset>6C</Offset>
<Offset>4</Offset>
<Offset>40</Offset>
<Offset>150</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>15</ID>
<Description>"Reaper Energy"</Description>
<LastState Value="246" RealAddress="131CB10C"/>
<VariableType>Float</VariableType>
<Address>Darksiders2.exe+1460F58</Address>
<Offsets>
<Offset>66C</Offset>
<Offset>6C</Offset>
<Offset>4</Offset>
<Offset>40</Offset>
<Offset>150</Offset>
</Offsets>
</CheatEntry>
<CheatEntry>
<ID>14</ID>
<Description>"Wrath"</Description>
<LastState Value="418.6602783" RealAddress="131CB108"/>
<VariableType>Float</VariableType>
<Address>"Darksiders2.exe"+01460F58</Address>
<Offsets>
<Offset>668</Offset>
<Offset>6C</Offset>
<Offset>4</Offset>
<Offset>40</Offset>
<Offset>150</Offset>
</Offsets>
</CheatEntry>
</CheatEntries>
</CheatEntry>
<CheatEntry>
<ID>10991</ID>
<Description>"Based on CT from http://www.deadendthrills.com/forum/discussion/263/guide-darksiders-2"</Description>
<LastState Value="" RealAddress="00000000"/>
<GroupHeader>1</GroupHeader>
<CheatEntries>
<CheatEntry>
<ID>10999</ID>
<Description>"Code for camera hooks/FoV/Timestop: DET &amp; Jim2Point0"</Description>
<LastState Value="" RealAddress="00000000"/>
<GroupHeader>1</GroupHeader>
</CheatEntry>
<CheatEntry>
<ID>11000</ID>
<Description>"Code for camera movement: Otis / Infuse Project"</Description>
<LastState Value="" RealAddress="00000000"/>
<GroupHeader>1</GroupHeader>
</CheatEntry>
</CheatEntries>
</CheatEntry>
</CheatEntries>
<CheatCodes>
<CodeEntry>
<Description>Code :mov [esi+48],al</Description>
<Address>00B470C6</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>7470C6</ModuleNameOffset>
<Before>
<Byte>40</Byte>
<Byte>EB</Byte>
<Byte>02</Byte>
<Byte>33</Byte>
<Byte>C0</Byte>
</Before>
<Actual>
<Byte>88</Byte>
<Byte>46</Byte>
<Byte>48</Byte>
</Actual>
<After>
<Byte>84</Byte>
<Byte>C0</Byte>
<Byte>0F</Byte>
<Byte>84</Byte>
<Byte>BE</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp dword ptr [ecx+000000F8],00</Description>
<Address>00B458CF</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>7458CF</ModuleNameOffset>
<Before>
<Byte>79</Byte>
<Byte>14</Byte>
<Byte>00</Byte>
<Byte>74</Byte>
<Byte>21</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>B9</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>18</Byte>
<Byte>56</Byte>
<Byte>8D</Byte>
<Byte>B1</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp dword ptr [esi+000000F8],00</Description>
<Address>004CFFEF</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>CFFEF</ModuleNameOffset>
<Before>
<Byte>88</Byte>
<Byte>48</Byte>
<Byte>34</Byte>
<Byte>EB</Byte>
<Byte>26</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>BE</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>13</Byte>
<Byte>85</Byte>
<Byte>FF</Byte>
<Byte>74</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp [eax+000000F8],ecx</Description>
<Address>004E53DB</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>E53DB</ModuleNameOffset>
<Before>
<Byte>05</Byte>
<Byte>F2</Byte>
<Byte>FF</Byte>
<Byte>33</Byte>
<Byte>C9</Byte>
</Before>
<Actual>
<Byte>39</Byte>
<Byte>88</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>0F</Byte>
<Byte>9F</Byte>
<Byte>C0</Byte>
<Byte>C3</Byte>
<Byte>55</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp dword ptr [esi+000000F8],00</Description>
<Address>00B47004</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>747004</ModuleNameOffset>
<Before>
<Byte>8A</Byte>
<Byte>3D</Byte>
<Byte>02</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>BE</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7E</Byte>
<Byte>49</Byte>
<Byte>D8</Byte>
<Byte>96</Byte>
<Byte>FC</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Change of cmp dword ptr [esi+000000F8],00</Description>
<Address>00B47090</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>747090</ModuleNameOffset>
<Before>
<Byte>50</Byte>
<Byte>58</Byte>
<Byte>88</Byte>
<Byte>45</Byte>
<Byte>EF</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>BE</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>2B</Byte>
<Byte>8B</Byte>
<Byte>46</Byte>
<Byte>10</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :nop </Description>
<Address>00B47090</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>747090</ModuleNameOffset>
<Before>
<Byte>50</Byte>
<Byte>58</Byte>
<Byte>88</Byte>
<Byte>45</Byte>
<Byte>EF</Byte>
</Before>
<Actual>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
<Byte>90</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>2B</Byte>
<Byte>8B</Byte>
<Byte>46</Byte>
<Byte>10</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :cmp dword ptr [esi+000000F8],00</Description>
<Address>00B47090</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>747090</ModuleNameOffset>
<Before>
<Byte>50</Byte>
<Byte>58</Byte>
<Byte>88</Byte>
<Byte>45</Byte>
<Byte>EF</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>BE</Byte>
<Byte>F8</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>7F</Byte>
<Byte>2B</Byte>
<Byte>8B</Byte>
<Byte>46</Byte>
<Byte>10</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :mov [esi+48],al</Description>
<Address>00B470C6</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>7470C6</ModuleNameOffset>
<Before>
<Byte>40</Byte>
<Byte>EB</Byte>
<Byte>02</Byte>
<Byte>33</Byte>
<Byte>C0</Byte>
</Before>
<Actual>
<Byte>88</Byte>
<Byte>46</Byte>
<Byte>48</Byte>
</Actual>
<After>
<Byte>84</Byte>
<Byte>C0</Byte>
<Byte>0F</Byte>
<Byte>84</Byte>
<Byte>BE</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :mov [esi+000000C0],al</Description>
<Address>00D435AA</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>9435AA</ModuleNameOffset>
<Before>
<Byte>C4</Byte>
<Byte>10</Byte>
<Byte>8A</Byte>
<Byte>45</Byte>
<Byte>08</Byte>
</Before>
<Actual>
<Byte>88</Byte>
<Byte>86</Byte>
<Byte>C0</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>E8</Byte>
<Byte>21</Byte>
<Byte>57</Byte>
<Byte>07</Byte>
<Byte>00</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :cmp [esi+000000C0],bl</Description>
<Address>00D4353D</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>94353D</ModuleNameOffset>
<Before>
<Byte>E8</Byte>
<Byte>5E</Byte>
<Byte>ED</Byte>
<Byte>FF</Byte>
<Byte>FF</Byte>
</Before>
<Actual>
<Byte>38</Byte>
<Byte>9E</Byte>
<Byte>C0</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
</Actual>
<After>
<Byte>74</Byte>
<Byte>14</Byte>
<Byte>8B</Byte>
<Byte>06</Byte>
<Byte>8B</Byte>
</After>
</CodeEntry>
<CodeEntry>
<Description>Code :or dword ptr [esi+000000BC],01</Description>
<Address>00D43522</Address>
<ModuleName>Darksiders2.exe</ModuleName>
<ModuleNameOffset>943522</ModuleNameOffset>
<Before>
<Byte>38</Byte>
<Byte>5D</Byte>
<Byte>08</Byte>
<Byte>74</Byte>
<Byte>09</Byte>
</Before>
<Actual>
<Byte>83</Byte>
<Byte>8E</Byte>
<Byte>BC</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>00</Byte>
<Byte>01</Byte>
</Actual>
<After>
<Byte>EB</Byte>
<Byte>07</Byte>
<Byte>83</Byte>
<Byte>A6</Byte>
<Byte>BC</Byte>
</After>
</CodeEntry>
</CheatCodes>
<UserdefinedSymbols>
<SymbolEntry>
<Name>pHealth</Name>
<Address>34760000</Address>
</SymbolEntry>
<SymbolEntry>
<Name>tHealth</Name>
<Address>34760010</Address>
</SymbolEntry>
<SymbolEntry>
<Name>pSkillPts</Name>
<Address>04E80020</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB4_jmp</Name>
<Address>00723165</Address>
</SymbolEntry>
<SymbolEntry>
<Name>pWrath</Name>
<Address>04100020</Address>
</SymbolEntry>
<SymbolEntry>
<Name>pCurrency</Name>
<Address>05010000</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB2_jmp</Name>
<Address>00726238</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB5_jmp</Name>
<Address>00811E9C</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB3_jmp</Name>
<Address>0078347E</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB1_jmp</Name>
<Address>007248D2</Address>
</SymbolEntry>
<SymbolEntry>
<Name>AOB6_jmp</Name>
<Address>00761711</Address>
</SymbolEntry>
<SymbolEntry>
<Name>OwnCode</Name>
<Address>0B150000</Address>
</SymbolEntry>
<SymbolEntry>
<Name>_fovAddress</Name>
<Address>345A00F1</Address>
</SymbolEntry>
</UserdefinedSymbols>
<Comments>Info about this table:
</Comments>
</CheatTable>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment