Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Compress/Rar3Vm.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/Rar3Vm.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,1094 @@ 1.4 +// Rar3Vm.cpp 1.5 +// According to unRAR license, this code may not be used to develop 1.6 +// a program that creates RAR archives 1.7 + 1.8 +/* 1.9 +Note: 1.10 + Due to performance considerations Rar VM may set Flags C incorrectly 1.11 + for some operands (SHL x, 0, ... ). 1.12 + Check implementation of concrete VM command 1.13 + to see if it sets flags right. 1.14 +*/ 1.15 + 1.16 +#include "StdAfx.h" 1.17 + 1.18 +extern "C" 1.19 +{ 1.20 +#include "../../../C/7zCrc.h" 1.21 +#include "../../../C/Alloc.h" 1.22 +} 1.23 + 1.24 +#include "Rar3Vm.h" 1.25 + 1.26 +namespace NCompress { 1.27 +namespace NRar3 { 1.28 + 1.29 +UInt32 CMemBitDecoder::ReadBits(int numBits) 1.30 +{ 1.31 + UInt32 res = 0; 1.32 + for (;;) 1.33 + { 1.34 + Byte b = _bitPos < _bitSize ? _data[_bitPos >> 3] : 0; 1.35 + int avail = (int)(8 - (_bitPos & 7)); 1.36 + if (numBits <= avail) 1.37 + { 1.38 + _bitPos += numBits; 1.39 + return res | (b >> (avail - numBits)) & ((1 << numBits) - 1); 1.40 + } 1.41 + numBits -= avail; 1.42 + res |= (UInt32)(b & ((1 << avail) - 1)) << numBits; 1.43 + _bitPos += avail; 1.44 + } 1.45 +} 1.46 + 1.47 +UInt32 CMemBitDecoder::ReadBit() { return ReadBits(1); } 1.48 + 1.49 +namespace NVm { 1.50 + 1.51 +static const UInt32 kStackRegIndex = kNumRegs - 1; 1.52 + 1.53 +static const UInt32 FLAG_C = 1; 1.54 +static const UInt32 FLAG_Z = 2; 1.55 +static const UInt32 FLAG_S = 0x80000000; 1.56 + 1.57 +static const Byte CF_OP0 = 0; 1.58 +static const Byte CF_OP1 = 1; 1.59 +static const Byte CF_OP2 = 2; 1.60 +static const Byte CF_OPMASK = 3; 1.61 +static const Byte CF_BYTEMODE = 4; 1.62 +static const Byte CF_JUMP = 8; 1.63 +static const Byte CF_PROC = 16; 1.64 +static const Byte CF_USEFLAGS = 32; 1.65 +static const Byte CF_CHFLAGS = 64; 1.66 + 1.67 +static Byte kCmdFlags[]= 1.68 +{ 1.69 + /* CMD_MOV */ CF_OP2 | CF_BYTEMODE, 1.70 + /* CMD_CMP */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.71 + /* CMD_ADD */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.72 + /* CMD_SUB */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.73 + /* CMD_JZ */ CF_OP1 | CF_JUMP | CF_USEFLAGS, 1.74 + /* CMD_JNZ */ CF_OP1 | CF_JUMP | CF_USEFLAGS, 1.75 + /* CMD_INC */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS, 1.76 + /* CMD_DEC */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS, 1.77 + /* CMD_JMP */ CF_OP1 | CF_JUMP, 1.78 + /* CMD_XOR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.79 + /* CMD_AND */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.80 + /* CMD_OR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.81 + /* CMD_TEST */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.82 + /* CMD_JS */ CF_OP1 | CF_JUMP | CF_USEFLAGS, 1.83 + /* CMD_JNS */ CF_OP1 | CF_JUMP | CF_USEFLAGS, 1.84 + /* CMD_JB */ CF_OP1 | CF_JUMP | CF_USEFLAGS, 1.85 + /* CMD_JBE */ CF_OP1 | CF_JUMP | CF_USEFLAGS, 1.86 + /* CMD_JA */ CF_OP1 | CF_JUMP | CF_USEFLAGS, 1.87 + /* CMD_JAE */ CF_OP1 | CF_JUMP | CF_USEFLAGS, 1.88 + /* CMD_PUSH */ CF_OP1, 1.89 + /* CMD_POP */ CF_OP1, 1.90 + /* CMD_CALL */ CF_OP1 | CF_PROC, 1.91 + /* CMD_RET */ CF_OP0 | CF_PROC, 1.92 + /* CMD_NOT */ CF_OP1 | CF_BYTEMODE, 1.93 + /* CMD_SHL */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.94 + /* CMD_SHR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.95 + /* CMD_SAR */ CF_OP2 | CF_BYTEMODE | CF_CHFLAGS, 1.96 + /* CMD_NEG */ CF_OP1 | CF_BYTEMODE | CF_CHFLAGS, 1.97 + /* CMD_PUSHA */ CF_OP0, 1.98 + /* CMD_POPA */ CF_OP0, 1.99 + /* CMD_PUSHF */ CF_OP0 | CF_USEFLAGS, 1.100 + /* CMD_POPF */ CF_OP0 | CF_CHFLAGS, 1.101 + /* CMD_MOVZX */ CF_OP2, 1.102 + /* CMD_MOVSX */ CF_OP2, 1.103 + /* CMD_XCHG */ CF_OP2 | CF_BYTEMODE, 1.104 + /* CMD_MUL */ CF_OP2 | CF_BYTEMODE, 1.105 + /* CMD_DIV */ CF_OP2 | CF_BYTEMODE, 1.106 + /* CMD_ADC */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS , 1.107 + /* CMD_SBB */ CF_OP2 | CF_BYTEMODE | CF_USEFLAGS | CF_CHFLAGS , 1.108 + /* CMD_PRINT */ CF_OP0 1.109 +}; 1.110 + 1.111 +CVm::CVm(): Mem(NULL) {} 1.112 + 1.113 +bool CVm::Create() 1.114 +{ 1.115 + if (Mem == NULL) 1.116 + Mem = (Byte *)::MyAlloc(kSpaceSize + 4); 1.117 + return (Mem != NULL); 1.118 +} 1.119 + 1.120 +CVm::~CVm() 1.121 +{ 1.122 + ::MyFree(Mem); 1.123 +} 1.124 + 1.125 +// CVm::Execute can change CProgram object: it clears progarm if VM returns error. 1.126 + 1.127 +bool CVm::Execute(CProgram *prg, const CProgramInitState *initState, 1.128 + CBlockRef &outBlockRef, CRecordVector<Byte> &outGlobalData) 1.129 +{ 1.130 + memcpy(R, initState->InitR, sizeof(initState->InitR)); 1.131 + R[kStackRegIndex] = kSpaceSize; 1.132 + R[kNumRegs] = 0; 1.133 + Flags = 0; 1.134 + 1.135 + UInt32 globalSize = MyMin((UInt32)initState->GlobalData.Size(), kGlobalSize); 1.136 + if (globalSize != 0) 1.137 + memcpy(Mem + kGlobalOffset, &initState->GlobalData[0], globalSize); 1.138 + UInt32 staticSize = MyMin((UInt32)prg->StaticData.Size(), kGlobalSize - globalSize); 1.139 + if (staticSize != 0) 1.140 + memcpy(Mem + kGlobalOffset + globalSize, &prg->StaticData[0], staticSize); 1.141 + 1.142 + bool res = true; 1.143 + #ifdef RARVM_STANDARD_FILTERS 1.144 + if (prg->StandardFilterIndex >= 0) 1.145 + ExecuteStandardFilter(prg->StandardFilterIndex); 1.146 + else 1.147 + #endif 1.148 + { 1.149 + res = ExecuteCode(prg); 1.150 + if (!res) 1.151 + prg->Commands[0].OpCode = CMD_RET; 1.152 + } 1.153 + UInt32 newBlockPos = GetFixedGlobalValue32(NGlobalOffset::kBlockPos) & kSpaceMask; 1.154 + UInt32 newBlockSize = GetFixedGlobalValue32(NGlobalOffset::kBlockSize) & kSpaceMask; 1.155 + if (newBlockPos + newBlockSize >= kSpaceSize) 1.156 + newBlockPos = newBlockSize = 0; 1.157 + outBlockRef.Offset = newBlockPos; 1.158 + outBlockRef.Size = newBlockSize; 1.159 + 1.160 + outGlobalData.Clear(); 1.161 + UInt32 dataSize = GetFixedGlobalValue32(NGlobalOffset::kGlobalMemOutSize); 1.162 + dataSize = MyMin(dataSize, kGlobalSize - kFixedGlobalSize); 1.163 + if (dataSize != 0) 1.164 + { 1.165 + dataSize += kFixedGlobalSize; 1.166 + outGlobalData.Reserve(dataSize); 1.167 + for (UInt32 i = 0; i < dataSize; i++) 1.168 + outGlobalData.Add(Mem[kGlobalOffset + i]); 1.169 + } 1.170 + return res; 1.171 +} 1.172 + 1.173 + 1.174 +#define SET_IP(IP) \ 1.175 + if ((IP) >= numCommands) return true; \ 1.176 + if (--maxOpCount <= 0) return false; \ 1.177 + cmd = commands + (IP); 1.178 + 1.179 +#define GET_FLAG_S_B(res) (((res) & 0x80) ? FLAG_S : 0) 1.180 +#define SET_IP_OP1 { UInt32 val = GetOperand32(&cmd->Op1); SET_IP(val); } 1.181 +#define FLAGS_UPDATE_SZ Flags = res == 0 ? FLAG_Z : res & FLAG_S 1.182 +#define FLAGS_UPDATE_SZ_B Flags = (res & 0xFF) == 0 ? FLAG_Z : GET_FLAG_S_B(res) 1.183 + 1.184 +UInt32 CVm::GetOperand32(const COperand *op) const 1.185 +{ 1.186 + switch(op->Type) 1.187 + { 1.188 + case OP_TYPE_REG: return R[op->Data]; 1.189 + case OP_TYPE_REGMEM: return GetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask]); 1.190 + default: return op->Data; 1.191 + } 1.192 +} 1.193 + 1.194 +void CVm::SetOperand32(const COperand *op, UInt32 val) 1.195 +{ 1.196 + switch(op->Type) 1.197 + { 1.198 + case OP_TYPE_REG: R[op->Data] = val; return; 1.199 + case OP_TYPE_REGMEM: SetValue32(&Mem[(op->Base + R[op->Data]) & kSpaceMask], val); return; 1.200 + } 1.201 +} 1.202 + 1.203 +Byte CVm::GetOperand8(const COperand *op) const 1.204 +{ 1.205 + switch(op->Type) 1.206 + { 1.207 + case OP_TYPE_REG: return (Byte)R[op->Data]; 1.208 + case OP_TYPE_REGMEM: return Mem[(op->Base + R[op->Data]) & kSpaceMask];; 1.209 + default: return (Byte)op->Data; 1.210 + } 1.211 +} 1.212 + 1.213 +void CVm::SetOperand8(const COperand *op, Byte val) 1.214 +{ 1.215 + switch(op->Type) 1.216 + { 1.217 + case OP_TYPE_REG: R[op->Data] = (R[op->Data] & 0xFFFFFF00) | val; return; 1.218 + case OP_TYPE_REGMEM: Mem[(op->Base + R[op->Data]) & kSpaceMask] = val; return; 1.219 + } 1.220 +} 1.221 + 1.222 +UInt32 CVm::GetOperand(bool byteMode, const COperand *op) const 1.223 +{ 1.224 + if (byteMode) 1.225 + return GetOperand8(op); 1.226 + return GetOperand32(op); 1.227 +} 1.228 + 1.229 +void CVm::SetOperand(bool byteMode, const COperand *op, UInt32 val) 1.230 +{ 1.231 + if (byteMode) 1.232 + SetOperand8(op, (Byte)(val & 0xFF)); 1.233 + else 1.234 + SetOperand32(op, val); 1.235 +} 1.236 + 1.237 +bool CVm::ExecuteCode(const CProgram *prg) 1.238 +{ 1.239 + Int32 maxOpCount = 25000000; 1.240 + const CCommand *commands = &prg->Commands[0]; 1.241 + const CCommand *cmd = commands; 1.242 + UInt32 numCommands = prg->Commands.Size(); 1.243 + for (;;) 1.244 + { 1.245 + switch(cmd->OpCode) 1.246 + { 1.247 + #ifndef RARVM_NO_VM 1.248 + 1.249 + case CMD_MOV: 1.250 + SetOperand32(&cmd->Op1, GetOperand32(&cmd->Op2)); 1.251 + break; 1.252 + case CMD_MOVB: 1.253 + SetOperand8(&cmd->Op1, GetOperand8(&cmd->Op2)); 1.254 + break; 1.255 + case CMD_CMP: 1.256 + { 1.257 + UInt32 v1 = GetOperand32(&cmd->Op1); 1.258 + UInt32 res = v1 - GetOperand32(&cmd->Op2); 1.259 + Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S); 1.260 + } 1.261 + break; 1.262 + case CMD_CMPB: 1.263 + { 1.264 + Byte v1 = GetOperand8(&cmd->Op1); 1.265 + Byte res = v1 - GetOperand8(&cmd->Op2); 1.266 + res &= 0xFF; 1.267 + Flags = res == 0 ? FLAG_Z : (res > v1) | GET_FLAG_S_B(res); 1.268 + } 1.269 + break; 1.270 + case CMD_ADD: 1.271 + { 1.272 + UInt32 v1 = GetOperand32(&cmd->Op1); 1.273 + UInt32 res = v1 + GetOperand32(&cmd->Op2); 1.274 + SetOperand32(&cmd->Op1, res); 1.275 + Flags = (res < v1) | (res == 0 ? FLAG_Z : (res & FLAG_S)); 1.276 + } 1.277 + break; 1.278 + case CMD_ADDB: 1.279 + { 1.280 + Byte v1 = GetOperand8(&cmd->Op1); 1.281 + Byte res = v1 + GetOperand8(&cmd->Op2); 1.282 + res &= 0xFF; 1.283 + SetOperand8(&cmd->Op1, (Byte)res); 1.284 + Flags = (res < v1) | (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)); 1.285 + } 1.286 + break; 1.287 + case CMD_ADC: 1.288 + { 1.289 + UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1); 1.290 + UInt32 FC = (Flags & FLAG_C); 1.291 + UInt32 res = v1 + GetOperand(cmd->ByteMode, &cmd->Op2) + FC; 1.292 + if (cmd->ByteMode) 1.293 + res &= 0xFF; 1.294 + SetOperand(cmd->ByteMode, &cmd->Op1, res); 1.295 + Flags = (res < v1 || res == v1 && FC) | (res == 0 ? FLAG_Z : (res & FLAG_S)); 1.296 + } 1.297 + break; 1.298 + case CMD_SUB: 1.299 + { 1.300 + UInt32 v1 = GetOperand32(&cmd->Op1); 1.301 + UInt32 res = v1 - GetOperand32(&cmd->Op2); 1.302 + SetOperand32(&cmd->Op1, res); 1.303 + Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S); 1.304 + } 1.305 + break; 1.306 + case CMD_SUBB: 1.307 + { 1.308 + UInt32 v1 = GetOperand8(&cmd->Op1); 1.309 + UInt32 res = v1 - GetOperand8(&cmd->Op2); 1.310 + SetOperand8(&cmd->Op1, (Byte)res); 1.311 + Flags = res == 0 ? FLAG_Z : (res > v1) | (res & FLAG_S); 1.312 + } 1.313 + break; 1.314 + case CMD_SBB: 1.315 + { 1.316 + UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1); 1.317 + UInt32 FC = (Flags & FLAG_C); 1.318 + UInt32 res = v1 - GetOperand(cmd->ByteMode, &cmd->Op2) - FC; 1.319 + // Flags = res == 0 ? FLAG_Z : (res > v1 || res == v1 && FC) | (res & FLAG_S); 1.320 + if (cmd->ByteMode) 1.321 + res &= 0xFF; 1.322 + SetOperand(cmd->ByteMode, &cmd->Op1, res); 1.323 + Flags = (res > v1 || res == v1 && FC) | (res == 0 ? FLAG_Z : (res & FLAG_S)); 1.324 + } 1.325 + break; 1.326 + case CMD_INC: 1.327 + { 1.328 + UInt32 res = GetOperand32(&cmd->Op1) + 1; 1.329 + SetOperand32(&cmd->Op1, res); 1.330 + FLAGS_UPDATE_SZ; 1.331 + } 1.332 + break; 1.333 + case CMD_INCB: 1.334 + { 1.335 + Byte res = GetOperand8(&cmd->Op1) + 1; 1.336 + SetOperand8(&cmd->Op1, res);; 1.337 + FLAGS_UPDATE_SZ_B; 1.338 + } 1.339 + break; 1.340 + case CMD_DEC: 1.341 + { 1.342 + UInt32 res = GetOperand32(&cmd->Op1) - 1; 1.343 + SetOperand32(&cmd->Op1, res); 1.344 + FLAGS_UPDATE_SZ; 1.345 + } 1.346 + break; 1.347 + case CMD_DECB: 1.348 + { 1.349 + Byte res = GetOperand8(&cmd->Op1) - 1; 1.350 + SetOperand8(&cmd->Op1, res);; 1.351 + FLAGS_UPDATE_SZ_B; 1.352 + } 1.353 + break; 1.354 + case CMD_XOR: 1.355 + { 1.356 + UInt32 res = GetOperand32(&cmd->Op1) ^ GetOperand32(&cmd->Op2); 1.357 + SetOperand32(&cmd->Op1, res); 1.358 + FLAGS_UPDATE_SZ; 1.359 + } 1.360 + break; 1.361 + case CMD_XORB: 1.362 + { 1.363 + Byte res = GetOperand8(&cmd->Op1) ^ GetOperand8(&cmd->Op2); 1.364 + SetOperand8(&cmd->Op1, res); 1.365 + FLAGS_UPDATE_SZ_B; 1.366 + } 1.367 + break; 1.368 + case CMD_AND: 1.369 + { 1.370 + UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2); 1.371 + SetOperand32(&cmd->Op1, res); 1.372 + FLAGS_UPDATE_SZ; 1.373 + } 1.374 + break; 1.375 + case CMD_ANDB: 1.376 + { 1.377 + Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2); 1.378 + SetOperand8(&cmd->Op1, res); 1.379 + FLAGS_UPDATE_SZ_B; 1.380 + } 1.381 + break; 1.382 + case CMD_OR: 1.383 + { 1.384 + UInt32 res = GetOperand32(&cmd->Op1) | GetOperand32(&cmd->Op2); 1.385 + SetOperand32(&cmd->Op1, res); 1.386 + FLAGS_UPDATE_SZ; 1.387 + } 1.388 + break; 1.389 + case CMD_ORB: 1.390 + { 1.391 + Byte res = GetOperand8(&cmd->Op1) | GetOperand8(&cmd->Op2); 1.392 + SetOperand8(&cmd->Op1, res); 1.393 + FLAGS_UPDATE_SZ_B; 1.394 + } 1.395 + break; 1.396 + case CMD_TEST: 1.397 + { 1.398 + UInt32 res = GetOperand32(&cmd->Op1) & GetOperand32(&cmd->Op2); 1.399 + FLAGS_UPDATE_SZ; 1.400 + } 1.401 + break; 1.402 + case CMD_TESTB: 1.403 + { 1.404 + Byte res = GetOperand8(&cmd->Op1) & GetOperand8(&cmd->Op2); 1.405 + FLAGS_UPDATE_SZ_B; 1.406 + } 1.407 + break; 1.408 + case CMD_NOT: 1.409 + SetOperand(cmd->ByteMode, &cmd->Op1, ~GetOperand(cmd->ByteMode, &cmd->Op1)); 1.410 + break; 1.411 + case CMD_NEG: 1.412 + { 1.413 + UInt32 res = 0 - GetOperand32(&cmd->Op1); 1.414 + SetOperand32(&cmd->Op1, res); 1.415 + Flags = res == 0 ? FLAG_Z : FLAG_C | (res & FLAG_S); 1.416 + } 1.417 + break; 1.418 + case CMD_NEGB: 1.419 + { 1.420 + Byte res = (Byte)(0 - GetOperand8(&cmd->Op1)); 1.421 + SetOperand8(&cmd->Op1, res); 1.422 + Flags = res == 0 ? FLAG_Z : FLAG_C | GET_FLAG_S_B(res); 1.423 + } 1.424 + break; 1.425 + 1.426 + case CMD_SHL: 1.427 + { 1.428 + UInt32 v1 = GetOperand32(&cmd->Op1); 1.429 + int v2 = (int)GetOperand32(&cmd->Op2); 1.430 + UInt32 res = v1 << v2; 1.431 + SetOperand32(&cmd->Op1, res); 1.432 + Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 << (v2 - 1)) & 0x80000000 ? FLAG_C : 0); 1.433 + } 1.434 + break; 1.435 + case CMD_SHLB: 1.436 + { 1.437 + Byte v1 = GetOperand8(&cmd->Op1); 1.438 + int v2 = (int)GetOperand8(&cmd->Op2); 1.439 + Byte res = (Byte)(v1 << v2); 1.440 + SetOperand8(&cmd->Op1, res); 1.441 + Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 << (v2 - 1)) & 0x80 ? FLAG_C : 0); 1.442 + } 1.443 + break; 1.444 + case CMD_SHR: 1.445 + { 1.446 + UInt32 v1 = GetOperand32(&cmd->Op1); 1.447 + int v2 = (int)GetOperand32(&cmd->Op2); 1.448 + UInt32 res = v1 >> v2; 1.449 + SetOperand32(&cmd->Op1, res); 1.450 + Flags = (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C); 1.451 + } 1.452 + break; 1.453 + case CMD_SHRB: 1.454 + { 1.455 + Byte v1 = GetOperand8(&cmd->Op1); 1.456 + int v2 = (int)GetOperand8(&cmd->Op2); 1.457 + Byte res = (Byte)(v1 >> v2); 1.458 + SetOperand8(&cmd->Op1, res); 1.459 + Flags = (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C); 1.460 + } 1.461 + break; 1.462 + case CMD_SAR: 1.463 + { 1.464 + UInt32 v1 = GetOperand32(&cmd->Op1); 1.465 + int v2 = (int)GetOperand32(&cmd->Op2); 1.466 + UInt32 res = UInt32(((Int32)v1) >> v2); 1.467 + SetOperand32(&cmd->Op1, res); 1.468 + Flags= (res == 0 ? FLAG_Z : (res & FLAG_S)) | ((v1 >> (v2 - 1)) & FLAG_C); 1.469 + } 1.470 + break; 1.471 + case CMD_SARB: 1.472 + { 1.473 + Byte v1 = GetOperand8(&cmd->Op1); 1.474 + int v2 = (int)GetOperand8(&cmd->Op2); 1.475 + Byte res = (Byte)(((signed char)v1) >> v2); 1.476 + SetOperand8(&cmd->Op1, res); 1.477 + Flags= (res == 0 ? FLAG_Z : GET_FLAG_S_B(res)) | ((v1 >> (v2 - 1)) & FLAG_C); 1.478 + } 1.479 + break; 1.480 + 1.481 + case CMD_JMP: 1.482 + SET_IP_OP1; 1.483 + continue; 1.484 + case CMD_JZ: 1.485 + if ((Flags & FLAG_Z) != 0) 1.486 + { 1.487 + SET_IP_OP1; 1.488 + continue; 1.489 + } 1.490 + break; 1.491 + case CMD_JNZ: 1.492 + if ((Flags & FLAG_Z) == 0) 1.493 + { 1.494 + SET_IP_OP1; 1.495 + continue; 1.496 + } 1.497 + break; 1.498 + case CMD_JS: 1.499 + if ((Flags & FLAG_S) != 0) 1.500 + { 1.501 + SET_IP_OP1; 1.502 + continue; 1.503 + } 1.504 + break; 1.505 + case CMD_JNS: 1.506 + if ((Flags & FLAG_S) == 0) 1.507 + { 1.508 + SET_IP_OP1; 1.509 + continue; 1.510 + } 1.511 + break; 1.512 + case CMD_JB: 1.513 + if ((Flags & FLAG_C) != 0) 1.514 + { 1.515 + SET_IP_OP1; 1.516 + continue; 1.517 + } 1.518 + break; 1.519 + case CMD_JBE: 1.520 + if ((Flags & (FLAG_C | FLAG_Z)) != 0) 1.521 + { 1.522 + SET_IP_OP1; 1.523 + continue; 1.524 + } 1.525 + break; 1.526 + case CMD_JA: 1.527 + if ((Flags & (FLAG_C | FLAG_Z)) == 0) 1.528 + { 1.529 + SET_IP_OP1; 1.530 + continue; 1.531 + } 1.532 + break; 1.533 + case CMD_JAE: 1.534 + if ((Flags & FLAG_C) == 0) 1.535 + { 1.536 + SET_IP_OP1; 1.537 + continue; 1.538 + } 1.539 + break; 1.540 + 1.541 + case CMD_PUSH: 1.542 + R[kStackRegIndex] -= 4; 1.543 + SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], GetOperand32(&cmd->Op1)); 1.544 + break; 1.545 + case CMD_POP: 1.546 + SetOperand32(&cmd->Op1, GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask])); 1.547 + R[kStackRegIndex] += 4; 1.548 + break; 1.549 + case CMD_CALL: 1.550 + R[kStackRegIndex] -= 4; 1.551 + SetValue32(&Mem[R[kStackRegIndex] & kSpaceMask], (UInt32)(cmd - commands + 1)); 1.552 + SET_IP_OP1; 1.553 + continue; 1.554 + 1.555 + case CMD_PUSHA: 1.556 + { 1.557 + for (UInt32 i = 0, SP = R[kStackRegIndex] - 4; i < kNumRegs; i++, SP -= 4) 1.558 + SetValue32(&Mem[SP & kSpaceMask], R[i]); 1.559 + R[kStackRegIndex] -= kNumRegs * 4; 1.560 + } 1.561 + break; 1.562 + case CMD_POPA: 1.563 + { 1.564 + for (UInt32 i = 0, SP = R[kStackRegIndex]; i < kNumRegs; i++, SP += 4) 1.565 + R[kStackRegIndex - i] = GetValue32(&Mem[SP & kSpaceMask]); 1.566 + } 1.567 + break; 1.568 + case CMD_PUSHF: 1.569 + R[kStackRegIndex] -= 4; 1.570 + SetValue32(&Mem[R[kStackRegIndex]&kSpaceMask], Flags); 1.571 + break; 1.572 + case CMD_POPF: 1.573 + Flags = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]); 1.574 + R[kStackRegIndex] += 4; 1.575 + break; 1.576 + 1.577 + case CMD_MOVZX: 1.578 + SetOperand32(&cmd->Op1, GetOperand8(&cmd->Op2)); 1.579 + break; 1.580 + case CMD_MOVSX: 1.581 + SetOperand32(&cmd->Op1, (UInt32)(Int32)(signed char)GetOperand8(&cmd->Op2)); 1.582 + break; 1.583 + case CMD_XCHG: 1.584 + { 1.585 + UInt32 v1 = GetOperand(cmd->ByteMode, &cmd->Op1); 1.586 + SetOperand(cmd->ByteMode, &cmd->Op1, GetOperand(cmd->ByteMode, &cmd->Op2)); 1.587 + SetOperand(cmd->ByteMode, &cmd->Op2, v1); 1.588 + } 1.589 + break; 1.590 + case CMD_MUL: 1.591 + { 1.592 + UInt32 res = GetOperand32(&cmd->Op1) * GetOperand32(&cmd->Op2); 1.593 + SetOperand32(&cmd->Op1, res); 1.594 + } 1.595 + break; 1.596 + case CMD_MULB: 1.597 + { 1.598 + Byte res = GetOperand8(&cmd->Op1) * GetOperand8(&cmd->Op2); 1.599 + SetOperand8(&cmd->Op1, res); 1.600 + } 1.601 + break; 1.602 + case CMD_DIV: 1.603 + { 1.604 + UInt32 divider = GetOperand(cmd->ByteMode, &cmd->Op2); 1.605 + if (divider != 0) 1.606 + { 1.607 + UInt32 res = GetOperand(cmd->ByteMode, &cmd->Op1) / divider; 1.608 + SetOperand(cmd->ByteMode, &cmd->Op1, res); 1.609 + } 1.610 + } 1.611 + break; 1.612 + 1.613 + #endif 1.614 + 1.615 + case CMD_RET: 1.616 + { 1.617 + if (R[kStackRegIndex] >= kSpaceSize) 1.618 + return true; 1.619 + UInt32 ip = GetValue32(&Mem[R[kStackRegIndex] & kSpaceMask]); 1.620 + SET_IP(ip); 1.621 + R[kStackRegIndex] += 4; 1.622 + continue; 1.623 + } 1.624 + case CMD_PRINT: 1.625 + break; 1.626 + } 1.627 + cmd++; 1.628 + --maxOpCount; 1.629 + } 1.630 +} 1.631 + 1.632 + 1.633 +////////////////////////////////////////////////////// 1.634 +// Read program 1.635 + 1.636 +UInt32 ReadEncodedUInt32(CMemBitDecoder &inp) 1.637 +{ 1.638 + switch(inp.ReadBits(2)) 1.639 + { 1.640 + case 0: 1.641 + return inp.ReadBits(4); 1.642 + case 1: 1.643 + { 1.644 + UInt32 v = inp.ReadBits(4); 1.645 + if (v == 0) 1.646 + return 0xFFFFFF00 | inp.ReadBits(8); 1.647 + else 1.648 + return (v << 4) | inp.ReadBits(4); 1.649 + } 1.650 + case 2: 1.651 + return inp.ReadBits(16); 1.652 + default: 1.653 + return inp.ReadBits(32); 1.654 + } 1.655 +} 1.656 + 1.657 +void CVm::DecodeArg(CMemBitDecoder &inp, COperand &op, bool byteMode) 1.658 +{ 1.659 + if (inp.ReadBit()) 1.660 + { 1.661 + op.Type = OP_TYPE_REG; 1.662 + op.Data = inp.ReadBits(kNumRegBits); 1.663 + } 1.664 + else if (inp.ReadBit() == 0) 1.665 + { 1.666 + op.Type = OP_TYPE_INT; 1.667 + if (byteMode) 1.668 + op.Data = inp.ReadBits(8); 1.669 + else 1.670 + op.Data = ReadEncodedUInt32(inp); 1.671 + } 1.672 + else 1.673 + { 1.674 + op.Type = OP_TYPE_REGMEM; 1.675 + if (inp.ReadBit() == 0) 1.676 + { 1.677 + op.Data = inp.ReadBits(kNumRegBits); 1.678 + op.Base = 0; 1.679 + } 1.680 + else 1.681 + { 1.682 + if (inp.ReadBit() == 0) 1.683 + op.Data = inp.ReadBits(kNumRegBits); 1.684 + else 1.685 + op.Data = kNumRegs; 1.686 + op.Base = ReadEncodedUInt32(inp); 1.687 + } 1.688 + } 1.689 +} 1.690 + 1.691 +void CVm::ReadVmProgram(const Byte *code, UInt32 codeSize, CProgram *prg) 1.692 +{ 1.693 + CMemBitDecoder inp; 1.694 + inp.Init(code, codeSize); 1.695 + 1.696 + prg->StaticData.Clear(); 1.697 + if (inp.ReadBit()) 1.698 + { 1.699 + UInt32 dataSize = ReadEncodedUInt32(inp) + 1; 1.700 + for (UInt32 i = 0; inp.Avail() && i < dataSize; i++) 1.701 + prg->StaticData.Add((Byte)inp.ReadBits(8)); 1.702 + } 1.703 + while (inp.Avail()) 1.704 + { 1.705 + prg->Commands.Add(CCommand()); 1.706 + CCommand *cmd = &prg->Commands.Back(); 1.707 + if (inp.ReadBit() == 0) 1.708 + cmd->OpCode = (ECommand)inp.ReadBits(3); 1.709 + else 1.710 + cmd->OpCode = (ECommand)(8 + inp.ReadBits(5)); 1.711 + if (kCmdFlags[cmd->OpCode] & CF_BYTEMODE) 1.712 + cmd->ByteMode = (inp.ReadBit()) ? true : false; 1.713 + else 1.714 + cmd->ByteMode = 0; 1.715 + int opNum = (kCmdFlags[cmd->OpCode] & CF_OPMASK); 1.716 + if (opNum > 0) 1.717 + { 1.718 + DecodeArg(inp, cmd->Op1, cmd->ByteMode); 1.719 + if (opNum == 2) 1.720 + DecodeArg(inp, cmd->Op2, cmd->ByteMode); 1.721 + else 1.722 + { 1.723 + if (cmd->Op1.Type == OP_TYPE_INT && (kCmdFlags[cmd->OpCode] & (CF_JUMP | CF_PROC))) 1.724 + { 1.725 + int Distance = cmd->Op1.Data; 1.726 + if (Distance >= 256) 1.727 + Distance -= 256; 1.728 + else 1.729 + { 1.730 + if (Distance >= 136) 1.731 + Distance -= 264; 1.732 + else if (Distance >= 16) 1.733 + Distance -= 8; 1.734 + else if (Distance >= 8) 1.735 + Distance -= 16; 1.736 + Distance += prg->Commands.Size() - 1; 1.737 + } 1.738 + cmd->Op1.Data = Distance; 1.739 + } 1.740 + } 1.741 + } 1.742 + if (cmd->ByteMode) 1.743 + { 1.744 + switch (cmd->OpCode) 1.745 + { 1.746 + case CMD_MOV: cmd->OpCode = CMD_MOVB; break; 1.747 + case CMD_CMP: cmd->OpCode = CMD_CMPB; break; 1.748 + case CMD_ADD: cmd->OpCode = CMD_ADDB; break; 1.749 + case CMD_SUB: cmd->OpCode = CMD_SUBB; break; 1.750 + case CMD_INC: cmd->OpCode = CMD_INCB; break; 1.751 + case CMD_DEC: cmd->OpCode = CMD_DECB; break; 1.752 + case CMD_XOR: cmd->OpCode = CMD_XORB; break; 1.753 + case CMD_AND: cmd->OpCode = CMD_ANDB; break; 1.754 + case CMD_OR: cmd->OpCode = CMD_ORB; break; 1.755 + case CMD_TEST: cmd->OpCode = CMD_TESTB; break; 1.756 + case CMD_NEG: cmd->OpCode = CMD_NEGB; break; 1.757 + case CMD_SHL: cmd->OpCode = CMD_SHLB; break; 1.758 + case CMD_SHR: cmd->OpCode = CMD_SHRB; break; 1.759 + case CMD_SAR: cmd->OpCode = CMD_SARB; break; 1.760 + case CMD_MUL: cmd->OpCode = CMD_MULB; break; 1.761 + } 1.762 + } 1.763 + } 1.764 +} 1.765 + 1.766 +#ifdef RARVM_STANDARD_FILTERS 1.767 + 1.768 +enum EStandardFilter 1.769 +{ 1.770 + SF_E8, 1.771 + SF_E8E9, 1.772 + SF_ITANIUM, 1.773 + SF_RGB, 1.774 + SF_AUDIO, 1.775 + SF_DELTA, 1.776 + SF_UPCASE 1.777 +}; 1.778 + 1.779 +struct StandardFilterSignature 1.780 +{ 1.781 + UInt32 Length; 1.782 + UInt32 CRC; 1.783 + EStandardFilter Type; 1.784 +} 1.785 +kStdFilters[]= 1.786 +{ 1.787 + 53, 0xad576887, SF_E8, 1.788 + 57, 0x3cd7e57e, SF_E8E9, 1.789 + 120, 0x3769893f, SF_ITANIUM, 1.790 + 29, 0x0e06077d, SF_DELTA, 1.791 + 149, 0x1c2c5dc8, SF_RGB, 1.792 + 216, 0xbc85e701, SF_AUDIO, 1.793 + 40, 0x46b9c560, SF_UPCASE 1.794 +}; 1.795 + 1.796 +static int FindStandardFilter(const Byte *code, UInt32 codeSize) 1.797 +{ 1.798 + UInt32 crc = CrcCalc(code, codeSize); 1.799 + for (int i = 0; i < sizeof(kStdFilters) / sizeof(kStdFilters[0]); i++) 1.800 + { 1.801 + StandardFilterSignature &sfs = kStdFilters[i]; 1.802 + if (sfs.CRC == crc && sfs.Length == codeSize) 1.803 + return i; 1.804 + } 1.805 + return -1; 1.806 +} 1.807 + 1.808 +#endif 1.809 + 1.810 +void CVm::PrepareProgram(const Byte *code, UInt32 codeSize, CProgram *prg) 1.811 +{ 1.812 + Byte xorSum = 0; 1.813 + for (UInt32 i = 1; i < codeSize; i++) 1.814 + xorSum ^= code[i]; 1.815 + 1.816 + prg->Commands.Clear(); 1.817 + #ifdef RARVM_STANDARD_FILTERS 1.818 + prg->StandardFilterIndex = -1; 1.819 + #endif 1.820 + 1.821 + if (xorSum == code[0] && codeSize > 0) 1.822 + { 1.823 + #ifdef RARVM_STANDARD_FILTERS 1.824 + prg->StandardFilterIndex = FindStandardFilter(code, codeSize); 1.825 + if (prg->StandardFilterIndex >= 0) 1.826 + return; 1.827 + #endif 1.828 + // 1 byte for checksum 1.829 + ReadVmProgram(code + 1, codeSize - 1, prg); 1.830 + } 1.831 + prg->Commands.Add(CCommand()); 1.832 + CCommand *cmd = &prg->Commands.Back(); 1.833 + cmd->OpCode = CMD_RET; 1.834 +} 1.835 + 1.836 +void CVm::SetMemory(UInt32 pos, const Byte *data, UInt32 dataSize) 1.837 +{ 1.838 + if (pos < kSpaceSize && data != Mem + pos) 1.839 + memmove(Mem + pos, data, MyMin(dataSize, kSpaceSize - pos)); 1.840 +} 1.841 + 1.842 +#ifdef RARVM_STANDARD_FILTERS 1.843 + 1.844 +static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9) 1.845 +{ 1.846 + if (dataSize <= 4) 1.847 + return; 1.848 + dataSize -= 4; 1.849 + const UInt32 kFileSize = 0x1000000; 1.850 + Byte cmpByte2 = (e9 ? 0xE9 : 0xE8); 1.851 + for (UInt32 curPos = 0; curPos < dataSize;) 1.852 + { 1.853 + Byte curByte = *(data++); 1.854 + curPos++; 1.855 + if (curByte == 0xE8 || curByte == cmpByte2) 1.856 + { 1.857 + UInt32 offset = curPos + fileOffset; 1.858 + UInt32 addr = (Int32)GetValue32(data); 1.859 + if (addr < kFileSize) 1.860 + SetValue32(data, addr - offset); 1.861 + else if ((Int32)addr < 0 && (Int32)(addr + offset) >= 0) 1.862 + SetValue32(data, addr + kFileSize); 1.863 + data += 4; 1.864 + curPos += 4; 1.865 + } 1.866 + } 1.867 +} 1.868 + 1.869 +static inline UInt32 ItaniumGetOpType(const Byte *data, int bitPos) 1.870 +{ 1.871 + return (data[(unsigned int)bitPos >> 3] >> (bitPos & 7)) & 0xF; 1.872 +} 1.873 + 1.874 + 1.875 +static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset) 1.876 +{ 1.877 + UInt32 curPos = 0; 1.878 + fileOffset >>= 4; 1.879 + while (curPos < dataSize - 21) 1.880 + { 1.881 + int b = (data[0] & 0x1F) - 0x10; 1.882 + if (b >= 0) 1.883 + { 1.884 + static Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0}; 1.885 + Byte cmdMask = kCmdMasks[b]; 1.886 + if (cmdMask != 0) 1.887 + for (int i = 0; i < 3; i++) 1.888 + if (cmdMask & (1 << i)) 1.889 + { 1.890 + int startPos = i * 41 + 18; 1.891 + if (ItaniumGetOpType(data, startPos + 24) == 5) 1.892 + { 1.893 + const UInt32 kMask = 0xFFFFF; 1.894 + Byte *p = data + ((unsigned int)startPos >> 3); 1.895 + UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16); 1.896 + int inBit = (startPos & 7); 1.897 + UInt32 offset = (bitField >> inBit) & kMask; 1.898 + UInt32 andMask = ~(kMask << inBit); 1.899 + bitField = ((offset - fileOffset) & kMask) << inBit; 1.900 + for (int j = 0; j < 3; j++) 1.901 + { 1.902 + p[j] &= andMask; 1.903 + p[j] |= bitField; 1.904 + andMask >>= 8; 1.905 + bitField >>= 8; 1.906 + } 1.907 + } 1.908 + } 1.909 + } 1.910 + data += 16; 1.911 + curPos += 16; 1.912 + fileOffset++; 1.913 + } 1.914 +} 1.915 + 1.916 +static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels) 1.917 +{ 1.918 + UInt32 srcPos = 0; 1.919 + UInt32 border = dataSize * 2; 1.920 + for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++) 1.921 + { 1.922 + Byte prevByte = 0; 1.923 + for (UInt32 destPos = dataSize + curChannel; destPos < border; destPos += numChannels) 1.924 + data[destPos] = (prevByte = prevByte - data[srcPos++]); 1.925 + } 1.926 +} 1.927 + 1.928 +static void RgbDecode(Byte *srcData, UInt32 dataSize, UInt32 width, UInt32 posR) 1.929 +{ 1.930 + Byte *destData = srcData + dataSize; 1.931 + const UInt32 numChannels = 3; 1.932 + for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++) 1.933 + { 1.934 + Byte prevByte = 0; 1.935 + 1.936 + for (UInt32 i = curChannel; i < dataSize; i+= numChannels) 1.937 + { 1.938 + unsigned int predicted; 1.939 + if (i < width) 1.940 + predicted = prevByte; 1.941 + else 1.942 + { 1.943 + unsigned int upperLeftByte = destData[i - width]; 1.944 + unsigned int upperByte = destData[i - width + 3]; 1.945 + predicted = prevByte + upperByte - upperLeftByte; 1.946 + int pa = abs((int)(predicted - prevByte)); 1.947 + int pb = abs((int)(predicted - upperByte)); 1.948 + int pc = abs((int)(predicted - upperLeftByte)); 1.949 + if (pa <= pb && pa <= pc) 1.950 + predicted = prevByte; 1.951 + else 1.952 + if (pb <= pc) 1.953 + predicted = upperByte; 1.954 + else 1.955 + predicted = upperLeftByte; 1.956 + } 1.957 + destData[i] = prevByte = (Byte)(predicted - *(srcData++)); 1.958 + } 1.959 + } 1.960 + if (dataSize < 3) 1.961 + return; 1.962 + for (UInt32 i = posR, border = dataSize - 2; i < border; i += 3) 1.963 + { 1.964 + Byte g = destData[i + 1]; 1.965 + destData[i] = destData[i] + g; 1.966 + destData[i + 2] = destData[i + 2] + g; 1.967 + } 1.968 +} 1.969 + 1.970 +static void AudioDecode(Byte *srcData, UInt32 dataSize, UInt32 numChannels) 1.971 +{ 1.972 + Byte *destData = srcData + dataSize; 1.973 + for (UInt32 curChannel = 0; curChannel < numChannels; curChannel++) 1.974 + { 1.975 + UInt32 prevByte = 0, prevDelta = 0, dif[7]; 1.976 + Int32 D1 = 0, D2 = 0, D3; 1.977 + Int32 K1 = 0, K2 = 0, K3 = 0; 1.978 + memset(dif, 0, sizeof(dif)); 1.979 + 1.980 + for (UInt32 i = curChannel, byteCount = 0; i < dataSize; i += numChannels, byteCount++) 1.981 + { 1.982 + D3 = D2; 1.983 + D2 = prevDelta - D1; 1.984 + D1 = prevDelta; 1.985 + 1.986 + UInt32 predicted = 8 * prevByte + K1 * D1 + K2 * D2 + K3 * D3; 1.987 + predicted = (predicted >> 3) & 0xFF; 1.988 + 1.989 + UInt32 curByte = *(srcData++); 1.990 + 1.991 + predicted -= curByte; 1.992 + destData[i] = (Byte)predicted; 1.993 + prevDelta = (UInt32)(Int32)(signed char)(predicted - prevByte); 1.994 + prevByte = predicted; 1.995 + 1.996 + Int32 D = ((Int32)(signed char)curByte) << 3; 1.997 + 1.998 + dif[0] += abs(D); 1.999 + dif[1] += abs(D - D1); 1.1000 + dif[2] += abs(D + D1); 1.1001 + dif[3] += abs(D - D2); 1.1002 + dif[4] += abs(D + D2); 1.1003 + dif[5] += abs(D - D3); 1.1004 + dif[6] += abs(D + D3); 1.1005 + 1.1006 + if ((byteCount & 0x1F) == 0) 1.1007 + { 1.1008 + UInt32 minDif = dif[0], numMinDif = 0; 1.1009 + dif[0] = 0; 1.1010 + for (int j = 1; j < sizeof(dif) / sizeof(dif[0]); j++) 1.1011 + { 1.1012 + if (dif[j] < minDif) 1.1013 + { 1.1014 + minDif = dif[j]; 1.1015 + numMinDif = j; 1.1016 + } 1.1017 + dif[j] = 0; 1.1018 + } 1.1019 + switch (numMinDif) 1.1020 + { 1.1021 + case 1: if (K1 >= -16) K1--; break; 1.1022 + case 2: if (K1 < 16) K1++; break; 1.1023 + case 3: if (K2 >= -16) K2--; break; 1.1024 + case 4: if (K2 < 16) K2++; break; 1.1025 + case 5: if (K3 >= -16) K3--; break; 1.1026 + case 6: if (K3 < 16) K3++; break; 1.1027 + } 1.1028 + } 1.1029 + } 1.1030 + } 1.1031 +} 1.1032 + 1.1033 +static UInt32 UpCaseDecode(Byte *data, UInt32 dataSize) 1.1034 +{ 1.1035 + UInt32 srcPos = 0, destPos = dataSize; 1.1036 + while (srcPos < dataSize) 1.1037 + { 1.1038 + Byte curByte = data[srcPos++]; 1.1039 + if (curByte == 2 && (curByte = data[srcPos++]) != 2) 1.1040 + curByte -= 32; 1.1041 + data[destPos++] = curByte; 1.1042 + } 1.1043 + return destPos - dataSize; 1.1044 +} 1.1045 + 1.1046 +void CVm::ExecuteStandardFilter(int filterIndex) 1.1047 +{ 1.1048 + UInt32 dataSize = R[4]; 1.1049 + if (dataSize >= kGlobalOffset) 1.1050 + return; 1.1051 + EStandardFilter filterType = kStdFilters[filterIndex].Type; 1.1052 + 1.1053 + switch (filterType) 1.1054 + { 1.1055 + case SF_E8: 1.1056 + case SF_E8E9: 1.1057 + E8E9Decode(Mem, dataSize, R[6], (filterType == SF_E8E9)); 1.1058 + break; 1.1059 + case SF_ITANIUM: 1.1060 + ItaniumDecode(Mem, dataSize, R[6]); 1.1061 + break; 1.1062 + case SF_DELTA: 1.1063 + if (dataSize >= kGlobalOffset / 2) 1.1064 + break; 1.1065 + SetBlockPos(dataSize); 1.1066 + DeltaDecode(Mem, dataSize, R[0]); 1.1067 + break; 1.1068 + case SF_RGB: 1.1069 + if (dataSize >= kGlobalOffset / 2) 1.1070 + break; 1.1071 + { 1.1072 + UInt32 width = R[0]; 1.1073 + if (width <= 3) 1.1074 + break; 1.1075 + SetBlockPos(dataSize); 1.1076 + RgbDecode(Mem, dataSize, width, R[1]); 1.1077 + } 1.1078 + break; 1.1079 + case SF_AUDIO: 1.1080 + if (dataSize >= kGlobalOffset / 2) 1.1081 + break; 1.1082 + SetBlockPos(dataSize); 1.1083 + AudioDecode(Mem, dataSize, R[0]); 1.1084 + break; 1.1085 + case SF_UPCASE: 1.1086 + if (dataSize >= kGlobalOffset / 2) 1.1087 + break; 1.1088 + UInt32 destSize = UpCaseDecode(Mem, dataSize); 1.1089 + SetBlockSize(destSize); 1.1090 + SetBlockPos(dataSize); 1.1091 + break; 1.1092 + } 1.1093 +} 1.1094 + 1.1095 +#endif 1.1096 + 1.1097 +}}}