Current version

v1.10.4 (stable)


Main page
Archived news
Plugin SDK
Knowledge base
Contact info
Other projects



« April 2021
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  


01 Dec - 31 Dec 2013
01 Oct - 31 Oct 2013
01 Aug - 31 Aug 2013
01 May - 31 May 2013
01 Mar - 31 Mar 2013
01 Feb - 29 Feb 2013
01 Dec - 31 Dec 2012
01 Nov - 30 Nov 2012
01 Oct - 31 Oct 2012
01 Sep - 30 Sep 2012
01 Aug - 31 Aug 2012
01 June - 30 June 2012
01 May - 31 May 2012
01 Apr - 30 Apr 2012
01 Dec - 31 Dec 2011
01 Nov - 30 Nov 2011
01 Oct - 31 Oct 2011
01 Sep - 30 Sep 2011
01 Aug - 31 Aug 2011
01 Jul - 31 Jul 2011
01 June - 30 June 2011
01 May - 31 May 2011
01 Apr - 30 Apr 2011
01 Mar - 31 Mar 2011
01 Feb - 29 Feb 2011
01 Jan - 31 Jan 2011
01 Dec - 31 Dec 2010
01 Nov - 30 Nov 2010
01 Oct - 31 Oct 2010
01 Sep - 30 Sep 2010
01 Aug - 31 Aug 2010
01 Jul - 31 Jul 2010
01 June - 30 June 2010
01 May - 31 May 2010
01 Apr - 30 Apr 2010
01 Mar - 31 Mar 2010
01 Feb - 29 Feb 2010
01 Jan - 31 Jan 2010
01 Dec - 31 Dec 2009
01 Nov - 30 Nov 2009
01 Oct - 31 Oct 2009
01 Sep - 30 Sep 2009
01 Aug - 31 Aug 2009
01 Jul - 31 Jul 2009
01 June - 30 June 2009
01 May - 31 May 2009
01 Apr - 30 Apr 2009
01 Mar - 31 Mar 2009
01 Feb - 29 Feb 2009
01 Jan - 31 Jan 2009
01 Dec - 31 Dec 2008
01 Nov - 30 Nov 2008
01 Oct - 31 Oct 2008
01 Sep - 30 Sep 2008
01 Aug - 31 Aug 2008
01 Jul - 31 Jul 2008
01 June - 30 June 2008
01 May - 31 May 2008
01 Apr - 30 Apr 2008
01 Mar - 31 Mar 2008
01 Feb - 29 Feb 2008
01 Jan - 31 Jan 2008
01 Dec - 31 Dec 2007
01 Nov - 30 Nov 2007
01 Oct - 31 Oct 2007
01 Sep - 30 Sep 2007
01 Aug - 31 Aug 2007
01 Jul - 31 Jul 2007
01 June - 30 June 2007
01 May - 31 May 2007
01 Apr - 30 Apr 2007
01 Mar - 31 Mar 2007
01 Feb - 29 Feb 2007
01 Jan - 31 Jan 2007
01 Dec - 31 Dec 2006
01 Nov - 30 Nov 2006
01 Oct - 31 Oct 2006
01 Sep - 30 Sep 2006
01 Aug - 31 Aug 2006
01 Jul - 31 Jul 2006
01 June - 30 June 2006
01 May - 31 May 2006
01 Apr - 30 Apr 2006
01 Mar - 31 Mar 2006
01 Feb - 29 Feb 2006
01 Jan - 31 Jan 2006
01 Dec - 31 Dec 2005
01 Nov - 30 Nov 2005
01 Oct - 31 Oct 2005
01 Sep - 30 Sep 2005
01 Aug - 31 Aug 2005
01 Jul - 31 Jul 2005
01 June - 30 June 2005
01 May - 31 May 2005
01 Apr - 30 Apr 2005
01 Mar - 31 Mar 2005
01 Feb - 29 Feb 2005
01 Jan - 31 Jan 2005
01 Dec - 31 Dec 2004
01 Nov - 30 Nov 2004
01 Oct - 31 Oct 2004
01 Sep - 30 Sep 2004
01 Aug - 31 Aug 2004


Powered by Pivot  
XML: RSS feed 
XML: Atom feed 

§ Platform support on Visual Studio 2012

Much has been said about the lack of support for targeting Windows XP in the RTM version of Visual Studio 2012. However, it looks like there are also ominous clouds on the horizon for Vista.

I happened to be looking at the Visual Studio 2012 compatibility page and noticed something weird: the little footnote [4] that indicated Remote Debugging was not available for a platform was not only on the XP row, but also on the Vista row. I figured that must have been a mistake, until I also checked the Visual Studio 2012 Remote Tools download and found that it requires Windows 7 SP1. Now, I don't exactly feel like dragging out the old laptops to find out which one has the secondary Vista installation to test, so I'll have to take Microsoft's word on this. If it's true, though, it would be the first time I can remember that Visual Studio would let you target a platform and have no debugging support for it. I also find it weird because generally there are a lot more reasons at the API level to require Vista than to require Windows 7. With Vista, you get some long desired goodies like native conditional variables and CancelIoEx(). Requiring Windows 7 doesn't give you nearly as much, particularly with some of the new stuff back-ported through the Vista Platform Update.

