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

📄 rarvm.java

📁 java下操作rar文件,创建,压缩/解压缩等等.
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 "&"
 * "<":  "&#060;" or "&lt;"
 * ">":  "&#062;" or "&gt;"
 * "@":  "&#064;" 
 */
package de.innosystec.unrar.unpack.vm;

import java.util.List;
import java.util.Vector;

import de.innosystec.unrar.crc.RarCRC;
import de.innosystec.unrar.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<Byte> 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<VMPreparedCommand> 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<VMPreparedCommand> 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)|(Result==0 ? VM_FZ:((Result&0x80) ?
					// VM_FS:0));
				} else
					flags = (result < value1) ? 1
							: 0 | (result == 0 ? VMFlags.VM_FZ.getFlag()
									: (result & VMFlags.VM_FS.getFlag()));
				setValue(cmd.isByteMode(), mem, op1, result);
			}
				break;

			case VM_ADDB:
				setValue(true, mem, op1,
						(int) ((long) getValue(true, mem, op1) & 0xFFffFFff
								+ (long) getValue(true, mem, op2) & 0xFFffFFff));
				break;
			case VM_ADDD:
				setValue(
						false,
						mem,
						op1,
						(int) ((long) getValue(false, mem, op1) & 0xFFffFFff
								+ (long) getValue(false, mem, op2) & 0xFFffFFff));
				break;

			case VM_SUB: {
				int value1 = getValue(cmd.isByteMode(), mem, op1);
				int result = (int) ((long) value1 & 0xffFFffFF
						- (long) getValue(cmd.isByteMode(), mem, op2) & 0xFFffFFff);
				flags = (result == 0) ? VMFlags.VM_FZ.getFlag()
						: (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;

⌨️ 快捷键说明

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