blob: cf83969ffeb16bbbec39b730045f710219693c32 [file] [log] [blame] [raw]
/* 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();
}
}