//
// File loader
//
#include <allegro.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include "ithelib.h"
#include "loadfile.h"
#include "oscli.h"
#include "tdgui.h"
// Defines
// Macro to make a directory using the right API version
#ifdef _WIN32
#define MAKE_DIR(a) mkdir(a)
#else
#define MAKE_DIR(a) mkdir(a,S_IRUSR|S_IWUSR|S_IXUSR);
#endif
// Variables
char savegamedest[1024];
// Functions
extern int check_rar_file(char *filename);
extern void scan_rar_file(char *filename);
#ifdef _WIN32
static void winslash(char *name);
#endif
static int blank_savegame(const char *name, int attrib, void *irrelevant);
static int copy_savegame(const char *name, int attrib, void *irrelevant);
// Code
// user can choose a datafile
int data_choose(char *path,char *path_file,int size)
{
char *home;
int i,len;
int k=0;
memset(path,0,size); // Blank it
// home=getenv("HOME");
// if(!home)
home=".";
strcpy(path_file,home);
strcat(path_file,"/");
// if(!file_select_ex("load game (gamedata.ini)",path_file,"ini",size,0,0))
if(!billfile_select("load game (gamedata.ini)",path_file,"ini"))
return 0;
else
{
len = strlen(path_file);
strslash(path_file); // Ensure slashes are correct
// Find last slash
for (i=0;i<len;i++)
{
if (path_file[i]=='/')
{
k=i;
}
}
i=0;
// Copy everything up to the last slash
while(i<=k)
{
path[i]=path_file[i];
i++;
}
return 1;
}
}
char *loadfile(char *srcname, char *destname)
{
// Normalise filename
strcpy(destname,srcname);
strlwr(destname);
strslash(destname);
// Check it
if(iexist(destname))
return destname;
return NULL;
}
int fileexists(char *name)
{
//char fn[1024];
if(!name)
ithe_panic("fileexists: NULL filename given",NULL);
return(iexist(name));
//if(strchr(name,'#'))
// return(exists(name));
//ilog_quiet("F-exists\n");
//return((int)loadfile(name,fn));
}
int filelen(char *fname)
{
char fn[1024];
if(!fname)
ithe_panic("filelen: NULL filename given",NULL);
if(strchr(fname,'#'))
return file_size(fname);
if(loadfile(fname,fn))
return file_size(fn);
// Die
ithe_panic("filelen: file does not exist",fname);
return 0;
}
/*
* Convert slashes to windows format
*/
#ifdef _WIN32
void winslash(char *name)
{
char *a;
do {
a=strchr(name,'/');
if(a)
*a='\\';
// *a='|';
} while(a);
}
#endif
/*
* Convert a path from Absolute to Relative format
*/
void clean_path(char *fn)
{
char filename[1024];
char pathname[1024];
char *ptr;
int len;
strcpy(pathname,"/");
strcat(pathname,projectname);
strcat(pathname,"/");
strcpy(filename,"/");
strcat(filename,fn);
strslash(pathname);
strslash(filename);
strlwr(pathname);
strlwr(filename);
// OK, everything should be ready.
ptr = strstr(filename,pathname);
if(!ptr)
return; // It's clean
// It's not clean. Clean it.
ptr += strlen(pathname);
ptr--; // Remove initial '/'
len = (int)(ptr-filename);
strcpy(filename,&fn[len]);
strcpy(fn,filename);
}
/*
* .WAD manipulation functions. Assumes a 40-byte signature in front of the
* data and works around this. If you strip the first 40 bytes of the
* file away you have a true .WAD file that can load into DEU.
*/
void StartWad(IFILE *ofp)
{
iputl_i(0x44415750,ofp);// PWAD
iputl_i(0L,ofp);// Entries, patched later
iputl_i(0L,ofp);// Offset, ditto
}
/*
* Append the directory to the file to make a true .WAD
*/
void FinishWad(IFILE *ofp, WadEntry entries[])
{
unsigned int directory,num;
directory = itell(ofp);
// Write the entries
for(num=0;entries[num].name;num++)
{
iputl_i(entries[num].start-40,ofp); // Cancel out the signature
iputl_i(entries[num+1].start-entries[num].start,ofp);
iwrite((unsigned char *)entries[num].name,8,ofp);
}
// Back up the WAD and write the initial entries. Since each IRE file has
// a 40-byte signature of it's own, we don't start from 4 like DEU does.
iseek(ofp,44,SEEK_SET);
iputl_i(num,ofp);
iputl_i(directory-40,ofp); // -40 to cancel the signature
// Finish
iclose(ofp);
}
int GetWadEntry(IFILE *ifp, char *name)
{
unsigned int sig,num,off,ctr;
char buf[]="nothing!";
iseek(ifp,40,SEEK_SET);
sig = igetl_i(ifp);
if(sig != 0x44415750)
return 0;
num = igetl_i(ifp);
off = igetl_i(ifp);
iseek(ifp,off+40,SEEK_SET); // Cancel out the signature
for(ctr=0;ctr<num;ctr++)
{
off = igetl_i(ifp);
igetl_i(ifp); // skip length
iread((unsigned char *)buf,8,ifp);
if(!strcmp(buf,name))
{
iseek(ifp,off+40,SEEK_SET); // Cancel out the signature
return 1;
}
}
return 0;
}
// Work out savegame dir (and save it)
char *getsavegamedir(int savegame)
{
char temp[256];
char *home;
char *out;
out=strLocalBuf(); // Get local string (with garbage collection)
#ifdef __SOMEUNIX__
home=getenv("HOME");
if(!home)
return NULL;
sprintf(temp,"%s/.iresaves/%s/slot%02d/",home,projectname,savegame);
#else
sprintf(temp,"savegame\\%s\\slot%02d\\",projectname,savegame);
#ifndef _WIN32
strslash(temp);
#endif
#endif
strcpy(out,temp);
return out;
}
// File mangling for mapfiles, work out the full path and filename
char *makemapname(int number, int savegame, char *extension)
{
char *temp,*t2;
temp=strLocalBuf();
// Savegame 0 means the actual level data (master copy) not a savegame,
// (savegames are modified copies of the original).
if(!savegame)
sprintf(temp,"%s%s%04d%s",projectdir,projectname,number,extension);
else
{
t2=getsavegamedir(savegame);
if(!t2)
return NULL;
sprintf(temp,"%s%s%04d%s",t2,projectname,number,extension);
#ifdef _WIN32
strwinslash(temp);
#else
strslash(temp);
#endif
}
return temp;
}
// Make savegame dir (somewhat involved)
int makesavegamedir(int savegame, int erase)
{
char temp[512];
char *home;
#ifdef __SOMEUNIX__
home=getenv("HOME");
if(!home)
return 0;
sprintf(temp,"%s/.iresaves",home);
MAKE_DIR(temp);
sprintf(temp,"%s/.iresaves/%s",home,projectname);
MAKE_DIR(temp);
sprintf(temp,"%s/.iresaves/%s/slot%02d",home,projectname,savegame);
MAKE_DIR(temp);
// Empty it
if(erase)
{
// sprintf(temp,"rm -f %s/.iresaves/%s/slot%02d/*",home,projectname,savegame);
// system(temp);
sprintf(temp,"%s/.iresaves/%s/slot%02d/*",home,projectname,savegame);
for_each_file_ex(temp,0,FA_DIREC,blank_savegame,0);
}
#else
MAKE_DIR("savegame");
sprintf(temp,"savegame\\%s",projectname);
#ifndef _WIN32
strslash(temp);
#endif
MAKE_DIR(temp);
sprintf(temp,"savegame\\%s\\slot%02d",projectname,savegame);
#ifndef _WIN32
strslash(temp);
#endif
MAKE_DIR(temp);
// Empty it
if(erase)
{
sprintf(temp,"savegame\\%s\\slot%02d\\*.*",projectname,savegame);
// for_each_file_ex(temp,FA_RDONLY|FA_ARCH,0,blank_savegame,0);
for_each_file_ex(temp,0,FA_DIREC,blank_savegame,0);
}
#endif
return 1;
}
/*
* Allegro callback function
*/
static int blank_savegame(const char *name, int attrib, void *irrelevant)
{
ilog_quiet("Erase: %s\n",name);
remove(name);
return 0;
}
void copysavegamedir(int src, int dest)
{
char *srcdir;
char *destdir;
destdir=getsavegamedir(dest);
strcpy(savegamedest,destdir); // Copy destination to a global
srcdir=getsavegamedir(src);
strcat(srcdir,"*.*"); // Seek all files
ilog_quiet("Try to copy: %s %s\n",srcdir,savegamedest);
//for_each_file_ex(srcdir,FA_RDONLY|FA_ARCH,0,copy_savegame,0);
for_each_file_ex(srcdir,0,FA_DIREC,copy_savegame,0);
}
/*
* Allegro callback function to copy a single file to a certain directory
*/
static int copy_savegame(const char *name, int attrib, void *irrelevant)
{
FILE *fi,*fo;
char fname[512];
unsigned char buf[4096]; // 4k read buffer
int bytes,total;
fi=fopen(name,"rb");
if(!fi)
{
ilog_quiet("COPY: sourcename: can't open '%s'\n",name);
return 0;
}
// Assemble path - get_filename is an allegro support function to strip
// the path and return a bare filename
strcpy(fname,savegamedest);
strcat(fname,get_filename(name));
fo=fopen(fname,"wb");
if(!fo)
{
fclose(fi);
ilog_quiet("COPY: destname: can't create '%s'\n",fname);
return 0;
}
total=0;
do
{
bytes=fread(buf,1,4096,fi);
total+=bytes;
fwrite(buf,1,bytes,fo);
} while(bytes==4096);
fclose(fi);
fclose(fo);
ilog_quiet("COPY: '%s' to '%s' : %d bytes copied\n",name,fname,total);
return 0;
}
/*
* Read and write RLE sprite files. Average colour weighting can be
* stored in the file as well.
*/
void save_rle_sprite(RLE_SPRITE* spr, char *fname, long avgcol)
{
FILE *fp;
fp = fopen(fname,"wb");
if(!fp)
{
// Couldn't write file. Try building the path first.
makepath(fname);
fp = fopen(fname,"wb");
if(!fp)
return;
}
putw(spr->size, fp);
putw(spr->color_depth, fp);
putw(spr->w, fp);
putw(spr->h, fp);
fwrite(spr->dat, 1, spr->size, fp);
putw(avgcol, fp);
fclose(fp);
}
/*
* Load an RLE-compressed sprite, optionally get the average colour weight
*/
RLE_SPRITE* load_rle_sprite(char *fname, long *avgcol)
{
RLE_SPRITE* spr = 0;
int sz = 0;
FILE *fp;
fp = fopen(fname,"rb");
if(!fp)
return NULL;
sz = getw(fp);
if(sz < 1)
return 0;
spr = calloc(1,sizeof(RLE_SPRITE) + sz);
if(!spr)
{
// out of memory, but skip rest of data in file
fseek(fp, sz + 12, SEEK_SET);
return 0;
}
spr->color_depth = getw(fp);
spr->w = getw(fp);
spr->h = getw(fp);
spr->size = sz;
fread(spr->dat, 1, sz, fp);
// Get average pixel colour, if a pointer is given
if(avgcol)
*avgcol=getw(fp);
fclose(fp);
return spr;
}
#ifdef _WIN32
void makepath(char *fname)
{
char buffer[1024];
char *p,*pp;
strcpy(buffer,fname);
winslash(buffer); // Normalise slashes
p=strrchr(buffer,'\\');
if(p)
*p=0; // Chop off the filename
MAKE_DIR(buffer);
pp=&buffer[0];
do
{
p=strchr(pp,'\\');
if(p)
{
*p=0; // Pop the slash out
MAKE_DIR(buffer);
*p='\\'; // Put it back
pp=++p; // Look for the next one?
}
} while(p);
}
#else
void makepath(char *fname)
{
char buffer[1024];
char *p,*pp;
strcpy(buffer,fname);
strslash(buffer); // Normalise slashes
p=strrchr(buffer,'/');
if(p)
*p=0; // Chop off the filename
MAKE_DIR(buffer);
pp=&buffer[0];
do
{
p=strchr(pp,'/');
if(p)
{
*p=0; // Pop the slash out
MAKE_DIR(buffer);
*p='/'; // Put it back
pp=++p; // Look for the next one?
}
} while(p);
}
#endif
/*
// copy a file from an absolute path to a relative path
void cpfile(char *local_path, char *abs_path, char *file_name)
{
char cmd[1024];
char tmp1[1024];
char tmp2[1024];
FILE *fd;
strcpy(tmp1,abs_path);
strcat(tmp1,file_name);
strcpy(tmp2,local_path);
strcat(tmp2,file_name);
// Can we copy it?
if(access(tmp1,R_OK))
return;
// BUG: This checks if it exists, not if it can be created
// if(access(tmp2,W_OK))
// return;
sprintf(cmd,"cp -f %s %s > /dev/null",tmp1,tmp2);
fd = fopen(tmp2,"r");
if (!fd)
system(cmd);
else
fclose(fd);
// printf("%s\n",cmd);
}
*/