thread: .lvl files
View Single Post
  #579  
01-24-2010, 05:23 AM
Paul's Avatar
Paul
Outlaw Sniper
 
: Jun 2007
: MilkyWay
: 1,535
Rep Power: 19
Paul  (718)Paul  (718)Paul  (718)Paul  (718)Paul  (718)Paul  (718)Paul  (718)

The only way to extract the table is from reversing the code since that table is generated by a function in the game. The function that does that pulls it from some other smaller table so I guess you could pull the data from that offset, copy what the function is doing to make the bigger table (which looks far from simple) and then you have your data.

FYI the loop to decode the last stage of the pixels is doing something like this:

:
if ( g_left7 <= 0 ) // First if batch
{
right25Copy2 = g_right25;
vlc_buf_ptr = *g_pointer_to_vlc_buffer;
vlc_buf_ptr1 = g_pointer_to_vlc_buffer + 1;
++g_pointer_to_vlc_buffer;
left7M1 = (unsigned int)vlc_buf_ptr >> 7;
right25_new = (signed __int16)vlc_buf_ptr << 25 >> 25;
g_left7 = left7M1;
g_right25 = right25_new;
}
else
{
right25_new = g_right25;
vlc_buf_ptr1 = g_pointer_to_vlc_buffer;
left7M1 = g_left7 - 1;
right25Copy2 = 0;
--g_left7;
}
There is one case in the function where it will call itself 3 times!

The function of intrest is the one that uses the array i posted which looks something like this:

:
signed int __cdecl decode_vlc_segment(int camSegPtr, int vlcBufferPtr)
{
signed int result; // eax@1
int index; // ebx@1
int segDWord; // esi@1
__int16 *retPtr; // edi@2
int retDWord; // ecx@2
signed int forCounter; // ebp@4
int v8; // [sp+14h] [bp+4h]@1

index = vlcBufferPtr;
segDWord = *(_WORD *)(camSegPtr + 2) | (*(_WORD *)camSegPtr << 16);
v8 = camSegPtr + 4;
result = 0;
loop_start:
while ( 2 )
{
retDWord = (unsigned __int16)g_cam_look_up_table_q[4 * ((unsigned int)segDWord >> 21)];
retPtr = &g_cam_look_up_table_q[4 * ((unsigned int)segDWord >> 21)];
result += retDWord;
segDWord <<= retDWord;
if ( result > 15 )
{
result &= 0xFu;
segDWord |= *(_WORD *)v8 << result;
v8 += 2;
}
for ( forCounter = 0; ; ++forCounter )
{
++retPtr;
if ( forCounter >= 3 || !*retPtr )
goto loop_start;
if ( (unsigned __int16)*retPtr == 0xFFFF )
break;
*(_WORD *)index = *retPtr;
index += 2;
}
*(_WORD *)index = (unsigned int)segDWord >> 19;
if ( (unsigned int)segDWord >> 19 != 1 )
{
result += 13;
index += 2;
segDWord <<= 13;
if ( result > 15 )
{
result &= 0xFu;
segDWord |= *(_WORD *)v8 << result;
v8 += 2;
}
continue;
}
return result;
}
}
Where g_cam_look_up_table_q is the array. Looks like I was wrong and its actually checking for 0xFFF.

Also I found an old function I wrote to decode part of a specific path file which looks like this:

:
void ParseFile( std::vector& aBuf )
{
int numBytes = aBuf.size();
int numDwords = aBuf.size() / 4;

DWORD* ptr = (DWORD*)&aBuf[0];

// Read the last dword
int pos = 1;
DWORD end = ptr[numDwords-pos];
do
{
// Process the dword
if ( end != -1 )
{
struct rec
{
WORD u1;
WORD u2;
DWORD funcPtr;
DWORD u3; // Used in asm up to here
};


rec* ptr = (rec*)&aBuf[end];

cout << ptr->u1 << " ";
cout << ptr->u2 << " ";
cout << hex << ptr->funcPtr << " ";
cout << ptr->u3 << " ";
cout << "\n";
}

// Get next last dword
pos++;
end = ptr[numDwords-pos];
}
while ( end != 1 );

}
I've attached the file thats in "aBuf" thats passed to this function.

Edit: Also attached an image of when I replaced a slig with a mud from changing the op codes at run time.
Attached Thumbnails
Click image for larger version

Name:	slig replaced.JPG
Views:	399
Size:	46.8 
ID:	11236  
Attached Files
File Type: txt spathraw.raw.txt (364 , 273 views)
__________________
[ http://www.paulsapps.com ]

Crawling sligs will shout "Mommy!" while running around and then the slig mommy will appear and help them put their pants on.


Last edited by Paul; 01-24-2010 at 05:40 AM..
Reply With Quote