Contributing to Ares
Contributing to Ares is relatively simple, if you know at least the basics of C++:
What you'll need
- A knowledge of C++
- Yes, you'll need this.
- Microsoft's C++ compiler
- Right now, only Microsoft Visual Studio is supported. Due to binary layout issues, gcc-based compilers/IDEs like Dev-C++/WxDev-C++ can not be used to create useful DLLs. If you want a free solution, try Microsoft Visual C++ 2008 Express Edition (highly recommended).
- The Microsoft Visual C++ 2008 Redistributables
- You can't run Syringe without these. These also come with Microsoft Visual C++ 2008 Express Edition.
- The Microsoft Windows SDK
- The Microsoft Windows SDK is required to contribute to and compile Ares. Microsoft Visual Studio (Express Edition) comes with it, but if you don't have it, you can freely download it from Microsoft's site, provided you have a legit copy of Windows. The latest version is 6.1, issued in Feb 2008.
- A Subversion (SVN) client
- TortoiseSVN is recommended.
Getting the code
The code consists of two parts:
- yrpp
- the wrapper library enabling the use of most ingame functionality through plain C++
- Ares itself
- the code for Ares itself, the functionality that is actually utilised
Each of them has its own SVN repository:
- Create a folder on your hard drive where you'll be keeping the code, for example, C:\My Documents\Visual Studio Projects\Ares or F:\source\Ares, whatever suits you.
- Create two subfolders in it, one for yrpp and one for Ares.
- yrpp
-
- Right click yrpp's folder, and (as of this point we are assuming that you have successfully installed TortoiseSVN) select SVN Checkout... from the context menu.
- Enter svn://www.renegadeprojects.com/yrpp/trunk as the Repository address.
- Leave the other options as they are, and press OK.
- Right click yrpp's folder, and (as of this point we are assuming that you have successfully installed TortoiseSVN) select SVN Checkout... from the context menu.
- Ares
-
- Right click Ares' folder, and select SVN Checkout... from the context menu.
- Enter svn://www.renegadeprojects.com/ares/trunk as the Repository address.
- Leave the other options as they are, and press OK.
- Right click Ares' folder, and select SVN Checkout... from the context menu.
Code Layout
The files in the yrpp folder are parts of the wrapper library. Ares' code is in the Ares folder. There are other repositories for other DLLs using yrpp - ExceptChecker contains the code for the current YR Development Environment (formerly known as ExceptChecker) DLL. The yrpp/Examples folder contains some examples of using the more complex functionality in yrpp.
Your new code should go in the Ares folder, the YRPP folder should not be modified without approval.
Also, take the time to at least skim over the existing code, including the wrapper library - knowing what is possible already and how is always good.
Writing A Function
All functionality in Ares is implemented as callback functions - when the game hits a certain location in the original code, some Ares function is invoked. To make your function invokable at a certain point, you'll need to assign your function as one of the predefined callbacks or use the Syringe Injection Control File to define that.
Any serious modification will normally require more than one callback.
Currently, callback functions are usually declared like this:
DEFINE_HOOK(address, Functionality_FunctionName, length) { // actual code }
What the actual code does is naturally up to you, but usually you'll need to pull a pointer to one of the game classes from one of the CPU registers. This sort of information is very location-/context-specific, and as such you'll need information from the people familiar with the reverse-engineered ASM view of the code (as it is now, pd, jonwil, VK, DCoder and TSHyper). What the actual game classes do is documented in the wrapper library, look at its header files and the existing code snippets.
An Example
Here's a sample callback. It fixes a comparatively simple bug - that units firing Temporal=yes warheads get experience from erasing friendly units (bug report, Actual code as used in Ares (may differ from shown below)).
Bits marked with (ASM knowledge) you are not required to know, the ASM hackers can explain that part.
// bugfix #379: Temporal friendly kills give veterancy //(ASM knowledge) - address and length DEFINE_HOOK(71A92A, _Temporal_AvoidFriendlies, 5) { // (ASM knowledge) the ESI register contains a pointer to an instance of TemporalClass, so let's get it GET(TemporalClass *, Temp, ESI); // House that owns the unit firing this weapon HouseClass *hv = Temp->Target->Owner; // House that owns the unit being erased HouseClass *ho = Temp->Owner->Owner; // proceed normally unless the two houses are allied with each other return ho->IsAlliedWith(hv) ? 0x71A97D : 0; }
Compiling that code to a DLL and placing it in the game directory will give you this functionality...
... almost, there's one more step to do.
Registering the DLL/function with Syringe
To tell Syringe when to invoke the "_Temporal_AvoidFriendlies" function, you just need to create one extra file:
Let's say you called the DLL with that function temporal.dll. Now you need to create a plain text file called temporal.dll.inj in the same directory as the DLL is, and place the following line into it:
71A92A = _Temporal_AvoidFriendlies, 5
That's all. Now, running YR via Syringe will invoke that functionality and prevent units from gaining experience this way.
INJgen
If you've paid attention, you will have noticed that we used same address/length that was specified in the DEFINE_HOOK up above. We have a tool named INJgen, coded up by one of our developers, to automatically generate an .inj file from the sources so you don't have to add it manually.
Appendix A: Setting up the Build Environment
At the moment, the Visual Studio IDE cannot compile/link Ares correctly. This is due to the fact that it has no config option to generate a custom .obj name based on its relative path from the Ares source root folder. The project contains multiple files with the same name (Ext/WarheadType/Hooks.cpp and Ext/WeaponType/Hooks.cpp, for example) and Visual Studio either manages to overwrite the first one's .obj with the second one, or to muck up the paths completely and fail to link them.
To solve this, we use a custom application that invokes the MSVC compiler, resource compiler, linker and INJgen as needed. This application, along with INJgen, will be released if their original authors permit.
Building manually
Work in Progress | ||
---|---|---|
This page is the result of a currently running discussion. The information on it is subject to change. If you wish to follow the discussion or want to know more about the history of this page, please follow this link. |
If you cannot wait for the tools and want to try building it yourself:
Compiler options
/Ox /W4 /errorReport:prompt /FC /wd4100 /wd4731 /wd4740 /DWIN32 /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS /EHsc /Gz /Zp8 /MP2 /Gm /Zi /nologo /we4035 /we4715
Also, add yrpp's base folder, VC's /include folder, and the PSDK's /include folder as /I"path".
Linker options
/MANIFEST:NO /DLL /SUBSYSTEM:WINDOWS /MACHINE:X86 /BASE:0x30000000 /FIXED /NXCOMPAT:NO /DEFAULTLIB:"user32.lib"
Add MSVC's /lib and PSDK's /lib folders as /LIBPATH:"path". Add /DEBUG /PDB:"path" if you want the debug symbols to be generated as well. Add the PSDK's "Lib/DbgHelp.lib" to the list of files to be linked, together with all of Ares's .obj and YRPP's static lib.
Workflow
- Compile YRPP's StaticInits.cpp as a static library.
- Compile all Ares's .cpp files into .obj.
- Compile all Ares's .rc files into .res.
- Link.
- Generate the .inj file somehow (grep is a good option. Syntax is explained above.)