Microsoft has announced that they will be working on an update to VS2012 to allow targeting Windows XP with the 2012 compiler, but I haven't heard about extending the debugging support. As such, it might be a good idea to brush up on your WinDbg skills. But hey, as I always say, using WinDbg builds character.

(Read more....)

§ That annoying sound

For the past couple of days I have been harassed by a sporadic random beep in my house. Usually when I'm not watching a movie or playing a game it's pretty quiet, so I'd be sitting around in my living room eating, reading, coding, or whatever, and then


One really quick, high pitched beep. Out of nowhere. Worse yet, it was only happening about every ten minutes and wasn't that loud, so it was hard to track down. I'd think it was the microwave timer or something, clear 'em all to be sure, then return to what I was doing, such as writing some code


Maybe the smoke alarm? Nope, it's a lot louder than that. Alarm clock? It's off.



Having had enough, I picked up my laptop and started computing at various places on the floor, trying to pick up directional cues as to the location of the sound. Problem is, the sound was so high pitched and quick that I could only tell by hearing that it was roughly left-ish or right-ish of my current position. After a couple of dead ends in the hallway and dining room, I could only determine that it was somewhere in the vicinity of one side of my living room, which strangely enough isn't supposed to have any electronic devices that are plugged in much less powered. An hour later, after hovering around the area while folding various bits of laundry, I had a suspicion that it was coming from a nondescript cardboard box.

Which, when opened and emptied, turned out to have a cordless phone receiver in it.

It turns out, for some dumb reason, that the way this model phone indicates that it is out of its cradle and needs to be charged is that it outputs a single, tenth of a second beep every ten minutes. I had picked this up intending to use it, but had forgotten about it. Apparently this phone is dual-purpose in that if it doesn't work out as a phone, you can plant the receiver near someone you hate as an electronic torture device. Now I'm not so sure I want to use it....

(Read more....)

§ Gotchas when creating a single instance application

A single instance application is one that only permits one instance of itself to run at a time. One reason to do this is that the program requires exclusive access to a shared resource, such as a large persistent database within the user profile. Another reason is for better UI: perhaps for an image viewer you want the same window to be reused by default instead of popping up new windows each time that the user needs to close.

Depending on the specific requirements, there are a couple of ways to enforce a single instance on Windows, such as named mutexes and exclusive file locks. In addition to enforcing the restriction, though, you'll usually want to pass the command-line parameters over as well so that the existing instance can respond to the new request. The first inclination is to just marshal over the command-line parameters via some RPC mechanism. A cursory search for sample code shows this to be a common practice. This works great, until you get a command line like this:

awesomeness.exe file.awe

The problem here is that the passed-in path is relative. Since most Win32 GUI programs will change their current directory whenever the common file dialog is used, it's likely that the existing and new processes will have different current working directories and thus the open operation in the existing process will fail. Sending over the current directory solves this problem, but this is the case I find is often forgotten:

awesomeness.exe d:file.awe

This is a drive-relative path, which causes the same problem. These are useful if you're a command-line junkie like me. The tricky part is that there aren't explicit APIs in Win32 to access the current drive paths, even though Win32 itself does the resolution. It turns out they're hidden environment variables of the form =A:, =B:, etc. Send those over too, and now the paths work. Another way to solve this would be to expand all of the paths to full paths in the second instance, but that's a bit more command-line parsing in the cross-launch path than I like.

There is a third case to watch out for, which is when the existing instance is running under a different user account within the same window session. You can get into this situation via the "runas" command or the "run as a different user" functionality. This bites me in the butt occasionally with Firefox where some program I have running under one user account will launch a web link and it'll load into the existing Firefox instance under a different user profile than it would have otherwise. Detecting this situation involves a little bit of detective work with getting the process ID of the window, opening the process, and checking the user information on the process token.

The final odd situation is elevated vs. non-elevated status on Windows Vista, i.e. run as administrator. This is a pretty odd situation since the process is running under the same user and mostly the same but not quite the same environment. A particular issue is that elevated and non-elevated processes see different sets of SUBST'ed drives. It's pretty clear that you wouldn't want a non-elevated launcher to hand arbitrary arguments off to an existing elevated process, but silently failing or throwing an error isn't a good user experience either. Handling of this case likely needs to be tailored depending on the reason for the single-instance restriction.

(Read more....)

§ Altirra 2.10 released

I'll keep this one brief: version 2.10 of my emulator Altirra is now out. Have fun!

