package net.scapeemulator.asm.bundler.trans;
import java.util.Iterator;
import java.util.List;
import net.scapeemulator.asm.bundler.Resource;
import net.scapeemulator.asm.util.InsnMatcher;
import net.scapeemulator.asm.util.InsnNodeUtils;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
public final class FileTransformer extends Transformer {
private static final String RESOURCE_CONSTRUCTOR_PATTERN = "NEW DUP LDC LDC ICONST_4 ANEWARRAY (DUP ICONST LDC AASTORE)+ (ICONST | BIPUSH | SIPUSH | LDC) (ICONST | BIPUSH | SIPUSH | LDC) BIPUSH NEWARRAY (DUP (ICONST | BIPUSH) (ICONST | BIPUSH | SIPUSH | LDC) IASTORE)+ INVOKESPECIAL";
private final Resource[] resources;
public FileTransformer(Resource[] resources) {
this.resources = resources;
}
@SuppressWarnings("unchecked")
@Override
public void transform(ClassNode node) {
for (MethodNode method : (List<MethodNode>) node.methods) {
if (!method.name.equals("<clinit>"))
continue;
int resourceNum = 0;
InsnMatcher matcher = new InsnMatcher(method.instructions);
for (Iterator<AbstractInsnNode[]> it = matcher.match(RESOURCE_CONSTRUCTOR_PATTERN); it.hasNext();) {
AbstractInsnNode[] match = it.next();
if (match.length != 107)
continue;
Resource resource = resources[resourceNum++];
method.instructions.set(match[22], InsnNodeUtils.createNumericPushInsn(resource.getUncompressedSize()));
method.instructions.set(match[23], InsnNodeUtils.createNumericPushInsn(resource.getCompressedSize()));
int[] checksum = resource.getChecksum();
for (int i = 0; i < checksum.length; i++) {
int j = 28 + i * 4;
method.instructions.set(match[j], InsnNodeUtils.createNumericPushInsn(checksum[i]));
}
}
}
}
}