我记得2013年的时候 写过一个修改欲火银河2HD的飞船数据的文章
飞船数据是ships.bin这几天心烦又偷偷玩了一下,又想改装备items.bin,然后时间少不想自己研究
于是看了下别人怎么改,确实有人改,但是写出来乱七八糟,也可能是自己的文档习惯不同吧
于是:
欲火银河2全高清硬盘版
Galaxy on Fire 2™ Full HD
不说那么多,二进制打开items.bin文件:
出于偷懒,我写了个程序查找0-1-2-3-...这样的偏移,以得到固定的存储空间,实际上不存在
稍微观察一下也不难发现,红色箭头所示,总是有0x00000000 0x00000000 0xXXXXXXXX 这样的三个DWORD
再看第一个红色箭头,值是0x1E000000,转换为x86字节序是0x0000001E,十进制的30,数一下选中部分的DWORD数量
正好也是30,再看绿色箭头不难看出,总是一个DWORD+一个DWORD这样一对一对的奸夫淫妇
而且,第一个DWORD为零时,第二个DWORD是0,1,2,3...这样递增的,像飞船的存储方式,可以认为是ID
那么暂定为非固定大小结构体:
typedef struct _tagValue{ DWORD Flags; // property flags DWORD Value; // property value } VALUE, *PVALUE; typedef struct _tagEquipment{ // "items.bin" union { struct { DWORD Reserved1; // 0x00000000 DWORD Reserved2; // 0x00000000 DWORD NumOfDWORD; // how many dwords followed VALUE Values[1]; }; DWORD Dummy[1]; }; } EQUIP, *PEQUIP;
算了,贴上DLL部分的代码,也好做备份,有空的时候传到资源,大家有需要的就狠狠的下吧
(目前仅限修改飞船和物品)
1.gof2.h
// **************************************************************************************************** // 文件: GOF2\\gof2.h // 作者: 虎胆游侠(blog.csdn.net/prsniper; [email protected]) // 时间: 2015-11-13 05:45:21 // 注释: // 这只是一个.h文件, 用力包含吧 // **************************************************************************************************** #ifndef __GOF2HD_H_ #define __GOF2HD_H_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #ifdef __GOF2HD_DLL_INC_ #define __V32_DLL_API_ // 内部编译标识 #endif #include "v32_prefix.h" // 预编译宏, 切换内外部编译 // auto include #include "v32_api.h" #include "types.h" // exports V32API int __stdcall CacheOpen(const char *szFileName); V32API int __stdcall CacheSave(const char *szFileName, int bRelease); V32API int __stdcall GetSpace(DWORD dwSpaceId, PSHIPS *ppShips); V32API int __stdcall GetShipValue(PSHIPS pShips, int dwIndex, DWORD *pdwValue); V32API int __stdcall SetShipValue(PSHIPS pShips, int dwIndex, DWORD dwValue); V32API int __stdcall GetItem(DWORD dwIndex, PEQUIP *ppItem); V32API int __stdcall GetItemValue(PEQUIP pItem, int dwIndex, DWORD *pdwValue); V32API int __stdcall SetItemValue(PEQUIP pItem, int dwIndex, DWORD dwValue); #include "v32_subfix.h" // 预编译宏, 切换内外部编译 #endif
// **************************************************************************************************** // 文件: GOF2\\types.h // 作者: 虎胆游侠(blog.csdn.net/prsniper; [email protected]) // 时间: 2015-11-13 05:35:15 // 注释: // 类型定义 // **************************************************************************************************** #ifndef __GOF2HD_TYPE_H_ #define __GOF2HD_TYPE_H_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 //typedef unsigned long ThisIsAFuckingType; //typedef unsigned long FuckYouAndYourMotherFatherSisterYourSonAndYourDaughter; //typedef unsigned long DWORD; //typedef unsigned long DOUBLEWORD; //typedef unsigned long DWORD; //typedef unsigned long DWORD; //typedef unsigned long DWORD; //typedef unsigned long DWORD; //typedef unsigned int DWORD; // Multiple typedef alias type is legal, but this one typedef unsigned long DWORD; typedef unsigned char BYTE; // Begin type definitions #pragma pack(1) typedef struct _tagUnits{ union { struct { BYTE Byte1; BYTE Byte2; BYTE Byte3; BYTE Byte4; }; DWORD Value; }; } UNITS, *PUNITS; #pragma pack() typedef struct _tagValue{ DWORD Flags; // property flags DWORD Value; // property value } VALUE, *PVALUE; typedef struct _tagEquipment{ // "items.bin" union { struct { DWORD Reserved1; // 0x00000000 DWORD Reserved2; // 0x00000000 DWORD NumOfDWORD; // how many dwords followed VALUE Values[1]; }; DWORD Dummy[1]; }; } EQUIP, *PEQUIP; typedef struct _tagShips{ // "ships.bin" union { struct { DWORD Identifier; // spaceship id DWORD Capacity; // HP DWORD Volume; // cargo hold space DWORD Price; // standard price DWORD Primary; // max 1st weapon count DWORD Secondary; // max 2nd weapon count DWORD Turret; // max turret count DWORD Equipment; // equipment capacity DWORD Operation; // operability }; DWORD Dummy[1]; }; } SHIPS, *PSHIPS; // End type definitions #include "v32_subfix.h" // 预编译宏, 切换内外部编译 #endif
// **************************************************************************************************** // 文件: GOF2\\gof2.cpp // 作者: 虎胆游侠(blog.csdn.net/prsniper; [email protected]) // 时间: 2015-11-13 05:50:05 // 注释: // 操作函数 // **************************************************************************************************** #include <stdio.h> #include <malloc.h> #include "v32_api.h" //using namespace Valiant; #define __GOF2HD_DLL_INC_ #include "gof2.h" void *g_pBuffer = NULL; // global data int g_dwCount = 0; // byte size // 转换字节序 DWORD fnTurnBytes(DWORD dwNumber) { UNITS u1, u; u1.Value = dwNumber; u.Byte1 = u1.Byte4; // dwNumber << 24; // 低位补零 u.Byte2 = u1.Byte3; // (dwNumber << 8) & 0xFF0000; u.Byte3 = u1.Byte2; // (dwNumber >> 8) & 0xFF00; u.Byte4 = u1.Byte1; // (dwNumber >> 24) & 0xFF; return u.Value; } V32API int __stdcall CacheOpen(const char *szFileName) { FILE *pf; long dwSize; void *p; pf = fopen(szFileName, "rb"); if(pf == NULL) { return 0; } fseek(pf, 0, SEEK_END); dwSize = ftell(pf); if(dwSize <= 0) { fclose(pf); return -1; } p = malloc(dwSize); if(p == NULL) { fclose(pf); return -2; } fseek(pf, 0, SEEK_SET); fread(p, sizeof(char), dwSize, pf); fclose(pf); if(g_pBuffer) { free(g_pBuffer); g_pBuffer = p; g_dwCount = (int)dwSize; } return 1; } V32API int __stdcall CacheSave(const char *szFileName, int bRelease) { FILE *pf; int dwRet; if(szFileName != NULL) { if(g_pBuffer == NULL) { return 0; } pf = fopen(szFileName, "wb"); dwRet = fwrite(g_pBuffer, sizeof(char), g_dwCount, pf); fclose(pf); if(dwRet != g_dwCount) { return -1; } } if(bRelease) { //Valiant::SafeFree(g_pBuffer); SafeFree(g_pBuffer); // using namespace Valiant; g_dwCount = 0; return 2; } return 1; } V32API int __stdcall GetSpace(DWORD dwSpaceId, PSHIPS *ppShips) { union { PSHIPS pShips; void *p; }; int dwCount; if(ppShips == NULL) { return 0; } p = g_pBuffer; if(pShips == NULL) { return -1; } dwSpaceId = fnTurnBytes(dwSpaceId); dwCount = 0; while(dwCount < g_dwCount) { if(pShips->Identifier == dwSpaceId) { *ppShips = pShips; return 1; } dwCount += sizeof(SHIPS); pShips++; } //if(dwCount >= g_dwCount) return -2; // not found } V32API int __stdcall GetShipValue(PSHIPS pShips, int dwIndex, DWORD *pdwValue) { if(pShips == NULL || pdwValue == NULL) { return 0; } if(dwIndex >= (sizeof(SHIPS) / sizeof(DWORD)) || dwIndex < 0) { return -1; } *pdwValue = fnTurnBytes(pShips->Dummy[dwIndex]); return 1; } V32API int __stdcall SetShipValue(PSHIPS pShips, int dwIndex, DWORD dwValue) { if(pShips == NULL) { return 0; } if(dwIndex >= (sizeof(SHIPS) / sizeof(DWORD)) || dwIndex < 0) { return -1; } pShips->Dummy[dwIndex] = fnTurnBytes(dwValue); return 1; } V32API int __stdcall GetItem(DWORD dwIndex, PEQUIP *ppItem) { union { PEQUIP pItem; int dwNum; char *p1; void *p; }; union { int dwCount; void *pDummy; }; if(ppItem = NULL) { return 0; } p = g_pBuffer; if(pItem == NULL) { return -1; } pDummy = g_pBuffer; while(dwIndex) { p1 += (pItem->NumOfDWORD + 3) * sizeof(DWORD); if((dwNum - dwCount) >= g_dwCount) { return -2; // not found } dwIndex--; } *ppItem = pItem; return 1; } V32API int __stdcall GetItemValue(PEQUIP pItem, int dwIndex, DWORD *pdwValue) { int dwRet; if(pItem == NULL) { return 0; } dwRet = (int)fnTurnBytes(pItem->NumOfDWORD) + 3; if(pdwValue == NULL) { return dwRet; } if(dwIndex >= dwRet || dwIndex < 0) { return -1; } *pdwValue = fnTurnBytes(pItem->Dummy[dwIndex]); return 1; } V32API int __stdcall SetItemValue(PEQUIP pItem, int dwIndex, DWORD dwValue) { int dwRet; if(pItem == NULL) { return 0; } dwRet = (int)fnTurnBytes(pItem->NumOfDWORD) + 3; if(dwIndex >= dwRet || dwIndex < 0) { return -1; } pItem->Dummy[dwIndex] = fnTurnBytes(dwValue); return 1; }
// **************************************************************************************************** // 文件: GOF2\\api.cpp // 作者: 虎胆游侠(blog.csdn.net/prsniper; [email protected]) // 时间: 2015-11-13 06:42:13 // 注释: // 入口模块 // **************************************************************************************************** //#include <windows.h> #include "v32_api.h" #define __GOF2HD_DLL_INC_ #include "gof2.h" using namespace Valiant; #ifdef _DEBUG #pragma comment(lib, "Debug\\V32.lib") #else #pragma comment(lib, "Release\\V32.lib") #endif // *** DLL入口函数 *** //BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) int __stdcall DllMain(VT32 hModule, VT32 ul_reason_for_call, VT32 lpReserved) { //printf("DllMain(%p, %d, %p);\r\n", hModule, ul_reason_for_call, lpReserved); switch(ul_reason_for_call.Value32){ case V32_PROCESS_ATTACH: case V32_PROCESS_DETACH: case V32_THREAD_ATTACH: // 线程创建并调用 case V32_THREAD_DETACH: // 线程结束并解除 break; default: return 0; // FALSE } return 1; // TRUE }
就这样吧