| /* Copyright 2015-2022 Rivoreo |
| |
| This Source Code Form is subject to the terms of the Mozilla Public |
| License, v. 2.0. If a copy of the MPL was not distributed with this |
| file, You can obtain one at https://mozilla.org/MPL/2.0/. |
| */ |
| |
| package rivoreo.minecraft.monospacefont; |
| |
| import net.minecraft.launchwrapper.IClassTransformer; |
| import org.objectweb.asm.ClassReader; |
| import org.objectweb.asm.ClassWriter; |
| import org.objectweb.asm.tree.ClassNode; |
| import org.objectweb.asm.tree.MethodNode; |
| import org.objectweb.asm.tree.InsnList; |
| import org.objectweb.asm.tree.FieldInsnNode; |
| import org.objectweb.asm.tree.IntInsnNode; |
| import org.objectweb.asm.tree.LdcInsnNode; |
| import org.objectweb.asm.tree.VarInsnNode; |
| import org.objectweb.asm.tree.JumpInsnNode; |
| import org.objectweb.asm.tree.InsnNode; |
| import org.objectweb.asm.tree.LabelNode; |
| import org.objectweb.asm.tree.AbstractInsnNode; |
| import org.objectweb.asm.Opcodes; |
| import java.util.List; |
| |
| public class MonospaceFontTransformer implements IClassTransformer { |
| private static final byte UNICODE_FONT_CHARACTER_WIDTH = 4; |
| //private static final byte UNICODE_FONT_CHARACTER_WIDTH = 5; |
| |
| private static InsnList create_space_width_insn_list() { |
| InsnList insn_list = new InsnList(); |
| insn_list.add(new VarInsnNode(Opcodes.ALOAD, 0)); |
| insn_list.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/client/gui/FontRenderer", "field_78293_l", "Z")); |
| LabelNode label = new LabelNode(); |
| insn_list.add(new JumpInsnNode(Opcodes.IFNE, label)); |
| insn_list.add(new LdcInsnNode(Float.valueOf(6F))); |
| insn_list.add(new InsnNode(Opcodes.FRETURN)); |
| insn_list.add(label); |
| return insn_list; |
| } |
| |
| private static InsnList create_x_offset_insn_list() { |
| InsnList insn_list = new InsnList(); |
| insn_list.add(new InsnNode(Opcodes.ISUB)); |
| insn_list.add(new VarInsnNode(Opcodes.ISTORE, 6)); |
| insn_list.add(new VarInsnNode(Opcodes.ILOAD, 6)); |
| insn_list.add(new InsnNode(Opcodes.ICONST_0)); |
| LabelNode label = new LabelNode(); |
| insn_list.add(new JumpInsnNode(Opcodes.IF_ICMPGE, label)); |
| insn_list.add(new InsnNode(Opcodes.ICONST_0)); |
| insn_list.add(new VarInsnNode(Opcodes.ISTORE, 6)); |
| insn_list.add(label); |
| insn_list.add(new VarInsnNode(Opcodes.ILOAD, 6)); |
| return insn_list; |
| } |
| |
| public byte[] transform(String original_name, String runtime_name, byte[] class_code) { |
| if(!runtime_name.equals("net.minecraft.client.gui.FontRenderer")) return class_code; |
| ClassReader reader = new ClassReader(class_code); |
| ClassNode class_node = new ClassNode(); |
| reader.accept(class_node, ClassReader.SKIP_DEBUG); |
| if(class_node.version == 52) class_node.version = 50; |
| boolean old_draw_space_transformed = false; |
| boolean new_draw_space_transformed = false; |
| boolean draw_unicode_transformed = false; |
| for(MethodNode method : (List<MethodNode>)class_node.methods) { |
| if(method.desc.equals("(ICZ)F") && (method.name.equals("a") || method.name.equals("func_78278_a")) && method.access == Opcodes.ACC_PRIVATE) { |
| // Draw character |
| AbstractInsnNode[] insn_nodes = method.instructions.toArray(); |
| if(insn_nodes.length < 6) continue; |
| for(int i = 0; i < 6; i++) { |
| if(insn_nodes[i].getOpcode() != Opcodes.LDC) continue; |
| LdcInsnNode ldc_insn = (LdcInsnNode)insn_nodes[i]; |
| if(!(ldc_insn.cst instanceof Float)) continue; |
| InsnList insn_list = create_space_width_insn_list(); |
| method.instructions.insertBefore(ldc_insn, insn_list); |
| if(UNICODE_FONT_CHARACTER_WIDTH != 4) { |
| ldc_insn.cst = Float.valueOf(UNICODE_FONT_CHARACTER_WIDTH); |
| } |
| old_draw_space_transformed = true; |
| break; |
| } |
| } else if(method.desc.equals("(IZ)F") && (method.name.equals("a") || method.name.equals("func_78266_a")) && (method.access == Opcodes.ACC_PROTECTED || method.access == Opcodes.ACC_PRIVATE)) { |
| // Draw character with non-unicode font |
| int x_offset_var_after_insn_i = -1; |
| int char_width_var_i = -1; |
| AbstractInsnNode[] insn_nodes = method.instructions.toArray(); |
| for(int i = 0; i < insn_nodes.length - 2; i++) { |
| int first_opcode = insn_nodes[i].getOpcode(); |
| if(char_width_var_i != -1 && first_opcode == Opcodes.FLOAD) { |
| VarInsnNode var_insn = (VarInsnNode)insn_nodes[i]; |
| if(var_insn.var == char_width_var_i) { |
| method.instructions.insert(var_insn, new LdcInsnNode(Float.valueOf(6F))); |
| method.instructions.remove(var_insn); |
| } |
| continue; |
| } |
| if(char_width_var_i == 7 && first_opcode == Opcodes.ILOAD) { |
| VarInsnNode var_insn = (VarInsnNode)insn_nodes[i]; |
| if(var_insn.var != 6) continue; |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.I2F) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.FRETURN) continue; |
| method.instructions.insert(var_insn, new LdcInsnNode(Float.valueOf(6F))); |
| method.instructions.remove(var_insn); |
| method.instructions.remove(insn_nodes[i + 1]); |
| break; |
| } |
| if(first_opcode != Opcodes.ALOAD) continue; |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.GETFIELD) continue; |
| FieldInsnNode getfield_insn = (FieldInsnNode)insn_nodes[i + 1]; |
| if(getfield_insn.desc.equals("[I")) { |
| if(i >= insn_nodes.length - 4) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.IALOAD) continue; |
| int opcode = insn_nodes[i + 4].getOpcode(); |
| if(opcode == Opcodes.I2F) { |
| opcode = insn_nodes[i + 5].getOpcode(); |
| if(opcode == Opcodes.LDC && i < insn_nodes.length - 7 && insn_nodes[i + 6].getOpcode() == Opcodes.FSUB && insn_nodes[i + 7].getOpcode() == Opcodes.FSTORE) { |
| VarInsnNode var_insn = (VarInsnNode)insn_nodes[i + 7]; |
| if(var_insn.var != 6) continue; |
| char_width_var_i = 6; |
| method.instructions.insertBefore(insn_nodes[i], new IntInsnNode(Opcodes.BIPUSH, 6)); |
| InsnList insn_list = create_x_offset_insn_list(); |
| method.instructions.insert(insn_nodes[i + 3], insn_list); |
| insn_list = new InsnList(); |
| insn_list.add(new InsnNode(Opcodes.FCONST_2)); |
| insn_list.add(new InsnNode(Opcodes.FDIV)); |
| method.instructions.insert(insn_nodes[i + 4], insn_list); |
| method.instructions.remove(insn_nodes[i + 5]); |
| method.instructions.remove(insn_nodes[i + 6]); |
| x_offset_var_after_insn_i = i += 7; |
| } else if(opcode == Opcodes.FRETURN) { |
| method.instructions.insert(getfield_insn, new LdcInsnNode(Float.valueOf(6F))); |
| method.instructions.remove(insn_nodes[i]); |
| method.instructions.remove(getfield_insn); |
| method.instructions.remove(insn_nodes[i + 2]); |
| method.instructions.remove(insn_nodes[i + 3]); |
| method.instructions.remove(insn_nodes[i + 4]); |
| break; |
| } |
| } else if(opcode == Opcodes.ISTORE && i < insn_nodes.length - 9) { |
| VarInsnNode var_insn = (VarInsnNode)insn_nodes[i + 4]; |
| if(var_insn.var != 6) continue; |
| if(insn_nodes[i + 5].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 6].getOpcode() != Opcodes.I2F) continue; |
| if(insn_nodes[i + 7].getOpcode() != Opcodes.LDC) continue; |
| if(insn_nodes[i + 8].getOpcode() != Opcodes.FSUB) continue; |
| if(insn_nodes[i + 9].getOpcode() != Opcodes.FSTORE) continue; |
| var_insn = (VarInsnNode)insn_nodes[i + 9]; |
| if(var_insn.var != 7) continue; |
| char_width_var_i = 7; |
| method.instructions.insertBefore(insn_nodes[i], new IntInsnNode(Opcodes.BIPUSH, 6)); |
| InsnList insn_list = create_x_offset_insn_list(); |
| method.instructions.insert(insn_nodes[i + 3], insn_list); |
| method.instructions.remove(insn_nodes[i + 4]); |
| method.instructions.remove(insn_nodes[i + 5]); |
| insn_list = new InsnList(); |
| insn_list.add(new InsnNode(Opcodes.FCONST_2)); |
| insn_list.add(new InsnNode(Opcodes.FDIV)); |
| method.instructions.insert(insn_nodes[i + 6], insn_list); |
| method.instructions.remove(insn_nodes[i + 7]); |
| method.instructions.remove(insn_nodes[i + 8]); |
| var_insn.var = 6; |
| x_offset_var_after_insn_i = i += 9; |
| } |
| } else if(x_offset_var_after_insn_i > 0 && i > x_offset_var_after_insn_i && getfield_insn.desc.equals("F")) { |
| int opcode = insn_nodes[i + 2].getOpcode(); |
| if(opcode != Opcodes.FLOAD && (char_width_var_i != 7 || opcode != Opcodes.ILOAD)) continue; |
| InsnList insn_list = new InsnList(); |
| insn_list.add(new VarInsnNode(Opcodes.FLOAD, 6)); |
| insn_list.add(new InsnNode(Opcodes.FADD)); |
| method.instructions.insert(getfield_insn, insn_list); |
| i++; |
| } |
| } |
| } else if(method.desc.equals("(CZ)F")) { |
| if(!old_draw_space_transformed && !new_draw_space_transformed && (method.name.equals("a") || method.name.equals("func_181559_a")) && method.access == Opcodes.ACC_PRIVATE) { |
| // Draw character |
| AbstractInsnNode[] insn_nodes = method.instructions.toArray(); |
| if(insn_nodes.length < 10) continue; |
| for(int i = 0; i < 10; i++) { |
| int first_opcode = insn_nodes[i].getOpcode(); |
| if(UNICODE_FONT_CHARACTER_WIDTH != 4 && first_opcode == Opcodes.SIPUSH) { |
| IntInsnNode int_insn = (IntInsnNode)insn_nodes[i]; |
| if(int_insn.operand != 160) continue; |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.IF_ICMPNE) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.LDC) continue; |
| LdcInsnNode ldc_insn = (LdcInsnNode)insn_nodes[i + 2]; |
| if(!(ldc_insn.cst instanceof Float)) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.IRETURN) continue; |
| ldc_insn.cst = Float.valueOf(UNICODE_FONT_CHARACTER_WIDTH); |
| i += 3; |
| continue; |
| } |
| if(first_opcode != Opcodes.BIPUSH) continue; |
| IntInsnNode int_insn = (IntInsnNode)insn_nodes[i]; |
| if(int_insn.operand != 32) continue; |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.IF_ICMPNE) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.LDC) continue; |
| LdcInsnNode ldc_insn = (LdcInsnNode)insn_nodes[i + 2]; |
| if(!(ldc_insn.cst instanceof Float)) continue; |
| InsnList insn_list = create_space_width_insn_list(); |
| method.instructions.insertBefore(ldc_insn, insn_list); |
| if(UNICODE_FONT_CHARACTER_WIDTH != 4) { |
| ldc_insn.cst = Float.valueOf(UNICODE_FONT_CHARACTER_WIDTH); |
| } |
| new_draw_space_transformed = true; |
| break; |
| } |
| } else if(!draw_unicode_transformed && ((!new_draw_space_transformed && method.name.equals("a")) || (!old_draw_space_transformed && method.name.equals("b")) || method.name.equals("func_78277_a")) && (method.access == Opcodes.ACC_PROTECTED || method.access == Opcodes.ACC_PRIVATE)) { |
| // Draw charactor with unicode font |
| int x_offset_var_after_insn_i = -1; |
| AbstractInsnNode[] insn_nodes = method.instructions.toArray(); |
| for(int i = 0; i < insn_nodes.length - 7; i++) { |
| int first_opcode = insn_nodes[i].getOpcode(); |
| if(first_opcode == Opcodes.ILOAD) { |
| VarInsnNode last_pos_var_insn = (VarInsnNode)insn_nodes[i]; |
| if(last_pos_var_insn.var != 5 && last_pos_var_insn.var != 6) continue; |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.ICONST_1) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.IADD) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.I2F) continue; |
| if(insn_nodes[i + 4].getOpcode() != Opcodes.FSTORE) continue; |
| VarInsnNode end_pos_var_insn = (VarInsnNode)insn_nodes[i + 4]; |
| if(end_pos_var_insn.var != 7 && end_pos_var_insn.var != 8) continue; |
| InsnList insn_list = new InsnList(); |
| insn_list.add(new VarInsnNode(Opcodes.ILOAD, last_pos_var_insn.var)); |
| insn_list.add(new IntInsnNode(Opcodes.BIPUSH, 8)); |
| LabelNode label1 = new LabelNode(); |
| insn_list.add(new JumpInsnNode(Opcodes.IF_ICMPGE, label1)); |
| if(UNICODE_FONT_CHARACTER_WIDTH == 4) { |
| insn_list.add(new InsnNode(Opcodes.ICONST_4)); |
| } else { |
| //insn_list.add(new InsnNode(Opcodes.ICONST_5)); |
| insn_list.add(new IntInsnNode(Opcodes.BIPUSH, UNICODE_FONT_CHARACTER_WIDTH)); |
| } |
| LabelNode label2 = new LabelNode(); |
| insn_list.add(new JumpInsnNode(Opcodes.GOTO, label2)); |
| insn_list.add(label1); |
| insn_list.add(new IntInsnNode(Opcodes.BIPUSH, UNICODE_FONT_CHARACTER_WIDTH * 2)); |
| insn_list.add(label2); |
| insn_list.add(new VarInsnNode(Opcodes.ISTORE, 5)); |
| method.instructions.insert(end_pos_var_insn, insn_list); |
| i += 4; |
| } else if(first_opcode == Opcodes.LDC) { |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.FSUB) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.FSTORE) continue; |
| VarInsnNode var_insn = (VarInsnNode)insn_nodes[i + 2]; |
| if(var_insn.var != 10 && var_insn.var != 11) continue; |
| InsnList insn_list = new InsnList(); |
| insn_list.add(new VarInsnNode(Opcodes.ILOAD, 5)); |
| insn_list.add(new InsnNode(Opcodes.I2F)); |
| insn_list.add(new VarInsnNode(Opcodes.FLOAD, var_insn.var)); |
| insn_list.add(new InsnNode(Opcodes.FCONST_2)); |
| insn_list.add(new InsnNode(Opcodes.FDIV)); |
| insn_list.add(new InsnNode(Opcodes.FSUB)); |
| insn_list.add(new LdcInsnNode(Float.valueOf(0.01F))); // Needed for some platforms |
| insn_list.add(new InsnNode(Opcodes.FSUB)); |
| insn_list.add(new VarInsnNode(Opcodes.FSTORE, 4)); |
| insn_list.add(new VarInsnNode(Opcodes.FLOAD, 4)); |
| insn_list.add(new InsnNode(Opcodes.FCONST_0)); |
| insn_list.add(new InsnNode(Opcodes.FCMPG)); |
| LabelNode label1 = new LabelNode(); |
| insn_list.add(new JumpInsnNode(Opcodes.IFGE, label1)); |
| insn_list.add(new InsnNode(Opcodes.FCONST_0)); |
| LabelNode label2 = new LabelNode(); |
| insn_list.add(new JumpInsnNode(Opcodes.GOTO, label2)); |
| insn_list.add(label1); |
| insn_list.add(new VarInsnNode(Opcodes.FLOAD, 4)); |
| insn_list.add(new InsnNode(Opcodes.FCONST_2)); |
| insn_list.add(new InsnNode(Opcodes.FDIV)); |
| insn_list.add(label2); |
| insn_list.add(new VarInsnNode(Opcodes.FSTORE, 4)); |
| method.instructions.insert(var_insn, insn_list); |
| method.instructions.remove(insn_nodes[i]); |
| method.instructions.remove(insn_nodes[i + 1]); |
| x_offset_var_after_insn_i = i += 2; |
| } else if(x_offset_var_after_insn_i > 0 && i > x_offset_var_after_insn_i && first_opcode == Opcodes.ALOAD) { |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.GETFIELD) continue; |
| FieldInsnNode getfield_insn = (FieldInsnNode)insn_nodes[i + 1]; |
| if(!getfield_insn.desc.equals("F")) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.FLOAD) continue; |
| InsnList insn_list = new InsnList(); |
| insn_list.add(new VarInsnNode(Opcodes.FLOAD, 4)); |
| insn_list.add(new InsnNode(Opcodes.FADD)); |
| method.instructions.insert(getfield_insn, insn_list); |
| i += 2; |
| } else if(first_opcode == Opcodes.FLOAD) { |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.FLOAD) continue; |
| VarInsnNode var_insn_1 = (VarInsnNode)insn_nodes[i]; |
| VarInsnNode var_insn_2 = (VarInsnNode)insn_nodes[i + 1]; |
| if((var_insn_1.var != 7 || var_insn_2.var != 6) && (var_insn_1.var != 8 || var_insn_2.var != 7)) { |
| continue; |
| } |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.FSUB) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.FCONST_2) continue; |
| if(insn_nodes[i + 4].getOpcode() != Opcodes.FDIV) continue; |
| if(insn_nodes[i + 5].getOpcode() != Opcodes.FCONST_1) continue; |
| if(insn_nodes[i + 6].getOpcode() != Opcodes.FADD) continue; |
| if(insn_nodes[i + 7].getOpcode() != Opcodes.FRETURN) continue; |
| var_insn_1.setOpcode(Opcodes.ILOAD); |
| var_insn_1.var = 5; |
| method.instructions.insert(var_insn_1, new InsnNode(Opcodes.I2F)); |
| method.instructions.remove(insn_nodes[i + 1]); |
| method.instructions.remove(insn_nodes[i + 2]); |
| method.instructions.remove(insn_nodes[i + 3]); |
| method.instructions.remove(insn_nodes[i + 4]); |
| method.instructions.remove(insn_nodes[i + 5]); |
| method.instructions.remove(insn_nodes[i + 6]); |
| draw_unicode_transformed = true; |
| break; |
| } |
| } |
| } |
| } else if(method.desc.equals("(C)I") && (method.name.equals("a") || method.name.equals("func_78263_a")) && method.access == Opcodes.ACC_PUBLIC) { |
| // Get character width |
| AbstractInsnNode[] insn_nodes = method.instructions.toArray(); |
| for(int i = 0; i < insn_nodes.length - 4; i++) { |
| int first_opcode = insn_nodes[i].getOpcode(); |
| if(first_opcode == Opcodes.ALOAD) { |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.GETFIELD) continue; |
| FieldInsnNode getfield_insn = (FieldInsnNode)insn_nodes[i + 1]; |
| if(!getfield_insn.desc.equals("[I")) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.ILOAD) continue; |
| VarInsnNode var_insn = (VarInsnNode)insn_nodes[i + 2]; |
| if(var_insn.var != 2) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.IALOAD) continue; |
| if(insn_nodes[i + 4].getOpcode() != Opcodes.IRETURN) continue; |
| method.instructions.insert(getfield_insn, new IntInsnNode(Opcodes.BIPUSH, 6)); |
| method.instructions.remove(insn_nodes[i]); |
| method.instructions.remove(getfield_insn); |
| method.instructions.remove(var_insn); |
| method.instructions.remove(insn_nodes[i + 3]); |
| i += 4; |
| } else if(i < insn_nodes.length - 14 && first_opcode == Opcodes.BIPUSH) { |
| IntInsnNode int_insn = (IntInsnNode)insn_nodes[i]; |
| if(int_insn.operand == 32) { |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.IF_ICMPNE) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.ICONST_4) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.IRETURN) continue; |
| InsnList insn_list = new InsnList(); |
| insn_list.add(new VarInsnNode(Opcodes.ALOAD, 0)); |
| insn_list.add(new FieldInsnNode(Opcodes.GETFIELD, "net/minecraft/client/gui/FontRenderer", "field_78293_l", "Z")); |
| LabelNode label = new LabelNode(); |
| insn_list.add(new JumpInsnNode(Opcodes.IFNE, label)); |
| insn_list.add(new IntInsnNode(Opcodes.BIPUSH, 6)); |
| insn_list.add(new InsnNode(Opcodes.IRETURN)); |
| insn_list.add(label); |
| if(UNICODE_FONT_CHARACTER_WIDTH != 4) { |
| //insn_list.add(new InsnNode(Opcodes.ICONST_5)); |
| insn_list.add(new IntInsnNode(Opcodes.BIPUSH, UNICODE_FONT_CHARACTER_WIDTH)); |
| } |
| method.instructions.insert(insn_nodes[i + 1], insn_list); |
| if(UNICODE_FONT_CHARACTER_WIDTH != 4) { |
| method.instructions.remove(insn_nodes[i + 2]); |
| } |
| i += 3; |
| } else if(int_insn.operand == 15) { |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.ISTORE) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.ICONST_0) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.ISTORE) continue; |
| if(insn_nodes[i + 4].getType() != AbstractInsnNode.LABEL) continue; |
| if(insn_nodes[i + 5].getType() != AbstractInsnNode.FRAME) continue; |
| if(insn_nodes[i + 6].getOpcode() != Opcodes.IINC) continue; |
| if(insn_nodes[i + 7].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 8].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 9].getOpcode() != Opcodes.ISUB) continue; |
| if(insn_nodes[i + 10].getOpcode() != Opcodes.ICONST_2) continue; |
| if(insn_nodes[i + 11].getOpcode() != Opcodes.IDIV) continue; |
| if(insn_nodes[i + 12].getOpcode() != Opcodes.ICONST_1) continue; |
| if(insn_nodes[i + 13].getOpcode() != Opcodes.IADD) continue; |
| if(insn_nodes[i + 14].getOpcode() != Opcodes.IRETURN) continue; |
| int_insn.operand = UNICODE_FONT_CHARACTER_WIDTH * 2; |
| method.instructions.insert(int_insn, new InsnNode(Opcodes.IRETURN)); |
| method.instructions.insert(insn_nodes[i + 4], new IntInsnNode(Opcodes.BIPUSH, UNICODE_FONT_CHARACTER_WIDTH)); |
| method.instructions.remove(insn_nodes[i + 1]); |
| method.instructions.remove(insn_nodes[i + 2]); |
| method.instructions.remove(insn_nodes[i + 3]); |
| method.instructions.remove(insn_nodes[i + 5]); |
| method.instructions.remove(insn_nodes[i + 6]); |
| method.instructions.remove(insn_nodes[i + 7]); |
| method.instructions.remove(insn_nodes[i + 8]); |
| method.instructions.remove(insn_nodes[i + 9]); |
| method.instructions.remove(insn_nodes[i + 10]); |
| method.instructions.remove(insn_nodes[i + 11]); |
| method.instructions.remove(insn_nodes[i + 12]); |
| method.instructions.remove(insn_nodes[i + 13]); |
| break; |
| } |
| } else if(i < insn_nodes.length - 9 && first_opcode == Opcodes.ISTORE) { |
| VarInsnNode var_insn = (VarInsnNode)insn_nodes[i]; |
| if(var_insn.var != 4 && var_insn.var != 5) continue; |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.IINC) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.ILOAD) continue; |
| if(insn_nodes[i + 4].getOpcode() != Opcodes.ISUB) continue; |
| if(insn_nodes[i + 5].getOpcode() != Opcodes.ICONST_2) continue; |
| if(insn_nodes[i + 6].getOpcode() != Opcodes.IDIV) continue; |
| if(insn_nodes[i + 7].getOpcode() != Opcodes.ICONST_1) continue; |
| if(insn_nodes[i + 8].getOpcode() != Opcodes.IADD) continue; |
| if(insn_nodes[i + 9].getOpcode() != Opcodes.IRETURN) continue; |
| InsnList insn_list = new InsnList(); |
| insn_list.add(new IntInsnNode(Opcodes.BIPUSH, 8)); |
| LabelNode label = new LabelNode(); |
| insn_list.add(new JumpInsnNode(Opcodes.IF_ICMPGE, label)); |
| insn_list.add(new IntInsnNode(Opcodes.BIPUSH, UNICODE_FONT_CHARACTER_WIDTH)); |
| insn_list.add(new InsnNode(Opcodes.IRETURN)); |
| insn_list.add(label); |
| insn_list.add(new IntInsnNode(Opcodes.BIPUSH, UNICODE_FONT_CHARACTER_WIDTH * 2)); |
| method.instructions.insert(var_insn, insn_list); |
| method.instructions.remove(var_insn); |
| method.instructions.remove(insn_nodes[i + 1]); |
| method.instructions.remove(insn_nodes[i + 2]); |
| method.instructions.remove(insn_nodes[i + 3]); |
| method.instructions.remove(insn_nodes[i + 4]); |
| method.instructions.remove(insn_nodes[i + 5]); |
| method.instructions.remove(insn_nodes[i + 6]); |
| method.instructions.remove(insn_nodes[i + 7]); |
| method.instructions.remove(insn_nodes[i + 8]); |
| break; |
| } else if(UNICODE_FONT_CHARACTER_WIDTH != 4 && first_opcode == Opcodes.SIPUSH) { |
| IntInsnNode int_insn = (IntInsnNode)insn_nodes[i]; |
| if(int_insn.operand != 160) continue; |
| if(insn_nodes[i + 1].getOpcode() != Opcodes.IF_ICMPNE) continue; |
| if(insn_nodes[i + 2].getOpcode() != Opcodes.ICONST_4) continue; |
| if(insn_nodes[i + 3].getOpcode() != Opcodes.IRETURN) continue; |
| method.instructions.insert(insn_nodes[i + 2], new IntInsnNode(Opcodes.BIPUSH, UNICODE_FONT_CHARACTER_WIDTH)); |
| method.instructions.remove(insn_nodes[i + 2]); |
| i += 3; |
| } |
| } |
| } |
| } |
| ClassWriter writer = new ClassWriter(0); |
| class_node.accept(writer); |
| return writer.toByteArray(); |
| } |
| } |