Update: Quake 3 Arena .NET Port is Done!
Posted by gregd1024 on January 22, 2008
Yup – I’m now done porting Quake III Arena to managed C++ with Visual Studio 2008/v9.0 and .NET v3.5. My apologies to the guys on my private email list for getting this post out a week late. I ran into massive problems getting the Release build to work, even though there was no difference between its configuration and the Debug build (the latter of which has been working perfectly for two weeks now). Turned out to be one of those, “…damn it! How could I have been so stupid?!” problems/solutions. The Release build doesn’t look in the same directory for DLL’s as the Debug build.
Before I begin explaining the port, I’d like to clarify one thing. Someone emailed me last week regarding this port and judging from his/her message it led me to believe that some people don’t understand the difference between a .NET port versus simply compiling a C++ application with MSVC++ 2008. Here’s the difference: taking the Quake III codebase and making the changes necessary so that it will compile with Visual Studio 2008 is not a .NET MC++ port. That is a C port to a different compiler. Yes, C not C++; the project files included in Id Software’s codebase are all set to compile as native C. Furthermore, changing the settings to compile everything as C++, then fixing 3,000 compile errors, is also not, I repeat not, a .NET port. That is a native C++ port of Quake III to a different compiler. Lastly, taking the former C++ build I just mentioned, turning on the “/clr” Visual Studio option, fixing 28,000 compile errors with 4,000 warnings, patching all managed to native calls such that the first run doesn’t “blue-screen” your machine, and finally doing everything else necessary to be able to view the EXE with its supporting DLL’s under ILDASM (the .NET CLR disassembler), now THAT is a .NET port! ;-)
Anyway, 99% percent of this port gets compiled into IL / CLR bytecode. The exception is a few small functions which contain inline x86 assembly. Obviously I can’t do anything about those. Now let’s get into the details…
Before Getting Started
As I explain in the post which started this effort three weeks ago, the QVM generation code was not ported (see the previous post for why). Therefore, mixing game DLL’s with QVM’s or running your own QVM’s will not work. The known issues in this port stem from old QVM code. So make sure you’re using all DLL’s in order to run this port.
Get the Source Code
First thing’s first: you’ll need the retail copy of Quake III to run this source, it will not work with the demo version. I know what you’re thinking – “if I have the source, I can circumvent the license check, right?” Wrong. The license check isn’t the problem. The problem is that there are a few big differences between the structure of a demo PK3 data file and a retail PK3 data file. You’d have to change the code to read the demo format, which nobody has unless you work for Id Software.
Here is the download link:
- Quake III Arena .NET Port [~7MB]
In order for the source to compile you’ll need the DirectX SDK. Quake III uses it for sound and keyboard / joystick / mouse input. You can download it here. I used the June 2007 release, but it should work with earlier or later versions.
After the DirectX SDK installs, check for this environment variable: DXSDK_DIR. It should have been set automatically by the DirectX installation, but if it is not there, set it manually to the root directory in which the SDK was installed (on my computer it was: “C:\Program Files\DirectX SDK (June 2007)\”).
The Quake III source is organized into eight project files:
- ui.vcproj (originally part of the Id Software source, but I removed it from the solution)
The master solution file containing all these projects is under “<source root>\code\.” It is the only solution file in that directory. Open it with Visual Studio 2008 to get started. Hopefully there are no errors on loading; if there are, please contact me.
Note: the “ui” project was originally part of Id Software’s source tree, but I removed it from the solution because it’s not needed (the project is still contained in the download, just not referenced). This project is used for the Quake III Team Arena (TA) game which is not part of this port.
Game Directory Structure
There are two important directories in the retail Quake III installation: the root and “baseq3″ located directly underneath the root. The root folder contains “quake3.exe” and “baseq3″ contains the three supporting DLL’s needed to run the game. You won’t find these DLL’s in the commercial install of Quake III, but after compiling the source they will be put there (if you’re curious as to why this is, check out my earlier post about installing a Quake III mod).
I would recommend installing another Quake III instance under the path “c:\quake3″ if you don’t already have it there. That way, you won’t have to edit any of the project settings. And, more importantly, you won’t overwrite your commercial copy of Quake III after compiling the source. There’s nothing wrong with having two instances of the game installed on the same machine – you can have one as the original, and the other as a test-bed when messing with the source code.
Steps to Run the Source
First, if you don’t have the commercial version of Quake III installed under “c:\quake3\” then you’ll have to change the project settings a bit. The outputs of the following three projects will have to change:
Locate the “Output File” setting for each project under Visual Studio’s Project Properties dialog (this would be under, Project -> Properties -> Configuration Properties -> Linker -> General -> Output File). Change each of them to the following:
- For cgame: c:\<quake3 install dir>\baseq3\cgamex86.dll
- For game: c:\<quake3 install dir>\baseq3\qagamex86.dll
- For q3_ui: c:\<quake3 install dir>\baseq3\uix86.dll
Change “<quake3 install dir>” with whatever directory you have the Quake III game installed.
Now set the build configuration to Debug. Yes, you could do Release, but if anything goes wrong the Debug build will give you better diagnostic information. You may also notice other build configs in the drop-down list, such as “Debug Alpha,” “Debug TA,” and a few others – don’t touch these!! The only two you should be interested in are “Debug” and “Release.” The others are for Team Arena and non-Intel builds. They won’t work for this port.
Now select “Build -> Rebuild Solution” from Visual Studio’s menu options. If everything builds with zero errors and zero warnings, great! If not, please contact me.
Set quake3.vcproj as the startup project. It should already be set by default, but I’ve noticed Visual Studio 2008 seems to have a bug with this – sometimes, for no reason, the startup project will get changed.
Run the solution directly from Visual Studio. Now start fragging! ;-)
Note: you could run the game directly from a command line, but you’ll need to start it like this:
“quake3.exe +set sv_pure 0 +set vm_game 0 +set vm_cgame 0 +set vm_ui 0″
Sometimes on fast machines in single player mode, if you add a lot of additional bots after joining an arena, the game will have connection problems. The phone jack icon will display in the corner and you won’t be able to move your player. This bug also happens in the commercial version so it’s not a new bug.
However, here’s a bug caused by the port which only happens in Release builds (Debug works fine). When connecting to some third-party servers on the internet, usually one supporting DLL fails to load (usually uix86.dll). When this happens, Quake III’s default behavior is to load the QVM files contained in the PK3 data files. As explained earlier, mixing QVM’s and DLL’s don’t work, so you’ll get very weird behavior if this scenario arises.
My Comment Log
If you take a look at the source code you’ll probably notice a lot of lines have comments that begin with this string: “***GREGS_VC9_PORT_MOD***.” A line beginning with this comment indicates that it was changed from the original codebase. It also contains a brief explanation on what was changed. This comment was added to almost every modified line except when getting rid of a keyword conflict caused by member variables being named “generic” (since “generic” is also a .NET keyword). This member was used on nearly 2,500 lines and I didn’t see the point in wasting time repeating the same comment over and over. Instead, one comment was added to the top of every module affected by this conflict along with what was done to resolve it.
Here’s a screenshot at the startup menu with the console pulled down. Notice how it displays which .NET runtime is executing the game:
If you have any questions or problems with this port, please send me an email via my Contact page.
Thanks for reading! ;-)