CLOG

A coder's BLOG from Todd S. Murchison

Disclaimer

The opinions expressed herein are my own and do not represent any other individual or organization.

© Copyright 2009

The philosophy of favoring Playstation over Xbox

Due to some recent events I have been forced to closely examine my preference for the Playstation brand over the Xbox brand.  Trusting vaguely in my impressions and gut feelings is fine in a casual day-to-day context, but once you "go public" with your opinions you are expected to explain yourself, and rightly so.

To date I have always avoided explaining myself, because I knew it would be a difficult task.  I know that my opinions are not based on a spreadsheet of numbers somewhere.  They are not founded in a game genre that is entirely missing from one platform or the other.  I knew that examining my opinions and impressions closely, understanding them, and then expressing them clearly would not be easy, but the time has come to try.

As I began to seriously consider the topic I  had to admit to myself I can not entirely separate my feelings about the Xbox from my feelings about Microsoft (you can't argue that they are not closely related).  This concession gave me the key; it was the breakthrough I needed to begin understanding my opinions.

This realization led me to pondering the culture in which games are created (corporate culture, gamming culture, media culture, national culture), the big business, big budget production process, and inevitably, a resulting limit in scope of inspiration.  A good analogy here would be the film industry.  As Hollywood becomes more and more of a streamlined moneymaking machine, the films resulting from the process drift further and further away from film as art, from film as boundary pushing or revolutionary.

So what does all this have to do with games?  Well, big business has a proven track record of gravitating towards the lowest common denominator, for sticking to proven formulas over and over again, for minimizing risk while maximizing profit.  And who could blame them for that, right?  It's good business.

Now I acknowledge that the big-production games of today need to be commercially viable to even exist, but I do not want my video games (or my movies) to come entirely from business.  I want at least some portion of the game to come from artistic sensibilities.  I want at least some portion of the game to come from artists rather than a money-making formula.

Ok, so how does this relate directly to Microsoft and the Xbox 360 or its predecessor?  Well this is where we soundly enter the realm of opinion.  It is my opinion that, based on what I have seen for the Xbox platform so far, that Microsoft is doing an excellent job of minimizing risk while maximizing profit.  So far I have seen very little content that strays all that far from proven formula (with the possible exception of some of the XBL content).

My feelings regarding content available for the Xbox platform can be nicely summed up by paraphrasing the lead designer of Bioshock.  He essentially said that it's like most game designers have read one book and seen one movie in their lives, which is "Lord of the Rings" and "Aliens" or variations thereof.  They both have great content, but you need some variety.  In other words, I love "Aliens" and "Lord of the Rings", but I don’t want to keep seeing them remade over and over again with slight variations.  As long as game makers for the Xbox consoles continue to draw from such a limited pool of inspiration, it will not matter if they are making an FPS, an RPG, a flight simulator, or a roll-playing FPS flight-sim.  Aesthetically the game will come out feeling stale.

As an aside, I am well aware of the irony of referencing Bioshock (which premiered on the 360) in this article.  But as a friend of mine said, it is the exception that proves the rule.

But wait!  What about Sony?  Aren't they a big profit maximizing corporation as well?  I would not even consider trying to argue that Sony is not also a "big evil company".  I would also not dream of trying to support the unsupportable position that the Playstation platform has not prominently featured some huge, big money game productions (just look at the numbers for the Final Fantasy franchise).

What Sony does have, however, is a proven track record.  They have a long history of delivering a wide range of diverse titles that constantly push the envelope on game inspiration, game play, etc.  They have done this for decades while being a huge corporate entity the entire time.

Microsoft has no such track record, not yet anyway.  Even for a heavily biased guy like me they could still win me over by building such a track record, but they failed to do so with the original Xbox and with the exception of some home-brew initiatives they have going (which I consider a different issue) I haven’t seen them heading in that direction yet.

My concerns about games in the hands of Microsoft can be summed up nicely by quoting Steve Jobs: "Microsoft isn't evil, they just have no taste".  They can make software that works.  They can even make powerful software.  But rarely is their software graceful, elegant, or a pleasure to use.  Their products are competent and commercially successful, but rarely are they inspired or creative.

As a friend of mine pointed out these criticisms only directly apply to the design of the Xbox consoles themselves and Microsoft's first party titles.  He went on to say that third party game studios could decide to release their creative and artistic games on the 360; there's nothing about the platform that precludes innovation.  To some extent, however, Microsoft does create the gamer culture for their systems by the way they do their marketing and by the tone of their first party flagship games.

Ok, so Microsoft sets the tone for their consoles, but is that enough to explain why it feels like there are Xbox-style games and Playstation-style games in the world?  At this point we come back to culture.

Based purely on sales numbers it is clear that the Xbox is an American system.  It is a poor last-place seller in Japan.  Europe is a much closer race, but parts of it (as in some European countries) have the Xbox soundly last.  Only here in America is the Xbox clearly ahead in sales.  Is this somehow significant?  If American gamer culture is different, is that because of American developers, or American gamers, or both?

My guess is that Americans in general have the same broad range of interests as Europeans and Japanese do, but that fewer of these demographics play games here in the US.  Gaming is simply less culturally accepted here.  It is still largely perceived as a pastime for young males.  So would it be surprising to discover that Microsoft's money making formulas are based on less varied demographics than what we might find in other parts of the world?

Sony's history of being all over the map with their games, of constantly pursing innovation, may simply be a natural result of trying to peg and please a much wider range of gamer demographics.

At the end of the day it is simply not a simple issue.  I am left with trepidation regarding a Microsoft gaming console of any generation.  As you can see these reservations are not based on lists of games, they are not based on a comparison of consol features.  I do not even need to consider exclusive titles or killer apps.  Rather my onions come from a complex lattice of economic and cultural considerations and, of course, history.

Feel free to prove me wrong one day Microsoft.  In all honesty, I hope you do.  There was a time long, long ago when I was not even aware that a console called the "Playsation" even existed.  That consol long ago worked its way onto my radar and eventually convinced me to buy one based purely on compelling content that I did not see anywhere else.  I will make every effort to give Microsoft the same opportunity, but so far they have failed to impress me.

-Todd

Currently rated 4.0 by 34 people

  • Currently 4.029412/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Gaming
Posted by toddm on Sunday, January 20, 2008 10:10 PM
Permalink | Comments (47) | Post RSSRSS comment feed

Windows Mobile 5 MSI Installers With CF2

I’ve recently jump through a number of hoops to put together an MSI install package for a Mobile 5 application that uses the Compact Framework 2.0. The goal was to provide a single file installation that includes the CF2 install CAB and the CAB for our application.

Microsoft actually provides a very helpful MSDN article on "Deploying .NET Compact Framework 2.0 Applications with .cab and .msi Files" ( http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/deploy_cf2_apps_cab_msi.asp). There are just a few things I’d like to add from my own experience.

1. Making your installer wait for ActiveSync to finish.

Part of the custom installation code you will be writing for the MSI is code to launch ActiveSync to have it deploy the various CAB files out to the connected device. The MSDN article provides good sample code for this. The only problem I see with the sample code is that it fires off ActiveSync and returns immediately. What this means is that your MSI desktop installer process will finish and say it’s done with the installation before ActiveSync has actually deployed to the device.

The fix for this is very simple. After launching ActiveSync simply wait for the process to exit. In C# this would look something like this:

System.Diagnostics.Process p = 
        System.Diagnostics.Process.Start({exe}, {args});
p.WaitForExit();

In C++ it takes a few more lines of code, but what you’d want to do is make a call to CreateProcess() filling in a PROCESS_INFORMATION structure. Then make a call to WaitForSingleObject(). As a note, I was unable to get CreateProcess() to work correctly until I gave it NULL for the exe and simply passed in the entire command line via the command line argument.

2. Getting the installer to correctly deploy CF2 and then your own CAB.

In the MSDN article we are told that the INI file used to register an application CAB with ActiveSync can contain multiple CAB files on the "CabFiles" line.

"Line 7 enumerates all of the .cab files that are used for this installation in a comma-separated list."

This may work for installations that do not require a reboot of the mobile device, but I was unable to get this to work for deploying CF2, rebooting, and the deploying our application CAB. The solution I found that works quite nicely is to actually launch the ActiveSync process once for each CAB to be installed. So, in my case I created two different INI files (one for each CAB) and then in my custom install code I simply sequentially launch ActiveSync twice (once for each INI file). So, my custom install code runs ActiveSync to deploy the CF2 CAB, waits for the process to finish, and the runs ActiveSync again to deploy our application CAB.

3. C#, C++, and desktop dependencies.

The last quark I had to muddle through involved making sure that our MSI installer did not create additional dependencies on the desktop computer. The MSDN article provides all sample code in C#. If you code your custom install actions DLL in C# you will be building a dependency on the .NET Framework into your installer. In order to run the installer the end user would be required to download all 20 some-odd megabytes of the .NET Framework first!

So, I coded my DLL in C++ using the C# sample code as a guide. Unfortunately, I built my C++ code using Visual Studio 2005. Why is this unfortunate, you ask? Because C++ built in VS 2K5 uses version 8 of the CRT. Most machines will not have version 8, so VS 2K5 auto-detects this as a dependency and auto-includes the CRT v8 DLLs in your installer. Cool... but wait.

The CRT v8 DLLs are considered "system components" and are installed into the Windows system directories. Well guess what, only administrators can do that. So, now, probably without even knowing it, you have an MSI installer that can only be run by administrators and can only be installed for "all users".

The solution is simple enough. Build your C++ DLL in an older IDE (Visual Studio 2003 or Visual Studio 6 would work). You can then take the already-built DLL and do the rest of the installer work in Visual Studio 2005.

Good luck with those MSIs!
-Todd

Currently rated 3.0 by 2 people

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by toddm on Saturday, October 28, 2006 6:13 AM
Permalink | Comments (0) | Post RSSRSS comment feed

"Minimize Size" can be BAD

Here's a handy tidbit for anyone using Visual Studio 2005 to build C++ DLLs for Windows Mobile 5. I'm working on a DLL and I've written a small C++ test harness using LoadLibrary(), etc. I was seeing some VERY odd behavior while stepping through the code in the debugger. The symptoms seemed to suggest that the code I was seeing on the screen and that I was visually stepping through was different or out of sync with the code that was actually running.

I pulled my hair out over this for a bit, doing cleans, deleting everything in site, making SURE I was loading the version of the DLL I was building, etc. One earlier symptom was an inability to even step into the DLL calls at all! In the end it turned out to be a problem caused by a compiler flag I had changed. Because the DLL is targeted for download to Mobile devices I'm trying to make it very small. So I had right clicked on the project, selected "Properties", selected "Configuration Properties" -> "C/C++" -> "Optimizations", and changed the "Optimization" setting to "Minimize Size (/01)".

It would seem that this plays havoc with the debugger. It's a very handy option for cutting down on the size of your compiled C++, which can matter if you want to target an app for wireless download to mobile devices. For development and debugging I've set the option back to "Disabled (/0d)". This allows the debugger to correctly step through the code, hit breakpoints, etc.

-Todd

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by toddm on Thursday, September 28, 2006 7:01 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Unhandled Exceptions. The first code you should always write...

You can find a large number of references on line talking about unhandled exceptions in the .NET Framework 2.0 and registering for the UnhandledException event. I would like to first, point out that this event is available in the Compact Framework 2.0 as well and second, recommend that the first thing you should do in any project is register for it.

In a standard Windows app the code would look something like this:

namespace YourNamespace {
    static class Program {
        [MTAThread]
        static void Main() {
            AppDomain.CurrentDomain.UnhandledException += 
                new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
            Application.Run(new YourAppForm());
        }
        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
            // Log the exception here
            MessageBox.Show(((Exception)e.ExceptionObject).Message, "ERROR");
        }
    }
}

