Draggin the marbles around, DirectDraw, Part 9

You could sure use some mouse input with the marbles. Remove the timer stuff from the DDEX3 program that we modified and add handling for WM_LBUTTONDOWN, WM_LBUTTONUP and WM_MOUSEMOVE messages in the WindowProc() function. You will need to add some code to find out if WM_LBUTTONDOWN was on the marble and then move the position of the marble relative to its last position whenever you get WM_MOUSEMOVE message.

 

Here is a video of it:

 

 

If you run this in debug mode you can notice considerable lag because it runs over the debugger. The video here shows the application running normally, i.e. I select the program to "Start Without Debugging" (ctrl + F5).

Combining the pieces, DirectDraw, Part 10

Hi there! What do get when you combine this and this? Well, maybe a game called Crash Marbles? ;)

 

Anyways, game is still pretty far off but here is a video of the result:

 

 

Well, the basic concept of the "would-be" game revolves around the player having to dodge the evil marbles and also collect the powers that show up randomly on the screen. I am still thinking about how to make the game more interesting and entertaining. Don’t bother about the score that shows in the top left, its still work in progress ;)

A glitch corrected, DirectDraw, Part 11

In part 8 of this series of posts on DirectDraw, I had mentioned that there still seems to be a minor problem with the program. Read the "Note" section at the end of the post. The problem now has been solved.



Recap

The problem was that even after calculating the new positions for the marbles, the marbles would still be overlapping because of the approximations that we use. And this would sometimes repeat many times over which creates the problem.



Solution

The fix that I’d said in the "Note" section works well. After calculating the new position for the marbles you check again if they collide. And if they do then adjust their positions so that they don’t overlap anymore. Every time I move the marbles 2 pixels away from each other and check the distance again. And repeat this until they are no more overlapping. Here is the code:

     MinDistance = ball1->radius + ball2->radius;

    dxx = ball1->xPos – ball2->xPos;

    dyy = ball1->yPos – ball2->yPos;



    //calculate new distance between marbles

    distance = sqrt(dxx*dxx + dyy*dyy);

    printf("COLLISION: New Distance:%d \r\n", (int)distance);



    //this part makes sure that the new positions of the marbles are not overlapping

    //sometimes the new position itself overlaps and that leads to weird behaviour

    //check if the marbles are overlapping

    if ((int)distance <= MinDistance)

    {

        //adjust their positions

        do

        {

            if (ball1->xPos > ball2->xPos)

            {

                ball1->xPos += 1;

                ball2->xPos -= 1;

            }

            else

            {

                ball1->xPos -= 1;

                ball2->xPos += 1;

            }



            if (ball1->yPos > ball2->yPos)

            {

                ball1->yPos += 1;

                ball2->yPos -= 1;

            }

            else

            {

                ball1->yPos -= 1;

                ball2->yPos += 1;

            }



            dxx = ball1->xPos – ball2->xPos;

            dyy = ball1->yPos – ball2->yPos;



            distance = sqrt(dxx*dxx + dyy*dyy);



        }while((int)distance <= MinDistance);

    }

 

So the same set of values for xPos and yPos which used to create the problem before, now work fine.

Tools: Cellular Emulator and Fake RIL

Today I had the chance to fiddle with the cellular emulator and try a few things with it. Its a very useful tool to test out all your radio related applications (which use RIL directly or indirectly) without having the actual hardware.

Cellular emulator  is very well documented so I don’t want to repeat the same things here, for more information visit the following link:
http://msdn.microsoft.com/en-us/library/bb158495.aspx

In short, you can simulate MO/MT calls, send and receive sms’s and do data sessions as well.

