Compiling DirectX 9 code with MinGW’s GCC

It appears targeting DirectX 9 using just plain C (not C++) and using GCC, instead Visual Studio, isn’t as easy as you would think it is. Because Microsoft uses so-called COM-objects in DirectX, you can’t just do:

direct3d9_device_instance->Release();

GCC will yell at you:

‘struct IDirect3D9’ has no member ‘Release’

You will have to do:

#define CINTERFACE
IDirect3D9_Release(direct3d9_device_instance);

I.e.: <struct name>_<function name>(<instance>, <other args…>). So, now you’ve got that covered. As you come to the linking step, GCC will complain again:

Skipping incompatible d3d9.lib when searching for -ld3d9

Oh my, something seems to have gone terribly wrong! Incompatible! No way! But fear not, there is a way to fix this (at least for 32 bit builds, haven’t tried it for 64 bit yet). GCC simply does not like Microsoft’s .lib format. Grab MinGW utils (not v0.4-1, it appears that binary is broken!). Preferrably add the packaged binaries to your path. Now move the DirectX libs somewhere cosy and fire up the command prompt in that directory. Remove the DxErr.lib file (for some reason it seems to be incompatible beyond repair. Unfortunately this means you will not be able to use the specific DX error APIs). Now type in:

for %f in (*.lib) do reimp %f

Press Enter, and watch the magic happen (reimp.exe is converting the .lib files to lib*.a files which are compatible with GCC) [1]. Now we’re almost done. Move the prepared lib*.a files to a location you will remember, add the location to your library path using the -L switch, and you’re done :).
[1]: Credit to Ken Fitlike for his explaining forumpost.

Setting up Qt-Creator for a C / assembly mixed project

Since Microsoft’s compiler’s support for modern C is lackluster to say the least (in short: no real support for C99, only for C90), I decided to change compilers and use GCC. Qt-Creator is a really neat IDE; in this post we’ll be looking into how to setup Qt-Creator to compile mixed C (not C++) and assembly-code projects under Windows, as well as getting it to compile both in 32 and 64 bit modes (note: with some slight changes this post can probably be applied to other OS’s as well.) [1]

Compiler and kit setup

So, let’s first setup our compiler (Image 1). I will assume you will already have installed MinGW-w64 (or it’s 32 bit equivalent).  Go to Tools -> Options -> Build & Run. Under the Compilers tab, you can add additional compilers. Though Qt-Creator sometimes adds compilers automatically, it probably will not add GCC. Press Add -> GCC. Under compiler path, browse to the GCC executable. If you wish to be able to compile for both 32 and 64 bit, add the compiler once more and under ABI change the architecture to 64 bit. Note: more settings are required to get 32 and 64-bit builds to work side by side. More on this later on!

qt-creator-compiler-buildoptions

Image 1: the compiler options in Qt-Creator

Qt-Creator uses so-called ‘kits’ to do the actual compilation (Image 2). Add two kits in the kits tab: one for 32 bit, the other for 64. Set them to use the appropriate compilers we just created in the previous step. Note that you must set Qt version, even though we are setting up C compilers and thus will be unable to compile any Qt applications (which require C++). Just choose any entry from the list.

qt-creator-kitoptions

Image 2: Qt-Creator kit options

Build settings

Now that we have setup our kit, we go on to the actual build settings. Unfortunately, you will have to set these settings for each project individually (as far as I’m aware). Thus if you have not created a project within Qt-Creator, do so now (choose something like ‘plain C project’). Then, add the kit we just created (either 32 or 64 bit) by going to Projects (left-hand side of screen) -> Add kit. Your screen should now look just like Image 3.

qt-buildsettings

Image 3: Qt-Creator’s build settings

Now, I also like to be able to assembly my MASM-style assembly-code. A good (free, open-source) portable assembler for this purpose is JWasm. I will assume you have already installed this assembler and that you have added it’s directory to your PATH environmental variable. To get the assembler to work, we need to add a custom build step. Thus (in the build settings screen) click on Add build step -> Custom Process step. Use the following settings:
Command: jwasm
Arguments: -coff -Fo%{buildDir}/debug/.obj/assembly.o *.asm
Working directory: %{sourceDir}

These settings will tell jwasm to assembly an object file with a COFF layout. The -Fo switch ensures the assembled object file will be placed among all the other object files and *.asm ensures that all assembly code in the source directory is processed. (Note: this setup combines all assembly code into one object file, I’m not yet sure how to build them into separate object files.) Something you should not forget to do, is to move this custom build step before the make step, otherwise the assembled file will not be used in the linking step! The resulting build setting should look as Image 4.

qt-creator-kitsettings-assembly

Image 4: the final build settings for our C / assembly project

Setting up the .pro file

Now we’re on the home stretch! We just need to setup the .pro file (which is processed by qmake prior to all the other build steps.) First of all, make sure GCC knows we’re using C99:

QMAKE_CFLAGS+=-std=c99

Next, we want Qt-Creator to show our assembly files in the IDE, as well as use our assembly object file in linking:

OTHER_FILES += \
    assembly.asm

LIBS += assembly.o

We still need to get our 32/64 bits working correctly!

contains(QT_ARCH, x86_64):{

} else {
    # 32 bit specifics here
    QMAKE_CFLAGS += -m32
    LIBS += -m32
}
This code tests the QT_ARCH variable (set by qmake) and sets the -m32 flag (32 bit compilation) if necessary. (Note: this code assumes either 32 / 64 bit x86 architectures. If you’re compiling for more architectures, such as ARM, adjust the code yourself.)

Finally, under Windows, if you’re compiling a DLL, you’ll probably want to have the export files (.lib) as well. Add the following code:

QMAKE_CFLAGS+=-Wl,--subsystem,windows,--out-implib,libraryname.lib

[1]: This post was based partly on a helpful post by Divan Visagie.

Getting Visual Studio’s C++ Intellisense to work for projects stored on virtual drives

Recently I moved some of my Visual Studio (VS) projects to a virtual drive. Sadly, Microsoft SQL Server Compact, doesn’t like this. This is a problem, because all the information relevant for Intellisense is stored in an SQL database called <project name>.sdf, thus effectively breaking Intellisense.

There’s an easy fix: make sure your Intellisense database is not stored on your virtual disk. Go to Tools -> Options -> Text Editor -> C/C++ -> Advanced and adjust the following options:

Always Use Fallback Location to True
Do Not Warn If Fallback Location Used to True (optional)

You can leave Fallback Location empty (it will default to your temp folder) or fill in a path to a folder on a real drive.

PS: The exact error message is:

An error occurred while creating or opening the C++ browsing database file <project file path>\<project name>.sdf. Intellisense and browsing information will not be available for C++ Projects.Ensure that Microsoft SQL Server Compact 4.0 is installed and that no other applications are accessing the file. If this problem persists, delete the file and reopen the solution.

Mixing assembly and C++ in Visual Studio (2010)

Sometimes in-line assembly just doesn’t cut it and you want to use assembly directly in Visual Studio. This can be done easily by changing a few settings in Visual Studio. We’ll discuss how this is done, then we’ll go into ways to call assembly code from C++. Lastly, we’ll discuss an easy way to ‘copy-paste’ code stubs, using assembly. Continue reading

DLL-injection, part 2: calling LoadLibrary the easy way

(This post is part of a series on DLL-injection. You can find the previous post here)

Introduction

As mentioned in the first post, the challenge of loading a DLL by calling LoadLibrary, is the fact that this function must be called from within the target process. As with DLL-injection in general, calling LoadLibrary remotely can be done in a number of ways. In this post we are going to use what is probably the easiest method: using CreateRemoteThread. Continue reading