/************************/ /*** 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[] = "\\/!�$%^&*()+-=-:. "; 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); }