home *** CD-ROM | disk | FTP | other *** search
- /* unlzexe.c
- * unlzexe ver 0.5 (PC-VAN UTJ44266 Kou )
- * UNLZEXE converts the compressed file by lzexe(ver.0.90,0.91) to the
- * UNcompressed executable one.
- *
- * usage: UNLZEXE packedfile[.EXE] [unpackedfile.EXE]
- */
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <dos.h>
- #define FAILURE 1
- #define SUCCESS 0
-
- typedef unsigned int WORD;
- typedef unsigned char BYTE;
-
- int isjapan(void);
- int japan_f;
- #define iskanji(c) ('\x81'<=(c)&&(c)<='\x9f' || '\xe0'<=(c)&&(c)<='\xfc')
-
- char *tmpfname = "$tmpfil$.exe";
- char *backup_ext = ".olz";
- char ipath[FILENAME_MAX],
- opath[FILENAME_MAX],
- ofname[13];
-
-
- main(int argc,char **argv){
- int fnamechk(char*,char*,char*,int,char**);
- int fnamechg(char*,char*,char*,int);
- int rdhead(FILE *,int *);
- int mkreltbl(FILE *,FILE *,int);
- int unpack(FILE *,FILE *);
- void wrhead(FILE *);
-
- FILE *ifile,*ofile;
- int ver,rename_sw=0;
-
- printf("UNLZEXE Ver. 0.5\n");
- japan_f=isjapan();
- if(argc!=3 && argc!=2){
- printf("usage: UNLZEXE packedfile [unpackedfile]\n");
- exit(EXIT_FAILURE);
- }
- if(argc==2)
- rename_sw=1;
- if(fnamechk(ipath,opath,ofname,argc,argv)!=SUCCESS) {
- exit(EXIT_FAILURE);
- }
- if((ifile=fopen(ipath,"rb"))==NULL){
- printf("'%s' :not found\n",ipath);
- exit(EXIT_FAILURE);
- }
-
- if(rdhead(ifile,&ver)!=SUCCESS){
- printf("'%s' is not LZEXE file.\n",ipath);
- fclose(ifile); exit(EXIT_FAILURE);
- }
- if((ofile=fopen(opath,"w+b"))==NULL){
- printf("can't open '%s'.\n",opath);
- fclose(ifile); exit(EXIT_FAILURE);
- }
- printf("file '%s' is compressed by LZEXE Ver. ",ipath);
- switch(ver){
- case 90: printf("0.90\n"); break;
- case 91: printf("0.91\n"); break;
- }
- if(mkreltbl(ifile,ofile,ver)!=SUCCESS) {
- fclose(ifile);
- fclose(ofile);
- remove(opath);
- exit(EXIT_FAILURE);
- }
- if(unpack(ifile,ofile)!=SUCCESS) {
- fclose(ifile);
- fclose(ofile);
- remove(opath);
- exit(EXIT_FAILURE);
- }
- fclose(ifile);
- wrhead(ofile);
- fclose(ofile);
-
- if(fnamechg(ipath,opath,ofname,rename_sw)!=SUCCESS){
- exit(EXIT_FAILURE);
- }
- exit(EXIT_SUCCESS);
- }
-
-
-
- void parsepath(char *pathname, int *fname, int *ext);
-
- /* file name check */
- int fnamechk(char *ipath,char *opath, char *ofname,
- int argc,char **argv) {
- int idx_name,idx_ext;
-
- strcpy(ipath,argv[1]);
- parsepath(ipath,&idx_name,&idx_ext);
- if (! ipath[idx_ext]) strcpy(ipath+idx_ext,".exe");
- if(! stricmp(ipath+idx_name,tmpfname)){
- printf("'%s':bad filename.\n",ipath);
- return(FAILURE);
- }
- if(argc==2)
- strcpy(opath,ipath);
- else
- strcpy(opath,argv[2]);
- parsepath(opath,&idx_name,&idx_ext);
- if (! opath[idx_ext]) strcpy(opath+idx_ext,".exe");
- if (!stricmp(opath+idx_ext,backup_ext)){
- printf("'%s':bad filename.\n",opath);
- return(FAILURE);
- }
- strncpy(ofname,opath+idx_name,12);
- strcpy(opath+idx_name,tmpfname);
- return(SUCCESS);
- }
-
-
- int fnamechg(char *ipath,char *opath,char *ofname,int rename_sw) {
- int idx_name,idx_ext;
- char tpath[FILENAME_MAX];
-
- if(rename_sw) {
- strcpy(tpath,ipath);
- parsepath(tpath,&idx_name,&idx_ext);
- strcpy(tpath+idx_ext,backup_ext);
- remove(tpath);
- if(rename(ipath,tpath)){
- printf("can't make '%s'.\n", tpath);
- remove(opath);
- return(FAILURE);
- }
- printf("'%s' is renamed to '%s'.\n",ipath,tpath);
- }
- strcpy(tpath,opath);
- parsepath(tpath,&idx_name,&idx_ext);
- strcpy(tpath+idx_name,ofname);
- remove(tpath);
- if(rename(opath,tpath)){
- if(rename_sw) {
- strcpy(tpath,ipath);
- parsepath(tpath,&idx_name,&idx_ext);
- strcpy(tpath+idx_ext,backup_ext);
- rename(tpath,ipath);
- }
- printf("can't make '%s'. unpacked file '%s' is remained.\n",
- tpath, tmpfname);
-
- return(FAILURE);
- }
- printf("unpacked file '%s' is generated.\n",tpath);
- return(SUCCESS);
- }
-
- int isjapan() {
- union REGS r;
- struct SREGS rs;
- BYTE buf[34];
-
- segread(&rs);
- rs.ds=rs.ss; r.x.dx=(WORD)buf;
- r.h.al=0x3800;
- intdosx(&r,&r,&rs);
- return(!strcmp(buf+2,"\\"));
- }
-
- void parsepath(char *pathname, int *fname, int *ext) {
- /* use int japan_f */
- char c;
- int i;
-
- *fname=0; *ext=0;
- for(i=0;c=pathname[i];i++) {
- if(japan_f && iskanji(c))
- i++;
- else
- switch(c) {
- case ':' :
- case '\\': *fname=i+1; break;
- case '.' : *ext=i; break;
- default : ;
- }
- }
- if(*ext<=*fname) *ext=i;
- }
- /*-------------------------------------------*/
- static WORD ihead[0x10],ohead[0x10],inf[8];
- static WORD allocsize;
- static long loadsize;
-
- /* EXE header test (is it LZEXE file?) */
- int rdhead(FILE *ifile ,int *ver){
- if(fread(ihead,sizeof ihead[0],0x10,ifile)!=0x10)
- return FAILURE;
- memcpy(ohead,ihead,sizeof ihead[0] * 0x10);
- if(ihead[0]!=0x5a4d || ihead[4]!=2 || ihead[0x0d]!=0)
- return FAILURE;
- if(ihead[0x0c]==0x1c && memcmp(&ihead[0x0e],"LZ09",4)==0){
- *ver=90; return SUCCESS ;
- }
- if(ihead[0x0c]==0x1c && memcmp(&ihead[0x0e],"LZ91",4)==0){
- *ver=91; return SUCCESS ;
- }
- return FAILURE;
- }
-
- /* make relocation table */
- int mkreltbl(FILE *ifile,FILE *ofile,int ver) {
- int reloc90();
- int reloc91();
- long fpos;
- int i;
-
- allocsize=((ihead[1]+16-1)>>4) + ((ihead[2]-1)<<5) - ihead[4] + ihead[5];
- fpos=(long)(ihead[0x0b]+ihead[4])<<4; /* goto CS:0000 */
- fseek(ifile,fpos,SEEK_SET);
- fread(inf, sizeof inf[0], 0x08, ifile);
- ohead[0x0a]=inf[0]; /* IP */
- ohead[0x0b]=inf[1]; /* CS */
- ohead[0x08]=inf[2]; /* SP */
- ohead[0x07]=inf[3]; /* SS */
- /* inf[4]:size of compressed load module (PARAGRAPH)*/
- /* inf[5]:increase of load module size (PARAGRAPH)*/
- /* inf[6]:size of decompressor with compressed relocation table (BYTE) */
- /* inf[7]:check sum of decompresser with compressd relocation table(Ver.0.90) */
- ohead[0x0c]=0x1c; /* start position of relocation table */
- fseek(ofile,0x1cL,SEEK_SET);
- switch(ver){
- case 90: i=reloc90(ifile,ofile,fpos);
- break;
- case 91: i=reloc91(ifile,ofile,fpos);
- break;
- default: i=FAILURE; break;
- }
- if(i!=SUCCESS){
- printf("error at relocation table.\n");
- return (FAILURE);
- }
- fpos=ftell(ofile);
- i=fpos & 0x1ff;
- if(i) i=0x200-i;
- ohead[4]=(fpos+i)>>4;
-
- for( ; i>0; i--)
- putc(0, ofile);
- return(SUCCESS);
- }
- /* for LZEXE ver 0.90 */
- int reloc90(FILE *ifile,FILE *ofile,long fpos) {
- unsigned int c;
- WORD rel_count=0;
- WORD rel_seg,rel_off;
-
- fseek(ifile,fpos+0x19d,SEEK_SET);
- /* 0x19d=compressed relocation table address */
- rel_seg=0;
- do{
- if(feof(ifile) || ferror(ifile) || ferror(ofile)) return(FAILURE);
- c=getw(ifile);
- for(;c>0;c--) {
- rel_off=getw(ifile);
- putw(rel_off,ofile);
- putw(rel_seg,ofile);
- rel_count++;
- }
- rel_seg += 0x1000;
- } while(rel_seg!=(0xf000+0x1000));
- ohead[3]=rel_count;
- return(SUCCESS);
- }
- /* for LZEXE ver 0.91*/
- int reloc91(FILE *ifile,FILE *ofile,long fpos) {
- WORD span;
- WORD rel_count=0;
- WORD rel_seg,rel_off;
-
- fseek(ifile,fpos+0x158,SEEK_SET);
- /* 0x158=compressed relocation table address */
- rel_off=0; rel_seg=0;
- for(;;) {
- if(feof(ifile) || ferror(ifile) || ferror(ofile)) return(FAILURE);
- if((span=getc(ifile))==0) {
- span=getw(ifile);
- if(span==0){
- rel_seg += 0x0fff;
- continue;
- } else if(span==1){
- break;
- }
- }
- rel_off += span;
- rel_seg += (rel_off & ~0x0f)>>4;
- rel_off &= 0x0f;
- putw(rel_off,ofile);
- putw(rel_seg,ofile);
- rel_count++;
- }
- ohead[3]=rel_count;
- return(SUCCESS);
- }
-
- /*---------------------*/
- typedef struct {
- FILE *fp;
- WORD buf;
- BYTE count;
- } bitstream;
-
- void initbits(bitstream *,FILE *);
- int getbit(bitstream *);
-
- /*---------------------*/
- /* decompressor routine */
- int unpack(FILE *ifile,FILE *ofile){
- int len;
- int span;
- long fpos;
- bitstream bits;
- static BYTE data[0x4500], *p=data;
-
- fpos=(long)(ihead[0x0b]-inf[4]+ihead[4])<<4;
- fseek(ifile,fpos,SEEK_SET);
- fpos=(long)ohead[4]<<4;
- fseek(ofile,fpos,SEEK_SET);
- initbits(&bits,ifile);
- printf(" unpacking. ");
- for(;;){
- if(ferror(ifile)) {printf("\nread error\n"); return(FAILURE); }
- if(ferror(ofile)) {printf("\nwrite error\n"); return(FAILURE); }
- if(p-data>0x4000){
- fwrite(data,sizeof data[0],0x2000,ofile);
- p-=0x2000;
- memcpy(data,data+0x2000,p-data);
- putchar('.');
- }
- if(getbit(&bits)) {
- *p++=getc(ifile);
- continue;
- }
- if(!getbit(&bits)) {
- len=getbit(&bits)<<1;
- len |= getbit(&bits);
- len += 2;
- span=getc(ifile) | 0xff00;
- } else {
- span=(BYTE)getc(ifile);
- len=getc(ifile);
- span |= ((len & ~0x07)<<5) | 0xe000;
- len = (len & 0x07)+2;
- if (len==2) {
- len=getc(ifile);
-
- if(len==0)
- break; /* end mark of compreesed load module */
-
- if(len==1)
- continue; /* segment change */
- else
- len++;
- }
- }
- for( ;len>0;len--,p++){
- *p=*(p+span);
- }
- }
- if(p!=data)
- fwrite(data,sizeof data[0],p-data,ofile);
- loadsize=ftell(ofile)-fpos;
- printf("end\n");
- return(SUCCESS);
- }
-
- /* write EXE header*/
- void wrhead(FILE *ofile) {
- if(ihead[6]!=0) {
- ohead[5]=allocsize-((loadsize+16-1)>>4);
- if(ihead[6]!=0xffff)
- ohead[6]-=(ihead[5]-ohead[5]);
- }
- ohead[1]=(loadsize+(ohead[4]<<4)) & 0x1ff;
- ohead[2]=(loadsize+(ohead[4]<<4)+0x1ff) >>9;
- fseek(ofile,0L,SEEK_SET);
- fwrite(ohead,sizeof ohead[0],0x0e,ofile);
- }
-
- /*-------------------------------------------*/
-
- /* get compress information bit by bit */
- void initbits(bitstream *p,FILE *filep){
- p->fp=filep;
- p->count=0x10;
- p->buf=getw(filep);
- /* printf("%04x ",p->buf); */
- }
-
- int getbit(bitstream *p) {
- int b;
- b = p->buf & 1;
- if(--p->count == 0){
- (p->buf)=getw(p->fp);
- /* printf("%04x ",p->buf); */
- p->count= 0x10;
- }else
- p->buf >>= 1;
-
- return b;
- }
-