592 lines
14 KiB
C++
592 lines
14 KiB
C++
/************************/
|
||
/*** DataFile Creator ***/
|
||
/************************/
|
||
|
||
#include <windows.h>
|
||
#include <stdlib.h>
|
||
#include <stdarg.h>
|
||
#include <string.h>
|
||
#include <stdio.h>
|
||
#include <time.h>
|
||
#include <math.h>
|
||
#include <io.h>
|
||
#include <fstream.h>
|
||
#include <conio.h>
|
||
#include <vector>
|
||
#include "Mkdata.h"
|
||
|
||
using namespace std;
|
||
|
||
|
||
//***********************************************************************
|
||
//***********************************************************************
|
||
//***********************************************************************
|
||
int DebugFlag=0;
|
||
int AlignSize=2048;
|
||
char *AlignBuffer;
|
||
|
||
//***********************************************************************
|
||
CBank Banks;
|
||
CFileList Files;
|
||
char *BaseDir=0;
|
||
|
||
//***********************************************************************
|
||
|
||
static void app_debug_msg(const char * pszFmt,va_list args)
|
||
{
|
||
char szBuf[256];
|
||
vsprintf(szBuf,pszFmt,args);
|
||
|
||
printf("%s\n",szBuf);
|
||
}
|
||
|
||
|
||
//******************************************************************
|
||
//******************************************************************
|
||
|
||
void __cdecl DEBUG(const char * pszFmt,...)
|
||
{
|
||
if (DebugFlag)
|
||
if (pszFmt)
|
||
{
|
||
va_list args;
|
||
va_start(args,pszFmt);
|
||
app_debug_msg(pszFmt,args);
|
||
va_end(args);
|
||
}
|
||
}
|
||
|
||
void __cdecl FATAL(const char * pszFmt,...)
|
||
{
|
||
if (pszFmt)
|
||
{
|
||
va_list args;
|
||
va_start(args,pszFmt);
|
||
app_debug_msg(pszFmt,args);
|
||
va_end(args);
|
||
}
|
||
exit(123);
|
||
}
|
||
|
||
//******************************************************************
|
||
char *LoadFileInMem(const char * FileName,int *OutSize)
|
||
{
|
||
FILE *FileHandle;
|
||
char *Buffer;
|
||
int Size;
|
||
|
||
FileHandle= fopen( FileName,"rb" );
|
||
if(!FileHandle)
|
||
{
|
||
FATAL("ERROR : Could not open file %s\n",FileName);
|
||
}
|
||
else
|
||
{
|
||
fseek(FileHandle,0,SEEK_END);
|
||
Size=ftell(FileHandle);
|
||
fseek(FileHandle,0,SEEK_SET);
|
||
|
||
if( (Buffer=(char*)malloc(Size))==NULL ) {printf("Out of memory.\n");exit(123);}
|
||
fread(Buffer, 1,Size,FileHandle);
|
||
fclose(FileHandle);
|
||
}
|
||
if (OutSize) *OutSize=Size;
|
||
return Buffer;
|
||
}
|
||
|
||
|
||
//******************************************************************
|
||
static char s_illegalChars[] = "\\/!<21>$%^&*()+-=-:. ";
|
||
static int s_nbChars = sizeof(s_illegalChars);
|
||
|
||
void convertIllegalChar( char *c )
|
||
{
|
||
for (int i=0;i<s_nbChars;i++)
|
||
{
|
||
if (*c == s_illegalChars[i]) *c = '_';
|
||
}
|
||
}
|
||
|
||
//******************************************************************
|
||
void ConvertString(char *Str)
|
||
{
|
||
strupr(Str);
|
||
while(*Str) convertIllegalChar(Str++);
|
||
}
|
||
|
||
//******************************************************************
|
||
void MakeEqName(char *In,char *Out)
|
||
{
|
||
int StrLen=strlen(In);
|
||
int begin0 = 0;
|
||
int begin1 = 0;
|
||
|
||
for (int i=0;i<StrLen;i++)
|
||
{
|
||
if (In[i] == '/' || In[i] == '\\')
|
||
{
|
||
begin0 = begin1;
|
||
begin1 = i;
|
||
}
|
||
}
|
||
if (In[begin0]=='/' || In[begin0]=='\\') begin0++;
|
||
strcpy(Out,In+begin0);
|
||
ConvertString(Out);
|
||
|
||
}
|
||
|
||
//***********************************************************************
|
||
//*** CFileList *********************************************************
|
||
//***********************************************************************
|
||
CFileList::~CFileList()
|
||
{
|
||
int ListSize=FileList.size();
|
||
for (int i=0;i<ListSize;i++) if (!FileList[i].BankIdx) free(FileList[i].Data);
|
||
|
||
}
|
||
//***********************************************************************
|
||
int CFileList::FindFileIdx(char *Filename)
|
||
{
|
||
int ListSize=FileList.size();
|
||
for (int i=0;i<ListSize;i++) if (!strcmp(Filename,FileList[i].Filename)) return(i);
|
||
return(-1);
|
||
|
||
}
|
||
//***********************************************************************
|
||
int CFileList::AddFile(char *BaseFilename,int BankIdx)
|
||
{
|
||
int Idx;
|
||
sFile File;
|
||
|
||
File.BankIdx=BankIdx;
|
||
strupr(BaseFilename);
|
||
sprintf(File.Filename,"%s/%s",BaseDir,BaseFilename);
|
||
MakeEqName(File.Filename,File.ShortName);
|
||
Idx=FindFileIdx(File.Filename);
|
||
|
||
if (Idx==-1)
|
||
{
|
||
Idx=FileList.size();
|
||
if (!BankIdx)
|
||
{
|
||
File.Data=LoadFileInMem(File.Filename,&File.Size);
|
||
}
|
||
else
|
||
{
|
||
File.BankIdx=BankIdx;
|
||
}
|
||
FileList.push_back(File);
|
||
}
|
||
return(Idx);
|
||
|
||
}
|
||
|
||
//***********************************************************************
|
||
//*** CBank *************************************************************
|
||
//***********************************************************************
|
||
void CBank::Start(char *Name,int Align)
|
||
{
|
||
sBank B;
|
||
if (Align==0) Align=AlignSize;
|
||
strcpy(B.Name,Name);
|
||
B.Align=Align;
|
||
CurrentBank=BankList.size();
|
||
BankList.push_back(B);
|
||
if (CurrentBank) Files.AddFile(Name,CurrentBank);
|
||
}
|
||
|
||
//***********************************************************************
|
||
void CBank::End()
|
||
{
|
||
CurrentBank=0;
|
||
}
|
||
|
||
//***********************************************************************
|
||
int CBank::FindEntry(int Idx)
|
||
{
|
||
sBank &ThisBank=GetBank(CurrentBank);
|
||
|
||
int ListSize=ThisBank.FileList.size();
|
||
|
||
for (int i=0;i<ListSize;i++)
|
||
{
|
||
if (ThisBank.FileList[i].ListIdx==Idx) return(i);
|
||
}
|
||
return(-1);
|
||
}
|
||
|
||
//***********************************************************************
|
||
void CBank::Add(char *Filename)
|
||
{
|
||
sBankEntry Entry;
|
||
|
||
if (Filename[0]==CHAR_SKIP) {Files.AddFile(Filename+1); return;}
|
||
Entry.ListIdx=Files.AddFile(Filename);
|
||
if (FindEntry(Entry.ListIdx)==-1) BankList[CurrentBank].FileList.push_back(Entry);
|
||
}
|
||
|
||
//******************************************************************
|
||
//*** Script shite *************************************************
|
||
//******************************************************************
|
||
int IsWhiteSpace(char c)
|
||
{
|
||
if (c==' ') return(1);
|
||
if (c==CHAR_TAB) return(1);
|
||
if (c==0xd) return(1);
|
||
if (c==0xa) return(1);
|
||
return(0);
|
||
}
|
||
|
||
//******************************************************************
|
||
char *SkipWhiteSpace(char *Ptr)
|
||
{
|
||
while (IsWhiteSpace(*Ptr)) Ptr++;
|
||
return(Ptr);
|
||
}
|
||
|
||
//******************************************************************
|
||
char *GotoNextLine(char *Ptr)
|
||
{
|
||
while (*Ptr && *Ptr!=CHAR_EOL ) Ptr++;
|
||
return(Ptr+2);
|
||
}
|
||
|
||
//******************************************************************
|
||
void Line2Str(char *Ptr,char *EndPtr)
|
||
{
|
||
int i=0;
|
||
while (!IsWhiteSpace(*Ptr) && Ptr<EndPtr) Ptr++;
|
||
*Ptr=0;
|
||
}
|
||
|
||
//******************************************************************
|
||
char *ScriptComment(char *Ptr,char *EndPtr)
|
||
{
|
||
return(GotoNextLine(Ptr));
|
||
}
|
||
|
||
//******************************************************************
|
||
char *ScriptStartBank(char *Ptr,char *EndPtr)
|
||
{
|
||
int Align;
|
||
char *Name;
|
||
|
||
Ptr=SkipWhiteSpace(Ptr+1);
|
||
Line2Str(Ptr,EndPtr);
|
||
Name=Ptr;
|
||
Ptr+=strlen(Ptr)+1;
|
||
Align=atoi(Ptr);
|
||
DEBUG("[%s] (%i)\n\t{",Name,Align);
|
||
Banks.Start(Name,Align);
|
||
return(GotoNextLine(Ptr));
|
||
}
|
||
|
||
//******************************************************************
|
||
char *ScriptEndBank(char *Ptr,char *EndPtr)
|
||
{
|
||
DEBUG("\t}");
|
||
Banks.End();
|
||
return(GotoNextLine(Ptr));
|
||
}
|
||
|
||
//******************************************************************
|
||
char *ScriptFile(char *Ptr,char *EndPtr)
|
||
{
|
||
Line2Str(Ptr,EndPtr);
|
||
Banks.Add(Ptr);
|
||
if (DebugFlag)
|
||
{
|
||
if (Banks.GetCurrentBankNo()) printf("\t");
|
||
printf("%s\n",Ptr);
|
||
}
|
||
return(GotoNextLine(Ptr));
|
||
}
|
||
|
||
//******************************************************************
|
||
void ReadScript(char *Filename)
|
||
{
|
||
char *Script,*Ptr,*EndPtr;
|
||
int Size;
|
||
Script = (char *)LoadFileInMem( Filename,&Size);
|
||
Ptr=Script;
|
||
EndPtr=Ptr+Size;
|
||
|
||
printf("Reading %s\n",Filename);
|
||
while (Ptr<EndPtr)
|
||
{
|
||
Ptr=SkipWhiteSpace(Ptr);
|
||
if (Ptr>=EndPtr) return;
|
||
switch (*Ptr)
|
||
{
|
||
case CHAR_COMMENT:
|
||
Ptr=ScriptComment(Ptr,EndPtr);
|
||
break;
|
||
case CHAR_STARTBANK:
|
||
Ptr=ScriptStartBank(Ptr,EndPtr);
|
||
break;
|
||
case CHAR_ENDBANK:
|
||
Ptr=ScriptEndBank(Ptr,EndPtr);
|
||
break;
|
||
default:
|
||
Ptr=ScriptFile(Ptr,EndPtr);
|
||
break;
|
||
}
|
||
}
|
||
free(Script);
|
||
}
|
||
|
||
//***********************************************************************
|
||
//***********************************************************************
|
||
//***********************************************************************
|
||
void ResetFAT(std::vector<sFAT> &FAT)
|
||
{
|
||
int FATSize=Files.GetCount();
|
||
int Loop;
|
||
|
||
FAT.resize(FATSize);
|
||
for (Loop=0; Loop<FATSize; Loop++)
|
||
{
|
||
sFile &F=Files.GetFile(Loop);
|
||
FAT[Loop].FilePos=-1;
|
||
FAT[Loop].FileSize=F.Size;
|
||
}
|
||
}
|
||
|
||
//***********************************************************************
|
||
void AlignData(FILE *FileHandle,int Align)
|
||
{
|
||
int Pos=ftell(FileHandle);
|
||
int AlignPad= (Pos & (Align-1));
|
||
if (AlignPad) fwrite(AlignBuffer,1,Align-AlignPad,FileHandle);
|
||
}
|
||
|
||
//***********************************************************************
|
||
int WriteFAT(FILE *FileHandle,std::vector<sFAT> &FAT,int Align)
|
||
{
|
||
int Pos=ftell(FileHandle);
|
||
int FATSize=Files.GetCount();
|
||
|
||
for (int Loop=0;Loop<FATSize;Loop++)
|
||
{
|
||
fwrite(&FAT[Loop],1,sizeof(sFAT),FileHandle);
|
||
}
|
||
AlignData(FileHandle,Align);
|
||
|
||
return(Pos);
|
||
}
|
||
|
||
//***********************************************************************
|
||
void WriteFileData(FILE *FileHandle,sFile &File,int Align,sFAT &ParentFAT)
|
||
{
|
||
ParentFAT.FilePos=ftell(FileHandle);
|
||
ParentFAT.FileSize=File.Size;
|
||
|
||
fwrite(File.Data,1,File.Size,FileHandle);
|
||
AlignData(FileHandle,Align);
|
||
}
|
||
|
||
//***********************************************************************
|
||
void WriteBankData(FILE *FileHandle,int BankIdx,sFAT &ParentFAT)
|
||
{
|
||
std::vector<sFAT> FAT;
|
||
sBank &ThisBank=Banks.GetBank(BankIdx);
|
||
int ThisListSize=ThisBank.FileList.size();
|
||
int Loop;
|
||
long StartFilePos,EndFilePos;
|
||
|
||
// reset FAT and write dummy FAT
|
||
ResetFAT(FAT);
|
||
ParentFAT.FilePos=WriteFAT(FileHandle,FAT,ThisBank.Align);
|
||
StartFilePos=ftell(FileHandle);;
|
||
|
||
// Write files
|
||
|
||
for (Loop=0; Loop<ThisListSize; Loop++)
|
||
{
|
||
int Idx=ThisBank.FileList[Loop].ListIdx;
|
||
sFile &ThisFile=Files.GetFile(Idx);
|
||
WriteFileData(FileHandle,ThisFile,ThisBank.Align,FAT[Idx]);
|
||
FAT[Idx].FilePos-=ParentFAT.FilePos;
|
||
DEBUG("\t %s %i %i",ThisFile.Filename,FAT[Idx].FilePos,FAT[Idx].FileSize);
|
||
}
|
||
|
||
EndFilePos=ftell(FileHandle);
|
||
fseek(FileHandle,ParentFAT.FilePos,SEEK_SET);
|
||
WriteFAT(FileHandle,FAT,ThisBank.Align);
|
||
fseek(FileHandle,EndFilePos,SEEK_SET);
|
||
|
||
ParentFAT.FileSize=EndFilePos-StartFilePos;
|
||
// printf("%i %i\n",BankSize,ParentFAT.FileSize);
|
||
}
|
||
|
||
//***********************************************************************
|
||
void WriteData(char *Filename)
|
||
{
|
||
FILE *FileHandle;
|
||
std::vector<sFAT> FAT;
|
||
int FATSize=Files.GetCount(),Idx;
|
||
|
||
FileHandle= fopen( Filename,"wb" );
|
||
if(!FileHandle) FATAL( "Could not write %s", Filename);
|
||
ResetFAT(FAT);
|
||
WriteFAT(FileHandle,FAT,AlignSize);
|
||
for (Idx=0; Idx<FATSize; Idx++)
|
||
{
|
||
sFile &ThisFile=Files.GetFile(Idx);
|
||
if (ThisFile.BankIdx)
|
||
{ // Databank
|
||
DEBUG("Bank %s",ThisFile.Filename);
|
||
WriteBankData(FileHandle,ThisFile.BankIdx,FAT[Idx]);
|
||
FAT[Idx].FileSize+=FATSize*sizeof(FAT);
|
||
// printf("%i\n",(int)FAT[Idx].FileSize);
|
||
|
||
AlignData(FileHandle,AlignSize);
|
||
}
|
||
else
|
||
{ // Normal File
|
||
WriteFileData(FileHandle,ThisFile,AlignSize,FAT[Idx]);
|
||
DEBUG("%s %i %i",ThisFile.Filename,FAT[Idx].FilePos,FAT[Idx].FileSize);
|
||
}
|
||
}
|
||
|
||
fseek(FileHandle,0,SEEK_SET);
|
||
WriteFAT(FileHandle,FAT,AlignSize);
|
||
fclose(FileHandle);
|
||
}
|
||
|
||
//***********************************************************************
|
||
//***********************************************************************
|
||
//***********************************************************************
|
||
void WriteFileHeader(FILE *FileHandle,char *Name)
|
||
{
|
||
static Count=0;
|
||
|
||
if (!Count)
|
||
fprintf( FileHandle, "%s=%i,\n" ,Name,Count);
|
||
else
|
||
fprintf( FileHandle, "%s,\n" ,Name);
|
||
|
||
Count++;
|
||
|
||
}
|
||
|
||
//***********************************************************************
|
||
void WriteBankHeader(FILE *FileHandle,int BankIdx)
|
||
{
|
||
sBank &ThisBank=Banks.GetBank(BankIdx);
|
||
|
||
WriteFileHeader(FileHandle,ThisBank.Name);
|
||
}
|
||
|
||
//***********************************************************************
|
||
void WriteHeader(char *Filename)
|
||
{
|
||
FILE *FileHandle;
|
||
int FATSize=Files.GetCount(),Idx;
|
||
|
||
|
||
FileHandle= fopen( Filename,"wb" );
|
||
if(!FileHandle) FATAL( "Could not write %s", Filename);
|
||
fprintf( FileHandle, "#ifndef __FILE_EQUATES_H__\n");
|
||
fprintf( FileHandle, "#define __FILE_EQUATES_H__\n\n");
|
||
fprintf( FileHandle, "enum FileEquate\n" );
|
||
fprintf( FileHandle, "{\n" );
|
||
|
||
for (Idx=0; Idx<FATSize; Idx++)
|
||
{
|
||
sFile &ThisFile=Files.GetFile(Idx);
|
||
if (ThisFile.BankIdx)
|
||
{ // Databank
|
||
WriteBankHeader(FileHandle,ThisFile.BankIdx);
|
||
}
|
||
else
|
||
{ // Normal File
|
||
WriteFileHeader(FileHandle,ThisFile.ShortName);
|
||
}
|
||
}
|
||
|
||
fprintf( FileHandle, "\nFileEquate_MAX,\n");
|
||
fprintf( FileHandle, "};\n" );
|
||
fprintf( FileHandle, "#endif\n" );
|
||
|
||
fclose(FileHandle);
|
||
}
|
||
|
||
//***********************************************************************
|
||
//***********************************************************************
|
||
//***********************************************************************
|
||
int main(int argc, char *argv[])
|
||
{
|
||
char *DataFilename=0;
|
||
char *IncludeFilename=0;
|
||
std::vector<char*> Scripts;
|
||
// Parse Input
|
||
for (int Loop=1;Loop<argc;Loop++)
|
||
{
|
||
char *StrPtr=argv[Loop];
|
||
if (StrPtr[0]=='-') StrPtr++;
|
||
switch(StrPtr[0])
|
||
{
|
||
case 'o': // Output
|
||
if(*StrPtr=':')StrPtr++;
|
||
DataFilename=StrPtr+1;
|
||
break;
|
||
case 's': // script
|
||
if(*StrPtr=':')StrPtr++;
|
||
Scripts.push_back(StrPtr+1);
|
||
break;
|
||
case 'i': // include file
|
||
if(*StrPtr=':')StrPtr++;
|
||
IncludeFilename=StrPtr+1;
|
||
break;
|
||
case 'd': // Cache script
|
||
DebugFlag=1;
|
||
break;
|
||
case 'a': // Align Size
|
||
if(*StrPtr=':')StrPtr++;
|
||
AlignSize=atoi(StrPtr+1);
|
||
break;
|
||
case 'b': // Base Dir
|
||
if(*StrPtr=':')StrPtr++;
|
||
BaseDir=StrPtr+1;
|
||
break;
|
||
default:
|
||
printf("Unknown Param [%s]\n",StrPtr);
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!AlignSize) FATAL("ERROR: AlignSize is 0");
|
||
|
||
if(!DataFilename || !Scripts.size() || !BaseDir)
|
||
{
|
||
printf("Error in command line\n");
|
||
printf("Usage : MkData [files] -o:OutFile\n");
|
||
printf(" -s\tIn Script\n");
|
||
printf(" -i\tHeaderFile\n");
|
||
printf(" -a\tAlignSize (Default 2048)\n");
|
||
printf(" -d\tDebug Msgs\n");
|
||
printf(" -b\tBase Dir\n");
|
||
return(0);
|
||
}
|
||
|
||
if( (AlignBuffer=(char*)malloc(AlignSize))==NULL ) {printf("Couldnt Alloc AlignBuffer.\n");exit(123);}
|
||
for (int i=0;i<AlignSize;i++) AlignBuffer[i]=0;
|
||
|
||
strupr(DataFilename);
|
||
printf("Creating Data File: %s\n",DataFilename);
|
||
Banks.Start("",AlignSize);
|
||
for (int Script=0;Script<Scripts.size();Script++)
|
||
{
|
||
ReadScript(Scripts[Script]);
|
||
}
|
||
|
||
printf("Writing Data File: %s\n",DataFilename);
|
||
WriteData(DataFilename);
|
||
if (IncludeFilename) WriteHeader(IncludeFilename);
|
||
printf("FATSize =%i\n",Files.GetCount()*sizeof(sFAT));
|
||
|
||
return(0);
|
||
}
|
||
|