我记得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;
说到这里应该可以自己写程序编辑这些bin了吧
算了,贴上DLL部分的代码,也好做备份,有空的时候传到资源,大家有需要的就狠狠的下吧
(目前仅限修改飞船和物品)
1.gof2.h
// ****************************************************************************************************
// 文件: GOF2\\gof2.h
// 作者: 虎胆游侠(blog.csdn.net/prsniper; cto@renshenguo.com)
// 时间: 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
2.types.h
// ****************************************************************************************************
// 文件: GOF2\\types.h
// 作者: 虎胆游侠(blog.csdn.net/prsniper; cto@renshenguo.com)
// 时间: 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
3.gof2.cpp
// ****************************************************************************************************
// 文件: GOF2\\gof2.cpp
// 作者: 虎胆游侠(blog.csdn.net/prsniper; cto@renshenguo.com)
// 时间: 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;
}
4.api.cpp
// ****************************************************************************************************
// 文件: GOF2\\api.cpp
// 作者: 虎胆游侠(blog.csdn.net/prsniper; cto@renshenguo.com)
// 时间: 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
}
这里用到了V32.dll基础类库,不过都是memcpy啊之类的自己用汇编写裸函数,同时封装为C++基类,还有一些SafeFree之类的宏定义和类型声明
就这样吧