#include "rar.hpp" #include "rarvmtbl.cpp" RarVM::RarVM() { Mem=NULL; } RarVM::~RarVM() { delete[] Mem; } void RarVM::Init() { if (Mem==NULL) Mem=new byte[VM_MEMSIZE+4]; } inline uint RarVM::GetValue(bool ByteMode,uint *Addr) { if (ByteMode) return(*(byte *)Addr); else { #if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) byte *B=(byte *)Addr; return UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24)); #else return UINT32(*Addr); #endif } } #if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) #define GET_VALUE(ByteMode,Addr) GetValue(ByteMode,(uint *)Addr) #else #define GET_VALUE(ByteMode,Addr) ((ByteMode) ? (*(byte *)(Addr)):UINT32(*(uint *)(Addr))) #endif inline void RarVM::SetValue(bool ByteMode,uint *Addr,uint Value) { if (ByteMode) *(byte *)Addr=Value; else { #if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32) ((byte *)Addr)[0]=(byte)Value; ((byte *)Addr)[1]=(byte)(Value>>8); ((byte *)Addr)[2]=(byte)(Value>>16); ((byte *)Addr)[3]=(byte)(Value>>24); #else *(uint32 *)Addr=Value; #endif } } #if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32) #define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint *)Addr,Value) #else #define SET_VALUE(ByteMode,Addr,Value) ((ByteMode) ? (*(byte *)(Addr)=(Value)):(*(uint32 *)(Addr)=((uint32)(Value)))) #endif void RarVM::SetValue(uint *Addr,uint Value) { SetValue(false,Addr,Value); } inline uint* RarVM::GetOperand(VM_PreparedOperand *CmdOp) { if (CmdOp->Type==VM_OPREGMEM) return((uint *)&Mem[(*CmdOp->Addr+CmdOp->Base)&VM_MEMMASK]); else return(CmdOp->Addr); } void RarVM::Execute(VM_PreparedProgram *Prg) { memcpy(R,Prg->InitR,sizeof(Prg->InitR)); unsigned int GlobalSize=Min(Prg->GlobalData.Size(),VM_GLOBALMEMSIZE); if (GlobalSize) memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize); unsigned int StaticSize=Min((uint)Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize); if (StaticSize) memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize); R[7]=VM_MEMSIZE; Flags=0; VM_PreparedCommand *PreparedCode=Prg->AltCmd ? Prg->AltCmd:&Prg->Cmd[0]; if (!ExecuteCode(PreparedCode,Prg->CmdCount)) PreparedCode[0].OpCode=VM_RET; uint NewBlockPos=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20])&VM_MEMMASK; uint NewBlockSize=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x1c])&VM_MEMMASK; if (NewBlockPos+NewBlockSize>=VM_MEMSIZE) NewBlockPos=NewBlockSize=0; Prg->FilteredData=Mem+NewBlockPos; Prg->FilteredDataSize=NewBlockSize; Prg->GlobalData.Reset(); uint DataSize=Min(GET_VALUE(false,(uint*)&Mem[VM_GLOBALMEMADDR+0x30]),VM_GLOBALMEMSIZE); if (DataSize!=0) { Prg->GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE); memcpy(&Prg->GlobalData[0],&Mem[VM_GLOBALMEMADDR],DataSize+VM_FIXEDGLOBALSIZE); } } #define SET_IP(IP) \ if ((IP)>=(uint)CodeSize) \ return(true); \ if (--MaxOpCount<=0) \ return(false); \ Cmd=PreparedCode+(IP); bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize) { int MaxOpCount=25000000; VM_PreparedCommand *Cmd=PreparedCode; while (1) { uint *Op1=GetOperand(&Cmd->Op1); uint *Op2=GetOperand(&Cmd->Op2); switch(Cmd->OpCode) { #ifndef NORARVM case VM_MOV: SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2)); break; #ifdef VM_OPTIMIZE case VM_MOVB: SET_VALUE(true,Op1,GET_VALUE(true,Op2)); break; case VM_MOVD: SET_VALUE(false,Op1,GET_VALUE(false,Op2)); break; #endif case VM_CMP: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); } break; #ifdef VM_OPTIMIZE case VM_CMPB: { uint Value1=GET_VALUE(true,Op1); uint Result=UINT32(Value1-GET_VALUE(true,Op2)); Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); } break; case VM_CMPD: { uint Value1=GET_VALUE(false,Op1); uint Result=UINT32(Value1-GET_VALUE(false,Op2)); Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); } break; #endif case VM_ADD: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:(ResultByteMode,Op1,Result); } break; #ifdef VM_OPTIMIZE case VM_ADDB: SET_VALUE(true,Op1,GET_VALUE(true,Op1)+GET_VALUE(true,Op2)); break; case VM_ADDD: SET_VALUE(false,Op1,GET_VALUE(false,Op1)+GET_VALUE(false,Op2)); break; #endif case VM_SUB: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; #ifdef VM_OPTIMIZE case VM_SUBB: SET_VALUE(true,Op1,GET_VALUE(true,Op1)-GET_VALUE(true,Op2)); break; case VM_SUBD: SET_VALUE(false,Op1,GET_VALUE(false,Op1)-GET_VALUE(false,Op2)); break; #endif case VM_JZ: if ((Flags & VM_FZ)!=0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JNZ: if ((Flags & VM_FZ)==0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_INC: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1); SET_VALUE(Cmd->ByteMode,Op1,Result); Flags=Result==0 ? VM_FZ:Result&VM_FS; } break; #ifdef VM_OPTIMIZE case VM_INCB: SET_VALUE(true,Op1,GET_VALUE(true,Op1)+1); break; case VM_INCD: SET_VALUE(false,Op1,GET_VALUE(false,Op1)+1); break; #endif case VM_DEC: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1); SET_VALUE(Cmd->ByteMode,Op1,Result); Flags=Result==0 ? VM_FZ:Result&VM_FS; } break; #ifdef VM_OPTIMIZE case VM_DECB: SET_VALUE(true,Op1,GET_VALUE(true,Op1)-1); break; case VM_DECD: SET_VALUE(false,Op1,GET_VALUE(false,Op1)-1); break; #endif case VM_JMP: SET_IP(GET_VALUE(false,Op1)); continue; case VM_XOR: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:Result&VM_FS; SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_AND: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:Result&VM_FS; SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_OR: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:Result&VM_FS; SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_TEST: { uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2)); Flags=Result==0 ? VM_FZ:Result&VM_FS; } break; case VM_JS: if ((Flags & VM_FS)!=0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JNS: if ((Flags & VM_FS)==0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JB: if ((Flags & VM_FC)!=0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JBE: if ((Flags & (VM_FC|VM_FZ))!=0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JA: if ((Flags & (VM_FC|VM_FZ))==0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_JAE: if ((Flags & VM_FC)==0) { SET_IP(GET_VALUE(false,Op1)); continue; } break; case VM_PUSH: R[7]-=4; SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],GET_VALUE(false,Op1)); break; case VM_POP: SET_VALUE(false,Op1,GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK])); R[7]+=4; break; case VM_CALL: R[7]-=4; SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Cmd-PreparedCode+1); SET_IP(GET_VALUE(false,Op1)); continue; case VM_NOT: SET_VALUE(Cmd->ByteMode,Op1,~GET_VALUE(Cmd->ByteMode,Op1)); break; case VM_SHL: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Value2=GET_VALUE(Cmd->ByteMode,Op2); uint Result=UINT32(Value1<ByteMode,Op1,Result); } break; case VM_SHR: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Value2=GET_VALUE(Cmd->ByteMode,Op2); uint Result=UINT32(Value1>>Value2); Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_SAR: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint Value2=GET_VALUE(Cmd->ByteMode,Op2); uint Result=UINT32(((int)Value1)>>Value2); Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_NEG: { uint Result=UINT32(-GET_VALUE(Cmd->ByteMode,Op1)); Flags=Result==0 ? VM_FZ:VM_FC|(Result&VM_FS); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; #ifdef VM_OPTIMIZE case VM_NEGB: SET_VALUE(true,Op1,-GET_VALUE(true,Op1)); break; case VM_NEGD: SET_VALUE(false,Op1,-GET_VALUE(false,Op1)); break; #endif case VM_PUSHA: { const int RegCount=sizeof(R)/sizeof(R[0]); for (int I=0,SP=R[7]-4;IByteMode,Op1); SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2)); SET_VALUE(Cmd->ByteMode,Op2,Value1); } break; case VM_MUL: { uint Result=GET_VALUE(Cmd->ByteMode,Op1)*GET_VALUE(Cmd->ByteMode,Op2); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; case VM_DIV: { uint Divider=GET_VALUE(Cmd->ByteMode,Op2); if (Divider!=0) { uint Result=GET_VALUE(Cmd->ByteMode,Op1)/Divider; SET_VALUE(Cmd->ByteMode,Op1,Result); } } break; case VM_ADC: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint FC=(Flags&VM_FC); uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC); Flags=Result==0 ? VM_FZ:(ResultByteMode,Op1,Result); } break; case VM_SBB: { uint Value1=GET_VALUE(Cmd->ByteMode,Op1); uint FC=(Flags&VM_FC); uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC); Flags=Result==0 ? VM_FZ:(Result>Value1 || (Result==Value1 && FC))|(Result&VM_FS); SET_VALUE(Cmd->ByteMode,Op1,Result); } break; #endif case VM_RET: if (R[7]>=VM_MEMSIZE) return(true); SET_IP(GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK])); R[7]+=4; continue; #ifdef VM_STANDARDFILTERS case VM_STANDARD: ExecuteStandardFilter((VM_StandardFilters)Cmd->Op1.Data); break; #endif case VM_PRINT: #ifdef DEBUG PrintState(Cmd-PreparedCode); #endif break; } Cmd++; --MaxOpCount; } } void RarVM::PrintState(uint IP) { #if defined(DEBUG) && !defined(GUI) && !defined(SILENT) mprintf("\n"); for (int I=0;ICmdCount=0; if (XorSum==Code[0]) { #ifdef VM_STANDARDFILTERS VM_StandardFilters FilterType=IsStandardFilter(Code,CodeSize); if (FilterType!=VMSF_NONE) { Prg->Cmd.Add(1); VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount++]; CurCmd->OpCode=VM_STANDARD; CurCmd->Op1.Data=FilterType; CurCmd->Op1.Addr=&CurCmd->Op1.Data; CurCmd->Op2.Addr=&CurCmd->Op2.Data; CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; CodeSize=0; } #endif uint DataFlag=fgetbits(); faddbits(1); if (DataFlag&0x8000) { int DataSize=ReadData(*this)+1; for (int I=0;InAddrStaticData.Add(1); Prg->StaticData[I]=fgetbits()>>8; faddbits(8); } } while (InAddrCmd.Add(1); VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount]; 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; CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; for (int I=0;ICmdCount;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 (PosCmd[0]; int CodeSize=Prg->CmdCount; for (int I=0;IOpCode) { case VM_MOV: Cmd->OpCode=Cmd->ByteMode ? VM_MOVB:VM_MOVD; continue; case VM_CMP: Cmd->OpCode=Cmd->ByteMode ? VM_CMPB:VM_CMPD; continue; default: break; } if ((VM_CmdFlags[Cmd->OpCode] & VMCF_CHFLAGS)==0) continue; bool FlagsRequired=false; for (int J=I+1;JOpCode) { 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; default: break; } } } #endif #ifdef VM_STANDARDFILTERS VM_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 (unsigned int I=0;I=VM_GLOBALMEMADDR) break; const int FileSize=0x1000000; byte CmpByte2=FilterType==VMSF_E8E9 ? 0xe9:0xe8; for (uint CurPos=0;CurPos<((uint)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=VM_GLOBALMEMADDR) break; uint CurPos=0; FileOffset>>=4; while (CurPos=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<=VM_GLOBALMEMADDR/2) break; for (int CurChannel=0;CurChannel=VM_GLOBALMEMADDR/2) break; for (int CurChannel=0;CurChannel=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=VM_GLOBALMEMADDR/2) break; for (int CurChannel=0;CurChannel>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 (unsigned int J=1;J=-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>= 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<>8)|0xff000000; BitField>>=8; } } #endif