mirror of
https://github.com/BC46/freelancer-hd-edition
synced 2024-08-30 18:32:47 +00:00
282 lines
6.2 KiB
C
282 lines
6.2 KiB
C
|
/*
|
||
|
jflpmod.c - Patch a mod's script files to work with JFLP.
|
||
|
|
||
|
Jason Hood, 12 & 13 August, 2009.
|
||
|
|
||
|
Make adjustments to script files so they will work with JFLP:
|
||
|
* change numbers from six decimals to six significant digits;
|
||
|
* comment the opening movies;
|
||
|
* remove marketgood lines for ships that can't be bought;
|
||
|
* remove faction_weight lines;
|
||
|
* delete data sections using DATA\MISSIONS\mshipprops.ini.
|
||
|
|
||
|
It's quite a simple parser, so it expects CRLF files, no leading or trailing
|
||
|
spaces, correct syntax and no comments within <section> and <dest> regions.
|
||
|
|
||
|
Developed in MinGW, changes may be necessary for other compilers.
|
||
|
*/
|
||
|
|
||
|
#define PVERS "1.00"
|
||
|
#define PDATE "13 August, 2009"
|
||
|
|
||
|
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#include <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
|
||
|
void process( LPCSTR );
|
||
|
LPSTR get_line( int*, LPSTR*, DWORD* );
|
||
|
BOOL market_ship( LPSTR, int, FILE* );
|
||
|
BOOL numbers( LPSTR, int, FILE* );
|
||
|
LPSTR EngNum( double, LPSTR );
|
||
|
|
||
|
|
||
|
int main( int argc, char* argv[] )
|
||
|
{
|
||
|
if (argc == 1 ||
|
||
|
((argv[1][0] == '/' || argv[1][0] == '-') && argv[1][1] == '?') ||
|
||
|
strcmp( argv[1], "--help" ) == 0)
|
||
|
{
|
||
|
puts( "JFLPMOD by Jason Hood <jadoxa@yahoo.com.au>\n"
|
||
|
"Version " PVERS " (" PDATE "). Freeware.\n"
|
||
|
"http://freelancer.adoxa.cjb.net/\n"
|
||
|
"\n"
|
||
|
"Patch a mod's script files for JFLP compatibility.\n"
|
||
|
"\n"
|
||
|
"jflpmod mods\\mod\\*.xml\n"
|
||
|
"\n"
|
||
|
"The original script has \".sdk\" appended."
|
||
|
);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
while (*++argv)
|
||
|
process( *argv );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
void process( LPCSTR name )
|
||
|
{
|
||
|
char oname[MAX_PATH];
|
||
|
FILE* ofile;
|
||
|
|
||
|
HANDLE file = CreateFile( name, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||
|
OPEN_EXISTING, 0, NULL );
|
||
|
if (file == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
fprintf( stderr, "Unable to open \"%s\".\n", name );
|
||
|
return;
|
||
|
}
|
||
|
HANDLE map = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL );
|
||
|
if (map == NULL)
|
||
|
{
|
||
|
fprintf( stderr, "Unable to create file mapping for \"%s\".\n", name );
|
||
|
CloseHandle( file );
|
||
|
return;
|
||
|
}
|
||
|
LPSTR view = MapViewOfFile( map, FILE_MAP_READ, 0, 0, 0 );
|
||
|
if (view == NULL)
|
||
|
{
|
||
|
fprintf( stderr, "Unable to map view of \"%s\".\n", name );
|
||
|
CloseHandle( map );
|
||
|
CloseHandle( file );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_snprintf( oname, sizeof(oname), "%s.new", name );
|
||
|
ofile = fopen( oname, "wb" );
|
||
|
if (!ofile)
|
||
|
{
|
||
|
fprintf( stderr, "Unable to create file \"%s\".\n", oname );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
BOOL changed = FALSE;
|
||
|
LPSTR xml = view;
|
||
|
DWORD len = GetFileSize( file, NULL );
|
||
|
while (len)
|
||
|
{
|
||
|
LPSTR line;
|
||
|
int llen;
|
||
|
LPSTR strt = xml;
|
||
|
DWORD slen = len;
|
||
|
while (len)
|
||
|
{
|
||
|
line = get_line( &llen, &xml, &len );
|
||
|
if (*line == '<' && (strnicmp( line+1, "dest>", 5 ) == 0 ||
|
||
|
strnicmp( line+1, "section>", 8 ) == 0))
|
||
|
break;
|
||
|
if (llen > 41 &&
|
||
|
strnicmp( line,
|
||
|
"<data file=\"DATA\\Missions\\mShipProps.ini\"", 41 ) == 0)
|
||
|
{
|
||
|
fwrite( strt, slen - len - llen - 1, 1, ofile );
|
||
|
do
|
||
|
line = get_line( &llen, &xml, &len );
|
||
|
while (*line != '<' || strnicmp( line+1, "/data>", 6 ) != 0);
|
||
|
strt = xml;
|
||
|
slen = len;
|
||
|
changed = TRUE;
|
||
|
}
|
||
|
}
|
||
|
fwrite( strt, slen - len, 1, ofile );
|
||
|
while (len)
|
||
|
{
|
||
|
line = get_line( &llen, &xml, &len );
|
||
|
if (*line == '<')
|
||
|
{
|
||
|
fwrite( line, llen, 1, ofile );
|
||
|
break;
|
||
|
}
|
||
|
if (llen > 12 && strnicmp( line, "movie_file", 10 ) == 0)
|
||
|
{
|
||
|
fputc( ';', ofile );
|
||
|
fwrite( line, llen, 1, ofile );
|
||
|
changed = TRUE;
|
||
|
}
|
||
|
else if (llen > 12 && strnicmp( line, "marketgood", 10 ) == 0)
|
||
|
changed |= market_ship( line, llen, ofile );
|
||
|
else if (llen > 14 && strnicmp( line, "faction_weight", 14 ) == 0)
|
||
|
changed = TRUE;
|
||
|
else
|
||
|
changed |= numbers( line, llen, ofile );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fclose( ofile );
|
||
|
|
||
|
UnmapViewOfFile( view );
|
||
|
CloseHandle( map );
|
||
|
CloseHandle( file );
|
||
|
|
||
|
if (!changed)
|
||
|
remove( oname );
|
||
|
else
|
||
|
{
|
||
|
char tname[MAX_PATH];
|
||
|
_snprintf( tname, sizeof(tname), "%s.sdk", name );
|
||
|
rename( name, tname );
|
||
|
rename( oname, name );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// Fortunately, only the market_ships file has this particular sequence. If
|
||
|
// it's found, ignore the line, since my patch doesn't have it.
|
||
|
BOOL market_ship( LPSTR line, int len, FILE* ofile )
|
||
|
{
|
||
|
if (len > 20 && memcmp( line + len - 20, ", -1, 0, 0, 1, 1, 1\r", 20 ) == 0)
|
||
|
return TRUE;
|
||
|
fwrite( line, len, 1, ofile );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Search each parameter for a floating point number; if found, reformat it.
|
||
|
BOOL numbers( LPSTR line, int len, FILE* ofile )
|
||
|
{
|
||
|
char num[16];
|
||
|
BOOL rc = FALSE;
|
||
|
|
||
|
LPSTR parm = memchr( line, '=', len );
|
||
|
if (!parm)
|
||
|
{
|
||
|
fwrite( line, len, 1, ofile );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
parm += 2;
|
||
|
fwrite( line, parm - line, 1, ofile );
|
||
|
len -= parm - line;
|
||
|
for (;;)
|
||
|
{
|
||
|
LPSTR comma = memchr( parm, ',', len );
|
||
|
if (!comma)
|
||
|
comma = parm + len - 2;
|
||
|
if (comma - parm >= 8 && comma[-7] == '.')
|
||
|
{
|
||
|
fputs( EngNum( atof( parm ), num ), ofile );
|
||
|
rc = TRUE;
|
||
|
}
|
||
|
else
|
||
|
fwrite( parm, comma - parm, 1, ofile );
|
||
|
if (*comma != ',')
|
||
|
{
|
||
|
fputs( "\r\n", ofile );
|
||
|
break;
|
||
|
}
|
||
|
fputs( ", ", ofile );
|
||
|
len -= comma + 2 - parm;
|
||
|
parm = comma + 2;
|
||
|
}
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Return a pointer to the start of the line; LLEN contains its length,
|
||
|
// including the CRLF. MEM & LEN are updated to the next line.
|
||
|
LPSTR get_line( int* llen, LPSTR* mem, DWORD* len )
|
||
|
{
|
||
|
LPSTR line = *mem;
|
||
|
|
||
|
LPSTR nl = memchr( *mem, '\n', *len );
|
||
|
if (!nl)
|
||
|
{
|
||
|
nl = *mem + *len;
|
||
|
*mem += *len;
|
||
|
*len = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
++nl;
|
||
|
*len -= nl - *mem;
|
||
|
*mem = nl;
|
||
|
}
|
||
|
|
||
|
*llen = nl - line;
|
||
|
return line;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Convert a number like "%g", but use engineering notation (the exponent is a
|
||
|
// multiple of 3; there's also no plus sign or leading zeros).
|
||
|
LPSTR EngNum( double num, LPSTR buf )
|
||
|
{
|
||
|
LPSTR s = buf;
|
||
|
|
||
|
if (num < 0)
|
||
|
{
|
||
|
*s++ = '-';
|
||
|
num = -num;
|
||
|
}
|
||
|
|
||
|
if (num && (num >= 1e6 || num <= 1e-5))
|
||
|
{
|
||
|
int exp = (int)floor( log10( num ) );
|
||
|
int adj = exp % 3;
|
||
|
if (adj < 0)
|
||
|
adj += 3;
|
||
|
exp -= adj;
|
||
|
num /= pow( 10, exp );
|
||
|
if (num > 999.999) // some numbers just aren't what they seem...
|
||
|
{
|
||
|
num /= 1000;
|
||
|
exp += 3;
|
||
|
}
|
||
|
sprintf( s, "%ge%d", num, exp );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprintf( s, "%g", num );
|
||
|
}
|
||
|
|
||
|
return buf;
|
||
|
}
|