Thursday, December 17, 2009

const keyword in C and C++

Given the following:
char my_string[] = "12345";
You can create a pointer to this char array with, or without, the "const" keyword. The four options are these:
char *my_ptr1 = my_string;
char *my_ptr2 const = my_string;
const char *my_ptr3 = my_string;
const char *my_ptr4 const = my_string;
These all point to the '1' in "12345".


For "my_ptr1", any of the following operations are legal:
my_ptr1 = my_string + 1; // now points to '2' in "12345"
*my_ptr1 = '8'; // '1' in "12345" is changed to an '8', making "82345"
(*my_ptr1)++; // '1' in "12345" is changed to an '2', and my_ptr1 now points to the second '2' in "22345"

For "my_ptr2", the following are legal:
my_ptr2 = my_string + 1; // now points to '2' in "12345"
my_ptr2++; // also points to '2' in "12345"
However, you cannot change the value of "my_string" in any way. This means that
*my_ptr1 = '8';
would not change the string to "82345", but instead your compiler would inform you that this is an illegal operation.


For "my_ptr3", the following is legal:
*my_ptr3 = '8'; // '1' in "12345" is changed to '8', making "82345"
However, changing the address where it pointed to would be illegal:
my_ptr3 = my_string + 1;
my_ptr3++;
Having the "const" identifier AFTER the pointer declaration means that the pointer can't move or be changed, although the data CAN be.


Finally, there's "my_ptr4". You cannot change the address of my_ptr4 (same restrictions as my_ptr3 has), nor can you change the data that it is pointing at (same restrictions as my_ptr2).

None of these are legal operations:
my_ptr4 = my_string + 1;
my_ptr4[1] = '8';
If you want to see some of this in action, check out the following code. Change line 6
char *my_ptr = my_string;
to include the "const" keyword in various places as shown above to see the different kinds of compiler warnings/errors you get. (Tested with i686-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5367) compiler.)

#include

int main()
{
char my_string[] = "12345";
char *my_ptr = my_string; // you could also use "&my_string[0]", which is the same thing


// Before any modifications
printf("my_string: \"%s\"\n", my_string);
printf("my_ptr is pointing to the \'%c\' in \"%s\"\n", *my_ptr, my_string);


// This will change my_string to equal "18345"
my_ptr[1] = '8';

printf("\n");
printf("my_string now equals: \"%s\"\n", my_string);


// This will make my_ptr point to the '8' in "18345"
my_ptr++;

printf("\n");
printf("my_ptr is now pointing to the \'%c\' in \"%s\"\n", *my_ptr, my_string);


// This will change the '8' in "18345"
(*my_ptr)++;

printf("\n");
printf("my_string now equals: \"%s\"\n", my_string);
printf("my_ptr is now pointing to the \'%c\' in \"%s\"\n", *my_ptr, my_string);


return 0;
}

Wednesday, May 27, 2009

KQlives on the Mac

I've been out of the programming loop for a while.  Two kids can do that to you.

I wanted to download and play with KQlives on my iMac.  The download from Sourceforge provided an outdated version, but which ran.  The CVS version gave me all the current updates, but wouldn't run (and compile).

My iMac isn't configured for programming: it's got XCode, a few programming projects I've worked on, DarwinPorts (very nice, by the way), and a few libraries to run Allegro-built games.

When I started, I was informed that my 'autoreconf' was out-of-date.  I upgraded to the most recent version via DarwinPorts, then got a bunch of warnings stating that a bunch of stuff was deprecated.  Lovely.

I don't remember how, but after hammering away at it for a good day or two, I finally got it to create a Makefile for me.

I ran that, and found that I didn't have the Allegro4, Lua, or DuMB libraries installed.  I grabbed them from DarwinPorts, but to my chagrin, it didn't give me any header files or sources: just the precompiled binaries.

I went off and downloaded the library sources, installed, and then was able to compile KQ (yay!).

Trying to RUN kq gave me problems.  It created a blank window, then complained that it was missing "misc.pcx".  I saw a few other reports like this on Google from a few years ago, but no resolution.  I found the answer, so I wanted to create this blog in case someone else happens across it.

I found out what was happening by adding a line of code that told me where, exactly, the datafile was trying to be found (the "mpcx.dat" datafile specifically).  Instead of being under the current directory (or even under ./data/mpcx.dat like I expected), it was looking for it under "./Contents/Resources/data/mpcx.dat"  So I simply created that directory, copied everything from ./data into that directory, and ran it.  It gave me the opening credits!  Of course, it died shortly after, complaining about some scripts and whatnot, but it's the same situation: it needs "./Contents/Resources/scripts/" and all of the other "important" subdirectories (like music, etc.) to be moved/copied under that.

If I get this up and working, I may even be able to work on some more code and see if I can't resurrect a few things for the kqlives project.  Kids- and time-willing, of course.

Thursday, October 18, 2007

Binary Bomb

Since my Binary Bomb class is over, I thought I'd post some of my findings. It's basically a spoiler for other people who Google "Binary Bomb". If a few professors (my school or others) request that I take it down, I can do that. You are supposed to be learning this on your own, after all...

I mentioned earlier that you could simply use "strings" to find the magic phrase in the bomb. The better way is to look at the assembly itself:

Phase_1: About the 4th instruction down, there is the following disassembled code:
8048bd2: 68 54 98 04 08 push $0x8049854
This is the simplest to determine (even without “strings bomb > theStrings.txt”) the value, since all you need to do to see what this is, is to:
x /s 0x8049854

Phase_2: First, we learn that the function read_six_numbers() is called before any other tests are done, so we step into this function. We notice that this function, before testing anything itself, tries to pull in 6 values from the specified input. This, in reverse order, contains the 6 strings the user entered. Once all are pushed individually into the stack, we notice the following two lines:
8048f9f: 68 bf 9b 04 08 push $0x8049bbf
8048fa7: e8 88 f9 ff ff call 8048934
When the first address (0x8049bbf) is dereferenced, we see that it is a string of text:
"%d %d %d %d %d %d"
This shows that sscanf() is being asked to pull the 6 numbers in, and save the results into %eax.
Once we return to phase_2, the first result of sscanf() is placed on the top of the stack:
8048c08: 8b 44 9d d4 mov 0xffffffd4(%ebp,%ebx,4),%eax
This could be more easily understood to be:
a = userInput[0];
The next line shows how we wish to test against the future values:
8048c0c: 83 c0 05 add $0x5,%eaxBasically a += 5. We don’t get too much out of this until we see the next line is comparing this number with our next number:
8048c0f: 39 44 9d d8 cmp %eax,0xffffffd8(%ebp,%ebx,4)
Again, this can be read as:
if (userInput[x] == userInput[x-1] - 5);
So it simply checks that
userInput[1] == userInput[0] + 5
userInput[2] == userInput[1] + 5
, etc.

Phase_3: We see immediately that this function pushes three values onto the stack, followed by a function push:
8048c38: 68 be 98 04 08 push $0x80498be
Dereferencing this shows us that the numbers must be in the format of "%d %c %d". Another sscanf() gives us:
a = sscanf(userString, "%d %c %d", userInput1);
Our inputs will be an integer, followed with a single character, followed by another integer. This phase is more dynamic than the previous ones, as it contains a switch()…case pair, and the second and third values we enter will depend on the first integer specified. In some peoples’ bombs, this switch() statement actually is not a simple 0..7 number structure (some can be -2..4, or 100..108). If this were the case, there would be an additional statement such as “subl $0x4,%eax” or similar.
This should give us our first guesses as to the different case’s. Regardless of which one is selected, the next thing seen is along the lines of:
8048c66: b3 7a mov $0x7a,%bl
The bl is the lower byte of the %eax register, and the value $0x7a actually denotes an ASCII value (in this case, the letter ‘z’). The user’s 3rd input is checked next, before the letter is actually validated, so onto the next line:
8048c68: 81 7d f8 f2 00 00 00 cmpl $0xf2,0xfffffff8(%ebp)The user’s 3rd input needs to be 0xf2 (decimal 242), and if so, we are jumped out of the switch() statement. It is here that the user’s input and the ASCII letter is compared, and if equal, the phase is complete.