(Read more....)

§ The DXGI_FORMAT_R8G8_B8G8_UNORM texture format

A pet peeve of mine is underspecification, where the documentation for an API or file format doesn't tell you enough specifics about what it is describing. Instead, you get some ambiguous description of a feature that looks like it's informative, but doesn't actually tell you what you need to know.

Take, for example, this description of a texture format from Microsoft's DXGI_FORMAT enumeration (from

A four-component, 32-bit unsigned-normalized integer format. [3]

I'm pretty sure this wasn't reviewed by anyone who would actually try to use said format.

Well, at least we know it's 32-bit, and the unsigned-normalized (UNORM) part described later tells us that the components are at least decoded as 0-1. From the name we could make an educated guess that the components are 8-bit and somehow relate to red, green, and blue, and that there's something strange going on with green, but that's about it. Maybe that footnote will tell us more?

3. A resource using a sub-sampled format (such as DXGI_FORMAT_R8G8_B8G8) must have a size that is a multiple of 2 in the x dimension.

That's good to know, but we still don't know enough to actually use it.

Allow me to fill in the missing information:

This format encodes pairs of RGB pixels in a 32-bit packed format, where the red and blue components are encoded at half the horizontal resolution of the green component. The byte ordering in memory is red, green0, blue, green1, where the green0 and green1 pixels are the left and right pixels of each horizontal pair, respectively. The RGB color of each pixel is the shared red and blue values of the pair combined with the corresponding green pixel. Alpha is 1.0.

Although the resource size must be an even number of pixels in the X dimension, it may have mipmaps that are not an even number of pixels across, similarly to how mipmapped DXTn/BCn textures are handled.

Apparently, this format was intended to allow for efficient decoding of UYVY format video, which encodes video in YCbCr colorspace with 4:2:2 subsampling. R8G8_B8G8_UNORM could be used to render UYVY video with an appropriate color matrix transform, if it were not for two deficiencies. First, the red and blue components are upsampled using point sampling. Bilinear interpolation can be used but will simply interpolate the result after the red and blue samples have been doubled up. Second, the shared red and blue components are positioned in the center of the pair of green samples, which is at odds with modern video formats that align it with the left sample (coalignment). The result is that the R8G8_B8G8_UNORM format gives low-quality rendering of UYVY and should not be used in a production video renderer. This might have been somewhat useful for MPEG-1 rendering, except that MPEG-1 is 4:2:0 instead of 4:2:2 and if you have hardware that supports Direct3D 10/11 you might as well use three R8 textures instead.

The G8R8_G8B8_UNORM format is a byte-swapped version that is analogous for YUY2 encoded video, and is equally useless.

(Read more....)

§ The case of the PIX-only crash

PIX for Windows is a tool that comes with the Microsoft DirectX SDK for debugging Direct3D applications. I have a love/hate relationship with it, but when it comes to debugging rendering state problems, I haven't found anything that works better. NVPerfHUD is no good at tracking down single-frame glitches, and Intel Graphics Performance Analyzer (GPA), while surprisingly useful for debugging, doesn't expose full device state. Thus, I find myself using PIXWin a lot, even despite its shortcomings (its data presentation could use a lot of cleanup).

While trying to use it today, I ran into the annoyance of a PIX-only crash, meaning that the program would crash only when run with PIX instrumentation enabled.

Typically, I turn on the Direct3D debug runtime and make sure the program is debug runtime clean before trying to use PIX. The debug runtime fires debug asserts if it sees badness like invalid state, which is much easier to track down with the debug runtime than from mysterious crashes or error asserts in PIX. Unfortunately, that trick didn't work this time as the program ran cleanly outside of PIX and bombed inside of it, so I had to attach a debugger to the process while PIX had it hooked to try to diagnose the problem.

Long story short, the problem had to do with the extra code that the PIX hook runs when it instruments a process. PIX works by hooking the Direct3D entry points and running extra code to capture the D3D calls made by the program. Apparently, one of the things it does when D3D is initialized (Direct3DCreate9) is use Windows Management Instrumentation (WMI) to get some information about the graphics device. This in turn makes a blocking COM call to another thread, which then runs a message loop within the current thread to service messages while waiting for the other thread to run the call. This is needed to service other cross-thread calls back into the blocked thread and prevent deadlocks.

The other piece of the puzzle is a change that was made to COM starting with Windows Vista to allow WM_PAINT to be dispatched during blocking calls. IMO this is a bad idea as dispatching anything other than other sent messages (SendMessage) invites reentrancy problems, and that is true here as well. In my case, this caused a paint message to be dispatched on the display window that was still stuck in init in the Direct3DCreate9 call, resulting in an attempt to refresh the window using the 3D context that hadn't been inited yet. The workaround I applied was to add a reentrancy counter to block normal WM_PAINT handling on that window until init had completed.

(Read more....)