home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / dos / unlze04.lzh / UNLZEXE.C next >
Text File  |  1990-05-12  |  11KB  |  415 lines

  1. /* unlzexe.c
  2. * unlzexe ver 0.4 (PC-VAN UTJ44266 Kou )
  3. *   UNLZEXE converts the compressed file by lzexe(ver.0.90,0.91) to the
  4. *   UNcompressed executable one.
  5. *
  6. *   usage:  UNLZEXE packedfile[.EXE] [unpackedfile.EXE]
  7. */
  8.  
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <dos.h>
  13. #define FAILURE 1
  14. #define SUCCESS 0
  15.  
  16. typedef unsigned int WORD;
  17. typedef unsigned char BYTE;
  18.  
  19. int isjapan(void);
  20. int japan_f;
  21. #define    iskanji(c)    ('\x81'<=(c)&&(c)<='\x9f' || '\xe0'<=(c)&&(c)<='\xfc')
  22.  
  23. char *tmpfname = "$tmpfil$.exe";
  24. char *backup_ext = ".olz";
  25. char ipath[FILENAME_MAX],
  26.      opath[FILENAME_MAX],
  27.      ofname[13];
  28.  
  29.  
  30. main(int argc,char **argv){
  31.     int fnamechk(char*,char*,char*,int,char**);
  32.     int  fnamechg(char*,char*,char*,int);
  33.     int rdhead(FILE *,int *);
  34.     int mkreltbl(FILE *,FILE *,int);
  35.     int unpack(FILE *,FILE *);
  36.     void wrhead(FILE *);
  37.     
  38.     FILE *ifile,*ofile;
  39.     int  ver,rename_sw=0;
  40.     
  41.     printf("UNLZEXE Ver. 0.4\n");
  42.     japan_f=isjapan();
  43.     if(argc!=3 && argc!=2){
  44.         printf("usage: UNLZEXE packedfile [unpackedfile]\n");
  45.         exit(EXIT_FAILURE);
  46.     }
  47.     if(argc==2)
  48.         rename_sw=1;
  49.     if(fnamechk(ipath,opath,ofname,argc,argv)!=SUCCESS) {
  50.         exit(EXIT_FAILURE);
  51.     }
  52.     if((ifile=fopen(ipath,"rb"))==NULL){
  53.         printf("'%s' :not found\n",ipath);
  54.             exit(EXIT_FAILURE);
  55.     }
  56.     
  57.     if(rdhead(ifile,&ver)!=SUCCESS){
  58.         printf("'%s' is not LZEXE file.\n",ipath);
  59.         fclose(ifile); exit(EXIT_FAILURE);
  60.     }
  61.     if((ofile=fopen(opath,"w+b"))==NULL){
  62.         printf("can't open '%s'.\n",opath);
  63.         fclose(ifile); exit(EXIT_FAILURE);
  64.     }
  65.     printf("file '%s' is compressed by LZEXE Ver. ",ipath);
  66.     switch(ver){
  67.     case 90: printf("0.90\n"); break;
  68.     case 91: printf("0.91\n"); break;
  69.     }
  70.     if(mkreltbl(ifile,ofile,ver)!=SUCCESS) {
  71.         fclose(ifile);
  72.         fclose(ofile);
  73.         remove(opath);
  74.         exit(EXIT_FAILURE);
  75.     }
  76.     if(unpack(ifile,ofile)!=SUCCESS) {
  77.         fclose(ifile);
  78.         fclose(ofile);
  79.         remove(opath);
  80.         exit(EXIT_FAILURE);
  81.     }
  82.     fclose(ifile);
  83.     wrhead(ofile);
  84.     fclose(ofile);
  85.         
  86.     if(fnamechg(ipath,opath,ofname,rename_sw)!=SUCCESS){
  87.         exit(EXIT_FAILURE);
  88.     }
  89.     exit(EXIT_SUCCESS);
  90. }
  91.  
  92.  
  93.  
  94. void parsepath(char *pathname, int *fname, int *ext);
  95.  
  96. /* file name check */
  97. int fnamechk(char *ipath,char *opath, char *ofname,
  98.               int argc,char **argv) {
  99.     int idx_name,idx_ext;
  100.     
  101.     strcpy(ipath,argv[1]);
  102.     parsepath(ipath,&idx_name,&idx_ext);
  103.     if (! ipath[idx_ext]) strcpy(ipath+idx_ext,".exe");
  104.     if(! stricmp(ipath+idx_name,tmpfname)){
  105.         printf("'%s':bad filename.\n",ipath);
  106.         return(FAILURE);
  107.     }
  108.     if(argc==2)
  109.         strcpy(opath,ipath);
  110.     else
  111.         strcpy(opath,argv[2]);
  112.     parsepath(opath,&idx_name,&idx_ext);
  113.     if (! opath[idx_ext]) strcpy(opath+idx_ext,".exe");
  114.     if (!stricmp(opath+idx_ext,backup_ext)){
  115.         printf("'%s':bad filename.\n",opath);
  116.         return(FAILURE);
  117.     }
  118.     strncpy(ofname,opath+idx_name,12);
  119.     strcpy(opath+idx_name,tmpfname);
  120.     return(SUCCESS);
  121. }
  122.  
  123.  
  124. int fnamechg(char *ipath,char *opath,char *ofname,int rename_sw) {
  125.     int idx_name,idx_ext;
  126.     char tpath[FILENAME_MAX];
  127.     
  128.     if(rename_sw) {
  129.         strcpy(tpath,ipath);
  130.         parsepath(tpath,&idx_name,&idx_ext);
  131.         strcpy(tpath+idx_ext,backup_ext);
  132.         remove(tpath);
  133.         if(rename(ipath,tpath)){
  134.             printf("can't make '%s'.\n", tpath);
  135.             remove(opath);
  136.             return(FAILURE);
  137.         }
  138.     printf("'%s' is renamed to '%s'.\n",ipath,tpath);
  139.     }
  140.     strcpy(tpath,opath);
  141.     parsepath(tpath,&idx_name,&idx_ext);
  142.     strcpy(tpath+idx_name,ofname);
  143.     remove(tpath);
  144.     if(rename(opath,tpath)){
  145.         if(rename_sw) {
  146.             strcpy(tpath,ipath);
  147.             parsepath(tpath,&idx_name,&idx_ext);
  148.             strcpy(tpath+idx_ext,backup_ext);
  149.             rename(tpath,ipath);
  150.         }
  151.         printf("can't make '%s'.  unpacked file '%s' is remained.\n",
  152.                  tpath, tmpfname);
  153.         
  154.         return(FAILURE);
  155.     }
  156.     printf("unpacked file '%s' is genarated.\n",tpath);
  157.     return(SUCCESS);
  158. }
  159.  
  160. int isjapan() {
  161.     union REGS r;
  162.     struct SREGS rs;
  163.     BYTE buf[34];
  164.     
  165.     segread(&rs);
  166.     rs.ds=rs.ss;  r.x.dx=(WORD)buf;
  167.     r.h.al=0x3800;
  168.     intdosx(&r,&r,&rs);
  169.     return(!strcmp(buf+2,"\\"));
  170. }
  171.  
  172. void parsepath(char *pathname, int *fname, int *ext) {
  173.     /* use  int japan_f */
  174.     char c;
  175.     int i;
  176.     
  177.     *fname=0; *ext=0;
  178.     for(i=0;c=pathname[i];i++) {
  179.         if(japan_f && iskanji(c)) 
  180.             i++;
  181.         else
  182.             switch(c) {
  183.             case ':' :
  184.             case '\\':  *fname=i+1; break;
  185.             case '.' :  *ext=i; break;
  186.             default  :  ;
  187.             }
  188.     }
  189.     if(*ext<=*fname) *ext=i;
  190. }
  191. /*-------------------------------------------*/
  192. static WORD ihead[0x10],ohead[0x10],inf[8];
  193. static WORD allocsize;
  194. static long loadsize;
  195.  
  196. /* EXE header test (is it LZEXE file?) */
  197. int rdhead(FILE *ifile ,int *ver){
  198.     if(fread(ihead,sizeof ihead[0],0x10,ifile)!=0x10)
  199.         return FAILURE;
  200.     memcpy(ohead,ihead,sizeof ihead[0] * 0x10);
  201.     if(ihead[0]!=0x5a4d || ihead[4]!=2 || ihead[0x0d]!=0)
  202.         return FAILURE;
  203.     if(ihead[0x0c]==0x1c && memcmp(&ihead[0x0e],"LZ09",4)==0){
  204.         *ver=90; return SUCCESS ;
  205.     }
  206.     if(ihead[0x0c]==0x1c && memcmp(&ihead[0x0e],"LZ91",4)==0){
  207.         *ver=91; return SUCCESS ;
  208.     }
  209.     return FAILURE;
  210. }
  211.  
  212. /* make relocation table */
  213. int mkreltbl(FILE *ifile,FILE *ofile,int ver) {
  214.     int reloc90();
  215.     int reloc91();
  216.     long fpos;
  217.     int i;
  218.     
  219.     allocsize=((ihead[1]+16-1)>>4) + ((ihead[2]-1)<<5) - ihead[4] + ihead[5];
  220.     fpos=(long)(ihead[0x0b]+ihead[4])<<4;        /* goto CS:0000 */
  221.     fseek(ifile,fpos,SEEK_SET);
  222.     fread(inf, sizeof inf[0], 0x08, ifile);
  223.     ohead[0x0a]=inf[0];        /* IP */
  224.     ohead[0x0b]=inf[1];        /* CS */
  225.     ohead[0x08]=inf[2];        /* SP */
  226.     ohead[0x07]=inf[3];        /* SS */
  227.     /* inf[4]:size of compressed load module (PARAGRAPH)*/
  228.     /* inf[5]:increase of load module size (PARAGRAPH)*/
  229.     /* inf[6]:size of decompressor with  compressed relocation table (BYTE) */
  230.     /* inf[7]:check sum of decompresser with compressd relocation table(Ver.0.90) */
  231.     ohead[0x0c]=0x1c;        /* start position of relocation table */
  232.     fseek(ofile,0x1cL,SEEK_SET);
  233.     switch(ver){
  234.     case 90: i=reloc90(ifile,ofile,fpos);
  235.              break;
  236.     case 91: i=reloc91(ifile,ofile,fpos);
  237.              break;
  238.     default: i=FAILURE; break;
  239.     }
  240.     if(i!=SUCCESS){
  241.         printf("error at relocation table.\n");
  242.         return (FAILURE);
  243.     }
  244.     fpos=ftell(ofile);
  245.     i=fpos & 0x1ff;
  246.     if(i) i=0x200-i;
  247.     ohead[4]=(fpos+i)>>4;
  248.     
  249.     for( ; i>0; i--)
  250.         putc(0, ofile);
  251.     return(SUCCESS);
  252. }
  253. /* for LZEXE ver 0.90 */
  254. int reloc90(FILE *ifile,FILE *ofile,long fpos) {
  255.     unsigned int c;
  256.     WORD rel_count=0;
  257.     WORD rel_seg,rel_off;
  258.  
  259.     fseek(ifile,fpos+0x19d,SEEK_SET); 
  260.                     /* 0x19d=compressed relocation table address */
  261.     for(rel_seg=0;rel_seg<0x10;rel_seg++) {
  262.         if(feof(ifile) || ferror(ifile) || ferror(ofile)) return(FAILURE);
  263.         if((c=getw(ifile))==0)
  264.             continue;
  265.         else {
  266.             for(;c>0;c--) {
  267.                 rel_off=getw(ifile);
  268.                 putw(rel_off,ofile);
  269.                 putw(rel_seg,ofile);
  270.                 rel_count++;
  271.             }
  272.         }
  273.     }
  274.     ohead[3]=rel_count;
  275.     return(SUCCESS);
  276. }
  277. /* for LZEXE ver 0.91*/
  278. int reloc91(FILE *ifile,FILE *ofile,long fpos) {
  279.     WORD span;
  280.     WORD rel_count=0;
  281.     WORD rel_seg,rel_off;
  282.  
  283.     fseek(ifile,fpos+0x158,SEEK_SET);
  284.                     /* 0x158=compressed relocation table address */
  285.     rel_off=0; rel_seg=0;
  286.     for(;;) {
  287.         if(feof(ifile) || ferror(ifile) || ferror(ofile)) return(FAILURE);
  288.         if((span=getc(ifile))==0) {
  289.             span=getw(ifile);
  290.             if(span==0){
  291.                 rel_seg += 0x0fff;
  292.                 continue;
  293.             } else if(span==1){
  294.                 break;
  295.             }
  296.         }
  297.         rel_off += span;
  298.         rel_seg += (rel_off & ~0x0f)>>4;
  299.         rel_off &= 0x0f;
  300.         putw(rel_off,ofile);
  301.         putw(rel_seg,ofile);
  302.         rel_count++;
  303.     }
  304.     ohead[3]=rel_count;
  305.     return(SUCCESS);
  306. }
  307.  
  308. /*---------------------*/
  309. typedef struct {
  310.         FILE  *fp;
  311.         WORD  buf;
  312.         BYTE  count;
  313.     } bitstream;
  314.  
  315. void initbits(bitstream *,FILE *);
  316. int getbit(bitstream *);
  317.  
  318. /*---------------------*/
  319. /* decompressor routine */
  320. int unpack(FILE *ifile,FILE *ofile){
  321.     int len;
  322.     int span;
  323.     long fpos;
  324.     bitstream bits;
  325.     static BYTE data[0x4500], *p=data;
  326.     
  327.     fpos=(long)(ihead[0x0b]-inf[4]+ihead[4])<<4;
  328.     fseek(ifile,fpos,SEEK_SET);
  329.     fpos=(long)ohead[4]<<4;
  330.     fseek(ofile,fpos,SEEK_SET);
  331.     initbits(&bits,ifile);
  332.     printf(" unpacking. ");
  333.     for(;;){
  334.         if(ferror(ifile)) {printf("\nread error\n"); return(FAILURE); }
  335.         if(ferror(ofile)) {printf("\nwrite error\n"); return(FAILURE); }
  336.         if(p-data>0x4000){
  337.             fwrite(data,sizeof data[0],0x2000,ofile);
  338.             p-=0x2000;
  339.             memcpy(data,data+0x2000,p-data);
  340.             putchar('.');
  341.         }
  342.         if(getbit(&bits)) {
  343.             *p++=getc(ifile);
  344.             continue;
  345.         }
  346.         if(!getbit(&bits)) {
  347.             len=getbit(&bits)<<1;
  348.             len |= getbit(&bits);
  349.             len += 2;
  350.             span=getc(ifile) | 0xff00;
  351.         } else {
  352.             span=(BYTE)getc(ifile);
  353.             len=getc(ifile);
  354.             span |= ((len & ~0x07)<<5) | 0xe000;
  355.             len = (len & 0x07)+2; 
  356.             if (len==2) {
  357.                 len=getc(ifile);
  358.  
  359.                 if(len==0)
  360.                     break;    /* end mark of compreesed load module */
  361.  
  362.                 if(len==1)
  363.                     continue; /* segment change */
  364.                 else
  365.                     len++;
  366.             }
  367.         }
  368.         for( ;len>0;len--,p++){
  369.             *p=*(p+span);
  370.         }
  371.     }
  372.     if(p!=data)
  373.         fwrite(data,sizeof data[0],p-data,ofile);
  374.     loadsize=ftell(ofile)-fpos;
  375.     printf("end\n");
  376.     return(SUCCESS);
  377. }
  378.  
  379. /* write EXE header*/
  380. void wrhead(FILE *ofile) {
  381.     if(ihead[6]!=0) {
  382.         ohead[5]=allocsize-((loadsize+16-1)>>4);
  383.         if(ihead[6]!=0xffff)
  384.             ohead[6]-=(ihead[5]-ohead[5]);
  385.     }
  386.     ohead[1]=(loadsize+(ohead[4]<<4)) & 0x1ff;
  387.     ohead[2]=(loadsize+(ohead[4]<<4)+0x1ff) >>9;
  388.     fseek(ofile,0L,SEEK_SET);
  389.     fwrite(ohead,sizeof ohead[0],0x0e,ofile);
  390. }
  391.  
  392. /*-------------------------------------------*/
  393.  
  394. /* get compress information bit by bit */
  395. void initbits(bitstream *p,FILE *filep){
  396.     p->fp=filep;
  397.     p->count=0x10;
  398.     p->buf=getw(filep);
  399.     /* printf("%04x ",p->buf); */
  400. }
  401.  
  402. int getbit(bitstream *p) {
  403.     int b;
  404.     b = p->buf & 1;
  405.     if(--p->count == 0){
  406.         (p->buf)=getw(p->fp);
  407.         /* printf("%04x ",p->buf); */
  408.         p->count= 0x10;
  409.     }else
  410.         p->buf >>= 1;
  411.     
  412.     return b;
  413. }
  414.  
  415.