Attribute VB_Name = "WarpBot"
Option Explicit

Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As Any, lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As String, ByVal nSize As Long, ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Private Declare Function SetTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal hWnd As Long, ByVal nIDEvent As Long) As Long

Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal wndrpcPrev As Long, ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long
Private Declare Function DestroyWindow Lib "user32" (ByVal hWnd As Long) As Long

Private Enum WM_MSGS
    WM_LBUTTONDOWN = &H201
    WM_PAINT = &HF
    WM_SHOWWINDOW = &H18
    WM_SIZE = &H5
    WM_ACTIVATEAPP = &H1C
    WM_ACTIVATE = &H6
    WM_KILLFOCUS = &H8
    WM_NCPAINT = &H85
    WM_KEYUP = &H101
    WM_KEYDOWN = &H100
    WM_MOUSEMOVE = &H200
    WM_QUIT = &H12
    WM_CLOSE = &H10
    WM_TIMER = &H113
End Enum

Private Const GWL_WNDPROC = -4

Public Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessId As Long
    dwThreadID As Long
End Type
Private Type STARTUPINFO
    cb As Long
    lpReserved As String
    lpDesktop As String
    lpTitle As String
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Private Pointer         As String * 4
Private lBuff           As Long
Private StartInfo       As STARTUPINFO
Private ProcInfo        As PROCESS_INFORMATION
Private ActiveProcess   As PROCESS_INFORMATION
Private OldWndProc      As Long

Private WindowHandle    As Long

Private BaseAddy1       As Long
Private X1              As Long
Private Y1              As Long

'My own control window

Private Function LoadWindow() As Long
    Dim hWnd As Long

    hWnd = CreateWindowEx(0, "#32770", "WarpBot", 0&, 0, 0, 1, 1, 0&, 0&, App.hInstance, 0&)
    OldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)

    LoadWindow = hWnd
End Function

Private Sub UnloadWindow(WindowHandle As Long)
    SetWindowLong WindowHandle, GWL_WNDPROC, OldWndProc
    Call DestroyWindow(WindowHandle)
End Sub

'Timer setup

Public Function StartWarping() As Boolean
    If RunProcess("subspace.bin") = True Then
        WindowHandle = LoadWindow
        SetTimer WindowHandle, 123, 100, AddressOf WindowProc
        StartWarping = True
    ElseIf RunProcess("subspace.exe") = True Then
        WindowHandle = LoadWindow
        SetTimer WindowHandle, 123, 100, AddressOf WindowProc
        StartWarping = True
    Else
        StartWarping = False
    End If
End Function

Public Sub StopWarping()
    If WindowHandle <> 0 Then
        KillTimer WindowHandle, 123
        UnloadWindow WindowHandle
        UnloadHandles
    End If
End Sub

'Timer callback

Private Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Select Case uMsg
        Case WM_MSGS.WM_TIMER
            NextMove
        Case Else
            WindowProc = CallWindowProc(OldWndProc, hWnd, uMsg, wParam, ByVal lParam)
    End Select
End Function

'Memory stuff

Private Function RunProcess(CmdLine As String) As Boolean
    StartInfo.cb = Len(StartInfo)

    If CreateProcess(vbNullString, CmdLine, ByVal 0&, ByVal 0&, False, 0, vbNull&, vbNullString, StartInfo, ProcInfo) Then
        ActiveProcess = ProcInfo
        RunProcess = True
    Else
        RunProcess = False
    End If
End Function

Private Sub UnloadHandles()
    Call CloseHandle(ActiveProcess.hProcess)
    Call CloseHandle(ActiveProcess.hThread)
End Sub

Private Sub Poke4(BaseAddress As Long, StuffToWrite As Long)
    Call WriteProcessMemory(ActiveProcess.hProcess, ByVal BaseAddress&, StuffToWrite, 4, 0)
End Sub

'Move to the next available spot

Private Sub NextMove()
    BaseAddy1 = Peek4(4702840) + 150

    If BaseAddy1 > 150 And Asc(Peek(BaseAddy1 - 64, 1)) = 8 Then
        X1 = X1 + 1
        If X1 > 7 Then X1 = 4: Y1 = Y1 + 1
        If Y1 > 7 Then Y1 = 4: X1 = 4

        Call Poke4(BaseAddy1, X1 * 1635588)
        Call Poke4(BaseAddy1 + 4, Y1 * 1635599)
    End If

    DoEvents
End Sub

