Monday, December 29, 2008

List your HWNDs

For Win32 GUI debugging I'm usually using WinSpector (I highly recommend it), but as it turns out WinSpector doesn't display owner windows (or maybe I just can't find it).

I was debugging a foreground activation error when the application was running through Citrix. As it turns out in certain combinations of Citrix clients and Citrix server registry setting, the windows ownership on the client is different than on the desktop.

I highly doubt this will be useful to anyone else but me, but here it goes anyway: lshwnd - program for listing all HWNDs, their parents and their owners.

#define UNICODE

#include <windows.h>
#include <vector>

wchar_t name[1000];

BOOL CALLBACK myEnum(HWND hwnd, LPARAM lParam)
{
 std::vector<HWND> *windows = (std::vector<HWND>*)lParam;
 windows->push_back(hwnd);
}

void enumerate(HWND hwnd, int depth)
{
 std::vector<HWND> windows;
 EnumChildWindows(hwnd, myEnum, LPARAM(&windows));
 GetWindowText(hwnd, name, 1000);

 for (int i = 0; i < depth; i++)
  wprintf(L"    ");
 
 wprintf(L"%x:%x - %s\n", hwnd, GetAncestor(hwnd, GA_ROOTOWNER), name);

 for (int i = 0; i < windows.size(); i++)
 {
  enumerate(windows[i], depth+1);
 }
}

int main()
{
 enumerate(NULL, 0);

 return 0;
}

Usage is quite easy, you start

lshwnd.exe > hwnd.txt
and you will get a list of all your HWNDs in a tree structure according to parent child relationship. Every HWND is represented as

parent:parent_owner parent_window_title
 child:child_owner child_window_title

Relationship structure

Version for download lshwnd.zip - 11 kB

Friday, December 26, 2008

Snooping on TCP connections - Putting the MAN in the Middle

It's quite often when debugging a networking application, that you have to look at the underlaying data. You might say, this is very easy with existing tools like tcpdump and windump. But let's say you have to do it on a remote server without admin rights. Suddenly the task is not so easy.

You can usually get away with telnet in case you need to simulate the client or more preferably netcat (where you can simulate the server as well). However sometimes you just want to watch the communication between two endpoints.

You basically need a tunnel, that will forward all communication and simultaneously write all the data to file / screen.

I wrote a little program for that, it's called middleman and it saves all communication in files. New file is created for every connection and raw data from both endpoints are written into this one file. If the protocol, you will be monitoring is hard to understand, you can modify the program to split the communication into two files, the program is quite simple, so it shouldn't be much of a problem:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

class Client
{
 int id;
 TcpClient local;
 TcpClient remote;
 NetworkStream localStream;
 NetworkStream remoteStream;
 FileStream file;

 public Client(TcpClient newLocal, string remoteAddress, int remotePort, int nid)
 {
  local = newLocal;
  localStream = local.GetStream();
  remote = new TcpClient(remoteAddress, remotePort);
  remoteStream = remote.GetStream();
  id = nid;

  file = new FileStream("session_" + Convert.ToString(nid) + ".txt", FileMode.Create);
 }

 public void process()
 {
  int time = 0;
  int i;
  Byte[] bytes = new Byte[4096];
  while(true)
  {
   if (localStream.DataAvailable)
   {
    if ( (i = localStream.Read(bytes, 0, bytes.Length)) != 0)
    {
     try 
     {
      if (remoteStream.CanWrite)
      {
       remoteStream.Write(bytes, 0, i);
       file.Write(bytes, 0, i);
      }
     }
     catch (Exception)
     {
      break;
     }
    }
    time = 0;
   }

   if (remoteStream.DataAvailable)
   {
    if ( (i = remoteStream.Read(bytes, 0, bytes.Length)) != 0)
    {
     try
     {
      if (localStream.CanWrite)
      {
       localStream.Write(bytes, 0, i);
       file.Write(bytes, 0, i);
      }
     }
     catch (Exception)
     {
      break;
     }
    }
    time = 0;
   }

   time++;

   Thread.Sleep(1);

   if (time > 5000)
    break;
  }
  remote.Close();
  local.Close();
  file.Close();
 }
}

class ManInTheMiddle
{
 static int Main(string[] args)
 {
  int localPort, remotePort;
  string localAddress, remoteAddress;

  switch (args.Length)
  {
   case 2 :
    remoteAddress = args[0];
    remotePort = localPort = Int32.Parse(args[1]);
    localAddress = "127.0.0.1";
    break;

   case 3:
    remoteAddress = args[0];
    remotePort = Int32.Parse(args[1]);
    localAddress = "127.0.0.1";
    localPort = Int32.Parse(args[2]);
    break;
   case 4:
    remoteAddress = args[0];
    remotePort = Int32.Parse(args[1]);
    localAddress = args[2];
    localPort = Int32.Parse(args[2]);
    break;
   default:
    Console.WriteLine("MiddleMan - Tool for snooping on TCP/IP connections");
    Console.WriteLine("");
    Console.WriteLine("Usage: middleman remote_server port");
    Console.WriteLine("Usage: middleman remote_server remote_port local_port");
    Console.WriteLine("Usage: middleman remote_server remote_port local_ip_address local_port");
    Console.WriteLine("");
    Console.WriteLine("");
    Console.WriteLine("MiddleMan starts listening as a server on local_ip_address (default 127.0.0.1)");
    Console.WriteLine("on local_port. All incoming connections to this server are forwarded");
    Console.WriteLine("to remote_server:remote_port and logged into a file.");
    Console.WriteLine("");
    Console.WriteLine("");
    return 0;
  }
  
  TcpListener server = new TcpListener(IPAddress.Parse(localAddress), localPort);
  server.Start();

  int id = 0;

  while(true)
  {
   Client client = new Client(server.AcceptTcpClient(), remoteAddress, remotePort, id++);
   Thread w = new Thread(new ThreadStart(client.process));
   w.Start();
  }
 }
}

The usage is quite simple, you specify the IP address or hostname, which you want to connect your tunnel to and the port

middleman www.google.com 80

From now on, all the communication that goes to localhost:80 will be forwarded to google:80 and will be simultaneously written to a file

In case you specify only one port (as in the example above), middleman will start listening on the same port as is the remote server listening on (in this case 80). If for whatever reason you can't use the same port on the local machine, you can start middleman like this:

middleman www.google.com 80 81

which means - forward all requests from localhost:81 to google.com:80

Simple demonstration video follows:

Download middleman.zip - 6kB

Obligatory thanks to Mark James for creating the amazing Silk icons.

Wednesday, December 24, 2008

Ludum Dare 2008

The theme of this year's Ludum Dare competition was "Roads". So how did I do?

The game

Here is a video from my game

and the game itself Chopper vs Trucks 3 MB

The Backend

In the beginning I wanted to use Lua to define the game logic, but I found out, that it's not easy to integrate OPP with Lua, so I wrote the whole logic in C++. But I definitely want to investigate Lua integration with C++ further to use it in my following projects.

What really paid of was my one-click deployment system. I was running a webserver on my development PC and every time I wanted to test something I made a release:

7zip a -r -x!.\* /$(RELEASE_DIR)/angiine.release/angiine$(DATE).7z $(ANGIINE_DIR)
cp /$(RELEASE_DIR)/angiine.release/angiine$(DATE).7z /$(RELEASE_DIR)/angiine.release/angiine_current.7z

And on the target computer I had a batch file looking like this

wget http://server/angiine_current.7z
7z x angiine.current.7z
cd angiine/bin/
./angiine

The whole cycle "recompile, package, download, unpack and start" took about ten to fifteen seconds. I was able to test the game on two different computers almost seamlessly and I can't recommend this hard enough.

For real masochist you can check you all the versions of the game I managed to produce during the 48 hours - angiine.releases.7z 4 MB

The Progress

During the compo, I spent quite some time on loading 3D models to my C++ program. I should have prepared my base library and not waste my time with this during the competition time.

Here are some progress screenshots of the game:

Progress screenshot #1 Progress screenshot #2 Progress screenshot #3 Progress screenshot #4 Final screenshot #1 Final screenshot #2

For more information, you can look at my almost award winning journal :) here

