⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datatrack.pas

📁 斗地主源代码.Delphi编写.....
💻 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 + -