In my opinion, it is a good idea to do this early on in a project (if not first thing). Eventually most projects of any size will end up with situations that muddle the normal chain of exception propagation. Dialog windows, multi-threaded behavior, exceptions not derived from Exception, or just "incorrect" code on your part are just a few things that can confuse exception cases. By handling the UnhandledException event you can guarantee that you maintain an iron grip on exception awareness and ensure that you are logging valuable failure information. As we all know "silent death" sucks.

-Todd

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by toddm on Monday, August 28, 2006 6:39 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Windows Mobile 5, CF1, and the camera dialog

So, you're coding a Mobile 5 app that uses Microsoft's canned camera dialog (because let's face it, DirectShow is not much fun), but you want to do most of your work in Compact Framework version 1 (let's all thank Microsoft for not shipping CF2 in time to be included with most mobile devices). Well, this can easily be done with a small amount of C++ code and a bit of interop.

The first thing you need to know is that, although Microsoft didn't get CF2 onto most Mobile 5 devices, they DID get that Camera Dialog in there. So the camera dialog is actually available on all Mobile 5 devices (as far as I know). The next thing you need to know is that the Win32 function you'll need is called SHCameraCapture(). This function is well documented in the MSDN libraries, etc.

The general approach to take is to code up a small C++ DLL to make the SHCameraCapture() call. You'll likely want to wrap the call in your own C++ DLL to simplify the interop calls from CF1. Beware the limitations of interop marshaling in CF1, CF2 interop is MUCH nicer. Here is a bit of sample code that might resemble a couple of the entry points in such a DLL:

