📄 unpack.cpp
字号:
} Array<byte> VMCode(Length); for (int I=0;I<Length;I++) { int Ch=PPM.DecodeChar(); if (Ch==-1) return(false); VMCode[I]=Ch; } return(AddVMCode(FirstByte,&VMCode[0],Length));}bool Unpack::AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize){ BitInput Inp; Inp.InitBitInput(); memcpy(Inp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize)); VM.Init(); uint FiltPos; if (FirstByte & 0x80) { FiltPos=RarVM::ReadData(Inp); if (FiltPos==0) InitFilters(); else FiltPos--; } else FiltPos=LastFilter; if (FiltPos>Filters.Size() || FiltPos>OldFilterLengths.Size()) return(false); LastFilter=FiltPos; bool NewFilter=(FiltPos==Filters.Size()); UnpackFilter *Filter; if (NewFilter) { Filters.Add(1); Filters[Filters.Size()-1]=Filter=new UnpackFilter; OldFilterLengths.Add(1); Filter->ExecCount=0; } else { Filter=Filters[FiltPos]; Filter->ExecCount++; } UnpackFilter *StackFilter=new UnpackFilter; int EmptyCount=0; for (int I=0;I<PrgStack.Size();I++) { PrgStack[I-EmptyCount]=PrgStack[I]; if (PrgStack[I]==NULL) EmptyCount++; if (EmptyCount>0) PrgStack[I]=NULL; } if (EmptyCount==0) { PrgStack.Add(1); EmptyCount=1; } int StackPos=PrgStack.Size()-EmptyCount; PrgStack[StackPos]=StackFilter; StackFilter->ExecCount=Filter->ExecCount; uint BlockStart=RarVM::ReadData(Inp); if (FirstByte & 0x40) BlockStart+=258; StackFilter->BlockStart=(BlockStart+UnpPtr)&MAXWINMASK; if (FirstByte & 0x20) StackFilter->BlockLength=RarVM::ReadData(Inp); else StackFilter->BlockLength=FiltPos<OldFilterLengths.Size() ? OldFilterLengths[FiltPos]:0; StackFilter->NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MAXWINMASK)<=BlockStart;// DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart); OldFilterLengths[FiltPos]=StackFilter->BlockLength; memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR)); StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR; StackFilter->Prg.InitR[4]=StackFilter->BlockLength; StackFilter->Prg.InitR[5]=StackFilter->ExecCount; if (FirstByte & 0x10) { unsigned int InitMask=Inp.fgetbits()>>9; Inp.faddbits(7); for (int I=0;I<7;I++) if (InitMask & (1<<I)) StackFilter->Prg.InitR[I]=RarVM::ReadData(Inp); } if (NewFilter) { uint VMCodeSize=RarVM::ReadData(Inp); if (VMCodeSize>=0x10000 || VMCodeSize==0) return(false); Array<byte> VMCode(VMCodeSize); for (int I=0;I<VMCodeSize;I++) { VMCode[I]=Inp.fgetbits()>>8; Inp.faddbits(8); } VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg); } StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0]; StackFilter->Prg.CmdCount=Filter->Prg.CmdCount; int StaticDataSize=Filter->Prg.StaticData.Size(); if (StaticDataSize>0 && StaticDataSize<VM_GLOBALMEMSIZE) { StackFilter->Prg.StaticData.Add(StaticDataSize); memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize); } if (StackFilter->Prg.GlobalData.Size()<VM_FIXEDGLOBALSIZE) { StackFilter->Prg.GlobalData.Reset(); StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE); } byte *GlobalData=&StackFilter->Prg.GlobalData[0]; for (int I=0;I<7;I++) VM.SetValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]); VM.SetValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength); VM.SetValue((uint *)&GlobalData[0x20],0); VM.SetValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount); memset(&GlobalData[0x30],0,16); if (FirstByte & 8) { uint DataSize=RarVM::ReadData(Inp); if (DataSize>=0x10000) return(false); unsigned int CurSize=StackFilter->Prg.GlobalData.Size(); if (CurSize<DataSize+VM_FIXEDGLOBALSIZE) StackFilter->Prg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize); byte *GlobalData=&StackFilter->Prg.GlobalData[VM_FIXEDGLOBALSIZE]; for (int I=0;I<DataSize;I++) { GlobalData[I]=Inp.fgetbits()>>8; Inp.faddbits(8); } } return(true);}bool Unpack::UnpReadBuf(){ int DataSize=ReadTop-InAddr; if (DataSize<0) return(false); if (InAddr>BitInput::MAX_SIZE/2) { if (DataSize>0) memmove(InBuf,InBuf+InAddr,DataSize); InAddr=0; ReadTop=DataSize; } else DataSize=ReadTop; int ReadCode=UnpIO->UnpRead(InBuf+DataSize,(BitInput::MAX_SIZE-DataSize)&~0xf); if (ReadCode>0) ReadTop+=ReadCode; ReadBorder=ReadTop-30; return(ReadCode!=-1);}void Unpack::UnpWriteBuf(){ unsigned int WrittenBorder=WrPtr; unsigned int WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK; for (int I=0;I<PrgStack.Size();I++) { UnpackFilter *flt=PrgStack[I]; if (flt==NULL) continue; if (flt->NextWindow) { flt->NextWindow=false; continue; } unsigned int BlockStart=flt->BlockStart; unsigned int BlockLength=flt->BlockLength; if (((BlockStart-WrittenBorder)&MAXWINMASK)<WriteSize) { if (WrittenBorder!=BlockStart) { UnpWriteArea(WrittenBorder,BlockStart); WrittenBorder=BlockStart; WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK; } if (BlockLength<=WriteSize) { unsigned int BlockEnd=(BlockStart+BlockLength)&MAXWINMASK; if (BlockStart<BlockEnd || BlockEnd==0) VM.SetMemory(0,Window+BlockStart,BlockLength); else { unsigned int FirstPartLength=MAXWINSIZE-BlockStart; VM.SetMemory(0,Window+BlockStart,FirstPartLength); VM.SetMemory(FirstPartLength,Window,BlockEnd); } VM_PreparedProgram *Prg=&flt->Prg; ExecuteCode(Prg); byte *FilteredData=Prg->FilteredData; unsigned int FilteredDataSize=Prg->FilteredDataSize; delete PrgStack[I]; PrgStack[I]=NULL; while (I+1<PrgStack.Size()) { UnpackFilter *NextFilter=PrgStack[I+1]; if (NextFilter==NULL || NextFilter->BlockStart!=BlockStart || NextFilter->BlockLength!=FilteredDataSize || NextFilter->NextWindow) break; VM.SetMemory(0,FilteredData,FilteredDataSize); VM_PreparedProgram *NextPrg=&PrgStack[I+1]->Prg; ExecuteCode(NextPrg); FilteredData=NextPrg->FilteredData; FilteredDataSize=NextPrg->FilteredDataSize; I++; delete PrgStack[I]; PrgStack[I]=NULL; } UnpIO->UnpWrite(FilteredData,FilteredDataSize); UnpSomeRead=true; WrittenFileSize+=FilteredDataSize; WrittenBorder=BlockEnd; WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK; } else { for (int J=I;J<PrgStack.Size();J++) { UnpackFilter *flt=PrgStack[J]; if (flt!=NULL && flt->NextWindow) flt->NextWindow=false; } WrPtr=WrittenBorder; return; } } } UnpWriteArea(WrittenBorder,UnpPtr); WrPtr=UnpPtr;}void Unpack::ExecuteCode(VM_PreparedProgram *Prg){ if (Prg->GlobalData.Size()>0) { Prg->InitR[6]=int64to32(WrittenFileSize); VM.SetValue((uint *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize)); VM.SetValue((uint *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>32)); VM.Execute(Prg); }}void Unpack::UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr){ if (EndPtr!=StartPtr) UnpSomeRead=true; if (EndPtr<StartPtr) { UnpWriteData(&Window[StartPtr],-StartPtr & MAXWINMASK); UnpWriteData(Window,EndPtr); UnpAllBuf=true; } else UnpWriteData(&Window[StartPtr],EndPtr-StartPtr);}void Unpack::UnpWriteData(byte *Data,int Size){ if (WrittenFileSize>=DestUnpSize) return; int WriteSize=Size; Int64 LeftToWrite=DestUnpSize-WrittenFileSize; if (WriteSize>LeftToWrite) WriteSize=int64to32(LeftToWrite); UnpIO->UnpWrite(Data,WriteSize); WrittenFileSize+=Size;}bool Unpack::ReadTables(){ byte BitLength[BC]; unsigned char Table[HUFF_TABLE_SIZE]; if (InAddr>ReadTop-25) if (!UnpReadBuf()) return(false); faddbits((8-InBit)&7); unsigned int BitField=fgetbits(); if (BitField & 0x8000) { UnpBlockType=BLOCK_PPM; return(PPM.DecodeInit(this,PPMEscChar)); } UnpBlockType=BLOCK_LZ; PrevLowDist=0; LowDistRepCount=0; if (!(BitField & 0x4000)) memset(UnpOldTable,0,sizeof(UnpOldTable)); faddbits(2); for (int I=0;I<BC;I++) { int Length=(byte)(fgetbits() >> 12); faddbits(4); if (Length==15) { int ZeroCount=(byte)(fgetbits() >> 12); faddbits(4); if (ZeroCount==0) BitLength[I]=15; else { ZeroCount+=2; while (ZeroCount-- > 0 && I<sizeof(BitLength)/sizeof(BitLength[0])) BitLength[I++]=0; I--; } } else BitLength[I]=Length; } MakeDecodeTables(BitLength,(struct Decode *)&BD,BC); const int TableSize=HUFF_TABLE_SIZE; for (int I=0;I<TableSize;) { if (InAddr>ReadTop-5) if (!UnpReadBuf()) return(false); int Number=DecodeNumber((struct Decode *)&BD); if (Number<16) { Table[I]=(Number+UnpOldTable[I]) & 0xf; I++; } else if (Number<18) { int N; if (Number==16) { N=(fgetbits() >> 13)+3; faddbits(3); } else { N=(fgetbits() >> 9)+11; faddbits(7); } while (N-- > 0 && I<TableSize) { Table[I]=Table[I-1]; I++; } } else { int N; if (Number==18) { N=(fgetbits() >> 13)+3; faddbits(3); } else { N=(fgetbits() >> 9)+11; faddbits(7); } while (N-- > 0 && I<TableSize) Table[I++]=0; } } TablesRead=true; if (InAddr>ReadTop) return(false); MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC); MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC); MakeDecodeTables(&Table[NC+DC],(struct Decode *)&LDD,LDC); MakeDecodeTables(&Table[NC+DC+LDC],(struct Decode *)&RD,RC); memcpy(UnpOldTable,Table,sizeof(UnpOldTable)); return(true);}void Unpack::UnpInitData(int Solid){ if (!Solid) { TablesRead=false; memset(OldDist,0,sizeof(OldDist)); OldDistPtr=0; LastDist=LastLength=0;// memset(Window,0,MAXWINSIZE); memset(UnpOldTable,0,sizeof(UnpOldTable)); UnpPtr=WrPtr=0; PPMEscChar=2; InitFilters(); } InitBitInput(); PPMError=false; WrittenFileSize=0; ReadTop=0; ReadBorder=0;#ifndef SFX_MODULE // Igor Pavlov
// UnpInitData20(Solid);
#endif}void Unpack::InitFilters(){ OldFilterLengths.Reset(); LastFilter=0; for (int I=0;I<Filters.Size();I++) delete Filters[I]; Filters.Reset(); for (int I=0;I<PrgStack.Size();I++) delete PrgStack[I]; PrgStack.Reset();}void Unpack::MakeDecodeTables(unsigned char *LenTab,struct Decode *Dec,int Size){ int LenCount[16],TmpPos[16],I; long M,N; memset(LenCount,0,sizeof(LenCount)); memset(Dec->DecodeNum,0,Size*sizeof(*Dec->DecodeNum)); for (I=0;I<Size;I++) LenCount[LenTab[I] & 0xF]++; LenCount[0]=0; for (TmpPos[0]=Dec->DecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++) { N=2*(N+LenCount[I]); M=N<<(15-I); if (M>0xFFFF) M=0xFFFF; Dec->DecodeLen[I]=(unsigned int)M; TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1]; } for (I=0;I<Size;I++) if (LenTab[I]!=0) Dec->DecodeNum[TmpPos[LenTab[I] & 0xF]++]=I; Dec->MaxNum=Size;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -