[D3d]-Debug commercial games with perfhud

Source: Internet
Author: User

Source: http://blog.csdn.net/RAINini/archive/2008/10/28/3162112.aspx

 

Perfhud is a very useful tool for NV. It can be used to view the running efficiency of the game and identify the bottleneck. It can also be used to analyze the game rendering process and view the rendering operations of each DPC, including the rendering status, the shader used is very powerful.

Perfhud is used to debug self-writtenProgramBut sometimes you can see some good effects of other games and want to know how they are implemented. perfhud can also be used in this case.

To use perfhud, you must modify your d3d program. During createdevice, do not use d3dadapter_default as the adapter parameter, but enumerate all the adapters, select the adapter with the "perfhud" string in the description. Generally, for a single video card machine, it is usually the second adapter. I don't have multiple video cards, so I don't know whether to move back with multiple video cards.

In addition, do not select d3ddevtype_hal for devicetype, but d3ddevtype_ref for devicetype.

In this way, you can use perfhud to mount and analyze the device program. For more information about the creation process, see the perfhud help document.

It can be seen from the above that for other programs, the device is not created by itself, and it does not seem to be able to use perfhud for analysis, but after some hands and feet on the program to be analyzed, this is also possible. The following uses World of Warcraft as an example.

First, open VC (vc6 has not tried vc6, which is similar to the one I used in) and make sure that this option is selected in options,

 

 

 

Only when it is selected can the function name be used as a breakpoint to break the function in the DLL.

Use VC to execute the EXE of the game to be analyzed, click File-> open-> Project of VC, and select the EXE file to be analyzed in the pop-up dialog box, for example:

 

 

 

After adding the file, you can see the file under solution, right-click debug-> step into new instance, start the program, and next function breakpoint, click debug> New breakpoint> break at function in the menu. In the displayed dialog box, write direct3dcreate9, for example:

 

 

 

After clicking OK, the breakpoint will be ready. If a program uses d3d, the breakpoint will be broken and the idirect3d9 interface pointer will be obtained through it.

After completing the preceding steps, press F5 to continue running the program. The breakpoint of the function is broken, for example:

 

 

 

Press SHIFT + F11 to exit the function body. If the function is created successfully, idirect3d9 is obtained, because the returned value of this function is the idirect3d9 pointer. You only need to check the value of the eax register, you can find this pointer, because eax stores the function return value.

Enter eax in the watch window. The current eax value is 0x0016cfc0.

Open a memory window, right click 0x0016cfc0, and use 4-byte integer to view the memory, copy the value of the first 4 bytes of the memory 0x0016cfc0. The value displayed on my machine is 4b641a98. Why do you need to copy this value, because a pointer to a class with a virtual function points to the address, the starting four bytes are the pointer to the virtual function table, through which the function addresses of each virtual function can be found.

In the memory window, add H to the value and then press it. You can also use a 4-byte integer to view the entry address of each function on the idirect3d9 interface, the address of the createdevice function is used to open d3d of the d3d SDK you have installed. h. Search for the idirect3d9 interface declaration and find the followingCode:

 

  Declare_interface _ (idirect3d9, iunknown)
{
/* ** Iunknown Methods ** */
Stdmethod (QueryInterface) (This _ refiid riid, Void ** Ppvobj) pure;
Stdmethod _ (ulong, addref) (this) pure;
Stdmethod _ (ulong, release) (this) pure;

/* ** Idirect3d9 Methods ** */
Stdmethod (registersoftwaredevice) (This _ Void * Pinitializefunction) pure;
Stdmethod _ (uint, getadaptercount) (this) pure;
Stdmethod (getadapteridentifier) (This _ uint adapter, DWORD flags, d3dadapter_identifier9 * Pidentifier) pure;
Stdmethod _ (uint, getadaptermodecount) (This _ uint adapter, d3dformat format) pure;
Stdmethod (enumadaptermodes) (This _ uint adapter, d3dformat format, uint mode, d3ddisplaymode * Pmode) pure;
Stdmethod (getadapterdisplaymode) (This _ uint adapter, d3ddisplaymode * Pmode) pure;
Stdmethod (checkdevicetype) (This _ uint adapter, d3ddevtype devtype, d3dformat adapterformat, d3dformat backbufferformat, bool bwindowed) pure;
Stdmethod (checkdeviceformat) (This _ uint adapter, d3ddevtype devicetype, d3dformat adapterformat, DWORD usage, d3dresourcetype Rtype, d3dformat checkformat) pure;
Stdmethod (checkdevicemultisampletype) (This _ uint adapter, d3ddevtype devicetype, d3dformat surfaceformat, bool initialize wed, d3dmultisample_type multisampletype, DWORD * Pqualitylevels) pure;
Stdmethod (checkdepthstencilmatch) (This _ uint adapter, d3ddevtype devicetype, d3dformat adapterformat, d3dformat rendertargetformat, d3dformat depthstencilformat) pure;
Stdmethod (checkdeviceformatconversion) (This _ uint adapter, d3ddevtype devicetype, d3dformat sourceformat, d3dformat targetformat) pure;
Stdmethod (getdevicecaps) (This _ uint adapter, d3ddevtype devicetype, d3dcaps9 * Pcaps) pure;
Stdmethod _ (hmonitor, getadaptermonitor) (This _ uint adapter) pure;
Stdmethod (createdevice) (This _ uint adapter, d3ddevtype devicetype, hwnd hfocuswindow, DWORD behaviorflags, d3dpresent_parameters * Ppresentationparameters, idirect3ddevice9 ** Ppreturneddeviceinterface) pure;

# Ifdef d3d_debug_info
Lpcwstr version;
# Endif
};

 

