Categories
AI Graphics and Game Programming

AI refactoring of 20+ year-old code from Tricks of the Windows Game Programming Gurus

How good is AI at bringing old code into the 21st century? I’ve undertaken a small project to refactor code from the book Tricks of the Windows Game Programming Gurus, by Andre Lamothe, to see how easy it might be to modernize.

First, some background: back in 2002, I was a General Manager at the Adtech division of Spirent Communications, located in Honolulu, Hawaii. Adtech made telecom test equipment, and I oversaw our division’s P&L through the telecom boom/bust cycle: and what a wild ride that was! It was an extremely stressful job, with long hours and lots of travel; I needed a way to relax in between corporate crises.

Somehow, I came across the legendary Andre Lamothe’s book, Tricks of the Windows Game Programming Gurus, Second Edition. I think that it’s still available on Amazon, if you want to try to get a copy: https://www.amazon.com/Tricks-Windows-Game-Programming-Gurus/dp/0672323699. Although I wasn’t a hardcore programmer at the time, I bought the book, and I was hooked. Andre’s approachable style and great sense of humor made learning some of the basics of Windows game programming easy; there were plenty of source code examples included, and they all compiled nicely using Visual Studio 6 and DirectX 8. I worked my way through the entire book, compiling and running all of his example code, starting with a simple “Hello World” Windows program, and ending with a complete game, “Outpost”.

The book was a groundbreaker at the time: over 1,000 pages of amazing content, I think the first of its kind to teach low-level game programming. We have certainly come a long way since then, with new platforms like Unity, and now even AI writing games on its own. But to learn game design from the bottom up, I can’t think of any better way to have gotten started (at least, back in 2002).

And there’s the rub – the code in Andre’s book is old! 25+ years old, to be precise – the book was published in 2002, but the code on the included CD dates back to 1998 and 1999. All the code was Win32, and it even pre-dated Unicode being used in Windows. And we’re up to DirectX Ultimate, released in 2020, versus DirectX 8.0. I ran all this code on a PC running Windows ME. Would it be possible to port it to Windows 11 with a modern IDE and code base using AI, and how much guidance would AI need to get it right? I decided to find out.

For these experiments, I’m running on Windows 11, with a fresh install of Visual Studio 2022 Community, and GitHub Copilot.

Let’s start with the first version of a Windows “Hello World” program. The 1998 code for this from Andre’s book looks like the below:

// DEMO2_2.CPP - a simple message box

#define WIN32_LEAN_AND_MEAN

#include <windows.h>        // the main windows headers

#include <windowsx.h>       // a lot of cool macros

// main entry point for all windows programs

int WINAPI WinMain(HINSTANCE hinstance,

                   HINSTANCE hprevinstance,

                   LPSTR lpcmdline,

                   int ncmdshow)

{

// call message box api with NULL for parent window handle

MessageBox(NULL, "THERE CAN BE ONLY ONE!!!",

                 "MY FIRST WINDOWS PROGRAM",

                  MB_OK | MB_ICONEXCLAMATION);

// exit program

return(0);

} // end WinMain

To begin the modernization, open up an Empty Project:

Copy and paste in Andre’s code.

Of course, compiling it generates build errors:

I asked for help from GitHub Copilot:

HelloWorld.cpp is Win32 code that was written in 2002. It has build errors, and needs to be refactored to run on Windows 11 with unicode. Can you modernize this code so that it will compile and run on Windows 11?

Certainly. To modernize this Win32 code for Windows 11 and Unicode support, the following changes are required:

  1. Use the wide-character (Unicode) versions of Win32 APIs by:
    1. Replacing string literals with wide string literals (prefix with L).
    1. Changing the WinMain signature to use LPWSTR for the command line argument.
  2. Ensure the project is set to use Unicode (which is default in modern Visual Studio projects).
  3. No other major changes are needed for such a simple program.

Here is the refactored code:

// DEMO2_2.CPP - a simple message box

#define WIN32_LEAN_AND_MEAN
#include <windows.h>        // the main windows headers

#include <windowsx.h>       // a lot of cool macros

// main entry point for all windows programs (Unicode)

int WINAPI wWinMain(HINSTANCE hinstance,

    HINSTANCE hprevinstance,

    LPWSTR lpcmdline,

    int ncmdshow)

{

    // call message box api with NULL for parent window handle

    MessageBoxW(NULL, L"THERE CAN BE ONLY ONE!!!",

        L"MY FIRST WINDOWS PROGRAM",

        MB_OK | MB_ICONEXCLAMATION);

    // exit program

    return 0;

} // end wWinMain

Copilot then creates a nice diff environment within the Code window:

Use the Tab key selectively and the final code is updated to the below, which is the same that was displayed in the Copilot Chat window:

// DEMO2_2.CPP - a simple message box

#define WIN32_LEAN_AND_MEAN

#include <windows.h>        // the main windows headers

#include <windowsx.h>       // a lot of cool macros

// main entry point for all windows programs (Unicode)

int WINAPI wWinMain(HINSTANCE hinstance,

    HINSTANCE hprevinstance,

    LPWSTR lpcmdline,

    int ncmdshow)

{

    // call message box api with NULL for parent window handle

    MessageBoxW(NULL, L"THERE CAN BE ONLY ONE!!!",

        L"MY FIRST WINDOWS PROGRAM",

        MB_OK | MB_ICONEXCLAMATION);

    // exit program

    return 0;

} // end wWinMain

Compile it again and there’s still an error, with an unresolved external:

Now, this is a common error.

I asked for help from Copilot again:

I have accepted all of your changes, but the compile still fails with LNK2019 and LNK1120 unresolved externals error messages. Can you help me with that?

Yes, I can help. The linker errors LNK2019 and LNK1120 typically mean that the linker cannot find the entry point or other required symbols. In this case, the most common cause is that the project is still configured to use WinMain as the entry point, but your code now uses wWinMain for Unicode.

How to fix:

  1. Ensure the project is set to use Unicode:
    1. In Visual Studio, go to Project > Properties.Navigate to Configuration Properties > General.
    1. Set Character Set to Use Unicode Character Set.
  2. Set the correct entry point:
    1. Go to Configuration Properties > Linker > System.Ensure Subsystem is set to Windows (/SUBSYSTEM:WINDOWS).
    1. If you still get errors, explicitly set the entry point:
      1. Go to Configuration Properties > Linker > Advanced.
      1. Set Entry Point to wWinMainCRTStartup.
  3. Rebuild the project.

Why this works:

  • wWinMain is the Unicode entry point, and the CRT startup code expects to call wWinMainCRTStartup when Unicode is enabled.
  • If the entry point is not set correctly, the linker cannot find the function to start your program, resulting in LNK2019/LNK1120.

Summary of steps:

  • Set the project to use Unicode.
  • Set the entry point to wWinMainCRTStartup if needed.

Try these steps and rebuild. If you still see errors, please provide the full error messages for further assistance.

In my opinion, #1 seems unlikely. And besides, I can’t find Character Set in the Project Properties (I believe that was superceded in my most current version of VS):

So going on to #2, I find in fact that the Linker Subsystem is not correctly set:

I saw that error 25 years ago. It’s strange that it’s still there – you would think the system would be able to auto-correct that. And although I asked Copilot to go ahead and change it, it refused – it said it doesn’t have access to my HelloWorld.vcxproj project file:

I do not currently have access to your HelloWorld.vcxproj project file, so I cannot directly check the Linker Subsystem setting.

Anyway, I made the change suggested, and it compiled and ran successfully!

This took only about five minutes to get through – amazing!

Just for fun, I decided to have the same interaction with ChatGPT 5:

Thought for 11s

Here’s a tiny, modernized version that compiles on Visual Studio 2022 (Community), runs on Windows 11, and uses Unicode explicitly:

// A minimal Unicode Win32 app that shows a message box.

// Build: Visual Studio 2022 (Community)

// Platform: Windows 11 (works on earlier versions too)

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

// Unicode entry point (no console)

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,

                      _In_opt_ HINSTANCE /*hPrevInstance*/,

                      _In_ PWSTR /*lpCmdLine*/,

                      _In_ int /*nCmdShow*/)

