Sign in to follow this  
Followers 0
crashdemons

Minesweeper Trainer [WinXP]

3 posts in this topic

#1 ·  Posted (edited)

This was originally posted as an example for This Question, until I moved it here as an example.

Requirements: Windows XP Minesweeper

Memory Editing Options:

Set/Lock time elapsed (Lock meaning continually reset here)

One mine mode** (Only creates one mine on the field; standard minimum is 10)

Right-click to win** (Every square is occupied by a mine; right-click wins)

Edit the "Best Times" records.

(* = Takes effect on the NEXT game; ** = Also all subsequent games)

Other:

The script will check the file version/size of winmine.exe to determine if it is compatible, and warn you if not. A hash might actually be more efficient though.

Notes: you can undo "One Mine" and "Right-Click-Win" modes by resetting the values with the "Custom" menu in Minesweeper - since I didn't offer a direct method of editing the values.

This was based on my own findings of minesweeper and the script that w0uter wrote back in 2005.

If there's any official problem with editing the memory of this product, I'll happily stop.

I should be using something like NomadMemory I guess, but I'll worry about it later.

#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Global Const $MEM_O = 0x8
Global Const $MEM_R = 0x10
Global Const $MEM_W = 0x20

Global $sProcessName='winmine.exe'
Global $WinMinePath=@SystemDir&'\winmine.exe'
Global $WinMineSize=119808
Global $WinMineVers='5.1.2600.0'
Global $aLockText[2]=['Lock Value','Unlock Value']
Global $fLockElapsed=False


If Not FileExists($WinMinePath) Then Exit(MsgBox(16,'MineSweeper Trainer','Error: Winmine.exe was not found during file verification.'))
If Not (FileGetSize($WinMinePath)=$WinMineSize And FileGetVersion($WinMinePath)=$WinMineVers) Then
    Global $iContinue=MsgBox(32+4,'Minesweeper Trainer','Your Minesweeper version is not compatible with this program.'&@CRLF&' It is suggested that you discontinue use of this program to avoid damaging the program process.'&@CRLF&@CRLF&'Do you want to continue anyway?')
    If Not ($iContinue=6) Then Exit
EndIf


_CheckProcess(); just to make sure it's running before we do anything

Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("MineSweeper 5.1 Trainer - By CrashDemons", 361, 156+20, 192, 124)
GUISetOnEvent(-3,'GUIOnEvent_Close')
$Input1 = GUICtrlCreateInput("0", 85, 0, 96, 21, BitOR($ES_AUTOHSCROLL,$ES_NUMBER))
GUICtrlSetLimit(-1, 3)
$Label1 = GUICtrlCreateLabel("Time Elapsed: ", 2, 3, 77, 17)
$Button1 = GUICtrlCreateButton("Set Value", 182, 0, 72, 21, $WS_GROUP)
GUICtrlSetOnEvent(-1,'GUICtrlOnEvent_SetElapsed')
$Button2 = GUICtrlCreateButton("Lock Value", 255, 0, 101, 21, $WS_GROUP)
GUICtrlSetOnEvent(-1,'GUICtrlOnEvent_LockElapsed')


$Button4 = GUICtrlCreateButton("Only 1 mine (on New Game)", 182, 20, 356-182, 21, $WS_GROUP)
GUICtrlSetOnEvent(-1,'GUICtrlOnEvent_SetOneMine')
$Button5 = GUICtrlCreateButton("Right-click win (on New Game)", 0, 20, 356-182, 21, $WS_GROUP)
GUICtrlSetOnEvent(-1,'GUICtrlOnEvent_SetAllMines')


