The trainer uses the cheats as buttons - when clicked it will change the item value to 99 and freeze the value, if clicked again it will unfreeze the value.
The finished trainer is only 21.5 KB file size uncompressed, or 14 KB using the EXE packer UPX (as most trainer builders use UPX automatically). VirusScan.Jotti.org reports 0 false-positives for a virus (from 20 virus scanners). So no problems with users getting a false-positive virus warning.
Spelunky Tutorial - Part 5 of 5
- Game Cheating Tutorial
- GTS Trainer Tutorial
- Cheat Engine Trainer Tutorial
- AutoIt Trainer Tutorial
- FreeBASIC Trainer Tutorial
To do this tutorial you will need --
- FreeBASIC version 0.23.0
- FbEdit version 22.214.171.124c
- My complete FreeBASIC trainer project (Extract to your FbEdit Projects folder - C:\FreeBASIC\Projects )
- PC game Spelunky version 1.1 by Derek Yu. Also available at FilePlanet.com and Games.On.Net
** This section covers installing FreeBASIC and FbEdit.
FreeBASIC. For ease of use I recommend the Windows Installer version. Once downloaded, simply install the program to the default directory.
For your own reference when using FreeBASIC, I recommend you also download the FreeBASIC User Manual (Compiled HTML). The manual is a CHM help file, extract it from the ZIP file to the FreeBASIC Docs folder.
For me this is extracted to the C:\Program Files (x86)\FreeBASIC\docs folder.
FbEdit, a easy download link is on the right-side of the page.
Extract the program/files for FbEdit from the ZIP file, I recommend you extract the files to C:\FreeBASIC Create a shortcut to FbEdit by right-clicking FbEdit.exe, select Send To, and click Desktop (create shortcut).
Download my FreeBASIC project trainer ZIP file. Extract it to the FbEdit folder, C:\FreeBASIC\Projects. The actual files will be in the folder C:\FreeBASIC\Projects\Trainer.
Now start the FbEdit program, by double-clicking FbEdit.exe or your shortcut.
** This section covers setting up FbEdit correctly.
In the new window the first option, Default Project path, is the directory of where you installed FbEdit ending with Project. For example mine reads C:\FreeBASIC\Projects
The next option, Compiler Path, is the directory where you installed FreeBASIC. The default install directory is C:\Program Files (x86)\FreeBASIC
The last path directory, Help Path, points to the directory FreeBASIC Docs folder. The default install directory is C:\Program Files (x86)\FreeBASIC\docs
Click the Ok button once you have them set correctly. Next click the FbEdit menu Options, and click Help Menu.
In the new window the first item, Win32, is for the Windows API help file. Although outdated (as it is now strictly update online) the CHM help file is often more then enough, and a handy reference.
You can get the Windows API help file from Carabez.com. Visit the Carabez download page, and download the file called win32api_big.zip (it is the second from the very bottom).
Download and extract the ZIP file. Next click the extracted 7-Zip self-extractor and extract to C:\Program Files (x86)\FreeBASIC\docs\Win32.
Set the FbEdit Win32 option Command to the file win32sdk.hlp (as it is the most complete) - C:\Program Files (x86)\FreeBASIC\docs\Win32\win32sdk.hlp
The next item, FreeBASIC, points to the FB help file you downloaded ealier. My command for this is C:\Program Files (x86)\FreeBASIC\docs\FB-manual-0.23.0.chm
The other options should be fine as they are set with the FbEdit defaults. Click the Ok button, as you are done.
FbEdit is now setup to use the FreeBASIC compiler, knows where to save the projects/files, and you can access the help files (From the FbEdit menu Help, and select the help file to load) - it's time to get started.
** As this is not a entire FreeBASIC programming guide, but a tutorial to create trainers, I have zipped the complete FB project for you to download. The project is a great trainer skeleton/base to create your own trainers in FreeBASIC as well.
Trainer.fbp from the Project Trainer folder (my FB trainer project). Click the Open button.
FbEdit will open three files that are part of the project. I have heavy commented the main file, Trainer.bas, so you can make changes as needed.
To access the other project files simply click the tab of the filename, towards the top of the screen. You should have three tabs - Trainer.bas, Trainer.rc, and Trainer.bi
When the project if first loaded it should default to the Trainer.bas tab.
You can easily change the resources with FbEdit as it has a GUI (UI) builder, along with other tools.
For example to change the trainer dialog/window size click inside a blank area if the dialog/window. Next use the dialog/window outline (small squares) and drag them to the desired size.
You can also edit the size more precisely by editing the data Height and Width in the dialog/window properties.
Example to add a new button - click the button image on the left (image of a button with the word Ok). Then click inside the trainer dialog/window where you want it to be displayed.
Next you will need to add the new button's define line (see the Trainer.bi section). Finally add the programming code inside the main trainer file, Trainer.bas, so that when the new button is clicked it will do something.
To add a new resource such as a image or the like, I did for the trainer icon, you can do this under the menu item Resource (when you are viewing the Trainer.rc tab).
Anytime you add or remove resources you will have to manually update the Trainer.bi file to use them properly in the main trainer file (Trainer.bas).
Take note of the define lines, like this -
#Define IDM_BTN1 1001
The example define line is setting-up a button resource, using the #Define command. Followed by the resource name, example is IDM_BTN1. Lastly followed by the resource ID number, in the example is 1001.
The resource Name and ID number are specified in the RC file, and given default values (which can be changed), see the above image in the Trainer.rc section to see the ID field selected.
This is the main program file, where the actual program code goes. With my default project everything is completed for a 3 button cheat for the game Spelunky version 1.1
This file is setup into specific sections, in which the order does matter to FreeBASIC.
- Include section
- Dim variables section
- Function and Sub section
- Program start section
This area is for the various library and files required by the trainer. You should not have to change this section unless you use code that requires a library that is not already included.
The optional code Once is included to ensure that the library/files are only included once in the trainer (no matter if they are included from somewhere else or not). If they were included multiple times the compiler will give you errors.
Dim Variables Section
Variables are setup to be used throughout the trainer. Notice the code Shared allows the variables to be used/changed inside the functions/subs as well.
If you need additional variables for use in multiple functions then you will need to add them here; otherwise, they are simply setup in the function/sub they are used (that way they are removed when the program/function is done with them).
A interesting note is that any variables that are setup the same way can be combined on the same line. For example instead of using
Dim Shared GameAddr As Integer Dim Shared GamePntr1 As Integer Dim Shared BTN1_Status As Integer Dim Shared Process As String
You can combine the variables on the same line as
Dim Shared As Integer GameAddr, GamePntr1, BTN1_Status Dim Shared Process As String
Using either provides the same results; however, the second example is cleaner. The variable Process was not combined as it is setup differently.
Function and Sub Section
A great option in FbEdit is the ability to collapse/hide the function code - allowing you to scroll through the code quicker.
To collapse/hide the function code, click the white square with a minus sign [-] and it will hide it. To view the function code again simply click the white square with a plus sign [+]. See the image for an example of the collapse/hide option in use.
* If you find it annoying or simply prefer the functions/subs to be at the bottom of the BAS file you can do that using the Declare code.
For example to move the function, Function _GetBaseAddress(ByVal _mempid As DWORD) As Integer, enter a new line above the function line and enter Declare and copy/paste the function line to it - Declare Function _GetBaseAddress(ByVal _mempid As DWORD) As Integer.
Then select the entire function code, from the original line Function _GetBaseAddress(ByVal _mempid As DWORD) As Integer and select to end of the End Function line. Cut the selected code and paste it at the very end of the BAS file.
Program Start Section
Line 409 is the start of the program code that makes the trainer do what we want, cheat. The variable Process is given the name of the game we want to cheat (Which is Spelunky.exe).
Then lines 411-415 set the trainer variables with default values so the trainer runs smoothly. As some of the variable may not have been accessed/written to before they are used otherwise.
Line 417 the code _SetPrivilege() gives the trainer full access in Windows so it can do the cheats we want it to.
The next three lines 420-422, sets some program variables for the trainer dialog/window. Then line 423, WinMain(hInstance,NULL,CommandLine,SW_SHOWDEFAULT) actually calls the function that creates the trainer dialog/window.
Inside the function (stating at line 350) two variables are setup to be used only in this function. The following lines 354-365 setup the information that will be passed to the Windows API's to create the trainer dialog/window.
The lines 367-369 are the Window API's to create the trainer dialog/window.
After that the Timer variable is given the current time in milliseconds so the trainer has a delay between updating the cheats.
At line 372 is the Do .. Loop which is the main program area once the trainer window is created. The code will loop (repeat) until the user of the trainer closes the trainer window.
The code If msg.message=WM_QUIT Then Exit Do will check if the user has closed the trainer window, and if they have it will exit the program loop. This will send the program to line 406, which sends it to line 424.
Lines 374-377 check if the trainer user clicked/changed something to the trainer window. If they did it will send the program to the function WndProc (see below).
Now we get to the heart of the trainer itself, not the GUI (trainer window). Line 379 with the If timer code checks if the time passed is more than 250 milliseconds. Also it checks if it is a negative number, as it is a backup check in-case the timer was started before midnight and the current time is after midnight.
If the enough time has passed, more than 250 milliseconds, then it will access the code in lines 380 to 403.
Line 380 checks if the trainer has already got the pID (process identifier) of the game. In other words if the game was not loaded the last time the trainer was here.
Next it will call the function _ProcessExists to check if the game, as specified in the variable Process, exists - checks if the game is loaded and if so returns the game pID.
Line 382 checks if the game pID was found, and if so gives full access of the game to the trainer - using the function _MemoryOpen. The function returns the handle to the variable ghWnd.
The function _GetBaseAddress on line 384 does just as it implies, it will get the image base address of the game loaded into memory. Most times it is 400000 (HEX) but can be anything, and the function will return what it actually is.
It is the same as a Cheat Engine cheat address that uses the game name, like "Spelunky.exe"+ whatever.
Now the trainer has full access to the game, and retrieved the information it needs to start cheating. Line 386 checks that the game pID is not empty - the game is loaded.
Line 387 and 388 gets the pointer address information from the game for our cheats. Here are the cheats we found for Spelunky, from the Game Cheating Tutorial.
Bombs "Spelunky.exe"+0018F124 Offset 4 Offset 23D8 Health "Spelunky.exe"+0018F124 Offset 4 Offset 23B0 Rope "Spelunky.exe"+0018F124 Offset 4 Offset 2400
In line 387 "Spelunky.exe" is the BaseAddr variable. We are adding it to the decimal value of 18F124 (HEX). As this is done in the _MemoryRead function it will return the first address of the 2 level pointer.
For example "Spelunky.exe"+0018F124 pointer address is saved to the variable GamePntr1 which was 02685680 (HEX) - it can change.
The next line 388 takes us to the second level of the pointer address. It takes the previous address (GamePntr1) and adds the offset of 4, and reads the address.
For example this gets us to the point of "Spelunky.exe"+0018F124 Offset 4 in Cheat Engine. Which is the 2nd level pointer, and saves the address to the variable GamePntr1 which was 0B260238 (HEX) - it can change.
As all three of the Spelunky cheats use the same pointer, just a different ending offset we now have the pointer address to get started cheating.
* The two lines 387 and 388 does this each time before updating the cheat, because when actually playing the game when a new level is started/advanced the address can change. In some of the other advanced cheats the address changes each time.
Lines 390-402 are the same basic setup for all three buttons, I will walk you through the first.
Line 390 checks if the user has the Bomb Max cheat on. If the cheat is on it will update the cheat value, doing so every 250 milliseconds "freezing" the cheat.
At line 391 it takes our pointer, saved in the variable GamePntr1 and adds the decimal offset of the cheat - in this case for bombs. Which is GamePntr1 + 9176 and saves the address to the variable GameAddr. For example the address for the bomb cheat, which varies, was 0B262610.
The next line 392 writes the decimal value 99 as a "double" value to the address specified in the variable GameAddr. For example, shown in HEX, at the address 0B262610 it writes 0000000000C05840. Remember the address is a pointer and will change, it is shown as a example.
Lines 394-402 check if the other two cheats are turned on, and if they are update the item cheat values. This is done the same way as I just walked you through with the above bomb cheat.
The line 403 updates the variable TimerDelay to the current time in milliseconds so the cheats are not updated again for 250 milliseconds.
The program will now loop back to the start of the loop on line 372 repeating everything. As mentioned previously if the user clicks a button, or changes something, on the trainer dialog/window the function WndProc is called.
When a user of the trainer clicks a button or changes something on the trainer dialog/window the program sends a message, calling this function.
Line 287 sets the program to look for a message in the form of a Select Case (similar to If statements that only vary by what they are compared to - in this case which message).
On line 288 the message WM_INITDIALOG is sent by the program when the dialog/window is first created. We use this to our advantage to send a message of our own.
Line 289 sends a message to the trainer to use a icon for the EXE, dialog/window, and in the taskbar. The important thing to point out is the number 100. This is the ID of the icon resource image (FreeBASIC and the Windows API prefer/require the ID of a resource instead of the resource name).
A WM_COMMAND message is checked on line 291. This is the main select case code area for nearly any GUI object - in the case of the trainer the cheat buttons.
Next, line 292 take the variable passed to the function, wParam, and gets the HiWord from it. The next line checks if a button was clicked. Last of this code area line 294 gets the LoWord of the variable wParam to check our trainer buttons.
The lines 295-332 is the code that handles what to do if one of the cheat buttons was clicked. As typical all three code blocks for the buttons are the same and I will walk you through the first.
Line 295 checks if the first button was clicked, the Bomb Max cheat. At line 296 if the button was clicked it checks if the game pID is not empty - the game is loaded.
A check at line 297 to see if the cheat button, Bomb Max, is on. Line 298 changes the variable BTN1_Status to 0 (off). Next it changes the button text to let the user know it is off - the ID 1001 is the button id, also specified is the text caption to change it to.
Line 300 says the button is currently off. Line 301 changes the variable BTN1_Status to 1 (on). Next it changes the button text to let the user know it is on - the ID 1001 is the button id, also specified is the text caption to change it to.
At line 304 this code is executed if the game is not loaded, the pID is 0. The next line tells the trainer to play the Windows SystemDefault sound, a beep, as a way to let them know clicking the button did nothing - i.e. load the game first.
307 to line 332 is the code for the other two buttons. It uses the same basic code as I just described, see above if you need help with them.
At line 336 it checks for WM_CLOSE, this is the message when the user clicks the X button on the top-right of the trainer window to close it. If the user did click the X then destroy the trainer window and send the message WM_DESTROY.
Line 339 checks if the window was destroyed. If it was then close the trainer program thread and send the message WM_QUIT.
The remaining lines 342-345 handle any other possible messages and end the function.
Exiting the Trainer
Most of this has been discussed but I will put it in order so you understand what is going on when the user clicks the X button to close the trainer window.
When the program is running normally it is in the Do Loop at line 372. If the user clicks the X button on the trainer window the program uses the lines 374-377 to get the dialog/window message.
The program then calls the WndProc at line 286. It gets to line 336 and destroys the trainer window and sends the message WM_DESTROY.
Line 339 is reached and the trainer program thread is closed, and sends the message WM_QUIT. The trainer returns to line 378. It does a single loop to line 373 and exits the Do Loop going to line 406.
That returns the program to the program start section at line 424 (right after calling the function that ran the trainer).
The remaining code is finally executed now. Line 426 closes the trainer program's access to the Spelunky game.
Next at line 427 the trainer process is itself terminated. Finally at line 428 the trainer is ended, exiting from the code.
FbEdit will show you any warnings or errors when you compile the trainer; however, you have to set the window to display any compiler messages.
To show the compiler messages hover your mouse over the bottom left section text (see the image). In my image it says Output, yours may be different.
Once the mouse pointer is over the text a tall column of round radio buttons will appear. Click the first (the top) radio button. This will then change to Output, and show all compiler messages.
To compile your trainer, which turns it into a EXE, there are three ways to access the compiler. Press the button F5, click the menu Make then click the Compile menu, or press the compile icon (a white rectangle with black dots -- see the compiling image).
When the compiler has finished, the compiler message text will be shown in the Output area in FbEdit. If there are no problems the text will simply show the command to the compiler and the text Make Done.
If there are any warnings or errors they will be shown in the Output area and red x squares are put on the code lines that have errors. The Output area uses blue for warnings, and red for errors.
You need to correct any warnings/errors and try to compile the trainer again. My project files have no warnings or errors, if yours does you may want to extract my project files again.
When the trainer is compiled with no warnings or errors you can then test run the trainer.
Run the compiled trainer by pressing the keys Shift+F5, clicking the run button (the red explanation point !), or the menu item Make and click Run.
The finished EXE is saved in the project folder, which should be inside C:\FreeBASIC\Projects\Trainer.
*A note about the difference between the Run and Go commands. The Run command will start the last trainer EXE you compiled (so if you compiled and got errors it will be the last trainer that successfully compiled and not the current code). The Go command (the green play arrow) will first compile your current trainer code then run the trainer.
It seems the typical way these three commands (compile, run, go) are best used is like this - To test that your trainer will compile as you program it simply run a compile command, if it compiles continue programming else edit your code.
When you are ready to test your trainer do the go command, that way it uses the current code. If however you recently compiled to save time use the run command to skip the compile command.
The finished trainer is 21.5 KB in file size. If you want to use a file packer, such as UPX, the file size will be shrunk to 14 KB.
Removing the icon from the FB trainer, as my GTS trainer tutorial does not use one, it almost catches GTS in final size. The FreeBASIC trainer comes in at 9 KB and the GTS trainer at 6 KB (both without a icon).
With further code optimzation the FreeBASIC trainer could tie or even be smaller in file size than GTS if you really want a tiny trainer file size.
The t2EservoMemory functions have been compiled into a FreeBASIC library, for easier use in other trainers. Instructions are included in the zip file for installing and using the library.
Download link for the t2EservoMemory library.
Of course feel free to use the project file as a skeleton/base to create other trainers. The library is only a option, which is not needed if you use the trainer project.
If you want to know how to create this trainer using other programs, view the links in the Spelunky Tutorial section near the beginning of this page.