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

296 lines
7.3 KiB
C++

// xap2td.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "xap2td.h"
#include <afxtempl.h>
#include <conio.h> //for _kbhit()
#include <fstream>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// The one and only application object
CWinApp theApp;
using namespace std;
bool g_bStrict = false; // if true, do strict verification on project file. This includes enforcing a 1:1 mapping of sound to wave banks.
bool g_bDumpStats = false; // if true, dump xap data to the screen
bool g_bLog = false; // if true, will log to a file (xap2td.log)
ofstream g_logFile;
void CXap2tdCommandLineInfo::ParseParam(const char* pszParam, BOOL bFlag, BOOL bLast)
{
if (bFlag)
{
if (!stricmp(pszParam, "strict"))
g_bStrict = true;
else if (!stricmp(pszParam, "dumpstats"))
g_bDumpStats = true;
else if (!stricmp(pszParam, "log"))
g_bLog = true;
else
{
ShowUsage();
}
}
CCommandLineInfo::ParseParam(pszParam, bFlag, bLast);
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print an error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
CXap2tdCommandLineInfo cmdInfo;
theApp.ParseCommandLine(cmdInfo);
CStdioFile ProjectFile;
CString ProjectFileName;
CStdioFile HeaderFile;
CString HeaderFileName;
cout << "R*SD XACT 2 Project File (.xap) to TD File Converter v" << VERSION_STR << endl << endl;
if (argc < 2 || argc > 5 || cmdInfo.m_strFileName.IsEmpty())
{
ShowUsage();
}
ProjectFileName = cmdInfo.m_strFileName;
HeaderFileName = ProjectFileName;
HeaderFileName.Replace(".xap", ".h");
if (ProjectFileName.Right(4) != ".xap")
{
cerr << "Project file name must end in .xap!" << endl;
WaitForKey();
return 1;
}
//Make sure the .td files emerge in the same directory that the .xap and .h files are in.
CString Path(".");
int index = ProjectFileName.ReverseFind('\\');
if (index == -1)
index = ProjectFileName.ReverseFind('/');
if (index != -1)
{
Path = ProjectFileName.Left(index + 1);
SetCurrentDirectory((LPCSTR) Path);
}
CString logFilePath = Path + CString("\\xap2td.log");
if (g_bLog)
{
char fullPath[_MAX_PATH];
GetFullPathName((LPCSTR) logFilePath, _MAX_PATH, fullPath, NULL);
cout << "Logging to file: " << fullPath << "." << endl << endl;
time_t osBinaryTime;
time(&osBinaryTime);
CTime time(osBinaryTime);
g_logFile.open((LPCSTR)logFilePath, ofstream::out | ofstream::trunc);
g_logFile << "R*SD XACT 2 Project File (.xap) to TD File Converter v" << VERSION_STR << endl << endl;
g_logFile << time.Format( "%A, %B %d, %Y %I:%M:%S %p" ) << endl << endl;
}
if (!ProjectFile.Open(ProjectFileName, CFile::modeRead | CFile::shareDenyNone | CFile::typeBinary | CFile::osSequentialScan))
{
//Couldn't open project file
cerr << "Unable to open project file " << (LPCTSTR) ProjectFileName << "!" << endl;
WaitForKey();
return 1;
}
if (!HeaderFile.Open(HeaderFileName, CFile::modeRead | CFile::shareDenyNone))
{
//Couldn't open output file
cerr << "Unable to open header file " << (LPCTSTR) HeaderFileName << "!" << endl;
ProjectFile.Close();
WaitForKey();
return 1;
}
XAPFile* xap = NULL;
try
{
//Load up XAP data
cout << "Loading .xap file " << (LPCSTR) ProjectFile.GetFilePath() << "." << endl;
if (g_bLog)
g_logFile << "Loading .xap file " << (LPCSTR) ProjectFile.GetFilePath() << "." << endl << endl;
xap = new XAPFile(ProjectFile, g_bStrict);
//Optionally dump stats
if (g_bDumpStats)
xap->DumpStats(cout);
if (g_bLog)
xap->DumpStats(g_logFile);
//Make sure cue ordering is correct based on header file enums
cout << "Loading header file " << (LPCSTR) HeaderFile.GetFilePath() << "." << endl << endl;
if (g_bLog)
g_logFile << "Loading header file " << (LPCSTR) HeaderFile.GetFilePath() << "." << endl << endl;
xap->ReorderCues(HeaderFile);
//Write out the .td files
WriteTdFiles(xap);
cout << "Done!" << endl;
if (g_bLog)
g_logFile << "Done!" << endl << endl;
}
catch (XapException e)
{
cout << "Error: " << e.GetMessage() << endl << endl;
cout << "BUILD FAILED -- ERRORS ENCOUNTERED!" << endl;
if (g_bLog)
{
g_logFile << "Error: " << e.GetMessage() << endl << endl;
g_logFile << "BUILD FAILED -- ERRORS ENCOUNTERED!" << endl;
}
nRetCode = 1;
}
delete xap; //Safe even if NULL -- get over it.
ProjectFile.Close();
HeaderFile.Close();
if (g_bLog)
g_logFile.close();
}
WaitForKey();
return nRetCode;
}
void WriteTdFiles(const XAPFile* xapFile)
{
CStdioFile TDFile;
for (int i = 0; i < xapFile->GetNumSoundBanks(); i++)
{
CString TDFileName = xapFile->GetSoundBank(i).GetName() + CString(".td");
if (!TDFile.Open(TDFileName, CFile::modeWrite | CFile::modeCreate | CFile::shareDenyWrite))
{
//Couldn't open output file
CString error;
error.Format("Unable to open/create .td file %s.", (LPCTSTR) TDFileName);
throw XapException((LPCSTR)error);
}
CString strOutLine;
int NumCues = (int) xapFile->GetSoundBank(i).GetNumCues();
cout << "Writing .td file " << (LPCSTR) TDFile.GetFilePath() << "." << endl;
if (g_bLog)
g_logFile << "Writing .td file " << (LPCSTR) TDFile.GetFilePath() << "." << endl;
strOutLine = "TD_FILE "TD_VERSION_STR"\n";
TDFile.WriteString(strOutLine);
strOutLine.Format("STREAMING %d\n", xapFile->GetSoundBank(i).IsStreaming() ? 1 : 0);
TDFile.WriteString(strOutLine);
strOutLine.Format("BUFFERSIZE %d\n", xapFile->GetSoundBank(i).CalcStreamingBufferSize());
TDFile.WriteString(strOutLine);
strOutLine.Format("WAVEBANKREFS %d\n", xapFile->GetSoundBank(i).GetNumWaveBankRefs());
TDFile.WriteString(strOutLine);
for (int j = 0; j < xapFile->GetSoundBank(i).GetNumWaveBankRefs(); j++)
{
strOutLine.Format("\t%s\n", xapFile->GetSoundBank(i).GetWaveBankRef(j).GetName());
TDFile.WriteString(strOutLine);
}
strOutLine.Format("NUMSOUNDS %d\n", NumCues);
TDFile.WriteString(strOutLine);
for (int j = 0; j < NumCues; j++)
{
XACTCue cue = xapFile->GetSoundBank(i).GetCue(j);
char temp[32];
strOutLine = "\t";
strOutLine += cue.GetName();
strOutLine += "\n";
TDFile.WriteString(strOutLine);
strOutLine = "\t\t";
strOutLine += _itoa(j, temp, 10); //cue index
strOutLine += "\n";
TDFile.WriteString(strOutLine);
strOutLine = "\t\t";
strOutLine += cue.IsLooping() ? "1" : "0"; //Loop flag.
strOutLine += "\n";
TDFile.WriteString(strOutLine);
strOutLine = "\t\t";
strOutLine += _itoa(cue.GetLenghtInMs(), temp, 10); //length in milliseconds. Note that this only reflects
//the length of the last wave of the last sound in this
//cue, so really only useful when there's a 1:1:1 cue:sound:wave
//mapping
strOutLine += "\n";
TDFile.WriteString(strOutLine);
}
TDFile.Close();
}
}
void ShowUsage(void)
{
cerr << "Usage: xap2td <filename>.xap [-strict] [-dumpstats] [-log]" << endl;
cerr << " or just drag the .xap file onto executable." << endl;
WaitForKey();
exit(1);
}
void WaitForKey(int timeOutMS /* = 2000 */)
{
int ms = 0;
cerr << endl << "Press any key..." << endl;
do
{
Sleep(100);
ms += 100;
} while (!_kbhit() && ms < timeOutMS);
}