$Group1 = GUICtrlCreateGroup("Fastest Minesweeper Times", 2, 24+20, 354, 129)
$Label2 = GUICtrlCreateLabel("Beginner: ", 18, 49+20, 52, 17)
$Input2 = GUICtrlCreateInput("0", 114, 46+20, 70, 21, BitOR($ES_AUTOHSCROLL,$ES_NUMBER))
GUICtrlSetLimit(-1, 3)
$Label5 = GUICtrlCreateLabel("seconds", 189, 49+20, 44, 17)
$Input3 = GUICtrlCreateInput("Anonymous", 247, 45+20, 100, 21, $ES_AUTOHSCROLL)
GUICtrlSetLimit(-1, 32)
$Label3 = GUICtrlCreateLabel("Intermediate: ", 18, 76+20, 68, 17)
$Input4 = GUICtrlCreateInput("0", 114, 73+20, 70, 21, BitOR($ES_AUTOHSCROLL,$ES_NUMBER))
GUICtrlSetLimit(-1, 3)
$Label4 = GUICtrlCreateLabel("seconds", 189, 76+20, 44, 17)
$Input5 = GUICtrlCreateInput("Anonymous", 247, 72+20, 100, 21,$ES_AUTOHSCROLL)
GUICtrlSetLimit(-1, 32)
$Label6 = GUICtrlCreateLabel("Expert: ", 18, 102+20, 40, 17)
$Input6 = GUICtrlCreateInput("0", 114, 99+20, 70, 21, BitOR($ES_AUTOHSCROLL,$ES_NUMBER))
GUICtrlSetLimit(-1, 3)
$Label7 = GUICtrlCreateLabel("seconds", 189, 102+20, 44, 17)
$Input7 = GUICtrlCreateInput("Anonymous", 247, 98+20, 100, 21, $ES_AUTOHSCROLL)
GUICtrlSetLimit(-1, 32)
$Button3 = GUICtrlCreateButton("Set Values", 247, 125+20, 100, 21, $WS_GROUP)
GUICtrlSetOnEvent(-1,'GUICtrlOnEvent_SetScores')
GUICtrlCreateGroup("", -99, -99, 1, 1)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
    If $fLockElapsed Then _WriteProcess(_CheckProcess(),0x0100579C,Int(GUICtrlRead($Input1)),4)
    Sleep(300)
WEnd


Func GUIOnEvent_Close()
    Exit
EndFunc
Func GUICtrlOnEvent_SetElapsed()
    _WriteProcess(_CheckProcess(),0x0100579C,Int(GUICtrlRead($Input1)),4)
EndFunc
Func GUICtrlOnEvent_LockElapsed()
    GUICtrlSetState($Button2,$GUI_DISABLE)
    $fLockElapsed=Not $fLockElapsed
    Switch $fLockElapsed
        Case True
            ;locked
            GUICtrlSetState($Input1,$GUI_DISABLE)
            GUICtrlSetState($Button1,$GUI_DISABLE)
            GUICtrlSetData($Button2,$aLockText[1])
        Case False
            ;unlocked
            GUICtrlSetState($Input1,$GUI_ENABLE)
            GUICtrlSetState($Button1,$GUI_ENABLE)
            GUICtrlSetData($Button2,$aLockText[0])
    EndSwitch
    GUICtrlSetState($Button2,$GUI_ENABLE)
EndFunc
Func GUICtrlOnEvent_SetScores()
    GUICtrlSetState($Button3,$GUI_DISABLE)
    ; I *REALLY* don't want to have to bother with disabling this entire section of the form
    Local $Score1=Int(GUICtrlRead($Input2))
    Local $Score2=Int(GUICtrlRead($Input4))
    Local $Score3=Int(GUICtrlRead($Input6))
    Local $Name1=GUICtrlRead($Input3)
    Local $Name2=GUICtrlRead($Input5)
    Local $Name3=GUICtrlRead($Input7)
    _WriteProcess(_CheckProcess(),0x010056CC,$Score1,4)
    _WriteProcess(_CheckProcess(),0x010056D0,$Score2,4)
    _WriteProcess(_CheckProcess(),0x010056D4,$Score3,4)

    Local $nul=Chr(0)
    $Name1=StringToBinary($Name1&$nul,2)
    $Name2=StringToBinary($Name2&$nul,2)
    $Name3=StringToBinary($Name3&$nul,2)
    _WriteProcess(_CheckProcess(),0x010056D8,$Name1,BinaryLen($Name1))
    _WriteProcess(_CheckProcess(),0x01005718,$Name2,BinaryLen($Name2))
    _WriteProcess(_CheckProcess(),0x01005758,$Name3,BinaryLen($Name3))

    GUICtrlSetState($Button3,$GUI_ENABLE)
EndFunc
Func GUICtrlOnEvent_SetOneMine()
    ;0x010056A4 is the number of mines to place - which you can normally change on custom games (winmine GUI minimum is 10)
    _WriteProcess(_CheckProcess(),0x010056A4,1,4)
