public CodeLine ReadCodeLine() { CodeLine code = new CodeLine(current_line, (int)fs.Position); UInt16 code_len = br.ReadUInt16(); int code_offset = 0; //byte[] bytes = ReadCodeBytes(); code.opcode_index = br.ReadByte(); code_offset++; if (!opcode_dict.ContainsKey(code.opcode_index)) { throw new Exception("未知的opcode!"); } code.opcode = opcode_dict[code.opcode_index].opcode; CodeInfo info = new CodeInfo(br.ReadByte()); code_offset++; info.data = new UInt16[info.count]; for (int i = 0; i < info.count; i++) { info.data[i] = br.ReadUInt16(); code_offset += 2; } code.info = info; // 参数类型列表 code.param_types = opcode_dict[code.opcode_index].param.ToArray(); // 参数数据 code.param_datas = new List <ParamData>(ReadParamData(code.param_types, code_len, ref code_offset)); while (code_offset + 1 < code_len) { byte[] temp = br.ReadBytes(2); code_offset += 2; code.param_datas.Add(new ParamData(Type.Byte2, temp, ScriptUtil.Byte2Hex(temp))); } if (code_offset < code_len) { byte temp = br.ReadByte(); code_offset++; code.param_datas.Add(new ParamData(Type.Byte, temp, ScriptUtil.Byte2Hex(temp))); } current_line++; return(code); }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } if (value.GetType().Name == "Byte[]") { byte[] bytes = ((byte[])value); if (bytes.Length == 0) { writer.WriteNull(); return; } writer.WriteValue(ScriptUtil.Byte2Hex(bytes, false, true)); } else { writer.WriteValue(value); } }
public ScriptOpcodeGuide(string opcode = "", int version = 3) { if (opcode == "") { scriptVersion = version; for (int i = 0; i < 128; i++) { bytesToOpcodeDict.Add((byte)i, new ScriptOpcode((byte)i, "OPCODE_" + ScriptUtil.Byte2Hex((byte)i))); } Console.WriteLine("无opcode文件,创建默认opcode文件"); } else if (File.Exists(opcode)) { string[] dic; dic = File.ReadAllLines(opcode); bytesToOpcodeDict.Clear(); if (dic.Length > 0) { if (dic[0].Trim() == ";Ver3") { scriptVersion = 3; } else if (dic[0].Trim() == ";Ver2") { scriptVersion = 2; } } int i = 0; foreach (string line in dic) { if (line.TrimStart()[0] == ';') { continue; } bytesToOpcodeDict.Add((byte)i, new ScriptOpcode((byte)i, line.Replace("\r", ""))); i++; } if (bytesToOpcodeDict.Count > 0) { hasOpcode = true; } Console.WriteLine("已加载opcode文件:{0}", Path.GetFileName(opcode)); } }
public ParamData[] ReadParamData(ref BinaryReader tbr, List <ParamType> param) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); List <string> retn = new List <string>(); List <ParamData> datas = new List <ParamData>(); int count = 0; int curr_pos = (int)tbr.BaseStream.Position; int tbr_len = (int)tbr.BaseStream.Length; bool nullable_skip = false; string data_str; foreach (var value in param) { DataType type = value.type; count++; curr_pos = (int)tbr.BaseStream.Position; switch (type) { case DataType.Byte: case DataType.Byte2: case DataType.Byte3: case DataType.Byte4: { var data_bytes = tbr.ReadBytes((int)type); data_str = ScriptUtil.Byte2Hex(data_bytes); datas.Add(new ParamData(type, data_bytes, data_str)); break; } case DataType.UInt16: if (value.nullable && curr_pos + 2 >= tbr_len) { nullable_skip = true; break; } var data_uint16 = tbr.ReadUInt16(); data_str = data_uint16.ToString(); datas.Add(new ParamData(DataType.UInt16, data_uint16, data_str)); break; case DataType.Int16: if (value.nullable && curr_pos + 2 > tbr_len) { nullable_skip = true; break; } var data_int16 = tbr.ReadInt16(); data_str = data_int16.ToString(); datas.Add(new ParamData(DataType.Int16, data_int16, data_str)); break; case DataType.UInt32: if (value.nullable && curr_pos + 4 > tbr_len) { nullable_skip = true; break; } var data_uint32 = tbr.ReadUInt32(); data_str = data_uint32.ToString(); datas.Add(new ParamData(DataType.UInt32, data_uint32, data_str)); break; case DataType.Int32: if (value.nullable && curr_pos + 4 > tbr_len) { nullable_skip = true; break; } var data_int32 = tbr.ReadInt32(); data_str = data_int32.ToString(); datas.Add(new ParamData(DataType.Int32, data_int32, data_str)); break; case DataType.StringUnicode: case DataType.StringSJIS: case DataType.StringUTF8: { if (type == DataType.StringUnicode) { data_str = Encoding.Unicode.GetString(ReadStringDoubleEnd(ref tbr)); datas.Add(new ParamData(DataType.StringUnicode, data_str, data_str)); } else if (type == DataType.StringSJIS) { data_str = Encoding.GetEncoding("Shift-Jis").GetString(ReadStringSingleEnd(ref tbr)); datas.Add(new ParamData(DataType.StringSJIS, data_str, data_str)); } else if (type == DataType.StringUTF8) { data_str = Encoding.UTF8.GetString(ReadStringSingleEnd(ref tbr)); datas.Add(new ParamData(DataType.StringUTF8, data_str, data_str)); } break; } case DataType.LenStringUnicode: case DataType.LenStringSJIS: { if (value.nullable && curr_pos + 2 > tbr_len) { nullable_skip = true; break; } int len = tbr.ReadUInt16(); if (type == DataType.LenStringUnicode) { data_str = Encoding.Unicode.GetString(tbr.ReadBytes(len * 2)); datas.Add(new ParamData(DataType.LenStringUnicode, data_str, data_str)); } else if (type == DataType.LenStringSJIS) { data_str = Encoding.GetEncoding("Shift-Jis").GetString(tbr.ReadBytes(len * 2)); datas.Add(new ParamData(DataType.LenStringSJIS, data_str, data_str)); } break; } case DataType.Position: if (value.nullable && curr_pos + 4 > tbr_len) { nullable_skip = true; break; } uint pos = tbr.ReadUInt32(); if (code_position.ContainsKey(pos)) { datas.Add(new ParamData(DataType.Position, pos, code_position[pos].ToString())); } else { throw new Exception("错误的跳转位置: " + pos + "!"); } break; default: break; } } return(datas.ToArray()); }
private byte[] CompileCode(string code, long position) { code += " "; MemoryStream ms = new MemoryStream(); BinaryWriter mbw = new BinaryWriter(ms); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); int i = 0; while (i + 4 <= code.Length && code.Substring(i, 4) == " ") { i += 4; } int len_pos = (int)ms.Position; mbw.Write(new byte[2]);//长度填充 string token = ""; bool str = false; for (; i < code.Length; i++) { if (code[i] == '\"') { str = !str; } if (code[i] == ' ' && !str) { switch (token[0]) { case '<': int goto_line = Convert.ToInt32(token.Substring(1, token.Length - 2)); goto_position.Add((uint)(position + ms.Position), goto_line); mbw.Write(BitConverter.GetBytes((uint)0)); break; case '[': //byte mbw.Write(ScriptUtil.Hex2Byte(token.Substring(1, token.Length - 2))); break; case '(': //uint16 mbw.Write(BitConverter.GetBytes(Convert.ToUInt16(token.Substring(1, token.Length - 2)))); break; case '{': //uint32 mbw.Write(BitConverter.GetBytes(Convert.ToUInt32(token.Substring(1, token.Length - 2)))); break; case '$': { token = token.Replace(@"\n", "\n"); token = token.Replace(@"{\n}", "\n"); // 兼容保留 string tmp = token.Substring(3, token.Length - 4); if (token[1] == 'u') //unicode string + 00 00 { mbw.Write(Encoding.Unicode.GetBytes(tmp)); mbw.Write(new byte[] { 0x00, 0x00 }); } else if (token[1] == 'j') //sjis string + 00 { mbw.Write(Encoding.GetEncoding("Shift-Jis").GetBytes(tmp)); mbw.Write((byte)0x00); } else if (token[1] == '8') //utf8 string + 00 { mbw.Write(Encoding.UTF8.GetBytes(tmp)); mbw.Write((byte)0x00); } else if (token[1] == 'c') //custom string + 00 { mbw.Write(CustomEncoding.GetBytes(tmp)); mbw.Write((byte)0x00); } break; } case '&': { token = token.Replace(@"\n", "\n"); token = token.Replace(@"{\n}", "\n"); // 兼容保留 string tmp = token.Substring(3, token.Length - 4); if (token[1] == 'u') //len + unicode string { mbw.Write(BitConverter.GetBytes((UInt16)tmp.Length)); mbw.Write(Encoding.Unicode.GetBytes(tmp)); } else if (token[1] == 'j') //len + sjis string { mbw.Write(BitConverter.GetBytes((UInt16)tmp.Length)); mbw.Write(Encoding.GetEncoding("Shift-Jis").GetBytes(tmp)); } else if (token[1] == 'c') //custom string + 00 { mbw.Write(BitConverter.GetBytes((UInt16)tmp.Length)); mbw.Write(CustomEncoding.GetBytes(tmp)); } break; } case 'u': // 兼容保留 token = token.Replace(@"{\n}", "\n"); mbw.Write(Encoding.Unicode.GetBytes(token.Substring(2, token.Length - 3))); mbw.Write(new byte[] { 0x00, 0x00 }); break; case 'j': // 兼容保留 token = token.Replace(@"{\n}", "\n"); mbw.Write(Encoding.GetEncoding("Shift-Jis").GetBytes(token.Substring(2, token.Length - 3))); mbw.Write((byte)0x00); break; case 'p': // 兼容保留 token = token.Replace(@"{\n}", "\n"); mbw.Write(BitConverter.GetBytes((UInt16)(token.Length - 3))); mbw.Write(Encoding.Unicode.GetBytes(token.Substring(2, token.Length - 3))); break; case 's': // 兼容保留 token = token.Replace(@"{\n}", "\n"); mbw.Write(BitConverter.GetBytes((UInt16)(token.Length - 3))); mbw.Write(Encoding.GetEncoding("Shift-Jis").GetBytes(token.Substring(2, token.Length - 3))); break; default: if (token[0] >= 'A' && token[0] <= 'Z') { int index_info = token.IndexOf('('); string info = ""; if (index_info > 0) { info = token.Substring(index_info); token = token.Substring(0, index_info); } if (compress_dic.ContainsKey(token)) { if (ScriptVersion == 2) { // [opcode] length/2 code // 1byte 1byte ms.Seek(len_pos, SeekOrigin.Begin); mbw.Write(compress_dic[token]); mbw.Write(new byte[1]); } else if (ScriptVersion == 2) { // length [opcode] code // 2byte 1byte mbw.Write(compress_dic[token]); } } if (index_info > 0) { if (info.Length > 2) { string[] info_split = info.Substring(1, info.Length - 2).Split(','); if (ScriptVersion == 3) { mbw.Write((byte)info_split.Length); } foreach (string str1 in info_split) { mbw.Write(BitConverter.GetBytes(Convert.ToUInt16(str1))); } } else { mbw.Write((byte)0); } } } else { throw new Exception("未知的指令或错误的数据格式:" + token); } break; } token = ""; } else { token += code[i]; } } UInt16 len = (UInt16)(ms.Position - len_pos); if (ScriptVersion == 2) { // opcode [length/2] code // 1byte 1byte ms.Seek(len_pos + 1, SeekOrigin.Begin); mbw.Write((byte)(len / 2)); } else if (ScriptVersion == 3) { // [length] opcode code // 2byte 1byte if (len % 2 != 0) { mbw.Write((byte)0x00); } ms.Seek(len_pos, SeekOrigin.Begin); mbw.Write(BitConverter.GetBytes(len)); } byte[] retn = ms.ToArray(); if (retn.Length > 0 && Program.debug) { Console.WriteLine(ScriptUtil.Byte2Hex(retn, true)); } mbw.Close(); ms.Close(); return(retn); }
private string DecompileCode(byte[] line) { if (line.Length == 0) { return(""); } MemoryStream ms = new MemoryStream(line); BinaryReader mbr = new BinaryReader(ms); string retn = ""; byte opcode_index = mbr.ReadByte(); if (!decompress_dic.ContainsKey(opcode_index)) { throw new Exception("未知的opcode!"); } else { string opcode = decompress_dic[opcode_index].opcode; int param_num = 0; byte[] param_data = null; if (ScriptVersion == 2) { mbr.ReadByte(); param_num = 1; param_data = mbr.ReadBytes(param_num * 2); } else if (ScriptVersion == 3) { param_num = mbr.ReadByte(); param_data = mbr.ReadBytes(param_num * 2); } string data = ParamDataToString(ReadParamData(ref mbr, decompress_dic[opcode_index].param)); retn = (data.Length > 0 ? " " : "") + data; while (ms.Position + 1 < ms.Length) { retn += " [" + ScriptUtil.Byte2Hex(BitConverter.GetBytes(mbr.ReadUInt16())) + "]"; } if (ms.Position < ms.Length) { retn += " [" + ScriptUtil.Byte2Hex(mbr.ReadByte()) + "]"; } param_num = param_data.Length / 2 < param_num ? param_data.Length / 2 : param_num; string info = "("; for (int i = 0; i < param_num; i++) { info += BitConverter.ToUInt16(param_data, i * 2).ToString(); if (i != param_num - 1) { info += ","; } } info += ")"; retn = opcode + info + retn; } if (retn != " " && retn != "" && Program.debug) { Console.WriteLine(retn); } mbr.Close(); ms.Close(); return(retn); }
public ParamData[] ReadParamData(ParamType[] param, int code_len, ref int code_offset) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); List <string> retn = new List <string>(); List <ParamData> datas = new List <ParamData>(); int count = 0; bool nullable_skip = false; string data_str; foreach (var value in param) { Type type = value.type; count++; var temp_pos = fs.Position; switch (type) { case Type.Byte: case Type.Byte2: case Type.Byte3: case Type.Byte4: { var data_bytes = br.ReadBytes((int)type + 1); data_str = ScriptUtil.Byte2Hex(data_bytes); datas.Add(new ParamData(type, data_bytes, data_str)); break; } case Type.UInt16: if (value.nullable && code_offset + 2 > code_len) { nullable_skip = true; break; } var data_uint16 = br.ReadUInt16(); data_str = data_uint16.ToString(); datas.Add(new ParamData(Type.UInt16, data_uint16, data_str)); break; case Type.Int16: if (value.nullable && code_offset + 2 > code_len) { nullable_skip = true; break; } var data_int16 = br.ReadInt16(); data_str = data_int16.ToString(); datas.Add(new ParamData(Type.Int16, data_int16, data_str)); break; case Type.UInt32: if (value.nullable && code_offset + 4 > code_len) { nullable_skip = true; break; } var data_uint32 = br.ReadUInt32(); data_str = data_uint32.ToString(); datas.Add(new ParamData(Type.UInt32, data_uint32, data_str)); break; case Type.Int32: if (value.nullable && code_offset + 4 > code_len) { nullable_skip = true; break; } var data_int32 = br.ReadInt32(); data_str = data_int32.ToString(); datas.Add(new ParamData(Type.Int32, data_int32, data_str)); break; case Type.StringUnicode: case Type.StringSJIS: case Type.StringUTF8: { if (type == Type.StringUnicode) { data_str = Encoding.Unicode.GetString(ReadStringDoubleEnd()); datas.Add(new ParamData(Type.StringUnicode, data_str, data_str)); } else if (type == Type.StringSJIS) { data_str = Encoding.GetEncoding("Shift-Jis").GetString(ReadStringSingleEnd()); datas.Add(new ParamData(Type.StringSJIS, data_str, data_str)); } else if (type == Type.StringUTF8) { data_str = Encoding.UTF8.GetString(ReadStringSingleEnd()); datas.Add(new ParamData(Type.StringUTF8, data_str, data_str)); } break; } case Type.LenStringUnicode: case Type.LenStringSJIS: { if (value.nullable && code_offset + 2 > code_len) { nullable_skip = true; break; } int len = br.ReadUInt16(); if (type == Type.LenStringUnicode) { data_str = Encoding.Unicode.GetString(br.ReadBytes(len * 2)); datas.Add(new ParamData(Type.LenStringUnicode, data_str, data_str)); } else if (type == Type.LenStringSJIS) { data_str = Encoding.GetEncoding("Shift-Jis").GetString(br.ReadBytes(len * 2)); datas.Add(new ParamData(Type.LenStringSJIS, data_str, data_str)); } break; } case Type.Position: if (value.nullable && code_offset + 4 > code_len) { nullable_skip = true; break; } uint pos = br.ReadUInt32(); if (code_position.ContainsKey(pos)) { datas.Add(new ParamData(Type.Position, pos, code_position[pos].ToString())); } else { throw new Exception("错误的跳转位置: " + pos + "!"); } break; default: break; } code_offset += (int)(fs.Position - temp_pos); } return(datas.ToArray()); }
/// <summary> /// 读取参数的实际值 /// </summary> /// <param name="param">类型列表</param> /// <param name="codeLength">此指令长度</param> /// <param name="codeOffset">当前位置引用</param> /// <returns></returns> private List <ParamData> ReadParamData(ParamType[] param, int codeLength, ref int codeOffset) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); List <string> retn = new List <string>(); List <ParamData> datas = new List <ParamData>(); int count = 0; bool nullableSkip = false; string dataStr = ""; foreach (var value in param) { DataType type = value.type; count++; var tempPos = fs.Position; switch (type) { case DataType.Byte: case DataType.Byte2: case DataType.Byte3: case DataType.Byte4: if (value.nullable && codeOffset + (int)type > codeLength) { nullableSkip = true; break; } var dataBytes = br.ReadBytes((int)type); dataStr = ScriptUtil.Byte2Hex(dataBytes, false, true); datas.Add(new ParamData(type, dataBytes, dataStr)); break; case DataType.UInt16: if (value.nullable && codeOffset + 2 > codeLength) { nullableSkip = true; break; } var dataUint16 = br.ReadUInt16(); dataStr = dataUint16.ToString(); datas.Add(new ParamData(type, dataUint16, dataStr)); break; case DataType.Int16: if (value.nullable && codeOffset + 2 > codeLength) { nullableSkip = true; break; } var dataInt16 = br.ReadInt16(); dataStr = dataInt16.ToString(); datas.Add(new ParamData(type, dataInt16, dataStr)); break; case DataType.UInt32: case DataType.Position: if (value.nullable && codeOffset + 4 > codeLength) { nullableSkip = true; break; } var dataUint32 = br.ReadUInt32(); dataStr = dataUint32.ToString(); datas.Add(new ParamData(type, dataUint32, dataStr)); break; case DataType.Int32: if (value.nullable && codeOffset + 4 > codeLength) { nullableSkip = true; break; } var dataInt32 = br.ReadInt32(); dataStr = dataInt32.ToString(); datas.Add(new ParamData(type, dataInt32, dataStr)); break; case DataType.StringUnicode: case DataType.StringSJIS: case DataType.StringUTF8: if (type == DataType.StringUnicode) { dataStr = Encoding.Unicode.GetString(ReadStringDoubleEnd()); } else if (type == DataType.StringSJIS) { dataStr = Encoding.GetEncoding("Shift-Jis").GetString(ReadStringSingleEnd()); } else if (type == DataType.StringUTF8) { dataStr = Encoding.UTF8.GetString(ReadStringSingleEnd()); } datas.Add(new ParamData(type, dataStr, dataStr)); break; case DataType.LenStringUnicode: case DataType.LenStringSJIS: if (value.nullable && codeOffset + 2 > codeLength) { nullableSkip = true; break; } int len = br.ReadUInt16(); if (type == DataType.LenStringUnicode) { dataStr = Encoding.Unicode.GetString(br.ReadBytes(len * 2)); } else if (type == DataType.LenStringSJIS) { dataStr = Encoding.GetEncoding("Shift-Jis").GetString(br.ReadBytes(len * 2)); } datas.Add(new ParamData(type, dataStr, dataStr)); break; default: break; } codeOffset += (int)(fs.Position - tempPos); if (codeOffset > codeLength) { throw new Exception("opcode参数数量错误! "); } } return(datas); }
private CodeLine ReadCodeLine() { CodeLine code = new CodeLine(currentLine, (int)fs.Position); if (!gotoPosLine.ContainsKey((int)fs.Position)) { // 位置 下标 gotoPosLine.Add((int)fs.Position, currentLine); } int codeLength = 0; int codeOffset = 0; if (script.version == 2) { // [xx] [xx] // opcode len code.opcodeIndex = br.ReadByte(); codeLength = br.ReadByte() * 2; codeOffset += 2; } else if (script.version == 3) { // [xx xx] [xx] // len opcode codeLength = br.ReadUInt16() - 2; code.opcodeIndex = br.ReadByte(); codeOffset++; } long savePosition = fs.Position; fs.Seek(-codeOffset, SeekOrigin.Current); code.bytes = br.ReadBytes(codeLength); fs.Seek(savePosition, SeekOrigin.Begin); if (!opcodeDict.ContainsKey(code.opcodeIndex)) { throw new Exception("未知的opcode!"); } code.opcode = opcodeDict[code.opcodeIndex].opcode; int infoCount = 0; CodeInfo info = null; if (script.version == 2) { info = new CodeInfo(0); info.count = 1; info.data = new UInt16[1]; info.data[0] = br.ReadUInt16(); //fs.Seek(-2, SeekOrigin.Current); codeOffset += 2; code.info = info; } else if (script.version == 3) { info = new CodeInfo(br.ReadByte()); codeOffset++; infoCount = info.count; // END指令info.count需要减一 if (code.opcode == "END") { infoCount--; } else if (code.opcode == "LOG" && infoCount == 7) { infoCount = 3; } while (codeLength - 2 < infoCount * 2) { infoCount--; } info.data = new UInt16[infoCount]; for (int i = 0; i < infoCount; i++) { info.data[i] = br.ReadUInt16(); codeOffset += 2; } code.info = info; } // 参数类型列表 code.paramTypes = opcodeDict[code.opcodeIndex].param.ToArray(); // 读取已知参数数据 code.paramDatas = ReadParamData(code.paramTypes, codeLength, ref codeOffset); // 处理未知参数数据 while (codeOffset + 1 < codeLength) { byte[] temp = br.ReadBytes(2); codeOffset += 2; code.paramDatas.Add(new ParamData(DataType.Byte2, temp, ScriptUtil.Byte2Hex(temp, false, true))); } if (codeOffset < codeLength) { byte[] temp = br.ReadBytes(1); codeOffset++; if (script.version == 2 && temp[0] == 0x00) { // 最后多出的单字节,若为0x00则舍弃 } else { code.paramDatas.Add(new ParamData(DataType.Byte, temp, ScriptUtil.Byte2Hex(temp, false, true))); } } // 长度非偶数,最后会有补位 if (codeLength % 2 != 0) { br.ReadByte(); } // 判断是否含跳转 foreach (var param in code.paramDatas) { if (param.type == DataType.Position) { code.isPosition = true; labelPos.Add((int)(uint)param.value); } } currentLine++; return(code); }