And that is when I came across Fake RIL. Well, I had heard about fake ril before and had a fairly good idea about what it was but never truly had the chance to play with it. I dug down a little deeper today and found it amazing. Basically, as the name suggests, it is a fake ril driver which simulates the network too.  It is so well documented (it ships with AKU so I cannot shell out the docs here bacause of the NDA) and I really appreciate the idea and the brains that went behind designing it. Fake ril simulates the network and all the clients above can work as is, well, that was the whole idea in the first place (:

I had a windows mobile professional device so I thought I might try to make the device use Fake RIL instead of our customised ril which it was using. I built it into a dll and made the device load fakeril instead of the OEM ril driver that it was loading before.  When the device booted up it came up with full signal strength and that is when I noticed that there was no SIM in the device! It worked. I tried making calls and sending a few sms’s and it worked perfectly. When you make a call the call is automatically answered, and there are some special numbers which simulate busy, unanswered, reject etc. If you’ve read the above link you know already.This is a great way for some of our sibling teams to test their applications as there is no dependency on the radio hardware, waiting for the radio code to stabilize et al. I couldn’t try data session though. Will try it out next week.

Applications: Process Viewer update

I noticed that I hadn’t added the filename associated with the process in the Process Info section last time. It struck me when looked at the PViewCE sample, which I mentioned about in this post.

So I thought why not add the filename label, could anything else be simpler!

I edited the dialog to include another static text control and added the code in AllignComponents() to beautify the control. But a small hiccup, when I ran the program just to test if it was displayed correctly, it wasn’t to be seen. And then I remembered that the group box hides it. Darn, not again! So I went back removed the group control, added the static text and then added the group control back on. The control displayed correctly. Use GetModuleFileName() api to get the filename associated with the process.

WINAPI DWORD GetModuleFileName(HMODULE hModule, LPWSTR lpFileName, DWORD nSize);


The api takes the module handle for which the filename is requested, a buffer to hold the filename and finally the size of the buffer.

For hModule, you can pass the th32ProcessID member of the PROCESSENTRY32 structure after casting it to HMODULE.

Here is how I called the function in ShowProcInfo():

TCHAR filename[256] = TEXT("Unknown");

if(GetModuleFileName((HMODULE)pProcess->th32ProcessID, filename, sizeof(filename)/sizeof(TCHAR)))

{..}

Here are a few screen shots:

Cellular emulator, COM3 in use please verify

I was trying to set up the cellular emulator with the windows mobile emulator on my laptop when the cellular emulator spat out "COM3 in use, please verify". I knew it was another classic case of some application holding a port and another application failing because of it. Such problems are usually solved by changing the order of installing those application. To find a solution I binged around (yes! I bing :) and found this msdn forum link.



No surprise that many people had already gone through this. Had a hunch that one of my bluetooth services was holding down on that port. I had to find a way to make the cellular emulator use another port, so I went about searching the registry. While the search was going on, I was reading through the forum thread and it mentioned about bluetooth services holding down on a number of ports. I disabled my bluetooth device and then re-enabled it. And then when I opened Cellular Emulator, it came up on COM3. How in the world!



I guess my disabling and re-enabling of the bluetooth device must have somehow freed COM3. By that time I had reached the end of the thread and there was a solution suggested which involved changing your registry keys. Well, I didn’t have to do that.

Update: Next post.

Cellular emulator and Device Emulator, COM port issues

Well, it looks like the magic that made the cellular emulator come up on COM3 in my previous post was not long lived. Once the cellular emulator came up, I started the device emulator and tried to set the "Serial Port 0" of the emulator to COM3, so that the device and the cellular emulator can talk to each other and that is where it went boom! Threw a message saying something like, "Unable to open COM3, cannot find the file specified". All my efforts to fiddle with disabling and enabling the bluetooth services went in vain. I tried for about an hour scouring the net to find some info that could help me. I knew that uninstalling the bluetooth software from my laptop (WIDCOMM bluetooth stack) might solve the problem. But I was looking for a work around and saving me the trouble of a re-install. I tried to change the registry settings for the cellular emulator to make it use another port like COM8, COM9, COM10 etc but all failed. I either got "Access denied" or "cannot open file specified" error. And when I finally ran out of options I did uninstall the bluetooth software from my machine. Tried the device emulator, cellular emulator thingy and it worked. I could make incoming calls and send recieve sms’s. Then I installed the bluetooth software back on. Success! Both BT and emulators are working in harmony (:

Problems with UNICODE files and chinese characters

I was working on a XML parser that we had written some time back. We used Microsoft’s SAX (Simple API’s for XML) for parsing the xml. Here is a very useful and elaborate SAX tutorial. All was working fine until a few XML files with Chinese characters showed up. Well, basically the program revolved around:



–> Parse the input xml

–> do something with the parsed data

–> and create an output xml



The ouput XML, of course, depended on the data we parsed in step 2. The problem was that when the input XML contained chinese characters, our output XML would contain boxes! And this immediately reminded me of this post by Joel Spolsky. I checked the code and found what was wrong. I was reading the data into WCHAR from the input XML and while writing the data I converted it to a multi-byte string using wcstombs. Which obviously was incorrect. When the API tried to convert the chinese characters into multi-byte it went nuts! So I went ahead and changed the code, the changed code looked something like this:



WCHAR buffer[MAX_BUFF_SIZE] = L"";

WCHAR temp;

DWORD bytesWritten = -1, bytesRead = -1;



int counter = 0;



do

{
    //Read from the file and store in buffer

    if(ReadFile(hInputFile, temp, sizeof(temp), &bytesRead, NULL))

    {

        buffer[counter++] = temp;



        if(temp == L’\n’)

        {

            //got a line, do something with it

            ..

            ..

            WriteFile(hOutputFile, buffer, counter, &bytesWritten, NULL);


            //reset the counter for the next line

            counter = 0;

        }

    }



}while (bytesRead > 0);



After this I saw that a lot of things were missing in the output file! You can see the problem at first glance can’t you? The variable counter keeps track of the number of WCHAR characters, each of which is 2 bytes wide. In the call  to WriteFile(), the counter parameter specifies the number of bytes to write, so only half the data was getting written. The write file call should really have been:



WriteFile(hOutputFile, buffer, counter*sizeof(buffer[0]), &bytesWritten, NULL);



That fixed it. But there was still a problem, I was still getting boxes. What else could be wrong now! So I binged around a little and found out that the first two bytes in a unicode file must always be 0xFF 0xFE. Joel mentions this in his post on encoding schemes. The problem is that without the 0xFF 0xFE the text editor thought that it was a normal text file encoded in ANSI or something. Basically making the editor to process every byte of the data as an ANSI character and that turned all zeroes into boxes. 0xFF 0xFE told the editors to process them as UNICODE encoded files, thus making them interpret every two bytes of the file. I wrote the two bytes into the output file before writing anything else into it and it worked. The chinese characters showed correctly in the output file.

Why would the controls not show up!

A colleague of mine had a strange problem today. He had written a small UI application for a Windows Mobile Professional device with many controls. The controls contained several check boxes, text boxes, labels and buttons. When he ran the dialog using the "Run Dialog" option in Visual Studio, it showed up correctly and when the program ran on the device a strange thing happened. Some of the controls would show up and others would not.

It wasn’t random, the same set of controls showed up every time and others didn’t. The UI was divided into three sections each contained within a group box. I could imagine how strange he must have thought it to be. But it had already happened to me before. And when he asked me for help, I couldn’t help a smile (: If you had read this post carefully enough, you would have noticed a small remark on the group box that I had made. "Add these three static controls into a group box, name the group box "Process Info". Remember to create the three static text controls before creating the group box. I was trying the other way around, by creating the group box first, the text controls would not show up, they were hidden behind the group box." And that was the exact problem in this case too. He had added controls to the UI in a particular order, or rather, in no particular order. So all the controls added before the group box showed up correctly and others didn’t.



Update:

As Gato pointed out, this problem occurs because of the Tab order (also called z-order) of the individual controls. See the ‘Comments’ section below.

Lets do some graphics: DirectDraw, Part 1

I always wanted to do stuff with DirectDraw. And when I saw the iPhone UI the urge intensified. But somehow the topic seemed esoteric to me and eluded me for quite some time, or, to put it in other words, laziness won over me (:



Anyways, I was going through the Donuts sample game provided by Microsoft which comes with Win Mob 6 Professional SDK installation. Here is the path:



<InstallDir>\Samples\PocketPC\CPP\win32\directx\DDraw\Donuts2



It seemed a bit too complicated for a first timer and truly I was a held back a little. So I decided to go through some tutorials first  and stop trying to be superman (: This post is what I found. Its quite old and pretty basic but gives you good understanding of what things are and where they stand. Donuts started to make a little sense now (:



The post mentioned about a few samples like DDEX1, DDEX2 etc. and I saw that these were present in the same SDK directory. I was happy to have found a step by step tutorial for DirectDraw. But when I built and tried to run the samples on the emulator the applications failed with a message box saying "This device does not support backbuffers". Of course, you don’t have to be Einstein to figure that the emulator doesn’t support back buffers. Donuts was the only application that ran ): So I got back looking at Donuts’ code. I saw that they were handling the absense of a back buffer intelligently. They got the capabilities of the device:



    lpDD->lpVtbl->GetCaps(lpDD, &ddCaps, &ddHelCaps);



    if (!(ddCaps.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER) || !(ddCaps.ddsCaps.dwCaps & DDSCAPS_FLIP))

    {

        bSingleBuffer = TRUE;

    }



and depending on whether the device supported back buffers or not created other appropriate buffers/surfaces



    // Create surfaces

    memset( &ddsd, 0, sizeof( ddsd ) );

    ddsd.dwSize = sizeof( ddsd );

    if (bSingleBuffer)

    {

        printf("bSingleBuffer is TRUE\n");

        ddsd.dwFlags = DDSD_CAPS;

        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

    }

    else

    {

        printf("bSingleBuffer is FALSE\n");

        ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP;

        ddsd.dwBackBufferCount = 1;

    }



    ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpFrontBuffer, NULL );

    if (ddrval != DD_OK)

    {

        if (ddrval == DDERR_NOFLIPHW)

            return CleanupAndExit(TEXT("******** Display driver doesn’t support flipping surfaces. ********"));

 

        return CleanupAndExit(TEXT("CreateSurface FrontBuffer Failed!"));

    }



    if (bSingleBuffer)

    {

        ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;

        ddsd.dwWidth = ScreenX;

        ddsd.dwHeight = ScreenY;

        ddrval = lpDD->lpVtbl->CreateSurface( lpDD, &ddsd, &lpBackBuffer, NULL );

        if (ddrval != DD_OK)

        {

            return CleanupAndExit(TEXT("CreateSurface BackBuffer Failed!"));

        }

    }

    else

    {

        ddrval = lpFrontBuffer->lpVtbl->EnumAttachedSurfaces( lpFrontBuffer, &lpBackBuffer, EnumFunction);

        if (ddrval != DD_OK)

        {

            return CleanupAndExit(TEXT("EnumAttachedSurfaces Failed!"));

        }

    }



So this was interesting. I thought I could try to do the same for the DDEX1 sample. I played around with the code a bit; added handling for single buffer changed the Flip() api into Blt(), because that is what Donuts did



    while( 1 )

    {

        if (bSingleBuffer)

        {

            //copy back buffer to front.

            ddrval = lpFrontBuffer->lpVtbl->Blt( lpFrontBuffer, &dest, lpBackBuffer, &src, dwTransType, NULL );

        }

        else

        {

            ddrval = lpFrontBuffer->lpVtbl->Flip( lpFrontBuffer, NULL, 0);

        }



        if( ddrval == DD_OK )

        {

            break;

        }

        if( ddrval == DDERR_SURFACELOST )

        {

            if( !RestoreSurfaces() )

            {

                return;

            }

        }

        if( ddrval != DDERR_WASSTILLDRAWING )

        {

            break;

        }

    }



And voila! It worked (: It showed a screen flip flopping with blinking text. If you have gone through the tutorial above you probably know what Flip() and Blt() do. The only problem I ran into was, to the Blt() function I was passing "DDBLT_KEYSRC" as the second last parameter, and it wasn’t showing anything. I tried "DDBLT_KEYDEST" too but same result. So since the final parameter (a pointer to a structure) was NULL anyways, I passed 0 as the second last parameter. It worked.



You can check the documentation of Blt() here.

More details about the changes I made to DDEX1 and other stuff about DirectDraw, coming soon.