<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>luminance &#187; Code</title>
	<atom:link href="http://www.luminance.org/tag/code/feed" rel="self" type="application/rss+xml" />
	<link>http://www.luminance.org/blog</link>
	<description>Programming and Game Development - Kevin Gadd&#039;s Blog</description>
	<lastBuildDate>Sun, 02 Oct 2011 00:15:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>A Journey Into Linker Hell, And A Mistake</title>
		<link>http://www.luminance.org/blog/code/2011/08/01/a-journey-into-linker-hell-and-a-mistake</link>
		<comments>http://www.luminance.org/blog/code/2011/08/01/a-journey-into-linker-hell-and-a-mistake#comments</comments>
		<pubDate>Tue, 02 Aug 2011 00:08:46 +0000</pubDate>
		<dc:creator>Kael</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[heapprofiler]]></category>

		<guid isPermaLink="false">http://www.luminance.org/?p=1013</guid>
		<description><![CDATA[While doing some research into why Firefox sometimes takes a long amount of time to shut down, I discovered that builds of Firefox on my work machine could not even shut down successfully. Every time I tried to shut down, shortly into the shutdown process, I&#8217;d get a crash, with a message about heap corruption. [...]]]></description>
			<content:encoded><![CDATA[<p>While doing some research into why Firefox sometimes takes a long amount of time to shut down, I discovered that builds of Firefox on my work machine could not even shut down successfully. Every time I tried to shut down, shortly into the shutdown process, I&#8217;d get a crash, with a message about heap corruption. At first, I assumed I was dealing with breakage that someone had checked into trunk. When dealing with a large enough software project, the odds are good that pulling down the latest code from trunk will bring you a few bugs to discover. Very often, you can just roll back a few revisions, or find the right person and determine that they&#8217;ve already got a fix.</p>
<p>So, I tried those things. I rolled back a few revisions, rebuilt, and it still crashed. I tried rolling back four weeks to a known-good revision, and it still crashed. I went through all the commits over that time period to try and identify any obvious suspects, but didn&#8217;t find anything. I tried running the browser with a new, empty profile, on the assumption that perhaps one of my add-ons was causing the problem. Still crashed.</p>
<p>At this point, I could have thrown out my clone of the mozilla source code, along with my build folders, in the hopes that starting over from scratch would fix the problem. I&#8217;ve done this before, and sometimes it does make problems go away. But in practice, if everyone does this every time they hit a problem, insidious bugs can creep their way into your build system (or worse, your code base), and when you have a few hundred developers hacking on one project, the time wasted by using that solution adds up. So I decided to try and figure out why FF was crashing on shutdown.</p>
<p>The first thing I needed to figure out was whether the heap was actually corrupted. I started up Firefox inside the Visual Studio debugger and configured it to break on error, so that I could inspect the state of the application. At the point of the crash, here&#8217;s what the state looked like, along with some other useful information:</p>
<p><a href="http://www.luminance.org/wp-content/uploads/2011/08/failed_free.png"><img src="http://www.luminance.org/wp-content/uploads/2011/08/failed_free.png" width="800" height="967" /></a></p>
<p>The most immediately obvious piece of information is that the &#8216;crash&#8217; in this case is actually a breakpoint, triggered by <tt>ntdll.dll!_RtlValidateHeap</tt>. Furthermore, if we walk up the stack a bit, we can see that this is from <tt>msvcr100d.dll!_free_dbg</tt>. This tells us that we&#8217;re using the debug heap provided by the Visual C++ Debug Runtime, and the validations it performs when freeing a block of memory have failed. This can happen for various reasons, but if it happens, it almost always means something is wrong.</p>
<p>Next, we need to figure out <b>why</b> this is failing. There are a few obvious candidates, so let&#8217;s try to rule them out.</p>
<p>Memory corruption would be a likely cause. Corrupting memory that is infrequently used will probably not cause an application to fail, but when you try to free the memory, if the bookkeeping data used by the heap was also corrupted, the <tt>free</tt> call will fail. To rule that out, I walked up the stack to find free()&#8217;s caller and figure out what kind of data I was dealing with:</p>
<pre>
  free(lib-&gt;name);
  lib-&gt;name = NULL;
</pre>
<p>Based on this, we can guess that the data is a name (and if you read more code, it&#8217;s clear that it is in fact a single-byte-per-character null terminated string). Finding the pointer being freed within the crashed process and looking at it in the debugger&#8217;s Memory window shows a well-formed string (see the Memory 1 and Locals panes in the screenshot above).</p>
<p>So, casual inspection suggests that this is not memory corruption, but it&#8217;s still possible. What if the library in question is corrupting memory near the string, and that&#8217;s why free is failing when we unload the library?</p>
<p>To rule that out, I climbed further up the stack and discovered that there&#8217;s an environment variable you can set that prevents the library from being unloaded. Interestingly enough, setting this variable causes the crash to go away&#8230; but one of Firefox&#8217;s child processes, plugin-container, then crashes in the same way, unloading a different library. This suggests that it&#8217;s at least not specific to one single library.</p>
<p>At this point, I decided I wanted to know where lib-&gt;name was coming from. I tried a couple quick searches with DXR (for <a href="http://dxr.mozilla.org/mozilla/search.cgi?tree=mozilla-central&#038;string=lib-%3Ename">lib-&gt;name</a>, then <a href="http://dxr.mozilla.org/mozilla/search.cgi?tree=mozilla-central&#038;string=-%3Ename">-&gt;name</a>), but the first didn&#8217;t provide any results, and the second provided a bunch of results. </p>
<p>So, instead, I started Firefox up under Heap Profiler, and then attached a debugger and shut it down normally. I followed the above steps to get the address of the pointer being freed, and then opened up the Heap view of the latest snapshot I had taken in Heap Profiler. It was at this point I realized that I had completely failed to anticipate this use case when I was working on Heap Profiler, so I had to manually scroll through the heap, looking for the address I wanted. Whoops. Luckily, the address was near the beginning of the heap, so I found it easily:</p>
<p><a href="http://www.luminance.org/wp-content/uploads/2011/08/allocator.png"><img src="http://www.luminance.org/wp-content/uploads/2011/08/allocator.png" width="800" height="633" /></a></p>
<p>Now, given the stack, I knew exactly who was responsible for allocating the string. Closer inspection even revealed why I was getting a crash: The string was being allocated by <tt><b>msvcr100</b>!malloc</tt>, but freed by <tt><b>msvcr100d</b>!free</tt>. Wait, how is that even possible?</p>
<p>I set breakpoints on the respective calls and started Firefox under the debugger, to ensure that I wasn&#8217;t being tricked by DLL load/unload operations that were occurring between the malloc and free calls. After seeing that the data from Heap Profiler matched reality, I decided to do some more digging. I opened up the Modules window to confirm that yes, both the debug and release C++ runtimes were loaded, and used the watch window to find the addresses of free and strdup, respectively (as strdup was the function responsible for calling the release malloc, in this case).</p>
<p><img src="http://www.luminance.org/wp-content/uploads/2011/08/addresses.png"/></p>
<p>As you can see in the highlighted sections, <tt>__imp__free</tt>, the import symbol for <tt>free</tt>, points into <tt>MSVCR100D</tt>, while <tt>__imp___strdup</tt>, the import symbol for <tt>_strdup</tt>, points into <tt>MSVCR100</tt>. This is pretty confusing, and definitely confirms that the crash we&#8217;re seeing is caused by mismatched heaps.</p>
<p>At this point, there are two major questions:</p>
<ol>
<li>How are we loading both versions of the runtime in a debug build?</li>
<li>And, how is this causing strdup and free to get imported from different runtimes?</li>
</ol>
<p>This is especially troubling, because my local build of Firefox seems to run perfectly, other than this shutdown bug. You would expect mismatched heaps to cause all sorts of trouble. I did some digging around, and arrived at part of the answer to both questions:</p>
<p><img src="http://www.luminance.org/wp-content/uploads/2011/08/imports.png"/></p>
<p>This screenshot shows that <tt>nspr4.dll</tt> is linked against both runtimes, but <b>only imports <tt>_putenv</tt> and <tt>_strdup</tt> from the release runtime.</b> Everything else comes from the debug runtime! This explains why the heap mismatch is limited to the one crash I&#8217;m seeing, instead of causing widespread problems with Firefox &#8211; the effects of this linking problem are (theoretically) limited to code within NSPR, and further limited to code that uses <tt>_strdup</tt> or <tt>_putenv</tt>. Very mysterious.</p>
<p>After confirming that <tt>NSPR4.dll</tt> didn&#8217;t link against both libraries when compiled on my home machine, I set out to try and get verbose output from the linker, to identify just <b>why</b> I was getting linked against both runtime libraries. And this is where I made a mistake.</p>
<p>Earlier in the debugging process, I had convinced myself that the problem was reproducible, because checking out various revisions of the Firefox source code and doing full builds had caused the problem to persist. In order to get the linker to actually re-link <tt>nspr4.dll</tt> from scratch, I decided that I had to delete the contents of my build folder &#8211; I couldn&#8217;t get it to perform the link operation by simply deleting the output files (probably because I was deleting the wrong ones). So, I deleted my build folder, and performed a full build from scratch. Pouring over the log files for the build, I found the link command in question:</p>
<pre>
c:\mozilla\nsprpub\config\rules.mk:330:0$ rm -f nspr4.dll
c:\mozilla\nsprpub\config\rules.mk:345:0$ link -nologo -DLL -SUBSYSTEM:WINDOWS -DYNAMICBASE -OUT:"nspr4.dll" -DEBUG -MAP   advapi32.lib wsock32.lib winmm.lib ./prvrsion.obj io/./prfdcach.obj io/./prmwait.obj io/./prmapopt.obj io/./priometh.obj io/./pripv6.obj io/./prlayer.obj io/./prlog.obj io/./prmmap.obj io/./prpolevt.obj io/./prprf.obj io/./prscanf.obj io/./prstdio.obj threads/./prcmon.obj threads/./prrwlock.obj threads/./prtpd.obj linking/./prlink.obj malloc/./prmalloc.obj malloc/./prmem.obj md/./prosdep.obj memory/./prshm.obj memory/./prshma.obj memory/./prseg.obj misc/./pralarm.obj misc/./pratom.obj misc/./prcountr.obj misc/./prdtoa.obj misc/./prenv.obj misc/./prerr.obj misc/./prerror.obj misc/./prerrortable.obj misc/./prinit.obj misc/./prinrval.obj misc/./pripc.obj misc/./prlog2.obj misc/./prlong.obj misc/./prnetdb.obj misc/./praton.obj misc/./prolock.obj misc/./prrng.obj misc/./prsystem.obj misc/./prthinfo.obj misc/./prtpool.obj misc/./prtrace.obj misc/./prtime.obj io/./prdir.obj io/./prfile.obj io/./prio.obj io/./prsocket.obj misc/./pripcsem.obj threads/./prcthr.obj threads/./prdump.obj threads/./prmon.obj threads/./prsem.obj threads/combined/./prucpu.obj threads/combined/./prucv.obj threads/combined/./prulock.obj threads/combined/./prustack.obj threads/combined/./pruthr.obj md/windows/./ntmisc.obj md/windows/./ntsec.obj md/windows/./ntsem.obj md/windows/./ntinrval.obj md/windows/./ntgc.obj md/windows/./w95thred.obj md/windows/./w95io.obj md/windows/./w95cv.obj md/windows/./w95sock.obj md/windows/./win32_errors.obj md/windows/./w32ipcsem.obj md/windows/./w32poll.obj md/windows/./w32rng.obj md/windows/./w32shm.obj md/windows/./w95dllmain.obj  ./nspr.res
</pre>
<p>I dug around further in the log files to locate the <tt>nspr4.dll</tt> in question, deleted it, and then ran the link command with the additional <tt>-VERBOSE</tt> flag to get verbose linker output. Pouring through the verbose output from the linker, I located the two functions in question:</p>
<pre>
      Found __imp__free
        Referenced in prlog.obj
        Referenced in prlink.obj
        Referenced in prmem.obj
        Referenced in prdtoa.obj
        Loaded MSVCRTD.lib(MSVCR100D.dll)
</pre>
<pre>
      Found __imp__strdup
        Referenced in prlog.obj
        Referenced in prlink.obj
        Loaded OLDNAMES.lib(strdup.obi)
</pre>
<pre>
      Found __imp___strdup
        Referenced in OLDNAMES.lib(strdup.obi)
        Loaded MSVCRTD.lib(MSVCR100D.dll)
</pre>
<p>It was at this point that I realized my mistake: <tt>NSPR4.dll</tt> was now linking correctly. Somehow, my previous attempts at building older revisions of the code had not fixed the build, but entirely wiping out my build folder had fixed it. Now I felt like a moron.</p>
<p>On the other hand, the mystery grew slightly more mysterious: Somehow, <tt>strdup</tt> was different from <tt>free</tt> &#8211; the verbose linker output, even from this valid build, was different for the two! <tt>strdup</tt>, for some reason, was defined in <tt>OLDNAMES.lib</tt>, while free was defined in <tt>MSVCRTD.lib</tt>. Why the difference?</p>
<p>A quick search of MSDN reveals the truth: <a href="http://msdn.microsoft.com/en-us/library/ms235454%28v=vs.80%29.aspx">The POSIX <tt>strdup</tt> function is deprecated beginning in Visual C++ 2005, and you should use the ISO C++ conformant <tt>_strdup</tt> function instead</a>. <tt>strdup</tt> is an alias to <tt>_strdup</tt>! This means that the way the linker treats it is <b>different from the way the linker treats <tt>free</tt>.</b></p>
<p>Armed with this knowledge, I stumbled across a discussion forum post where someone encountered the same problem, by accidentally linking against both runtimes, and that post linked to <a href="http://connect.microsoft.com/VisualStudio/feedback/details/333868/programs-using-a-static-library-and-calling-strdup-crash">a bug report on Microsoft&#8217;s Connect website</a>. The bug report not only confirms that the crash in question is caused by having both heaps loaded, but describes the behavior as by design, and points out that strdup and free are being loaded from different runtimes.</p>
<p>And now, at the end of this long, frustrating journey, I have acquired many valuable things:</p>
<ul>
<li>A further distrust for huge build systems, and linkers in particular</li>
<li>The knowledge that loading both debug and release C++ runtimes is definitely not a good idea</li>
<li>The knowledge that aliases and exported functions in libraries are treated differently by the linker</li>
<li>A Heap Profiler to-do item: Add support for searching the heap by address</li>
<li>And most importantly: Don&#8217;t delete your build folder while debugging, even if you think you can reproduce the problem!</li>
</ul>
<p>(As an aside, while debugging <b>this</b> problem I also discovered that debug builds of Firefox crash on my personal machine but not my work machine &#8211; but the crash only occurs if I run <tt>firefox.exe</tt> from within a <tt>bash</tt> shell. I kind of hate computers.)</p>
<p>I hope this short tale of woe has given you some new ideas about how to debug the next mysterious crash you encounter. If it hasn&#8217;t, I hope it at least entertained you!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.luminance.org/blog/code/2011/08/01/a-journey-into-linker-hell-and-a-mistake/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Compiler-assisted Data Binding with LINQ</title>
		<link>http://www.luminance.org/blog/code/2010/04/27/compiler-assisted-data-binding-with-linq</link>
		<comments>http://www.luminance.org/blog/code/2010/04/27/compiler-assisted-data-binding-with-linq#comments</comments>
		<pubDate>Wed, 28 Apr 2010 07:33:05 +0000</pubDate>
		<dc:creator>Kael</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[JSON]]></category>

		<guid isPermaLink="false">http://www.luminance.org/?p=866</guid>
		<description><![CDATA[When trying to write reliable, maintainable software, it&#8217;s important to try and minimize duplication. When you find yourself writing the same magic number in multiple places, you move it into a named constant to eliminate the duplication. When you find yourself writing the same expression multiple times, you move it into a named function, or [...]]]></description>
			<content:encoded><![CDATA[<p>When trying to write reliable, maintainable software, it&#8217;s important to try and minimize duplication. When you find yourself writing the same magic number in multiple places, you move it into a named constant to eliminate the duplication. When you find yourself writing the same expression multiple times, you move it into a named function, or perhaps a property. Sometimes, you find yourself dealing with higher level duplication &#8211; entire concepts and patterns that you find yourself writing again and again. Many modern languages provide tools to help you eliminate this kind of duplication: class inheritance allows you to share common logic between classes by inheriting that logic from a parent class, and generic types allow you to apply a generic pattern to multiple individual types. Both of these tools work with the aid of the compiler, so they interact well with debugging tools and allow you to catch most errors at compile time. Sometimes, though, you run into duplication that can&#8217;t easily be eliminated, even with the aid of the compiler.</p>
<p>In many graphical applications, a common pattern is the need to remember user preferences or inputs. Modern languages provide useful tools that can make this task simpler &#8211; for example, both Java and C# provide ways to automatically serialize an entire data structure into XML, which eliminates the need to manually read/write your preference values. Unfortunately, even with the aid of these features, you still find yourself with a lot of duplication &#8211; even if the runtime can automatically serialize your data structure, you still have to fill the structure out with your preferences, or read them back in manually. I&#8217;m going to demonstrate how you can use a little-known aspect of the new LINQ feature in C# 3.5 to eliminate duplication with the aid of the compiler.</p>
<p><a rel="attachment wp-att-869" href="http://www.luminance.org/wp-content/uploads/2010/04/PreferencesExample1.png"><img class="aligncenter size-full wp-image-869" title="Preferences Example Screenshot" src="http://www.luminance.org/wp-content/uploads/2010/04/PreferencesExample1.png" alt="" width="329" height="274" /></a></p>
<p>As an example, we&#8217;ll be using the simple application shown above. It&#8217;s a Windows Forms dialog box, with a few different controls, set up to remember user inputs between sessions. You can download the source code for this application below:</p>
<p><a href="http://luminance.org/articles/PreferencesExample1.zip">Preferences Example (v1)</a></p>
<p>If you run the application, input some values, and click OK, you&#8217;ll find that it stores your inputs in a JSON file in the %AppData%\PreferencesExample folder. If you run it again, you&#8217;ll see that it pulls your inputs back out of the JSON file to populate the UI.</p>
<p><span id="more-866"></span></p>
<p>Let&#8217;s take a look at the relevant parts of the source code:</p>
<pre>public void LoadPreferences () {
  if (!File.Exists(GetPrefsPath()))
    return;

  var serializer = new JavaScriptSerializer();
  var preferences = serializer.Deserialize&lt;Dictionary&lt;string, object&gt;&gt;(File.ReadAllText(GetPrefsPath()));

  checkBox1.Checked = (bool)preferences["checkBox1"];
  radioButton1.Checked = (bool)preferences["radioButton1"];
  radioButton2.Checked = (bool)preferences["radioButton2"];

  listBox1.SelectedIndices.Clear();
  var indices = preferences["listBox1"] as ArrayList;
  foreach (var index in indices)
    listBox1.SelectedIndices.Add((int)index);

  textBox1.Text = (string)preferences["textBox1"];
  dateTimePicker1.Value = (DateTime)preferences["dateTimePicker1"];
}

public void SavePreferences () {
  var preferences = new Dictionary&lt;string, object&gt;();

  preferences["checkBox1"] = checkBox1.Checked;
  preferences["radioButton1"] = radioButton1.Checked;
  preferences["radioButton2"] = radioButton2.Checked;
  preferences["listBox1"] = listBox1.SelectedIndices.Cast&lt;int&gt;().ToArray();
  preferences["textBox1"] = textBox1.Text;
  preferences["dateTimePicker1"] = dateTimePicker1.Value;

  if (!Directory.Exists(Path.GetDirectoryName(GetPrefsPath())))
    Directory.CreateDirectory(Path.GetDirectoryName(GetPrefsPath()));

  var serializer = new JavaScriptSerializer();
  File.WriteAllText(GetPrefsPath(), serializer.Serialize(preferences));
}
</pre>
<p>This application is relatively small &#8211; in particular, the JavaScriptSerializer handles a lot of the work involved in storing preferences for us. But regardless, we find ourselves having to list out all the control names multiple times, and some of those references to the controls are strings. Since they&#8217;re strings, that means that automatic refactoring tools, like the Rename tool in Visual Studio, won&#8217;t find them. As a result, this sort of code becomes difficult to maintain, especially in a larger codebase &#8211; changes are extremely error-prone and require careful, manual work.</p>
<p>What we want is a way to eliminate this duplication &#8211; a way to pull the list of controls and values out and store them in one place, so that we don&#8217;t have to specify them multiple times. Unfortunately, there&#8217;s no obvious way to do this in either Java or C#. While you can add the controls to a list quite easily, and walk over the list to get control names &#8211; eliminating part of the duplication &#8211; there&#8217;s no clean way to specify the particular fields/properties you wish to store.</p>
<p>Those of you familiar with reflection techniques may realize that you can eliminate the duplication by using reflection. By specifying a control and the name of the field we care about, we can use reflection to find that field and fetch its value. This technique will work, and other than the performance overhead of reflection, it will work well enough to ship in an application. However, it still suffers from the downside of breaking automated refactoring tools, and it&#8217;s somewhat error-prone due to the complexity involved in finding fields/properties via reflection.</p>
<p>One of the new features in C# 3.5 is support for &#8216;<a href="http://msdn.microsoft.com/en-us/library/bb397951.aspx" target="_blank">Expression Trees</a>&#8216;. Expression trees allow you to convert a C# expression into a tree of objects that describe the expression and allow you to evaluate it. This feature is used to support LINQ &#8211; for example, when you write &#8216;where i &lt; 5&#8242; in a LINQ query, the &#8216;i &lt; 5&#8242; portion of the query is turned into an expression tree, that LINQ can then use to run the query &#8211; for example, by turning it into SQL. As it happens, we can use this feature to solve our problem!</p>
<p>In C# 3.5, virtually any expression we can write can be converted into a delegate using lambda syntax, like so:</p>
<pre>Func&lt;int, int&gt; func = (x) =&gt; x * 5;</pre>
<p>And, as part of the Expression Tree feature, we can convert that lambda into an expression tree, at compile time:</p>
<pre>Expression&lt;Func&lt;int, int&gt;&gt; expr = (x) =&gt; x * 5;</pre>
<p>The compiler provides us all the information we need to evaluate an expression within the expression tree &#8211; if the expression references a field, the expression tree will contain the object containing the field, along with the FieldInfo object representing the field. Using this knowledge, we can eliminate the duplication from our sample application: By using a single expression to represent each preference we want to store, we can list all of our preferences in a single place in our application, and use that list of expressions to both load and save preference values. Best of all, because the compiler gives us full information on the expressions, we know the exact data types involved, and we can find out the name of the field being stored, and even the name of the object containing the field &#8211; eliminating the need to name each preference manually.</p>
<p>Using this knowledge, we can write a simple helper class that represents a field or property reference, and construct instances of that class by passing it an expression. You can find the source code to the class here:<br />
<a href="http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/Bind.cs">http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/Bind.cs</a><br />
And we&#8217;ll be using it to eliminate the duplication from our sample application. The code is relatively small &#8211; a couple hundred lines &#8211; so by reading it you can easily see how to apply this technique for your own purposes, even if you don&#8217;t end up using my code.</p>
<p>The first step is to use expressions to build a list of all the values we want to store. We&#8217;ll do this by creating an array of bound members in the dialog box&#8217;s constructor:</p>
<pre>IBoundMember[] BoundMembers;

public MainDialog () {
  InitializeComponent();

  BoundMembers = new IBoundMember[] {
    BoundMember.New(() =&gt; checkBox1.Checked),
    BoundMember.New(() =&gt; radioButton1.Checked),
    BoundMember.New(() =&gt; radioButton2.Checked),
    BoundMember.New(() =&gt; listBox1.SelectedIndices),
    BoundMember.New(() =&gt; textBox1.Text),
    BoundMember.New(() =&gt; dateTimePicker1.Value)
  };
}
</pre>
<p>Note that all we have to do is create an expression that evaluates to the value we wish to store. The C# compiler will convert it into an expression tree that tells us which object contains the value, and the FieldInfo or PropertyInfo we can use to fetch the value.</p>
<p>To eliminate the need to specify the name of each preference, we can combine the name of the field/property along with the name of the control containing the field/property, like so:</p>
<pre>string GetMemberName (IBoundMember member) {
  return String.Format("{0}.{1}", ((Control)member.Target).Name, member.Name);
}
</pre>
<p>If we specify the Checked property of a RadioButton named radioButton2, this function will evaluate to &#8216;radioButton2.Checked&#8217;.</p>
<p>With these two pieces of functionality, we can now eliminate all the duplication from the old LoadPreferences and SavePreferences functions:</p>
<pre>public void LoadPreferences () {
  if (!File.Exists(GetPrefsPath()))
    return;

  var serializer = new JavaScriptSerializer();
  var preferences = serializer.Deserialize&lt;Dictionary&lt;string, object&gt;&gt;(File.ReadAllText(GetPrefsPath()));

  foreach (var bm in BoundMembers)
    bm.Value = preferences[GetMemberName(bm)];
}

public void SavePreferences () {
  var preferences = new Dictionary&lt;string, object&gt;();

  foreach (var bm in BoundMembers)
    preferences[GetMemberName(bm)] = bm.Value;

  if (!Directory.Exists(Path.GetDirectoryName(GetPrefsPath())))
    Directory.CreateDirectory(Path.GetDirectoryName(GetPrefsPath()));

  var serializer = new JavaScriptSerializer();
  File.WriteAllText(GetPrefsPath(), serializer.Serialize(preferences));
}</pre>
<p>Another thing you&#8217;ll notice is that the type casting from the original version is gone &#8211; since we have type information, we can automatically cast preference values to the appropriate type &#8211; and if we were using a strongly typed datastore, instead of JSON, we could actually store preferences directly in their correct type, without having to do any boxing or type casting.</p>
<p>If you download the source code for the revised example:<br />
<a href="http://luminance.org/articles/PreferencesExample2.zip">Preferences Example (v2)</a><br />
You can run it and see that while it works the first time, and correctly saves preferences to JSON, it fails when loading preferences back from JSON. This turns out to be because of the JSON serializer: While listBox1.SelectedIndices is of type SelectedIndexCollection, the list we get back from the JSON serializer is of type ArrayList. The two types aren&#8217;t convertible, so the application fails.</p>
<p>Luckily, we can easily solve this problem. Since this technique works for any field or property, we can simply define a property that handles type conversion so that we don&#8217;t get an error when trying to load the preference value from JSON, like this:</p>
<pre>// This has to be ArrayList since that's what we get back from the JSON serializer
ArrayList ListBox1_SelectedIndices {
  get {
    var result = new ArrayList();
    foreach (var index in listBox1.SelectedIndices)
      result.Add(index);
    return result;
  }
  set {
    listBox1.SelectedIndices.Clear();
    foreach (var index in value)
      listBox1.SelectedIndices.Add((int)index);
  }
}</pre>
<p>If we change the list in the dialog box constructor to reference this new property instead of referencing the listbox directly, we can run the application and it will now successfully load and save preferences.<br />
<a href="http://luminance.org/articles/PreferencesExample3.zip">Preferences Example (v3)</a></p>
<p>With this technique, you can easily handle automatically loading and saving values from almost any datastore &#8211; and do so efficiently, without any unnecessary duplication, thanks to the information we&#8217;re given by the compiler. As an example, here&#8217;s a simple implementation of an object that loads and saves preferences from a database using this technique:<br />
<a href="http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/Data/PropertySerializer.cs">http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/Data/PropertySerializer.cs</a></p>
<p>I hope this post has shown you something useful! In the future I&#8217;ll be showing some other interesting applications of this technique.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.luminance.org/blog/code/2010/04/27/compiler-assisted-data-binding-with-linq/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>A managed WebKit library: BerkeliumSharp</title>
		<link>http://www.luminance.org/blog/code/2010/02/21/a-managed-webkit-library-berkeliumsharp</link>
		<comments>http://www.luminance.org/blog/code/2010/02/21/a-managed-webkit-library-berkeliumsharp#comments</comments>
		<pubDate>Mon, 22 Feb 2010 03:54:46 +0000</pubDate>
		<dc:creator>Kael</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[berkelium]]></category>
		<category><![CDATA[berkeliumsharp]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[webkit]]></category>
		<category><![CDATA[windows forms]]></category>
		<category><![CDATA[xna]]></category>

		<guid isPermaLink="false">http://www.luminance.org/?p=852</guid>
		<description><![CDATA[I spent the past day or so hacking together a managed wrapper for Sirikata&#8217;s Berkelium library. Berkelium allows you to easily embed a WebKit-based browser into games and other applications. It&#8217;s based on Chrome and it&#8217;s really easy to get up and running in a C++ application. Unfortunately, if you&#8217;re using C# or VB.net, you&#8217;re [...]]]></description>
			<content:encoded><![CDATA[<p>I spent the past day or so hacking together a managed wrapper for <a href="http://www.sirikata.com/blog/?p=115">Sirikata&#8217;s Berkelium library</a>. Berkelium allows you to easily embed a WebKit-based browser into games and other applications. It&#8217;s based on Chrome and it&#8217;s really easy to get up and running in a C++ application. Unfortunately, if you&#8217;re using C# or VB.net, you&#8217;re out of luck &#8211; no way to link directly against a C++ .lib file in those languages. The addition of my managed wrapper &#8211; <a href="http://code.google.com/p/berkelium-sharp/">BerkeliumSharp</a> &#8211; means that you can use the library in managed applications, and integrate it with Windows Forms, XNA, or even WPF.</p>
<p><a href="http://www.luminance.org/wp-content/uploads/2010/02/berkeliumtests.png" rel="attachment wp-att-853"><img src="http://www.luminance.org/wp-content/uploads/2010/02/berkeliumtests.png" alt="" title="berkelium test screenshots" width="633" height="494" class="aligncenter size-full wp-image-853" /></a></p>
<p>I&#8217;ve released the source under the BSD license (just like Berkelium) and included two simple examples (one for Windows Forms, one for XNA). It&#8217;s not a Chrome competitor but it&#8217;s surprisingly easy to get a lot of complicated things working &#8211; you can watch Hulu videos if you have Flash installed, and Flash games like Dino Run work in the Windows Forms example since it implements keyboard input.</p>
<p>You can <a href="http://berkelium-sharp.googlecode.com/files/BerkeliumSharpDemos.zip">download pre-built demos</a> to test it out, or <a href="http://code.google.com/p/berkelium-sharp/source/checkout">grab the source code</a> over at Google Code.</p>
<p>Have fun!</p>
<p><del datetime="2010-02-23T12:41:56+00:00">P.S. If you try out the examples, be aware that content that opens pop-up windows doesn&#8217;t seem to work. I think this is a bug in Berkelium.</del><br />
<b>Edit:</b> Figured out how to build Chromium and Berkelium myself and fixed the bug. Open source is awesome!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.luminance.org/blog/code/2010/02/21/a-managed-webkit-library-berkeliumsharp/feed</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Constant Binding</title>
		<link>http://www.luminance.org/blog/gruedorf/2009/08/13/constant-binding</link>
		<comments>http://www.luminance.org/blog/gruedorf/2009/08/13/constant-binding#comments</comments>
		<pubDate>Thu, 13 Aug 2009 10:31:28 +0000</pubDate>
		<dc:creator>Kael</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Gruedorf]]></category>
		<category><![CDATA[constants]]></category>
		<category><![CDATA[csharp]]></category>

		<guid isPermaLink="false">http://www.luminance.org/?p=729</guid>
		<description><![CDATA[One of the changes I made in the weeks leading up to my contest deadlines was to pull some of the player-specific combat logic, like that for attack chains, combos, and flinching, out into their own objects. Doing this let me apply that same combat logic to monsters and other entities in the game world, [...]]]></description>
			<content:encoded><![CDATA[<p>One of the changes I made in the weeks leading up to my contest deadlines was to pull some of the player-specific combat logic, like that for attack chains, combos, and flinching, out into their own objects. Doing this let me apply that same combat logic to monsters and other entities in the game world, which cut down on duplication considerably.</p>
<p>However, doing this made it clear that I had some architectural issues to tackle: All of these mechanics were heavily dependent on the <a href="http://www.luminance.org/gruedorf/2009/03/30/changing-constants-at-runtime">tunable constants</a> for the creature in question, which meant I couldn&#8217;t just pull methods and variables out of my entity classes into classes of their own.</p>
<p>To solve the problem of accessing an object&#8217;s constants, I came up with a solution based on reflection. I can define a helper object designed to handle an aspect of an entity&#8217;s mechanics &#8211; for example, a HealthPool object to manage the creature&#8217;s health, along with associated aspects like regeneration. The helper object can define instance variables for the constants it needs access to, like so:</p>
<pre>public class HealthPool {
    public Constant&lt;float&gt; HealthMax = null;
    public Constant&lt;float&gt; HealthPassiveRegen = null;
    public Constant&lt;float&gt; HealthRegenDelayTime = null;
    public Constant&lt;float&gt; HealthRegenRampTime = null;
    public Constant&lt;float&gt; FlinchThreshold = null;
    public Constant&lt;float&gt; FlinchThresholdDecay = null;

    public readonly RuntimeEntity Entity;
    public readonly ITimeProvider TimeProvider;
    public float Health = 0.0f;</pre>
<p>Note that these variables are the same name and type as the actual <a href="http://www.luminance.org/gruedorf/2009/03/30/changing-constants-at-runtime">tunable constants</a> &#8211; the difference is that instead of being static, they&#8217;re instance variables. Doing this allows me to pull a function out of an entity&#8217;s source code without needing to change the way it references particular constants, since the constants have the exact same names as before.</p>
<p>Of course, since these variables default to null, we need some way to fill them in with references to the actual tunable constants we want to use. To do that, we apply reflection:</p>
<pre>public static void BindConstants (object destination, params Type[] sourceTypes) {
    var genericConstant = typeof(Constant&lt;&gt;);
    var destinationType = destination.GetType();
    var destinationFields = new Dictionary&lt;string, FieldInfo&gt;();

    foreach (var field in
        destinationType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
    ) {
        var fieldName = field.Name;
        var fieldType = field.FieldType;

        if (!fieldType.IsGenericType || fieldType.GetGenericTypeDefinition() != genericConstant)
            continue;

        destinationFields[fieldName] = field;
    }

    foreach (var sourceType in sourceTypes) {
        foreach (var field in
            sourceType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy)
        ) {
            var fieldName = field.Name;
            var fieldType = field.FieldType;

            if (!fieldType.IsGenericType || fieldType.GetGenericTypeDefinition() != genericConstant)
                continue;

            FieldInfo destinationField = null;
            if (destinationFields.TryGetValue(fieldName, out destinationField)) {
                destinationField.SetValue(destination, field.GetValue(null));
                destinationFields.Remove(fieldName);
            }
        }
    }

    if (destinationFields.Count &gt; 0) {
        var constants = String.Join(", ", (from key in destinationFields.Keys select key).ToArray());
        var types = String.Join(", ", (from type in sourceTypes select type.Name).ToArray());

        throw new InvalidDataException(String.Format("Type(s) {0} do not declare the following constants:\n{1}", types, constants));
    }
}</pre>
<p>What we&#8217;re doing here is pretty simple: We accept a reference to an object that has constants requiring binding, and a list of source types to retrieve constants from. The function operates in two stages: First, we enumerate all the instance variables defined in the target object, and build a list of all the tunable constants it has that need to be bound. After that, we enumerate all the static fields of the provided source types, looking for constants that have names matching those of the instance variables on the target object, binding them where appropriate. After this, we can simply check to see if our list of constants is empty or not &#8211; if it&#8217;s empty, we successfully bound all our constants, and if it&#8217;s not, we know that one or more of the desired constants was missing.</p>
<p>We get a few useful things out of this: First, accepting a list of types allows us to do simple inheritance of constants. If we first check the most-derived type and then the base type of an entity, that allows us to define a &#8216;default value&#8217; for a particular constant, like &#8216;Maximum Health&#8217;, in a base class, and then define a new constant with the same name in the derived type. This also allows us to create &#8216;global defaults&#8217; for a given constant &#8211; for example, if we always put Game at the end of the type list, we can have global game-wide constants for things like physics parameters, and only override them in specific classes if necessary.</p>
<p>Finally, to wire things up, we just need to do a little work in the constructor for our helper object:</p>
<pre>    public HealthPool (RuntimeEntity entity, ITimeProvider timeProvider) {
        Entity = entity;
        TimeProvider = timeProvider;

        ConstantManager.BindConstants(this, entity.GetType(), entity.Game.GetType());

        Health = HealthMax;
    }</pre>
<p>In this case, we&#8217;re initializing the HealthPool using the constants defined in the entity, and falling back to any constants defined in the Game when the entity doesn&#8217;t specify them. If a necessary constant is missing, we&#8217;ll get an exception thrown when constructing our helper object. Once we&#8217;ve bound the constants, we can just use them like we would otherwise &#8211; in this case, the HealthPool automatically initializes itself based on the HealthMax constant.</p>
<p>This is definitely preferable to the approach I used to use for exposing an entity&#8217;s constants &#8211; previously, for important constants like an entity&#8217;s bounding box size, I&#8217;d define an abstract property in a base class, and override it in each derived type to return the value of the constant. Now, I don&#8217;t need to use any abstract members or interfaces; I can just bind to the constants once when I initialize my helper objects.</p>
<p>One thing of note is that since this technique uses reflection, you might run into performance issues if you&#8217;re binding constants repeatedly. This is pretty trivial to solve, however; you can just cache the results of a constant binding operation based on the destination and source types, since those aren&#8217;t going to change at runtime.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.luminance.org/blog/gruedorf/2009/08/13/constant-binding/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shipping a Brick</title>
		<link>http://www.luminance.org/blog/code/2009/07/15/shipping-a-brick</link>
		<comments>http://www.luminance.org/blog/code/2009/07/15/shipping-a-brick#comments</comments>
		<pubDate>Wed, 15 Jul 2009 19:18:30 +0000</pubDate>
		<dc:creator>Kael</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Games]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[reliability]]></category>

		<guid isPermaLink="false">http://www.luminance.org/?p=563</guid>
		<description><![CDATA[Computer software, and by extension, video games, are getting more complicated every day. It used to be that a game might be a few hundred thousand or maybe a million lines of code. Now, some of the third-party libraries we use in our games are approaching that size, if not already larger! Keeping that in [...]]]></description>
			<content:encoded><![CDATA[<p>Computer software, and by extension, video games, are getting more complicated every day. It used to be that a game might be a few hundred thousand or maybe a million lines of code. Now, some of the third-party libraries we use in our games are approaching that size, if not already larger! Keeping that in mind, it&#8217;s quite impressive that modern games still run for the majority of users. But here&#8217;s a simple fact: Sooner or later, someone is going to be unable to play your game. What you do then determines whether or not they will remain your customer.</p>
<p><a href="http://www.luminance.org/wp-content/uploads/2009/07/brick.png"><img class="aligncenter size-full wp-image-569" title="brick" src="http://www.luminance.org/wp-content/uploads/2009/07/brick.png" alt="brick" width="200" height="174" /></a></p>
<hr />A few years back I was doing design work on an MMORPG. Really satisfying work &#8211; come up with characters &amp; stories, try to construct gameplay around them, and then watch the rest of the team turn it into a living, breathing part of your game world that your players are going to interact with for months afterward.</p>
<p>So, at one point we decided to run a weekend promotion to promote our upcoming title. We temporarily enabled access to the content from our next game, and allowed people who didn&#8217;t own the game to create characters and play for the duration of the weekend. Great idea &#8211; get people in there at no cost, try and convince them your game is fun and worth playing. Works good for existing customers, too, because now they get excited about what&#8217;s coming down the pipe because you&#8217;ve let them play it for a couple days.</p>
<p>I was pretty excited about it, since it was the first promotion of its kind that we&#8217;d run since I had started working there &#8211; which meant I could finally show some of my friends what I was working on, and try and convince them it was worth playing. Most of them hadn&#8217;t even looked at the game since they had to pay for it first &#8211; and who can blame them, really?</p>
<p>Friday rolls around and I head home late and get some rest. The rest of the team does the same.</p>
<p>On Saturday morning, I send a message to a couple of my friends explaining how to download our client and try out the game. They&#8217;re both pretty enthusiastic about it and get started. A few minutes later, one of them says:</p>
<p><em>&#8216;Why can&#8217;t I use any skills?&#8217;</em></p>
<p>What? What do you mean you can&#8217;t use any skills? Are there buttons on the bar at the bottom of the screen?</p>
<p><em>&#8216;Yeah, but they have little lock icons over them. Nothing happens when I press them.&#8217;</em></p>
<p>Well, uh, s&#8211;t. That&#8217;s not supposed to happen. I emailed one of my coworkers to ask &#8211; uh, did anyone try creating a brand new account for the promotion to see if it worked? &#8211; and the answer is depressing: Nope. Luckily, it wasn&#8217;t a total loss &#8211; our existing customers were still able to participate in the event, because they already had working accounts. But for new, potential customers &#8211; the game didn&#8217;t work. They downloaded and installed our game, and it was mostly useless to them.</p>
<hr /><span id="more-563"></span>When you ship a title, you need to be prepared for it to break. What&#8217;s more, you need to <strong>know</strong> as soon as it breaks, and be prepared to take action to deal with the problem. Some issues simply can&#8217;t be solved, whether they&#8217;re caused by hardware problems or software glitches, and sometimes a bug that just affects one or two customers is not worth fixing. Regardless, though, you need to take action to keep your customers happy, whether that action is a patch, a refund, or a workaround. If you do nothing, your customers won&#8217;t be your customers much longer.</p>
<p>The worst possible scenario is that your game breaks and you don&#8217;t know about it. A modern game company can be quite hard to communicate with sometimes &#8211; when a person&#8217;s only choices for getting support are outsourced email support in India or &#8216;support forums&#8217; full of angry trolls, they might just give up instead of trying to get help. Even worse, if they bought the game with a credit card, they might just issue a chargeback instead of trying to get the game fixed &#8211; which costs you <strong>more than it would have to issue a refund</strong> &#8211; all because they either couldn&#8217;t, or simply didn&#8217;t, get in touch with you about their issues.</p>
<p><strong><br />
</strong></p>
<p><strong>As a developer, you want to do everything within your power to make sure that a customer with a broken game remains a customer. Here are some important steps you can take:</strong></p>
<p><strong><br />
</strong></p>
<h3>Provide a visible, straightforward channel for user feedback and support. An email address printed in the front of the manual, placed at the bottom of error dialogs, or on the front page of your website are a good start.</h3>
<p style="padding-left: 30px;">You can get extravagant by using things like forums, twitter, blogs, etc. to communicate with your customers &#8211; some of them will probably appreciate it &#8211; but it is <strong>tremendously important</strong> that whatever tool you provide for customer feedback be as simple and straightforward as possible, and that it be easy to find. Many game companies have switched to hugely complicated &#8216;automated support systems&#8217; that require logins, registration, password management, support tickets, etc. While these systems make sense from the perspective of a studio, most gamers <strong>simply won&#8217;t bother</strong> and will issue a chargeback instead of trying to figure out why your automated support system&#8217;s registration page is sending them an HTTP 500. If you want to manage support tickets using an automated system, go for it, but you <strong>absoutely</strong> need to accept customer feedback via email or some equally accessible method.</p>
<p style="padding-left: 30px;">Also, when considering the use of twitter, forums, or blogs, keep in mind that <strong>visible complaints and negative feedback</strong> cost you more than invisible ones. You should strive to encourage your customers to contact you privately before taking their issue public for the world to see. Ideally, you can resolve it in private before anyone else ever sees it, which limits the negative impact the issue has on your image as a developer.</p>
<p style="padding-left: 30px;">Prompt responses to feedback are also important. Nobody expects you to solve a bug in 2 hours, but you should strive to send your customer an initial response to their feedback as quickly as possible, even if the response is &#8216;We&#8217;re taking a look at your issue, please be patient &#8211; here&#8217;s a link to the ticket in our support system&#8217;.</p>
<h3>Provide news to your customers about ongoing issues with your game in an obvious and accessible location (your website&#8217;s homepage or the homepage for your title are good choices).</h3>
<p style="padding-left: 30px;">Running a website is, contrary to popular opinion, quite difficult. As a result, some developers tend to &#8230; <a href="http://brokentoys.org/2009/07/07/patching-is-so-2001/">forget to update their website</a>, or simply don&#8217;t offer support information for customers in a visible place, relying on blogs, forums, or news sites to serve as their method for communicating with customers.</p>
<p style="padding-left: 30px;">This is inadequate. It sucks, but you need to be putting regular updates out there for your customers in the first place they&#8217;re probably going to look &#8211; your website. If possible, you should put that news <strong>in the launcher</strong> for your game, if it has one. When you&#8217;re showing your customers an error message because the game failed to start, you should <strong>make sure to point them at your website, too</strong>, just to be sure that they get any information you have for them.</p>
<p style="padding-left: 30px;">It costs you time and money to communicate with your customers, but it&#8217;s time well spent and money that will pay for itself by keeping those customers from leaving.</p>
<h3>Design your game so that when it breaks, it breaks gracefully. Present clear, informative error messages that customers can pop into Google and send you via email.</h3>
<p style="padding-left: 30px;">So, let&#8217;s be honest. Software in general does not break gracefully. People are used to <a href="http://thedailywtf.com/Articles/Serious-SelfService.aspx">cryptic</a> <a href="http://thedailywtf.com/Articles/10,-10,-or-15.aspx">error</a> <a href="http://thedailywtf.com/Articles/Circular-Logic.aspx">messages</a> by now. Regardless, you should strive to do better.</p>
<p style="padding-left: 30px;">Every failure should present an error message that:</p>
<ul>
<li>Tells your customers what to do to resolve the problem (even if it is &#8216;contact customer support at support@mycompany.com&#8217;)</li>
<li>Clearly identifies the failure. Providing an error number or error code is good, so is providing the location where the error occurred. However, if possible you should avoid presenting gigantic stack traces or error dumps to the customer &#8211; they&#8217;re overwhelming, not helpful. Get them back to you, the developer, some other way.</li>
<li>Lists any <strong>user-actionable</strong> problems that contributed to the failure &#8211; &#8216;your microphone isn&#8217;t plugged in&#8217; is actionable, while &#8216;your Direct3D driver returned D3DERR_INVALIDCALL&#8217; is not.</li>
</ul>
<h3>Do whatever you can to find out about failures.</h3>
<p style="padding-left: 30px;">When your game fails, if possible, it should &#8216;phone home&#8217; to notify you. At the very least, it should report the version number of your game, the error that occurred, and a stacktrace of where it occurred.</p>
<p style="padding-left: 30px;">Sometimes it&#8217;s not possible to phone home &#8211; no internet connection, for example &#8211; and in that case, it&#8217;s okay to give up. If you&#8217;re concerned that failures happen a lot in this environment, consider storing the most recent failure message in your game&#8217;s AppData directory and reporting it the next time your game is launched with an internet connection. Better than nothing, right?</p>
<p style="padding-left: 30px;">In many cases you may find it useful to report detailed information on the user&#8217;s system configuration, and the circumstances under which the failure occurred &#8211; remaining memory and disk space available, etc. This is a good idea, but if you do it, you must be <strong>absolutely certain</strong> that you do not report a single shred of your customer&#8217;s personal/private information along with the crash report. If you do, they will be completely justified in kicking up an annoying s&#8211;tstorm about it on the internet.</p>
<p style="padding-left: 30px;">Some customers will complain about your game phoning home no matter what you do. As long as you only phone home when your game fails, you can safely ignore them. You&#8217;re doing your best to make sure the game works for everybody, and you&#8217;re not compromising their privacy. If they&#8217;re worried, they can unplug the ethernet cable.</p>
<p style="padding-left: 30px;">Note that if your game requires internet access to work anyway, you should probably also consider reporting a successful start and exit of your game as well. This will help you track down situations where your automated crash reporting also fails to work correctly (these are more common than you might think).</p>
<h3>Don&#8217;t compromise your game&#8217;s reliability for business reasons.</h3>
<p style="padding-left: 30px;">Now, to begin with &#8211; I&#8217;m not a fan of DRM, but I&#8217;m not going to try and convince you to abandon it here. If you&#8217;re already using DRM, you probably have a reason for doing so.</p>
<p style="padding-left: 30px;">However, there is <strong>no excuse</strong> for allowing DRM &#8211; or any other addition to a game title &#8211; to compromise the reliability of your game. Any addition -  DRM, an automatic updater, a &#8216;compatibility check&#8217;, etc &#8211; should never prevent customers who purchased your title from playing it.</p>
<p style="padding-left: 30px;">Nobody&#8217;s perfect, of course &#8211; sometimes your game is going to break despite your best efforts, and it will be due to some secondary part of the game, like DRM. In these situations, the previous rules apply: Provide clear, informative error messages, and communicate with your customers.</p>
<p style="padding-left: 30px;">When a game breaks because of a business decision, customers tend to be less willing to forgive. They just want to play your game; they don&#8217;t care about your revenue. Sorry. Therefore, while a good business decision is still a good business decision, you should always strive to make sure that you don&#8217;t make your game more likely to break.</p>
<p style="padding-left: 30px;">If the addition of DRM reduces piracy by 2% but causes the game to break for 4% of your legitimate customers, you just kneecapped the effectiveness of that DRM package, which doesn&#8217;t benefit anyone.</p>
<p style="padding-left: 30px;">
<p style="padding-left: 30px;">
]]></content:encoded>
			<wfw:commentRss>http://www.luminance.org/blog/code/2009/07/15/shipping-a-brick/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>&#8216;This application is not configured to use PerfHUD&#8217; &#8211; how to fix it</title>
		<link>http://www.luminance.org/blog/code/2009/07/01/this-application-is-not-configured-to-use-perfhud-how-to-fix-it</link>
		<comments>http://www.luminance.org/blog/code/2009/07/01/this-application-is-not-configured-to-use-perfhud-how-to-fix-it#comments</comments>
		<pubDate>Thu, 02 Jul 2009 01:35:21 +0000</pubDate>
		<dc:creator>Kael</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[NVidia]]></category>
		<category><![CDATA[NVPerfHUD]]></category>
		<category><![CDATA[PerfHUD]]></category>
		<category><![CDATA[retarded]]></category>

		<guid isPermaLink="false">http://www.luminance.org/?p=536</guid>
		<description><![CDATA[For anyone trying to use NVPerfHud, if you get stuck trying to figure out this error message: This application is not configured to use PerfHUD. Consult the User&#8217;s Guide for more information. You may have noticed that there is no reference to this error message, or &#8216;configuring your application&#8217; in the User&#8217;s Guide. The solution [...]]]></description>
			<content:encoded><![CDATA[<p>For anyone trying to use NVPerfHud, if you get stuck trying to figure out this error message:</p>
<p><strong>This application is not configured to use PerfHUD.</strong></p>
<p><strong>Consult the User&#8217;s Guide for more information.</strong></p>
<p>You may have noticed that there is no reference to this error message, or &#8216;configuring your application&#8217; in the User&#8217;s Guide. The solution is actually documented in the <strong>&#8216;<a href="http://developer.download.nvidia.com/tools/NVPerfKit/6.0/PerfHUD6-QuickTutorial.pdf">NVPerfHud Quick Tutorial</a></strong>&#8216;, and involves changing the parameters you pass to CreateDevice.</p>
<p>Hopefully posting this here will help other people find this information, since googling the error message turned up zero results for me. Good work, NVidia!</p>
<p>P.S. Preventing &#8216;unauthorized profiling by third parties&#8217;? What the hell is this, the cold war? This is computer graphics, not espionage. Can you imagine if other software worked this way?</p>
<p><em>To prevent unauthorized pixel modification by third parties, any images you wish to view with Adobe Photoshop must contain a hand-written sample of dialogue from the second act of A Midsummer Night&#8217;s Dream, by William Shakespeare. Please note that dialogue from modern adaptations like the 1999 version featuring Kevin Kline is <span style="text-decoration: underline;">not sufficient</span>. Also please note that handwriting in sufficiently obscure cursive scripts is unlikely to be recognized.<br />
</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.luminance.org/blog/code/2009/07/01/this-application-is-not-configured-to-use-perfhud-how-to-fix-it/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Threaded EndDraw in XNA (Crouching WaitOne, Hidden Lock)</title>
		<link>http://www.luminance.org/blog/gruedorf/2009/07/01/threaded-enddraw-in-xna</link>
		<comments>http://www.luminance.org/blog/gruedorf/2009/07/01/threaded-enddraw-in-xna#comments</comments>
		<pubDate>Wed, 01 Jul 2009 23:21:29 +0000</pubDate>
		<dc:creator>Kael</dc:creator>
				<category><![CDATA[Gruedorf]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[concurrency]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[threading]]></category>
		<category><![CDATA[xna]]></category>

		<guid isPermaLink="false">http://www.luminance.org/?p=526</guid>
		<description><![CDATA[After finishing up the materials for my Level Up 2009 entry, today I spent a little while trying out an idea I had recently: One of the problems with using vertical sync in a video game is that it eats into the available CPU time for performing game updates. The way vsync is implemented in [...]]]></description>
			<content:encoded><![CDATA[<p>After finishing up the materials for <a href="http://software.intel.com/en-us/contests/levelup2009/entry_detail.php?entryid=132339">my Level Up 2009 entry</a>, today I spent a little while trying out an idea I had recently:</p>
<p>One of the problems with using vertical sync in a video game is that it eats into the available CPU time for performing game updates. The way vsync is implemented in most graphics APIs, it causes your Present/EndDraw/SwapBuffers call to block until the card enters vertical blank and the frame is shown to the user. While this is ideal from a correctness perspective, it&#8217;s a tremendous waste since it means you can end up sitting there for up to 16 milliseconds, waiting for vertical blank. If your game spends lots of time doing both updating and drawing, all that time could be spent performing updates instead. Ouch.</p>
<p>Currently, my game spends about as much time drawing as it does updating. A significant portion of the time spent drawing (20-30%) is within the EndDraw function. Turning off vertical sync drops the amount of time spent in EndDraw considerably, but introduces tearing. So, as a potential solution, why not call EndDraw on a background thread? While the thread waits for vertical blank, I can begin performing the next frame&#8217;s Update, and in the event that I finish updating before the previous frame is visible, I simply wait for that previous EndDraw call before beginning to paint the next frame. In the optimal case, this means I can come much closer to the best possible framerate without introducing tearing, and in the worst case, the cost of rendering an individual frame is only *slightly* increased by the use of thread synchronization. The fact that I&#8217;m only doing EndDraw on another thread means that I don&#8217;t have to worry about protecting my game data with locks and other synchronization techniques, since the GraphicsDevice doesn&#8217;t use any of my game data when performing the EndDraw operation.</p>
<p>So, to test this out, I overrode my Game class&#8217;s BeginDraw and EndDraw methods. This turns out to be all we have to do to change the way drawing is performed, because the XNA Framework developers were kind enough to make both of these methods virtual.</p>
<pre>        protected override bool BeginDraw () {
            _DrawCompleteEvent.WaitOne();
            _DrawCompleteEvent.Reset();
            return base.BeginDraw();
        }

        protected override void EndDraw () {
            _DrawRequiredEvent.Set();
        }</pre>
<p>Of course, at this point, the two events used here are never set, so this code won&#8217;t work. Thus, we add a background thread to perform our painting:</p>
<pre>        AutoResetEvent _DrawRequiredEvent = new AutoResetEvent(false);
        ManualResetEvent _DrawCompleteEvent = new ManualResetEvent(true);

        public Game () {
            ...

            _DrawThread = new Thread(DrawThreadFunc);
            _DrawThread.IsBackground = true;
            _DrawThread.Start();
        }

        protected void DrawThreadFunc () {
            while (true) {
                _DrawRequiredEvent.WaitOne();
                base.EndDraw();
                _DrawCompleteEvent.Set();
            }
        }</pre>
<p>Fairly simple thread programming here: We create a thread, and set IsBackground to true so that it will stop as soon as the main thread exits. The thread spends all of its time waiting for a &#8216;required draw&#8217; signal, and then performs an EndDraw call. Once the call is complete, it sets another signal to inform the Game class that the previous draw has finished and it&#8217;s safe to perform a BeginDraw call (this lets us make sure that we never use the GraphicsDevice on the main thread while the background thread is performing an EndDraw).</p>
<p>Once this is all done, I start up my game, and&#8230; the framerate isn&#8217;t any different. Huh? What&#8217;s more, my frame profiler indicates that Update is now taking <strong>ten times</strong> as long as it used to, while Draw isn&#8217;t any faster. Huh???</p>
<p>In situations like this, it&#8217;s always good to consult a profiler to see if you&#8217;re missing something important:</p>
<p><a href="http://www.luminance.org/wp-content/uploads/2009/07/profile_01.png"><img class="aligncenter size-full wp-image-527" title="profile_01" src="http://www.luminance.org/wp-content/uploads/2009/07/profile_01.png" alt="profile_01" width="550" height="255" /></a></p>
<p>So, we can see that the DrawThread is definitely doing its job &#8211; it calls EndDraw, then waits for a signal asking it to draw again. Both are taking about as much time as we&#8217;d expect. But why is Update taking so long&#8230;?</p>
<p style="text-align: center;"><a href="http://www.luminance.org/wp-content/uploads/2009/07/profile_02.png"><img class="aligncenter size-full wp-image-528" title="profile_02" src="http://www.luminance.org/wp-content/uploads/2009/07/profile_02.png" alt="profile_02" width="499" height="132" /></a></p>
<p style="text-align: left;">&#8230; oh. Oops.</p>
<p>So it turns out that I was using GraphicsDevice.Viewport.Width and GraphicsDevice.Viewport.Height in my camera code. Accessing the Viewport property caused the XNA framework to call into Direct3D to retrieve the viewport, which acquired the exact same lock being used by EndDraw, causing my main thread to stall until the draw completed. <strong>WHOOPS</strong>.</p>
<p>This is especially embarassing since the viewport size never changes anyway, so I could have just stored the width/height into constants. After doing just that and starting the game again, the profile looks more like you&#8217;d expect:</p>
<p><a href="http://www.luminance.org/wp-content/uploads/2009/07/profile_03.png"><img class="aligncenter size-full wp-image-529" title="profile_03" src="http://www.luminance.org/wp-content/uploads/2009/07/profile_03.png" alt="profile_03" width="562" height="254" /></a></p>
<p>What&#8217;s more, this is actually an improvement: With vertical sync <strong>enabled</strong>, this results in a significant reduction in the amount of time spent inside the BeginDraw/Draw/EndDraw functions on the main thread, which means there&#8217;s more time left to perform Updates. This means that I can maintain a solid, smooth 60fps easier on dual-core/hyperthreaded machines.</p>
<p>Even with vertical sync <strong>disabled</strong>, this is still an improvement, though not as significant &#8211; apparently other things are happening inside EndDraw (not a big surprise), so by shifting that work off onto a second thread, I&#8217;m still gaining some time to spend performing the next update. When I disable the built in framerate balancer, this brings my framerate from ~350fps up to ~380fps. Not bad for a couple dozen lines of code!</p>
<p>Of course, it&#8217;s worth pointing out that the XNA Framework documentation doesn&#8217;t make any promises here, so it&#8217;s possible that this technique is unsafe. When it comes to concurrency, it&#8217;s very easy to do the wrong thing and get away with it &#8211; as you might have noticed here, I was doing something utterly stupid and unsafe in my Update function, and I got away with it because the DirectX developers had the foresight to put a lock in the right place. If they hadn&#8217;t, my game might have corrupted state from accessing the GraphicsDevice on two threads, and crashed intermittently.</p>
<p>Regardless, this is a handy technique &#8211; once I&#8217;ve had the chance to do lots of testing on various PC configurations (and the XBox 360), I&#8217;ll probably be using it in my game when I ship.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.luminance.org/blog/gruedorf/2009/07/01/threaded-enddraw-in-xna/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Collision detection and motion</title>
		<link>http://www.luminance.org/blog/gruedorf/2008/11/29/collision-detection-and-motion</link>
		<comments>http://www.luminance.org/blog/gruedorf/2008/11/29/collision-detection-and-motion#comments</comments>
		<pubDate>Sat, 29 Nov 2008 15:02:39 +0000</pubDate>
		<dc:creator>Kael</dc:creator>
				<category><![CDATA[Gruedorf]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[collision]]></category>
		<category><![CDATA[csharp]]></category>
		<category><![CDATA[Fury²]]></category>
		<category><![CDATA[motion]]></category>
		<category><![CDATA[platformer]]></category>
		<category><![CDATA[polygon]]></category>
		<category><![CDATA[xna]]></category>

		<guid isPermaLink="false">http://www.luminance.org/?p=21</guid>
		<description><![CDATA[Initially I implemented collision detection and motion in this platformer prototype the same way I had done it previously in Fury², my game creation system project from a while back. Entities have a position and velocity, which are both pairs of floats (x, y). Every frame, I compute the new position of the entity &#8211; [...]]]></description>
			<content:encoded><![CDATA[<p>Initially I implemented collision detection and motion in this platformer prototype the same way I had done it previously in Fury², my game creation system project from a while back. Entities have a position and velocity, which are both pairs of floats (x, y). Every frame, I compute the new position of the entity &#8211; pos+vel &#8211; in a given axis (x or y), and then do a check to see if it&#8217;s obstructed. If it&#8217;s obstructed, I halve the velocity and try again, and I repeat that iteratively a few times until I give up. After doing that for both axes, I have a relatively good approximation of how far the entity can move in its desired direction.</p>
<p>It was good enough for me, and the performance wasn&#8217;t *terrible*, so I didn&#8217;t worry about it much. But I always had this nagging doubt in my mind &#8211; this solution is obviously a hack. Isn&#8217;t there a way to do this with pure math?</p>
<p>Well, I&#8217;m not very good at math, but it turns out there is a way to do it with pure math. So today I threw out all the motion and collision code I had written for the platformer and decided to try a pure math approach, and see if I could resolve collisions non-iteratively. Suprisingly enough, it wasn&#8217;t actually that hard.</p>
<p>Here&#8217;s a summary of how it works:</p>
<p>I already do my collision detection using the separating axis theorem (SAT). To check for collision between a pair of convex polygons, I compute a set of axes based on the polygons (a vector perpendicular to every edge of each polygon) and then for each axis in the set, I project both polygons onto that axis and see if they overlap. As soon as I find an axis in which the polygons are not overlapping, I know that they are not intersecting &#8211; no need to check all of them.</p>
<p>Pretty simple, and actually quite easy to code &#8211; Around 20 lines of C# for a relatively efficient implementation of the check itself, and another 20 lines to compute the list of axes without any duplicates, since there&#8217;s no point in checking the same axis twice.</p>
<p>With the algorithm described above, it&#8217;s actually quite simple to build motion on top of it. Once I&#8217;ve projected both polygons onto a given axis, and confirmed that they don&#8217;t intersect, I can do another projection &#8211; I can project the velocity of the moving polygon onto that same axis, and add that to the original projection of the moving polygon to get the projection of its new, desired location. At that point, I know whether the polygon will intersect on this axis as a result of moving, and not only that, I can compute the <strong>amount</strong> of intersection by determining how much the two intervals overlap. Once I have that value, I can use it to compute a vector that will separate the two polygons.</p>
<p>Once I iterate over all the axes and compute separating vectors, I can pick the smallest separating vector and add it to the original velocity of the polygon. At this point I can do some checks to see if the new velocity is acceptable &#8211; for example, did the separating vector cause the polygon to change directions entirely? In that case, it&#8217;s probably not acceptable, and we can just flat-out reject movement and say that the polygon cannot move in this direction at all. Likewise, if the separating vector is enormous, that means the polygon moved <strong>all the way</strong> through the obstruction to avoid collision, which we obviously don&#8217;t want either, so we can reject it.</p>
<p>The end result was essentially this:</p>
<ul>
<li>For every <strong>axis</strong>, project <strong>movingPolygon</strong> and <strong>stationaryPolygon</strong> onto that axis. This produces two intervals &#8211; <strong>movingInterval</strong> and <strong>stationaryInterval</strong>.</li>
<li>Check to see if <strong>movingInterval</strong> and <strong>stationaryInterval</strong> overlap. This tells us whether or not the polygons <strong>were already colliding</strong>.</li>
<li>Project the velocity of <strong>movingPolygon</strong> onto the <strong>axis</strong>, and add that projected value to <strong>movingInterval</strong>. This gives us the new interval of the moving polygon &#8211; <strong>newInterval</strong>.</li>
<li>Check to see if <strong>newInterval</strong> and <strong>stationaryInterval</strong> overlap. If they overlap, determine how much they overlap by &#8211; <strong>overlapAmount</strong>. At this point we know whether or not the two objects <strong>would have</strong> collided.</li>
<li>If the <strong>newInterval</strong> is overlapping, we can now compute a vector that will separate the two polygons, by multiplying the current <strong>axis</strong> by the amount of overlap (the axis is a unit vector, and the amount of overlap is a distance).</li>
<li>Add the separating vector to the original velocity of the polygon, to compute the new candidate velocity &#8211; <strong>newVector</strong>.</li>
<li>Check to see if <em>Magnitude</em>(<strong>newVector</strong>)<em></em> &lt;= <em>Magnitude</em>(<strong>movingPolygonVelocity</strong>). If not, reject the new vector.</li>
<li>Check to see if <em>Normalize</em>(<strong>newVector</strong>) <em>·dot·</em> <em>Normalize</em>(<strong>movingPolygonVelocity</strong>) &gt;= 0. If not, reject the new vector. (This ensures that we don&#8217;t push the object in the opposite direction to resolve the potential collision &#8211; in this case, the magnitude would have still passed the previous check)</li>
<li>If the new vector was not rejected, we know that the two objects <strong>will not be colliding</strong>.</li>
<li>Once you&#8217;ve iterated over all the axes, select the largest non-colliding vector (if any). That&#8217;s your <strong>resultVector</strong>.</li>
</ul>
<p>At the end of this algorithm, you have four outputs:</p>
<ul>
<li><strong>areColliding</strong> (right now, before applying the velocity)</li>
<li><strong>wouldHaveCollided</strong> (if we applied the original velocity)</li>
<li><strong>willCollide</strong> (if you apply the result velocity)</li>
<li><strong>resultVelocity</strong></li>
</ul>
<p>In the case where the collision could not be resolved, the <strong>resultVelocity</strong> will be 0. In the case where there was no collision, the <strong>resultVelocity</strong> will be the input velocity. In every other case, the <strong>resultVelocity</strong> is a vector that safely moves the polygon in the desired direction, without producing a collision.</p>
<p>One detail to note is that the quality of the result velocity depends on the axes that you check. If you only check axes generated from the shapes of the colliding objects, you can get strange (though valid) results &#8211; for example, two boxes will not produce any axes except X and Y to check, so if the object is moving at an angle, the algorithm will miss the ideal axis to compute the <strong>resultVelocity</strong> from. There are a few ways to solve this &#8211; you can pre-compute a set of &#8216;basic axes&#8217; to check in every case, or you can derive a set of axes from the velocity of the object. Either way, though, the algorithm seems to work quite well &#8211; it works as well as the old one did in the platformer, and passes all my unit tests.</p>
<p>It&#8217;s always nice to go from 100 lines of code to 10 lines of code. Unfortunately, I&#8217;m not done yet. My previous implementation supported walking up and down slopes in a natural manner, and it also supported moving platforms. The new implementation supports neither, so I have some more work to do. Hopefully I can solve both of those problems using pure math, too &#8211; I&#8217;m working on sloped surfaces right now, and it looks like I can make it work with pure math by improving on my existing algorithm.</p>
<p><strong>You can see the source code for my implementation <a href="http://code.google.com/p/fracture/source/browse/trunk/Squared/GameLib/Geometry.cs?r=199#130" target="_blank">here</a>.</strong> Note that there&#8217;s some commented out bits in there from my work on sloped surfaces. <img src='http://www.luminance.org/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.luminance.org/blog/gruedorf/2008/11/29/collision-detection-and-motion/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fury² Post-post-mortem: Lessons learned</title>
		<link>http://www.luminance.org/blog/code/1986/10/20/fury2-post-mortem</link>
		<comments>http://www.luminance.org/blog/code/1986/10/20/fury2-post-mortem#comments</comments>
		<pubDate>Mon, 20 Oct 1986 21:37:50 +0000</pubDate>
		<dc:creator>Kael</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[engine design]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[postmortem]]></category>
		<category><![CDATA[project management]]></category>
		<category><![CDATA[tl;dr]]></category>

		<guid isPermaLink="false">http://www.luminance.org/?p=206</guid>
		<description><![CDATA[Warning: This is an incomplete draft. I haven&#8217;t found time to edit this down and fix mistakes yet. Starting at the beginning of high school, through my few years of college, and into the first year of my professional career, I spent a significant portion of my free time building and maintaining a toolset and [...]]]></description>
			<content:encoded><![CDATA[<p>Warning: This is an incomplete draft. I haven&#8217;t found time to edit this down and fix mistakes yet.</p>
<p>Starting at the beginning of high school, through my few years of college, and into the first year of my professional career, I spent a significant portion of my free time building and maintaining a toolset and game engine called <a href="http://sf.net/projects/fury2/"><strong>Fury²</strong></a>. It was built as a way for me to quickly prototype games and ideas, to learn about game design and engine design, and most importantly, to let me build games that I didn&#8217;t think I could create using any of the tools that were already out there.<br />
It was a long and painful development project, and by the end, I realized that I had made numerous mistakes; despite that, I also gained many valuable lessons and learned things that I might not have learned any other way, and with the clearer perspective that hindsight brings, I consider it one of the things that made it possible for me to start a career doing things that I love without having to struggle with debt or worry about how I&#8217;m going to afford my next meal. For me, this project embodies the famous Nietzsche quote, &#8216;<em>What does not kill me, makes me stronger</em>&#8216;.</p>
<p>Learning how much sheer effort goes into the process of creating even a simple piece of software has changed me for the better in many ways, so I&#8217;m writing this article in hopes that I can share some of the lessons I&#8217;ve learned with others. Unfortunately, the benefit of hindsight also brings with it the fact that I don&#8217;t remember many of the things that happened during the 8 or so years I spent developing the project. I hope that despite this, you can benefit from what I&#8217;ve learned as much as I have.</p>
<p>Of course, I must preface the contents of this article with a warning: It&#8217;s written in fairly technical terminology, and does not have any particular narrative structure. I have tried to compile the most important issues and triumphs from the history of the project, and present them in a form that a programmer can understand. Regardless of whether you&#8217;re a programmer or not, I encourage you to respond via email or comments and let me know what parts of this you couldn&#8217;t understand, so that I can improve this article and make it worthy of your time.</p>
<p>- <em>Kevin Gadd</em></p>
<hr /><span style="padding-top: 5px; padding-bottom: 5px;"></p>
<h1><strong>The Fury² Game Development System: A post-post-post-mortem</strong></h1>
<p></span></p>
<p style="padding-top: 5px;">This article is inspired by the format of and spirit behind the many wonderful &#8216;Postmortems&#8217; published in Game Developer magazine. I will attempt to collect the most significant failures and successes that occurred during the life of my project, and try to give you a glimpse of what the project looked like and how it felt to use it.</p>
<p><span id="more-206"></span></p>
<p>To begin, the many failures and unexpected challenges I encountered:</p>
<h1>Mitigated Disasters</h1>
<h3><strong>Passing by Reference</strong> versus <strong>Passing by Value</strong>, and the evils of <strong>Variants</strong></h3>
<p style="padding-left: 35px; padding-top: 5px;">Originally all of the APIs exposed to script used the VB default of <strong>&#8216;ByRef</strong>&#8216; (pass-by-reference) with static types. This had the unfortunate side effect of disabling automatic type conversion when calling into those APIs from scripts. As a workaround, I changed the types of all those parameters to <strong>Variant</strong> and did the type coercion inside the APIs.</p>
<p style="padding-left: 35px; padding-top: 5px;">Bad idea. Performance took a hit, and passing the values by reference caused some extremely confusing bugs. In most cases, <strong>&#8216;ByVal&#8217; </strong>(pass-by-value) would have been the correct choice, but I didn&#8217;t do enough research to discover how to use ByVal correctly with the scripting interface. As a result I wasted a lot of time dealing with coercion-related bugs, and then had to sink another few weeks of effort into moving things over to the correct model (ByVal with explicit types, ByRef where appropriate) much later on, which broke some code. Even by the time I stopped maintaining Fury², some portions of the API still had to accept variants as arguments for backwards compatibility reasons.</p>
<p style="padding-left: 35px; padding-top: 5px;">Some of the worst bugs in my engine were a result of this decision as well &#8211; out of my top 10 worst bugs, one of them was caused by an object reference being passed ByRef (that&#8217;s right &#8211; a reference to a reference) down a stack of function calls, about 12 levels deep. All the way down the stack, a function assigned null to an object reference before returning &#8211; a reference that had been passed in ByRef. The end result was that the null travelled all the way up the stack and obliterated the contents of a member variable elsewhere, causing multiple data structures to get out of sync with each other. This was worsened by the fact that the variable in question happened to be part of a linked list that was shared with C++ &#8211; more on that later&#8230;</p>
<h3>Lacking understanding of <strong>COM</strong> (Component Object Model)</h3>
<p style="padding-left: 35px; padding-top: 5px;">As a result of VB6 being built on top of COM, I was somewhat familiar with its feature set and how to use it at the beginning of the project. Unfortunately, I lacked deep understanding of a number of important details that turned out to be critical to getting my engine to perform well and run reliably. The main problems I encountered were:</p>
<ul style="padding-left: 30px;">
<li><strong>Circular references</strong> &#8211; while I had a vague notion of what a circular reference was and how it could cause resource leaks, it took a while before I finally realized that COM provided no built-in mechanisms for freeing object cycles. This meant that somewhat far into the life of my project, I started noticing that I was leaking huge amounts of memory on transitions between different maps, when I shouldn&#8217;t have been leaking anything at all. The ensuing cycle-hunt (using manual inspection of reference counts, hand-coded weak references, and all sorts of things that are extremely painful to do in VB6) took a lot of time, and while it yielded results, I still never got to the point where my application was cycle-free, and the introduction of weak references late in development created numerous elusive crash bugs.</li>
<li><strong>Creation/destruction overhead</strong> &#8211; Due to the lack of good support for structs in the scripting framework I was using, basically every type in my engine&#8217;s APIs was a class, which meant it incurred COM reference-counting overhead. This ended up being extremely painful for plain-old-data types like rectangles, which were created and destroyed extremely often and stored in many places. Even after some heavy optimization (reusing rectangles and similar objects whenever possible, and implementing object pooling where possible) this was still a significant bottleneck that could have been avoided with a better design.</li>
<li><strong>Type library registration and versioning</strong> &#8211; I originally believed that I could deploy all my components using what VB6 called &#8216;binary compatibility&#8217;, where I could deploy a new version of a given type library that could be dropped in to replace the old one without breaking any existing binaries. This worked for a few months, but eventually I realized that it was impossible to maintain binary compatibility given VB&#8217;s restrictions and the rapid pace at which I was making changes to my APIs. Once binary compatibility went out the window, distribution and installation became a serious issue &#8211; having to register over a dozen type libraries for a given version of the engine was extremely painful, creating significant performance issues and making it impossible to run games without being an administrator. Later, I even ran into versioning conflicts with a couple Microsoft type libraries where the latest version of a library was not backwards compatible with the previous version, but the previous version had a crippling bug &#8211; which meant I couldn&#8217;t run on a machine with the old version, but I couldn&#8217;t forcibly upgrade it without breaking other applications.</li>
<li><strong>Apartment models and RPC</strong> &#8211; VB6 does a fairly terrible job of abstracting away the many nuances of COM. Other than type library versioning, mentioned above, the worst examples in this area are probably apartment models and RPC &#8211; both options are exposed to users of VB6 via radio buttons in the project properties window; unfortunately, the documentation almost completely glosses over the significance of these options, making it easy to select the wrong one and not realize your mistake until much later. I spent weeks developing my tools pipeline using COM RPC to communicate with a running instance of the game engine, resulting in some extremely confusing bugs and awful performance characteristics. It was only once I realized what was going on behind the scenes, due to the awful performance (why is this so slow? wait, the engine is running in *another process* and COM is marshalling all my data between processes&#8230; uh oh) that I understood the importance of those settings and learned to leave them set to the defaults. I had some utterly mindrending bugs where I was allocating GDI bitmaps or large arrays of data in an Engine class for a map layer or an entity, and passing the class instance across the RPC boundary to the editor, and then scratching my head in confusion when BitBlt or CopyMemory failed to do what they should have done, due to the fact that I had just marshalled pointers and handles across process boundaries in an unsupported way, without even realizing it.</li>
<li><strong>Quality issues</strong> &#8211; unfortunately, many of the implementations of COM that I had the misfortune of dealing with were subpar. Some were downright broken. I discovered dozens of bugs in various COM libraries and APIs, some of them ones provided by Microsoft themselves. In most cases my only choices were to hack around the bugs or reimplement the entire component myself, and I ended up choosing the latter. While most of the implementations in Windows itself and the VB6 runtime were fairly stable, some had extremely bad performance characteristics that necessitated writing my own implementations &#8211; and reimplementing COM library functions is *not* a walk in the park.<br />
One positive note in this section, though, is that I happened to stumble across a bug in PyWin32&#8242;s support for COM exceptions, and the maintainer was very quick to merge my fix into the trunk. This was one of my first real introductions to the value of open source.</li>
</ul>
<h3>The wrong model for rendering</h3>
<p style="padding-left: 35px; padding-top: 5px;">The object model I chose for my graphics API had some strengths, but it also had one primary weakness that caused most of the graphics-related stability and performance problems the engine had later on: I had no distinction between mutable and immutable images. During the early stages of the project, this was liberating, because it meant that I could easily whip up prototypes with complex visual effects and that it was straightforward to create reusable pieces of rendering code that could be applied to anything.</p>
<p style="padding-left: 35px; padding-top: 5px;">The downside, which didn&#8217;t become apparent until much, much later, was that having an object model where everything is mutable makes it extremely hard to accelerate graphics rendering using hardware, because neither OpenGL, DirectDraw or Direct3D offer any way to get high-performance mutable surfaces that can still be used as textures. I ended up sinking at least a month of coding time into getting acceptable framerates out of OpenGL acceleration, and even after that, some of my games and prototypes simply would not run well on hardware due to heavy use of mutable surfaces.</p>
<p style="padding-left: 35px; padding-top: 5px;">If I had taken a more conservative approach I would have had a much easier time adapting my code to exploit hardware acceleration. In many cases the mutable nature of images wasn&#8217;t useful at all, and I paid a significant price for providing it. Hardware textures had to have software backing stores at all times, and I had to jump through significant hoops to ensure that the two were kept in sync and flagged as &#8216;dirty&#8217; after rendering operations. Copying texture data back and forth between CPU and GPU was an enormous performance killer, especially on older hardware &#8211; hardware that would have otherwise been able to accelerate my engine just fine.</p>
<p style="padding-left: 35px; padding-top: 5px;">I also failed to abstract out my rendering operations in a sane manner until it was too late to do anything about it; the result was that hardware acceleration depended on a convoluted set of per-function &#8216;overrides&#8217; for the entire graphics API, all of which had to be hand-written for each rendering API and tuned to behave similarly to the built-in software implementations. All of the typical issues people are used to from working with virtual functions and inheritance applied here, except it was significantly worse due to the fact that I was implementing it from scratch without a concrete model or understanding of all the implications. Even after significant optimization and refactoring, the overhead this approach created was responsible for making my OpenGL accelerated renderer perform 2-5x worse than it would have otherwise, sometimes even worse than the native software implementation.</p>
<h3>Active Scripting</h3>
<p style="padding-left: 35px; padding-top: 5px;">Microsoft&#8217;s Active Scripting library made it really easy to get up and running, and provided a fairly solid feature set, so it was a good choice for a scripting platform initially. Unfortunately, as the engine matured, Active Scripting started becoming a bad choice. It lacked support for various portions of COM that I hadn&#8217;t realized I would need, and had some severe performance problems that were extremely hard to compensate for. It also had some sneaky bugs and reliability issues that took a long time to track down once discovered.</p>
<p style="padding-left: 35px; padding-top: 5px;">I also initially believed, based on some testing and documentation, that Active Scripting gave me a way to transition to a better language when the need arose &#8211; it was possible to use it to run Ruby, JavaScript or Python scripts instead of VBScript, which gave me a good path for transitioning to another scripting framework in the future if I so desired. In practice, this didn&#8217;t turn out to be true &#8211; there were subtle, crippling issues in the Active Scripting implementations of all three languages, leaving VBScript as the only feasible option. In the end, this miscalculation cost me weeks of time writing workarounds for Active Scripting bugs and trying to get other languages to work as well as VBScript did, and the cost of ending up stuck with VBScript is hard to estimate.</p>
<p style="padding-left: 35px; padding-top: 5px;">The lack of expressiveness that initially made VBScript &#8216;accessible&#8217; to new users and quick to prototype with also ended up being a hindrance. VBScript provided no usable implementations of concepts like delegates, interfaces, inheritance, exception handling, or strongly typed arrays &#8211; all things that don&#8217;t seem particularly important early on in a project, but become increasingly important as your architecture grows more complex and your performance requirements are more demanding. In some cases, the language provided a functioning implementation of a feature, but it was implemented in such a way that it was impossible to use it with native APIs, making it useless in the context of a game engine.</p>
<p style="padding-left: 35px; padding-top: 5px;">The worst example by far was delegates; at first, it seemed that the performance of invoking a script function by name was acceptable, so I built my event-handling model around having a list of event handler names to invoke at runtime. Later I began to realize that every invocation was resulting in expensive name lookups and type conversions, which resulted in severe performance hits when you were having scripts respond to thousands of events per frame. In the end I had to build a fairly complex code generation system to construct &#8216;trampoline&#8217; functions any time I needed to have scripts handle events, which resulted in a small but steady leakage of memory to generated scripts (which couldn&#8217;t be garbage collected or reclaimed).</p>
<p style="padding-left: 35px; padding-top: 5px;">Larger games also suffered from inefficiencies in VBScript&#8217;s runtime, with the cost of individual variable lookups increasing based on the number of variables defined in the entire game, due to a lack of support for usable namespacing or modules.</p>
<h3>Wide feature set and endless &#8216;scope creep&#8217;</h3>
<p style="padding-left: 35px; padding-top: 5px;">From the beginning, I had a habit of allowing the scope of the engine&#8217;s feature set to increase rather than stay fixed, and it took me a very long time to recognize the problems that this caused. By the end of its development, Fury² had nearly 200 unique classes spanning over 100000 lines of VB6 code, with thousands of unique methods and properties. Many of the classes interacted in ways that were unclear or unpredictable, and some of them had decayed into various forms of brokenness due to neglect. Near the end of the project I regularly discovered that I had just reimplemented a function or feature that already existed elsewhere in the codebase, which was a clear sign that things had gotten out of hand.</p>
<p style="padding-left: 35px; padding-top: 5px;">The most representative example was the &#8216;Engine&#8217; class, which would have probably been more appropriately named &#8216;KitchenSink&#8217;. Due to Active Scripting limitations, the Engine class held any and all variables or functions that needed to be accessible at global scope, which resulted in a steady growth of new public variables, properties, and functions, many of which were interdependent or affected the behavior of classes elsewhere in the codebase. Keeping all of the responsibilities and features of the Engine class in my head soon became impossible, and it was far more difficult than I had anticipated to factor out individual responsibilities into unique classes without breaking existing games or degrading performance.</p>
<p style="padding-left: 35px; padding-top: 5px;">Even after aggressive refactoring and elimination of dead code, by the time I put the project to bed, the Fury2Engine class was over 6000 lines of code, containing over a hundred member variables and hundreds of member functions. Almost every class in the framework held a reference to an Engine instance for one reason or another, making it difficult to destroy dead Engine instances to reclaim memory, and leading to subtle bugs where multiple instances were alive at once. Basically any change to a part of Engine was likely to break other parts of the codebase, unless the change involved adding completely new functions and variables (a downward spiral if I&#8217;ve ever seen one.)</p>
<p style="padding-left: 35px; padding-top: 5px;">While the wide feature set meant that it was often possible to build a functioning game prototype with a high level of polish in a few hours, it also meant that it was impossible to build such a prototype without finding at least one bug in the engine (usually more like two or three), and the resulting interruption to my flow almost completely outweighed the benefits I got from rapid prototyping. In many cases I used my engine to build a game for a competition with a short time limit &#8211; as short as 48 or 72 hours to build a game from scratch &#8211; and had a large chunk of content and code complete, only to find a showstopper bug hours before the deadline that ended up taking days to fix. The reasons for this weren&#8217;t immediately clear to me, but over time it became obvious that it was due to the breadth of the codebase.</p>
<h3>Large footprint</h3>
<p style="padding-left: 35px; padding-top: 5px;">As a result of using COM and VB6, the size of my engine&#8217;s binaries alone quickly grew into the megabytes. This was pretty severe &#8211; it meant that merely downloading my engine on a typical connection at the time would take as long as an hour, without even including a game. I went to great lengths to reduce the size of my binaries, by trimming out dependencies, applying code compressors like UPX, and attempting to eliminate as much code as possible from the largest sections of my codebase. In the end, though, the real problem was that the combined overhead of COM and VB6 meant that even simple code resulted in a large binary, and when you applied that overhead to my already large codebase, you ended up with something that was almost impossible to trim down to a reasonable size. For this reason I ended up having to apply UPX to all of my binaries to be able to get them to a size that was remotely small enough for a typical end-user to download, even after halving the size of some of them and eliminating entirely unneeded libraries. Even by the end of the project, the engine and development tools combined totaled around 12 megabytes of executable code &#8211; somewhat large by modern standards, and unreasonably huge by the standards of someone using a 56k modem.</p>
<p style="padding-left: 35px; padding-top: 5px;">The footprint also had less obvious consequences &#8211; the size of the binaries meant that more and more often, I ran into strange bugs in the compiler and debugger, and overall build times grew to the point that going from the IDE to a running version of my engine could take up to a minute. This severely impacted my ability to iterate and track down problems.</p>
<p style="padding-left: 35px; padding-top: 5px;">The worst side effect of this by far, though, was the impact it had on actually using the engine to make games. While the size didn&#8217;t really impact my ability to build a game, it meant that I had to somehow get dozens of megabytes of data onto a user&#8217;s machine before they could play my game. Attempts at reducing the download size typically resulted in compatibility issues, as I discovered that &#8216;optional&#8217; libraries weren&#8217;t so optional because particular OS versions didn&#8217;t include them, or included outdated versions. Troubleshooting these issues was next to impossible since getting a user to download a dozen megabyte installer twice is exponentially more difficult than getting them to download it in the first place &#8211; many of my users gave up and simply did not have time to help me track down their issues, so those issues went unsolved until I could reproduce them on a personal machine &#8211; if I ever solved them at all.</p>
<h3>Instability</h3>
<p style="padding-left: 35px; padding-top: 5px;">One of the most significant disadvantages to using VB6 was the near-complete lack of error handling mechanisms. The only viable options when building a large VB6 application were to hand-write complex error handlers at the bottom of every function, or &#8216;delegate&#8217; errors up the stack using On Error Resume Next. Unfortunately, both approaches are actually worse in practice than they sound on paper &#8211; hand-written error handlers could not easily delegate to common error handler implementations due to language limitations, which meant that they had to be manually copy-pasted throughout the codebase, or machine-generated by automated tools. Neither option was sustainable, which meant that I ended up using On Error Resume Next to effectively ignore errors in any part of the codebase where they weren&#8217;t expected.</p>
<p style="padding-left: 35px; padding-top: 5px;">Even with the most diligent approach to error-checking, ignoring errors by default is not a sustainable way to build an application, and when you&#8217;re trying to build a reusable library or game engine, it&#8217;s outright disastrous. Up until the very last day I stopped working on it, Fury² suffered from crippling, unpredictable stability issues where a minor failure somewhere in the application could result in a catastrophic failure seconds later in an unrelated piece of code, with few clues as to the actual cause of the problem. In many ways, this was as bad as the issues that C/C++ programmers can run into through misuse of pointers and unchecked operations, but I managed to end up with this level of instability despite using a language that offered fairly safe string and array primitives along with null reference checking.</p>
<p style="padding-left: 35px; padding-top: 5px;">With more foresight, the sheer impossibility of handling errors properly in this environment would have resulted in the project coming to a halt and never resuming, or being restarted in another language. Unfortunately, I opted to continue down the path I was on, methodically hunting down bugs one by one, adding thousands of unique error handlers and &#8216;armoring&#8217; my code against unexpected conditions by checking for nulls anywhere I had an object reference and validating the input to any given function. While the resulting approach of &#8216;defensive programming&#8217; did have benefits, it also resulted in significantly slower code and didn&#8217;t help improve the quality of the rest of the codebase &#8211; 1000 input checks don&#8217;t do you any good if you forget one in an important function.</p>
<p style="padding-left: 35px; padding-top: 5px;">This approach to error-checking was worsened by the necessity of integrating with native code written in C/C++ &#8211; while a null reference could cause Visual Basic code to fail to work, the impact on a snippet of C/C++ was far worse: Due to the fact that my native code was being called from Visual Basic, I couldn&#8217;t rely on C++ exceptions and had to resort to return codes, and all of the problems that entailed. Furthermore, in cases where my error handling was faulty or nonexistent, a null object reference in Visual Basic would often transform into catastrophic failures in C++ &#8211; overwriting random parts of memory with garbage, smashing the stack, or simply throwing access violations. All of these failures inevitably brought down the application, some of them even resulting in data loss from unpredictable crashes of long-running editing tool sessions.</p>
<h3>Reinventing the wheel</h3>
<p style="padding-left: 35px; padding-top: 5px;">As mentioned multiple times previously, I ended up having to reimplement many components that I had taken for granted. This included a large portion of the VB6 UI stack, and significant portions of the COM API and the VB6 runtime. This effort cost me a significant amount of time &#8211; many months of engineering work in total &#8211; and resulted in an experience that felt inconsistent and often lacked key features that I could have gotten for free if I had been able to use the stock implementations. Trying to reimplement complex UI primitives like cascading dropdown menus was an exercise in torment, where every bug fixed revealed two more bugs waiting to be fixed, and the sheer fatigue that resulted was one of the main reasons I ended up abandoning the project.</p>
<p style="padding-left: 35px; padding-top: 5px;">Among some the many things I had to reimplement from scratch to solve issues, here are a few of the major ones:</p>
<ul style="padding-left: 30px;">
<li style="padding-left: 30px;"> <strong>Listbox, Toolbar, Menu, Tab Strip, Scrollbar and Button controls</strong> &#8211; because the stock VB6 implementations had severe performance issues, crash bugs, and missing features. Most of these issues were the result of bugs in the VB6 wrapper code that talked to the underlying native APIs, so in some cases I was able to use the native APIs directly &#8211; the longest-lived example of this was the VB6 scrollbar control, which ended up being replaced by a very complex wrapper for the native Win32 scrollbar. In other cases the native APIs were simply too difficult to use, so I had to reimplement them from scratch &#8211; I invested a significant amount of effort into building a good toolbar component, and ultimately it was still not as good as its equivalent in modern toolsets like Windows Forms or SWT.</li>
<li style="padding-left: 30px;"> <strong>COM type library registration, loading, and unregistration </strong>- Yes, you read that correctly. I reimplemented a significant portion of COM and the related portions of the VB6 runtime to work around significant limitations and bugs in the stock implementations. This meant that I had to learn far more about the inner workings of COM and the Windows Registry than I ever wanted to know, and it meant that I had to resort to hooking dozens of native Win32 APIs in order to fool native COM components into thinking that they were running in a normal COM environment. The end result met most of my needs &#8211; I was able to load and unload COM libraries on demand without running as an administrator, and the performance of my COM implementation was generally superior to Microsoft&#8217;s &#8211; but it caused hundreds of issues with COM components that depended on quirky undocumented traits of the Win32 API, or components that were simply written incorrectly. All said, I spent at least a month coding and troubleshooting something that would have been almost completely free if I had been using almost any other comparable toolset.</li>
<li style="padding-left: 30px;"> <strong>Rendering </strong>- I ended up implementing my entire graphics stack from scratch, only using third party libraries in cases where I could absolutely rely on them or where it wasn&#8217;t feasible to implement things myself &#8211; I used GDI or DirectX or OpenGL to render my framebuffer to the screen, and an open source library named Corona to load images &#8211; but everything else, I basically wrote from scratch. I spent an extremely large amount of time discovering the many nuances involved in rendering, and struggling with the Visual C++ compiler trying to get it to turn my C into performant assembly so that my games would run at a solid framerate. Despite the benefits I got from having complete control over my graphics pipeline, in the end I would have been better off learning an API like OpenGL extremely well, and taking advantage of pixel shaders once they were available to get the precise control over rendering that I wanted. While I thought that software rendering would protect me from driver issues and hardware bugs, in practice, it actually didn&#8217;t, and I lost many weeks tracking down obscene bugs in GDI and DirectDraw drivers that made simple things like drawing a framebuffer to the screen produce incorrect results or fail to work completely, often without any error messages or debugging information. A single bug in the DirectDraw drivers for a common Intel chipset cost me over a week of testing and debugging due to the fact that I had no access to a machine with the problem, despite it preventing hundreds of people from being able to run my game.</li>
<li style="padding-left: 30px;"> <strong>Text</strong> &#8211; Despite the fact that VB6 used UCS-2 as its internal string representation, I ended up having to write my own UTF-8 decoder and decoder, along with many other assorted utility functions and my own text rendering/measuring APIs to actually get functioning unicode support so that localized text could be put into a game. This was a huge, mostly unanticipated cost, because VB6 appeared to have top-notch Unicode support on the surface but was actually barely serviceable.</li>
</ul>
<h3>Incomplete and incorrect knowledge</h3>
<p style="padding-left: 35px; padding-top: 5px; padding-bottom: 15px;">I learned a lot of things during the course of the project, but unfortunately, much of the knowledge I gained was incomplete, or subtly incorrect. This is a common problem when self-teaching, and in the case of a project like this, it&#8217;s easy to form bad mental habits that are hard to break out of later. I don&#8217;t think it outweighs the benefits of what I learned, but it definitely poses a continuing problem, as I often have to relearn concepts and techniques that I already believed I understood. If you&#8217;re a particularly opinionated or strong-willed person, this can be especially dangerous as you may never realize how flawed your understanding is, despite the fact that it will cripple your professional career and even your personal life.</p>
<hr />
<p style="padding-top: 10px; padding-bottom: 5px;">Now that you have an idea of the challenges I faced and the mistakes I made, it&#8217;s time to try and share some of my triumphs and hard-won lessons:</p>
<h1>Silver Linings</h1>
<h3>Rapid UI development</h3>
<p style="padding-left: 35px; padding-top: 5px;">Despite all its flaws, VB6 was absolutely the right choice for building the UI for my editing tools. It provided a near-perfect mix of ease of use, simplicity, and ease of integration that let me build highly usable UIs without having to sink time into authoring message handlers, digging through API documentation, or struggling with resource management. I could open the visual basic editor, create a new form, place some simple UI components on it (many of which I had written to abstract out common UI elements, like lists of generic game objects or property grids), and rig up functioning event handlers to them in a matter of minutes. In most cases, the majority of the UI code worked right as soon as I hit save, and the majority of the bugs that did make it into my UI were simple and possible to avoid with enough diligence.</p>
<p style="padding-left: 35px; padding-top: 5px;">VB6 also scaled up suprisingly well as my UI grew more complex. Despite a few crippling issues, for the most part, it performed admirably &#8211; I had hundreds of unique dialogs and tens of thousands of unique event handlers, and most of them did not require any maintenance once they were fully implemented. I was able to reuse an extremely large amount of code between individual dialogs, allowing me to build extremely usable and powerful UI primitives that made it even easier to build more UI in the future. Many pieces of UI that would have otherwise taken weeks of effort to implement from scratch were finished in a matter of hours, leaving me time to spend on user experience, reliability, and performance. To this day, the editing tools that resulted from this have extremely good performance, a smooth workflow, and a robust feature set &#8211; things that weren&#8217;t available in any of the comparable tools at the time.</p>
<h3>Ad-hoc, iterative design</h3>
<p style="padding-left: 35px; padding-top: 5px;">While my initial approach was to design large sections of the engine up-front and then implement them, I quickly shifted to an iterative approach where I designed simple solutions to problems as they arose, and built on them as I continued. I prototyped many of my features in minutes, sometimes even using VBScript to implement them without worrying about static typing or having to compile code. When those prototypes were meeting my needs, it was easy to move the scripts into my codebase and add the necessary static types to compile them to native code, which made for an excellent feedback loop and allowed me to kill many bad ideas without having to spend days implementing them first. Being willing to throw out bad ideas and bad code was much easier because the code took less time to write, and I hadn&#8217;t gotten attached to it. Despite the numerous stability and performance issues I encountered, by the end of the project I had an extremely versatile set of prototyping tools, with complex primitives like functors and mixins that wouldn&#8217;t have otherwise been available to me.</p>
<p style="padding-left: 35px; padding-top: 5px;">In almost every case where I applied this approach intelligently, the end results were great, even without the benefit of a rigid development process, unit testing, or the kind of prototyping tools I now have access to in environments like Python and .NET. Being able to prototype rapidly allowed me to maintain an extremely high level of morale and build a large amount of usable code in a short amount of time, which was essential for maintaining my interest in the project and being able to carry it along to the point that I did. If I had been prototyping in an environment with a longer, more painful edit/compile/test cycle, like C++, I probably would have abandoned the project after months, instead of the nearly 7 years I maintained it for.</p>
<h3>Software rendering and the lowest common denominator</h3>
<p style="padding-left: 35px; padding-top: 5px;">Early on, my decision to use software rendering meant that games and prototypes I built would run the same on any machine (provided they ran at all) without any need for drivers, libraries, or special hardware. I was able to test and demonstrate prototypes on absurdly low-end machines, like a 486 running Windows 95, and then go back and make changes to them using my Windows 2000 or Windows XP machines at home, without seeing any difference in rendering behavior or gameplay. The performance tended to scale badly on the low end, but the games always ran and were often playable on the worst machines if I was careful enough about how I built them, which was something I couldn&#8217;t get at the time using OpenGL or DirectX. As time went on, this benefit grew less and less important, but in the early stages of the project it was essential in allowing me to get important feedback on usability, gameplay, and the overall experience from people who didn&#8217;t have powerful computers or have the necessary hardware to run most PC games, and it minimized the time I spent having to track down bizarre issues with video drivers and video hardware.</p>
<p style="padding-left: 35px; padding-top: 5px;">Software rendering also gave me the ability to produce visuals that were out of the reach of most indie developers at the time, with the ability to combine various blending modes, filters, masks, and transformations to create scenes approaching the level of quality that I could get with layers and filters in photoshop. The effort involved in getting these visuals to run at a decent framerate is hard to overstate, but the end result was also extremely satisfying &#8211; to this date, a few of the rendering techniques I experimented with and used in prototypes have only been used in a scant few games, due the near-impossibility of implementing them on pre-DX9 hardware, and how difficult it is to implement them even on modern hardware.</p>
<p style="padding-left: 35px; padding-top: 5px;">The process of learning how to implement the many graphics primitives and techniques that I had taken for granted was an extremely valuable one as well, and helped shore up the many academic weaknesses that had resulted from my lack of formal math education. Becoming intimately familiar with image processing and the mathematical models behind lighting and other common graphics effects gave me a strong appreciation for the value of math that I would not have had otherwise, and made it easier for me to begin learning more complex techniques and algorithms to apply to hardware rendering and 3D.</p>
<h3>The desire to innovate</h3>
<p style="padding-left: 35px; padding-top: 5px;">I regularly spent weeks or even months in pursuit of an implementation for a wild idea or concept that I had, digging through relevant articles and books, experimenting with formulas, and simply fiddling with things to try and come up with something new or entertaining. As a result, I ended up wandering into areas of computer science, graphics, and other areas like physics and artificial intelligence that I would have never been exposed to otherwise. I literally spent an entire summer attempting to form an understanding of how light and color worked, building a complex lighting model that could run in realtime and produce realistic, smooth-looking colored lighting for 2D scenes. By the end of the summer I had rewritten individual algorithms hundreds of times, and created and abandoned dozens of different lighting models. The process was difficult, but it was also one of the most satisfying things I&#8217;ve ever done.</p>
<p style="padding-left: 35px; padding-top: 5px;">Without the framework I had in place for rapid prototyping, and the willingness to investigate dead-ends in the search for fun new things, I would have missed out on a lot of valuable knowledge and experience. Once I was done, the resulting lighting model ended up being the springboard I needed to build many of the prototypes and game projects I&#8217;m most proud of, and without having spent all of that time in pursuit of something interesting, I wouldn&#8217;t have been able to build those prototypes. Even today, working in a medium-sized engineering team on a somewhat &#8216;normal&#8217; application, the thirst for knowledge and willingness to keep trying to solve a problem that I gained from these efforts are extremely valuable.</p>
<p style="padding-left: 35px; padding-top: 5px;">The downside, of course, is that I didn&#8217;t have time to watch any of those TV shows people were talking about. Is the cast of LOST still on that island?</p>
<h3>Language interoperation</h3>
<p style="padding-left: 35px; padding-top: 5px;">The need to combine tools and libraries written in multiple languages required that I form a deep understanding of the issues involved in getting multiple programming languages and environments to interact. As a result, I ended up digging into various parts of my toolchain and into the inner workings of various language environments. By the end of it, I had acquired a working knowledge of assembly, a fairly in-depth understanding of COM, and a grasp of how complex tools I had previously taken for granted truly were. Debugging issues with stack corruption and library load failures resulted in learning how the Win32 call stack is laid out, how PE executables are organized, and how the OS actually loads libraries and executables &#8211; things I otherwise might not have ever had to know that have ended up being extremely valuable in my professional career.</p>
<p style="padding-left: 35px; padding-top: 5px;">In no small part due to this project, in the span of a decade I went from not knowing anything about computer programming, to being able to write and debug software in dozens of different languages and environments. Being exposed to so many different mindsets and approaches helped counteract the many bad habits that I would have otherwise formed while working on my projects, and made it easier for me to adapt to the often strange and rigid processes I&#8217;ve encountered working on video games and commodity software. Being able to recognize similarities to existing tools and languages is extremely valuable when trying to learn a new skill or tool for a job, and has helped me develop my career without the benefit of a college degree or a significant academic education.</p>
<h3>Collaboration and documentation</h3>
<p style="padding-left: 35px; padding-top: 5px;">As my engine and toolset grew larger and more people became interested in trying them out, I quickly learned the value of collaboration with both programmers and non-programmers, and the importance of good documentation. Maintaining such a large project for such a large span of time, and making it possible for the uninitiated to learn how to use it and build things with it, was quite possibly the largest challenge I faced during the project. As a result, I developed some extremely valuable habits and skills, learning how to document APIs, reproduce bugs, provide workarounds, and track changes. I got better and better at all of these things as time went on, and as my skills improved, the results improved as well.</p>
<p style="padding-left: 35px; padding-top: 5px;">Near the end of the project, multiple people had successfully built playable game demos and prototypes using the engine, despite the subpar documentation, lack of stability, and other numerous problems. The experience of providing them with support when they encountered problems, and helping then understand how to use my tools, helped open my mind to the challenges involved in designing truly useful tools, and the value of open and honest communication with both customers and coworkers. Without them, I would not have been able to accomplish nearly as much as I did, and my personal projects and career would have suffered for it.</p>
<p style="padding-left: 35px; padding-top: 5px;">In retrospect, the people who spent their time trying to decipher my often-cryptic documentation and spent time finding bugs and workarounds were as important to the project as I was, and it was a blessing to have their help. The downside is that none of them were able to complete a game using my tools, but even that taught me a valuable lesson: My personal standards of quality aren&#8217;t enough to produce a quality product &#8211; I need to understand my customers&#8217; needs and listen to *them*, instead of focusing purely on my vision of how things should be. The point of building tools is to improve the quality of others&#8217; lives, and enable them to do things they couldn&#8217;t have done otherwise; if they succeed, you succeed with them, and if they fail, the failure is yours as well. Out of all the lessons I learned, this may be the one I treasure the most.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.luminance.org/blog/code/1986/10/20/fury2-post-mortem/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

