Latest: adam_20nov2007.plan
Spent a bit of time fixing up some code in Decrypt, killed some show stopper bugs dealing w\ the OS API for the applications which affected progressing through missions. Also upgraded PHPFreeChat to v1.0 final. PHPFreeChat is the software behind the chat application.

Gotten quite a lot done on the console project lately too.

See, in programing you quickly come to two assumptions which are fairly safe to make.

1) The programing language is right, your code is wrong.

2) The 3rd party library you are using is right, your code is wrong.

The first is pretty darn stead fast, and the second isn't far behind (depending on how mature the library is of course).

So you'd think it'd be safe to assume the second when you are using a 20 year old, time tested library put out by the likes of a company such as NewTek (makers of LightWave).

But... you'd be wrong...


Lets examine this piece of code, it comes from lwio.c which wraps all of the I/O functionality that the rest of the files use. In there, there is a specific function which is used to read a NULL terminated string of bytes (not necessarily ASCII characters, but it doesn't really make a difference). We know this is it's purpose because we have read the documentation and looked at the data it is actually called on, it is always NULL terminated.

Now take a look at the function and tell me if you can spot a problem with it:


for ( i = 1; ; i++ ) {
c = fp->fgetc();
if ( c <= 0 ) break;
}


Ok, the point of this piece of code is to count the size of bytes that the data is so we can allocate memory for it.

First, ew. Ugly code. But lets trace it, we keep reading and incrementing our count variable until... until what? Until it is less then or equal to 0...

HHhhhmmm... does that make any ef-ing sense if what it is we are looking for is NULL ( NULL == 0 btw )?

Assuming we just did not understand the actual point of the code we continued reading the spec, looking at the data it was reading in a Hex editor and running through everywhere the read function was called.

With out a doubt it was looking for a NULL terminated string of bytes, and that chunk of code was meant to count up to the NULL character.

So we quickly replaced the bugged line and came up with the more explicit:


for ( i = 1; ; i++ ) {
c = fp->fgetc();
if ( c == '\0' ) break;
}


Now on a side note, the most astute of you may notice the file I/O using what appears to be an Object or Struct pointer. Well you are right, we ported the code to C++ and use our FileBuffer and FileIterator classes to emulate std:: file I/O operations. We looked a lot into how our getc() function might have been working differently then std::getc(). But I can assure you, that it works the same.

So back on topic here, it's not hard to see the case in which the original code would fail. Anytime the byte overflowed as an unsigned 8 bit int, it would be negative. The specific byte that was fucking us over was 0x80.

So, with that fixed, we finished porting lwobject and fixing bugs that cropped up in it. Then I went on to extract all the information we needed out of it and create our internal data structure for holding the data how we wanted to render it. Let me tell you, the UV coordinates were a bitch to find.

Just to get the texture file path, it took these two lines of code:

lwClip *clip = lwFindClip( obj->clip,
layer->polygon.pol[ii].surf->color.tex->
param.imap.cindex );

char *texturePath =
clip->source.still.name;


Anyway... With that all done I finished connecting all the dots between all of the supporting systems and the renderer and finally, finally, got Textured, 3D, rendering working.

So the current state of things is and solid complete base with 2D and 3D loading and rendering working.

Next, we start on integrating ODE! I don't want to jinx things, but it should, *fingers crossed* go a lot smoother then the other integrations have.

- Adam

Post a Comment
Your Name:
Your Comment:

Anti-Bot:
anti-bot

Commenting has been permanently disabled