//---------------------------------------------------------------------------------------------
extern "C" SCANRCAMERA_API WCHAR* fnCameraCapture(
    WCHAR* szInitialDir, WCHAR* szDefaultFileName, WCHAR* szTitle, int iWidth, int iHeight)
{
    WCHAR* szResultImagePath = new WCHAR[MAX_PATH];
    memset(szResultImagePath, '\0', MAX_PATH);

    HRESULT hResult;
    SHCAMERACAPTURE shcc;
    ZeroMemory(&shcc, sizeof(shcc));

    shcc.cbSize = sizeof(shcc);
    shcc.hwndOwner = GetActiveWindow();
    shcc.pszInitialDir = szInitialDir;
    shcc.pszDefaultFileName = szDefaultFileName;
    shcc.pszTitle = szTitle;
    shcc.nResolutionWidth = iWidth;
    shcc.nResolutionHeight = iHeight;
    shcc.Mode = CAMERACAPTURE_MODE_STILL;
    shcc.StillQuality = CAMERACAPTURE_STILLQUALITY_HIGH;

    // Display the Camera Capture dialog.
    hResult = SHCameraCapture(&shcc);

    if(hResult != S_OK) { return(NULL); }
    wcscpy(szResultImagePath, shcc.szFile);
    return(szResultImagePath);
}

