??xml version="1.0" encoding="utf-8" standalone="yes"?> 如果本文对你的开发有所帮助Qƈ且你手头恰好有零钱?/p> 不如打赏我一杯咖啡,鼓励我l分享优U的文章?br />
解决办法Q修改Stringc,使用utf16来代替CEGUI的utf32?br>优点Q?br>解决了内存占用过多的问题Q一个字W只?个字节就可以了;
解决了调试问题,VS2005直接支持utf16的显C?br>~点Q?br>可能不支持全世界的字W,因ؓutf16不能表示过16位的字符Q但是,对于大多数国家的字符来说Q已l够了Q毕竟windows2000/xp也是Zutf16~码的?br>
然后Q下面是修改后的字符串类Q?a title=CEGUIString href="http://www.shnenglu.com/Files/mybios/CEGUIString.rar">CEGUIString
使用是很单的Q用命o行方式执行:
patch 源文?补丁文g
例如我们有源文gtest.cppQ下载了个补丁文件test.patchQ那么执行patch test.cpp test.patchQ就会自动把patch里的内容更新到test.cpp中去了?br />
PSQcygwin貌似也有q个工具吧。。以前看q里面好像还有diff工具Q可以生成patch文gQ呵c?br />
q有
void GridPartition::enumerateConnectedPartitions(vector<CorePartition*>& connected)
{
//get surrounding grid cells within a certain radius
float loadRadius = mGridPartitionMgr->getGridCellLoadRadius();
//enumerate partitions
vector<CorePartition*> partitions;
mGridPartitionMgr->enumeratePartitions(partitions);
//iterate through and check distance
for(vector<CorePartition*>::iterator itr = partitions.begin(); itr != partitions.end(); ++itr)
{
float distance = Vector3(getWorldPosition() - (*itr)->getWorldPosition()).length();
// add by 李锦?2007-7-16
// 不要q回自己作ؓdQ会产生bug
if(distance < loadRadius && *itr != this)
connected.push_back(*itr);
}
}
再给Z个比较严重的bug
GOOFTranslationManipulator.h中的
// add by 李锦?2007-7-12
// 不要用魔术数Q搞到缓存溢?br /> SceneNode* mNode[AT_LAST];
Entity* mEnt[AT_LAST];
Entity* mConeEnt[AT_LAST];
CollisionShapePtr mCol[AT_LAST];
AxisManipulatorHandle* mHandle[AT_LAST];
另外QCorePartition中的setSkyboxMaterial、setGlobalAmbient之类的代码貌似没用。准备弃之?br />
你可能不希望在发布程序时附带上一个外部的 DLLQ因为可能会有些用户在无意中?DLL 删除了而造成 EXE 不能正确q行Q也有可能该 DLL 会被别h拿去使用Q也有可能,?DLL 会成为破解者破解你的程序的H破口。无论出于何U原因,如果你想把一?DLL 合ƈC?EXE 中的话,本文向你介绍q种Ҏ?
LPVOID sRawDll; // 资源文g在内存中的地址 HRSRC hRes; HMODULE hLibrary; HGLOBAL hResourceLoaded; char lib_name[MAX_PATH]; GetModuleFileName(hInstance, lib_name, MAX_PATH ); // 得到q行E序的名? hLibrary = LoadLibrary(lib_name); // p载入一?DLL 一栯入运行程序到内存? if (NULL != hLibrary) { // 得到指定的资源文件在内存中的位置 hRes = FindResource(hLibrary, MAKEINTRESOURCE(IDR_DATA1), RT_RCDATA); if (NULL != hRes) { // 资源文件蝲入内? hResourceLoaded = LoadResource(hLibrary, hRes); if (NULL != hResourceLoaded) { // 得到资源文g大小 SizeofResource(hLibrary, hRes); // 锁定资源以得到它在内存中的地址 sRawDll = (LPVOID)LockResource(hResourceLoaded); } } else return 1; FreeLibrary(hLibrary); } else return 1;然后Q从资源中蝲?DLL 到内存函?LoadPbDllFromMemory 蝲?DLL 到内存中Q?该函数有两个参数Q第一个参数是指向 DLL 资源在内存中的地址的指针,也就是前面代码中?LockResource 函数的返回倹{第二个参数是一个空的指针,如果函数 LoadPbDllFromMemory q行成功Q该指针指向重新组合后的内存中?DLL 的v始地址。该函数q有一个功能就是如果运行成功,它将手动地用 DLL_PROCESS_ATTACH 参数调用 DLL 的入口函?DllMain 来初始化?DLL。除此之外,它还会手动地载入合ƈ?DLL 的入口表中导入的 DLL q调整它们在内存中的相对地址。以下是该函C?
DWORD LoadPbDllFromMemory(LPVOID lpRawDll, LPVOID lpImageDll) { SYSTEM_INFO sSysInfo; PIMAGE_DOS_HEADER dosHeader; PIMAGE_NT_HEADERS pNTHeader; PIMAGE_SECTION_HEADER section; PIMAGE_IMPORT_DESCRIPTOR pImportDesc; PIMAGE_IMPORT_BY_NAME pOrdinalName; PIMAGE_BASE_RELOCATION baseReloc; PDWORD lpLink; unsigned char Protection[4096]; HINSTANCE hDll; WORD i; DWORD ImagePages,fOldProtect,j,MaxLen,HdrLen,Addr1,Addr2,Pg,Pg1,Pg2; char * sDllName; if(NULL == lpRawDll) return 1 ; dosHeader = (PIMAGE_DOS_HEADER)lpRawDll; // Is this the MZ header? if ((TRUE == IsBadReadPtr(dosHeader,sizeof (IMAGE_DOS_HEADER))) || (IMAGE_DOS_SIGNATURE != dosHeader->e_magic)) return 2; // Get the PE header. pNTHeader = MakePtr(PIMAGE_NT_HEADERS,dosHeader,dosHeader->e_lfanew); // Is this a real PE image? if((TRUE == IsBadReadPtr(pNTHeader,sizeof ( IMAGE_NT_HEADERS))) || ( IMAGE_NT_SIGNATURE != pNTHeader->Signature)) return 3 ; if(( pNTHeader->FileHeader.SizeOfOptionalHeader != sizeof(pNTHeader->OptionalHeader)) || (pNTHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)) return 4; if (pNTHeader->FileHeader.NumberOfSections < 1) return 5; section = IMAGE_FIRST_SECTION( pNTHeader ); int HeaderSize = sizeof(IMAGE_SECTION_HEADER); // 节头长度 HdrLen = (DWORD)section - (DWORD)dosHeader + HeaderSize * pNTHeader->FileHeader.NumberOfSections; // 扑և最大的节的长度,此节一般是代码所在的?.text ? MaxLen = HdrLen; int ii=0; for (i = 0;i<(DWORD)pNTHeader->FileHeader.NumberOfSections;i++)// find MaxLen { if(MaxLen < section[i].VirtualAddress + section[i].SizeOfRawData) { MaxLen = section[i].VirtualAddress + section[i].SizeOfRawData; } if(strcmp((const char *)section[i].Name,".rsrc") == 0) ii=i; } GetSystemInfo(&sSysInfo); ImagePages = MaxLen / sSysInfo.dwPageSize; if (MaxLen % sSysInfo.dwPageSize) ImagePages++; // 分配所需的内? DWORD NeededMemory = ImagePages * sSysInfo.dwPageSize; lpImageDll = VirtualAlloc(NULL, NeededMemory, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (lpImageDll == NULL) return 6; // 分配内存p| MoveMemory( lpImageDll, lpRawDll, HdrLen ); // 复制节头 DWORD OrgAddr = 0; DWORD NewAddr = 0; DWORD Size = 0; // 复制 .text 节数? for (i = 0;i<pNTHeader->FileHeader.NumberOfSections;i++) { OrgAddr = (DWORD)lpImageDll + (DWORD)section[i].VirtualAddress; NewAddr = (DWORD)lpRawDll + (DWORD)section[i].PointerToRawData; Size = (DWORD)section[i].SizeOfRawData; MoveMemory((void *)OrgAddr, (void *)NewAddr, Size ); } // 把指针指向新?DLL 映像 dosHeader = (PIMAGE_DOS_HEADER) lpImageDll; // Switch to new image pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)dosHeader + dosHeader->e_lfanew); section = (PIMAGE_SECTION_HEADER) ((DWORD)pNTHeader + sizeof(IMAGE_NT_HEADERS)); pImageBase = (PBYTE)dosHeader; if((ii!=0) && (IsNT()==TRUE)) { section[ii].VirtualAddress = section[ii].VirtualAddress + (DWORD)lpRawDll; section[ii].PointerToRawData = section[ii].PointerToRawData + (DWORD)lpRawDll; } DWORD importsStartRVA; // Look up where the imports section is (normally in the .idata section) // but not necessarily so. Therefore, grab the RVA from the data dir. importsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_IMPORT); if ( !importsStartRVA ) { VirtualFree(dosHeader,0, MEM_RELEASE); return 7; } pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) pNTHeader-> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; if(pImportDesc!= 0) pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ((DWORD)pImportDesc + (DWORD)dosHeader); else { VirtualFree(dosHeader,0, MEM_RELEASE); return 8; } while (1) // 处理各入口表中的 DLL { // 查是否遇CI的 IMAGE_IMPORT_DESCRIPTOR if ((pImportDesc->TimeDateStamp==0 ) && (pImportDesc->Name==0)) break; // 从磁盘蝲入必ȝ Dll, // 注意,载入?DLL 是合q的 DLL 的入口表中的 DLL, // 不是合ƈ?EXE 中的 DLL sDllName = (char *) (pImportDesc->Name + (DWORD)pImageBase); hDll = GetModuleHandle(sDllName); if (hDll == 0 ) hDll = LoadLibrary(sDllName); if (hDll == 0 ) { MessageBox(NULL, "Can''t find required Dll", "Error in LoadPbDllFromMemory()",0); VirtualFree(dosHeader,0, MEM_RELEASE); return 9; } DWORD *lpFuncNameRef = (DWORD *) (pImportDesc->OriginalFirstThunk + (DWORD)dosHeader); DWORD *lpFuncAddr = (DWORD *) (pImportDesc->FirstThunk + (DWORD)dosHeader); while( *lpFuncNameRef != 0) { pOrdinalName = (PIMAGE_IMPORT_BY_NAME) (*lpFuncNameRef + (DWORD)dosHeader); DWORD pIMAGE_ORDINAL_FLAG = 0x80000000; if (*lpFuncNameRef & pIMAGE_ORDINAL_FLAG) *lpFuncAddr = (DWORD) GetProcAddress(hDll, (const char *)(*lpFuncNameRef & 0xFFFF)); else *lpFuncAddr = (DWORD) GetProcAddress(hDll, (const char *)pOrdinalName->Name); if (lpFuncAddr == 0) { VirtualFree(dosHeader,0, MEM_RELEASE); return 10;// Can''t GetProcAddress } lpFuncAddr++; lpFuncNameRef++; } pImportDesc++; } DWORD TpOffset; baseReloc = (PIMAGE_BASE_RELOCATION)((DWORD)pNTHeader-> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); if (baseReloc !=0) { baseReloc = (PIMAGE_BASE_RELOCATION) ((DWORD)baseReloc + (DWORD)dosHeader); while(baseReloc->VirtualAddress != 0) { PWORD lpTypeOffset = (PWORD) ((DWORD)baseReloc + sizeof(IMAGE_BASE_RELOCATION)); while (lpTypeOffset < (PWORD)((DWORD)baseReloc + (DWORD)baseReloc->SizeOfBlock)) { TpOffset = *lpTypeOffset & 0xF000; if(TpOffset == 0x3000) { lpLink = (PDWORD) ((DWORD)dosHeader + baseReloc->VirtualAddress + (*lpTypeOffset & 0xFFF)); *lpLink = (DWORD)dosHeader + (*lpLink) - pNTHeader->OptionalHeader.ImageBase; } else { if (TpOffset != 0) { VirtualFree(dosHeader,0, MEM_RELEASE); return 10; } } lpTypeOffset++; } baseReloc = (PIMAGE_BASE_RELOCATION)((DWORD)baseReloc + (DWORD)baseReloc->SizeOfBlock); } } // 取得原始的内存状? memset(Protection,0,4096); for (i = 0;i<=pNTHeader->FileHeader.NumberOfSections;i++) { if (i == pNTHeader->FileHeader.NumberOfSections) { Addr1 = 0; Addr2 = HdrLen; j = 0x60000000; } else { Addr1 = section[i].VirtualAddress; Addr2 = section[i].SizeOfRawData; j = section[i].Characteristics; } Addr2 += Addr1 - 1; Pg1 = Addr1 / sSysInfo.dwPageSize; Pg2 = Addr2 / sSysInfo.dwPageSize; for(Pg = Pg1 ;Pg<=Pg2;Pg++) { if (j & 0x20000000) Protection[Pg] |= 1; // Execute if (j & 0x40000000) Protection[Pg] |= 2; // Read if (j & 0x80000000) Protection[Pg] |= 4; // Write } } // 恢复原始的内存状? Addr1 = (DWORD)dosHeader; for (Pg = 0 ;Pg<= ImagePages;Pg++) { switch(Protection[Pg]) { case 2: fOldProtect = PAGE_READONLY; break; case 3: fOldProtect = PAGE_EXECUTE_READ; break; case 6: fOldProtect = PAGE_READWRITE; break; default: // Ignore strange combinations fOldProtect = PAGE_EXECUTE_READWRITE; break; } if (fOldProtect !=PAGE_EXECUTE_READWRITE) { if (VirtualProtect((void *)Addr1, sSysInfo.dwPageSize, fOldProtect, &fOldProtect) == 0) { VirtualFree(dosHeader,0, MEM_RELEASE); return 11; } } Addr1 += sSysInfo.dwPageSize; } EntryPoint = (LPENTRYPOINT) ((DWORD)pNTHeader->OptionalHeader.AddressOfEntryPoint + (DWORD)dosHeader); LPVOID lpReserved = 0; EntryPoint((HINSTANCE)dosHeader, DLL_PROCESS_ATTACH, lpReserved); lpImageDll2=lpImageDll; return 0; }一?DLL 被正地载入到内存中Q我们就可以通过自定义函?GetProcAddressDirectly 来获取某函数在内存中的地址QƈҎ该地址来调用该函数Q该函数也有两个参数Q第一个参数是指向载入到内存中?DLL 的v始地址的指针,W二个是要调用的函数的函数名。以下是 GetProcAddressDirectly 函数代码:
DWORD GetProcAddressDirectly(PIMAGE_DOS_HEADER dosHeader, char * FuncName) { PIMAGE_NT_HEADERS pNTHeader; PIMAGE_EXPORT_DIRECTORY pExportDir; PWORD lpNameOrdinals; LPDWORD lpFunctions; DWORD * lpName; char * lpExpFuncName; DWORD i; DWORD j; char * lpFuncName; if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE) return 0; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)dosHeader + dosHeader->e_lfanew); if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) return 0; if ((pNTHeader->FileHeader.SizeOfOptionalHeader != sizeof(pNTHeader->OptionalHeader)) || (pNTHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)) return 0; DWORD exportsStartRVA, exportsEndRVA; pImageBase = (PBYTE)dosHeader; // Make pointers to 32 and 64 bit versions of the header. pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader,dosHeader->e_lfanew ); exportsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_EXPORT); exportsEndRVA = exportsStartRVA + GetImgDirEntrySize(pNTHeader, IMAGE_DIRECTORY_ENTRY_EXPORT); // Get the IMAGE_SECTION_HEADER that contains the exports. This is // usually the .edata section, but doesn''t have to be. PIMAGE_SECTION_HEADER header; header = GetEnclosingSectionHeader( exportsStartRVA, pNTHeader ); if ( !header ) return 0; INT delta; delta = (INT)(header->VirtualAddress - header->PointerToRawData); pExportDir = (PIMAGE_EXPORT_DIRECTORY)GetPtrFromRVA(exportsStartRVA, pNTHeader, pImageBase); pExportDir =(PIMAGE_EXPORT_DIRECTORY) (pNTHeader-> OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); if (pExportDir == 0) { MessageBox(NULL,"Error in GetProcAddressDirectly()",0,0); return 0; } pExportDir =(PIMAGE_EXPORT_DIRECTORY) ((DWORD)pExportDir + (DWORD)dosHeader); lpNameOrdinals =(PWORD)((DWORD)pExportDir->AddressOfNameOrdinals + (DWORD)dosHeader); lpName =(LPDWORD) (pExportDir->AddressOfNames + (DWORD)dosHeader); lpFunctions =(LPDWORD) (pExportDir->AddressOfFunctions + (DWORD)dosHeader); lpFuncName = FuncName; if(HIWORD(lpFuncName)!=0 ) { for( i = 0;i<=pExportDir->NumberOfFunctions - 1;i++) { DWORD entryPointRVA = *lpFunctions; // Skip over gaps in exported function if ( entryPointRVA == 0 ) continue; for( j = 0;j<=pExportDir->NumberOfNames-1;j++) { if( lpNameOrdinals[j] == i) { lpExpFuncName = (char *) (lpName[j] + (DWORD)dosHeader); if(strcmp((char *)lpExpFuncName,(char *)FuncName)==0) return (DWORD) (lpFunctions[i] + (DWORD)dosHeader); } } } } else { for (i = 0 ;i<=pExportDir->NumberOfFunctions - 1;i++) { if (lpFuncName == (char *)(pExportDir->Base + i)) { if (lpFunctions[i]) return (unsigned long) (lpFunctions[i] + dosHeader); } } } return 0; }在调用完函数后,不要忘记?UnloadPbDllFromMemory 来从内存中移?DLL 以释攑ֈ配的内存Q该函数q会?DLL_PROCESS_DETACH 参数调用 DLL 的入口函?DllMain 来从调用q程的地址I间卸蝲?DLL?以下?UnloadPbDllFromMemory 函数代码:
DWORD UnloadPbDllFromMemory(PIMAGE_DOS_HEADER dosHeader) { PIMAGE_NT_HEADERS pNTHeader; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)dosHeader + (DWORD)dosHeader->e_lfanew); EntryPoint = (LPENTRYPOINT)(pNTHeader->OptionalHeader.AddressOfEntryPoint + (DWORD)dosHeader); EntryPoint((HINSTANCE)dosHeader, DLL_PROCESS_DETACH, 0); return VirtualFree(dosHeader, 0, MEM_RELEASE); }
在本文附带的CZ代码中,合ƈ了一个名?hardware.dll 的动态连接库Q该动态连接库是一个获取系l硬件信息的库文Ӟ其中包括了以下函?
getmac 取得|卡 MAC VolumeNumber 取得盘h changeres 改变屏幕分辩? IsDiskInDrive 查Y׃是否插有?nbsp; DPGetDefaultPrinter 取得默认的打印机? DPSetDefaultPrinter 讄默认的打印机 getserial 取得盘的出厂序列号 getmetric 取得昄分辩? PrintStringDirect 直接向打印机发送一个串 vfpbeep ?PC 喇叭发声 getcpuid 取得 CPU ID getbios 取得L BIOS ID在示例代码中Q只调用了其中一个函?getbios 来获取主?BIOS IDQ?q里说明一下,该函数实际上好象只能?AWARD L?BIOSQ?也就是说它是d的是pȝ内存 0x000fex71 处的倹{因为其它牌子的L BIOS 的位|稍有不同,但在E序中没有进行这斚w的处理,所以在d它牌子的L BIOS 时可能会有些问题(d的内容可能不正确)。关于此 DLL 的内容和实现Q也许我会在另一文章中论及?
题外?br /> 另外Q其它一些本文未提及的非主要的函敎ͼ误行参见源代码中的注释?br />再,本文涉及 PE 文g格式斚w的知识,它们已经出了本文的范围Q具体信息可参见 MSDM 中的:
特别感谢卢春明(AmingQ在我编写本文时所作的一些技术方面的和指?/strong>
如果本文对你的开发有所帮助Qƈ且你手头恰好有零钱?/p>
不如打赏我一杯咖啡,鼓励我l分享优U的文章?br />
/* 来至 Quake 3 的源?*/ float CarmSqrt(float x){union{int intPart; float floatPart; } convertor; union{int intPart; float floatPart; } convertor2; convertor.floatPart = x; convertor2.floatPart = x; convertor.intPart = 0x1FBCF800 + (convertor.intPart >> 1); convertor2.intPart = 0x5f3759df - (convertor2.intPart >> 1); return0.5f*(convertor.floatPart + (x * convertor2.floatPart)); }
union luai_Cast {double l_d; long l_l; }; #define lua_number2int(i,d) \{volatileunion luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }
unsignedshort alpha_blender(unsignedint x,unsignedint y,unsignedint alpha){ x = (x | (x<<16)) & 0x7E0F81F; y = (y | (y<<16)) & 0x7E0F81F; unsignedint result = ((x - y) * alpha / 32 + y) & 0x7E0F81F; return(unsignedshort)((result&0xFFFF) | (result>>16)); }
unsignedlong hash(constchar *name,size_t len){unsignedlong h=(unsignedlong)len; size_t step = (len>>5)+1; for(size_t i=len; i>=step; i-=step) h = h ^ ((h<<5)+(h>>2)+(unsignedlong)name[i-1]); return h; }
int UTF8toUTF16(int c){signedchar *t=(signedchar*)&c; int ret=*t &(0x0f | ((*t>>1) &0x1f) | ~(*t>>7)); int i; assert ((*t & 0xc0) != 0x80); for(i=1;i<3;i++){if((t[i] & 0xc0)!=0x80){break; } ret=ret<<6 | (t[i] & 0x3f); }return ret; }
AGEIA的PhysX处理器是世界上首Ƅ理模拟处理器 (PPU), 该处理器解除中央处理器q行物理模拟的负担。PhysX PPU 的设计构架基于顶点的多线E操作,允许游戏开发h员进行精、流畅和动画创作和运动模拟,例如毛发、布料、液体、流体等。本文介l了如何利用PhysX SDK物理引擎开发包来实现我们仿真的效果?/p>