The Immortal Descendants

Level:
Beginner
Date:
Aug. 14, 2000

Training Arkanoid 2000 v1.5

by Muad'Dib
muaddib(at)immortaldescendants(dot)org
The Immortal Descendants


This is a very easy game to train and is great for the beginner. For this essay you will need Arkanoid 2000, Teraphy's Trainer Creation Kit, and MASM.

http://www.terminalstudio.com/files/arkinst.exe - Arkanoid 2000
http://unixfu.box.sk/files/tools/pc_tck41.zip - TCK v4.1
http://masm32.cjb.net/ - MASM32v6


For this trainer we'll be using Win Mem Search v1.0 (included in the TCK v4.1). Load up the game in Win Mem Search and start a new game on any episode you want (easiest on Episode III).

Win Mem Patch Screen Shot 1

As soon as you begin to play, notice that the score has 5 digits, seemingly a WORD for the score. ALT+TAB out of the game and do a WORD search for 0 (or your current score) and then go back in.

Win Mem Patch Screen Shot 2

Get a few points and note down the score and then ALT+TAB again. This time put in your current score but do "Continue Search" in order to search through all of the previously obtained results. You should only have a few results. If any at all show up in the list box, click memory patch, otherwise, if some were found, repeat the process.

Win Mem Patch Screen Shot 3

Alt+TAB back and note down your new score. Then go back to the memory searcher and find your score as the far left value in the list box. This is the memory location for score. Why is this? Because Win Mem Patch sets the values incrementally if it has a narrow enough array of search results. Now we are going to do the same but with balls. Start a new game and note down how many balls you have. Do a BYTE search this time (balls have 2 digits) and then continue to play. Each time you get a new ball (a +1 icon falling when you hit a brick) continue the search. Once you have a narrow enough array of results, do a memory patch and then go back and note how many balls you have. Then do the same as you did with score to get a memory location. Here are the results I got:

BALLS - 444AAA - BYTE
SCORE - 442F1C - WORD

Now to make a trainer. I'd reccomend looking in your API guide for how to use the API functions I use. Here is a source listing:
.386
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib

MainDialog  PROTO   :DWORD,:DWORD,:DWORD,:DWORD
.data

OFFS_Points     dd  442F1Ch
OFFS_Balls      dd  444AAAh

ArkanoidWindow  db  "Arkanoid2000",0

Error_NoRun     db  "Arkanoid 2000 is not running...",0
Error_Write     db  "Error writing process memory!",0
Error           db  "ERROR:",0
About_Title     db  "About...",0
About           db  "Arkanoid 2000 v1.5 +2 Trainer by Muad'Dib/KNiFE",0dh,0ah,0dh,0ah
                db  "Greetings to OPTiCaL, Carpathia, CrackZ, sinn0r,",0dh,0ah
                db  "everyone in Pravus/Immortal Descendants and",0dh,0ah
                db  "everyone I know",0dh,0ah,0dh,0ah
                db  "-Muad'Dib / Aug. 4, 2000",0


.data?

hWnd_Arkanoid   dd  ?
pid_Arkanoid    dd  ?
process_Handle  dd  ?
number          dd  ?

hInst           dd  ?

.code

main:
    invoke  GetModuleHandle, 0
    mov     hInst, eax
    invoke  DialogBoxParam, hInst, 1, 0, OFFSET MainDialog, 0

MainDialog  PROC    hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
    .if uMsg == WM_INITDIALOG
        invoke  FindWindow, 0, OFFSET ArkanoidWindow
        .if     eax == 0
            invoke  MessageBox, 0, OFFSET Error_NoRun, OFFSET Error, 0
            invoke  EndDialog, hWnd, 0
            ret
        .endif
        mov     hWnd_Arkanoid, eax

        invoke  GetWindowThreadProcessId, hWnd_Arkanoid, OFFSET pid_Arkanoid

        invoke  OpenProcess, PROCESS_ALL_ACCESS, 0, dword ptr [pid_Arkanoid]
        mov     process_Handle, eax
    .elseif uMsg == WM_COMMAND
        mov     eax, wParam
        .if eax == 100
            invoke  GetDlgItemInt, hWnd, 300, 0, 0
            mov     number, eax
            invoke  WriteProcessMemory, process_Handle, OFFS_Balls, OFFSET number, 4, 0
            .if     eax == 0
               invoke  MessageBox, 0, OFFSET Error_Write, OFFSET Error, 0
               invoke  EndDialog, hWnd, 0
               ret
            .endif                    
        .elseif ax == 101
            invoke  GetDlgItemInt, hWnd, 301, 0, 0
            mov     number, eax
            invoke  WriteProcessMemory, process_Handle, OFFS_Points, OFFSET number, 4, 0
            .if     eax == 0
               invoke  MessageBox, 0, OFFSET Error_Write, OFFSET Error, 0
               invoke  EndDialog, hWnd, 0
               ret
            .endif                    

        .elseif ax == 102
            invoke  ExitProcess, 0
            ret
        .elseif ax == 103
            invoke  MessageBox, hWnd, OFFSET About, OFFSET About_Title, 0
        .endif
    .elseif uMsg == WM_CLOSE
        invoke  EndDialog, hWnd, 0
    .endif

    ret

MainDialog  ENDP

end main


I hope you enjoyed this essay and learned something. This technique can be used in many games. I hope to bring you an essay on savegame editors and more advanced training soon.


Muad'Dib / Aug. 14, 2000

muaddib(at)immortaldescendants(dot)org