Tuesday, September 2, 2014

SDL 1.2: "Failed to initialize video: No available video device"

I recently helped a person wanting to run cndoom 2.0, a fork of Chocolate Doom 2.0 geared towards speedrunners, but who was prohibited from doing so as the program would silently crash on startup (the only information I have is that it concerned a Windows 8.1 machine with latest drivers and DX versions). Only a cryptic error message was logged in a log file ('Failed to initialize GUI'). With a little help from acquaintances I managed to get a hold of a copy of the source code for cndoom 2.0 (usually kept secret to ensure security from speedrunners) and found out that this error occurred in InitTextscreen (src/setup/mainmenu.c) due to a call to TXT_Init (textscreen/txt_sdl.c). The takeaway, however, was that SDL_Init and SDL_InitSubsystem would fail (cndoom uses SDL 1.2). This is pretty strange behavior; I've never seen SDL fail at SDL_Init before.

After some poking around in the source code I deduced that SDL, or maybe cndoom, failed to detect a video driver and then failed to set a fallback driver (in SDL, the driver is detected via the SDL_getenv function). Using the SDL documentation as reference, I found that, under Windows, there are two drivers that can be used; windib, and directx. Just as I was about to force the video_driver environment variable via SDL_setenv, the person experiencing the problem detected that the cndoom configuration file (chocolate-doom.cfg or cndoom.cfg) had a parameter named video_driver that was left blank (intentionally, to let SDL automatically detect the appropriate driver). However, SDL still fails to find a driver when left to its own volition.

The solution, as it would seem, was to provide the video_driver parameter in the configuration file with windib as the value (inside the provided quotation marks). directx as the value, however, would cause SDL to fail.

So, where does the issue lie? I honestly do not know, but there are a list of suspects:

1) cndoom is mucking around in the environment variables and overwriting them, then failing to handle a rare contingency (see I_InitGraphics function in src/i_video.c). The thing that speaks against this is that directx as video_mode value causes the program to crash. Maybe cndoom does not expect directx to fail?

2) SDL 1.2 can't properly detect DirectX on some newer machines. Then SDL fails to default back to windib if directx fails.

3) Windows 8.1 does not set up environment variables for its drivers in rare cases. There might also be a change in environment variable naming policy?

4) User error. A likely case, although a case I have no information about.

If I could detect the source of the error I could file a bug report, but seeing as I did not experience the issue first-hand that makes matters difficult.

If the application you are trying to run fails in a similar manner to cndoom, but no video_driver parameter (or equivalent) is available in any configuration file I believe the issue can be resolved if you have access to the source code. Simply make a call to SDL_setenv and provide the appropriate values before (using this as reference) the call to SDL_Init and compile.

TL;DR

If an SDL 1.2 application crashes silently (or giving a 'No available video device' error), try finding a configuration file and entering an appropriate value for the video driver parameter (for Windows I believe windib is as failsafe as you can get). If no such configuration file or parameter exists you will need access to the source code and make a call to SDL_setenv (with an appropriate value for the video_driver parameter) before SDL_Init.