⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rarvm.cpp

📁 source code for unrar3.3.4,uppack the .rar files,for multi-os
💻 CPP
📖 第 1 页 / 共 2 页
字号:
      uint Data=fgetbits();      if ((Data&0x8000)==0)      {        CurCmd->OpCode=(VM_Commands)(Data>>12);        faddbits(4);      }      else      {        CurCmd->OpCode=(VM_Commands)((Data>>10)-24);        faddbits(6);      }      if (VM_CmdFlags[CurCmd->OpCode] & VMCF_BYTEMODE)      {        CurCmd->ByteMode=fgetbits()>>15;        faddbits(1);      }      else        CurCmd->ByteMode=0;      CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE;      int OpNum=(VM_CmdFlags[CurCmd->OpCode] & VMCF_OPMASK);      CurCmd->Op1.Addr=CurCmd->Op2.Addr=NULL;      if (OpNum>0)      {        DecodeArg(CurCmd->Op1,CurCmd->ByteMode);        if (OpNum==2)          DecodeArg(CurCmd->Op2,CurCmd->ByteMode);        else        {          if (CurCmd->Op1.Type==VM_OPINT && (VM_CmdFlags[CurCmd->OpCode]&(VMCF_JUMP|VMCF_PROC)))          {            int Distance=CurCmd->Op1.Data;            if (Distance>=256)              Distance-=256;            else            {              if (Distance>=136)                Distance-=264;              else                if (Distance>=16)                  Distance-=8;                else                  if (Distance>=8)                    Distance-=16;              Distance+=Prg->CmdCount;            }            CurCmd->Op1.Data=Distance;          }        }      }      Prg->CmdCount++;    }  }  Prg->Cmd.Add(1);  VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount++];  CurCmd->OpCode=VM_RET;  CurCmd->Op1.Addr=&CurCmd->Op1.Data;  CurCmd->Op2.Addr=&CurCmd->Op2.Data;  for (int I=0;I<Prg->CmdCount;I++)  {    VM_PreparedCommand *Cmd=&Prg->Cmd[I];    if (Cmd->Op1.Addr==NULL)      Cmd->Op1.Addr=&Cmd->Op1.Data;    if (Cmd->Op2.Addr==NULL)      Cmd->Op2.Addr=&Cmd->Op2.Data;  }#ifdef VM_OPTIMIZE  if (CodeSize!=0)    Optimize(Prg);#endif}void RarVM::DecodeArg(VM_PreparedOperand &Op,bool ByteMode){  uint Data=fgetbits();  if (Data & 0x8000)  {    Op.Type=VM_OPREG;    Op.Data=(Data>>12)&7;    Op.Addr=&R[Op.Data];    faddbits(4);  }  else    if ((Data & 0xc000)==0)    {      Op.Type=VM_OPINT;      if (ByteMode)      {        Op.Data=(Data>>6) & 0xff;        faddbits(10);      }      else      {        faddbits(2);        Op.Data=ReadData(*this);      }    }    else    {      Op.Type=VM_OPREGMEM;      if ((Data & 0x2000)==0)      {        Op.Data=(Data>>10)&7;        Op.Addr=&R[Op.Data];        Op.Base=0;        faddbits(6);      }      else      {        if ((Data & 0x1000)==0)        {          Op.Data=(Data>>9)&7;          Op.Addr=&R[Op.Data];          faddbits(7);        }        else        {          Op.Data=0;          faddbits(4);        }        Op.Base=ReadData(*this);      }    }}uint RarVM::ReadData(BitInput &Inp){  uint Data=Inp.fgetbits();  switch(Data&0xc000)  {    case 0:      Inp.faddbits(6);      return((Data>>10)&0xf);    case 0x4000:      if ((Data&0x3c00)==0)      {        Data=0xffffff00|((Data>>2)&0xff);        Inp.faddbits(14);      }      else      {        Data=(Data>>6)&0xff;        Inp.faddbits(10);      }      return(Data);    case 0x8000:      Inp.faddbits(2);      Data=Inp.fgetbits();      Inp.faddbits(16);      return(Data);    default:      Inp.faddbits(2);      Data=(Inp.fgetbits()<<16);      Inp.faddbits(16);      Data|=Inp.fgetbits();      Inp.faddbits(16);      return(Data);  }}void RarVM::SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize){  if (Pos<VM_MEMSIZE && Data!=Mem+Pos)    memmove(Mem+Pos,Data,Min(DataSize,VM_MEMSIZE-Pos));}#ifdef VM_OPTIMIZEvoid RarVM::Optimize(VM_PreparedProgram *Prg){  VM_PreparedCommand *Code=&Prg->Cmd[0];  int CodeSize=Prg->CmdCount;  for (int I=0;I<CodeSize;I++)  {    VM_PreparedCommand *Cmd=Code+I;    switch(Cmd->OpCode)    {      case VM_MOV:        Cmd->OpCode=Cmd->ByteMode ? VM_MOVB:VM_MOVD;        continue;      case VM_CMP:        Cmd->OpCode=Cmd->ByteMode ? VM_CMPB:VM_CMPD;        continue;    }    if ((VM_CmdFlags[Cmd->OpCode] & VMCF_CHFLAGS)==0)      continue;    bool FlagsRequired=false;    for (int J=I+1;J<CodeSize;J++)    {      int Flags=VM_CmdFlags[Code[J].OpCode];      if (Flags & (VMCF_JUMP|VMCF_PROC|VMCF_USEFLAGS))      {        FlagsRequired=true;        break;      }      if (Flags & VMCF_CHFLAGS)        break;    }    if (FlagsRequired)      continue;    switch(Cmd->OpCode)    {      case VM_ADD:        Cmd->OpCode=Cmd->ByteMode ? VM_ADDB:VM_ADDD;        continue;      case VM_SUB:        Cmd->OpCode=Cmd->ByteMode ? VM_SUBB:VM_SUBD;        continue;      case VM_INC:        Cmd->OpCode=Cmd->ByteMode ? VM_INCB:VM_INCD;        continue;      case VM_DEC:        Cmd->OpCode=Cmd->ByteMode ? VM_DECB:VM_DECD;        continue;      case VM_NEG:        Cmd->OpCode=Cmd->ByteMode ? VM_NEGB:VM_NEGD;        continue;    }  }}#endif#ifdef VM_STANDARDFILTERSVM_StandardFilters RarVM::IsStandardFilter(byte *Code,int CodeSize){  struct StandardFilterSignature  {    int Length;    uint CRC;    VM_StandardFilters Type;  } StdList[]={    53, 0xad576887, VMSF_E8,    57, 0x3cd7e57e, VMSF_E8E9,   120, 0x3769893f, VMSF_ITANIUM,    29, 0x0e06077d, VMSF_DELTA,   149, 0x1c2c5dc8, VMSF_RGB,   216, 0xbc85e701, VMSF_AUDIO,    40, 0x46b9c560, VMSF_UPCASE  };  uint CodeCRC=CRC(0xffffffff,Code,CodeSize)^0xffffffff;  for (int I=0;I<sizeof(StdList)/sizeof(StdList[0]);I++)    if (StdList[I].CRC==CodeCRC && StdList[I].Length==CodeSize)      return(StdList[I].Type);  return(VMSF_NONE);}void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType){  switch(FilterType)  {    case VMSF_E8:    case VMSF_E8E9:      {        byte *Data=Mem;        int DataSize=R[4];        uint FileOffset=R[6];        if (DataSize>=VM_GLOBALMEMADDR)          break;        const int FileSize=0x1000000;        byte CmpByte2=FilterType==VMSF_E8E9 ? 0xe9:0xe8;        for (uint CurPos=0;CurPos<DataSize-4;)        {          byte CurByte=*(Data++);          CurPos++;          if (CurByte==0xe8 || CurByte==CmpByte2)          {#ifdef PRESENT_INT32            sint32 Offset=CurPos+FileOffset;            sint32 Addr=GET_VALUE(false,Data);            if (Addr<0)            {              if (Addr+Offset>=0)                SET_VALUE(false,Data,Addr+FileSize);            }            else              if (Addr<FileSize)                SET_VALUE(false,Data,Addr-Offset);#else            long Offset=CurPos+FileOffset;            long Addr=GET_VALUE(false,Data);            if ((Addr & 0x80000000)!=0)            {              if (((Addr+Offset) & 0x80000000)==0)                SET_VALUE(false,Data,Addr+FileSize);            }            else               if (((Addr-FileSize) & 0x80000000)!=0)                SET_VALUE(false,Data,Addr-Offset);#endif            Data+=4;            CurPos+=4;          }        }      }      break;    case VMSF_ITANIUM:      {        byte *Data=Mem;        int DataSize=R[4];        uint FileOffset=R[6];        if (DataSize>=VM_GLOBALMEMADDR)          break;        uint CurPos=0;        FileOffset>>=4;        while (CurPos<DataSize-21)        {          int Byte=(Data[0]&0x1f)-0x10;          if (Byte>=0)          {            static byte Masks[16]={4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};            byte CmdMask=Masks[Byte];            if (CmdMask!=0)              for (int I=0;I<=2;I++)                if (CmdMask & (1<<I))                {                  int StartPos=I*41+5;                  int OpType=FilterItanium_GetBits(Data,StartPos+37,4);                  if (OpType==5)                  {                    int Offset=FilterItanium_GetBits(Data,StartPos+13,20);                    FilterItanium_SetBits(Data,(Offset-FileOffset)&0xfffff,StartPos+13,20);                  }                }          }          Data+=16;          CurPos+=16;          FileOffset++;        }      }      break;    case VMSF_DELTA:      {        int DataSize=R[4],Channels=R[0],SrcPos=0,Border=DataSize*2;        SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);        if (DataSize>=VM_GLOBALMEMADDR/2)          break;        for (int CurChannel=0;CurChannel<Channels;CurChannel++)        {          byte PrevByte=0;          for (int DestPos=DataSize+CurChannel;DestPos<Border;DestPos+=Channels)            Mem[DestPos]=(PrevByte-=Mem[SrcPos++]);        }      }      break;    case VMSF_RGB:      {        int DataSize=R[4],Width=R[0]-3,PosR=R[1];        byte *SrcData=Mem,*DestData=SrcData+DataSize;        const int Channels=3;        SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);        if (DataSize>=VM_GLOBALMEMADDR/2)          break;        for (int CurChannel=0;CurChannel<Channels;CurChannel++)        {          unsigned int PrevByte=0;          for (int I=CurChannel;I<DataSize;I+=Channels)          {            unsigned int Predicted;            int UpperPos=I-Width;            if (UpperPos>=3)            {              byte *UpperData=DestData+UpperPos;              unsigned int UpperByte=*UpperData;              unsigned int UpperLeftByte=*(UpperData-3);              Predicted=PrevByte+UpperByte-UpperLeftByte;              int pa=abs((int)(Predicted-PrevByte));              int pb=abs((int)(Predicted-UpperByte));              int pc=abs((int)(Predicted-UpperLeftByte));              if (pa<=pb && pa<=pc)                Predicted=PrevByte;              else                if (pb<=pc)                  Predicted=UpperByte;                else                  Predicted=UpperLeftByte;            }            else              Predicted=PrevByte;            DestData[I]=PrevByte=(byte)(Predicted-*(SrcData++));          }        }        for (int I=PosR,Border=DataSize-2;I<Border;I+=3)        {          byte G=DestData[I+1];          DestData[I]+=G;          DestData[I+2]+=G;        }      }      break;    case VMSF_AUDIO:      {        int DataSize=R[4],Channels=R[0];        byte *SrcData=Mem,*DestData=SrcData+DataSize;        SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);        if (DataSize>=VM_GLOBALMEMADDR/2)          break;        for (int CurChannel=0;CurChannel<Channels;CurChannel++)        {          unsigned int PrevByte=0,PrevDelta=0,Dif[7];          int D1=0,D2=0,D3;          int K1=0,K2=0,K3=0;          memset(Dif,0,sizeof(Dif));          for (int I=CurChannel,ByteCount=0;I<DataSize;I+=Channels,ByteCount++)          {            D3=D2;            D2=PrevDelta-D1;            D1=PrevDelta;            unsigned int Predicted=8*PrevByte+K1*D1+K2*D2+K3*D3;            Predicted=(Predicted>>3) & 0xff;            unsigned int CurByte=*(SrcData++);            Predicted-=CurByte;            DestData[I]=Predicted;            PrevDelta=(signed char)(Predicted-PrevByte);            PrevByte=Predicted;            int D=((signed char)CurByte)<<3;            Dif[0]+=abs(D);            Dif[1]+=abs(D-D1);            Dif[2]+=abs(D+D1);            Dif[3]+=abs(D-D2);            Dif[4]+=abs(D+D2);            Dif[5]+=abs(D-D3);            Dif[6]+=abs(D+D3);            if ((ByteCount & 0x1f)==0)            {              unsigned int MinDif=Dif[0],NumMinDif=0;              Dif[0]=0;              for (int J=1;J<sizeof(Dif)/sizeof(Dif[0]);J++)              {                if (Dif[J]<MinDif)                {                  MinDif=Dif[J];                  NumMinDif=J;                }                Dif[J]=0;              }              switch(NumMinDif)              {                case 1: if (K1>=-16) K1--; break;                case 2: if (K1 < 16) K1++; break;                case 3: if (K2>=-16) K2--; break;                case 4: if (K2 < 16) K2++; break;                case 5: if (K3>=-16) K3--; break;                case 6: if (K3 < 16) K3++; break;              }            }          }        }      }      break;    case VMSF_UPCASE:      {        int DataSize=R[4],SrcPos=0,DestPos=DataSize;        if (DataSize>=VM_GLOBALMEMADDR/2)          break;        while (SrcPos<DataSize)        {          byte CurByte=Mem[SrcPos++];          if (CurByte==2 && (CurByte=Mem[SrcPos++])!=2)            CurByte-=32;          Mem[DestPos++]=CurByte;        }        SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x1c],DestPos-DataSize);        SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);      }      break;  }}unsigned int RarVM::FilterItanium_GetBits(byte *Data,int BitPos,int BitCount){  int InAddr=BitPos/8;  int InBit=BitPos&7;  unsigned int BitField=(uint)Data[InAddr++];  BitField|=(uint)Data[InAddr++] << 8;  BitField|=(uint)Data[InAddr++] << 16;  BitField|=(uint)Data[InAddr] << 24;  BitField >>= InBit;  return(BitField & (0xffffffff>>(32-BitCount)));}void RarVM::FilterItanium_SetBits(byte *Data,unsigned int BitField,int BitPos,                                  int BitCount){  int InAddr=BitPos/8;  int InBit=BitPos&7;  unsigned int AndMask=0xffffffff>>(32-BitCount);  AndMask=~(AndMask<<InBit);  BitField<<=InBit;  for (int I=0;I<4;I++)  {    Data[InAddr+I]&=AndMask;    Data[InAddr+I]|=BitField;    AndMask=(AndMask>>8)|0xff000000;    BitField>>=8;  }}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -