com.github.junrar.unpack.vm.RarVM Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of junrar Show documentation
Show all versions of junrar Show documentation
rar decompression library in plain java
/*
* 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; <<??
if (opNum > 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));
}
}
}
}
@SuppressWarnings("incomplete-switch")
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
© 2015 - 2025 Weber Informatics LLC | Privacy Policy