From 124f869faae3a0f75a3825e6a8e195c17f3c626a Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Thu, 16 Oct 2014 23:34:20 +0400 Subject: initial for idea --- .../java/com/github/junrar/unpack/vm/RarVM.java | 1221 ++++++++++++++++++++ 1 file changed, 1221 insertions(+) create mode 100644 org.fox.ttcomics/src/main/java/com/github/junrar/unpack/vm/RarVM.java (limited to 'org.fox.ttcomics/src/main/java/com/github/junrar/unpack/vm/RarVM.java') diff --git a/org.fox.ttcomics/src/main/java/com/github/junrar/unpack/vm/RarVM.java b/org.fox.ttcomics/src/main/java/com/github/junrar/unpack/vm/RarVM.java new file mode 100644 index 0000000..e6e6a01 --- /dev/null +++ b/org.fox.ttcomics/src/main/java/com/github/junrar/unpack/vm/RarVM.java @@ -0,0 +1,1221 @@ +/* + * Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved. + * Original author: Edmund Wagner + * Creation date: 31.05.2007 + * + * Source: $HeadURL$ + * Last changed: $LastChangedDate$ + * + * the unrar licence applies to all junrar source and binary distributions + * you are not allowed to use this source to re-create the RAR compression algorithm + * + * Here some html entities which can be used for escaping javadoc tags: + * "&": "&" or "&" + * "<": "<" or "<" + * ">": ">" or ">" + * "@": "@" + */ +package com.github.junrar.unpack.vm; + +import java.util.List; +import java.util.Vector; + +import com.github.junrar.crc.RarCRC; +import com.github.junrar.io.Raw; + + +/** + * DOCUMENT ME + * + * @author $LastChangedBy$ + * @version $LastChangedRevision$ + */ +public class RarVM extends BitInput { + + public static final int VM_MEMSIZE = 0x40000; + + public static final int VM_MEMMASK = (VM_MEMSIZE - 1); + + public static final int VM_GLOBALMEMADDR = 0x3C000; + + public static final int VM_GLOBALMEMSIZE = 0x2000; + + public static final int VM_FIXEDGLOBALSIZE = 64; + + private static final int regCount = 8; + + private static final long UINT_MASK = 0xffffFFFF;//((long)2*(long)Integer.MAX_VALUE); + + private byte[] mem; + + private int[] R = new int[regCount]; + + private int flags; + + private int maxOpCount = 25000000; + + private int codeSize; + + private int IP; + + public RarVM() { + mem = null; + } + + public void init() { + if (mem == null) { + mem = new byte[VM_MEMSIZE + 4]; + } + } + + private boolean isVMMem(byte[] mem) { + return this.mem == mem; + } + + private int getValue(boolean byteMode, byte[] mem, int offset) { + if (byteMode) { + if (isVMMem(mem)) { + return (mem[offset]); + } else { + return (mem[offset] & 0xff); + } + } else { + if (isVMMem(mem)) { + //little + return Raw.readIntLittleEndian(mem, offset); + } else + //big endian + return Raw.readIntBigEndian(mem, offset); + } + } + + private void setValue(boolean byteMode, byte[] mem, int offset, int value) { + if (byteMode) { + if (isVMMem(mem)) { + mem[offset] = (byte) value; + } else { + mem[offset] = (byte) ((mem[offset] & 0x00) | (byte) (value & 0xff)); + } + } else { + if (isVMMem(mem)) { + Raw.writeIntLittleEndian(mem, offset, value); +// mem[offset + 0] = (byte) value; +// mem[offset + 1] = (byte) (value >>> 8); +// mem[offset + 2] = (byte) (value >>> 16); +// mem[offset + 3] = (byte) (value >>> 24); + } else { + Raw.writeIntBigEndian(mem, offset, value); +// mem[offset + 3] = (byte) value; +// mem[offset + 2] = (byte) (value >>> 8); +// mem[offset + 1] = (byte) (value >>> 16); +// mem[offset + 0] = (byte) (value >>> 24); + } + + } + // #define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint + // *)Addr,Value) + } + + public void setLowEndianValue(byte[] mem, int offset, int value) { + Raw.writeIntLittleEndian(mem, offset, value); +// mem[offset + 0] = (byte) (value&0xff); +// mem[offset + 1] = (byte) ((value >>> 8)&0xff); +// mem[offset + 2] = (byte) ((value >>> 16)&0xff); +// mem[offset + 3] = (byte) ((value >>> 24)&0xff); + } + public void setLowEndianValue(Vector mem, int offset, int value) { + mem.set(offset + 0, Byte.valueOf((byte) (value&0xff))) ; + mem.set(offset + 1, Byte.valueOf((byte) ((value >>> 8)&0xff))); + mem.set(offset + 2, Byte.valueOf((byte) ((value >>> 16)&0xff) )); + mem.set(offset + 3, Byte.valueOf((byte) ((value >>> 24)&0xff))) ; + } + private int getOperand(VMPreparedOperand cmdOp) { + int ret = 0; + if (cmdOp.getType() == VMOpType.VM_OPREGMEM) { + int pos = (cmdOp.getOffset() + cmdOp.getBase()) & VM_MEMMASK; + ret = Raw.readIntLittleEndian(mem, pos); + } else { + int pos = cmdOp.getOffset(); + ret = Raw.readIntLittleEndian(mem, pos); + } + return ret; + } + + public void execute(VMPreparedProgram prg) { + for (int i = 0; i < prg.getInitR().length; i++) // memcpy(R,Prg->InitR,sizeof(Prg->InitR)); + { + R[i] = prg.getInitR()[i]; + } + + long globalSize = Math + .min(prg.getGlobalData().size(), VM_GLOBALMEMSIZE) & 0xffFFffFF; + if (globalSize != 0) { + for (int i = 0; i < globalSize; i++) // memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize); + { + mem[VM_GLOBALMEMADDR + i] = prg.getGlobalData().get(i); + } + + } + long staticSize = Math.min(prg.getStaticData().size(), VM_GLOBALMEMSIZE + - globalSize) & 0xffFFffFF; + if (staticSize != 0) { + for (int i = 0; i < staticSize; i++) // memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize); + { + mem[VM_GLOBALMEMADDR + (int) globalSize + i] = prg + .getStaticData().get(i); + } + + } + R[7] = VM_MEMSIZE; + flags = 0; + + List preparedCode = prg.getAltCmd().size() != 0 ? prg + .getAltCmd() + : prg.getCmd(); + + if (!ExecuteCode(preparedCode, prg.getCmdCount())) { + preparedCode.get(0).setOpCode(VMCommands.VM_RET); + } + int newBlockPos = getValue(false, mem, VM_GLOBALMEMADDR + 0x20) + & VM_MEMMASK; + int newBlockSize = getValue(false, mem, VM_GLOBALMEMADDR + 0x1c) + & VM_MEMMASK; + if ((newBlockPos + newBlockSize) >= VM_MEMSIZE) { + newBlockPos = 0; + newBlockSize = 0; + } + + prg.setFilteredDataOffset(newBlockPos); + prg.setFilteredDataSize(newBlockSize); + + prg.getGlobalData().clear(); + + int dataSize = Math.min(getValue(false, mem, VM_GLOBALMEMADDR + 0x30), + VM_GLOBALMEMSIZE - VM_FIXEDGLOBALSIZE); + if (dataSize != 0) { + prg.getGlobalData().setSize(dataSize + VM_FIXEDGLOBALSIZE); + // ->GlobalData.Add(dataSize+VM_FIXEDGLOBALSIZE); + + for (int i = 0; i < dataSize + VM_FIXEDGLOBALSIZE; i++) // memcpy(&Prg->GlobalData[0],&Mem[VM_GLOBALMEMADDR],DataSize+VM_FIXEDGLOBALSIZE); + { + prg.getGlobalData().set(i, mem[VM_GLOBALMEMADDR + i]); + } + } + } + + public byte[] getMem() + { + return mem; + } + + private boolean setIP(int ip) { + if ((ip) >= codeSize) { + return (true); + } + + if (--maxOpCount <= 0) { + return (false); + } + + IP = ip; + return true; + } + + private boolean ExecuteCode(List preparedCode, + int cmdCount) { + + maxOpCount = 25000000; + this.codeSize = cmdCount; + this.IP = 0; + + while (true) { + VMPreparedCommand cmd = preparedCode.get(IP); + int op1 = getOperand(cmd.getOp1()); + int op2 = getOperand(cmd.getOp2()); + switch (cmd.getOpCode()) { + case VM_MOV: + setValue(cmd.isByteMode(), mem, op1, getValue(cmd.isByteMode(), + mem, op2)); // SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2)); + break; + case VM_MOVB: + setValue(true, mem, op1, getValue(true, mem, op2)); + break; + case VM_MOVD: + setValue(false, mem, op1, getValue(false, mem, op2)); + break; + + case VM_CMP: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int result = value1 - getValue(cmd.isByteMode(), mem, op2); + + if (result == 0) { + flags = VMFlags.VM_FZ.getFlag(); + } else { + flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS + .getFlag()); + } + } + break; + + case VM_CMPB: { + int value1 = getValue(true, mem, op1); + int result = value1 - getValue(true, mem, op2); + if (result == 0) { + flags = VMFlags.VM_FZ.getFlag(); + } else { + flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS + .getFlag()); + } + } + break; + case VM_CMPD: { + int value1 = getValue(false, mem, op1); + int result = value1 - getValue(false, mem, op2); + if (result == 0) { + flags = VMFlags.VM_FZ.getFlag(); + } else { + flags = (result > value1) ? 1 : 0 | (result & VMFlags.VM_FS + .getFlag()); + } + } + break; + + case VM_ADD: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int result = (int) ((((long) value1 + (long) getValue(cmd + .isByteMode(), mem, op2))) & 0xffffffff); + if (cmd.isByteMode()) { + result &= 0xff; + flags = (result < value1) ? 1 + : 0 | (result == 0 ? VMFlags.VM_FZ.getFlag() + : ((result & 0x80) != 0) ? VMFlags.VM_FS + .getFlag() : 0); + // Flags=(Result value1) ? 1 : 0 | (result & VMFlags.VM_FS + .getFlag()); + setValue(cmd.isByteMode(), mem, op1, result);// (Cmd->ByteMode,Op1,Result); + } + break; + + case VM_SUBB: + setValue(true, mem, op1, + (int) ((long) getValue(true, mem, op1) & 0xFFffFFff + - (long) getValue(true, mem, op2) & 0xFFffFFff)); + break; + case VM_SUBD: + setValue( + false, + mem, + op1, + (int) ((long) getValue(false, mem, op1) & 0xFFffFFff + - (long) getValue(false, mem, op2) & 0xFFffFFff)); + break; + + case VM_JZ: + if ((flags & VMFlags.VM_FZ.getFlag()) != 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JNZ: + if ((flags & VMFlags.VM_FZ.getFlag()) == 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_INC: { + int result = (int) ((long) getValue(cmd.isByteMode(), mem, op1) & 0xFFffFFff + 1); + if (cmd.isByteMode()) { + result &= 0xff; + } + + setValue(cmd.isByteMode(), mem, op1, result); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + } + break; + + case VM_INCB: + setValue( + true, + mem, + op1, + (int) ((long) getValue(true, mem, op1) & 0xFFffFFff + 1)); + break; + case VM_INCD: + setValue(false, mem, op1, (int) ((long) getValue(false, mem, + op1) & 0xFFffFFff + 1)); + break; + + case VM_DEC: { + int result = (int) ((long) getValue(cmd.isByteMode(), mem, op1) & 0xFFffFFff - 1); + setValue(cmd.isByteMode(), mem, op1, result); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + } + break; + + case VM_DECB: + setValue( + true, + mem, + op1, + (int) ((long) getValue(true, mem, op1) & 0xFFffFFff - 1)); + break; + case VM_DECD: + setValue(false, mem, op1, (int) ((long) getValue(false, mem, + op1) & 0xFFffFFff - 1)); + break; + + case VM_JMP: + setIP(getValue(false, mem, op1)); + continue; + case VM_XOR: { + int result = getValue(cmd.isByteMode(), mem, op1) + ^ getValue(cmd.isByteMode(), mem, op2); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_AND: { + int result = getValue(cmd.isByteMode(), mem, op1) + & getValue(cmd.isByteMode(), mem, op2); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_OR: { + int result = getValue(cmd.isByteMode(), mem, op1) + | getValue(cmd.isByteMode(), mem, op2); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_TEST: { + int result = getValue(cmd.isByteMode(), mem, op1) + & getValue(cmd.isByteMode(), mem, op2); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : result + & VMFlags.VM_FS.getFlag(); + } + break; + case VM_JS: + if ((flags & VMFlags.VM_FS.getFlag()) != 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JNS: + if ((flags & VMFlags.VM_FS.getFlag()) == 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JB: + if ((flags & VMFlags.VM_FC.getFlag()) != 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JBE: + if ((flags & (VMFlags.VM_FC.getFlag() | VMFlags.VM_FZ.getFlag())) != 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JA: + if ((flags & (VMFlags.VM_FC.getFlag() | VMFlags.VM_FZ.getFlag())) == 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_JAE: + if ((flags & VMFlags.VM_FC.getFlag()) == 0) { + setIP(getValue(false, mem, op1)); + continue; + } + break; + case VM_PUSH: + R[7] -= 4; + setValue(false, mem, R[7] & VM_MEMMASK, getValue(false, mem, + op1)); + break; + case VM_POP: + setValue(false, mem, op1, getValue(false, mem, R[7] + & VM_MEMMASK)); + R[7] += 4; + break; + case VM_CALL: + R[7] -= 4; + setValue(false, mem, R[7] & VM_MEMMASK, IP + 1); + setIP(getValue(false, mem, op1)); + continue; + case VM_NOT: + setValue(cmd.isByteMode(), mem, op1, ~getValue( + cmd.isByteMode(), mem, op1)); + break; + case VM_SHL: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int value2 = getValue(cmd.isByteMode(), mem, op2); + int result = value1 << value2; + flags = (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())) + | (((value1 << (value2 - 1)) & 0x80000000) != 0 ? VMFlags.VM_FC + .getFlag() + : 0); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_SHR: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int value2 = getValue(cmd.isByteMode(), mem, op2); + int result = value1 >>> value2; + flags = (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())) + | ((value1 >>> (value2 - 1)) & VMFlags.VM_FC.getFlag()); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_SAR: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int value2 = getValue(cmd.isByteMode(), mem, op2); + int result = ((int) value1) >> value2; + flags = (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())) + | ((value1 >> (value2 - 1)) & VMFlags.VM_FC.getFlag()); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_NEG: { + int result = -getValue(cmd.isByteMode(), mem, op1); + flags = result == 0 ? VMFlags.VM_FZ.getFlag() : VMFlags.VM_FC + .getFlag() + | (result & VMFlags.VM_FS.getFlag()); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + + case VM_NEGB: + setValue(true, mem, op1, -getValue(true, mem, op1)); + break; + case VM_NEGD: + setValue(false, mem, op1, -getValue(false, mem, op1)); + break; + case VM_PUSHA: { + for (int i = 0, SP = R[7] - 4; i < regCount; i++, SP -= 4) { + setValue(false, mem, SP & VM_MEMMASK, R[i]); + } + R[7] -= regCount * 4; + } + break; + case VM_POPA: { + for (int i = 0, SP = R[7]; i < regCount; i++, SP += 4) + R[7 - i] = getValue(false, mem, SP & VM_MEMMASK); + } + break; + case VM_PUSHF: + R[7] -= 4; + setValue(false, mem, R[7] & VM_MEMMASK, flags); + break; + case VM_POPF: + flags = getValue(false, mem, R[7] & VM_MEMMASK); + R[7] += 4; + break; + case VM_MOVZX: + setValue(false, mem, op1, getValue(true, mem, op2)); + break; + case VM_MOVSX: + setValue(false, mem, op1, (byte) getValue(true, mem, op2)); + break; + case VM_XCHG: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + setValue(cmd.isByteMode(), mem, op1, getValue(cmd.isByteMode(), + mem, op2)); + setValue(cmd.isByteMode(), mem, op2, value1); + } + break; + case VM_MUL: { + int result = (int) (((long) getValue(cmd.isByteMode(), mem, op1) + & 0xFFffFFff + * (long) getValue(cmd.isByteMode(), mem, op2) & 0xFFffFFff) & 0xFFffFFff); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_DIV: { + int divider = getValue(cmd.isByteMode(), mem, op2); + if (divider != 0) { + int result = getValue(cmd.isByteMode(), mem, op1) / divider; + setValue(cmd.isByteMode(), mem, op1, result); + } + } + break; + case VM_ADC: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int FC = (flags & VMFlags.VM_FC.getFlag()); + int result = (int) ((long) value1 & 0xFFffFFff + + (long) getValue(cmd.isByteMode(), mem, op2) + & 0xFFffFFff + (long) FC & 0xFFffFFff); + if (cmd.isByteMode()) { + result &= 0xff; + } + + flags = (result < value1 || result == value1 && FC != 0) ? 1 + : 0 | (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + case VM_SBB: { + int value1 = getValue(cmd.isByteMode(), mem, op1); + int FC = (flags & VMFlags.VM_FC.getFlag()); + int result = (int) ((long) value1 & 0xFFffFFff + - (long) getValue(cmd.isByteMode(), mem, op2) + & 0xFFffFFff - (long) FC & 0xFFffFFff); + if (cmd.isByteMode()) { + result &= 0xff; + } + flags = (result > value1 || result == value1 && FC != 0) ? 1 + : 0 | (result == 0 ? VMFlags.VM_FZ.getFlag() + : (result & VMFlags.VM_FS.getFlag())); + setValue(cmd.isByteMode(), mem, op1, result); + } + break; + + case VM_RET: + if (R[7] >= VM_MEMSIZE) { + return (true); + } + setIP(getValue(false, mem, R[7] & VM_MEMMASK)); + R[7] += 4; + continue; + + case VM_STANDARD: + ExecuteStandardFilter(VMStandardFilters.findFilter(cmd.getOp1() + .getData())); + break; + case VM_PRINT: + break; + } + IP++; + --maxOpCount; + } + } + + public void prepare(byte[] code, int codeSize, VMPreparedProgram prg) { + InitBitInput(); + int cpLength = Math.min(MAX_SIZE, codeSize); + for (int i = 0; i < cpLength; i++) // memcpy(inBuf,Code,Min(CodeSize,BitInput::MAX_SIZE)); + { + inBuf[i] |= code[i]; + } + + byte xorSum = 0; + for (int i = 1; i < codeSize; i++) { + xorSum ^= code[i]; + } + + faddbits(8); + + prg.setCmdCount(0); + if (xorSum == code[0]) { + VMStandardFilters filterType = IsStandardFilter(code, codeSize); + if (filterType != VMStandardFilters.VMSF_NONE) { + + VMPreparedCommand curCmd = new VMPreparedCommand(); + curCmd.setOpCode(VMCommands.VM_STANDARD); + curCmd.getOp1().setData(filterType.getFilter()); + curCmd.getOp1().setType(VMOpType.VM_OPNONE); + curCmd.getOp2().setType(VMOpType.VM_OPNONE); + codeSize = 0; + prg.getCmd().add(curCmd); + prg.setCmdCount(prg.getCmdCount()+1); + // TODO + // curCmd->Op1.Data=FilterType; + // >>>>>> CurCmd->Op1.Addr=&CurCmd->Op1.Data; <<<<<<<<<< not set + // do i need to ? + // >>>>>> CurCmd->Op2.Addr=&CurCmd->Op2.Data; <<<<<<<<<< " + // CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; + // CodeSize=0; + } + int dataFlag = fgetbits(); + faddbits(1); + + // Read static data contained in DB operators. This data cannot be + // changed, + // it is a part of VM code, not a filter parameter. + + if ((dataFlag & 0x8000) != 0) { + long dataSize = (long) ((long) ReadData(this) & 0xffFFffFF + 1); + for (int i = 0; inAddr < codeSize && i < dataSize; i++) { + prg.getStaticData().add( + Byte.valueOf((byte) (fgetbits() >> 8))); + faddbits(8); + } + } + + while (inAddr < codeSize) { + VMPreparedCommand curCmd = new VMPreparedCommand(); + int data = fgetbits(); + if ((data & 0x8000) == 0) { + curCmd.setOpCode(VMCommands.findVMCommand((data >> 12))); + faddbits(4); + } else { + curCmd.setOpCode(VMCommands + .findVMCommand((data >> 10) - 24)); + faddbits(6); + } + if ((VMCmdFlags.VM_CmdFlags[curCmd.getOpCode().getVMCommand()] & VMCmdFlags.VMCF_BYTEMODE) != 0) { + curCmd.setByteMode((fgetbits() >> 15) == 1 ? true : false); + faddbits(1); + } else { + curCmd.setByteMode(false); + } + curCmd.getOp1().setType(VMOpType.VM_OPNONE); + curCmd.getOp2().setType(VMOpType.VM_OPNONE); + + int opNum = (VMCmdFlags.VM_CmdFlags[curCmd.getOpCode() + .getVMCommand()] & VMCmdFlags.VMCF_OPMASK); + // TODO >>> CurCmd->Op1.Addr=CurCmd->Op2.Addr=NULL; << 0) { + decodeArg(curCmd.getOp1(), curCmd.isByteMode()); + if (opNum == 2) + decodeArg(curCmd.getOp2(), curCmd.isByteMode()); + else { + if (curCmd.getOp1().getType() == VMOpType.VM_OPINT + && (VMCmdFlags.VM_CmdFlags[curCmd.getOpCode() + .getVMCommand()] & (VMCmdFlags.VMCF_JUMP | VMCmdFlags.VMCF_PROC)) != 0) { + int distance = curCmd.getOp1().getData(); + 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.getCmdCount(); + } + curCmd.getOp1().setData(distance); + } + } + } + prg.setCmdCount(prg.getCmdCount() + 1); + prg.getCmd().add(curCmd); + } + } + VMPreparedCommand curCmd = new VMPreparedCommand(); + curCmd.setOpCode(VMCommands.VM_RET); + // TODO CurCmd->Op1.Addr=&CurCmd->Op1.Data; + // CurCmd->Op2.Addr=&CurCmd->Op2.Data; + curCmd.getOp1().setType(VMOpType.VM_OPNONE); + curCmd.getOp2().setType(VMOpType.VM_OPNONE); + + // for (int i=0;iCmd[I]; + // if (Cmd->Op1.Addr==NULL) + // Cmd->Op1.Addr=&Cmd->Op1.Data; + // if (Cmd->Op2.Addr==NULL) + // Cmd->Op2.Addr=&Cmd->Op2.Data; + // } + + prg.getCmd().add(curCmd); + prg.setCmdCount(prg.getCmdCount()+1); + // #ifdef VM_OPTIMIZE + if (codeSize != 0) { + optimize(prg); + } + } + + private void decodeArg(VMPreparedOperand op, boolean byteMode) { + int data = fgetbits(); + if ((data & 0x8000) != 0) { + op.setType(VMOpType.VM_OPREG); + op.setData((data >> 12) & 7); + op.setOffset(op.getData()); + faddbits(4); + } else { + if ((data & 0xc000) == 0) { + op.setType(VMOpType.VM_OPINT); + if (byteMode) { + op.setData((data >> 6) & 0xff); + faddbits(10); + } else { + faddbits(2); + op.setData(ReadData(this)); + } + } else { + op.setType(VMOpType.VM_OPREGMEM); + if ((data & 0x2000) == 0) { + op.setData((data >> 10) & 7); + op.setOffset(op.getData()); + op.setBase(0); + faddbits(6); + } else { + if ((data & 0x1000) == 0) { + op.setData((data >> 9) & 7); + op.setOffset(op.getData()); + faddbits(7); + } else { + op.setData(0); + faddbits(4); + } + op.setBase(ReadData(this)); + } + } + } + + } + + private void optimize(VMPreparedProgram prg) { + List commands = prg.getCmd(); + + for (VMPreparedCommand cmd : commands) { + switch (cmd.getOpCode()) { + case VM_MOV: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_MOVB + : VMCommands.VM_MOVD); + continue; + case VM_CMP: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_CMPB + : VMCommands.VM_CMPD); + continue; + } + if ((VMCmdFlags.VM_CmdFlags[cmd.getOpCode().getVMCommand()] & VMCmdFlags.VMCF_CHFLAGS) == 0) { + continue; + } + boolean flagsRequired = false; + + for (int i = commands.indexOf(cmd) + 1; i < commands.size(); i++) { + int flags = VMCmdFlags.VM_CmdFlags[commands.get(i).getOpCode() + .getVMCommand()]; + if ((flags & (VMCmdFlags.VMCF_JUMP | VMCmdFlags.VMCF_PROC | VMCmdFlags.VMCF_USEFLAGS)) != 0) { + flagsRequired = true; + break; + } + if ((flags & VMCmdFlags.VMCF_CHFLAGS) != 0) { + break; + } + } + if (flagsRequired) { + continue; + } + switch (cmd.getOpCode()) { + case VM_ADD: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_ADDB + : VMCommands.VM_ADDD); + continue; + case VM_SUB: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_SUBB + : VMCommands.VM_SUBD); + continue; + case VM_INC: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_INCB + : VMCommands.VM_INCD); + continue; + case VM_DEC: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_DECB + : VMCommands.VM_DECD); + continue; + case VM_NEG: + cmd.setOpCode(cmd.isByteMode() ? VMCommands.VM_NEGB + : VMCommands.VM_NEGD); + continue; + } + } + + } + + public static int ReadData(BitInput rarVM) { + int data = rarVM.fgetbits(); + switch (data & 0xc000) { + case 0: + rarVM.faddbits(6); + return ((data >> 10) & 0xf); + case 0x4000: + if ((data & 0x3c00) == 0) { + data = 0xffffff00 | ((data >> 2) & 0xff); + rarVM.faddbits(14); + } else { + data = (data >> 6) & 0xff; + rarVM.faddbits(10); + } + return (data); + case 0x8000: + rarVM.faddbits(2); + data = rarVM.fgetbits(); + rarVM.faddbits(16); + return (data); + default: + rarVM.faddbits(2); + data = (rarVM.fgetbits() << 16); + rarVM.faddbits(16); + data |= rarVM.fgetbits(); + rarVM.faddbits(16); + return (data); + } + } + + private VMStandardFilters IsStandardFilter(byte[] code, int codeSize) { + VMStandardFilterSignature stdList[]={ + new VMStandardFilterSignature(53, 0xad576887, VMStandardFilters.VMSF_E8), + new VMStandardFilterSignature(57, 0x3cd7e57e, VMStandardFilters.VMSF_E8E9), + new VMStandardFilterSignature(120, 0x3769893f, VMStandardFilters.VMSF_ITANIUM), + new VMStandardFilterSignature(29, 0x0e06077d, VMStandardFilters.VMSF_DELTA), + new VMStandardFilterSignature(149, 0x1c2c5dc8, VMStandardFilters.VMSF_RGB), + new VMStandardFilterSignature(216, 0xbc85e701, VMStandardFilters.VMSF_AUDIO), + new VMStandardFilterSignature(40, 0x46b9c560, VMStandardFilters.VMSF_UPCASE) + }; + int CodeCRC = RarCRC.checkCrc(0xffffffff,code,0,code.length)^0xffffffff; + for (int i=0;i=VM_GLOBALMEMADDR){ + break; + } + int fileSize=0x1000000; + byte cmpByte2=(byte) ((filterType==VMStandardFilters.VMSF_E8E9) ? 0xe9:0xe8); + for (int curPos=0;curPos=0) +// SET_VALUE(false,Data,Addr+FileSize); +// } +// else +// if (Addr=VM_GLOBALMEMADDR){ + break; + } + int curPos=0; + final byte Masks[]={4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0}; + fileOffset>>>=4; + + while (curPos=0) + { + + byte cmdMask=Masks[Byte]; + if (cmdMask!=0) + for (int i=0;i<=2;i++) + if ((cmdMask & (1<=VM_GLOBALMEMADDR/2){ + break; + } +// bytes from same channels are grouped to continual data blocks, +// so we need to place them back to their interleaving positions + + for (int curChannel=0;curChannel=VM_GLOBALMEMADDR/2 || posR<0){ + break; + } + for (int curChannel=0;curChannel=3) + { + int upperDataPos=destDataPos+upperPos; + int upperByte=mem[(int)upperDataPos]&0xff; + int upperLeftByte=mem[upperDataPos-3]&0xff; + predicted=prevByte+upperByte-upperLeftByte; + int pa=Math.abs((int)(predicted-prevByte)); + int pb=Math.abs((int)(predicted-upperByte)); + int pc=Math.abs((int)(predicted-upperLeftByte)); + if (pa<=pb && pa<=pc){ + predicted=prevByte; + } + else{ + if (pb<=pc){ + predicted=upperByte; + } + else{ + predicted=upperLeftByte; + } + } + } + else{ + predicted=prevByte; + } + + prevByte=(predicted-mem[srcPos++]&0xff)&0xff; + mem[destDataPos+i]=(byte)(prevByte&0xff); + + } + } + for (int i=posR,border=dataSize-2;i=VM_GLOBALMEMADDR/2){ + break; + } + for (int curChannel=0;curChannel>>3) & 0xff; + + long curByte=mem[srcPos++]&0xff; + + predicted = (predicted - curByte)&UINT_MASK; + mem[destDataPos+i]=(byte)predicted; + prevDelta=(byte)(predicted-prevByte); + prevByte=predicted; + + int D=((byte)curByte)<<3; + + Dif[0]+=Math.abs(D); + Dif[1]+=Math.abs(D-D1); + Dif[2]+=Math.abs(D+D1); + Dif[3]+=Math.abs(D-D2); + Dif[4]+=Math.abs(D+D2); + Dif[5]+=Math.abs(D-D3); + Dif[6]+=Math.abs(D+D3); + + if ((byteCount & 0x1f)==0) + { + long minDif=Dif[0], numMinDif=0; + Dif[0]=0; + for (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>>(32-bitCount); + andMask=~(andMask<>>8)|0xff000000; + bitField>>>=8; + } + + } + + private int filterItanium_GetBits(int curPos, int bitPos, int bitCount) { + int inAddr=bitPos/8; + int inBit=bitPos&7; + int bitField=(int)(mem[curPos+inAddr++]&0xff); + bitField|=(int) ((mem[curPos+inAddr++]&0xff) << 8); + bitField|=(int) ((mem[curPos+inAddr++]&0xff) << 16); + bitField|=(int) ((mem[curPos+inAddr]&0xff) << 24); + bitField >>>= inBit; + return(bitField & (0xffffffff>>>(32-bitCount))); + } + + + public void setMemory(int pos,byte[] data,int offset,int dataSize) + { + if (pos