/*wmepico (Power C 2.0, run "pc /e wmepico.c")*/
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <direct.h>
typedef struct{
char magic[8];
char packageVersion[12];
char desc[104];
char numDirs[8];
}hdr;
FILE*arc;
char far*heap;
long heapsz=0;
long filecnt=0;
char origdir[256];
void fail(char const*s){
puts(s);
fclose(arc);
chdir(origdir);
exit(0);
}
void put_header(){
hdr h;
memset(&h,0,sizeof(h));
strcpy(h.magic,"\xde\xad\xc0\xdeJUNK");
h.packageVersion[1]=2;
strcpy(h.desc,"MINhMain data (Wintermute Engine \xa9 DEAD:CODE 2010)");
h.numDirs[0]=1;
if(fwrite(&h,sizeof(h),1,arc)!=1){
fail("disk is not writeable");
}
}
char full_path[4096];
char iobuf[4096];
int subdirs[8];
char const*known_exts[]={
"act\0or",
"but\0ton",
"fon\0t",
"gam\0e",
"ima\0ge",
"ite\0ms",
"sce\0ne",
"scr\0ipt",
"set\0tings",
"spr\0ite",
"win\0dow",
NULL
};
int walk(char const*d,int depth){
struct ffblk e;
char*p=&e.ff_name;
char*o;
char*m;
int h;
char**s;
char*at=full_path;
char*ext;
int t;
FILE*f;
long off;
if(depth>=8||chdir(d))goto err;
if(depth)at+=subdirs[depth-1];
h=findfirst("*.*",&e,22);
while(h!=-1){
if(!(*p=='.'&&(p[1]==0||(p[1]=='.'&&p[2]==0)))){
o=at;
ext=p;
while(*ext&&*ext!='.'){
t=*ext;
if(t>='A'&&t<='Z')t+='a'-'A';
*o++=t;
++ext;
}
if(*ext=='.'&&ext[1]){
*o++='.';
++ext;
m=o;
while(*ext){
t=*ext;
if(t>='A'&&t<='Z')t+='a'-'A';
*o++=t;
++ext;
}
*o=0;
s=known_exts;
while(*s){
if(!strcmp(*s,m)){
ext=(*s)+(strlen(*s)+1);
t=strlen(ext);
memcpy(o,ext,t);
o+=t;
break;
}
++s;
}
}
if(o==at)fail("empty file name");
*o++='\\';
subdirs[depth]=o-full_path;
if(e.ff_attrib&16){
fwrite(full_path,1,subdirs[depth],stdout);
puts("");
walk(p,depth+1);
}else{
printf("File ");
fwrite(full_path,1,subdirs[depth]-1,stdout);
puts("");
if(subdirs[depth]>255)fail("filename is too long");
f=fopen(p,"rb");
if(!f)fail("can't open file");
if(heapsz+(8+subdirs[depth])>(1L<<19))fail("out of memory");
farmemcpy(heap+heapsz,full_path,subdirs[depth]);
heap[heapsz+subdirs[depth]-1]=0;
heapsz+=subdirs[depth];
off=ftell(arc);
farmemcpy(heap+heapsz,&off,4);
for(;;){
t=fread(iobuf,1,4096,f);
if(t<0){
fclose(f);
fail("read error");
}
if(!t)break;
if(fwrite(iobuf,t,1,arc)!=1){
fclose(f);
fail("write error");
}
}
off=ftell(arc)-off;
farmemcpy(heap+heapsz+4,&off,4);
heapsz+=8;
filecnt+=1;
fclose(f);
}
o=at;
while(*o!='\\'){
if(*o=='~')fail("long name error");
++o;
}
}
h=findnext(&e);
}
if(chdir("..")){
err:
fail("disk error");
}
return 0;
}
int main(){
size_t sz;
size_t z;
char far*s;
long p;
long i;
if(!(s=heap=farmalloc(1L<<19))){
puts("can't allocate");
return 0;
}
if(!getcwd(origdir,255))return 0;
arc=fopen("data.dcp","wb");
if(!arc)return 0;
put_header();
walk("data",0);
p=ftell(arc);
if(fwrite("\5data\0\0",7,1,arc)!=1)fail("can't write footer");
if(fwrite(&filecnt,4,1,arc)!=1)fail("can't write file count");
for(i=0;i<filecnt;++i){
sz=farstrlen(s)+1;
if(fputc(sz,arc)!=sz)fail("can't write filename length");
farmemcpy(iobuf,s,sz+8);
s+=sz+8;
for(z=0;z<sz;++z)iobuf[z]^='D';
if(fwrite(iobuf,sz+8,1,arc)!=1)fail("can't write filename");
if(fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",16,1,arc)!=1)
fail("can't write garbage");
}
fseek(arc,128,SEEK_SET);
if(fwrite(&p,4,1,arc)!=1)fail("Why? It was almost done!");
fail("OK");
return 0;
}