Tuesday, 13th September 2005
This is going to be a very boring update, I'm afraid. I wasn't feeling too good so haven't got much done.
First of all, Latenite updates. With the project thingummy, I thought it would be nicest if it displayed the proper Windows icons for file types rather than the ones I had hardcoded in. Here is a function I wrote to take a filename and return an icon (in the form of a .NET Bitmap) based on it and whether you requested a large or small icon.
It works by going into the registry and looking up the ".ext" key. Some keys like that contain a DefaultIcon property and a filename/index number of the icon to use, some just point at another subkey with that DefaultIcon property.
After I found that, I use the rather nasty ExtractIconEx to retrieve icon pointers from the DLL/ICO/EXE, select the one I want, copy that to an Icon (and then to a Bitmap) then clean up.
Here's a screenshot of it in action:
You'll notice the crud around the final icon. It seems that any XP-style icons with an alpha channel get mucked up by the ExtractIconEx ripping out the icon's data. If possible, I would force it to retrieve the 256 colour version (at 16x16, that's still a colour for every pixel!) but don't possess enough Win32 wizardry to achieve this. If anyone could help me, I'd really appreciate this.
Here is the module, in case someone finds it useful. Sorry if it appears a bit hacky, but it seems to work fine for me.
Module mdlIcons Private Declare Function ExtractIconEx Lib "shell32.dll" Alias "ExtractIconExA" (ByVal lpszFile As String, ByVal nIconIndex As Int32, ByRef phiconLarge As Int32, ByRef phiconSmall As Int32, ByVal nIcons As Int32) As Int32 Private Declare Function DestroyIcon Lib "user32.dll" (ByVal hIcon As Int32) As Int32 Function getIconFromFilename(ByVal filename As String, ByVal largeIcon As Boolean) As Bitmap ' Grab the extension: Dim getExtension() As String = filename.Split(".") ' Look up the file type: Dim searchKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey("." & getExtension(UBound(getExtension)), False) ' Was anything found? If searchKey Is Nothing Then Return Nothing ' Go through until you hit the end: Dim getDefaultIcon As Microsoft.Win32.RegistryKey Do getDefaultIcon = searchKey.OpenSubKey("DefaultIcon", False) If Not (getDefaultIcon Is Nothing) Then Exit Do searchKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(searchKey.GetValue("")) If searchKey Is Nothing Then Return Nothing Loop ' Get the details: Dim fileDescription As String = searchKey.GetValue("") Dim iconPath As String = getDefaultIcon.GetValue("") ' Close the registry keys: getDefaultIcon.Close() searchKey.Close() ' Now we have that data, we need to convert a "xxxx,0" path into a "xxxx" and a "0" Dim getPlainIconDetails() As String = iconPath.Replace("""", "").Split(",") Dim iconIndex As Integer = 0 Dim plainIconName As String = getPlainIconDetails(0) For i As Integer = 1 To UBound(getPlainIconDetails) - 1 plainIconName &= "," & getPlainIconDetails(i) Next If iconPath.Replace("""", "").ToUpper.EndsWith(".ICO") Then If UBound(getPlainIconDetails) <> 0 Then plainIconName &= getPlainIconDetails(UBound(getPlainIconDetails)) Else iconIndex = Val(getPlainIconDetails(UBound(getPlainIconDetails))) End If ' Now we have all that info, let's grab the icon: Dim iconLarge As Int32 Dim iconSmall As Int32 If (ExtractIconEx(plainIconName, iconIndex, iconLarge, iconSmall, 1) > 0) Then Dim iconPtr As IntPtr If largeIcon = True Then iconPtr = New IntPtr(iconLarge) Else iconPtr = New IntPtr(iconSmall) End If Dim iconRes As Icon = Icon.FromHandle(iconPtr) Dim returnBitmap As Bitmap = iconRes.ToBitmap iconRes.Dispose() If iconLarge <> 0 Then DestroyIcon(iconLarge) If iconSmall <> 0 Then DestroyIcon(iconSmall) Return returnBitmap Else Return Nothing End If End Function End Module
The C# source code I saw that used the ExtractIconEx call used ExtractIconExA instead of ExtractIconEx. I thought that this meant that A = alpha, so hopefully swapped the A in but VB.NET complained with a squiggly blue line. If only Win32 was as easy as that.
As far as Fire Track itself goes, there's nothing to really show for it - if you die, the game continues for a short way (with you invisible and uncontrollable) before decrementing your lives by one and sticking you back at the zone info screen. When you press START you get stuck back in the game at your old position in the level and you start again.
As dull as that sounds, there is a lot of work going on to achieve that - namely swapping palettes and tilesets to RAM and ROM and back again as required.
Here's a silly pair of screenshots. I played around with some of the more interesting VDP mode bits last night, and this is the "sprite zoom" one. By changing a couple of lines of the sprite routines with .ifdef blocks I can now set a switch in my config.inc file before compiling and all sprites are double size. Not sure why one would want to do that, but it's nice to know that the option is there.
Finally, here are some old shots I could have shown in here a while back - I thought I'd teach myself some OpenGL, what with SDL just sitting around doing nothing much for me.
As ever, click for bigger. Yep, it's the generic starter app of a terrain engine. (The Perlin noise for heights was new to me, I'd only used a precalculated one from Photoshop before). I couldn't quite work out how to do ambient lighting, hence the black sides to the hills. Not to mention that the tiling of the ground texture is blatently visible. The water moves up and down slowly to "wave", and the entire water texture scrolls past slowly.
I wish those shots were "real" - in face, there are two major flaws in my engine. First up is the very poor culling for terrain chunks outside the view - it's purely 2D, so looking down at the ground looks like this:
...which isn't quite right. I also had to tweak the LOD calculation for the above shots - here it is with the LOD tuned the other way;
Lots of nasty holes. I couldn't quite work out the skirting myself, so consigned the project to the bins once again (as I do with about 49 out of 50 projects). It runs at ~150FPS in debug mode, which is something to be pleased with I suppose.
I will release Fire Track, though. I hope. If someone could help with the music.
Lost projects... now there's an idea for a Lounge thread. I think I'll spare that by posting a few in my journal instead. Some of these started out as Really Good Ideas at 3AM when I couldn't sleep, but never seemed to get anywhere:
Album Art Viewer - for those covers that Windows Media Player displays, which Windows Explorer hides.
WAD Reader - DOOM WADfile reader/viewer. Has support for all graphics ("pictures" and raw flats), DOS end screens, PC speaker sound effects. Can view pictures in special viewer where you can rotate the sprites or watch their animations (it has to guess a lot, so that's not perfect). Can export all lumps as raw data or convert to PNG (graphics) or RTF (DOS end screens). Can also play the PC speaker (not wave) sound effects if your PC has a PC speaker on the motherboard. VB.NET, but quite fast. Full screen pictures take about 2 seconds to render as properly, though. However, once rendered all are cached internally for instant retrieval.
Lemming Syndrome - (click to download 194KB file, requires .NET runtimes) - wow! I forgot about this one. It was meant to be for the 1W1B contest - a challenge to work on a game for one week, with the requirement that you only used one button to control it. So, er, try and bounce me over the river in your lifeboat. There is no "game", as such, (unfinished), so it'll go on for ever.
MySQL Manager - I was feeling cheap and my trial to MySQL-Front was about to expire, so I started work on a MySQL clienty thing. It's massively faster at downloading/displaying data, but that's about all it actually does after I decided it was too much hassle to try and recreate a full tool, so I forked out for a license of MySQL-Front instead.
Anyway, this is scaring me, I just found a garishly coloured TETRIS.EXE that I swear I never wrote, but the code style is mine and it has my name on it, so I guess I actually did... I have been feeling a bit ropey for the last year-and-a-bit, so I guess it slipped my radar. Or I wrote it in my sleep. Or something. Just be glad I don't have an internet connection myself and have to rely on one at work, so you're safe from me posting in my sleep!