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.