Rev 1 | Rev 7 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include "spkprogress.h"
#ifndef _INCLUDE7ZIP
#include <ansi7zip/7Decoder.h>
#endif
#include <MultiSpkFile.h>
#include "../../HiP/HiP.h"
#ifdef _DEBUG
#define CLEANUP fclose ( id ); if ( data ) delete data; if ( uncomprData ) delete uncomprData; if ( !removeFile.Empty() ) remove ( removeFile.c_str() ); char pause; printf ( "Press Enter to Close\n" ); scanf ( "%c", &pause );
#else
#define CLEANUP fclose ( id ); if ( data ) delete data; if ( uncomprData ) delete uncomprData; if ( !removeFile.Empty() ) remove ( removeFile.c_str() );
#endif
char *ReadNextLine ( char *data, long *len, CyString *str )
{
int pos = 0;
bool end = false;
while ( pos < *len )
{
if ( data[pos] == '\n' )
break;
if ( data[pos] == '\0' )
{
end = true;
break;
}
++pos;
}
if ( end )
{
*len = 0;
*str = data;
return NULL;
}
data[pos] = '\0';
*str = data;
data[pos] = '\n';
*len -= (pos + 1);
return data + (pos + 1);
}
char *LineByLineRead ( char *data, long *len, CyString end, CyString *readData )
{
CyString line;
while ( true )
{
data = ReadNextLine ( data, len, &line );
if ( line == end )
break;
*readData += (line + "\n");
}
return data;
}
int main ( int argc, char **argv )
{
CyString filename ( argv[0] );
filename = filename.GetToken ( filename.NumToken ( '\\' ), '\\' );
printf ( "SPKConvert V1.10 (SPK VERSION %.2f) 28/07/2007 by Cycrow\n", FILEVERSION );
if ( argc < 3 )
{
printf ( "Syntax, %s <oldspkfile> <newspkfile>\n", filename.c_str() );
exit ( 1 );
}
CyString oldfile ( argv[1] );
CyString newfile ( argv[2] );
int ret = CBaseFile::CheckFile ( oldfile );
if ( ret != SPKFILE_INVALID && ret != SPKFILE_OLD )
{
printf ( "Spk file is already in the new format, unable to convert\n" );
exit ( 1 );
}
// firstcheck if the file exists
FILE *id = fopen ( argv[1], "rb" );
if ( !id )
{
printf ( "Unable to open file: %s\n", argv[1] );
exit ( 0 );
}
// read the first 3 charaters
CyString check = (char)fgetc ( id );
check += (char)fgetc ( id );
check += (char)fgetc ( id );
CyString removeFile;
unsigned char *uncomprData = NULL;
unsigned char *data = NULL;
long len = 0, newlen = 0;
MyProgress *progress = new MyProgress ( 0 );
if ( check == "HiP" )
{
fclose ( id );
bool opened = false;
if ( DecompressFile ( argv[1], "uncompr.tmp" ) )
{
removeFile = "uncompr.tmp";
id = fopen ( "uncompr.tmp", "r" );
if ( id )
opened = true;
}
if ( !opened )
{
printf ( "Unable to uncompress file, exiting...\n" );
exit ( 0 );
}
printf ( "* Reading file into memory... " );
// get file length
fseek ( id, 0, SEEK_END );
len = ftell ( id );
// move back to beginning
fseek ( id, 0, SEEK_SET );
// read the data from file into memory
uncomprData = new unsigned char[len + 1];
fread ( uncomprData, sizeof(unsigned char), len, id );
newlen = len;
}
else
{
printf ( "* Reading file into memory... " );
// get file length
fseek ( id, 0, SEEK_END );
len = ftell ( id );
// move back to beginning
fseek ( id, 0, SEEK_SET );
// read the data from file into memory
data = new unsigned char[len + 1];
fread ( data, sizeof(unsigned char), len, id );
// uncompress the file (currently only 7zip compression)
printf ( "\t(Done)\n* Uncompressing file...\n\t>" );
newlen = len;
#ifdef _INCLUDE7ZIP
uncomprData = LZMADecodeData ( data, len, newlen, progress );
#else
uncomprData = LZMADecode_C ( (unsigned char *)data, len, (size_t*)&newlen, NULL );
#endif
}
// uncomressed failed
if ( !uncomprData )
{
printf ( "\t(Error)\n" );
CLEANUP
exit ( 0 );
}
len = newlen;
printf ( "< (Done)\n" );
// now we can read the data
char *d = (char *)uncomprData;
CyString str;
CSpkFile *spkfile = new CSpkFile;
CMultiSpkFile *mspk = NULL;
SMultiSpkFile *cur_mspk = NULL;
int numscripts = 0, curscript = 0;
bool verbose = true;
float fVersion = 1;
printf ( "* Reading spk data..." );
if ( verbose )
printf ( "\n" );
while ( (d) && (len > 0) )
{
d = ReadNextLine ( d, &len, &str );
CyString first = str.GetToken ( 1, ' ' );
CyString rest = str.GetToken ( 2, -1, ' ' );
if ( first == "MultiPackage:" )
mspk = new CMultiSpkFile;
else if ( (first == "SelectScript:") && (mspk) )
{
mspk->AddFileEntry ( rest.GetToken ( 2, -1, ' ' ) + ".spk" );
++numscripts;
}
else if ( (str == "AllowSelection") && (mspk) )
mspk->SetSelection ( true );
else if ( str == "-- Start New Script --" )
{
if ( !mspk )
{
printf ( "Invalid file format, seems to be multi package file but isn't\n" );
CLEANUP
exit ( 0 );
}
cur_mspk = mspk->GetFileList()->Get ( curscript );
++curscript;
cur_mspk->pFile = new CSpkFile;
spkfile = (CSpkFile *)cur_mspk->pFile;
}
else if ( first == "Packager:" )
{
fVersion = rest.ToFloat ();
if ( verbose ) printf ( "\tPackager Version: %.2f\n", fVersion );
}
else if ( first == "Name:" )
{
spkfile->SetName ( rest );
if ( verbose ) printf ( "\tScript Name: %s\n", rest.c_str() );
}
else if ( first == "Author:" )
{
spkfile->SetAuthor ( rest );
if ( verbose ) printf ( "\tScript Author: %s\n", rest.c_str() );
}
else if ( str == "CustomStart" )
{
spkfile->SetCustomStart();
if ( verbose ) printf ( "\tPackage is a custom start!!\n" );
}
else if ( first == "AnotherMod:" )
{
spkfile->SetAnotherMod ( rest.GetToken ( 1, '|' ), rest.GetToken ( 2, -1, '|' ) );
if ( verbose ) printf ( "\tFor another Mod, Name: %s, Author: %s\n", spkfile->GetOtherName().c_str(), spkfile->GetOtherAuthor().c_str() );
}
else if ( str == "PATCH" )
{
spkfile->SetPatch();
if ( verbose ) printf ( "\tPackage is a Patch Mod!!\n" );
}
else if ( first == "Version:" )
{
spkfile->SetVersion ( rest );
if ( verbose ) printf ( "\tScript Version: %s\n", rest.c_str() );
}
else if ( first == "Date:" )
{
spkfile->SetCreationDate ( rest );
if ( verbose ) printf ( "\tScript Creation Date: %s\n", rest.c_str() );
}
else if ( first == "Desc:" )
{
spkfile->SetDescription ( rest.FindReplace ( "<br>", "\n" ) );
if ( verbose ) printf ( "\tScript Description: %s\n", spkfile->GetDescription().c_str() );
}
else if ( first == "WebAddress:" )
{
spkfile->SetWebAddress ( rest );
if ( verbose ) printf ( "\tWeb Address: %s\n", rest.c_str() );
}
else if ( first == "WebMirror1:" )
{
spkfile->AddWebMirror(rest);
if ( verbose ) printf ( "\tWeb Mirror Address: %s\n", rest.c_str() );
}
else if ( first == "WebMirror2:" )
{
spkfile->AddWebMirror(rest);
if ( verbose ) printf ( "\tWeb Mirror Address: %s\n", rest.c_str() );
}
else if ( first == "ScriptType:" )
spkfile->SetScriptType ( rest );
else if ( first == "WebSite:" )
{
spkfile->SetWebSite ( rest );
if ( verbose ) printf ( "\tWeb Site: %s\n", rest.c_str() );
}
else if ( first == "Email:" )
{
spkfile->SetEmail ( rest );
if ( verbose ) printf ( "\tAuthor Email Address: %s\n", rest.c_str() );
}
else if ( first == "GameVersion:" )
{
//TODO: fix this for new game version
/*
int version = rest.ToInt();
if ( version == 0 )
spkfile->SetGameVersion ( 1 );
else if (version == 1 )
spkfile->SetGameVersion ( 0 );
else
spkfile->SetGameVersion ( version );
if ( verbose ) printf ( "\tGame Version: %d\n", spkfile->GetGameVersion () );
*/
}
else if ( first == "Ware:" )
{
spkfile->AddWare ( rest );
if ( verbose ) printf ( "\tAdding Custom Ware\n" );
}
else if ( first == "WareText:" )
spkfile->AddWareText ( rest );
else if ( first == "UninstallAfter:" )
spkfile->AddUninstallAfterText ( rest.GetToken ( 1, ' ' ).ToInt(), rest.GetToken ( 2, -1, ' ' ) );
else if ( first == "UninstallBefore:" )
spkfile->AddUninstallBeforeText ( rest.GetToken ( 1, ' ' ).ToInt(), rest.GetToken ( 2, -1, ' ' ) );
else if ( first == "InstallAfter:" )
spkfile->AddInstallAfterText ( rest.GetToken ( 1, ' ' ).ToInt(), rest.GetToken ( 2, -1, ' ' ) );
else if ( first == "InstallBefore:" )
spkfile->AddInstallBeforeText ( rest.GetToken ( 1, ' ' ).ToInt(), rest.GetToken ( 2, -1, ' ' ) );
else if ( first == "ScriptName:" )
{
CyString lang = rest.GetToken ( 1, ':' );
CyString name = rest.GetToken ( 2, -1, ':' );
spkfile->AddLanguageName ( lang.ToInt(), name );
if ( verbose ) printf ( "\tScript Name Language (%s) %s\n", lang.c_str(), name.c_str() );
}
else if ( first == "Icon:" )
{
CyString ext = rest.GetToken ( 2, ' ' );
long size = rest.GetToken ( 1, ' ' ).ToLong ();
C_File *file = new C_File ();
file->ReadFromData ( d, size );
d += size;
spkfile->SetIcon ( file, ext );
if ( verbose ) printf ( "\tIcon (%s) Size: %s\n", ext.c_str(), file->GetDataSizeString ().c_str() );
}
else if ( (first == "$$$SharedScript:") || (first == "$$$Script:") || (first == "$$$SharedText:") || (first == "$$$Text:") || (first == "$$$Uninstall:") || (first == "$$$SharedMap:") || (first == "$$$Map:") || (first == "$$$Readme:") )
{
int type;
CyString end, print;
if ( (first == "$$$SharedText:") || (first == "$$$Text:") )
{
type = FILETYPE_TEXT;
end = "-- End of Script --";
print = "Text";
}
else if ( first == "$$$Uninstall:" )
{
type = FILETYPE_UNINSTALL;
end = "-- End of Uninstall --";
print = "Uninstall Script";
}
else if ( first == "$$$Readme:" )
{
type = FILETYPE_README;
end = "-- End of Readme --";
print = "Readme";
}
else if ( (first == "$$$SharedMap:") || (first == "$$$Map:") )
{
type = FILETYPE_MAP;
end = "-- End of Map --";
print = "Universe Map";
}
else
{
type = FILETYPE_SCRIPT;
end = "-- End of Script --";
print = "Script";
}
CyString filename, dir;
long time = 0, size = 0;
bool shared = false;
if ( fVersion >= 3.00f )
filename = rest.GetToken ( 3, -1, ' ' );
else if ( fVersion >= 2.00f )
filename = rest.GetToken ( 2, -1, ' ' );
else
filename = rest;
if ( filename.IsIn ( "<br>" ) )
{
filename = filename.FindReplace ( "<br>", "|" );
if ( filename[0] == '|' )
{
filename = filename.GetToken ( 1, '|' );
}
else
{
dir = filename.GetToken ( 1, '|' );
filename = filename.GetToken ( 2, -1, '|' );
}
}
if ( fVersion >= 2.00f )
time = rest.GetToken ( 1, ' ' ).ToLong();
if ( fVersion >= 3.00f )
size = rest.GetToken ( 2, ' ' ).ToLong();
if ( first.Left (9) == "$$$Shared" )
shared = true;
C_File *file = new C_File ();
bool binaryRead = false;
CyString ext = filename.GetToken ( filename.NumToken ( '.' ), '.' );
if ( ext.ToUpper() == "PCK" )
binaryRead = true;
if ( verbose )
{
if ( shared )
printf ( "\tFound %s File (Shared): %s, Reading...", print.c_str(), filename.c_str() );
else
printf ( "\tFound %s File: %s, Reading...", print.c_str(), filename.c_str() );
}
if ( binaryRead )
{
file->ReadFromData ( d, size );
d += size;
}
else
{
CyString readData;
d = LineByLineRead ( d, &len, end, &readData );
file->ReadFromData ( (char *)readData.c_str(), (long)readData.Length() );
}
file->SetName ( filename );
file->SetFileType ( type );
file->SetShared ( shared );
file->SetCreationTime ( time );
if ( !dir.Empty() )
file->SetDir ( dir );
spkfile->AddFile ( file );
printf ( "(Done) Size: %s\n", file->GetDataSizeString().c_str() );
}
else if ( (first == "$$$Mod:") || (first == "$$$Sound:") || (first == "$$$Extra:") || (first == "$$$Screen:") )
{
int type = -1;
CyString print;
if ( first == "$$$Mod:" )
{
type = FILETYPE_MOD;
print = "Mod";
}
else if ( first == "$$$Extra:" )
{
type = FILETYPE_EXTRA;
print = "Extra";
}
else if ( first == "$$$Screen:" )
{
type = FILETYPE_SCREEN;
print = "Screenshot";
}
else if ( first == "$$$Sound:" )
{
type = FILETYPE_SOUND;
print = "Sound Track";
}
CyString filename = rest.GetToken ( 3, -1, ' ' ), dir;
long time = rest.GetToken ( 1, ' ' ).ToLong(), size = rest.GetToken ( 2, ' ' ).ToLong();
bool shared = false;
if ( filename.IsIn ( "<br>" ) )
{
filename = filename.FindReplace ( "<br>", "|" );
if ( filename[0] == '|' )
filename = filename.GetToken ( 1, '|' );
else
{
dir = filename.GetToken ( 1, '|' );
filename = filename.GetToken ( 2, -1, '|' );
}
}
C_File *file = new C_File ();
file->ReadFromData ( d, size );
file->SetName ( filename );
file->SetFileType ( type );
file->SetShared ( shared );
file->SetCreationTime ( time );
if ( !dir.Empty() )
file->SetDir ( dir );
d += size;
spkfile->AddFile ( file );
if ( verbose )
{
if ( shared )
printf ( "\tFound %s File (Shared): %s, Size(%s)\n", print.c_str(), filename.c_str(), file->GetDataSizeString().c_str() );
else
printf ( "\tFound %s File: %s, Size(%s)\n", print.c_str(), filename.c_str(), file->GetDataSizeString().c_str() );
}
}
}
if ( verbose ) printf ( "* Reading spk data..." );
printf ( " (Done)\n" );
// now save the spk file
printf ( "\nStarting to write new spk file\n" );
if ( mspk )
{
for ( SMultiSpkFile *it = mspk->GetFileList()->First(); it; it = mspk->GetFileList()->Next() )
{
for ( C_File *f = it->pFile->GetFileList()->First(); f; f = it->pFile->GetFileList()->Next() )
{
printf ( "* Compressing %s...\n\t>", f->GetNameDirectory(it->pFile).c_str() );
if ( f->CompressData ( spkfile->GetDataCompression(), progress ) )
{
progress->PrintDone();
printf ( "< (Done)\n" );
}
else
{
progress->Reset();
printf ( "< (Error)\n" );
}
}
FILE *id = tmpfile();
if ( id )
{
it->pFile->WriteData ( id, NULL );
it->lSize = ftell ( id );
fclose ( id );
}
}
}
else
{
for ( C_File *f = spkfile->GetFileList()->First(); f; f = spkfile->GetFileList()->Next() )
{
printf ( "* Compressing %s...\n\t>", f->GetNameDirectory(spkfile).c_str() );
if ( f->CompressData ( spkfile->GetDataCompression(), progress ) )
{
progress->PrintDone();
printf ( "< (Done)\n" );
}
else
{
progress->Reset();
printf ( "< (Error)\n" );
}
}
}
printf ( "* Writing to %s... ", argv[2] );
if ( mspk )
{
if ( mspk->WriteFile ( CyString(argv[2]) ) )
printf ( "(Done)\n" );
else
printf ( "(Error)\n" );
}
else
{
spkfile->WriteFile ( CyString(argv[2]) );
printf ( "(Done)\n" );
}
printf ( "SPK file has been converted successfully\n" );
CLEANUP
return 1;
}