Statistics

For anyone interested, here is my timelapse

This is an overview of which programs I used the most during the competition:

Results

Overall32/59
Fun39/59
Innovation28/59
Theme42/59
Polish40/59
Graphics20/59
Audio42/59
Humor28/59
Technical12/59
Food28/59
Journal5/59
Towlr29/59
My best scores were in categories Journal (5th place - link) and Technical (12th place). I'm very happy about that, but I will definitely try to do better next time :).

So that was my Ludum Dare compo overview - I had extreme fun, I slept very little and after turning my game in, I got amazing sense of accomplishment. Kudos to the organizers, I'm already looking forward to the next one.

Tuesday, December 2, 2008

Preparing for Ludum Dare 2008 - Take multimonitor screenshots

It's part of the whole Ludum Dare experience to record your desktop every few minutes and create a movie afterwords which overviews your progress.

Since I recently became a proud owner of a second monitor, I found myself in need for a multi-monitor screenshot making tool. There are probably some utilities, which do exactly that, but I'm too lazy to look for them and decided to write my own tool.

This is just a very stupid prototype, which I will be using/testing during the competition. It doesn't save the files into one image but one image per monitor. That's kind of unfortunate, but composing picture from different DCs is no fun.

The other thing the program does is that it records which program was in foreground while you took the screenshot and records the data into sqlite database

So afterwards you can just start sqlite3 data.db and type in following command:

SELECT process, count(*) AS sum FROM work GROUP BY process ORDER BY sum;

You'll receive a nice overview about which application you used the most during the competition / monitoring time.

Here you can see my relative application use in the past 10 months on my work computer:

I spend more than 50% of my time in firefox

I guess I'm researching a lot :)

So for anyone interested, the download is - logger-0.1.zip (300 kB)

Thanks to Mark James for creating the amazing Silk icons.

