📄 ms-expand.c
字号:
// LZ77 compression / decompression algorithm// this is the compression Microsoft used in Windows *.HLP and *.MRB files// It is also used with Install Shield files. These files are// recognizable by the letters SZDD in the first 4 bytes. The file// names for files compressed in this way are usually the name of the// file as it would be installed but with the last character replaced// by '_'// This program is a complete hack. I am not responsible for the// algorithm code in any way. I stole the compression code from// somebody else who didn't put a blame line in the file so I've// forgotten who he was. I just adapted it to run under linux from// the command line. (D. Risacher)#define MSEXPAND #include <stdio.h>#include <stdlib.h>#define N 4096#define F 16#define THRESHOLD 3#define dad (node+1)#define lson (node+1+N)#define rson (node+1+N+N)#define root (node+1+N+N+N)#define NIL -1#define int16 shortchar *buffer;int16 *node;int16 pos;#include <sys/stat.h>#include <unistd.h>int main (int argc, char**argv){ FILE *fin, *fout; if (argc != 3) { fprintf(stderr, "%s: file-to-expand destination\n"); fprintf(stderr, "WARNING: this program is a complete hack.\n"); exit(1); } fin = fopen(argv[1],"r"); fout = fopen(argv[2],"w"); expand(fin, fout); }int16 filelength(int16 f){ struct stat buf; fstat(f, &buf); return buf.st_size;}#define min(x,y) (x>y?y:x)int16 insert(int16 i,int16 run){ int16 c,j,k,l,n,match; int16 *p; k=l=1; match=THRESHOLD-1; p=&root[(unsigned char)buffer[i]]; lson[i]=rson[i]=NIL; while((j=*p)!=NIL) { for(n=min(k,l);n<run&&(c=(buffer[j+n]-buffer[i+n]))==0;n++) ; if(n>match) { match=n; pos=j; } if(c<0) { p=&lson[j]; k=n; } else if(c>0) { p=&rson[j]; l=n; } else { dad[j]=NIL; dad[lson[j]]=lson+i-node; dad[rson[j]]=rson+i-node; lson[i]=lson[j]; rson[i]=rson[j]; break; } } dad[i]=p-node; *p=i; return match;}void delete(int16 z){ int16 j; if(dad[z]!=NIL) { if(rson[z]==NIL) { j=lson[z]; } else if(lson[z]==NIL) { j=rson[z]; } else { j=lson[z]; if(rson[j]!=NIL) { do { j=rson[j]; } while(rson[j]!=NIL); node[dad[j]]=lson[j]; dad[lson[j]]=dad[j]; lson[j]=lson[z]; dad[lson[z]]=lson+j-node; } rson[j]=rson[z]; dad[rson[z]]=rson+j-node; } dad[j]=dad[z]; node[dad[z]]=j; dad[z]=NIL; }}struct header_struct { long magic, magic2; int16 magic3; long filesize; } __attribute__ ((packed));void compress(FILE *f,FILE *out){ int16 ch,i,run,len,match,size,mask; char buf[17]; buffer=malloc(N+F+(N+1+N+N+256)*sizeof(int16)); // 28.5 k ! if(buffer) {#ifdef MSEXPAND struct header_struct header; header.magic=0x44445A53L; // SZDD header.magic2=0x3327F088L; header.magic3=0x0041; header.filesize=filelength(fileno(f)); fwrite(&header,sizeof(header),1,out);#endif node=(int16 *)(buffer+N+F); for(i=0;i<256;i++) root[i]=NIL; for(i=NIL;i<N;i++) dad[i]=NIL; size=mask=1; buf[0]=0; i=N-F-F; for(len=0;len<F&&(ch=getc(f))!=-1;len++) { buffer[i+F]=ch; i=(i+1)&(N-1); } run=len; do { ch=getc(f); if(i>=N-F) { delete(i+F-N); buffer[i+F]=buffer[i+F-N]=ch; } else { delete(i+F); buffer[i+F]=ch; } match=insert(i,run); if(ch==-1) { run--; len--; } if(len++>=run) { if(match>=THRESHOLD) {#ifdef MSEXPAND buf[size++]=pos; buf[size++]=((pos>>4)&0xF0)+(match-3);#else buf[0]|=mask; *(int16 *)(buf+size)=((match-3)<<12)|((i-pos-1)&(N-1)); size+=2;#endif len-=match; } else {#ifdef MSEXPAND buf[0]|=mask;#endif buf[size++]=buffer[i]; len--; } if(!((mask+=mask)&0xFF)) { fwrite(buf,size,1,out); size=mask=1; buf[0]=0; } } i=(i+1)&(N-1); } while(len>0); if(size>1) fwrite(buf,size,1,out); free(buffer); }}void expand(FILE *f,FILE *out){ int16 bits,ch,i,j,len,mask; char *buffer;#ifdef MSEXPAND struct header_struct header; i=fread(&header,1,sizeof(header),f); if(i!=sizeof(header)||header.magic!=0x44445A53L||header.magic2!=0x3327F088L||header.magic3!=0x0041) { fwrite(&header,1,i,out); while((ch=getc(f))!=-1) putc(ch,out); return; } #endif buffer=malloc(N); if(buffer) { i=N-F; while((bits=getc(f))!=-1) { for(mask=0x01;mask&0xFF;mask<<=1) {#ifdef MSEXPAND if(!(bits&mask)) { j=getc(f); if(j==-1) break; len=getc(f); j+=(len&0xF0)<<4; len=(len&15)+3;#else if(bits&mask) { j=getw(f); len=((j>>12)&15)+3; j=(i-j-1)&(N-1);#endif while(len--) { putc(buffer[i]=buffer[j],out); j=(j+1)&(N-1); i=(i+1)&(N-1); } } else { ch=getc(f);#ifndef MSEXPAND if(ch==-1) break;#endif putc(buffer[i]=ch,out); i=(i+1)&(N-1); } } } free(buffer); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -