home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / archvrs / msdos / unlzexe3 / unlzexe.c next >
Encoding:
C/C++ Source or Header  |  1990-04-17  |  11.1 KB  |  412 lines

  1. /* unlzexe.c
  2. * unlzexe ver 0.3 (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.3\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 fpos,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.     int i;
  217.     
  218.     allocsize=((ihead[1]+16-1)>>4) + ((ihead[2]-1)<<5) - ihead[4] + ihead[5];
  219.     fpos=(long)(ihead[0x0b]+ihead[4])<<4;        /* goto CS:0000 */
  220.     fseek(ifile,fpos,SEEK_SET);
  221.     fread(inf, sizeof inf[0], 0x08, ifile);
  222.     ohead[0x0a]=inf[0];        /* IP */
  223.     ohead[0x0b]=inf[1];        /* CS */
  224.     ohead[0x08]=inf[2];        /* SP */
  225.     ohead[0x07]=inf[3];        /* SS */
  226.     /* inf[4]:size of compressed load module (PARAGRAPH)*/
  227.     /* inf[5]:increase of load module size (PARAGRAPH)*/
  228.     /* inf[6]:size of decompressor with  compressed relocation table (BYTE) */
  229.     /* inf[7]:check sum of decompresser with compressd relocation table(Ver.0.90) */
  230.     ohead[0x0c]=0x1c;        /* start position of relocation table */
  231.     fseek(ofile,0x1cL,SEEK_SET);
  232.     switch(ver){
  233.     case 90: i=reloc90(ifile,ofile,fpos);
  234.              break;
  235.     case 91: i=reloc91(ifile,ofile,fpos);
  236.              break;
  237.     default: i=FAILURE; break;
  238.     }
  239.     if(i!=SUCCESS){
  240.         printf("error at relocation table.\n");
  241.         return (FAILURE);
  242.     }
  243.     i=ohead[3]*4+ohead[0x0c];
  244.     ohead[4]=((i+0x1ff) & ~0x1ff)>>4;
  245.     
  246.     for(i=0x200-(i & 0x1ff); i>0; i--)
  247.        putc(0, ofile);
  248.     return(SUCCESS);
  249. }
  250. /* for LZEXE ver 0.90 */
  251. int reloc90(FILE *ifile,FILE *ofile,long fpos) {
  252.     unsigned int c;
  253.     WORD rel_count=0;
  254.     WORD rel_seg,rel_off;
  255.  
  256.     fseek(ifile,fpos+0x19d,SEEK_SET); 
  257.                     /* 0x19d=compressed relocation table address */
  258.     for(rel_seg=0;rel_seg<0x10;rel_seg++) {
  259.         if(feof(ifile) || ferror(ifile) || ferror(ofile)) return(FAILURE);
  260.         if((c=getw(ifile))==0)
  261.             continue;
  262.         else {
  263.             for(;c>0;c--) {
  264.                 rel_off=getw(ifile);
  265.                 putw(rel_off,ofile);
  266.                 putw(rel_seg,ofile);
  267.                 rel_count++;
  268.             }
  269.         }
  270.     }
  271.     ohead[3]=rel_count;
  272.     return(SUCCESS);
  273. }
  274. /* for LZEXE ver 0.91*/
  275. int reloc91(FILE *ifile,FILE *ofile,long fpos) {
  276.     WORD span;
  277.     WORD rel_count=0;
  278.     WORD rel_seg,rel_off;
  279.  
  280.     fseek(ifile,fpos+0x158,SEEK_SET);
  281.                     /* 0x158=compressed relocation table address */
  282.     rel_off=0; rel_seg=0;
  283.     for(;;) {
  284.         if(feof(ifile) || ferror(ifile) || ferror(ofile)) return(FAILURE);
  285.         if((span=getc(ifile))==0) {
  286.             span=getw(ifile);
  287.             if(span==0){
  288.                 rel_seg += 0x0fff;
  289.                 continue;
  290.             } else if(span==1){
  291.                 break;
  292.             }
  293.         }
  294.         rel_off += span;
  295.         rel_seg += (rel_off & ~0x0f)>>4;
  296.         rel_off &= 0x0f;
  297.         putw(rel_off,ofile);
  298.         putw(rel_seg,ofile);
  299.         rel_count++;
  300.     }
  301.     ohead[3]=rel_count;
  302.     return(SUCCESS);
  303. }
  304.  
  305. /*---------------------*/
  306. typedef struct {
  307.         FILE  *fp;
  308.         WORD  buf;
  309.         BYTE  count;
  310.     } bitstream;
  311.  
  312. void initbits(bitstream *,FILE *);
  313. int getbit(bitstream *);
  314.  
  315. /*---------------------*/
  316. /* decompressor routine */
  317. int unpack(FILE *ifile,FILE *ofile){
  318.     int len;
  319.     int span;
  320.     long fpos;
  321.     bitstream bits;
  322.     static BYTE data[0x4500], *p=data;
  323.     
  324.     fpos=(long)(ihead[0x0b]-inf[4]+ihead[4])<<4;
  325.     fseek(ifile,fpos,SEEK_SET);
  326.     fpos=(long)ohead[4]<<4;
  327.     fseek(ofile,fpos,SEEK_SET);
  328.     initbits(&bits,ifile);
  329.     printf(" unpacking. ");
  330.     for(;;){
  331.         if(ferror(ifile)) {printf("\nread error\n"); return(FAILURE); }
  332.         if(ferror(ofile)) {printf("\nwrite error\n"); return(FAILURE); }
  333.         if(p-data>0x4000){
  334.             fwrite(data,sizeof data[0],0x2000,ofile);
  335.             p-=0x2000;
  336.             memcpy(data,data+0x2000,p-data);
  337.             putchar('.');
  338.         }
  339.         if(getbit(&bits)) {
  340.             *p++=getc(ifile);
  341.             continue;
  342.         }
  343.         if(!getbit(&bits)) {
  344.             len=getbit(&bits)<<1;
  345.             len |= getbit(&bits);
  346.             len += 2;
  347.             span=getc(ifile) | 0xff00;
  348.         } else {
  349.             span=(BYTE)getc(ifile);
  350.             len=getc(ifile);
  351.             span |= ((len & ~0x07)<<5) | 0xe000;
  352.             len = (len & 0x07)+2; 
  353.             if (len==2) {
  354.                 len=getc(ifile);
  355.  
  356.                 if(len==0)
  357.                     break;    /* end mark of compreesed load module */
  358.  
  359.                 if(len==1)
  360.                     continue; /* segment change */
  361.                 else
  362.                     len++;
  363.             }
  364.         }
  365.         for( ;len>0;len--,p++){
  366.             *p=*(p+span);
  367.         }
  368.     }
  369.     if(p!=data)
  370.         fwrite(data,sizeof data[0],p-data,ofile);
  371.     loadsize=ftell(ofile)-fpos;
  372.     printf("end\n");
  373.     return(SUCCESS);
  374. }
  375.  
  376. /* write EXE header*/
  377. void wrhead(FILE *ofile) {
  378.     if(ihead[6]!=0) {
  379.         ohead[5]=allocsize-((loadsize+16-1)>>4);
  380.         if(ihead[6]!=0xffff)
  381.             ohead[6]-=(ihead[5]-ohead[5]);
  382.     }
  383.     ohead[1]=(loadsize+(ohead[4]<<4)) & 0x1ff;
  384.     ohead[2]=(loadsize+(ohead[4]<<4)+0x1ff) >>9;
  385.     fseek(ofile,0L,SEEK_SET);
  386.     fwrite(ohead,sizeof ohead[0],0x0e,ofile);
  387. }
  388.  
  389. /*-------------------------------------------*/
  390.  
  391. /* get compress information bit by bit */
  392. void initbits(bitstream *p,FILE *filep){
  393.     p->fp=filep;
  394.     p->count=0x10;
  395.     p->buf=getw(filep);
  396.     /* printf("%04x ",p->buf); */
  397. }
  398.  
  399. int getbit(bitstream *p) {
  400.     int b;
  401.     b = p->buf & 1;
  402.     if(--p->count == 0){
  403.         (p->buf)=getw(p->fp);
  404.         /* printf("%04x ",p->buf); */
  405.         p->count= 0x10;
  406.     }else
  407.         p->buf >>= 1;
  408.     
  409.     return b;
  410. }
  411.  
  412.