Sunday, May 17, 2015

Update ...

Hey, so in the rush to get the last post out, I missed a couple of things. Like getting the Maven project to actually run.

So, I've done that and updated the project to reflect that.  Also, more documentation in the folders (a few more additions).

Have a good long weekend, folks.

Sunday, April 26, 2015

Long Time, no post. Today we talk about distributed real-time systems, Logging systems and 'The Cloud'

*dusts off the computer monitor, flicks a few switches and the hum of memory banks energizing can be heard in the background*

Good lord, has it been this long since I wrote a blog post? Wow.

Sorry about that folks.

Anyway, I've been doing a lot of things lately that are sort-of game related, but actually a little more mainstream. And I thought I would share it with you guys out there.

So, a little background, for you to get up to speed.

I shipped Dragon Age: Inquisition. I'm immensely proud of what we were able to accomplish on that title. A lot of firsts for me. And an amazing team that I had the luck to work with.

But times change. Family wanted to be back on the west coast. BC in specific. Apparently once it's in your blood, it's there for life.

Anyway, the fine folks at Demonware ( were gracious enough to offer me a position there and boy howdy, has it been a learning experience.

One of the things I'm working on is real-time event ingestion. That's not something I'll be talking about here (at least, not for a while), but I would like to talk about a couple of technologies I've come across that might be of interest to the general public, as well as some of the fine folks at Demonware.

So, quick poll - how many people are familiar with metrics and event logging? Show of hands? Yeah, not a lot of my readers would be familiar with that. I was in the same boat. Coming from a game dev background, logging is something you do when you're debugging a build. But 'logging' for me meant 'printf''s all over the place. Or maybe even something a little more fancy in our scripts for manipulation assets.

What if I told you there was something else that you could use, that would persist that data. It's not a deep store, but it's in the 'days' range. What if I told you there were a number of things out there, Open Source that could do that. There are! The one we're going to look at is something called 'Kafka'. It's from Apache (you know, the guys that make that web server thing). You can find it here:

No, I'm not going to go into how to install/set it up. That's a topic that already has enough coverage. So go, Google that, do some digging, maybe even set up an instance. I'll wait.

Cool, isn't it? The things we're going to be focusing on here are Kafka Topics and Producers.

Just to re-iterate: A Topic is a container for like messages sent to Kafka. So you could create a topic in Kafka called '' and store a text blob in that message that represented the asset that failed to build, the machine that failed to build it, the time and any error information you wanted to persist. What sends that data to Kafka is called a 'producer'.

And I'm going to show you how to build one in Python.

I've created a git repository here for those playing along at home. The script is called and you can find it in the python folder.

from kafka.client import KafkaClient
from kafka.producer import SimpleProducer

import time
import random
import logging


pronouns_possessive = [ "my", "your", "his", "her", ...]
nouns_singular = ["attorney-general", "brother-in-law", ...]
nouns_plural = ["attorneys-general", "brothers-in-law", ...]
verbs_singluar = ["become", "catch", "drink", "drive", ...]
verbs_plural = ["becomes", "catches", "drinks", "drives", ...]
infinitives = ["to make a pie.", "for no apparent reason.", ...]

# Make sure to change 'hostname' below.
broker = "hostname:9092""Connection to Kafka = {0}".format(broker))

client = KafkaClient(broker)
producer = SimpleProducer(client)
index = 0"Sending strings")


while index < 10000:
    sentence = "{0} {1} {2} {3} {4}".format( random.choice(pronouns_possessive),
        random.choice(nouns_singular).lower() or random.choice(nouns_plural).lower(),
    producer.send_messages('sentenceTutorial', sentence)"sent {0} of 10000. Message: {1}".format(index, sentence))

So, aside from a pretty crappy sentence generator (feel free to update it), the meat of the code lives inside the KafkaClient and the SimpleProducer interface. The Broker is Kafka parlance for where the system broker for Kafka lives. The underlying broker technology Kafka uses is Zookeeper (you can look that up). I think I'm going to do an article on that at some point as it's interesting tech as well. For now, think of Zookeeper as a distributed registry (like the registry in Windows) for apps.

We push a message into a Kafka topic "sentenceTutorial" via the send_messages() method. We're not limited to sending one message at a time to Kafka, but they do have to be on the same topic.

So, what's in Kafka now? In the topic "sentenceTutorial" there will be a new string pushed once every 5 seconds. Kafka has lots of ways of printing out what's in the topic, so read up on kafka_console_consumer.

Alright. Now we have something putting content into Kafka. Now we want to consume that data. And by consume, I mean read. What we write doesn't actually remove content from Kafka. That data will naturally expire based on a sliding window defined in the Kafka setup.

So, this is where Apache Storm comes into the mix. There are a bunch of other real time systems available, but Storm has the longest legs on it. That and so far, it's been the most reliable.

So, in the java folder of the storm-tutorial repo, I have a stand-alone storm project that will also (I think) work in a clustered environment.

I'll leave it as an exercise for the reader to examine the pom.xml file to see how I've set up the project for Maven. It's as simple and straight-forward as you can make a Maven project.

Now for the actual code. This will end up being a starter point for more tutorials, so it's best to start off simple. This is nothing more than a main class with a single class for doing the processing.

So, what does Storm 'do'? From the Apache Storm website:
Apache Storm is a free and open source distributed realtime computation system. Storm makes it easy to reliably process unbounded streams of data, doing for realtime processing what Hadoop did for batch processing. Storm is simple, can be used with any programming language, and is a lot of fun to use!

You need to have a cluster set up for doing any distributed processing, but we can simulate that on a single machine (and we can also debug it better).

How does it work? It's essentially a network topology that defines data 'Spouts' and process 'Bolts' that transform the data. You use the topology framework to define the network of these Spouts and bolts.

Here's an example from the repo:

// The TopologyBuilder is what defines the topology for the storm
// processing 'network'
TopologyBuilder builder = new TopologyBuilder();

// This next section defines the configuration information for the Kafka
// spout.
GlobalPartitionInformation hostsAndPartition = new GlobalPartitionInformation();

// Make sure to change 'hostname' below
hostsAndPartition.addPartition(0, new Broker("hostname", 9092));
BrokerHosts brokerHosts = new StaticHosts(hostsAndPartition);
SpoutConfig config = new SpoutConfig(brokerHosts, "sentenceTutorial", "/demonwaretutorial", "987654321");

// defining a scheme here does some default data transformation.
// if we don't define it, the data comes across as raw binary.
config.scheme = new SchemeAsMultiScheme(new StringScheme());

// This is where we define a spout in our topology
builder.setSpout("spout", new KafkaSpout(config), 1);

// This is were we define our bolt in the topology and what data it receives
builder.setBolt("print", new PrinterBolt(), 1).shuffleGrouping("spout");

What we're left with, defined in the builder instance is a topology that takes data from the Kafka spout "spout" and feeds that data into a 'PrinterBolt' bolt.

Note the 'StringScheme' that is bound to the config.scheme. In essence, this does some preliminary data transformation of the data. I'll dig into that in a later tutorial as well (as I'm still figuring it out).

That PrinterBolt looks like this:

public static class PrinterBolt extends BaseBasicBolt {
    static Logger logger = Logger.getLogger(PrinterBolt.class);
     * This execute method reads the data ingested by the spout and simply
     * logs it.
     * It's a very straightforward bolt.
     * @param input
     * @param collector
    public void execute(Tuple input, BasicOutputCollector collector) {
        String msg = input.getString(0);"Received message: %s", msg));
     * Currently this does nothing.
     * @param declarer
    public void declareOutputFields(OutputFieldsDeclarer declarer) {

I recommend stepping through the execute method to see what is in the Tuple that is passed in. The long and short of it is, it's a map of objects and in this case, we're getting the first string in that map.

One last thing. In the main function, we also do this:

if (args != null && args.length > 0) {
    // So, if we're in here, we're running the topology on a cluster.
    StormSubmitter.submitTopologyWithProgressBar(args[0], conf, builder.createTopology());
else {
    // if we're here, we're running stand-alone.
    LocalCluster cluster = new LocalCluster();
    cluster.submitTopology("tutorial01", conf, builder.createTopology());

Like the comments say, the first block is for running in a distributed cluster mode. The second part runs it in stand-alone mode.

So, feel free to give the project a go. Make sure you change all the instances of 'hostname' in the code to your Kafka instance to get this running. I'll eventually make this so it's far more configurable for both the Java and Python codebases.

This was a lot. There also isn't a lot of theory in here. I think I'll tackle that in the next blog post.

Enjoy and looking forward to the comments!

Tuesday, January 07, 2014

Useful scripts and hacks

Over the years, I've run into hundreds of little hacks/scripts/nuggets of things that I find useful.  And I have no centralized spot to store/share them.

Time to fix that!  Here, for posterity, is a list of common hacks/scripts/nuggets that I've run into and need to hold on to!


 p4 diff -sd //branch | p4 -x -sync -f  ||| looks for missing file in //branch and force syncs them.
 p4 changes -m1 #have                   ||| run from a folder, tells you what the current changelist is.

Actually, I'm going to move these over to gists in github.  Find them here:

Sunday, February 17, 2013

Archeology 101

Yesterday I was a little bored, so I started looking for a good ol' fashioned FPS to play. Of course, while digging through older CD's, I came across some old CDIS backups. And, of course, I came across, semesters worth of work. And, for me, work == old, forgotten code.

While I was digging through all that code, I found my OGDF project. It was a gaming framework that I was working on while at CDIS I was going to use for student work, as a baseline for 'hey, here's some framework code that will get you into game programming while avoiding some of the pitfalls of dealing with window resizing, switching to fullscreen/windowed mode ... you know the stuff I'm talking about in this blog now.

Some really interesting ideas in that codebase, that I'm probably going to pull forward.

But, oh my god, some awful, AWFUL ideas in there as well (Yeah, I found the Singleton Hammer1).

Anyway, one of the crazy things that I found in there was a series of articles that I wrote that eventually went on to become the lua series I wrote for (shameless promotion) and were then published in 'Beginning Game Programming: A collection'.  It's crazy how something I wrote over 10 years ago still has an impact on folks; I still, once in a while, get questions on it.  I always intended on writing more on scripting languages (like using python, or other, alternative languages), but I could never find the time to do that.  And it's something that I don't get to spend enough time on day-to-day to become an expert on the subject.

1.The Singleton Hammer refers to any new programming/design methodology that people get tunnel vision on ... where if you only have a Hammer, everything looks like a Nail.

    Sunday, January 27, 2013

    Dev Zero - Actually getting that window on the screen - [Part 3]

    The goal this time around is to determine what we need to do in order to get a proper Window on-screen. What does it take to get a window on-screen in the land of Microsoft? Well it breaks down into a couple of API calls:

    • RegisterClassEx() to register the appropriate systems to Windows and to create a message pump to handle the OS events.
    • CreateWindow(), ShowWindow() and UpdateWindow() to actually create and show the window.
    • The actual message pump that handles all the OS events.

    So, where do we put that? Well, a fair bit of it could live in our window.cpp file, as a set of file-global vars and functions. And that would work OK. It's simple and relatively easy to read. Let's try that and see what we end up with.

    What's of note here? Well, there's a couple of things. First off, we don't end up passing into the window class any information about the HINSTANCE. Which we need to be able to register the class. But there's a little trick that works well and allows you to get the instance of the current thread:

    That, with one call, gives us everything we need to instantiate our application. However, it doesn't allow us to properly update.

    If you look at the Window::Update method, you can see that I use PeekMessage(), instead of GetMessage(). This is good, because GetMessage is a blocking call; we don't ever return until we get a message. For a game, that's bad, because we still want our application to process, even if we don't get any OS level events. However, this leaves us with havint to find a way to determine when the application has actually terminated. It's a little harder, because we have to resort to using that global s_ActiveWindow to truly determine if our application is live. But it works. And we end up with our application running and behaving as we would expect!

    This, however could be implemented in a cleaner fashion. In my next post, I'll show you how to do that.

    Note that this time around, I haven't posted any code. Mostly because this isn't a 'good' implementation. But the goal for tonight was to get a live application running (window up and visible). And we've accomplished that.

    Dev Zero - Basic Window framework [Part 1]

    Our next step is to get a proper window framework in place.  What do I mean by 'proper'?
    1. Creating an application should be trivial.  All I should need to do is ask for a window to be created (with some simple parameters), get some result back that allows me to access it.
    2. Register a callback to handle some general-case behaviours
      1. The Window has been resized.
      2. We want to change fullscreen modes (start up fullscreen, switch to windowed).
      3. Have an 'update', giving us a delta time between updates.
    3. Clean up upon closing the window.
    That, essentially, is all that I need.  But it has to happen across multiple platforms.
    So, what do I want this to look like? Pseudo code, to the rescue!

    Yes, I know. Greatly oversimplifying the process, I know. But why shouldn't it be that simple? We can add as many handlers as we need to the Window class to get our functionality.

    With that in mind, let's implement it!

    The very first thing that I want to do is generate that Window class. The problem becomes, how do I end up setting the framework up so that creating an appropriate 'MS Windows' or 'OS X' version is trivial?  The answer, surprisingly enough, is to leave it to the linker.

    Here's the deal.  We're going to define a Window class using a header file.  ALL the implementation details will be in a .CPP file.  One for Windows, one for OS X, one for what ever other platform we're interested in. We leave the details of which one to use up to the linker.  Right now, I'm going to use the development environment to set those, but we should be able to set the linker options for which file to link in via appropriate #pragma options.

    Anyway, what we've done is create a 'window.h' file inside the platform folder (wanton\source\platform). For Windows, we create a 'windows.cpp' file inside the SPECIFIC platform folder (wanton\source\platform\mswin). We then explicitly compile and link that file and voila, we end up with a transparent method of dealing with a very platform specific system. At some point in the near future, when I get an OS X version of this ready, I'll be creating an implementation of that inside the OS X folder (wanton\source\platform\osx).

    This isn't a perfect solution; it requires a lot of work in order to keep up multiple platforms. I can see using some third-party tools for generating the appropriate build files (cmake comes to mind), but you'd need something that allows you a fair degree of customizability in order to exclude folders based on the target platform. Not saying it can't be done (I know it can) but that's outside the scope of this article (for now).

    Anyway, getting back on track, this is what we have:


    I won't go into detail about the implementation of the MS Windows version of this class just yet (I haven't written it, TBH). However, you should see that I've got a new #include: delegate.h. This is a cool little library that makes adding delegates to your application fairly easily.

    What is a delegate, you may ask? Most who read my blog already know, but in case you are new, a delegate is functionally equivalent to a Function Pointer in C. But you can use methods in classes, as well as regular function pointers. And this implementation is fast. About as fast as you can get. This is courtesy of the code project: and it's a great little read. These delegates are going to allow me to create the callbacks that I mentioned earlier. You know, once I get the window class actually working!

    One other thing to mention. In getting ready for making this work across multiple platforms, I've added yet another new file to the project, a build_config.h that allows me to set on a per-platform basis, specific configuration options. Here's the contents of the file:


    That should look very simple to you, until you note that I define a preprocessor define as either being 'ON' or 'OFF'. Those are defined, currently, inside util.h (until I can find a better place). It's worth it to take a look at it:


    I like it. I like it a lot. You can find the original article at
    I don't know if I would call them 'easy preprocessor defines', but I would call them 'sensible preprocessor defines'. The win in readability alone makes it totally worthwhile.

    Now that I have that generated, I've stubbed out the windows implementation. It's totally non-functional, but allows us to do a simple test.


    I'll be doing a proper implementation in a bit. But for now, I want to test the 'process' in getting a build actually functional.

    However, at this point in time we actually have enough to allow us to generate an app. Not a fully functional app, but something that will run without crashing. Let's put a pin in it now and actually implement our winmain function.


    If you take the code as it stands right at this instant, with these changes, you end up with a 'functional' application that will start, update and immediately exit. Without showing a window. Yeah, that's useless, I know, but it moves us along into the next phase, which is actually getting a fully functional window on screen.

    However, at this point, I'm going to submit the code, again to have a common reference point along the tutorial.

    As with last time, you can find the code on sourceforge here: HEAD will always be a work in progress. I've put the build from this blog post into R01272013B.

    Starting From Scratch - Dev Zero

    One of the things I hate the most is project set up.  I've talked about that in the past, but I want to revisit it today.  Essentially, since this is a re-start of a lot of pieces that I've done in the past, I want to clear the slate, as it was, and talk about some of the things I've learned over this long, crazy journey that has been my career.
    One thing to be clear on.  I'm not going to be working on the OSX version of this until I have the windows basic framework put to bed.  I just wanted to make that clear from the get-go.
    First things first, let's lay out our project directory structure.  To me, that's a significant issue that needs to be resolved at the beginning of any project. I'm going to follow a fairly common project layout, with some small adjustments.
    Since this is going to run across multiple platforms, I want to ensure that each platform has it's own 'solution' folder.  On Windows, we'll be using Visual Studio (2012 for now, I'll backfill into 2012 later). I suspect on Mac it'll be Xcode.  Linux will undoubtably be makefiles of some sort. So, for lack of a better term, the project is called 'Wanton'. So my folder layout will look something like this:

    I'm a firm believer that one should never check in executables; whatever you submit into you revision control system should be able to rebuild without error.  Continuous Integration servers are great for that. They can submit a numbered build elsewhere that you can grab, if need be.  That and it allows for 'verified builds' to go out to the appropriate groups.
    I went ahead and let Dev Studio create the project for me.  It puts it into it's default layout (which isn't optimal for me).  So that requires a little hand editing.  It's fairly trivial to fix up the issues that are created by hand. It does mean, however, that you've got to touch the .sln and .vcxproj files in order to have everything compile correctly.  And it's a huge pain in the ass, the first time you have to do it.  But setting this up right from the start is a huge time saver later. It also makes setting up other build types (Debug/Release) that much easier once you have a baseline to start with.
    That's it for now.  I've uploaded the current build to google code.  There's currently nothing in there that's 'interesting' aside from how the project is laid out.  You can access it here:  The code relating to this post has been tagged as R01272013.  Please note that Head may not match the contents of this blog post (ergo the associated tag).  If you don't speak SVN, I recommend you pick up TortoiseSVN and read up here:
    That's it for today.  I suspect I'll have the next installment ready to go shortly.  Until then, keep it between the lines.


    Haven't been updating like I should have.

    A couple of reasons for this, I think.  Mostly the new job, but mostly because I don't have a good, *base* set of tools to work with.

    What do I mean by that?

    I hate having to rebuild stuff from scratch.  So I've been searching for stuff to make things 'easier' to code in.  So I'll bounce back and forth bewteen C++ and C#.

    Here's the rub.  All I really want (at this point in time) is a simple windows abstraction layer.  Not 'Microsoft Windows', but a simple Windowing UI.

    To be clear, the API only has to create a window, handle resizing/fullscreen switching and be easy for me to inject an 'onUpdate' function/thread.  Everything else, I'll handle.

    So, unless anyone out there knows of a simple library out there for doing this (C++ or C#, I really don't care), I'm going to end up doing that myself.

    Sunday, January 29, 2012

    Settling into the Edmonton Way of life

    OK, so maybe that's a bit premature.  The house is still a shamble, boxes are everywhere, it's Sunday night at 10:00 but dammit, I have a home office all set up again.

    Those of you that have been following me (probably not many since my last post was ... well, let's just say that it was a while ago) know that I tend to be a bit sporadic in my posts.  I've also said in the past that I'm going to try and be a bit more prolific.  Well, with it being a new year and all that, time to see what I can do.

    So, what's gone on in the last little bit.  I've spent time in Toronto, Canada's answer to New York (apologies to New York), did my bit at Ubisoft Toronto (hey guys!) and I'm now back west-ish in Alberta.  Edmonton to be specific.  Bioware Edmonton, to be very specific.

    See, it's a long tale.  One involving friends from way back (GTez, you know who you are) and several attempts to get me out here over the period of five years.  In all honesty, I was starting to feel a little stagnant and needed a change.

    Edmonton is good.  Surprisingly so.  As in "The family mostly likes it here".  The missus is very surprised at how much she likes it.  Even though we're constantly saying "you know, it's cold, but it's not *that* cold" (trust me, -27 in Toronto is very, VERY different than -27 here).

    From my standpoint, work is very good as well.  No more 4 hour daily commutes.  Seriously.  My daily commute now is under 30 minutes. I have a shockingly large amount of free time on my hands now.

    That's where this blog comes into play.  I now see that I have time again to put towards this little endeavour.  And I think I'm going to run with it.

    I'm going to continue on with my investigation into DX11, but I also think I'm going to play around with some other ideas too.

    So, with that, I hope to see you all soon!  And Happy New Year!

    Sunday, September 18, 2011

    Walking The Graphics Pipeline - Part 1

    There once was a time, many, many years ago that I was very, very versed in the language of rendering programmers.  That was many moons ago (talking 2004 here … pre DirectX 9b days).  I’ve only been marginally keeping up, so when people talk about deferred renderers, I know what they’re talking about from a purely theoretical level.

    I’m tired of only understanding it from a theoretical level.  So I’m going to be taking the next couple of months to get my chops up to snuff.  And I thought I’d take you all along for the ride.

    I’m going to be focusing on DirectX 11 for the majority of these articles.  It’s new and whiz-bangy.  It’s not particularly useful when it comes to things like Xbox development, but it is the ‘next’ gen api.  I’m also not going to talk about OpenGL here, simply because I want to keep my focus on one thing.  I will probably approach OpenGL in a later post.

    So, where to start?  I’m tempted to use the DirectX sample framework as it gives us a *lot* to work with.  I’m not going to use their wrapper for DirectX, as that defeats the purpose of this exercise. As well, all dev will be running in both x86 and x64 modes.

    For now, this will be a simple Windows app.  Nothing fancy here.  So, putting a window up on screen looks like this, in straight C/C++:

    // wtgp_01.cpp : An simple application base.
    // We are doing nothing at this point in time aside from
    // displaying a window.
    //  x86 and x64 support.
    #include "stdafx.h"
    HINSTANCE	g_hInst = NULL;
    HWND		g_hWnd	= NULL;
    // TODO:
    //   Eventually move this off into a separate utility library
    //   We output any caught memory leaks here.
    #if defined(DEBUG) || defined(_DEBUG)
    #include "crtdbg.h"
    #include "wtgp_01.h"
    // Forward declarations
    HRESULT InitWindow( HINSTANCE _instance, int _cmdShow );
    int APIENTRY _tWinMain(HINSTANCE _instance, HINSTANCE _prevInstance, LPTSTR _cmdLine, int _cmdShow)
    	// Enable run-time memory check for debug builds.
    	// Again, this should live in a separate library
    #if defined(DEBUG) | defined(_DEBUG)
    	if( FAILED( InitWindow( _instance, _cmdShow ) ) )
    		return 0;
    	// Main message loop
    	MSG msg = {0};
    	while( WM_QUIT != msg.message )
    		if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
    			TranslateMessage( &msg );
    			DispatchMessage( &msg );
    	return ( int )msg.wParam;
    // Register class and create window
    HRESULT InitWindow( HINSTANCE _instance, int _cmdShow )
    	// Register class
    	WNDCLASSEX wcex;
    	wcex.cbSize = sizeof( WNDCLASSEX ); = CS_HREDRAW | CS_VREDRAW;
    	wcex.lpfnWndProc = WndProc;
    	wcex.cbClsExtra = 0;
    	wcex.cbWndExtra = 0;
    	wcex.hInstance = _instance;
    	wcex.hIcon = LoadIcon( _instance, ( LPCTSTR )IDI_WTGP_01 );
    	wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
    	wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
    	wcex.lpszMenuName = NULL;
    	wcex.lpszClassName = L"WTGTP_01";
    	wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_WTGP_01 );
    	if( !RegisterClassEx( &wcex ) )
    		return E_FAIL;
    	// Create window
    	g_hInst = _instance;
    	RECT rc = { 0, 0, 800, 600 };
    	AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
    	g_hWnd = CreateWindow( L"WTGTP_01", L"Walking The Graphics Pipeline - 01", WS_OVERLAPPEDWINDOW,
    		CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom -, NULL, NULL, _instance,
    		NULL );
    	if( !g_hWnd )
    		return E_FAIL;
    	ShowWindow( g_hWnd, _cmdShow );
    	return S_OK;
    // Called every time the application receives a message
    LRESULT CALLBACK WndProc( HWND _hWnd, UINT _msg, WPARAM _wParam, LPARAM _lParam )
    	HDC hdc;
    	switch( _msg )
    	case WM_PAINT:
    		hdc = BeginPaint( _hWnd, &ps );
    		EndPaint( _hWnd, &ps );
    	case WM_DESTROY:
    		PostQuitMessage( 0 );
    		return DefWindowProc( _hWnd, _msg, _wParam, _lParam );
    	return 0;

    Simple straightforward Win32/64 app.  Nothing extravagant in it, but it’s a plain-jane starting point. Where I’ve spent most of my time on this so far is just setting up the project to put all the resultant and intermediate files into to the correct locations.  This isn’t hard to do, it just takes a while to set up right.  

    As it now stands, all binary files (exes, compiled media files, etc) will live in a ‘bin’ folder at the same level as the solution.  

    Inside of each project, there will be a ‘tmp’ folder where all temporary files (obj, manifest, build logs) will go.

    For your convenience, I've uploaded the source to the project here: wtgp-build_001.rar

    Shortly, I'll be adding some actual graphics to this project.  Stay tuned!