- 浏览: 3052561 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
嗯,这个也是快一年前写的了。当时在澄空看到有人想要解手机少女的文件,就随便写了个程序来处理这个script.arc与string.arc。另外几个arc文件用下面的程序处理不了,因为文件头里的信息没有被正确的处理。嘛,后来asmodean也放出了处理这个游戏的工具而且是用C++写的,我就没必要继续把这个程序做完。
也是由于使用了BlowfishJ的BinConverter.java,所以以下代码以LGPL许可证发布。
Archiver.java:
IndexEntry.java:
LZSS.java:
Binconverter.java:
也是由于使用了BlowfishJ的BinConverter.java,所以以下代码以LGPL许可证发布。
Archiver.java:
/* * @(#)Archiver.java 2007/05/15 * Written by rednaxela / FX */ import java.io.*; import java.util.*; /* Data structures: //-------------------------------- typedef struct tagHEADER { DWORD id; // IDENTIFIER, BE AD CA A8, little-endian ("ARCW" xor 0xFF) DWORD ver; // VERSION, locked to 0x00 DWORD fileSize; // total size of current archive DWORD data_offset; // begin offset of file data } HEADER; // 16 bytes typedef struct tagSECINFO { DWORD sectionLength; // sectionLength = len(SECINFO)(=0x0C) + len(SECDATA) DWORD flags; // flags: NOT_MSK = 1, LZSS_MSK = 2 DWORD origSize; // original size of SECDATA after inflation } SECINFO; // 12 bytes typedef struct tagSECDATA { BYTE data[SECINFO.sectionLength - 12]; // when SECINFO.flags = NOT_MSK | LZSS_MSK, the contents is both encrypted by NOT // and compressed by LZSS. } SECDATA; struct INDEXBLOCK1 { struct INDEXENTRY { DWORD offset; // actualOfs = offset + totalHeaderLength - 0x0C DWORD length; // length in archive DWORD flags; // NOT_MSK = 1, LZSS_MSK = 2 DWORD origLen; // original file length }; DWORD reserved1; // some sort of flag I guess DWORD reserved2; // seems to be always zero DWORD entryCount; // number of entries in this block DWORD blockLength; // length of the remaining part of this block DWORD nameOffset[entryCount]; // offset relative to nameSecData after decode and decompression INDEXENTRY entry[entryCount]; // TOC entrys }; struct INDEXBLOCK2 { }; // structure is unknown //-------------------------------- arc file: HEADER header; // 1 header per archive SECINFO nameSecInfo; // 1st of SECINFO in archive SECDATA nameSecData; // 1st of SECDATA in archive, contents of which are filenames in UNICODE SECINFO indexSecInfo; // 2nd of SECINFO in archive SECDATA indexSecData; // 2nd of SECDATA in archive, contents of which indicates offset, length, flag info of file data. bytes data[]; // remaining part of archive, which is file data //-------------------------------- indexSecData after decode and decompression: DWORD blockCount; INDEXBLOCK1 block1; // INDEXBLOCK2 block2; // this is where I've got trouble figuring out. */ /** * Demonstrating archive operations on *.arc files as seen in Ketai-s. */ public class Archiver { static final int IDENTIFIER = 0xA8BCADBE; static final int VERSION = 0x00; static final int NOT_MSK = 1; static final int LZSS_MSK = 2; static final String USAGE = "Usage: java Archiver [option] srcPath dstPath\n" + "options:\n" + "[l]ist\n" + "[e]xtract\n" + "[a]rchive"; static ArrayList<IndexEntry> index = null; /** * the application entry point * @param args (command line) parameters */ public static void main(String[] args) throws Exception { // check command line arguments if (args.length != 3) error(USAGE); if ("l".equals(args[0].trim())) { // extract files from archive String srcPath = args[1].trim(); String dstPath = args[2].trim(); if (srcPath.length() == 0) error("2nd argument not exist."); if (dstPath.length() == 0) error("3rd argument not exist."); listFiles(srcPath, dstPath); } else if ("e".equals(args[0].trim())) { // extract files from archive String srcPath = args[1].trim(); String dstPath = args[2].trim(); if (srcPath.length() == 0) error("2nd argument not exist."); if (dstPath.length() == 0) error("3rd argument not exist."); extractFiles(srcPath, dstPath); } else if ("a".equals(args[0].trim())) { // pack files into archive String srcPath = args[1].trim(); String dstPath = args[2].trim(); if (srcPath.length() == 0) error("2nd argument not exist."); if (dstPath.length() == 0) error("3rd argument not exist."); packFiles(srcPath, dstPath); } else error(USAGE); } private static void listFiles(String srcFile, String listFile) throws Exception { // open source archive File arc = new File(srcFile); if (!arc.exists()) error("Archive " + srcFile + " doesn't exist"); long contentOfs = -1L; FileInputStream fis = new FileInputStream(arc); DataInputStream dis = new DataInputStream(fis); index = new ArrayList<IndexEntry>(); // match archive IDENTIFIER int id = flipEndian(dis.readInt()); if (IDENTIFIER != id) error("Archive file not supported. Unexpected identifier 0x" + Integer.toHexString(id).toUpperCase()); // match archive version int ver = flipEndian(dis.readInt()); if (VERSION != ver) error("Archive file not supported. Unexpected version."); // match file size int fsize = flipEndian(dis.readInt()); if ((int)(arc.length()) != fsize) error("Archive file not supported. Unexpected file size."); // probable checksum int checksum = flipEndian(dis.readInt()); // if (checksum(arc) != checksum)) error("Archive file not supported. Unexpected checksum."); System.err.println("CHECKSUM: 0x" + Integer.toHexString(checksum).toUpperCase()); // read index entries byte[] nameBuf = readIndexBlock(fis); byte[] infoBuf = readIndexBlock(fis); parseIndex(nameBuf, infoBuf); // extract files int baseOfs = (int)(fis.getChannel().position()); // check this, might not be correct PrintStream out = new PrintStream(new FileOutputStream(listFile)); System.setOut(out); // stdout redirection for (IndexEntry entry : index) { // print file info printFileInfo(entry, baseOfs); } } private static void extractFiles(String srcFile, String dstDir) throws Exception { // open source archive File arc = new File(srcFile); if (!arc.exists()) error("Archive " + srcFile + " doesn't exist"); long contentOfs = -1L; FileInputStream fis = new FileInputStream(arc); DataInputStream dis = new DataInputStream(fis); index = new ArrayList<IndexEntry>(); // match archive IDENTIFIER int id = flipEndian(dis.readInt()); if (IDENTIFIER != id) error("Archive file not supported. Unexpected identifier 0x" + Integer.toHexString(id).toUpperCase()); // match archive version int ver = flipEndian(dis.readInt()); if (VERSION != ver) error("Archive file not supported. Unexpected version."); // match file size int fsize = flipEndian(dis.readInt()); if ((int)(arc.length()) != fsize) error("Archive file not supported. Unexpected file size."); // probable checksum int checksum = flipEndian(dis.readInt()); // if (checksum(arc) != checksum)) error("Archive file not supported. Unexpected checksum."); System.err.println("CHECKSUM: 0x" + Integer.toHexString(checksum).toUpperCase()); // read index entries byte[] nameBuf = readIndexBlock(fis); byte[] infoBuf = readIndexBlock(fis); parseIndex(nameBuf, infoBuf); // extract files int baseOfs = (int)(fis.getChannel().position()); // check this, might not be correct for (IndexEntry entry : index) { // print file info printFileInfo(entry, baseOfs); // data correctness check - this support ordered file archive only // to support out-of-order archives, use RandomAccessFile instead. if ((int)(fis.getChannel().position()) != entry.getOffset() + baseOfs) { // error("Bad file content order " // + entry.getFilename() + " @ 0x" // + Integer.toHexString((int)(fis.getChannel().position()))); System.err.println("Out-of-order. " + entry.getFilename() + " @ 0x" + Integer.toHexString((int)(fis.getChannel().position()))); fis.getChannel().position(entry.getOffset() + baseOfs); } // get buffer and read file byte[] writeBuf = readBlock(fis, entry.getLength(), entry.getFlags(), entry.getOrigLength()); // write file writeFile(writeBuf, entry.getFilename(), dstDir); } fis.close(); } private static void packFiles(String srcDir, String dstFile) throws Exception { // TODO // not implemented yet } private static void parseIndex(byte[] nameBuf, byte[] infoBuf) throws IOException { DataInputStream dis = new DataInputStream( new ByteArrayInputStream(infoBuf)); int blockCount = flipEndian(dis.readInt()); // PROBLEM 1 // This is where my program doesn't go compatible with the image.arc // and sound.arc files. Their blockCount is 2. The 1st block seem // to be the same as string.arc and script.arc, but the 2nd block is severely // obsfucated that I don't know what the program is doing. // if (blockCount != 1) error("Archive not supported. BlockCount is " + blockCount); for (int i = 0; i < blockCount; ++i) { int reserved1 = flipEndian(dis.readInt()); // unknown usage int reserved2 = flipEndian(dis.readInt()); // not used int entryCount = flipEndian(dis.readInt()); // entry count in current block int blockSize = flipEndian(dis.readInt()); // current block size // System.err.println(Arrays.toString(nameBuf)); System.err.println("reserved1: " + reserved1); System.err.println("reserved2: " + reserved2); System.err.println("entry count: " + entryCount); System.err.println("block size: " + blockSize); // PROBLEM 2 // if (4 * 5 * entryCount != blockSize) error("Index error. Wrong block size.\n" // + "Count=" + entryCount + " BlockSize=" + blockSize); int[] nameOfs = new int[entryCount]; for (int j = 0; j < entryCount; ++j) { nameOfs[j] = flipEndian(dis.readInt()); } for (int j = 0; j < entryCount; ++j) { IndexEntry entry = new IndexEntry(); entry.setFilename(readWString(nameBuf, nameOfs[j])); entry.setOffset(flipEndian(dis.readInt())); entry.setLength(flipEndian(dis.readInt()) - 12); entry.setFlags(flipEndian(dis.readInt())); entry.setOrigLength(flipEndian(dis.readInt())); index.add(entry); } } } private static int flipEndian(int i) { byte[] bytes = new byte[4]; bytes[0] = (byte)(i >>> 24); bytes[1] = (byte)(i >>> 16); bytes[2] = (byte)(i >>> 8); bytes[3] = (byte) i; i = bytes[3] << 24; i |= (bytes[2] << 16) & 0x0ff0000; i |= (bytes[1] << 8) & 0x000ff00; i |= bytes[0] & 0x00000ff; return i; } private static void invertBitsArray(byte[] arr) { for (int i = 0; i < arr.length; ++i) { arr[i] = (byte)~arr[i]; } } private static void error(String cause) { System.err.println("Error " + cause); System.exit(1); } private static void printFileInfo(IndexEntry entry, int baseOfs) { System.out.print("File " + entry.getFilename()); System.out.print(" @ 0x" + Integer.toHexString(entry.getOffset() + baseOfs).toUpperCase()); System.out.print(" size: 0x" + Integer.toHexString(entry.getLength()).toUpperCase()); System.out.println(" origSize: 0x" + Integer.toHexString(entry.getOrigLength()).toUpperCase()); System.out.print("Masks: "); boolean doPrint = (entry.getFlags() | NOT_MSK) != 0; if (doPrint) System.out.print("NOT_MSK"); if ((entry.getFlags() | LZSS_MSK) != 0 && doPrint) System.out.print(" | "); else System.out.println(); if ((entry.getFlags() | LZSS_MSK) != 0) System.out.println("LZSS_MSK"); } private static byte[] readIndexBlock(InputStream in) throws IOException { DataInputStream dis = new DataInputStream(in); int len = flipEndian(dis.readInt()) - 12; int flags = flipEndian(dis.readInt()); int origLen = flipEndian(dis.readInt()); return readBlock(in, len, flags, origLen); } private static byte[] readBlock(InputStream in, int len, int flags, int origLen) throws IOException { byte[] buf = new byte[len]; in.read(buf); if ((flags | NOT_MSK) != 0) invertBitsArray(buf); if (((flags | LZSS_MSK) != 0) && (len < origLen)) buf = LZSS.decompress(buf, len, null, origLen); // TODO - other flag status are not supported yet return buf; } private static String readWString(byte[] buf, int pos) throws IOException { int len = 0; int i = pos; while ((buf[i] | buf[i+1]) != 0) { len += 2; i += 2; } return new String(buf, pos, len, "UTF-16LE"); } private static void writeFile(byte[] buf, String name, String dstDir) throws IOException { if (dstDir == null) dstDir = "./output"; File outfile = new File(dstDir + "/" + name); File parentDir = outfile.getParentFile(); if (!parentDir.exists()) parentDir.mkdirs(); FileOutputStream fos = new FileOutputStream(outfile); BufferedOutputStream bos = new BufferedOutputStream(fos, 0x100000); ByteArrayInputStream bais = new ByteArrayInputStream(buf); int remainder = buf.length; // keep track of the amount of remaining bytes byte[] bytes16 = new byte[16]; while (bais.available() != 0 && remainder / 16 != 0) { bais.read(bytes16); bos.write(bytes16); remainder -= 16; } if (remainder != 0) { byte[] remains = new byte[remainder]; bais.read(remains); bos.write(remains); } bos.flush(); bos.close(); } }
IndexEntry.java:
/* * @(#)IndexEntry.java 2007/05/15 * Written by rednaxela / FX */ public class IndexEntry { static final int ENTRY_LENGTH = 16; static final int MAX_FILENAME_LENGTH = 256; static final int OFFSET_OFS = 0; static final int LENGTH_OFS = 4; static final int FLAGS_OFS = 8; static final int ORIGLENGTH_OFS = 12; private String filename; private int length; private int offset; private int flags; // NOT_MSK = 1, LZSS_MSK = 2 private int origLength; /** * @return the filename */ public String getFilename() { return filename; } /** * @param filename the filename to set */ public void setFilename(String filename) { this.filename = filename; } /** * @return the length */ public int getLength() { return length; } /** * @param length the length to set */ public void setLength(int length) { this.length = length; } /** * @return the offset */ public int getOffset() { return offset; } /** * @param offset the offset to set */ public void setOffset(int offset) { this.offset = offset; } /** * @return the offset */ public int getFlags() { return offset; } /** * @param offset the offset to set */ public void setFlags(int flags) { this.flags = flags; } /** * @return the compressedLength */ public int getOrigLength() { return origLength; } /** * @param offset the compressedLength to set */ public void setOrigLength(int origLength) { this.origLength = origLength; } }
LZSS.java:
/* * @(#)LZSS.java 2007/05/15 * Written by rednaxela / FX */ public class LZSS { static final int WINDOW_LENGTH = 4096; public static byte[] decompress(byte[] from, int compLen, byte[] to, int origLen) { return decompress(from, compLen, to, 0, origLen); } public static byte[] decompress(byte[] from, int compLen, byte[] to, int pos, int origLen) { if (to == null) to = new byte[origLen]; byte[] window = new byte[WINDOW_LENGTH]; int readOffset = 0; int writeOffset = pos; int marker = 0; // read marker, 8-bits, 1 for raw byte, 0 for back ref int windowWriteOffset = 0x0FEE; int windowReadOffset = 0; int backRefLength = 0; int current = 0; while (readOffset != from.length) { marker >>= 1; if ((marker & 0x0100) == 0) { current = from[readOffset++] & 0x0FF; marker = 0x0FF00 | current; } if(readOffset == from.length) break; if ((marker & 0x01) == 1) { // copy raw bytes current = from[readOffset++] & 0x0FF; to[writeOffset++] = (byte)current; window[windowWriteOffset++] = (byte)current; windowWriteOffset &= 0x0FFF; } else { // copy from slide window windowReadOffset = from[readOffset++] & 0x0FF; if(readOffset == from.length) break; current = from[readOffset++] & 0x0FF; windowReadOffset |= (current & 0x0F0) << 4; backRefLength = (current & 0x0F) + 2; if (backRefLength < 0) continue; int addOffset = 0; while (addOffset <= backRefLength) { int curOfs = (windowReadOffset + addOffset++) & 0x0FFF; current = window[curOfs] & 0x0FF; windowReadOffset &= 0x0FFF; to[writeOffset++] = (byte)current; window[windowWriteOffset++] = (byte)current; windowWriteOffset &= 0x0FFF; } // while } // if-else } // while return to; } }
Binconverter.java:
/* * @(#)BinConverter.java */ /** * Some helper routines for data conversion, all data is treated in network * byte order. */ public class BinConverter { /** * Gets bytes from an array into an integer, in big-endian. * @param buf where to get the bytes * @param ofs index from where to read the data * @return the 32bit integer */ public final static int byteArrayToIntBE( byte[] buf, int ofs) { return (buf[ofs ] << 24) | ((buf[ofs + 1] & 0x0ff) << 16) | ((buf[ofs + 2] & 0x0ff) << 8) | ( buf[ofs + 3] & 0x0ff); } /** * Gets bytes from an array into an integer, in little-endian. * @param buf where to get the bytes * @param ofs index from where to read the data * @return the 32bit integer */ public final static int byteArrayToIntLE( byte[] buf, int ofs) { return (buf[ofs + 3] << 24) | ((buf[ofs + 2] & 0x0ff) << 16) | ((buf[ofs + 1] & 0x0ff) << 8) | ( buf[ofs ] & 0x0ff); } /////////////////////////////////////////////////////////////////////////// /** * Converts an integer to bytes in big-endian, which are put into an array. * @param value the 32bit integer to convert * @param buf the target buf * @param ofs where to place the bytes in the buf */ public final static void intToByteArrayBE( int value, byte[] buf, int ofs) { buf[ofs ] = (byte)((value >>> 24) & 0x0ff); buf[ofs + 1] = (byte)((value >>> 16) & 0x0ff); buf[ofs + 2] = (byte)((value >>> 8) & 0x0ff); buf[ofs + 3] = (byte) value; } /** * Converts an integer to bytes in little-endian, which are put into an array. * @param value the 32bit integer to convert * @param buf the target buf * @param ofs where to place the bytes in the buf */ public final static void intToByteArrayLE( int value, byte[] buf, int ofs) { buf[ofs + 3] = (byte)((value >>> 24) & 0x0ff); buf[ofs + 2] = (byte)((value >>> 16) & 0x0ff); buf[ofs + 1] = (byte)((value >>> 8) & 0x0ff); buf[ofs ] = (byte) value; } /////////////////////////////////////////////////////////////////////////// /** * Gets bytes from an array into a long. * @param buf where to get the bytes * @param ofs index from where to read the data * @return the 64bit integer */ public final static long byteArrayToLong( byte[] buf, int ofs) { // Looks more complex - but it is faster (at least on 32bit platforms). return ((long)(( buf[ofs ] << 24) | ((buf[ofs + 1] & 0x0ff) << 16) | ((buf[ofs + 2] & 0x0ff) << 8) | ( buf[ofs + 3] & 0x0ff )) << 32) | ((long)(( buf[ofs + 4] << 24) | ((buf[ofs + 5] & 0x0ff) << 16) | ((buf[ofs + 6] & 0x0ff) << 8) | ( buf[ofs + 7] & 0x0ff )) & 0x0ffffffffL); } /////////////////////////////////////////////////////////////////////////// /** * Converts a long to bytes, which are put into an array. * @param value the 64bit integer to convert * @param buf the target buf * @param ofs where to place the bytes in the buf */ public final static void longToByteArray( long value, byte[] buf, int ofs) { int tmp = (int)(value >>> 32); buf[ofs ] = (byte) (tmp >>> 24); buf[ofs + 1] = (byte)((tmp >>> 16) & 0x0ff); buf[ofs + 2] = (byte)((tmp >>> 8) & 0x0ff); buf[ofs + 3] = (byte) tmp; tmp = (int)value; buf[ofs + 4] = (byte) (tmp >>> 24); buf[ofs + 5] = (byte)((tmp >>> 16) & 0x0ff); buf[ofs + 6] = (byte)((tmp >>> 8) & 0x0ff); buf[ofs + 7] = (byte) tmp; } /////////////////////////////////////////////////////////////////////////// /** * Converts values from an integer array to a long. * @param buf where to get the bytes * @param ofs index from where to read the data * @return the 64bit integer */ public final static long intArrayToLong( int[] buf, int ofs) { return (((long) buf[ofs ]) << 32) | (((long) buf[ofs + 1]) & 0x0ffffffffL); } /////////////////////////////////////////////////////////////////////////// /** * Converts a long to integers which are put into an array. * @param value the 64bit integer to convert * @param buf the target buf * @param ofs where to place the bytes in the buf */ public final static void longToIntArray( long value, int[] buf, int ofs) { buf[ofs ] = (int)(value >>> 32); buf[ofs + 1] = (int) value; } /////////////////////////////////////////////////////////////////////////// /** * Makes a long from two integers (treated unsigned). * @param lo lower 32bits * @param hi higher 32bits * @return the built long */ public final static long makeLong( int lo, int hi) { return (((long) hi << 32) | ((long) lo & 0x00000000ffffffffL)); } /////////////////////////////////////////////////////////////////////////// /** * Gets the lower 32 bits of a long. * @param val the long integer * @return lower 32 bits */ public final static int longLo32( long val) { return (int)val; } /////////////////////////////////////////////////////////////////////////// /** * Gets the higher 32 bits of a long. * @param val the long integer * @return higher 32 bits */ public final static int longHi32( long val) { return (int)(val >>> 32); } /////////////////////////////////////////////////////////////////////////// // our table for hex conversion final static char[] HEXTAB = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; /** * Converts a byte array to a hex string. * @param data the byte array * @return the hex string */ public final static String bytesToHexStr( byte[] data) { return bytesToHexStr(data, 0, data.length); } /////////////////////////////////////////////////////////////////////////// /** * Converts a byte array to a hex string. * @param data the byte array * @param ofs start index where to get the bytes * @param len number of bytes to convert * @return the hex string */ public final static String bytesToHexStr( byte[] data, int ofs, int len) { int pos, c; StringBuffer sbuf; sbuf = new StringBuffer(); sbuf.setLength(len << 1); pos = 0; c = ofs + len; while (ofs < c) { sbuf.setCharAt(pos++, HEXTAB[(data[ofs ] >> 4) & 0x0f]); sbuf.setCharAt(pos++, HEXTAB[ data[ofs++] & 0x0f]); } return sbuf.toString(); } /////////////////////////////////////////////////////////////////////////// /** * Converts a hex string back into a byte array (invalid codes will be * skipped). * @param hex hex string * @param data the target array * @param srcofs from which character in the string the conversion should * begin, remember that (nSrcPos modulo 2) should equals 0 normally * @param dstofs to store the bytes from which position in the array * @param len number of bytes to extract * @return number of extracted bytes */ public final static int hexStrToBytes( String hex, byte[] data, int srcofs, int dstofs, int len) { int i, j, strlen, avail_bytes, dstofs_bak; byte abyte; boolean convertOK; // check for correct ranges strlen = hex.length(); avail_bytes = (strlen - srcofs) >> 1; if (avail_bytes < len) { len = avail_bytes; } int nOutputCapacity = data.length - dstofs; if (len > nOutputCapacity) { len = nOutputCapacity; } // convert now dstofs_bak = dstofs; for (i = 0; i < len; i++) { abyte = 0; convertOK = true; for (j = 0; j < 2; j++) { abyte <<= 4; char cActChar = hex.charAt(srcofs++); if ((cActChar >= 'a') && (cActChar <= 'f')) { abyte |= (byte) (cActChar - 'a') + 10; } else { if ((cActChar >= '0') && (cActChar <= '9')) { abyte |= (byte) (cActChar - '0'); } else { convertOK = false; } } } if (convertOK) { data[dstofs++] = abyte; } } return (dstofs - dstofs_bak); } /////////////////////////////////////////////////////////////////////////// /** * Converts a byte array into a Unicode string. * @param data the byte array * @param ofs where to begin the conversion * @param len number of bytes to handle * @return the string */ public final static String byteArrayToStr( byte[] data, int ofs, int len) { int avail_capacity, sbuf_pos; StringBuffer sbuf; // we need two bytes for every character len &= ~1; // enough bytes in the buf? avail_capacity = data.length - ofs; if (avail_capacity < len) { len = avail_capacity; } sbuf = new StringBuffer(); sbuf.setLength(len >> 1); sbuf_pos = 0; while (0 < len) { sbuf.setCharAt( sbuf_pos++, (char)((data[ofs ] << 8) | (data[ofs + 1] & 0x0ff))); ofs += 2; len -= 2; } return sbuf.toString(); } }
发表评论
-
IDA Pro Free笔记
2013-05-19 08:59 0IDA把数据都存哪里了? Windows 7 D:\tem ... -
加密算法收集
2011-01-23 16:10 0加密算法,OTP http://en.wikipedia.or ... -
BattleMoonWars 归档解压/压缩程序(砍掉重炼版)
2010-05-03 21:40 2281以前写过BattleMoonWars的 ... -
Quartett!文本插入程序
2008-06-21 20:38 1572年初写的Quartett!的文本 ... -
BattleMoonWars 归档解压/压缩程序 (Java)
2008-04-08 16:44 2448呼,这个也是一年多之 ... -
桃華月憚体験版的解压缩程序 (Java)
2008-04-08 13:38 3113这是差不多一年前写的程序了……有人说想看于是发出来。 当时也是 ... -
Quartett!的文本提取程序
2008-03-05 23:31 1878诶,之前写了这个程序 ... -
Fortune Arterial Tools
2008-02-28 13:34 2446using System; using System.IO; ... -
さくらシュトラッセ literal record
2008-01-28 14:53 1814脚本在scenario.sc里。无 ... -
Borland的库的一个小特征?
2008-01-06 00:22 2509最近弄了下KAMIPANI相关 ... -
[脚本分析] 从Quartett!的脚本得到资源列表
2007-12-21 14:00 1771听汉公的说明,看来LittleWitch所使用的FFD Sys ... -
[脚本分析] Quartett!的二进制脚本分析
2007-12-20 22:17 3325我前两天在NetOA方面确 ...
相关推荐
然而,通过特定的工具,比如"PKXARC",仍然可以对ARC文件进行解压缩。 "PKXARC"是一个专门用于处理ARC文件的工具,它允许用户打开、查看和提取ARC压缩包中的内容。这个程序的使用至关重要,因为没有它,那些包含ARC...
1. 安装:解压缩下载的"Lost.Planet.ARC.Exctactor.exe"文件,运行执行程序。 2. 打开ARC文件:通过软件界面选择要操作的ARC文件,进行加载。 3. 浏览与提取:工具会显示ARC文件内的所有内容,用户可以选择需要的...
尝试在窗体上画一张笑脸.Arc,Area 共有两种不同图案
对于压缩文件类型,`.arc`可以通过专业的解压缩软件如`Freearc`进行处理。理解`.arc`文件的性质和如何打开它,有助于你在遇到这类文件时能够有效地管理和使用其中的数据。无论是游戏资源还是其他类型的压缩数据,...
`.arc`文件是诺基亚Backup应用程序创建的一种压缩格式,它包含了用户的联系人、短信、通话记录、设置等个人信息。这种格式的备份文件旨在方便用户在更换设备或系统恢复时快速恢复数据。然而,由于文件损坏、不兼容或...
标题"SINUCOM-ARC.rar"表明这是一份与Siemens数控系统相关的压缩文件,其扩展名".rar"是常见的压缩文件格式,通常用于存储多个文件或文件夹以方便传输和存储。描述中提到".arc"格式的文档,这可能是指Siemens数控...
@architect/package ...// fake out an .arc file as a string let arcString = ` @app mybasicapp @http get / ` // parse .arc string into a plain javascript object let arc = parse ( arcString ) // expo
### Arc2D.Float 类在Java中的应用 #### 一、Arc2D.Float 概述 在Java图形绘制中,`Arc2D.Float`是`Arc2D`类的一个子类,用于表示用浮点精度定义的弧形。该类允许开发者以较高的精度创建并操作二维图形中的弧线。...
2. **解压缩数据**:根据头部信息,解包器选择合适的解压缩算法(如DEFLATE、LZMA等)来解压文件内容。 3. **解析内部结构**:arc文件可能包含复杂的内部结构,如索引、目录或者特定的游戏资源格式,解包器需要理解...
2. 用ArcEngine的工具条添加图层要素 2 3. ArcEngine中对Feature的编辑 5 4. Feature的概念 6 5. 如何实现经度纬度到平面坐标的相互转换?(转载) 7 6. ArcEngine 最短路径分析(源码) 9 7. ArcEngine中使用上下...
ArcEngine是Esri公司推出的用于构建地理信息系统(GIS)应用程序的强大开发工具,它提供了丰富的API,允许开发者使用多种编程语言,包括Java,来创建具有地图显示、空间分析等功能的应用。在这个名为“ArcEngine for...
这是关于fpga架构文件中的common文件,如有需要请下载
在IT行业中,ArcEngine是Esri公司开发的一款强大的地理信息系统(GIS)开发组件,它允许开发者利用Java、.NET等多种编程语言构建具有地图显示、空间分析、数据管理等功能的应用程序。ArcGIS是Esri的核心产品,它包含...
《ArcEngine示例程序:深度探索GIS开发技术》 ArcEngine是Esri公司推出的一款强大的地理信息系统(GIS)开发工具,它允许开发者利用C#.NET等编程语言构建桌面、Web和移动应用程序,实现对地理数据的高效管理和分析...
ArcEngine_java_plugin是一个专为开发者设计的工具,主要用于调试基于Java的ArcEngine程序。ArcEngine是Esri公司提供的一个强大的地理信息系统(GIS)开发平台,它允许开发人员创建桌面、服务器以及Web应用程序,以...
bgd.arc
在IT行业中,Java和ArcEngine的结合是一种常见的技术实践,特别是在地理信息系统(GIS)开发领域。ArcEngine是由Esri公司提供的一个强大的开发平台,用于构建地理空间应用。它提供了丰富的API,可以与多种编程语言...
使用freearc解压
本项目标题提及的是“程序实现用Java编写的基于ArcEngine的GIS中图形浏览编辑功能”,这暗示我们将讨论如何利用Java语言与ArcEngine API进行交互,实现地图的查看和编辑功能。 1. **ArcEngine简介** ArcEngine是...
### 使用WinRar打包ArcEngine程序 在IT领域中,软件开发完成后往往需要进行打包处理以便于分发或部署到目标环境中。对于基于ArcEngine的应用程序来说,使用WinRAR进行打包是一个常见且实用的方法。本文将详细介绍...