为什么使用TexturePackerGUI
https://www.codeandweb.com/texturepacker
1 OpenGL载入纹理图片时,所用内存会自动扩张到2的N次方。比如,一张图片的大小为10 10像素,OpenGL会按照16*16的规格将图片载入到内存中;如果图片大小为64 65,那么就会按照64 128载入了,这就造成了内存的无必要开销。所以在游戏开发使用图片资源时,我们要尽量保证图片的大小在接近且不大于2的整数倍,理想状态下,如果每一张图的长宽都恰好是2的n次方数值,就不会有任何浪费了。TexturePacker正是帮助我们将图片资源进行这样优化的一款软件
2 TexturePacker不仅能帮助我们在加载图片时节省内存,它将很多小图拼接成一张大图后,合成的大图会比之前所有的散图所占用的物理存储更小,也许一堆散图的大小为20KB,将它们合成一张大图后可能就变成了10KB,这样便从而通过减小图片资源物理存储大小起到压缩游戏安装包的作用
3 将很多小图拼接成一张大图,载入内存时一次载入,提高了载入速度
如,原本17张图片占用151k合并后占用51k
TexturePackerGUI 注册分析
TexturePackerGUI免费的pro版本只能试用7天,通过调试得知TexturePackerGUI会上报硬件信息的md5到服务器,服务器生成7天的授权保存在本地。
信息存储在 HKEY_CURRENT_USER\SOFTWARE\code-and-web.de\TexturePacker
补丁实现
观察到TexturePackerGUI采集的信息包含c盘磁盘大小, 那么就有一个很简单的思路,如果试用的授权过期则清除注册表保存的内容,同时hook GetVolumeInformationA让生成的机器7天变一次
TexturePackerGUI依赖winmm.dll所以利用aheadlib生成fake winmm.dll
BOOL
WINAPI
mine_GetVolumeInformationA(
_In_opt_ LPCSTR lpRootPathName,
_Out_writes_opt_(nVolumeNameSize) LPSTR lpVolumeNameBuffer,
_In_ DWORD nVolumeNameSize,
_Out_opt_ LPDWORD lpVolumeSerialNumber,
_Out_opt_ LPDWORD lpMaximumComponentLength,
_Out_opt_ LPDWORD lpFileSystemFlags,
_Out_writes_opt_(nFileSystemNameSize) LPSTR lpFileSystemNameBuffer,
_In_ DWORD nFileSystemNameSize
) {
if (lpRootPathName && 0 == _stricmp(lpRootPathName, "c:\\") && lpVolumeSerialNumber)
{
*lpVolumeSerialNumber = time(NULL) / (60 * 60 * 24 * 7);
return TRUE;
}
return FALSE;
}
void hook_texture() {
OutputDebugStringA(__FUNCTION__);
auto h = LoadLibraryW(L"TexturePackerLib.dll");
if (h)
{
IATHook((void*)h, (char*)"kernel32.dll", (char*)"GetVolumeInformationA", mine_GetVolumeInformationA, NULL);
DWORD dwType;
WCHAR reg_Data[MAX_PATH] = {0};
DWORD cbData;
if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, L"SOFTWARE\\code-and-web.de\\TexturePacker\\licensing\\data", L"expiryDate", &dwType, reg_Data, &cbData)) {
SYSTEMTIME SystemTime;
GetLocalTime(&SystemTime);
WCHAR cur_time[MAX_PATH] = { 0 };
wsprintf(cur_time, L"%d-%02d-%02d", SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay);
OutputDebugStringW(reg_Data);
OutputDebugStringW(cur_time);
if (_wcsicmp(cur_time, reg_Data) > 0)
{
OutputDebugStringA("delete");
SHDeleteKey(HKEY_CURRENT_USER, L"SOFTWARE\\code-and-web.de\\TexturePacker");
}
}
}
}
void hook(){
hook_texture();
}
最后把fake winmm.dll和TexturePackerGUI.exe放一起, 个人自测最新的6.0.2版本已经免费续杯了4个月