EndFunc
Func GUICtrlOnEvent_SetAllMines()
    Local $w=Execute(_ReadProcess(_CheckProcess(), 0x01005334, 1));cols currently drawn
    Local $h=Execute(_ReadProcess(_CheckProcess(), 0x01005338, 1));rows currently drawn (We'll assume this is below 255)
    Local $MaximumMines=$w*$h
    _WriteProcess(_CheckProcess(),0x010056A4,$MaximumMines,4)
EndFunc



Func _CheckProcess()
    Local $pid=ProcessExists($sProcessName)
    If $pid=0 Then
        Switch MsgBox(32+4,'Minesweeper Trainer','Minesweeper does not appear to be running.'&@CRLF&@CRLF&'Do you want to start it?')
            Case 6
                $pid=Run($WinMinePath)
            Case Else
                If $fLockElapsed Then GUICtrlOnEvent_LockElapsed()
        EndSwitch
    EndIf
    Return $pid
EndFunc


Func _WriteProcess($pid,$address,$value,$length)
    If $pid=0 Then Return
    $v_Open = _MemOpen($MEM_W + $MEM_O, False, $pid)
    $v_Read = _MemWrite($v_Open, $address, $value, $length)
    $v_Close = _MemClose($v_Open)
EndFunc
Func _ReadProcess($pid,$address,$length)
    If $pid=0 Then Return
    $v_Open = _MemOpen($MEM_R+$MEM_O ,False, $pid)
    $v_Read = _MemRead($v_Open, $address, $length)
    $v_Close = _MemClose($v_Open)
    Return $v_Read
EndFunc




Func _MemOpen($i_dwDesiredAccess, $i_bInheritHandle, $i_dwProcessId)
    $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', $i_dwDesiredAccess, 'int', $i_bInheritHandle, 'int', $i_dwProcessId)
    If @error Then
        SetError(1)
        Return 0
    EndIf
    Return $ai_Handle[0]
EndFunc ;==> _MemOpen()

Func _MemRead($i_hProcess, $i_lpBaseAddress, $i_nSize, $v_lpNumberOfBytesRead = '')
    Local $v_Struct = DllStructCreate ('byte[' & $i_nSize & ']')
    DllCall('kernel32.dll', 'int', 'ReadProcessMemory', 'int', $i_hProcess, 'int', $i_lpBaseAddress, 'int', DllStructGetPtr ($v_Struct, 1), 'int', $i_nSize, 'int', $v_lpNumberOfBytesRead)
    Local $v_Return = DllStructGetData ($v_Struct, 1)
    $v_Struct=0
    Return $v_Return
EndFunc ;==> _MemRead()

Func _MemWrite($i_hProcess, $i_lpBaseAddress, $v_Inject, $i_nSize, $v_lpNumberOfBytesRead = '')
    Local $v_Struct = DllStructCreate ('byte[' & $i_nSize & ']')
    DllStructSetData ($v_Struct, 1, $v_Inject)
    $i_Call = DllCall('kernel32.dll', 'int', 'WriteProcessMemory', 'int', $i_hProcess, 'int', $i_lpBaseAddress, 'int', DllStructGetPtr ($v_Struct, 1), 'int', $i_nSize, 'int', $v_lpNumberOfBytesRead)
    $v_Struct=0
    Return $i_Call[0]
EndFunc ;==> _MemWrite()

Func _MemClose($i_hProcess)
    $av_CloseHandle = DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $i_hProcess)
    Return $av_CloseHandle[0]
EndFunc ;==> _MemClose()

Posted ImagePosted Image

Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Share this post


Link to post
Share on other sites



Tested and it works fine on XP, cool.

I'll check out your memory functions when I get some time. I got to improve my DllCall+winapi understanding. :D

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

They're not my memory functions, I stole them from w0uter. (as per my note)

But I'd like to know what the advantages and disadvantages of using NomadMemory or a different memory UDF is.

The current memory functions fine for me - and unless someone can provide issue with it, there's not alot of a reason to change it.

There are other edits available in minesweeper, but some of the other values either aren't important enough to edit or are hard to track down.

And, as with minesweeper, if you have a program where you can see a unique value and see when it changes, or you can change an unknown value on-demand while using the program regularly - you can usually track down and change it in a method such as this.

Eg: there are memory edits available for Freecell, Spider Solitaire, etc. (and of course more advanced games)

By the way, why did Koda add the WS_GROUP style to the button controls? - I don't see the necessity unless I'm missing something.

Edited by crashdemons

My Projects - WindowDarken (Darken except the active window) Yahsmosis Chat Client (Discontinued) StarShooter Game (Red alert! All hands to battlestations!) YMSG Protocol Support (Discontinued) Circular Keyboard and OSK example. (aka Iris KB) Target Screensaver Drive Toolbar Thingy Rollup Pro (Minimize-to-Titlebar & More!) 2D Launcher physics example Ascii Screenshot AutoIt3 Quine Example ("Is a Quine" is a Quine.) USB Lock (Another system keydrive - with a toast.)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0