SBSPSS/Utils/MkData/MkData.cpp
2000-08-29 16:26:01 +00:00

592 lines
14 KiB
C++
Raw Blame History

/************************/
/*** 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);
}