Sunday, November 4, 2012

First Hack: Color change for loopy game in ubuntu

So after background tutorials let's actually hack something. First hack should be obviously very simple, so I've chosen an ubuntu game "loopy".

Installation: Go to Synaptic Package Manager->install sgt-puzzles package. This will show a logic submenu in Application->Games. There is a game called loopy in that logic menu.

Aim: So whenever the game is started, we'll see rectangular grid with numbers inside. Color of line forming rectangle is yellowish-green, which does not match with  gray background. So our aim in this experiment is to change color of that line.

Source Code: I've taken it from https://launchpad.net/ubuntu/+source/sgt-puzzles. Take for your own distribution.

Build: This package does not have any configure script, but a Makefile is present in build directory. So just go to the root folder for source code of this game, and type make.

Make sure that it builds. To confirm it, see for any error message when build process is finished and then run our loopy game from local build using ./loopy.
Remember to put './' to run from local build.

So far, so good. We have successfully compiled code  locally. So now all we need to do is just find the location where color for that line is defined and change it.

Let's start actual code analysis and modification now. An overview over code directory will tell you that all code is in same folder with icons in subfolder. So lets start CScope analysis on this code. Type cscope -R -q. '-R' is not necessary since code is in only one directory, but its usage will do no harm. '-q' will build a reverse index, so that string search inside code is faster.

Ok, we have a cscope index built now. What next? Let's start with standard C entrypoint 'main' function. So I'll search for global definitions of main in cscope, and it lists number of main functions, I guess one for each game. Which means, each game is kind of independent code in it's C file. So for any particular game we just need to see its code file. So our job is now reduced to analysis of C file for loopy game. If we look into code folder we'll find loopy.c present. So let's open it in 'geany code editor'.

Up to this point it was all predefined. No need to deviate from this procedure for any code. After this point however most of the things are intuition based. We need to look at multiple things and guess where our code of interest might be.

What we are looking for in this game is color used for drawing lines on grid. So let's see if there is any function for drawing line in the game. We have trust pretty much on function variable names now.

In geany, on left hand side, in list of functions, no functions starts with 'draw'. So let us see if anything is there starting with 'line'. No function with 'line' at start. OK, let's read the names of functions in the file then. We have a function named game_redraw. Now that is close. Name suggests it would redraw game board each time some activity happens. Let's take a closer look at the function.

Now within first 10 lines of function code, there is a call to draw_rect. Looks like we are on right track. CScope global definition of draw_rect gives 2 entries. Trusting on filenames, let's for with one in draw.c. I pulled draw.c in geany now. The function list for draw.c contains draw_rect and near that we can see a draw_line too. We're closing in here. Now we need to see calls to draw_line from our loopy.c.

So, let's go back to loopy.c, go to function game_redraw and search for call to draw_line using geany search. We have one. In the code that I have, call is located on line 3544. Depending on your code version it may very, but call should be there. Now prototype of draw_line from draw.c tells us that last parameter passed is line color. That is what we should look for in loopy.c. Last parameter in call is line_colour. We can guess that it is a variable which gets proper color as per the action. So let's search where that yellowish green color is assigned. For that let's see assignment to line_colour, first in the same function.

A look on 50 code lines above call to draw_line gives us few lines where line_colour is assigned some values. All values look like COL_XXX, which suggests it might be a constant defined using #define. So, let's search for global definition of COL_ constants in CScope.  Entry for loopy.c takes us to an enum. So we were wrong. Now we need to find out how this enum is used get exact color.  Now, since every game has its own definition of COL_XX enum (as pointed by CScope), we can search for enum-to-color conversion in local file only.

Let's go to line 1 of loopy.c then and start searching for any one enum value. I searched for COL_FAINT. First search takes us to enum definition again, but next one is interesting. It takes us to a function named game_colours. And that function simply assigns 3 numbers to  ret array indexed by COL_ enum values. Bingo! This must be red, green and blue component for every color.

Great, now all we need to find is yellowish color assigned somewhere, and change it. Again trusting on names and a bit of knowledge of game rules tells me it should be either COL_LINEUNKNOWN or COL_FAINT. But, COL_FAINT is 0.9, 0.9, 0.9 color, which is as good as white. So, by elimination we have only COL_LINEUNKNOWN which is 0.8, 0.8, 0.0. I want to make it greenish. So I'll change it to 0.1, 0.8, 0.1 (reducing red component).

We're nearly done. All we need to do is to recompile and check if it has changed. So, let's run make. It builds fine. Finally, run ./loopy and see that magic has happened.

That's it from this post. Please post comments for any suggestion, doubt or mistake in this post.
                                                                                                                    ASD