Monday, December 1, 2008

Preparing for Ludum Dare 2008 - Looking Back at my 48 Hour Compos History

As many young programmers I actually got into programming by writing games (or more precisely by trying to write games :) ).

In past years I've been constantly programming one game or another, not really finishing one, but often jumping to different project whenever new idea/technology came along.

Therefore I always liked the idea of 48 hours game programming competitions. You have to create a game according to some theme within one weekend. You have to create everything from scratch - the code, the graphics and the sounds. Although it might seem like a very short time and very limiting, it's quite the opposite. I've never found myself as concentrated, motivated and productive as within these weekends.

Due to Real Life™ I actually managed to finish a game just once out of my three tries. However I'm dedicated to finish a game in Ludum Dare 2008, which takes place this weekend.

But before I can start preparing for this years competition, I have to take a look at the past

Ludum Dare 2004

This was my first 48hrs competition and it was a blast. Also this is the only competition, I actually managed to finish a game.

The theme was Infection, the name of the game was "Awesome Adventures of Superhand" and I'm going to let one fellow competitor summarize my game:

philhassey: I liked the hand marching around kicking stuff :)

That was actually one of the nicest reviews I got and to this day, I'm extremely proud of it.

I'm fairly confident, that I had the smoothest walkcycle in the whole competition. I simply took my digital camera, recorded a short video of my hand walking around against a sheet of white paper and then processed it into a walkcycle. I had the animations for my character finished in about two hours.

SuperHand walking around and kicking stuff in the park

Unfortunately I decided for resolution of 800x600, which is a lot of pixels to draw. So I spent quite a lot of time drawing background - sky, trees, road and trying to make them look as good as possible.

The game had tons of problems - it would crash on startup on some computers, wouldn't run without sound card (forgot to test for lack of it), the speed of the game was driven by framerate, the difficulty was too hard, etc. But all in all, I finished a game in two days and that's all that matters to me :).

SuperHand walking around and kicking stuff in the street

An unexpected thing happened about two hours before deadline. The game was playable, the gameplay was reasonably fun and there weren't any bugs I was aware of - the game was finished. I felt an overwhelming sense of accomplishment. I felt I could do anything. In about twenty minutes I created a menu.

Awesome adventures of Superhand Menu Screen

And in another ten I created an intro screen. I was on top of my productivity and I was certain, I will be able to add any feature I could think of.

Awesome adventures of Superhand Intro

But I didn't think of anymore features, I just played the game over and over and basked in the newfound sense of accomplishment and it was awesome.

TINS 2005 (TINS Is Not Speedhack)

A year later a TINS competition came by and I had no other option than to sign up. The competition archives are located here

  • artistic genre: parody
  • artistic rule: give the player something to Unlock
  • artistic rule: trolls are cool, have a troll in your game
  • technical rule: make clever use of sine waves

Although I'm no pixel artist, I was actually able to come up with some sprites within a reasonable time frame. The idea of the game was a troll working in big corporate company. It would have been a little adventure/platform shooter.

I fell ill before I could come up with a clever use of sine waves, but I figured, that the enemy would be simply shooting them or something. Not really clever, but hey, my main character is a troll :).

Troll in the office

Some of troll's actions

Troll actions

and walkcycle and gruesome death of an enemy

Enemy walking and dying

Unfortunately I fell ill during this competition, so I couldn't finish.

But the good thing was that I started to work in 320x200 resolution - lot less pixels to cover and it has this cool retro look to it.

Ludum Dare 2006

The theme for this competition was "Swarms". This time I decided, that it's finally time to learn some OpenGL, so I started writing my game in 3D without any previous knowledge.

The idea was, that you will be a gravitation centre of a particle swarm and you will be travelling in a tube with a lot of obstacles. The center will be able to exert gravity on all the particles and pull them towards itself.

To my surprise I was actually able to pull the 3D off, what I didn't managed was Real Life™, awesomeness of gravity and 3D collisions. The collisions took so much time to fake right, that it would probably be faster to implement them for real.

Swarming 1

When I implemented gravity, the "game" became so interesting, that I spend couple of hours just chasing particles on the screen. I would move the gravity there and back just to watch the particles speed up, get pulled in different direction, rotate, slow down etc.

This point is quite critical for all my game projects. As soon as my game is playable and provides the tiniest amount of challenge/fun, I get completely hooked and play it over and over.

Swarming 2

I can imagine it happens to other programmers as well, because it's your own creation, that you are playing, but for the future successes in 48hr competitions I should avoid this habit :).

Learnings

So what did I learn from the past:

  • Buy a lot of oranges, so that you don't fall ill
  • DO NOT PLAY YOUR GAME
  • Choose a low resolution
  • Choose wisely between 2D and 3D
    • 2D is hard
    • 3D is harder
    • sprites are a lot of work
    • 3D models are easy to create, move, rotate and to scale
  • Have a distribution channel in place, so that your friends can test your game without any effort from your side (script that automatically uploads your game somewhere, etc). This is tremendous help and if it's automated it's tremendous time saver.