<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5677255309189696783</id><updated>2011-09-30T09:36:33.947-05:00</updated><category term='learning to program'/><category term='DTE'/><category term='init_seg'/><category term='simple english'/><category term='Games'/><category term='Addin'/><category term='C'/><category term='programming'/><category term='VS2010'/><category term='C++ Initialization order'/><category term='Arcane'/><category term='Instant Messenger'/><category term='Low Level'/><category term='Security'/><category term='Developement'/><category term='old school'/><category term='algorithmic thinking'/><category term='Pre Main'/><category term='assembly'/><category term='EEAddin'/><category term='IM'/><title type='text'>Meandering thoughts of an Addicted Games Programmer</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>16</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-7442216134183348951</id><published>2011-07-22T11:14:00.001-05:00</published><updated>2011-07-22T11:18:59.326-05:00</updated><title type='text'>What is an "Engineer Architect"</title><content type='html'>A question that i get asked rather a lot is "What is an Engineer Architect"&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;b&gt;en·gi·neer&lt;/b&gt;&lt;br /&gt;noun /ˌenjəˈni(ə)r/ &lt;br /&gt;A person who designs, builds, or maintains engines, machines, or public works&lt;br /&gt;&lt;b&gt;&lt;br /&gt;ar·chi·tect&lt;/b&gt;&lt;br /&gt;noun /ˈärkiˌtekt/ &lt;br /&gt;((computer science) the structure and organization of a computer's hardware or system software) "the architecture of a computer's system software"&lt;/blockquote&gt;&lt;br /&gt;This basically translates to the same thing all engineers do: &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Analyze the problem&lt;/li&gt;&lt;li&gt;Formulate a possible set of solutions &lt;/li&gt;&lt;li&gt;Analyze the solutions&lt;/li&gt;&lt;li&gt;Decide what to implement &lt;/li&gt;&lt;li&gt;Implement &lt;/li&gt;&lt;li&gt;Test/bug fix&lt;/li&gt;&lt;li&gt;Profile/sanitize&lt;/li&gt;&lt;li&gt;Repeat until satisfied &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;however with one important difference. My role involves the entire program, how its parts interact and how they are designed, what their dependencies are and how they affect the final output and the performance of that output. Combine this with data parallel infrastructure, task parallel objects, multiple platforms, myriad hardware limitations and a large programming team ... under many circumstances one might imagine something akin to &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-5Z2NdBq6VRA/TWX1VXrFszI/AAAAAAAABmQ/bbR-kD-TQow/s400/spaghetti-head.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/-5Z2NdBq6VRA/TWX1VXrFszI/AAAAAAAABmQ/bbR-kD-TQow/s400/spaghetti-head.jpg" width="297" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;and you often wouldn't be too far from the truth on a daily basis. Long term however we (the team) have a plan and a set of goals. Over time we re-assess based on those we hit and those we don't, new requirements and ultimately how the game is progressing and where it needs to go. The role I play in this is simply to ensure that under the stress and strain of day to day development, we're still aiming in the right direction as a whole. That decisions take into account as much of the big picture as possible and weigh that against the immediate requirements of the current goal. There are several people in similar roles at Bungie and our interactions provide a simple but effective method of applying "Checks &amp; Balances" to the progress we make; we each bring our own flavor to the table.&lt;br /&gt;&lt;br /&gt;Day to day this involves tasks such as&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Advising/Teaching on how to handle concurrency&lt;/li&gt;&lt;li&gt;Long term interface design&lt;/li&gt;&lt;li&gt;Short term prototyping/bug fix hacks&lt;/li&gt;&lt;li&gt;Discussing/Advising on future platforms&lt;/li&gt;&lt;li&gt;Optimizing programmer iteration, debugging &amp;amp; general workflow&lt;/li&gt;&lt;li&gt;Managing external teams&lt;/li&gt;&lt;li&gt;Auditioning Middleware&lt;/li&gt;&lt;li&gt;designing/writing/debugging infrastructure systems&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Technically i'm a member of Bungies "Infrastructure" team. This means that if its something "unexciting", "behind the scenes" or seemingly doesn't affect the final game at all... we handle it. This involves systems like&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Memory Allocation&lt;/li&gt;&lt;li&gt;File System&lt;/li&gt;&lt;li&gt;Network Transport&lt;/li&gt;&lt;li&gt;Crash Handling, Minidumps&lt;/li&gt;&lt;li&gt;Debugger Plugins&lt;/li&gt;&lt;li&gt;Multi-threading Infrastructure &amp; Architecture&lt;/li&gt;&lt;li&gt;Asset import/baking&lt;/li&gt;&lt;li&gt;Math Library&lt;/li&gt;&lt;li&gt;Schematization/Reflection&lt;/li&gt;&lt;li&gt;Audio Engine&lt;/li&gt;&lt;li&gt;Container Classes&lt;/li&gt;&lt;li&gt;Profiler Infrastructure&lt;/li&gt;&lt;li&gt;Compiler Configuration&lt;/li&gt;&lt;li&gt;Low &amp; High level Optimization&lt;/li&gt;&lt;li&gt;Build systems&lt;/li&gt;&lt;li&gt;Flux Capacitor Maintenance&lt;/li&gt;&lt;li&gt; - you still reading?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;as i said... the stuff most most programmers find tiresome and boring. Our team love this stuff and we're good at it.&lt;br /&gt;&lt;br /&gt;So there you have it, a much better idea of what i do @ Bungie and hopefully a guide to those in school who might want to progress towards a similar role (or avoid it).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-7442216134183348951?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/7442216134183348951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=7442216134183348951' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/7442216134183348951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/7442216134183348951'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2011/07/what-is-engineer-architect.html' title='What is an &quot;Engineer Architect&quot;'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-5Z2NdBq6VRA/TWX1VXrFszI/AAAAAAAABmQ/bbR-kD-TQow/s72-c/spaghetti-head.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-4587020058003926072</id><published>2011-07-07T01:26:00.000-05:00</published><updated>2011-07-07T01:26:17.277-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pre Main'/><category scheme='http://www.blogger.com/atom/ns#' term='C++ Initialization order'/><category scheme='http://www.blogger.com/atom/ns#' term='init_seg'/><title type='text'>Writing a "Pre-Main" function - Forcing Global Initialization order within VC++</title><content type='html'>One rule of C/C++ programming that bites everyone eventually is that initialization order of global variables across compilation units is not guaranteed. I've seen programs with global variable dependencies run fine for years then suddenly develop "issues" resulting in a hard lock before main(..) is hit. I've seen other programs have dependency issues but not actually crash resulting in subtle bugs that never seem to negatively affect run-time... until they do, usually on the day before gold master when the lead programmer is in Peru.&lt;br /&gt;&lt;br /&gt;So here's the situation, you want to create objects "a" through "g" in various files who register themselves with a manager into a list on construction... a relatively common setup and relatively simple within a single compilation module; for VC++ define them from bottom to top manager first and it will work. However across compilation modules things are not so simple and more often than not the manager will construct itself at a very inopportune time; likely after some objects have registered themselves and before all objects have. &lt;br /&gt;&lt;br /&gt;Without simply knowing that the manager will initialize first there really isn't a "Good" solution tho there are several lazy initialization techniques.&lt;br /&gt;&lt;br /&gt;So here's where things get "fun" and by "fun" i mean, people look at the code and get confused looks on their face.&lt;br /&gt;&lt;br /&gt;Put the following code into a cpp file on its own and add it to your project of choice.&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;#pragma init_seg( ".CRT$XCB" )&lt;br /&gt;&lt;br /&gt;class c_blog_first_class_construction&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    c_blog_first_class_construction() &lt;br /&gt;    {&lt;br /&gt;        printf("first class construction\n");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    ~c_blog_first_class_construction() {};&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;static c_blog_first_class_construction blog_first_class_construction;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;the constructor for c_blog_first_class_construction will be called before any other constructor in your code (assuming you have nothing else like this in there).&lt;br /&gt;&lt;br /&gt;NOTE: Expect C4075: initializers put in unrecognized initialization area, disable it if you feel the need.&lt;br /&gt;&lt;br /&gt;the key to the code is&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;#pragma init_seg(...)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;for more info on what this does see &lt;a href="http://support.microsoft.com/kb/104248"&gt;kb104248&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;The crux of it however is we are naming this compilation unit with a specific identifier, when the linker reads various .CRT groups, it combines them in one section and orders them alphabetically. This means that the user-defined global initializers (which the Visual C++ compiler puts in .CRT$XCU) will always come after CRT$XCA and before .CRT$XCZ. &lt;br /&gt;&lt;br /&gt;So we are depending linker to do the right thing and insert our section into the CRT sorted sections (verified in VS2010 as of 7/6/2011 for x86,x64,x360). It works and its very useful.&lt;br /&gt;&lt;br /&gt;Now if you want to get really fancy... make the constructor for c_blog_first_class_construction call a function that initializes your "Pre construction" requirements engine wide (usually memory management, assert systems).&lt;br /&gt;&lt;br /&gt;For other platforms (GCC/SNC are the only others i use) there are other options such as "init_priority" which is a per instance attribute. These can be used to achieve the same result but on a more granular level.&lt;br /&gt;&lt;br /&gt;It should be noted that this is not a method that one should use all over a codebase, personally i only ever use it on one compilation module and it is always VERY well commented.&lt;br /&gt;&lt;br /&gt;enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-4587020058003926072?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/4587020058003926072/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=4587020058003926072' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/4587020058003926072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/4587020058003926072'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2011/07/writing-pre-main-function-forcing.html' title='Writing a &quot;Pre-Main&quot; function - Forcing Global Initialization order within VC++'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-2821801747578437651</id><published>2011-05-22T09:27:00.001-05:00</published><updated>2011-05-22T09:30:42.942-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VS2010'/><category scheme='http://www.blogger.com/atom/ns#' term='DTE'/><category scheme='http://www.blogger.com/atom/ns#' term='EEAddin'/><category scheme='http://www.blogger.com/atom/ns#' term='Addin'/><title type='text'>Becoming a Console Programmer : Extending The Watch Window (debugger addin)</title><content type='html'>So previously we established how to use autoexp.dat for &lt;a href="http://andyfirth.blogspot.com/2011/05/becoming-console-programmer-extending.html"&gt;simple format changes&lt;/a&gt; and how to &lt;a href="http://andyfirth.blogspot.com/2011/05/becoming-console-programmer-extending_21.html"&gt;use a DLL&lt;/a&gt; to achieve those changes. There are major limitations to the DLL approach however in that we cannot access global symbols and thus any system that relies on global state for debug (as many do) cannot be debugged.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here I will discuss how to create a VS2010 plugin using C# (plugins also work for VS2008 however not using C#).&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://msdn.microsoft.com/en-us/library/envdte._dte.aspx"&gt;Development Tools Environment&lt;/a&gt; framework was setup around a decade ago to allow Visual Studio extensibility. I would recommend that any programmers read through what is possible using DTE however i'm not going to invest much time into that here; I will simply use one aspect of it to achieve our goal: global symbol access.&lt;br /&gt;&lt;br /&gt;VS2010 has a great Wizard to help us here, Select &lt;i&gt;File-&amp;gt;New-&amp;gt;Project&lt;/i&gt; then on the left hand side go to &lt;i&gt;Other Project Types-&amp;gt;Extensibility-&amp;gt;Visual Studio Addin&lt;/i&gt;, click next and then choose option (default) &lt;i&gt;Create an Add-in using Visual C#&lt;/i&gt;, leave application host as default, then give your addin a recognizable name. Set your addin to load when host application starts. The rest is default.&lt;br /&gt;&lt;br /&gt;This provides us with a very simple addin with a LOT of C# goodness and very little code. I should note that when i wrote this project it was my first foray into C# and thus my knowledge in this area is shady at best, i had lots of help from experts local to me in setting this up.&lt;br /&gt;&lt;br /&gt;If you read through the code you will find some relatively basic functionality. Your new addin has interfaces to intercept callbacks for various VS2010 events, OnConnection is the only default interface i used during which i installed new event handlers.&lt;br /&gt;&lt;br /&gt;So lets extend the default a little:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Add a member to the class of type "DebuggerEvents"&lt;/li&gt;&lt;li&gt;instantiate it to "_applicationObject.Events.DebuggerEvents"&lt;/li&gt;&lt;li&gt;setup handles for:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;OnEnterBreakMode&lt;/li&gt;&lt;li&gt;OnEnterRunMode&lt;/li&gt;&lt;li&gt;OnEnterDesignMode&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;VS2010 should auto-complete and auto generate these for you but the basics should look like :&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;_debugger_events.OnEnterBreakMode += new _dispDebuggerEvents_OnEnterBreakModeEventHandler(DebuggerEvents_OnEnterBreakMode);&lt;br /&gt;_debugger_events.OnEnterRunMode += new _dispDebuggerEvents_OnEnterRunModeEventHandler(_debugger_events_OnEnterRunMode);&lt;br /&gt;_debugger_events.OnEnterDesignMode += new _dispDebuggerEvents_OnEnterDesignModeEventHandler(_debugger_events_OnEnterDesignMode);&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;/li&gt;&lt;li&gt;For now ignore all but OnEnterBreakMode, this will be called whenever we enter any type of breakmode (stepping, breakpoints, exceptions etc). At this point we can do something quite nifty... any expression you can type into a watch window, can be evaluated here for example&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;Debugger debugger = _application_object.Debugger;&lt;br /&gt;Expression exp = debugger.GetExpression("&amp;amp;g_my_global_foo,d");&lt;br /&gt;&lt;br /&gt;if (exp.IsValidValue)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Int64 value = Convert.ToInt64(exp.Value.ToString(), 10);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Diagnostics.Debug.WriteLine(exp.Value.ToString());&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // do other fancy things here&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;At this point its really up to you to choose how you communicate this information to any external process. Personally my first simple solution was old school environment variable. This works perfectly well for a limited project, simply push your symbol address to the environment variable and let any other process (EEAddin for instance) read that environment variable and use it. Should you choose to publish the root address of your global systems for instance one might conceivably achieve full global memory addressing on your target.&lt;/li&gt;&lt;li&gt;The OnEnterRunMode hook should be used to "create" any resources you need on events "Attach" and "Launch"&lt;/li&gt;&lt;li&gt;The OnEnterDesignMode hook should be used to "destroy" those resources for events "Detach, EndProgram &amp;amp; Stop Debugging"&lt;/li&gt;&lt;/ol&gt;Debugging the debugger addin isn't difficult but is not obvious. Given the setup (Client Project) using (Debugger Addin) which launches Watch Window DLLS (EEAddin) the debugging method i used is:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Open the Debugger Addin project and build/run. This should open up an instance of VS2010 with your Addin loaded (check under &lt;i&gt;Tools-&amp;gt;Addin Manager&lt;/i&gt;&lt;/li&gt;&lt;li&gt;Within this second instance of VS2010 open up your Client Project, Build and run.&lt;/li&gt;&lt;li&gt;At this point breakpoints within the Debugger Addin are possible and you should be able to trap the incoming events.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Notes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;using environment variables will work for very simple projects however for production code i would recommend using process specific memory mapped files or another less hacky method&lt;/li&gt;&lt;li&gt;VS2008 can be supported however this has to be done as a C++/ATL project and requires a LOT of boilerplate code. Jason Weiler @ Airtight discusses this &lt;a href="http://www.myopictopics.com/?p=91"&gt;here&lt;/a&gt; and played a large part in enlightening me to this process.&lt;/li&gt;&lt;li&gt;As previous with EEAddin, this framework is not very forgiving and will require you to write defensively in all aspects. C# does handle a lot of this for you however the C++/ATL version will not. If you are writing an addin framework for a large group of programmers i would suggest significant boilerplate on all code. &lt;/li&gt;&lt;li&gt;the DTE framework is VERY powerful, anyone using it should read through the docs thoroughly to appreciate everything it can do and share what you do if you can :D&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-2821801747578437651?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/2821801747578437651/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=2821801747578437651' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/2821801747578437651'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/2821801747578437651'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2011/05/becoming-console-programmer-extending_22.html' title='Becoming a Console Programmer : Extending The Watch Window (debugger addin)'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-4368555920423527660</id><published>2011-05-21T18:41:00.001-05:00</published><updated>2011-05-22T08:14:55.674-05:00</updated><title type='text'>Becoming a Console Programmer : Extending The Watch Window (EEAddin)</title><content type='html'>So we established that its possible to re-format what a Watch Window shows you, make things look better and therefore easier to consume. What we cannot do with that method tho is any real processing... but we can with a little more work. &lt;br /&gt;&lt;br /&gt;consider the example&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;// blogtest.cpp : Defines the entry point for the console application.&lt;br /&gt;//&lt;br /&gt;&lt;br /&gt;#include "stdafx.h"&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;#include &amp;lt;intrin.h&amp;gt;&lt;br /&gt;&lt;br /&gt;enum e_union_test_case&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_unset,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_type_string,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_type_int,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_type_float,&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct u_test_level1&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int m_type;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; union u_data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const char *m_string;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int m_count;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; float m_value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }m_data;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void set(const char *string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_type= k_type_string;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_data.m_string= string;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void set(int int_value)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_type= k_type_int;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_data.m_count= int_value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void set(float float_value)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_type= k_type_float;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m_data.m_value= float_value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void print(void)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_unset)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("unset\n");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_type_string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("%s \n",m_data.m_string);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_type_int)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("%d \n",m_data.m_count);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_type_float)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("%f \n",m_data.m_value);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct s_test_level2&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static const int k_num_elements= 32;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; u_test_level1 m_elements[k_num_elements];&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int _tmain(int argc, _TCHAR* argv[])&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; s_test_level2 test;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; memset(&amp;amp;test,0,sizeof(test));&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test.m_elements[0].set("my foo");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test.m_elements[1].set(7);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; test.m_elements[2].set(3.14159265358f);&amp;nbsp;&amp;nbsp;&amp;nbsp; // everyone loves Pi&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return 0;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;similar to before setup a basic console project and drop in this code. Compile and run to the breakpoint and drop "test" into your watch window opening up the m_elements member... you should see something like.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-sgLfjCserMw/Tdg1YV398kI/AAAAAAAAACU/Xv2vEfpqQ00/s1600/autoexp_blog3.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-sgLfjCserMw/Tdg1YV398kI/AAAAAAAAACU/Xv2vEfpqQ00/s1600/autoexp_blog3.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;not very readable at all... the print function shows what we "might" do to display these elements by using "m_type" to change the formatting options...&lt;br /&gt;&lt;br /&gt;EEAddin is an option here, (Expression Evaluation Addin). This allows the autoexp.dat [AutoExpand] section to call into a dll for the preview display string. The dll can output any string it desires into the provided char buffer (obeying the limits of course).&lt;br /&gt;&lt;br /&gt;you can find an example EEAddin within the VS2010 install, assuming you have the samples extracted (most installs will have a zip file) you will find the solution at&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Samples\1033\VC2010Samples\C++\Debugging\EEaddin&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: small;"&gt;NOTE: the example does not work out of the box, you must edit "ADDIN_API" and make it&lt;/span&gt; &lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style="font-size: small;"&gt;#define ADDIN_API __declspec(dllexport)&amp;nbsp; __stdcall&lt;/span&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style="font-size: small;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;then move the HRESULT return to the opposite side of the ADDIN_API on use. Optionally you could achieve the same results by altering the project compiler options.&lt;/span&gt;&lt;/blockquote&gt;now paste the code&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;enum e_union_test_case&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_unset,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_type_string,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_type_int,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_type_float,&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct u_test_level1&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int m_type;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; union u_data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const char *m_string;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int m_count;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; float m_value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }m_data;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void print(char *result_buffer, int result_size)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_unset)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf_s(result_buffer, result_size,"unset\n");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_type_string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf_s(result_buffer, result_size,"str:\n");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_type_int)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf_s(result_buffer, result_size,"int:%d \n",m_data.m_count);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_type_float)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf_s(result_buffer, result_size,"flt:%f \n",m_data.m_value);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;HRESULT ADDIN_API AddIn_blogtest( DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t max, DWORD reserved )&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DWORD nGot;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; u_test_level1 example;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // read file time from debuggee memory space&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (pHelper-&amp;gt;ReadDebuggeeMemoryEx(pHelper, pHelper-&amp;gt;GetRealAddress(pHelper), sizeof(u_test_level1 ), &amp;amp;example, &amp;amp;nGot) != S_OK)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (nGot != sizeof(u_test_level1))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return E_FAIL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; example.print(pResult, max);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return S_OK;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Into the existing "timeaddin.cpp" file and add the export to both the header (timeaddin.h) and the def file (eeaddin.def).&lt;br /&gt;&lt;br /&gt;Compile this and it will generate EEaddin.dll, copy this dll to your VS2010 IDE folder (C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE).&lt;br /&gt;&lt;br /&gt;Add the line&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;u_test_level1=$ADDIN(eeaddin.dll,AddIn_blogtest)&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;to your autoexp.dat right below the previous example, below the [AutoExpand] tag.&lt;br /&gt;&lt;br /&gt;debug your application... your new display should be&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-6k3L0yvoZxQ/TdhHaSLoKZI/AAAAAAAAACY/eawMunthZ6k/s1600/autoexp_blog4.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-6k3L0yvoZxQ/TdhHaSLoKZI/AAAAAAAAACY/eawMunthZ6k/s1600/autoexp_blog4.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;each element now displays using the m_type correctly. We have an issue however, the string is not immediately available. This is due to the EEAddin working in a different memory space than the executable it is accessing. You'll note that the EEaddin DLL reads memory from the application manually using the supplied address AND by dint of the autoexp.dat line we know the size of the type we're representing. We must therefore pull any pointed at string data over manually in order to display it.&lt;br /&gt;&lt;br /&gt;the new code is&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;enum e_union_test_case&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_unset,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_type_string,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_type_int,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; k_type_float,&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct u_test_level1&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; int m_type;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; union u_data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const char *m_string;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int m_count;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; float m_value;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }m_data;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void print(char *result_buffer, int result_size)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_unset)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf_s(result_buffer, result_size,"unset\n");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_type_string)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf_s(result_buffer, result_size,"str:%s\n",m_data.m_string);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_type_int)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf_s(result_buffer, result_size,"int:%d \n",m_data.m_count);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (m_type == k_type_float)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sprintf_s(result_buffer, result_size,"flt:%f \n",m_data.m_value);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;HRESULT ADDIN_API AddIn_blogtest( DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t max, DWORD reserved )&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DWORD nGot;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; u_test_level1 example;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // read file time from debuggee memory space&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (pHelper-&amp;gt;ReadDebuggeeMemoryEx(pHelper, pHelper-&amp;gt;GetRealAddress(pHelper), sizeof(u_test_level1 ), &amp;amp;example, &amp;amp;nGot) != S_OK)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return E_FAIL;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (nGot != sizeof(u_test_level1))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return E_FAIL;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static const int local_buffer_size= 1024;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; char local_buffer[local_buffer_size];&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (example.m_type == k_type_string &amp;amp;&amp;amp; example.m_data.m_string != 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // pull over the string to our local buffer&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pHelper-&amp;gt;ReadDebuggeeMemoryEx(pHelper, (DWORDLONG)example.m_data.m_string, local_buffer_size, local_buffer, &amp;amp;nGot);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; example.m_data.m_string= local_buffer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; example.print(pResult, max);&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return S_OK;&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;this code uses the pointer within the original "example" and pulls over an arbitrary length data stream (1kb) relying upon the string being null terminated. It then points our local copy of example.m_data.m_string to that local buffer before calling our new print(...) function which will now output the string as before. Our new display is:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ojGQanJjP7U/TdhLLfDi8tI/AAAAAAAAACc/_dBEZ0fvPQc/s1600/autoexp_blog5.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-ojGQanJjP7U/TdhLLfDi8tI/AAAAAAAAACc/_dBEZ0fvPQc/s1600/autoexp_blog5.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;which is exactly what we need.&lt;br /&gt;&lt;br /&gt;Notes:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;EEAddin is not forgiving&lt;/li&gt;&lt;ul&gt;&lt;li&gt;if you do something heinous within an EEAddin entrypoint it WILL take out the devenv that loaded it. Within Addins you MUST program defensively at all points, assume you will be sent bad data, assume your strings will not be null terminated, assume that the pointers you need to follow are bad and take you into no mans land. Verify everything. You'll note that i did not do this in my example but that is merely for the purposes of keeping the code samples short and sweet.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Debugging the EEAddin&lt;/li&gt;&lt;ul&gt;&lt;li&gt;load up the EEAddin project, Attach to the instance of devenv (debug it) that your Main project runs in, put breakpoints into your Addin entrypoint then hit debug on your application. Each time your Watch Window updates your EEAddin dll is loaded/called/unloaded so expect a lot of calls in the array case.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Global Symbols are not accessible &lt;/li&gt;&lt;ul&gt;&lt;li&gt;Accessing client memory requires the physical address of said client memory, if this address isn't accessible from the element you're debugging then you have no way to get to that address. An example of this limitation would be a handle into a global manager. The client code can call the manager to get the object, the debugger can only display the value of the handle, EEAddin can only access the internals OF the handle. It does not have knowledge of the manager and thus it cannot access the object itself.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Not all Endianess was made equal&lt;/li&gt;&lt;ul&gt;&lt;li&gt;if your target is not the same endianess as PC (little) such as xbox 360 then you must switch the endianess of data before reading it.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Alignment &amp;amp; Pointer size&lt;/li&gt;&lt;ul&gt;&lt;li&gt;you will have to manually handle both alignment differences (target &amp;lt;=&amp;gt; client) and pointer size differences. In my support thus far i have chosen 2 pathways. Some structures i have made cross platform entirely by supplying a construct that is 64bit and aware of its pointer size. For other types where this isn't possible i have used an element of the next topic to disclose to the DLL the size of our pointer.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-4368555920423527660?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/4368555920423527660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=4368555920423527660' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/4368555920423527660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/4368555920423527660'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2011/05/becoming-console-programmer-extending_21.html' title='Becoming a Console Programmer : Extending The Watch Window (EEAddin)'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-sgLfjCserMw/Tdg1YV398kI/AAAAAAAAACU/Xv2vEfpqQ00/s72-c/autoexp_blog3.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-5133898336139343994</id><published>2011-05-21T16:17:00.001-05:00</published><updated>2011-06-07T16:00:24.709-05:00</updated><title type='text'>Becoming a Console Programmer : Extending The Watch Window (autoexp.dat)</title><content type='html'>Watch windows are important, they show us our data in various forms and generally enable us to debug effectively, sometimes however they need help.&lt;br /&gt;&lt;br /&gt;Setup a simple windows console project and use the following code:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace;color: #000000;background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px;overflow: auto;width: 100%"&gt;&lt;code&gt;struct s_test_level1&lt;br /&gt;{&lt;br /&gt;    int m_count;&lt;br /&gt;    char* m_string;&lt;br /&gt;    float m_value;&lt;br /&gt;&lt;br /&gt;    void print(void)&lt;br /&gt;    {&lt;br /&gt;        if (m_string)&lt;br /&gt;        {&lt;br /&gt;            printf(&amp;quot;%s %d %f\n&amp;quot;,m_string, m_count, m_value);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;static const int k_num_elements= 32;&lt;br /&gt;struct s_test_level2&lt;br /&gt;{&lt;br /&gt;    s_test_level1 m_elements[k_num_elements];&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int _tmain(int argc, _TCHAR* argv[])&lt;br /&gt;{&lt;br /&gt;    s_test_level2 test;&lt;br /&gt;&lt;br /&gt;    memset(&amp;amp;amp;test,0,sizeof(test));&lt;br /&gt;&lt;br /&gt;    test.m_elements[0].m_string= &amp;quot;my foo&amp;quot;;&lt;br /&gt;    test.m_elements[0].m_count= strlen(test.m_elements[0].m_string);&lt;br /&gt;    test.m_elements[0].m_value=3.14159265358f; // everyone loves Pi&lt;br /&gt;&lt;br /&gt;    test.m_elements[0].print();&lt;br /&gt;&lt;br /&gt;    return 0; // &amp;amp;lt;&amp;amp;lt;= breakpoint here&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;now run the program putting a breakpoint on indicated line. Open up a watch window and drop test into it opening up the m_elements array, you should see something like&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-fD57I8WDYwY/TdgldimnO9I/AAAAAAAAACM/7bisL11Jdj4/s1600/autoexp_blog.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-fD57I8WDYwY/TdgldimnO9I/AAAAAAAAACM/7bisL11Jdj4/s1600/autoexp_blog.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This is a really simple but even now we see some details we don't always need... lets reformat it.&lt;br /&gt;&lt;br /&gt;open up the file&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;VS2010 PC: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\Packages\Debugger\autoexp.dat&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;VS2008 PC: C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Packages\Debugger\autoexp.dat &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;Xbox360: C:\Program Files (x86)\Microsoft Xbox 360 SDK\bin\win32\autoexp.dat for 360&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;search for "[AutoExpand]" and add the line&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;s_test_level1=&amp;lt;m_count,d&amp;gt;, &amp;lt;m_string,s&amp;gt;, &amp;lt;m_value,f&amp;gt;f&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;save that file and re run the test program.... you should now see&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Ozlbj9ygezw/Tdgp8kkZPtI/AAAAAAAAACQ/grVtTN8vY-Y/s1600/autoexp_blog2.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Ozlbj9ygezw/Tdgp8kkZPtI/AAAAAAAAACQ/grVtTN8vY-Y/s1600/autoexp_blog2.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;a much easier to read version of the same data.&lt;br /&gt;&lt;br /&gt;All the original information is still available should you need it but this new format is much easier to quickly consume.&lt;br /&gt;&lt;br /&gt;This form of watch window help is somewhat limited however, you can only interpret existing data, remove superfluous detail, do some VERY rudimentary math and generally make things cleaner and easier to consume; see the next post for MORE.&lt;br /&gt;&lt;br /&gt;All of the help required to use autoexp.dat is within the file itself. Note that the "[Visualizer]" section is currently not available for xbox 360 targets but is VERY powerful for other targets.&lt;br /&gt;&lt;br /&gt;enjoy and feel free to ask questions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-5133898336139343994?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/5133898336139343994/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=5133898336139343994' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/5133898336139343994'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/5133898336139343994'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2011/05/becoming-console-programmer-extending.html' title='Becoming a Console Programmer : Extending The Watch Window (autoexp.dat)'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-fD57I8WDYwY/TdgldimnO9I/AAAAAAAAACM/7bisL11Jdj4/s72-c/autoexp_blog.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-8267407565063525580</id><published>2011-05-20T09:11:00.006-05:00</published><updated>2011-05-20T09:22:27.929-05:00</updated><title type='text'>Incoming Topics (what should I blog about next?)</title><content type='html'>So i've not had much time recently for various reasons and i apologize to those who were following avidly. I should however have some time very soon and wanted to give people the change to decide which topic i talk about... so go for it... comment away (these topics are for x86, x64 and xbox360 tho i cannot directly discuss xbox360 almost all code applies to all 3 targets)&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Extending "Watch Window" Vizualization&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Visual Studio debugger plugins&lt;/li&gt;&lt;li&gt;How to get YOUR object to construct first&lt;/li&gt;&lt;li&gt;Creating a "Premain" function that runs before global constructors&lt;/li&gt;&lt;li&gt;Suggestions?&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-8267407565063525580?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/8267407565063525580/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=8267407565063525580' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/8267407565063525580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/8267407565063525580'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2011/05/incoming-topics-what-shoud-i-blog-about.html' title='Incoming Topics (what should I blog about next?)'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-5068585803416563394</id><published>2010-08-07T22:09:00.004-05:00</published><updated>2010-08-08T12:47:11.008-05:00</updated><title type='text'>Static assert with a "real" message.</title><content type='html'>static asserts are important for many reasons and are heavily used in most large codebases esp when said codebase has many target environments. They inform the programmer when an assumption fails at compile time allowing for the runtime code to avoid expensive verification.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;#define COMPILE_ASSERT(x) extern int __dummy[(int)x]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Which is typically used as&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;COMPILE_ASSERT(sizeof(int) == sizeof(unsigned));&lt;br /&gt;COMPILE_ASSERT(sizeof(int) == sizeof(char));&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;the second example if obviously wrong and provides the output.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;error C2466: cannot allocate an array of constant size 0&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Which is not very useful other than as a signal that something bad occurred.&lt;br /&gt;&lt;br /&gt;Now consider the form&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;#pragma warning (disable: 4483)&lt;br /&gt;&lt;br /&gt;typedef char __identifier("compile assert:");&lt;br /&gt;&lt;br /&gt;#define COMPILE_STRING_ASSERT(condition, name) \&lt;br /&gt;typedef __identifier("compile assert:") __identifier(name)[1]; \&lt;br /&gt;typedef __identifier("compile assert:") __identifier(name)[(condition) ? 1 : 0];&lt;br /&gt;&lt;br /&gt;define COMPILE_ASSERT(condition) COMPILE_STRING_ASSERT(condition, #condition)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The above uses the identifier keyword which is technically an error however the pragma warning disables the error (yes it doesn't make sense). This keyword allows the user to define ANY identifier, valid C++ or not.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;COMPILE_ASSERT(sizeof(int) == sizeof(char));&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now provides the output&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;'compile assert: sizeof(int) == sizeof(char)[1]'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;which is a much more palatable message esp when considering automatic build systems.&lt;br /&gt;&lt;br /&gt;Note2&lt;br /&gt;&lt;ul&gt;&lt;li&gt;__identifier is specific to Visual Studio and may not be supported by other compilers.&lt;/li&gt;&lt;li&gt;VC++ 2010 introduces static_assert for all targets, tho it is less powerful than using __identifier.&lt;/li&gt;&lt;li&gt;SNC may support both, i will try to confirm.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-5068585803416563394?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/5068585803416563394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=5068585803416563394' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/5068585803416563394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/5068585803416563394'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2010/08/static-assert-with-real-message.html' title='Static assert with a &quot;real&quot; message.'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-27966390199936497</id><published>2010-08-07T12:52:00.008-05:00</published><updated>2010-08-07T22:09:16.608-05:00</updated><title type='text'>Becoming a console programmer : Math Libraries Part 2</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Implementation&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Generally speaking implementation of a math library is not determined by the programmer DOING the implementation but by the clients of the system and the platforms that require support.&lt;br /&gt;&lt;br /&gt;Given the myriad targets currently available AND the similarly complex client base i always recommend a relatively complex abstraction built on simple rules:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;separate the client facing api into semantic types&lt;/li&gt;&lt;li&gt;define those types using platform specific typedefs or defines&lt;/li&gt;&lt;li&gt;implement using a cross platform api with platform specific implementations.&lt;/li&gt;&lt;/ul&gt;for example we might want the client to use matrix, point, vector and proxy type for float constants.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_YajlJ--bbo4/TF4Wc0T39VI/AAAAAAAAABc/Bsf8PMSA-Y4/s1600/blog_math.jpg"&gt;&lt;img style="cursor: pointer; width: 400px; height: 98px;" src="http://3.bp.blogspot.com/_YajlJ--bbo4/TF4Wc0T39VI/AAAAAAAAABc/Bsf8PMSA-Y4/s400/blog_math.jpg" alt="" id="BLOGGER_PHOTO_ID_5502860479027475794" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;the semantic types define their functionality in terms of the low level api which in turn defines a set of common operations that all the semantic types can use at will. This means that to provide support for a new platform for ALL semantic types (which there are usually far more than 4) the programmer simply has to satisfy the lowest level api.&lt;br /&gt;&lt;br /&gt;That low level api is typically relatively small providing wrappers for some of the basic operations such as add, mul, madd, permute, shuffle/vsel etc whilst also implementing some of the more complex but common operations such as normalize, permute_operation etc.&lt;br /&gt;&lt;br /&gt;To flesh things out for the client side the programmer should define operators and functions that provide mathematically sensible and desirable operations such as&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;vector = point - point, &lt;/li&gt;&lt;li&gt;point = point + vector * scale.&lt;/li&gt;&lt;/ul&gt;the proxy type mentioned above would be a simd representation of a single float allowing the math itself to remain in registers.&lt;br /&gt;&lt;br /&gt;The key to maintaining long mathematically complex code in registers is in ensuring the semantic types are well defined within themselves and as a whole.&lt;br /&gt;&lt;br /&gt;there is a lot more to be said on the subject of math libraries however without infringing on company policies both new and old i cannot expand further. The above should however provide a good start and from there a good programmer will run with it and discover for themselves the rest.&lt;br /&gt;&lt;br /&gt;enjoy.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-27966390199936497?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/27966390199936497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=27966390199936497' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/27966390199936497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/27966390199936497'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2010/08/becoming-console-programmer-math.html' title='Becoming a console programmer : Math Libraries Part 2'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_YajlJ--bbo4/TF4Wc0T39VI/AAAAAAAAABc/Bsf8PMSA-Y4/s72-c/blog_math.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-5669239608606807076</id><published>2010-07-05T09:28:00.007-05:00</published><updated>2010-07-05T13:20:03.730-05:00</updated><title type='text'>Becoming a console programmer : Math Libraries Part 1</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Writing a Math Library&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Over the years i've had to write, re-write and optimize math libraries far too often. Sometimes 2-3 times within 1 project. This might sound strange given that time is money however, counter intuitively, that fact is the driving force behind so many re-writes.&lt;br /&gt;&lt;br /&gt;I believe that its possible to write an "ok" math library that will work for "all" use cases but nigh on almost impossible to write an "optimal" math library to suite all cases. Large and still growing programming teams, changing platforms and multiple  simultaneous platforms and differing requirements across target executables compound the issue to the point where its simply too complex.&lt;br /&gt;&lt;br /&gt;Gustavo Oliveira discusses some of the considerations &lt;a href="http://www.gamasutra.com/view/feature/4248/designing_fast_crossplatform_simd_.php"&gt;here&lt;/a&gt; which can be roughly summed up as&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;use intrinsics&lt;/li&gt;&lt;li&gt;return by value&lt;br /&gt;&lt;/li&gt;&lt;li&gt;declare data purely&lt;/li&gt;&lt;li&gt;provide operators and functions&lt;/li&gt;&lt;li&gt;inline everything&lt;br /&gt;&lt;/li&gt;&lt;li&gt;replicate results in SIMD&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;I don't agree with all of the above as hard rules but prefer to judge based on each specific platform and target build.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Use Intrinsics&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Intrinsics are functions whose implementation is handled entirely by the compiler. See &lt;a href="http://en.wikipedia.org/wiki/Intrinsic_function"&gt;Wiki&lt;/a&gt; for more. Most compilers provide the ability to write inline assembly routines and this can be very useful for pieces of code that require significant hand optimization however the for short functions such as those seen in vector math libraries, the bulk of the programming work is in the handling of the calling convention and how the return values are provided and interpreted. Due to the myriad entrypoints to support for math libraries it quickly gets out of control and unmanageable.&lt;br /&gt;&lt;br /&gt;Intrinsics hide these issues, the compiler has intimate knowledge of the intrinsic function, how it should be called, how it returns, how it can be combined with other instructions and every possible combination you might otherwise have to handle with inline assembly. It does this optimally every time (IME).&lt;br /&gt;&lt;br /&gt;Use them.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. "XXX by Value"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Return by value, on this one i both agree and disagree. It isn't hard and fast in all cases, especially so in cases where a function has more than 1 resultant value. Generally speaking however you should, where possible, write code that returns register sized values as "return by value". Under optimization the compiler will attempt to keep the value in a register and not commit to memory thus making the code faster. Certain platforms are however limited to a small set of registers for SIMD math and thus storage back to memory is more prevalent. I recommend investigating this for your platform(s) of choice.&lt;br /&gt;&lt;br /&gt;The XNAMath library handles this by specifying function parameters that can be altered per platform. For example&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;XMFINLINE XMVECTOR XMVector2IntersectLine&lt;br /&gt;(&lt;br /&gt;    FXMVECTOR Line1Point1,&lt;br /&gt;    FXMVECTOR Line1Point2,&lt;br /&gt;    FXMVECTOR Line2Point1,&lt;br /&gt;    &lt;span style="font-weight: bold;"&gt;CXMVECTOR&lt;/span&gt; Line2Point2                                  &lt;== different type&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;FXMVector is defined to be a constant, pass by reference type, for platforms that don't support passing in registers, under x86 we are limited to passing the 1st to 3rd parameters as registers so only the first three params to this function use this type. The typedef is thus defined as&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;typedef const XMVECTOR FXMVECTOR;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;for x86 / xbox 360.&lt;br /&gt;On xbox 360 the 4th parameter is defined as&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed,  monospace; color: #000000; background-color: #eee;font-size:  12px;border: 1px dashed #999999;line-height: 14px;padding: 5px;  overflow: auto; width: 100%"&gt;&lt;code&gt;typedef const XMVECTOR CXMVECTOR;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;whereas on x86 its defined as&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed,  monospace; color: #000000; background-color: #eee;font-size:  12px;border: 1px dashed #999999;line-height: 14px;padding: 5px;  overflow: auto; width: 100%"&gt;&lt;code&gt;typedef const XMVECTOR&amp;amp;  CXMVECTOR;&lt;br /&gt; &lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This allows the actual code to be completely independent of the underlying hardware limitations. Under x64 the PC has more registers to use thus the x86 limited types can be defined to pass by value without changing ought but the typedef.&lt;br /&gt;&lt;br /&gt;This platform agnostic setup becomes very important as more and more platforms need support.&lt;br /&gt;&lt;br /&gt;Note: On some platforms its possible to define this as a directive to the compiler. On xbox-360 for instance the compiler provides a pragma (passinreg) applying to a single float, double or __vector4. This informs the compiler that it should "prefer" using registers over temporary storage and helps avoid LHS (Load Hits Store).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. Declare data purely&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is a good general rule however brings with it issues that are hard to avoid. The theory is that the compiler can better optimize a native type than a wrapper type, which is generally the case apart from types supported by extended instructions such as VMX. On 360 the passinreg pragma does not require a pure type to be used provided the data is the  only member of the class being created. This allows you to define your type as&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;__declspec(passinreg)&lt;br /&gt;class my_foo_vector&lt;br /&gt;{&lt;br /&gt;private:&lt;br /&gt;    __vector4 m_vector_data;&lt;br /&gt;&lt;br /&gt;public:&lt;br /&gt;&lt;br /&gt;    // my foo vector interface&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;and the compiler will treat it as if it were the __vector4 type. This is similarly the case for float/double types and is enormously useful.&lt;br /&gt;&lt;br /&gt;What this means is that we can wrap the datatypes and better define their syntax and semantics without negatively impacting the resultant code generation. Typical types defined by a math library might be&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;point4d - 3d position in space, w = 1&lt;br /&gt;&lt;/li&gt;&lt;li&gt;direction4d - 3d direction vector, w = 0 &lt;/li&gt;&lt;li&gt;quaternion - simple quaternion container &lt;/li&gt;&lt;li&gt;sphere - 3d position, w= radius&lt;br /&gt;&lt;/li&gt;&lt;li&gt;plane -  3d normal, w= distance  &lt;/li&gt;&lt;li&gt;euler4d - euler angles, w not used.&lt;/li&gt;&lt;li&gt;float4d - x=y=z=w&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;each of the types represents a specific behavior and has specific interfaces both local to the type and to allow generation of them. For instance&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;direction4d generate_direction(point4d_const_in a, point4d_const_in b);&lt;br /&gt;point4d offset_point(point4d_const_in a, direction4d dir, float4d length);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Once a high level math library is defined in terms of behavior rather than type it is much more usable by general programmers who then don't need to worry about the implementation itself, only that the behavior they require is well defined by the type they choose.&lt;br /&gt;&lt;br /&gt;So, i would recommend that you investigate your platform and make the call, sometimes platforms don't provide any type of "passinreg" functionality and then it becomes a judgement call. Personally i prefer a wrapped type than a pure type simply because it allows me to limit the functionality i provide to the clients of my system.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Operators vs Functions&lt;/span&gt;&lt;br /&gt;we can all see that the code&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;position = position_a + direction_b * scalar_c;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;is easy to read and its precedence well defined. Just like general math terms, the more complex things get the more difficult it is to understand and thus we expand things out to more meta terms (temporaries). The compiler will do the same when presented with a long sequence of operators.&lt;br /&gt;&lt;br /&gt;IME however... it doesn't help to re-factor that long sequence of operators into a long(er?) sequence of function calls. I am willing to believe there are circumstances where this occurs however the general case that i examine when writing code doesn't show it.&lt;br /&gt;&lt;br /&gt;For now i recommend writing all sensible operators, of course those defined as "sensible" are often up for discussion. I tend to do +-*/ and all variants leaving it at that. I highly recommend AGAINST ever overloading operators to supply cross product / dot product.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;5. Inline everything.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Another general rule that i agree with (but for those pesky debug builds). Personally i choose to force the inlining of all base level math functions.&lt;br /&gt;&lt;br /&gt;Most development occurs in a debug form, we've written the code and it didn't work first time, or we've come back to fix an edge case 6months after writing the code. For most game logic code the math library will be a significant support system and in many cases it is &gt;50% OF said code.&lt;br /&gt;&lt;br /&gt;In a release build it is highly likely that most of our math functions will boil down to a small set of instructions, in many cases a single instruction acting on registers alone. This is perfect for our needs in a release environment. Due to the nature of math code we tend to use a lot of functions for very little actual work per function. In a full debug build the compiler will turn off all optimisations, this includes the general use of pass-by-register and return by register, it will also NOT inline functions defined as "inline" while (most of the time) maintaining the inlining of code defined as "forceinline". The net result is we get a LOT more actual code for a client function using the math library. The code is horribly inefficient, dumping to memory after every operation which results in significant LHS issues.&lt;br /&gt;&lt;br /&gt;Vectorized inline reliant math in debug is slow, so don't inline in debug.&lt;br /&gt;&lt;br /&gt;What i choose to do is define the math library as inline for all builds other than debug, in debug we instance the functions into a release optimized lib that the client executable links against. The math code itself isn't inlined so it doesn't bloat AND the compiler will honor the calling conventions of the code. It won't be anywhere near as fast as the full release inline versions but you can expect ~40% of the speed of said build completed to ~5-10% for full debug with inlining.&lt;br /&gt;&lt;br /&gt;6. Replicate&lt;br /&gt;&lt;br /&gt;The dot product mathematically provides a scalar value but in code this value most often used AS an operand to a vector operation. Consider reflection&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;i  - [in] A floating-point reflection vector.&lt;br /&gt;n - [in] A floating-point ray direction vector.&lt;br /&gt;v = i - 2 * dot(i, n) * n&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/span&gt;&lt;br /&gt;a naive implementation might do&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;// Result = Incident - (2 * dot(Incident, Normal)) * Normal&lt;br /&gt;float f_dot = dot_product(i , n);    // vector -&amp;gt; memory&lt;br /&gt;vector4 result= i - (2.0f   * f_dot * n);       &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;this will roughly boil down to&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;// simd register -&amp;gt; memory&lt;br /&gt;float f_dot = dot_product(i , n);   &lt;br /&gt;// LHS (~25cycles)&lt;br /&gt;// memory -&amp;gt; float register + mul -&amp;gt; memory&lt;br /&gt;float tmp= 2.0f * f_dot&lt;br /&gt;// LHS (~25cycles)&lt;br /&gt;// memory -&amp;gt; simd register + replicate&lt;br /&gt;vector4 promote= replicate(tmp);   &lt;br /&gt;// simd mul, simd subtract&lt;br /&gt;vector4 result= i - (promote * n);   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;for which we get 2 LHS hits. (360 PPC chip experience, not sure on PC side)&lt;br /&gt;Now if we consider the instructions above its not a huge jump to see how to remove the LHS problems.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;// simd register return from dot_product&lt;br /&gt;float4 f_dot4 = dot_product(i , n);   &lt;br /&gt;float4 f_dot4_2 = f_dot4 + f_dot4;&lt;br /&gt;// simd mul, simd subtract&lt;br /&gt;vector4 result= i - (f_dot4_2 * n);   &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;this is a relatively simple change that removes some very expensive operations &amp;amp; delays... it can be taken further with the use of vnmsubfp which will perform result= - ((b * c) - a).&lt;br /&gt;&lt;br /&gt;the general principle is that vector data should remain registers/vector storage as long as possible.&lt;br /&gt;&lt;br /&gt;Part 2 will discuss implementation details.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-5669239608606807076?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/5669239608606807076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=5669239608606807076' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/5669239608606807076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/5669239608606807076'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2010/07/becoming-console-programmer-math.html' title='Becoming a console programmer : Math Libraries Part 1'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-7711198418883748838</id><published>2010-06-17T20:14:00.014-05:00</published><updated>2010-06-19T21:57:16.793-05:00</updated><title type='text'>Becoming a console programmer : Structure Alignment</title><content type='html'>This is an area that all programmers should be familiar with however i've met and worked with a fair few who never had to care... until they had to care.&lt;br /&gt;consider:&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;struct foo1&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;struct foo2&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char;&lt;br /&gt;};&lt;br /&gt;struct foo3&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;long long m_longlong;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char1;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char2;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;using default settings under x86 these three structs are 1, 8 and 16 bytes respectively. What is actually allocated is&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&lt;br /&gt;struct foo2&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;            // offset 0 : size 4 bytes&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char;           // offset 4 : size 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_pad[3];         //                             3 bytes padding&lt;br /&gt;                     &lt;/code&gt;&lt;code&gt;     &lt;/code&gt;&lt;code&gt;// 8 bytes&lt;br /&gt;};&lt;br /&gt;struct foo3&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;long long m_longlong;  // offset 0  : size 8 bytes&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;            // offset 8  : size 4 bytes&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char1;          // offset 12 : size 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char2;          // offset 13 : size 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_pad[2];         //                            2 bytes padding&lt;br /&gt;                     &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt; // 16 bytes total&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;now lets take foo3 and jumble those members a little.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;struct foo4&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char1;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;long long m_longlong;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char2;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;One might expect foo4 to be the same size as foo3 however it is not, it comes out to 24 bytes, the padding is as follows.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;struct foo4&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char1;           // offset 0  : size 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_pad7[7];         //                          7 bytes padding&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;long long m_longlong;   // offset 8  : 8 bytes&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char2;           // offset 16 : 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_pad[3];          //                          3 bytes padding&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;             // offset 20 : 4 bytes&lt;br /&gt;};                          // 24 bytes total&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;each type contained within a struct must begin on a natively aligned boundary, so the 8 byte "long long" must start on an 8 byte offset within the struct but be after m_char1 so the compiler inserts 7 bytes of "padding" that the user cannot directly access to ensure this.&lt;br /&gt;&lt;br /&gt;to inspect this for yourself use the code&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;&lt;br /&gt;printf("\n(%d,",offsetof(foo4, m_char1));&lt;br /&gt;printf("%d,",offsetof(foo4, m_longlong));&lt;br /&gt;printf("%d,",offsetof(foo4, m_char2));&lt;br /&gt;printf("%d)",offsetof(foo4, m_int));&lt;br /&gt;printf(": %d",sizeof(foo4));&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;output : "(0, 8, 16, 20): 24"&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Manual Alignment&lt;/span&gt;&lt;br /&gt;It is often beneficial to align the base of a structure beyond its native requirements. I won't go into the reasons for this here (thats a later subject) but it does change the internals of a struct when you do this.&lt;br /&gt;Consider:&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;struct _CRT_ALIGN(16) foo_aligned4&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char1;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;long long m_longlong;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char2;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;the&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;_CRT_ALIGN(16)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;informs the compiler that this structure should be 16 byte aligned (and therefore a multiple of 16 bytes in size), this is actually a wrapper around a declspec (see below for further reading)&lt;br /&gt;&lt;br /&gt;In the case of foo4 this doesn't change the offsets of any of the internals but it does change the size of the struct&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;struct _CRT_ALIGN(16) foo_aligned4&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char1;           // offset 0  : size 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    //                          7 bytes padding&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;long long m_longlong;   // offset 8  : 8 bytes&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char2;           // offset 16 : 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;//                          3 bytes padding&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;             // offset 20 : 4 bytes&lt;br /&gt;                                                      8 bytes adding&lt;br /&gt;};                          // 32 bytes total&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;if we were to then include an instance of foo_aligned4 inside another struct, said struct will inherit the same aligment. In general a structure will always be aligned to the largest alignment of its components.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;struct foo_composite&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char1;                // offset  0: size 1 byte&lt;br /&gt;                                //                             15 bytes padding&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;foo_aligned4 m_foo_aligned4; // offset  16: size 32 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;long long m_longlong;        // offset  48: size 8 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char2;                // offset  56: size 1 byte&lt;br /&gt;                                //                             3 bytes padding&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;                  // offset  60: size 4 byte&lt;br /&gt;                                // total 64 bytes&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now given our composite structure of 64 bytes lets see how small we can make it without altering the client facing elements.&lt;br /&gt;&lt;pre style="font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; border: 1px dashed rgb(153, 153, 153); line-height: 14px; padding: 5px; overflow: auto; width: 100%;"&gt;&lt;code&gt;struct _CRT_ALIGN(16) foo_aligned4_opt&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;long long m_longlong;            // offset  0: size 8 bytes&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;                      // offset  8: size 4 bytes&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char1;                    // offset  12: size 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char2;                    // offset  13: size 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_pad[2];                   // offset  14: size 2 bytes&lt;br /&gt;};                                   // 16 bytes total&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;struct foo_composite_opt&lt;br /&gt;{&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;foo_aligned4_opt m_foo_aligned4;// offset  0: size 16 bytes&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;long long m_longlong;           // offset  16: size 8 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;int  m_int;                     // offset  24: size 4 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char1;                   // offset  28: size 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_char2;                   // offset  29: size 1 byte&lt;br /&gt;&lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;char m_pad[2];                  // offset  30: size 2 bytes&lt;br /&gt;                               &lt;/code&gt;&lt;code&gt;    &lt;/code&gt;&lt;code&gt;// 32 bytes total&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Our new composite struct is 32 bytes rather than 64, every member still exists but in a different configuration.&lt;br /&gt;You may notice that I manually inserted the padding into the struct, this isn't required but personally i prefer it in cases where i require specific alignment or optimal structure size.&lt;br /&gt;&lt;br /&gt;So key points are&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;structures inherit the largest alignment of their elements&lt;/li&gt;&lt;li&gt;elements will always begin at an offset that is a multiple of their alignment&lt;/li&gt;&lt;li&gt;the compiler will insert padding into your structure to achieve alignment requirements&lt;/li&gt;&lt;li&gt;structure size will always be a multiple of its alignment&lt;/li&gt;&lt;li&gt;to reduce alignment padding, arrange structures largest to smallest in alignement requirements.&lt;/li&gt;&lt;/ul&gt;Note that normal allocators, such as &lt;a href="http://msdn.microsoft.com/en-us/library/6ewkz86d%28v=VS.71%29.aspx"&gt;malloc&lt;/a&gt;,  C++ &lt;a href="http://msdn.microsoft.com/en-us/library/we2zys4d%28v=VS.71%29.aspx"&gt;operator  new&lt;/a&gt;, and the Win32 allocators return memory that will most likely  not be sufficiently aligned for &lt;b&gt;__declspec(align(&lt;/b&gt;&lt;i&gt;#&lt;/i&gt;&lt;b&gt;))&lt;/b&gt;  structures or arrays of structures. I recommend writing your own allocator either as a wrapper around these or as a region allocator to achieve alignment above default (4 or 8 bytes usually).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;further reading  -&lt;a href="http://msdn.microsoft.com/en-us/library/83ythb65%28VS.71%29.aspx"&gt;_CRL_ALIGN&lt;/a&gt;,&lt;a href="http://msdn.microsoft.com/en-us/library/45t0s5f4%28v=VS.71%29.aspx"&gt; __alignof&lt;/a&gt;,&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-7711198418883748838?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/7711198418883748838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=7711198418883748838' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/7711198418883748838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/7711198418883748838'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2010/06/becoming-console-programmer-structure.html' title='Becoming a console programmer : Structure Alignment'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-5885530238527624154</id><published>2010-06-17T08:36:00.004-05:00</published><updated>2010-06-17T11:49:15.584-05:00</updated><title type='text'>Becoming a console programmer : LHS</title><content type='html'>Zak Whaley pointed me at this &lt;a href="http://assemblyrequired.crashworks.org/2009/01/12/why-you-should-never-cast-floats-to-ints/"&gt;article&lt;/a&gt; on "Some Assembly required" discussing float-&gt; int conversion and what occurs when its done following onto the &lt;a href="http://assemblyrequired.crashworks.org/2008/07/08/load-hit-stores-and-the-__restrict-keyword/"&gt;LHS article&lt;/a&gt; within the same site which describes relatively well what "Load Hits Store" (LHS) is and how to avoid it using the restrict keyword.&lt;br /&gt;&lt;br /&gt;Later when i discuss math libraries i will come back to this with respect to vector &lt;=&gt; float interchange and how to effectively remove it from transient use.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-5885530238527624154?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/5885530238527624154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=5885530238527624154' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/5885530238527624154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/5885530238527624154'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2010/06/becoming-console-programmer-lhs.html' title='Becoming a console programmer : LHS'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-878720804437062380</id><published>2010-06-16T21:39:00.004-05:00</published><updated>2010-06-17T08:07:16.764-05:00</updated><title type='text'>Becoming a console programmer</title><content type='html'>Recently on a games industry forum, a friend who teaches over in the Netherlands (not Denmark :p) was asking us (programmers) what we would ensure a PC programmer moving to Console Development should know, before considering themselves a "console programmer"&lt;br /&gt;&lt;br /&gt;None of these particularly apply to console programming however i've  found over the years that programmers who come form a pure PC background  often are lacking in this area so i personally consider them important.&lt;br /&gt;&lt;br /&gt;Programmers new to console should strive to achieve:&lt;ul&gt;&lt;li&gt;an awareness  of memory consumption - PC programmers tend to be somewhat liberal with memory allocation and stack usage. On Consoles we're often faced with very limited memory resources that shrink with time (due to the game getting larger) rather than the opposite on PC where virtual memory allows incredibly large memory footprints.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;knowledge of alignment - internal to structures and how it pertains  to their size AND how not paying attention can massively increase cache misses&lt;br /&gt;&lt;/li&gt;&lt;li&gt;appreciation of the cost of type conversions both in terms of float  &lt;=&gt; integer, float &lt;=&gt; simd and the assumed simpler integer  to integer conversions thar can cost significantly more than is assumed.&lt;/li&gt;&lt;li&gt;full understanding of what a Load Hits Store (LHS) is, how it occurs, how to avoid it  and how to spot it in everyday code.&lt;/li&gt;&lt;li&gt;full understanding of the implications of a cache miss, what it is,  how to avoid them and how to fill the time around the unavoidable ones.&lt;/li&gt;&lt;li&gt;full understanding of what a branch is, how it affects the cpu, how  to avoid using them and what patterns should be avoided to minimize them  in general purpose code&lt;/li&gt;&lt;li&gt;understand what select functions are (fsel, vsel family) and how/when to use them.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;SIMD is important however there are MANY companies that write a math lib once and never look  back, i've been guilty of this myself however now i know i was wrong  back then and no doubt in many ways what i've written most recently is  still wrong.&lt;br /&gt;&lt;br /&gt;writing it once implies that when you wrote the lib you knew everything  there was to know then and nothing changed in the years afterwards....  yes many games will be fine with an "ok" math lib however a "good" math  lib can change the performance of a game and an entire team.&lt;br /&gt;&lt;br /&gt;re-write it as often as you can afford learning from the mistakes each  time... so much is based upon it that this is one of the few systems  that i'd recommend this behavior on.&lt;br /&gt;&lt;br /&gt;so a final point&lt;ul&gt;&lt;li&gt;learn simd math in all its forms, learn the  extra instructions that most don't use and what they provide, learn how  to use #.INF to your advantage and most of all use instructions such as  vsel / shuffle/ permute to their fullest advantage.&lt;/li&gt;&lt;/ul&gt;I will be posting expansions on the above points over the next few weeks depending on demand.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-878720804437062380?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/878720804437062380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=878720804437062380' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/878720804437062380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/878720804437062380'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2010/06/becoming-console-programmer.html' title='Becoming a console programmer'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-2010320144255370714</id><published>2009-11-19T09:58:00.002-06:00</published><updated>2009-11-19T10:04:41.819-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C'/><category scheme='http://www.blogger.com/atom/ns#' term='learning to program'/><category scheme='http://www.blogger.com/atom/ns#' term='algorithmic thinking'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='simple english'/><title type='text'>Becoming a programmer - thinking algorithmically</title><content type='html'>[duped from a post i made on www.thechaosengine.com an industry only forum]&lt;br /&gt;&lt;br /&gt;last time I taught someone how to think algorithmically I asked them... what is a seemingly simply task ... that you do ALL the time.&lt;br /&gt;&lt;br /&gt;they chose - make a cup of &lt;span class="highlight"&gt;tea&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I asked them to write down, in absolutely the order they would do it, everything they need in order to do it, everything they do to go from no cup of &lt;span class="highlight"&gt;tea&lt;/span&gt;...to a fresh cup in hand.&lt;br /&gt;&lt;br /&gt;each time they finished I asked them to follow their own instructions using only the inputs they specified, only the instructions they had written down....&lt;br /&gt;&lt;br /&gt;took about 20 iterations to get it right but each time they got better.&lt;br /&gt;&lt;br /&gt;I then asked them to repeat that process on their own with other simple tasks....&lt;br /&gt;&lt;br /&gt;I did this before introducing any language or limits... simple english....&lt;br /&gt;&lt;br /&gt;2 weeks later I sat in on them going through the same process for "checking &amp;amp; replying to email"... 100% correct.&lt;br /&gt;&lt;br /&gt;after that... developing small programs in C became a syntactic problem only... write down the english as comments... flesh it out with the C.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-2010320144255370714?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/2010320144255370714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=2010320144255370714' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/2010320144255370714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/2010320144255370714'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2009/11/becoming-programmer-thinking.html' title='Becoming a programmer - thinking algorithmically'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-4939146623447606426</id><published>2008-12-14T18:56:00.008-06:00</published><updated>2011-08-09T17:46:47.314-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Arcane'/><category scheme='http://www.blogger.com/atom/ns#' term='Low Level'/><category scheme='http://www.blogger.com/atom/ns#' term='old school'/><category scheme='http://www.blogger.com/atom/ns#' term='assembly'/><title type='text'>The demise of the "Low Level" programmer.</title><content type='html'>[updated 8/9/2011]&lt;br /&gt;&lt;br /&gt;When I started programming many of the elements we take for granted  now, did not exist. There was no DirectX and not many compatible libs  were available for the free compilers of the day. So I had to write my  own code for most basic programs, keyboard handlers, mouse handlers,  video memory accessors, rasterizers, texture mappers, blitters… the  programs I wrote then were 100% my own code and I had to be able to  handle anything and everything.&lt;br /&gt;Personally I’ve always been  interested in what was going on under the hood so this suited me just  fine. I always dug into the details and I almost always end up  programming as close to the bone ON the hardware (or OS) as I possibly  can both to eek out as much performance as possible AND to satisfy my  own hunger for knowledge.&lt;br /&gt;Combine the two and what you get today  is someone who enjoys spending 5 days making that single function 20x  faster, who revels in reducing the memory footprint of the primary data  structure by 1 byte per element across the entire program whilst  simultaneously writing a pre-caching system to avoid the special case  issues…. who… well you get the picture… I’m an OCD level sport  optimizing geek. To such a degree that I keep a notepad by my bed to  take notes when I wake up from a “bug fix” dream or a “eureka  optimization” doze…yes i’m that sick.&lt;br /&gt;Over the last decade I’ve  been involved in the hiring process at many studios and in more recent  years I’ve noticed a pattern. Knowledge of what is generally considered  “low-level” programming is waning. Many programmers know enough to get  through a C# or C++ test, but don’t understand something as basic (and  important) as the behavior of memory or god forbid a cache. They don’t  seem to grasp that one must understand the native environment you’re  working in before going ahead and writing a program to run within it.  The intricacies of floating point vs fixed point math are completely  lost on them as the term “fixed point” brings about a blank stare;  floating point numbers are best right?. I once mentioned bit shifting to  an experienced engineer of 10 years and was devastated by the complete  lack of basic understanding.&lt;br /&gt;It depresses me that so much of what I  consider to be essential is simply not being taught anymore. I’m not  talking about assembly language per se; even those of us who used to  spend hours writing assembly now more often opt to use intrinsics built  into compilers to avoid the stress and complication. What I’m talking  about is simply the understanding of WHAT is happening when someone does  i++ and not ++i, why one might opt to stripe a memory copy/set in  certain circumstances.&lt;br /&gt;So here goes… a list of things I believe  all console programmers (and recommend to all programmers as good  reading) should fully understand with links to educate where possible.  (feel free to suggest more/better links)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Floating Point Numbers&lt;/li&gt;&lt;ul&gt;&lt;li&gt;They  are very useful but often used in situations where they simply don’t  suit the solution the programmer is attempting to write. The following  links should provide some background and info on where they are not so  useful, what the pitfalls are and sometimes even how to avoid them.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cprogramming.com/tutorial.html#fptutorial" rel="nofollow"&gt;http://www.cprogramming.com/tutorial.html#fptutorial&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.johndcook.com/blog/2009/04/06/numbers-are-a-leaky-abstraction/" rel="nofollow"&gt;http://www.johndcook.com/blog/2009/04/06/numbers-are-a-leaky-abstraction/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.codeproject.com/KB/recipes/float_point.aspx" rel="nofollow"&gt;http://www.codeproject.com/KB/recipes/float_point.aspx&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://drdobbs.com/184402741?pgno=4" rel="nofollow"&gt;http://drdobbs.com/184402741?pgno=4&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://users.tkk.fi/jhi/infnan.html" rel="nofollow"&gt;http://users.tkk.fi/jhi/infnan.html&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Fixed Point Numbers&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Fixed  point math is mildly old school but it is VERY useful both to  understand its makeup and to use. Sadly because it is considered old  school many of the online sources are out of date.&lt;/li&gt;&lt;li&gt;&lt;a href="http://x86asm.net/articles/fixed-point-arithmetic-and-tricks/" rel="nofollow"&gt;http://x86asm.net/articles/fixed-point-arithmetic-and-tricks/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://gameprogrammer.com/4-fixed.html" rel="nofollow"&gt;http://gameprogrammer.com/4-fixed.html&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Processor Cache Behavior / Memory&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span class="aptureLink " id="apture_prvw66"&gt;&lt;span class="aptureLinkIcon" style="background-position: right -448px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;a class="aptureLink snap_noshots" href="http://www.akkadia.org/drepper/cpumemory.pdf"&gt;http://www.akkadia.org/drepper/cpumemory.pdf&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="aptureLink " id="apture_prvw67"&gt;&lt;span class="aptureLinkIcon" style="background-position: right -1348px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;a class="aptureLink snap_noshots" href="http://en.wikipedia.org/wiki/CPU%20cache"&gt;http://en.wikipedia.org/wiki/CPU_cache&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://igoro.com/archive/gallery-of-processor-cache-effects/" rel="nofollow"&gt;http://igoro.com/archive/gallery-of-processor-cache-effects/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Bit Shifting&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.cprogramming.com/tutorial/bitwise_operators.html" rel="nofollow"&gt;http://www.cprogramming.com/tutorial/bitwise_operators.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;useful hacks (use carefully)&lt;/li&gt;&lt;li&gt;&lt;a href="http://graphics.stanford.edu/%7Eseander/bithacks.html" rel="nofollow"&gt;http://graphics.stanford.edu/~seander/bithacks.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/539836/emulating-variable-bit-shift-using-only-constant-shifts" rel="nofollow"&gt;http://stackoverflow.com/questions/539836/emulating-variable-bit-shift-using-only-constant-shifts&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://guru.multimedia.cx/avoiding-branchesifconditionals/" rel="nofollow"&gt;http://guru.multimedia.cx/avoiding-branchesifconditionals/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Branch Prediction&lt;/li&gt;&lt;ul&gt;&lt;li&gt;This  may be lower level that people think they need to go… but they’d be  wrong. Understanding how the hardware you’re programming for treats  branches can affect performance to a HUGE degree… far more than most  programmers may appreciate re: &lt;i&gt;death&lt;/i&gt; by a thousand &lt;i&gt;cuts&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://cellperformance.beyond3d.com/articles/2006/04/background-on-branching.html" rel="nofollow"&gt;http://cellperformance.beyond3d.com/articles/2006/04/background-on-branching.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/" rel="nofollow"&gt;http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="aptureLink " id="apture_prvw68"&gt;&lt;span class="aptureLinkIcon" style="background-position: right -448px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;a class="aptureLink snap_noshots" href="http://www.k8gu.com/ece.umn.edu/documents/classes/ece362-branch-prediction.pdf"&gt;http://www.k8gu.com/ece.umn.edu/documents/classes/ece362-branch-prediction.pdf&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;cite&gt;&lt;/cite&gt;&lt;span class="aptureLink " id="apture_prvw69"&gt;&lt;span class="aptureLinkIcon" style="background-position: right -448px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;a class="aptureLink snap_noshots" href="http://www.cs.ucr.edu/%7Egupta/teaching/203A-09/My6.pdf"&gt;http://www.cs.ucr.edu/~gupta/teaching/203A-09/My6.pdf&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Sorting&lt;/li&gt;&lt;ul&gt;&lt;li&gt;This  isn’t really low-level but something i consider “basic” and its an area  where many programmers are simply lacking in understanding. Do yourself  a favor and play around with this link, read the links it sends you to  for each algorithm and try to grasp when each might be used, the  properties as described and the next time you need to sort something…  consult it.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.sorting-algorithms.com/" rel="nofollow"&gt;http://www.sorting-algorithms.com/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;another good link with sub links: &lt;a href="http://corte.si//posts/code/visualisingsorting/index.html" rel="nofollow"&gt;http://corte.si//posts/code/visualisingsorting/index.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;a funny one (but still strangely useful), the bubble sort dance: &lt;span class="aptureLink " id="apture_prvw70"&gt;&lt;span class="aptureLinkIcon" style="background-position: right -1548px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;a class="aptureLink snap_noshots" href="http://www.youtube.com/watch?v=lyZQPjUT5B4"&gt;http://www.youtube.com/watch?v=lyZQPjUT5B4&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;So  there you go, I’ve likely missed some aspects that should make the list  but if you can grasp the above then you’re more likely to get noticed  at interviews and you’ll certainly be a better programmer for it.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;Edit  8/8/2011 – It seems I didn’t do a very good job at explaining the core  audience for the article, I apologize for that. The programmers I would  like to see learning and absorbing these “low level” details are those  who would see themselves working in console games. The HW is fixed for  long periods of the time and resources become scarce usually within 1  game cycle; understanding how to better utilize resources becomes a key  part of the job.&lt;br /&gt;While i believe that most programmers would  benefit from understanding more about the medium they work in it is  certainly not required&lt;br /&gt;Hopefully you enjoyed the article in the spirit it was intended.&lt;br /&gt;Andy Firth&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-4939146623447606426?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/4939146623447606426/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=4939146623447606426' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/4939146623447606426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/4939146623447606426'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2008/12/demise-of-low-level-programmer.html' title='The demise of the &quot;Low Level&quot; programmer.'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-867523572724581140</id><published>2008-10-01T13:26:00.007-05:00</published><updated>2008-10-01T18:56:59.398-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Instant Messenger'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='Games'/><category scheme='http://www.blogger.com/atom/ns#' term='IM'/><category scheme='http://www.blogger.com/atom/ns#' term='Developement'/><title type='text'>Working with Instant Messenger.</title><content type='html'>Personally i could not work without instant messenger (IM) in all of its guises. I use trillian on my main dev machine to talk to friends, colleagues and peers around the world. I do it without thinking and i do it without negatively affecting my work; it is a tool of life and work. I use it to discuss tech within the game/engine, to setup meetings, to discuss scheduling issues, to setup tests... essentially anything work related (and some not work related things).&lt;br /&gt;&lt;br /&gt;Recently i did a poll on a well populated games dev only forum. I started the poll based entirely on a single conversation with a friend at R* San Diego who said that R* do not allow IM usage. After a few hours it became apparent that around 10% of developers do not allow IM usage in any form, the other 90% largely given open access.&lt;br /&gt;&lt;br /&gt;So why is it some companies simply don't allow it?&lt;br /&gt;&lt;br /&gt;It seems that IM usage is a worry to the powers that be who think maybe details that should not be discussed outside of work might be discussed over IM which could indeed be considered a security leak if the receipient is not employed by said company, on the other hand what about internal only IM. I would ask, how likely is it that someone would spend the time (and money) to infiltrate another persons messenger account in order to log the conversations that would require that person to be logged on in the first place. I don't know how easy/difficult this is (and maybe my opinion would change if i knew) but it seems very unlikely that this is happening and thus i question the decision to remove such a useful tool from developers.&lt;br /&gt;&lt;br /&gt;I also heard some rumblings that certain companies believe IM is a distraction and they need to remove any and all of those lest the peons get too engrossed in something other than work. Personally i think that people who use IM as a distraction at the expense of their work will likely find another distraction if / when IM is removed.&lt;br /&gt;&lt;br /&gt;In the past i've worked for Activision and EA, two of the largest publishers, both of whome encourage IM usage. EA has an SIP setup internal to each studio that provides access to ALL. ATVI don't actively help people setup IM but they do not discourage it either, many of the studio level heads use it. It is a useful element of everyday developer life.&lt;br /&gt;&lt;br /&gt;So, my opinions are known... what are yours?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-867523572724581140?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/867523572724581140/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=867523572724581140' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/867523572724581140'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/867523572724581140'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2008/10/working-with-instant-messenger.html' title='Working with Instant Messenger.'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5677255309189696783.post-7772908153451308532</id><published>2008-09-30T20:59:00.000-05:00</published><updated>2008-09-30T21:02:03.353-05:00</updated><title type='text'>First!!</title><content type='html'>So I've been reading blogs for a while now of various people and today a friend of mine asked if i had one... upon hearing i didn't he went ahead (with my permission) and published on his blog some of my thoughts and helpful hints regarding Vista64... I had always thought blogs took a long time however his post took about 30 seconds longer than it took for me to tell him my info...&lt;br /&gt;&lt;br /&gt;so i figured its high time i made one myself... hopefully i post something useful here soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5677255309189696783-7772908153451308532?l=andyfirth.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andyfirth.blogspot.com/feeds/7772908153451308532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5677255309189696783&amp;postID=7772908153451308532' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/7772908153451308532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5677255309189696783/posts/default/7772908153451308532'/><link rel='alternate' type='text/html' href='http://andyfirth.blogspot.com/2008/09/first.html' title='First!!'/><author><name>Andy Firth</name><uri>http://www.blogger.com/profile/06145256612053295677</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://1.bp.blogspot.com/_YajlJ--bbo4/Sr7OdCbkQ0I/AAAAAAAAAAM/z4weD9he-5k/S220/me.jpg'/></author><thr:total>1</thr:total></entry></feed>