//---------------------------------------------------------------------------------------------
extern "C" SCANRCAMERA_API void fnFreeMemory(void *p) {
    delete(p);
}

You will likely notice the odd "free memory" method my DLL is exposing. This is my favored way to make sure I'm dealing with allocated memory correctly while interoping from CF1. It's best to try not to leak too much memory while haphazardly bouncing back and forth between managed and unmanaged code. This will make more sense after having a look at the sample C# code that uses this DLL.

// Import the DLL entry points
[DllImport(@"CF1Camera.dll")]
public static extern IntPtr fnCameraCapture(
    String initialDir, String defaultFileName, String windowTitle, int imageWidth, int imageHeight);

[DllImport(@"CF1Camera.dll")]
public static extern void fnFreeMemory(IntPtr p);

// At some point later use your DLL
IntPtr imagePathPtr = fnCameraCapture(@"\Temp", "test.jpg", "Camera DLL Test", 800, 600);
if(imagePathPtr == IntPtr.Zero) {
    int win32ErrorCode = Marshal.GetLastWin32Error();
    throw (new ApplicationException("fnCameraCapture() failed. Error code: " + win32ErrorCode.ToString()));
}
string imagePath = Marshal.PtrToStringUni(imagePathPtr);
fnFreeMemory(imagePathPtr);

And there you go. You've just used the pre-packaged camera dialog to capture an image from CF1. Like I say, PInvoking from CF2 is a lot nicer. You could work your way through doing a direct PInvoke to SHCameraCapture() from CF1, but I found this approach to be much easier.

-Todd

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by toddm on Friday, July 28, 2006 6:56 AM
Permalink | Comments (1) | Post RSSRSS comment feed