{

    MessageBoxW(nullptr,

                L”THERE CAN BE ONLY ONE!!!”,

                L”MY FIRST WINDOWS PROGRAM”,

                MB_OK | MB_ICONEXCLAMATION);

    return 0;

}

Why this works now

  • Uses the Unicode entry point wWinMain and wide‐char Windows API (MessageBoxW) instead of ANSI.
  • Drops the old <windowsx.h> macros you don’t need for this sample.
  • Avoids deprecated/ambiguous types like LPSTR in the entry point.

Visual Studio 2022 setup (quick)

  1. File → New → Project → Windows Desktop Application (C++).
  2. Name the project, then Create.
  3. In Project → Properties (for All Configurations):
    • General → Character Set: Use Unicode Character Set.
    • (Optional) C/C++ → Language → Conformance mode: Yes (default).
  4. Replace the auto-generated .cpp with the main.cpp above.
  5. Build → Build Solution (Ctrl+Shift+B), then Debug → Start Without Debugging (Ctrl+F5).

That’s it—clean, Unicode-safe, and ready for Win11 with VS2022.

That compiled and ran like a charm!

It’s interesting that ChatGPT removed the deprecated #include <windowsx.h>, whereas Copilot just seemed to ignore it.

I also like the fact that ChatGPT used the Source (Code) Annotation Language (SAL) – for example, the _In_ and _In_opt_. It make the code much more readable. And finally, it used the more modern PWSTR, versus the legacy LPWSTR, as the pointer to the wide character string.

So, the winner is ChatGPT, at least for now.

To wrap this up, there are dozens and dozens of examples on the CD that was included with the book, in its original form. It might be hard to find that CD now, but I have the original source.  Here are the contents for all 15 chapters:

In my spare time, I plan to go through much of the content of the book again and modernize the code. Many of the older .exe files that Andre included in the book’s CD don’t run anymore (although some of them do – which is amazing!) so over time I’ll bring them all into Windows 11 and the 21st century.

Categories
Graphics and Game Programming

Explorations in 3D Graphics and DirectX 12: Episode 4: Chapter 14 – a beautiful demo

A few months have gone by, and I’m plowing away at Frank D. Luna’s book, 3D Game Programming with DirectX 12. It’s a lot of fun, and I’m learning a lot. And all this in between a full work schedule, including some webinars (I’ll write about them later; in the meantime, just look at my Company Blog); as well as my running hobby in the background.

This will be quick: I’m up to Chapter 14, and compiled the demo program that’s in there. Here’s a pretty video from the demo:

As you can see, the quality of the graphics is getting better and better, as the book progresses.

If you want to follow along, be sure to read the first three episodes in this series:

Episode 1

Episode 2

Episode 3

There are some bugs in D. Luna’s code, as well as some idiosyncrasies introduced over the years within different versions of Visual Studio, so these episodes will help you get past them.

Categories
Graphics and Game Programming

Review: Game Engine Architecture

I got the book Game Engine Architecture by Jason Gregory for Christmas. If you’re a technical geek, even if you’re not really into game design, this book is a must-have.

At 1,200 pages, this is a massive tome. It must be Jason Gregory’s “Magnum Opus”. I was delighted to see that, aside from the expected content on 3D Math, Rendering, Animation, Collision Detection, Audio, etc. it also delivered some hardcore computer science content on compiler optimizations, profiling tools, C++ coding practices, parallelism and concurrent programming, file systems, debugging, and a bunch of other topics.

So, if you’re like me, you’ll run, not walk, to buy this book. It will be providing me with months of fun reading.

Categories
Graphics and Game Programming

Explorations in 3D Graphics and DirectX 12: Episode 3: New bugs in VS2019 Version 16.8.3

What a pain! I’ve upgraded Visual Studio 2019 to Version 16.8.3, and it took me a while to find out that’s unveiled a bug in the code.

As you’ve seen from my prior blogs, Explorations in 3D Graphics and DirectX 12: Episode 1 and Explorations in 3D Graphics and DirectX 1w Episode 2: Video of Episode 1, I’ve been playing around with the demonstration examples in Frank D. Luna’s book, and having some great fun. But, then, a new bug emerged.

There are 23 chapters in the book 3D Game Programming with DirectX 12 by Frank D. Luna; most of which have little demo programs that you can download, import into Visual Studio, compile and run. The first 80 pages of the book crawl (slowly) through some of the math needed for 3D graphics: Vector Algebra, Matrix Algebra, Transformations, etc., and it’s pretty heavy going. To keep myself entertained in the meantime, I’m skipping ahead and honing my C++ and Visual Studio skills by working with the demo programs. I’ve actually learned a lot, as you can see by the prior two blogs, by overcoming some shortcomings in the programs introduced in the four years or so since the book was published.

I got up to Chapter 10 of the book’s demo programs when I hit a snag: even after applying all the workarounds I found out about, I got some new errors when I compiled a “Blending” demo application:

There are a bunch of C2102 “‘&’ requires l-value” errors coming out of the program compile. I worked my way through the code, pulling my hair out, until I found someone else with the same problem https://github.com/microsoft/directx-graphics-samples/issues/652 dated September 22, 2020. It turns out that some Visual C++ updates for the latest release changed something called “/permissive-“. Luna’s code is non-conforming to the new update: specifically, we’re using r-values and not l-values in these lines of the software.

So, problem easily solved! I right-clicked on the Project, chose Properties, then C/C++ -> Language and changed Conformance mode from “Yes” to “No”.

Then my program ran nicely:

Whew! This is probably not the best way to solve the C2102 errors, though. I’ll explore the code a little more, and introduce some fixes that address the VC++ updates for /permissive-.

Categories
Graphics and Game Programming

Explorations in 3D Graphics and DirectX 12: Episode 2: Video of Episode 1

Want a more visual version of the first blog in this series? There are some errors and omissions within Frank D. Luna’s book, 3D Game Programming with DirectX 12, so this video should help you get started:

Categories
Graphics and Game Programming

Explorations in 3D Graphics and DirectX 12: Episode 1

Explorations in 3D Graphics and DirectX 12: Episode 1

Almost 20 years ago, I picked up a copy of Andre LaMothe’s Tricks of the Windows Game Programming Gurus book.

I don’t remember what prompted me to select this particular title. Around that time, in 2001, I was promoted to the President role for the Adtech division within Spirent Communications. We had been growing exponentially for the prior two years. And then the “tech wreck” hit us hard in 2002; our company shrank from 150 people down to 80 over the course of one year. We struggled just to survive. It was a very stressful time for everyone.

The long hours and stress were taking their toll, and I needed an outlet. I played some video games in my spare time, and had always wondered at the technology behind their creation. 3D graphics for video games were a new concept back then: one of our favorite games was Serious Sam, and though it looks pretty simple now, the graphics just blew us away at the time.

So, I read the book from cover to cover, in the evenings and on weekends. At about the same time as I finished the book, I started a new job, so then put it down and didn’t pick it up again until very recently. I had also bought LaMothe’s Tricks of the 3d Game Programming Gurus: Advanced 3d Graphics and Rasterization in 2003 (probably the very first book I had ever pre-ordered, I was so anxious to get it), but never got past the first few chapters before life intervened. Time flies. Almost 20 years.

Amazingly, both Tricks books are as fresh now as they were then. You have to give credit to Andre LaMothe for that. Most of the .exe files that were on the CDs still run, with no changes. You can’t say that about a lot of 20-year-old software.

But I’ll get back to Tricks of the Windows Game Programming Gurus later – let’s fast-forward to 2020, where the pressure of the pandemic made me look for another source of stress relief, and I returned to the comfort of computer graphics technology. After I flew through LaMothe’s book for a second time last month, I decided that I wanted to learn more. Time has moved on, and technology has advanced. And I was especially interested in the graphics part of game programming, as opposed to collision detection, sound generation, particle physics, and the other aspects of the application.

So, on a bit of a whim, I ordered Frank D. Luna’s 3D Game Programming with DirectX 12. It was published in 2016, but appears to be the most recent book on the topic.