After a while, it is found that createdevice is a 17th function, so it should be 17th elements in the virtual function table, so the number of memories pointed to by 4b641a98h, the first pointer is the function entry point of createdevice. The value on my machine is 4b6c1670. It should be said that the same d3d version is used without special processing, the function address of a function is the same.

Enter the value 4b6c1670h in the address at the top of the disassembly code window, press enter to locate the createdevice function body, press F9 next breakpoint, and then press F5 to continue running the program, this function should be broken, for example:

 

 

In this case, check the ESP value to find out where the function is called. The current ESP value is 005a4c4b. When you first enter the function body, ESP stores the address of the next instruction to be executed after this function is returned, so above this instruction is the code that calls createdevice. Similarly, enter 005a4c4bh In the Disassembly window to locate the command, for example:

 

 

 

The call command at the top of the breakpoint is the place where createdevice is called.

From the Call Command, the first push is the push this pointer, that is, the idirect3d interface pointer is pushed, and the second push is the first parameter. You can see that, it was originally directly pushed 0, that is, it was passed to createdevice using d3dadapter_default as the first parameter, and the above push was put into the second parameter. It can be seen that the following command was completed,

 

 
  MoV EBX,1
Push EBX

 

That is to say, 1 is used as the second parameter, that is, d3ddevtype_hal. Therefore, calling createdevice in World of Warcraft is quite satisfactory. In this case, you need to modify the code, replace it with the mov EBX and 1 commands, and change it to push 2 and push 1, that is, change the first parameter passed to createdevice to 1, indicates the second adapter. Change the second parameter to 2, that is, the value represented by d3ddevtype_ref.

These three commands are to be replaced:

 

 
005a4c3d bb01 00 00 00MoV EBX,1
005a4c4253Push EBX
005a4c43 6a00Push0

 

To replace

 

 
Push2
Push1

 

The two commands are to replace the eight-byte machine code.

Then, use ultraedit to open the EXE file and search for the machine code of the command to be modified. You can find the machine code of mov EBX and 1, the machine code of this command is BB 01 00 00 00. Generally, the more bytes you search, the more accurate it is, because you search too little, it is very likely that the same command is called in many places, so I directly add the machine code after this command, such:

 

 

 

Remember to remove the "Search for ASCII" check box and click Next to locate the location where the command is located. Make sure that only one location is found. If there are multiple locations, use more machine codes to search. The final location is as follows:

 

 

 

Replace the byte from BB, position the cursor at the first B, and input 6a 02 6a 01 in sequence, that is, the machine code of Push 2 and push 1. The remaining four bytes can be replaced with 90. The replaced code is as follows:

 

 

 

After the modification is completed, save the EXE and use perfhud for debugging. After perfhud is attached, the World of Warcraft will run:

 

 

 

 

Summarize the above steps:

1. When the program is started, the breakpoint is broken to the place where direct3dcreate9 is executed and the idirect3d pointer is obtained.

2. Use the idirect3d pointer to obtain the virtual function table pointer and find the createdevice function body.

3. Break the breakpoint at the function body and use ESP to find the place where the function is called.

4. Find the code for passing parameters to createdevice and modify the code to the parameters required by perfhud.

As long as the d3d9 program is not encrypted, it can be modified using the above methods. I only tried a few games, such as crysis, wow, and pes2009.

I hope this article will help you explore other game production methods.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.