Files
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

336 lines
10 KiB
C++

// xapmunge.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "xapmunge.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace std;
// The one and only application object
CWinApp theApp;
CString xapBankName;
CString xapMasterName;
CString xapOutputName;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
OPTIONS opts;
opts.isCreate = false;
opts.isExtract = false;
opts.isMerge = false;
opts.isVerbose = false;
// fix up the executable name
char* exename = _tcsrchr((argv[0]), (int)'\\');
if (exename)
{
argv[0] = exename + 1;
char* dot = _tcsrchr((argv[0]), (int)'.');;
if (dot)
{
*dot = '\0';
}
}
cout << argv[0] << " v" VERSION " " __DATE__ " " __TIME__ << endl;
// get the options
if (!ParseCommandLine(argc, argv, &opts))
{
nRetCode = 2;
return nRetCode; // early exit - input parameter error
}
CStdioFile* inFile = NULL;
CStdioFile* outFile = NULL;
CStdioFile* bankFile = NULL;
XAPFile* masterXap = NULL;
XAPFile* bankXap = NULL;
try
{
if (opts.isVerbose)
{
cout << "Parsing: " << xapMasterName << endl;
}
inFile = new CStdioFile(xapMasterName, CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary | CFile::osSequentialScan);
masterXap = new XAPFile(*inFile, true);
if (opts.isCreate || opts.isExtract)
{
// create the output file in the same location as the input file
xapOutputName = inFile->GetFilePath();
xapOutputName.Replace(inFile->GetFileName(), xapBankName);
xapOutputName.Append(".xap");
// open the output file
outFile = new CStdioFile(xapOutputName, CFile::modeReadWrite | CFile::modeCreate | CFile::shareDenyWrite | CFile::typeBinary | CFile::osSequentialScan);
if (opts.isExtract)
{
int wbIndex = masterXap->FindWaveBank(xapBankName);
int sbIndex = masterXap->FindSoundBank(xapBankName);
if (wbIndex != -1 && sbIndex != -1)
{
if (opts.isVerbose)
{
cout << "Extracting: " << xapBankName << " from " << xapMasterName << endl;
}
masterXap->WriteXapGlobalSettings(*outFile);
masterXap->WriteXapWaveBank(wbIndex, *outFile);
masterXap->WriteXapSoundBank(sbIndex, *outFile);
}
else
{
CString msg;
msg.Format("Unable to find section: %s", xapBankName);
nRetCode = 3;
throw XapException((LPCSTR)msg);
}
}
else // opts.isCreate
{
if (opts.isVerbose)
{
cout << "Creating: " << xapBankName << endl;
}
masterXap->WriteXapGlobalSettings(*outFile);
masterXap->CreateXapWaveBank(*outFile);
masterXap->CreateXapSoundBank(*outFile);
}
}
else if (opts.isMerge)
{
// create the output file in the same location as the input file
xapOutputName = inFile->GetFilePath() + ".new";
// open the output file
outFile = new CStdioFile(xapOutputName, CFile::modeReadWrite | CFile::modeCreate | CFile::shareDenyWrite | CFile::typeBinary | CFile::osSequentialScan);
// open the bank file
bankFile = new CStdioFile(xapBankName, CFile::modeRead | CFile::shareDenyWrite | CFile::typeBinary);
// parse bank file
if (opts.isVerbose)
{
cout << "Parsing: " << xapBankName << endl;
}
bankXap = new XAPFile(*bankFile, true);
// verify the global settings
if (!masterXap->MatchGlobalSettings(bankXap))
{
CString msg = _T("Global Settings do not match" );
nRetCode = 4;
throw XapException((LPCSTR)msg);
}
// check for existing wave and sound banks
int wbIndex = masterXap->FindWaveBank(bankXap->GetWaveBank(0).GetName());
int sbIndex = masterXap->FindSoundBank(bankXap->GetSoundBank(0).GetName());
// appending
if (wbIndex == -1 && sbIndex == -1)
{
if (opts.isVerbose)
{
cout << "Appending wave bank: " << bankXap->GetWaveBank(0).GetName() << " to " << xapMasterName << endl;
}
masterXap->AppendXapWaveBank(bankXap, *outFile);
if (opts.isVerbose)
{
cout << "Appending sound bank: " << bankXap->GetSoundBank(0).GetName() << " to " << xapMasterName << endl;
}
masterXap->AppendXapSoundBank(bankXap, *outFile);
}
else // merging
{
if (opts.isVerbose)
{
cout << "Replacing wave bank: " << bankXap->GetWaveBank(0).GetName() << " in " << xapMasterName << endl;
}
masterXap->ReplaceXapWaveBank(wbIndex, bankXap, *outFile);
if (opts.isVerbose)
{
cout << "Replacing sound bank: " << bankXap->GetSoundBank(0).GetName() << " in " << xapMasterName << endl;
}
masterXap->ReplaceXapSoundBank(wbIndex, sbIndex, bankXap, *outFile);
}
}
}
catch (XapException ex)
{
cout << "Error: " << ex.GetMessage() << endl << endl;
}
catch (CFileException *ex)
{
ex->ReportError();
ex->Delete();
nRetCode = 5;
}
delete masterXap;
delete bankXap;
// close the files
delete inFile;
delete outFile;
delete bankFile;
try
{
CFileStatus status;
// remove the output file if any error is detected
if (nRetCode)
{
if (CFile::GetStatus(xapOutputName, status))
{
CFile::Remove(xapOutputName);
}
}
if (opts.isMerge)
{
// rename new file to old file
if (CFile::GetStatus(xapMasterName, status) &&
CFile::GetStatus(xapOutputName, status))
{
CFile::Remove(xapMasterName);
CFile::Rename(xapOutputName, xapMasterName);
}
}
}
catch (CFileException *ex)
{
ex->ReportError();
ex->Delete();
}
}
return nRetCode;
}
bool ParseCommandLine(int argc, TCHAR *argv[], OPTIONS *opts)
{
bool gotargs = true;
bool haveMaster = false;
int i = 1;
while (i < argc)
{
int pos = 0;
CString arg, command, param;
arg = argv[i++];
command = arg.Tokenize("-=", pos);
if (command != "")
{
param = arg.Tokenize("-=", pos);
}
if (command == "master")
{
if (param != "")
{
xapMasterName = param;
haveMaster = true;
}
else
{
cerr << endl << endl << "No master XAP file specified!" << endl;
break;
}
}
else if (command == "merge")
{
if (param != "")
{
xapBankName = param;
opts->isMerge = true;
}
else
{
cerr << endl << endl << "No project XAP file specified!" << endl;
break;
}
}
else if (command == "extract")
{
if (param != "")
{
xapBankName = param;
opts->isExtract = true;
}
else
{
cerr << endl << endl << "No bank name specified!" << endl;
break;
}
}
else if (command == "create")
{
if (param != "")
{
xapBankName = param;
opts->isCreate = true;
}
else
{
cerr << endl << endl << "No bank name specified!" << endl;
break;
}
}
else if (command == "verbose")
{
opts->isVerbose = true;
}
else
{
cerr << endl << endl << "Unknown option " << arg << endl;
break;
}
}
// validate input
if (!haveMaster ||
(!opts->isCreate && !opts->isMerge && !opts->isExtract) ||
(opts->isCreate && opts->isMerge && opts->isExtract))
{
ShowUsage(argv[0]);
gotargs = false;
}
return gotargs;
}
void ShowUsage(char* exename)
{
cerr << endl;
cerr << "Usage: " << exename << " <switches>" << endl << endl;
cerr << "[-merge=filename.xap | -extract=bank name] - specify only one of these" << endl;
cerr << "-master=filename.xap - specify the master XAP file" << endl;
}