In the Introduction, Luna gives a short description on compiling and running a demo application that displays a colored box on the screen. Like LaMothe’s book, a CD is provided with source code; and Luna has the source also in a Git repository. Unlike LaMothe’s books, though, the executables are not provided, so it is up to the reader to build the program and execute it.

I found (as have others on the web) that Luna’s build instructions don’t work “out of the box” (forgiving the pun). In the Introduction, on page xxix (Location 818 within my Kindle edition of the book) Luna starts a chapter entitled Demo Project Setup in Visual Studio 2010, even though he later refers to VS2015. I wanted to use Visual Studio 2019. Also, some API have (unbelievably) changed between then and now, so some code needs to be updated to reflect that. And there are a few other issues here and there.

So, I’ll dedicate the rest of this article on detailed, step-by-step directions on how to get the demo programs in his book to work.

You will, of course, need the Windows 10 SDK: https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk/. As of the time of this writing, the Windows 10 SDK (10.0.19041.0) for Windows 10, version 2004 provides the latest headers, libraries, metadata, and tools for building Windows 10 apps. There were no changes needed for Windows 10 20H2, the version I am running on now.

Open up VS2019, and select Empty Project:

Then save the Project, for example under the name Box (same as the Solution name). You’ll note that I have Luna’s “d3d12book\MyDemos” folder in my root (C:\) directory. But, do not check the checkbox for placing the solution and project in the same directory:

Right-click on the Project name, select Properties, and under General, ensure that the Windows SDK Version says “10.0 (latest installed version)”.

Also, under Properties, click on Linker > System, and change the Subsystem from Console to Windows:

Click OK.

Next, right-click on the Project again, and select Add… > Existing Item. Then go to C:\d3d12book\Common and pull across all the .cpp  and .h files there into the Project:

Your Solution Explorer should then look like this:

Then, go to C:\d3d12book\Chapter 6 Drawing in Direct3D\Box, and copy BoxApp.cpp and the Shaders folder into the C:\d3d12book\MyDemos\Box folder:

Note that this must be in the top “Solution” level! There is another “Box” folder MyDemos\Box\Box, but don’t put the source there; the MyDemos\Box\Box folder holds the Project files.

Now, right-click on the Project, select Add… > Existing Item, and pull the BoxApp.cpp from its “\d3d12book\Chapter 6 Drawing in Direct3D”, into the Project:

You see that BoxApp.cpp is now part of the Project.

Now, we have to deal with an old artifact in the Luna’s code. Within d3dApp.cpp, there is a function call at line 547:

HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);

This must be replaced with:

HANDLE eventHandle = CreateEventExW(nullptr, nullptr, NULL, EVENT_ALL_ACCESS);

There’s some history to this change that I haven’t thoroughly researched, but you need to do it; otherwise, the compiler will always error out with “invalid argument” C2664:

I made this change directly to the d3dApp.cpp within the Common folder, so I wouldn’t have to change it for each and every single Project.

Then, the Project will Build!

Note, you’re going to see a couple of Warnings:

1>C:\d3d12book\Common\d3dUtil.cpp(30,5): warning C4244: ‘argument’: conversion from ‘std::streamoff’ to ‘SIZE_T’, possible loss of data

1>C:\d3d12book\Common\d3dUtil.cpp(70,32): warning C4244: ‘=’: conversion from ‘UINT64’ to ‘LONG_PTR’, possible loss of data

But, these don’t seem to affect the outcome.

WAIT! There’s one more thing you need to do. The executable needs to be copied up one level, to get it into the same folder that holds the Shaders folder, for the executable to run without this error message:

So, copy Box.exe from C:\d3d12book\MyDemos\Box\Debug up to C:\d3d12book\MyDemos\Box:

And then, double-click on it:

It works! That’s all there is to it.

Hopefully, someone who might be stuck trying to get Luna’s demo programs to work reads this, and finds it helpful. The book looks really good: it was fun and satisfying to reverse-engineer the demo programs and get that thrill of having the programs run successfully. I’ll write more about what I learn as I plow through the material.