Alrighty, now for the stuff you want to know.
I will assume that your file may contain any data, but that the following
conditions hold:
1. The offset has a unique name.
2. The offset is found on a line of the form:
" # define NAME 0xN..N [...]"
|
(Sorry, I had to put those double-quotes in there to preserve spaces)
So we will need to assume one thing:
1. The name of the desired offset is known beforehand
|
This isn't a big deal because you have to know the name of the offset anyway...
Now for some structure. Let's keep the offsets in an enumerated array:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
/* The following enumeration is ALPHABETIZED, and MUST match the following
array.
*/
typedef enum {
AFewMountSkills,
ARandomOffsetName,
...
NUMBER_OF_OFFSETS
}
offset_names_t;
typedef struct {
char* const name; /* everything about name is immutable */
long value; /* the value to get from the file */
}
offset_t;
offset_t offsets[ NUMBER_OF_OFFSETS ] = {
{ "AFewMountSkills", -1 },
{ "ARandomOffsetName", -1 },
...
};
|
What this does for us is allow us to access offset data by name.
1 2 3 4 5 6
|
WritePrivateProfileString(
"Updates",
offsets[ AFewMountSkills ].name,
offsets[ AFewMountSkills ].value,
"C:/OffsetUpdates.ini"
);
|
OK, now to find specific offsets in the file. Going on the (rather loose) conditions on the structure of the .h that I listed above, we cannot scan the file sequentially for offset values. Rather, we must ask for them by name, and test each line for a match.
Since random file access is rather slow, I would normally just load the whole thing into memory and analyze it there. However, since that complicates things a little and there are so few offsets to process, we'll just access it directly on disk. This adds one requirement:
2. The file must be random access.
|
This isn't a big deal either.
First, since we're getting lines again, let's move that line-getting stuff with fgets() into a more convenient little function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
/* Get the next line from the file, maximum 80 characters.
Extra characters are ignored.
Returns a constant, static char buffer which is overwritten with each
call (so if you want to save the result, strcpy() it to your own char
array before using this function again).
*/
const char *getline( FILE* f )
{
static char line[ 81 ];
unsigned last_index;
int c;
fgets( line, sizeof( line ), f );
last_index = strlen( line ) -1;
if (line[ last_index ] != '\n')
while (((c = fgetc( stdin )) != EOF) && (c != '\n'));
else
line[ last_index ] = '\0';
return line;
}
|
Now to the dirty work. Search for a specificly-named offset. We must account for the possibility that it is not found. A simple routine to do just that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
/* Find and return the named offset.
* If not found, returns -1.
* The argument name must not exceed 65 characters plus null terminator.
*/
long findoffset( FILE* f, const char* name )
{
const char* line;
long result = -1;
char format_string[ 80 ] = " # define ";
strncat( format_string, name, 65 );
strcat( format_string, " %lx" );
fseek( f, 0, SEEK_SET );
while (!feof( f ))
{
line = getline( f );
if (sscanf( line, format_string, &result ) == 1)
return result;
}
return (-1);
}
|
Now at last, you can fill your offsets tree. Again, a little function to do the job:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
/* Endeavors to load the named offsets from the file.
* Accesses global data directly.
*
* Returns the number of offsets found.
* If the file could not be opened, returns -1;
*/
int load_offsets( const char* filename )
{
FILE* f;
unsigned i;
int result = 0;
long n;
f = fopen( filename, "r" );
if (f == NULL) return -1;
for (i = 0; i < NUMBER_OF_OFFSETS; i++)
{
n = offsets[ i ].value = findoffset( f, offsets[ i ].name )
if (n >= 0)
result++;
}
fclose( f );
return result;
}
|
Whew. I hope this has been helpful and instructive.
--Michael