Phase_4: Before any checks are made in this function, the user’s input is pushed to the stack (which is normal) and another sscanf() is issued. What is unusual is that the string value used to parse out the value, is that there are TWO values specified in the address 0x80498c4:
8048d52: 68 c4 98 04 08 push $0x80498c4
as we can see when we dereference it:
"%d %s"
This calls for an integer and a string of char’s, but only uses the integer. The string is actually used for the secret_phase().
The integer value is passed into func4, which seems to do nothing but test the current value and return when (value – 1) <= 1. This turns out to be doing a Fibonacci sequence, and the result is returned to phase_4. That result is checked against a fixed value, and if it passes, the phase is complete:
8048d7d: 3d f1 6f 00 00 cmp $0x6ff1,%eax
// When userInput == “22”, %eax == 28657


Phase_5: After the user’s input is pushed onto the stack, its string length is checked. If the user has input exactly 6 ASCII characters, the specific letters are each given a different weight. The total weight of all 6 letters are computed to equal a single value:
8048dc8: 83 f9 20 cmp $0x20,%ecx
I found it easiest to write down all the letters and their values (a..z) by breaking on this line:
8048dc6: 7e f0 jle 8048db8
then simply watching the value of %ecx change, and writing down that value. My ASCII weights were:
a = 10 b = 6 c = 1 d = 12 e = 16 f = 9 g = 3 h = 4
i = 7 j = 14 k = 5 l = 11 m = 8 n = 15 o = 13 p = 2
q = 10 r = 2 s = 1 t = 12 u = 16 v = 9 w = 3 x = 4
y = 7 z = 14

Once the weights equal the specified value (in the above case, 0x20 or 32 decimal), the phase is complete. I found the simplest to be bbbbbp (5(6) + 1(2)), but any other values that added up would work.

Phase_6: Through trial-and-error, I found that this is actually quite simple to test. You want your output to equal this line of code:
8048e60: 74 05 je 8048e67
// Break here: Test %ebx, and that’s what your input should be
The fun6() function doesn’t really do too much; it is a linked list that tries to twist around a lot, but does very little otherwise. You can pretty much skip any testing in it if you simply test the output value above.

Secret_Phase: Once the previous phases are complete, a branch in phase_defused() opens up. It tests whether you have finished all 6 previous phases:
80495bc: 83 3d 6c a8 04 08 06 cmpl $0x6,0x804a86c
// Check whether we're on phase 0x6 (6)

then enters starts to pull strings and values from previous phases. One that it lingered on was the “%d %s” from phase_4. It pulls the second value (the string) and tests if anything was entered. The simplest way to get into the secret_phase() is to look at the check value for the returned %s. This turned out to be the string “austinpowers” in a few bombs I worked on (I actually tried about 3 bombs, just for fun, and also to have a more complete guide that I'm writing now):
80495e4: 68 cb 9d 04 08 push $0x8049dcb
// 0x8049dcb contains the value "austinpowers"

The strings_not_equal() function tests these values, and you are taken into the secret_phase() to determine the last value.
The secret_phase() was more tricky than the other phases because it had a lookup array as well as a recursive function (fun7()). The lookup array contained several different values, and depending on the user input (either at the end of the user’s solutions text, or prompted), some or several of the tables were used. This result was returned and modified by the parent fun7() functions, until the end result passed back to the secret_phase() was the value it was looking for:
8048ee7: 83 f8 03 cmp $0x3,%eax
// Test that the (final) return value of fun7() is 3


That’s it! That’s all the bombs, and how they were found. The final phase (fun7()) took quite a bit of plug-and-chug before I began to see a pattern to how it was calculating which lookup array to use and how different return values affected the parent fun7()’s results as well.

Please leave comments if you found this useful, and especially if your values or addresses were different. How did you solve it? Are you still stuck on parts of it? What parts of the world are you from? Why are 95% of the readers for this post using Windows and Chrome instead of some Linux variant (I wasn't aware that Binary Bomb ran on anything BUT Linux...)?

Wednesday, April 05, 2006

Map Editor

Yea, still talking about KQ. This time, I'm just writing about what I did to update the KQ game's map editor.

At one time, Peter thought up a great idea to stick "markers" on the maps so we could dynamically call different parts of the map instead of statically. Meaning (if that didn't make sense) that we could have a marker named "entrance" somewhere on the map and just look for the marker's coordinates instead of telling the map to load coordinates (13, 77). This helps especially if we want to move things around on the map; when we do, we rarely have to even change the LUA script anymore; move the marker in the map and you're done.

So this is where we WERE. We also have something that will "grab" a tile: it basically sets the cursor to the same tile or attribute (zone, shadow, obstacle, etc.) so we can draw it elsewhere.

I added support so the map programmer can scroll to the "next instance" of the attribute in question. Not much of a functionality boost, but it's one more small thing I could work on in my spare time.

Monday, April 03, 2006

Original KQ

Pete, from the KQlives group, pointed me to a forum that links to (among others) the original KQ game by JB.

You can find it here. Ultra-cool. It's got a few storyline twists that have been modified, and so it's basically playing a completely different game. But how fun is that!!

Anyway, I thought it was very fun to play; it works fine on my WinXP machine (albeit jerky), and there is no source code for it. Maybe JB himself has the source backed up from 6 years ago... but then again, I never backup my stuff. Which is why when I have computers die, it's catastrophic.

I need to learn how to back up my computer. I just don't wanna pay for it. I want my hubby's paycheck for myself, not my computer (okay, that's almost one-and-the-same a lot of the time, but this is pride, people!).

I hate retards

I've spent about two weeks trying to get a stupid game to load with KQ. I start a new game. Crash. I load a game. Crash. I post my questions in forums and ask people to help with my debugging output. Then Peter suggests that I not only compile the PROGRAM but the GAME SCRIPTS. Oh yea... the game scripts.

I felt retarded.

Two weeks retarded.

I hate retards.

Tuesday, March 28, 2006

Discouraging stupidness

The general stupidity of people has certainly not died down at all in recent years; in fact, now that we have blog sites, chatrooms, p2p networks, and emulator havens, more people feel they should voice their opinions, regardless of whom they offend.

This is why I'm not keen to naming names.

But at the same time, I can't help but laugh at a new keyphrase the online community is starting to adopt, as stated by Ashlee Vance in a posting on The Register:

In fact, the Linux zealots have now proposed that an unreasonable support request be called a "Tuttle."

Incase you're interested, you may want to read up on what happened. I've read the email conversation between the two parties involved, and must say... good grief.

This is all I have to post tonight; sorry it's short. "Tuttle." It's even fun to say. I wonder how they named their city something like "Tuttle?"

Favorite sitcom so far: The IT Crowd

Wednesday, March 22, 2006

Why always KQlives?

Simple beginnings

Hi. I'm dedicating my first blog to my favorite RPG (probably because I'm helping to write it myself), KQlives.

Around the KQlives community, I've gone by TeamTerradactyl. So I might as well continue that nice trend here <grin>.

KQ is written in C. It was started by a programmer named Josh, but he decided that he didn't want to maintain it much past a fun demo. Another programmer, Peter, picked it up and put it on SourceForge. Since it was a game I had worked on before when Josh was over it, I started working on it again.

I had started primarily with the game engine (little tweaks, speed-ups, things like that), and started to learn how to program in C. Then I decided I'd much rather work on the maps. So I reworked Josh's map editor (and learned more C while doing it). Then I decided that the game's plot had inconsistencies that just dug at me, so I wanted to fix that.

Oops: Big mistake.

Now, I'm not too bad at making the game play out: NPCs interacting; making the player talk to person 1, then person 2, then back to person 1; stepping on a Hot Zone and having a pre-scripted dialog play out... that sort of thing. That wasn't my problem. My problem came when I tried to start thinking up the plot. Can I say how well that's been turning out?

It's not.

Now I've got writer's block and don't know where to go. Worse, my time with KQ has dwindled because I chose to get married (which I highly recommend) and had a kid (meh <shrug>). And trying to balance all them while I'm in school part time. (What? You think I'm crazy enough to do full-time with a baby? No way: he's too adorable to stay away from!)

Anyway, for those who read this blog and check out the game, let me know what ideas you'd have for the game. Isn't that the point of a blog? To get feedbacks? Yes, yes it is.

What do you call a doctor who fixes ugly pickles?
A Vlassic Surgeon!