📄 datatrack.pas
字号:
unit DataTrack;
//内存测试结果
{
$0041CC40 座签地址
数值含义:
右 00
下 01
左 02
座签位置0
$0041D024 手中牌面
$0041D164 手中牌数量
$0041D178 出牌牌面
$0041D2B8 出牌数量
座签位置1
$0041D4A0 手中牌面
$0041D5E0 手中牌数量
$0041D5F4 出牌牌面
$0041D734 出牌数量
座签位置2
$0041D91C 手中牌面
$0041DA5C 手中牌数量
$0041DA70 出牌牌面
$0041DBB0 出牌数量
$00422960 底牌牌面
当我在0的时候,数据存放顺序为:
我
左
右
当我在1的时候,数据存放顺序为:
右
我
左
当我在2的时候,数据存放顺序为:
左
右
我
}
interface
uses
Windows, Types, SysUtils, TLHelp32, Dialogs, Classes, StrUtils;
function MyFun_GetProcessID(ProcessName: string): Cardinal;
function GetAllDataAdr: Boolean;
function GetDataFromRam(DSAddres: Cardinal; var RamDataBack: Cardinal): Boolean;
function GetPokeListFromRam(DSAddres, CardCount: Cardinal): TStringList;
var
AdrSelfSeatNum: Cardinal;
SelfSeatNum: Cardinal;
AdrSelfPoke, AdrLeave: Cardinal;
AdrSelfCount, AdrSelfOut, AdrSelfOutCount: Cardinal;
AdrLeftCount, AdrLeftOut, AdrLeftOutCount: Cardinal;
AdrRightCount, AdrRightOut, AdrRightOutCount: Cardinal;
ProcessID: Cardinal;
implementation
uses
Main;
{-------------------------------------------------------------------------------
过程名: MyFun_GetProcessID
说明: 获取目标进程ID。
作者: who&who
日期: 2005.03.11
参数: ProcessName: string
返回值: Cardinal
-------------------------------------------------------------------------------}
function MyFun_GetProcessID(ProcessName: string): Cardinal;
var
FSnapshotHandle: THandle;
FProcessEntry32: TProcessEntry32;
Ret: Boolean;
TmpProcessName: string;
TmpProcessID: DWORD;
begin
TmpProcessID := 0; //如果没有找到
//创建系统快照
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
//先初始化 FProcessEntry32 的大小
FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
Ret := Process32First(FSnapshotHandle, FProcessEntry32);
//循环枚举出系统开启的所有进程,找出“ProcessName”所指定的进程
while Ret do
begin
TmpProcessName := ExtractFileName(FProcessEntry32.szExeFile);
if TmpProcessName = ProcessName then
begin
TmpProcessID := FProcessEntry32.th32ProcessID;
Break;
end;
Ret := Process32Next(FSnapshotHandle, FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
Result := TmpProcessID;
end;
{-------------------------------------------------------------------------------
过程名: CardCompare
说明: 在既定的扑克序列表中比对,并返回对应的Index。
作者: who&who
日期: 2005.03.11
参数: CardExample: Cardinal
返回值: Integer
-------------------------------------------------------------------------------}
function CardCompare(CardExample: Cardinal): Integer;
var
J: Integer;
begin
Result := -1;
for J := 0 to High(PokeTemplet) do
begin
if CardExample = PokeTemplet[J] then
begin
Result := J;
Exit;
end;
end;
end;
{-------------------------------------------------------------------------------
过程名: GetAllDataAdr
说明: 初始化内存所有数据地址。
作者: who&who
日期: 2005.03.11
参数: 无
返回值: Boolean
-------------------------------------------------------------------------------}
function GetAllDataAdr: Boolean;
var
ReadSucceed: LongBool;
RepeatTime: Byte;
TempLeave: Cardinal;
begin
Result := True;
AdrSelfSeatNum := $0041CC40; //座签号码地址
AdrLeave := $00422960; //底牌牌面地址
RepeatTime := 0;
repeat
if not GetDataFromRam(AdrSelfSeatNum, SelfSeatNum) then
begin
Result := False;
Exit;
end;
ReadSucceed := True;
inc(RepeatTime);
case SelfSeatNum of
0:
begin
AdrSelfPoke := $0041D024; //自己手中牌面地址
AdrSelfCount := $0041D164; //自己手中牌数地址
AdrSelfOut := $0041D178; //自己出牌牌面地址
AdrSelfOutCount := $0041D2B8; //自己出牌牌数地址
AdrLeftCount := $0041D5E0; //左方手中牌数地址
AdrLeftOut := $0041D5F4; //左方出牌牌面地址
AdrLeftOutCount := $0041D734; //左方出牌牌数地址
AdrRightCount := $0041DA5C; //右方手中牌数地址
AdrRightOut := $0041DA70; //右方出牌牌面地址
AdrRightOutCount := $0041DBB0; //右方出牌牌数地址
end;
1:
begin
AdrRightCount := $0041D164; //右方手中牌数地址
AdrRightOut := $0041D178; //右方出牌牌面地址
AdrRightOutCount := $0041D2B8; //右方出牌牌数地址
AdrSelfPoke := $0041D4A0; //自己手中牌面地址
AdrSelfCount := $0041D5E0; //自己手中牌数地址
AdrSelfOut := $0041D5F4; //自己出牌牌面地址
AdrSelfOutCount := $0041D734; //自己出牌牌数地址
AdrLeftCount := $0041DA5C; //左方手中牌数地址
AdrLeftOut := $0041DA70; //左方出牌牌面地址
AdrLeftOutCount := $0041DBB0; //左方出牌牌数地址
end;
2:
begin
AdrLeftCount := $0041D164; //左方手中牌数地址
AdrLeftOut := $0041D178; //左方出牌牌面地址
AdrLeftOutCount := $0041D2B8; //左方出牌牌数地址
AdrRightCount := $0041D5E0; //右方手中牌数地址
AdrRightOut := $0041D5F4; //右方出牌牌面地址
AdrRightOutCount := $0041D734; //右方出牌牌数地址
AdrSelfPoke := $0041D91C; //自己手中牌面地址
AdrSelfCount := $0041DA5C; //自己手中牌数地址
AdrSelfOut := $0041DA70; //自己出牌牌面地址
AdrSelfOutCount := $0041DBB0; //自己出牌牌数地址
end;
else
//读取失败
ReadSucceed := False;
end;
//根据底牌地址数据来判定是否目标窗口数据初始化完毕
if GetDataFromRam(AdrLeave, TempLeave) and ReadSucceed then
begin
ReadSucceed := False;
if CardCompare(TempLeave) >= 0 then
begin
if GetDataFromRam(AdrLeave + 8, TempLeave) then
begin
if CardCompare(TempLeave) >= 0 then
begin
if GetDataFromRam(AdrLeave + 16, TempLeave) then
begin
if CardCompare(TempLeave) >= 0 then
begin
ReadSucceed := True;
end
end;
end;
end;
end;
end;
//由于目标窗口需要一定的时间来完全打开并初始化各种数据,所以在读取目标
//窗口内存数据错误或失败时,延时200毫秒,再次读取。
if not ReadSucceed then
Delay(200);
until ReadSucceed or (RepeatTime > 30);
end;
{-------------------------------------------------------------------------------
过程名: GetDataFromRam
说明: 从内存中读取单一数据,Cardinal类型,如读取失败,返回False。
作者: who&who
日期: 2005.03.11
参数: DSAddres: Cardinal; var RamDataBack: Cardinal
返回值: Boolean
-------------------------------------------------------------------------------}
function GetDataFromRam(DSAddres: Cardinal; var RamDataBack: Cardinal): Boolean;
var
DataBuffer: Cardinal;
hProcess: Cardinal;
ReadSucceed: LongBool;
lpNumberOfBytesRead: Cardinal;
begin
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessID);
ReadSucceed := ReadProcessMemory(hProcess, Pointer(DSAddres), @DataBuffer, SizeOf(DataBuffer), lpNumberOfBytesRead);
if ReadSucceed then
begin
RamDataBack := DataBuffer;
Result := True;
end
else
begin
RamDataBack := 4294967295;
Result := False;
end;
CloseHandle(hProcess);
end;
{-------------------------------------------------------------------------------
过程名: GetPokeListFromRam
说明: 从内存中读取CardCount所指定数量的扑克数据。
作者: who&who
日期: 2005.03.11
参数: DSAddres, CardCount: Cardinal
返回值: TStringList
-------------------------------------------------------------------------------}
function GetPokeListFromRam(DSAddres, CardCount: Cardinal): TStringList;
var
PokeIndex, I: Integer;
NewPokeOut: Cardinal;
begin
Result := TStringList.Create;
for I := 1 to CardCount do
begin
if not GetDataFromRam(DSAddres, NewPokeOut) then
Break;
PokeIndex := CardCompare(NewPokeOut);
if PokeIndex = -1 then
Break;
Result.Add(RightStr('0' + IntToStr(PokeIndex), 2));
DSAddres := DSAddres + 8; //根据观察,斗地主程序数据存放间隔为8个字节
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -