public OProg(byte[] data, byte[] footer, int id, int type) { this.type = type; this.data = data; this.footer = footer; this.id = id; return; u0 = BinHelper.read_U16LE(footer, 0); exitsCnt = BinHelper.read_U16LE(footer, 2); if (type == 1) { entry = exitsCnt; exitsCnt = 0; unpack(); return; } actorsCnt = BinHelper.read_U16LE(footer, 4); u6 = BinHelper.read_U16LE(footer, 6); exits = BinHelper.read_U16LE(footer, 8); actors = BinHelper.read_U16LE(footer, 0x0A); sprites = BinHelper.read_U16LE(footer, 0x0C); entry = BinHelper.read_U16LE(footer, 0x0E); if (u0 != 0 || u6 != exits) { throw new Exception("Unknown prog values"); } unpack(); }
void process() { BinaryReader rd = new BinaryReader(new FileStream(filename, FileMode.Open, FileAccess.Read)); int len = rd.ReadUInt16(); rd.BaseStream.Position = 0; data = rd.ReadBytes(len); footer = rd.ReadBytes((int)(rd.BaseStream.Length - rd.BaseStream.Position)); rd.Close(); descramble(data, 2); progcnt[0] = BinHelper.read_U16LE(footer, 0x06); progcnt[1] = BinHelper.read_U16LE(footer, 0x08); progmap = BinHelper.read_U16LE(footer, 0x0A); actorsPart.count = BinHelper.read_U16LE(footer, 0x10); actorsPart.ofs = BinHelper.read_U16LE(footer, 0x12); entry = BinHelper.read_U16LE(footer, 0x42); charmap = BinHelper.read_U16LE(footer, 0x48); graphsPart.count = BinHelper.read_U16LE(footer, 0x20); graphsPart.ofs = BinHelper.read_U16LE(footer, 0x22); if (pref == "cer") { proc_cer(); } parse(); }
void proc_cer() { musPart.count = BinHelper.read_U16LE(footer, 0x34); musPart.ofs = BinHelper.read_U16LE(footer, 0x36); int bid = 0; strings.Add(new StringBlock(bid++, 0x72C9, 0x7353, data)); strings.Add(new StringBlock(bid++, 0xC100, 0xC26E, data)); strings.Add(new StringBlock(bid++, 0xC4DD, 0xD55C, data)); }
void unpack() { int spos = 2; int slen = data.Length - spos; if (type == 0) { List <UInt16> rms = new List <UInt16>(); UInt16 rm = 0; while (rm != 0xFFFF) { rm = BinHelper.read_U16LE(data, spos); spos += 2; rms.Add(rm); } rooms = rms.ToArray(); slen = exits - spos; if (actors - exits > 0) { exit_data = new byte[actors - exits]; Array.Copy(data, exits, exit_data, 0, exit_data.Length); } if (sprites - actors > 0) { actor_data = new byte[sprites - actors]; Array.Copy(data, actors, actor_data, 0, actor_data.Length); } if (entry - sprites > 0) { sprite_data = new byte[entry - sprites]; Array.Copy(data, sprites, sprite_data, 0, sprite_data.Length); } } else { slen = entry - spos; } code = new byte[data.Length - entry]; Array.Copy(data, entry, code, 0, code.Length); int enda = spos + slen; int sid = 0; while (spos < enda) { strings.Add(new OString(sid++, data, (UInt16)spos)); spos += strings[strings.Count - 1].length + 1; } }
public static string decompile(OProg prog, string eol) { foreach (OProg.OString s in prog.strings) { s.state = 0; } int pos = 0; byte[] data = prog.code; string res = ""; while (pos < data.Length) { byte op = data[pos++]; if (op >= Opcodes.OPCODE_SIZE) { throw new Exception(string.Format("Bad Opcode {0:X2} @ {1:X4}", op, pos)); } foreach (Opcodes.opcode b in Opcodes.opcodes) { if (b.op == op) { string s = b.name + "("; for (int i = 0; i < b.prms; i++) { byte ptp = data[pos++]; s += getParam(ptp, BinHelper.read_U16LE(data, pos), prog); pos += 2; if (i < b.prms - 1) { s += ","; } } s += ")" + eol; res += s; break; } } } return(res); }
public OString(int id, byte[] data, UInt16 ofs) { this.id = id; this.ofs = ofs; int len = 0; byte b = 0; string s = ""; while ((b = data[ofs + len]) != 0) { len++; switch (b) { case RETURN: s += "\\r"; break; case SLASH: s += "\\\\"; break; case COUNT_SP_TERM: s += "\\[t]"; break; case STRING_MOVE: UInt16 p1 = BinHelper.read_U16LE(data, ofs + len); UInt16 p2 = BinHelper.read_U16LE(data, ofs + len + 2); len += 4; s += String.Format("\\[r{0:X4},{1:X4}]", p1, p2); break; case STRING_MENU_OPTION: List <byte> nm = new List <byte>(); while (data[ofs + len] != 0) { nm.Add(data[ofs + len]); len++; } UInt16 p4 = BinHelper.read_U16LE(data, ofs + len); len += 2; s += String.Format("\\[o{0:s},{1:X4}]", new String(Encoding.Unicode.GetChars( Encoding.Convert(Encoding.GetEncoding(866), Encoding.Unicode, nm.ToArray()) )), p4); break; case COUNT_SP0: s += "\\[n]"; break; case COUNT_SP1: s += "\\[s]"; break; case CENTER: s += "\\[m]"; break; case WAIT: s += "\\[w]"; break; case SHARP: s += "!"; break; case ADVANCE: s += String.Format("\\[c{0:X2}]", data[ofs + len]); len++; break; case DEF_COLOUR: s += "\\[d]"; break; case SET_COLOUR: s += String.Format("\\[c{0:X2}]", data[ofs + len]); len++; break; case GLOBAL_WORD: UInt16 p3 = BinHelper.read_U16LE(data, ofs + len); len += 2; s += String.Format("\\[g{0:X4}]", p3); break; default: if (b < 0x20 || (b > 0xAF && (b < 0xE0 || b > 0xF1))) { s += String.Format("\\[x{0:X2}]", b); } else { s += new String(Encoding.Unicode.GetChars( Encoding.Convert(Encoding.GetEncoding(866), Encoding.Unicode, new byte[] { b }) )); } break; } } this.data = s; length = len; }