changeset 29:d229cce98f50

* no more (or, at least, less) duplicate code between scn2kdump and the rest
author thib
date Fri, 06 Mar 2009 20:02:26 +0000
parents f1f22bfc4496
children 3fe3e5f184b5
files scn2k/scn2k.h scn2k/scn2k_cmd.cc scn2k/scn2kdump.cc
diffstat 3 files changed, 23 insertions(+), 880 deletions(-) [+]
line wrap: on
line diff
--- a/scn2k/scn2k.h
+++ b/scn2k/scn2k.h
@@ -172,6 +172,7 @@ public:
 	void SetStrvar(VarInfo info, const std::string& s);
 	bool IsError() { return errorflag;}
 	void clear(void);
+	virtual const char * CmdDescr(int, int, int, int) { return "Not supported"; }
 	Cmd(const Flags& f, int _sys_ver) : flags(f), system_version(_sys_ver) { cmd_type = CMD_NOP; argc = 0; errorflag = false; cmdstr[0] = 0; strend = 0; pos = -1;}
 	void read(const CmdSimplified& cmd);
 	void write(CmdSimplified& cmd, char*& args_buffer) const;
--- a/scn2k/scn2k_cmd.cc
+++ b/scn2k/scn2k_cmd.cc
@@ -938,7 +938,7 @@ int Cmd::GetArgs(const char*& d) {
 	int i; for (i=0; i<100 ; i++) {
 		/* number, variable, string の種別なく値を得る */
 		if (*d == 0x61) { // よくわからない(智代アフター)
-			dprintf("*%d*",d[1]);
+			dprintf("@%d",d[1]);
 			d += 2;
 			if (*d == 0x28) {
 				dprintf("{");
@@ -1237,7 +1237,7 @@ void Cmd::GetCmd(Flags& flags_orig, cons
 		d += 8;
 		/* verbose */
 			// dprintf(" 0x23 - cmd %02x-%02x:%04x:%02x[%2d] \n",cmd1,cmd2,cmd3,cmd4,argc);
-			sprintf(cmdstr, "%02x-%02x:%04x:%02x",cmd1,cmd2,cmd3,cmd4);
+			sprintf(cmdstr, "%02x-%02x:%04x:%02x  : %s",cmd1,cmd2,cmd3,cmd4, CmdDescr(cmd1,cmd2,cmd3,cmd4));
 		/* 引数を得る */
 		/* 特殊引数のもの */
 		int is_special = 0;
@@ -1295,7 +1295,7 @@ void Cmd::GetCmd(Flags& flags_orig, cons
 retry:
 		/* 一般引数のもの */
 		if (!is_special) {
-			dprintf(" 0x23 - cmd %02x-%02x:%04x:%02x[%2d] \n",cmd1,cmd2,cmd3,cmd4,argc);
+			dprintf(" 0x23 - cmd %02x-%02x:%04x:%02x[%2d]  : %s\n",cmd1,cmd2,cmd3,cmd4,argc,CmdDescr(cmd1,cmd2,cmd3,cmd4));
 			dprintf("\t");
 			if (cmd1 == 1 && cmd2 == 0x22 && (cmd3 == 0xc1c || cmd3 == 0x835)) GetArgsSpecial(3, d);
 			else if (cmd1 == 1 && cmd2 == 0x0b && cmd3 == 0x65) GetArgsSpecial(0, d);
--- a/scn2k/scn2kdump.cc
+++ b/scn2k/scn2kdump.cc
@@ -31,278 +31,26 @@ using namespace std;
 #include"system/file.h"
 #include"system/file_impl.h"
 
-/* 注意点: @@@ で表記 */
-
-struct VarInfo {
-#define TYPE_VARSTR 18
-#define TYPE_VARMAX 7
-#define TYPE_STR 58
-#define TYPE_VAL 68
-#define TYPE_SYS 0xc8
-	int type;
-	int number;
-	int value;
-	VarInfo() { type = TYPE_VAL; value = 0;}
-	VarInfo(int n) { type = TYPE_VAL; value = n;}
-	VarInfo(const VarInfo& i) { type = i.type; number = i.number; value = i.value;}
-};
-class Flags {
-/* flag:
-**  type 0-5 : ローカル整数、各2000個
-**  type 6, 25 : グローバル整数、2000個
-**	type 12 : グローバル文字列、2000個 (今は無視しても良いが)
-**	type 18 : ローカル文字列、2000個
-**	type 25: システム変数(マウス座標など?) 1000 個?
-**  type 26-32, 51 : 1-bit access to 0-6, 25
-**  type 52-58, 77 : 2-bit access to 0-6, 25
-**  type 78-84, 103 : 4-bit access to 0-6, 25
-**  type 104-110, 129 : 8-bit access to 0-6, 25
-*/
-	typedef unsigned int uint;
-	int sys;
-	int var[8][2000];
-	string str[2000];
-public:
-	int operator () () const;
-	int operator () (VarInfo info) const;
-	void Str(unsigned int number, char* buf, int sz) const;
-
-	bool IsInt(int type) const;
-	int MaxIndex(int type) const;
-
-	void Set(VarInfo info, int value);
- 	int Get(int type, int number) const;
-	void SetSys(int value);
-	void SetStr(unsigned int number, string val);
-};
-
-bool Flags::IsInt(int type) const {
-	int v = type % 26;
-	return v >= 0 && v < 7 || v == 25;
-}
-
-int Flags::MaxIndex(int type) const {
-	switch (type / 26) {
-		case 1:
-			return 63999;
-		case 2:
-			return 31999;
-		case 3:
-			return 15999;
-		case 4:
-			return 7999;
-		default:
-			return 1999;
-	}
-}
-
-int Flags::operator()() const {
-	return rand() % 10000;
-}
-int Flags::operator() (VarInfo info) const {
-	return Get(info.type, info.number);
-}
- int Flags::Get(int type, int number) const {
-	int index = type % 26;
-	type /= 26;
-	if (index == 25) index = 7;
-	if (index > 7 || uint(type) > 4) return 0;
-	if (type == 0) {
-		// A[]..G[], Z[] を直に読む
-		if (uint(number) >= 2000) return 0;
-		return var[index][number];
-	} else {
-		// Ab[]..G4b[], Z8b[] などを読む
-		int factor = 1 << (type - 1);
-		int eltsize = 32 / factor;
-		if (uint(number) >= (64000 / factor)) return 0;
-		return (var[index][number / eltsize] >> ((number % eltsize) * factor)) & ((1 << factor) - 1);
-	}
- }
-
-void Flags::Set(VarInfo info, int value) {
-	int type = info.type / 26;
-	int index = info.type % 26;
-	if (index == 25) index = 7;
-	if (type == 0) {
-		// A[]..G[], Z[] を直に書く
-		if (uint(info.number) >= 2000) return;
-		var[index][info.number] = value;
-	} else {
-		// Ab[]..G4b[], Z8b[] などを書く
-		int factor = 1 << (type - 1);
-		int eltsize = 32 / factor;
-		int eltmask = (1 << factor) - 1;
-		int shift = (info.number % eltsize) * factor;
-		if (uint(info.number) >= (64000 / factor)) return;
-		var[index][info.number / eltsize] =
-			(var[index][info.number / eltsize] & ~(eltmask << shift))
-		  | (value & eltmask) << shift;
-	}
-}
-
-void Flags::SetSys(int value) {
-	sys = value;
-}
-void Flags::SetStr(unsigned int number, string val) {
-	if (number >= 2000) return;
-	str[number] = val;
-}
-void Flags::Str(unsigned int number, char* buf, int sz) const {
-	if (number >= 2000) {if(sz>0) buf[0] = 0; return;}
-	const string& s = str[number];
-	int len = s.length();
-	if (sz-1 > len) sz = len;
-	s.copy(buf, sz, 0);
-	buf[sz] = 0;
-	return;
-}
-
-/* commands */
-enum Cmdtype { CMD_FLAGS, CMD_JMP, CMD_TEXT, CMD_OTHER};
-class Cmd {
-	Cmdtype cmd_type;
-	int cmd1, cmd2, cmd3, cmd4;
-	int argc;
-	bool errorflag;
-	char cmdstr[1024];
-	const Flags& flags;
-	vector<VarInfo> args;
-
-	int GetArgs(const char*& d);
-	int GetArgsSpecial(int normal_args,const char*& d);
-	void GetSelection(const char*& d);
-	int GetSwitch(const char*& d);
-	int GetSimpleSwitch(const char*& d);
-	int GetExpression(const char*& d, struct VarInfo* info = 0);
-	int GetExpressionCond(const char*& d);
-	int GetLeftToken(const char*& d, struct VarInfo& info);
-	static int GetString(const char*& d);
-	int StrVar(int number);
-	static char strtype[256];
-	static int StrType(const char* d) { return strtype[*(unsigned const char*)d];}
-	int AddStr(char* s) {
-		// 1-0a-0064 はこういうものが必要らしい
-		int start = strend;
-		while (*s) strheap[strend++] = *s++;
-		strheap[strend++] = 0;
-		return start;
-	}
-#define STRHEAP_SIZE 10000
-	static char strheap[STRHEAP_SIZE];
-	static int strend;
-	void SetError(void) { errorflag = true;}
-	static void ResetString(void) {
-		strend = 0;
-	}
-	static map<int, struct CmdDescrItem*> cmd_descr;
-	const char* CmdDescr(int cmd1, int cmd2, int cmd3, int cmd4);
-public:
-	void GetCmd(Flags& f, const char*& d);
-	bool IsError() { return errorflag;}
-	bool ClearError() { errorflag = false;}
-	Cmd(const Flags& f) : flags(f) { argc = 0; errorflag = false; cmdstr[0] = 0;}
-
-};
-
-bool debug_flag = false;
-void dprintf(const char* fmt, ...) {
-	if (debug_flag) {
-		va_list ap; va_start(ap, fmt);
-		vprintf(fmt, ap);
-		va_end(ap);
-	}
-}
+#include "scn2k.h"
 
 
 #define SCN_DUMP
 
+class CmdD : public Cmd
+{
+  public:
+    CmdD(const Flags& flags, int system_version) : Cmd(flags, system_version) {}
+    //CmdD(const Flags& f) : flags(f) { argc = 0; errorflag = false; cmdstr[0] = 0;}
+    bool ClearError() { /*errorflag = false;*/}
+    static map<int, struct CmdDescrItem*> cmd_descr;
+	const char* CmdDescr(int cmd1, int cmd2, int cmd3, int cmd4);
+};
+
 int system_version = 0;
 bool ruby_flag = false;
 bool ret_flag = false;
 bool text_flag = false;
 bool selection_flag = false;
-char Cmd::strheap[STRHEAP_SIZE];
-int Cmd::strend = 0;
-
-/* 数値 num := 0x24 0xff <int num> */
-/* 変数 var := 0x24 <uchar type> 0x5b <exp> 0x5d */
-/* 項 token := num | var | 0x28 <exp> 0x29 | <plus|minus> token */
-
-int Cmd::GetLeftToken(const char*& d, VarInfo& info) {
-	bool var_flag = true;
-	int minus_flag = 0;
-	int value = 0;
-	if (d[0] == 0x5c && (d[1] == 1 || d[1] == 0) ) {
-		if (d[1] == 1)	{dprintf("minus-"); minus_flag ^= 1;}
-		else dprintf("plus-");
-		d += 2;
-		var_flag = false;
-	}
-	if (d[0] == 0x24 && ((unsigned const char*)d)[1] == 0xff) {
-	// if ( (d[0] == 0x30 || d[0] == 0x31) && d[1] == 0x24 && ((unsigned const char*)d)[2] == 0xff) 	/* @@@ not supported; selection 内で、0x30|0x31 が付随することがある */
-		// numerical atom
-		d += 6;
-		value = read_little_endian_int(d-4);
-		dprintf("%d",value);
-		var_flag = false;
-	} else if (d[0] == 0x24 && *(unsigned char*)(d+1) == 0xc8) {
-		dprintf("V<sys>");
-		d += 2;
-		info.type = TYPE_SYS; info.number = 0;
-		value = info.value =  flags();
-	} else if (d[0] == 0x24 && d[2] == 0x5b) {
-		// 0x24,<type>,0x5b,<expr>,0x5d-terminated term
-		info.type = *(unsigned char*)(d+1);
-		d += 3;
-		dprintf("V<%d>[",info.type);
-		info.number = GetExpression(d);
-		dprintf("]");
-		if (*d == 0x5d) d++;
-		else SetError();
-		if (info.type == TYPE_VARSTR) {
-			value = 0;
-			info.value = StrVar(info.number);
-		} else {
-			value = info.value = flags(info);
-		}
-		dprintf("(=%d)",value);
-	} else SetError();
-
-	if (minus_flag) value = -value;
-	if (!var_flag) {
-		info.type = TYPE_VAL;
-		info.value = value;
-	}
-	return value;
-}
-
-static char* op_str[70] = {
-//	 0      1      2      3      4      5      6      7      8     9
-	"+",   "-",   "*",   "/",   "%",   "&",   "|",   "^",   "<<",  ">>",	// +00
-	"err.","err.","err.","err.","err.","err.","err.","err.","err.","err.",	// +10
-	"+=",  "-=",  "*=",  "/=",  "%=",  "&=",  "|=",  "^=",  "<<=", ">>=",	// +20
-	"=",   "err.","err.","err.","err.","err.","err.","err.","err.","err.",	// +30
-	"==",  "!=",  "<=",  "<",   ">=",  ">",   "err.","err.","err.","err.",	// +40
-	"err.","err.","err.","err.","err.","err.","err.","err.","err.","err.",	// +50
-	"&&",  "||",  "err.","err.","err.","err.","err.","err.","err.","err.",	// +60
-};
-
-static int op_pri_tbl[12] = {
-//	+  -  *  /  %  &  |  ^ << >>
-	1, 1, 0, 0, 0, 3, 5, 4, 2, 2, 10, 10};
-
-inline int op_pri(int op) {
-	if (op > 11) return 10;
-	return op_pri_tbl[op];
-}
-inline int op_pri_cond(int op) {
-	if (op <= 11) return op_pri_tbl[op];
-	else if (op < 50) return 7;
-	else if (op == 60) return 8;
-	else if (op == 61) return 9;
-	else return 10;
-}
 
 
 inline int eval(int v1, int op, int v2) {
@@ -329,616 +77,6 @@ inline int eval(int v1, int op, int v2) 
 	return v2;
 }
 
-/* 演算子 op := 0x5c <uchar op> */
-/* 数式 exp: [op] <token> [op <token> [...]] */
-int Cmd::GetExpression(const char*& d, VarInfo* info_ptr) {
-#define STACK_DEPTH 1024
-#define OP_LB 11
-	char op_stack[STACK_DEPTH];
-	int val_stack[STACK_DEPTH];
-	int stack_count = 0;
-	
-	// 第一項の読み込み
-	while(*d == 0x28) {
-		d++;
-		dprintf("(");
-		op_stack[stack_count++] = OP_LB;
-	}
-	VarInfo info;
-	int value = GetLeftToken(d, info);
-	
-	while(*d == 0x29 && stack_count > 0 && op_stack[stack_count-1] == OP_LB) {
-		d++;
-		dprintf(")");
-		stack_count--;
-	}
-	
-	if (*d != 0x5c && stack_count == 0) {
-		if (info_ptr) *info_ptr = info;
-		return value; // 単純なleft-termはここで終了。有効なinfo_ptrを帰す(可能性がある)
-	}
-	
-	while(*d == 0x5c) {
-		int op_type = *(unsigned char*)(d+1);
-		d += 2;
-		if (op_type < 70) dprintf("%s",op_str[op_type]);
-		else dprintf("err.");
-		if (op_type >= 10) SetError();
-		int cur_pri = op_pri(op_type);
-		while(stack_count != 0 && op_pri(op_stack[stack_count-1]) <= cur_pri) {
-			// 優先順位の高い、先行する演算を行う
-			value = eval(val_stack[stack_count-1], op_stack[stack_count-1], value);
-			stack_count--;
-		}
-		val_stack[stack_count] = value;
-		op_stack[stack_count++] = op_type;
-		while(*d == 0x28) {
-			d++;
-			dprintf("(");
-			op_stack[stack_count++] = OP_LB;
-		}
-		if (stack_count >= STACK_DEPTH) SetError();
-		value = GetLeftToken(d, info);
-
-		while (*d != 0x5c && stack_count > 0) {
-			// 未実行の演算を終わらせる
-			if (op_stack[stack_count-1] != OP_LB) {
-				value = eval(val_stack[stack_count-1], op_stack[stack_count-1], value);
-				stack_count--;
-			} else if (*d == 0x29) { /* op_stack == OP_LB */
-			// bracket 終端があれば、閉じておく
-				d++;
-				dprintf(")");
-				stack_count--;
-			} else break; // error
-		}
-	}
-	if (stack_count) SetError(); // unbalanced bracket
-	dprintf("(=%d)",value);
-	if (info_ptr) {
-		info_ptr->type = TYPE_VAL;
-		info_ptr->value = value;
-	}
-	return value;
-}
-
-// 条件分岐専用に、条件演算と算術演算の混合を検知できる専用ルーチン(本来はGetExpressionで差し支えない)
-int Cmd::GetExpressionCond(const char*& d) {
-	char op_stack[STACK_DEPTH];
-	int val_stack[STACK_DEPTH];
-	int valattr_stack[STACK_DEPTH];
-#define ATTR_VAL 0
-#define ATTR_FLAG 1
-	int stack_count = 0;
-	
-	// 第一項の読み込み
-	while(*d == 0x28) {
-		d++;
-		dprintf("(");
-		op_stack[stack_count++] = OP_LB;
-	}
-	VarInfo info;
-	int value = GetLeftToken(d, info);
-	bool valattr = ATTR_VAL;
-	
-	while(*d == 0x5c) {
-		int op_type = *(unsigned char*)(d+1);
-		d += 2;
-		if (op_type < 70) dprintf("%s",op_str[op_type]);
-		else dprintf("err.");
-		int cur_pri = op_pri_cond(op_type);
-		while(stack_count != 0 && op_pri_cond(op_stack[stack_count-1]) <= cur_pri) {
-			// 優先順位の高い、先行する演算を行う
-			if (op_stack[stack_count-1] >= 60) {
-				if (valattr_stack[stack_count-1] != ATTR_FLAG || valattr != ATTR_FLAG) SetError();
-			} else {
-				if (valattr_stack[stack_count-1] != ATTR_VAL || valattr != ATTR_VAL) SetError();
-			}
-			value = eval(val_stack[stack_count-1], op_stack[stack_count-1], value);
-			if (op_stack[stack_count-1] >= 40) valattr = ATTR_FLAG;
-			stack_count--;
-		}
-		val_stack[stack_count] = value;
-		valattr_stack[stack_count] = valattr;
-		op_stack[stack_count++] = op_type;
-		while(*d == 0x28) {
-			d++;
-			dprintf("(");
-			op_stack[stack_count++] = OP_LB;
-		}
-		if (stack_count >= STACK_DEPTH) SetError();
-		value = GetLeftToken(d, info);
-		valattr = ATTR_VAL;
-
-		while (*d != 0x5c && stack_count > 0) {
-			// 未実行の演算を終わらせる
-			if (op_stack[stack_count-1] != OP_LB) {
-				if (op_stack[stack_count-1] >= 60) {
-					if (valattr_stack[stack_count-1] != ATTR_FLAG || valattr != ATTR_FLAG) SetError();
-				} else {
-					if (valattr_stack[stack_count-1] != ATTR_VAL || valattr != ATTR_VAL) SetError();
-				}
-				value = eval(val_stack[stack_count-1], op_stack[stack_count-1], value);
-				if (op_stack[stack_count-1] >= 40) valattr = ATTR_FLAG;
-				stack_count--;
-			// bracket 終端があれば、閉じておく
-			} else if (*d == 0x29) { /* op_stack == OP_LB */
-				d++;
-				dprintf(")");
-				stack_count--;
-			} else break; // error
-		}
-	}
-	if (stack_count) SetError(); // unbalanced bracket
-	if (value) dprintf("(=true)");
-	else dprintf("(=false)");
-	return value;
-}
-
-
-/*
-str = 
-arg = 
-args = 0x28 <exp> [[0x2c] <exp> [[0x2c] <exp> [...] ]]
-*/
-
-int Cmd::GetArgs(const char*& d) {
-	if (*d != 0x28) return 0; /* 引数なし */
-	d++;
-	dprintf("args:");
-	VarInfo var;
-	int i; for (i=0; i<100 ; i++) {
-		/* number, variable, string の種別なく値を得る */
-		if (*d == 0x61) { // よくわからない(智代アフター)
-			dprintf("@%d",d[1]);
-			d += 2;
-			if (*d == 0x28) {
-				dprintf("{");
-				GetArgs(d); // (A,B,C)節が含まれることがある
-				dprintf("}");
-			} else {
-				dprintf("{}");
-			}
-		} else if (d[0] == 0x0a || d[0] == 0x40) { // よくわからない (Little Busters!)
-			int var;
-			if (system_version == 0) { var = read_little_endian_int(d+1); d += 5;}
-			else { var = read_little_endian_short(d+1); d += 3;}
-			dprintf("line %d; ",var);
-		} else if (*d == 0x24 || (*d == 0x5c && (d[1] == 1 || d[1] == 0)) || *d == 0x28) {
-			GetExpression(d, &var);
-			args.push_back(var);
-		} else if (StrType(d)) {
-			var.type = TYPE_STR;
-			var.value = GetString(d);
-			args.push_back(var);
-		} else SetError();
-		if (*d == 0x29) break;
-		if (*d == 0x2c) {d++;} // 次の arg が演算子で始まる、などがなければ存在しない
-		dprintf(",");
-	}
-	if (*d == 0x29) d++;
-	else SetError();
-	return i;
-}
-
-int Cmd::GetArgsSpecial(int normal_args,const char*& d) {
-	if (*d != 0x28) return 0; /* 引数なし */
-	d++;
-	dprintf("args:");
-	int i; for (i=0; i<normal_args; i++) {
-		/* number, variable, string の種別なく値を得る */
-		if (*d == 0x24 || (*d == 0x5c && (d[1] == 1 || d[1] == 0)) || *d == 0x28) {
-			GetExpression(d);
-		} else if (StrType(d)) {
-			GetString(d);
-		} else SetError();
-		if (*d == 0x29) break;
-		if (*d == 0x2c) {d++;} // 次の arg が演算子で始まる、などがなければ存在しない
-		dprintf(",");
-	}
-	for (i=0; i<argc ; i++) {
-		if (*d == 0x28) {
-/*
-** cmd 01-22:0c1c, 01-22:0835
-** Princess Bride のカードが落ちるアニメの場面
-** なお、_PBCARDANM* の画像はこのコマンドでのみ使われているので、特殊処理として無視することも可能
-**
-** cmd 01-04:0276, 026c, 0270
-** 複数の enum が args の数だけ続く処理。特殊処理として分離する
-*/
-dprintf("enum.<");
-			/* (...) は列挙型 or 構造体の可能性がある */
-			const char* d_orig = d;
-			int pt = args.size(); args.push_back(VarInfo(0));
-			int count = GetArgs(d);
-			args[pt] = VarInfo(count);
-dprintf(">");
-		} else if (*d == 0x61 && (d[1] >= 0x00 && d[1] <= 0x04) && d[2] == 0x28 ) {
-			/* 使われるコマンドは 01-21:004b, 01-28:0064 のいずれか(R,C,PB,LO)
-			** それらのコマンドは
-			** arg1: 画像ファイル名
-			** arg2 : Sel 番号
-			** らしく、arg3 以降が 0x61 <00-04> (a,b,c,...) となる(ダンプ上は enum と表記される)
-			** () 内の引数はさまざまで、a のみ(画像ファイル名)、
-			** a,b b=SEL?
-			** a,b,c (b,c)=座標?
-			** a,(b,c,d,e,f,g) b-g = src / dest?
-			** らしい
-			*/
-			dprintf("kasane. #%d <",d[1]);
-			d += 2;
-			int pt = args.size(); args.push_back(VarInfo(0));
-			int count = GetArgs(d);
-			args[pt] = VarInfo(count);
-			dprintf(">");
-		} else if (*d == 0x24 || (*d == 0x5c && (d[1] == 1 || d[1] == 0))) {
-			/* cmd 01-15:0028 ; 始めに 0x24 節があり、続いて 0x28 節になる */
-			VarInfo var;
-			GetExpression(d, &var);
-			args.push_back(var);
-			i--; // この引数はargc の数には入らない
-		} else SetError();
-		if (d[0] == 0x0a || d[0] == 0x40) {
-			/* cmd 01-15:0028 ; 0x28 節の後に毎回 0x0a 節が来る */
-			int var;
-			if (system_version == 0) { var = read_little_endian_int(d+1); d += 5;}
-			else { var = read_little_endian_short(d+1); d += 3;}
-			dprintf("line %d; ",var);
-		}
-		if (*d == 0x29) break;
-		if (*d == 0x2c) {d++;} // 次の arg が演算子で始まる、などがなければ存在しない
-		dprintf(",");
-	}
-	if (*d == 0x29) d++;
-	else SetError();
-	return 0;
-}
-
-/* switch
-	<exp>
-	0x7b
-		<exp> <int>
-		...
-	0x7d
-*/
-
-int Cmd::GetSwitch(const char*& d) {
-	if (*d != 0x28) {SetError(); return -1;}
-	d++;
-	dprintf("switch. ");
-	int var = GetExpression(d);
-	if (*d != 0x29) {SetError(); return -1;}
-	d++;
-	dprintf("->\n");
-	if (*d == 0x7b) {
-		d++;
-	} else SetError();
-
-	int default_jmp = -1; int jmpto = -1;
-	int i; for (i=0; i<argc; i++) {
-		dprintf("\t");
-		if (*d++ != 0x28) {SetError(); return -1;}
-		int item = -1; // default
-		if (*d != 0x29) {
-			int item = GetExpression(d);
-			if (*d++ != 0x29) {SetError(); return -1;}
-			int jmp = read_little_endian_int(d);
-			if (var == item) {
-				dprintf("(selected)");
-				jmpto = jmp;
-			}
-			dprintf(" -> %d\n", jmp);
-		} else {
-			d++;
-			default_jmp = read_little_endian_int(d);
-		}
-		d += 4;
-	}
-	if (default_jmp != -1) {
-		dprintf("default -> %d\n",default_jmp);
-		if (jmpto == -1) jmpto = default_jmp;
-	}
-	if (*d == 0x7d) {
-		d++;
-	} else SetError();
-	return jmpto;
-}
-/* simple switch
-	<exp>
-	0x7b
-		<int>
-		...
-	0x7d
-*/
-int Cmd::GetSimpleSwitch(const char*& d) {
-	if (*d != 0x28) {SetError(); return -1;}
-	d++;
-	dprintf("simple switch. ");
-	int var = GetExpression(d);
-	if (*d != 0x29) {SetError(); return -1;}
-	d++;
-	dprintf(" ->\n");
-	int jumpto = -1;
-	if (*d == 0x7b) {
-		d++;
-	} else SetError();
-	int i; for (i=0; i<argc; i++) {
-		int j = read_little_endian_int(d);
-		d += 4;
-		dprintf("\t%d -> %d\n", i+1, j);
-		if (var == i+1) jumpto = j;
-	}
-	if (*d == 0x7d) {
-		d++;
-	} else SetError();
-	return jumpto;
-}
-
-/*
-selection
-	? <exp>
-	0x7b
-		<0x0a|0x40> <ushort | uint> 
-*/
-void Cmd::GetSelection(const char*& d) {
-	dprintf("selection. ");
-	if (*d == 0x28) {
-		d++;
-		GetExpression(d);
-		if (*d != 0x29) { SetError(); return;}
-		d++;
-	}
-	if (*d == 0x7b) {
-		d++;
-		dprintf("{\n\t");
-	} else SetError();
-	int arg_count = 0;
-	while(*d != 0x7d) {
-		if (d[0] == 0x0a || d[0] == 0x40) {
-			int var;
-			if (system_version == 0) { var = read_little_endian_int(d+1); d += 5;}
-			else { var = read_little_endian_short(d+1); d += 3;}
-			dprintf("line %d; ",var);
-		} else if (d[0] == 0x2c) {
-			dprintf(":comma:");
-		} else if (d[0] == 0x28) {
-			dprintf(":cond:");
-			d++;
-			while(d[0] != 0x29) {
-				GetExpressionCond(d); // PRINT- 節でないばあい、条件表示。次は文字節、またはPRINT節のはず
-				if (IsError()) break;
-				if (*d == 0x32) { d++; dprintf("##");} // 0x32 なら、現在の条件節を表示しない
-				if (*d == 0x31) { d++; dprintf("**");} // 0x31 なら、現在の条件節を表示する(Little Busters! : 処理が正しいかは分からない)
-				dprintf(":");
-			}
-			d++;
-		} else if (StrType(d)) {
-			GetString(d);
-			arg_count++;
-			dprintf("\n\t");
-		} else if (*d == 0x23 && strncmp(d,"###PRINT",8) == 0) {
-			d += 8;
-			if (d[0] != 0x28) SetError();
-			else { // 文字変数の内容の表示
-				d++;
-				dprintf("Print.");
-				VarInfo info;
-				GetLeftToken(d, info);
-				if (d[0] != 0x29 || info.type == -1) SetError();
-				d++;
-				dprintf(";");
-			}
-		} else { SetError(); break;}
-	}
-	d++;
-	/* @@@ */
-	/* 一致しない場合があるのでコメントアウト */
-	// if (arg_count != argc) SetError();
-	dprintf("\n}\n");
-	return;
-}
-
-char* op_str3[11] = { "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>=", "="};
-void Cmd::GetCmd(Flags& flags_orig, const char*& d ) {
-	ResetString();
-
-	cmdstr[0] = 0;
-	debug_flag = true;
-	if (*d == 0x23) { /* コマンド */
-		cmd_type = CMD_OTHER;
-		cmd1 = *(unsigned const char*)(d+1);
-		cmd2 = *(unsigned const char*)(d+2);
-		cmd3 = read_little_endian_short(d+3);
-		argc = read_little_endian_short(d+5);
-		cmd4 = *(unsigned const char*)(d+7);
-		d += 8;
-		/* verbose */
-			// dprintf(" 0x23 - cmd %02x-%02x:%04x:%02x[%2d] \n",cmd1,cmd2,cmd3,cmd4,argc);
-			sprintf(cmdstr, "%02x-%02x:%04x:%02x  : %s",cmd1,cmd2,cmd3,cmd4,CmdDescr(cmd1,cmd2,cmd3,cmd4));
-		/* 引数を得る */
-		/* 特殊引数のもの */
-		int is_special = 0;
-		if (cmd1 == 0) {
-			if (cmd2 == 1) {
-				int jump_arg = -1;
-				if (cmd3 == 0 || cmd3 == 5) {
-					/* gosub / goto */
-					jump_arg =read_little_endian_int(d);
-					d += 4;
-					dprintf("\tjmp -> %d\n", jump_arg);
-					is_special = 1;
-				} else if (cmd3 == 1 || cmd3 == 2) {
-					/* conditional jump (if / unless) */
-					if (*d++ != 0x28) { SetError(); return;}
-					dprintf("\t");
-					int cond = GetExpressionCond(d);
-					if (IsError()) return;
-					if (*d++ != 0x29) { SetError(); return; }
-					int jumpto = read_little_endian_int(d);
-					d += 4;
-					dprintf("-> %d\n", jumpto);
-					if (cond) jump_arg = jumpto;
-					is_special = 1;
-				} else if (cmd3 == 4) {
-					/* switch to */
-					jump_arg = GetSwitch(d);
-					is_special = 1;
-				} else if (cmd3 == 16) {
-					dprintf("local call with paramters;\n");
-					GetArgs(d);
-					int jumpto = read_little_endian_int(d);
-					d += 4;
-					dprintf("\tjmp -> %d\n",jumpto);
-					is_special = 1;
-				} else if (cmd3 == 8 || cmd3 == 3) {
-					/* switch to */
-					jump_arg = GetSimpleSwitch(d);
-					dprintf("\tjmp -> %d\n",jump_arg);
-					is_special = 1;
-				}
-				cmd_type = CMD_OTHER;
-				args.push_back(VarInfo(jump_arg));
-			} else if (cmd2 == 2 && (cmd3 == 0 || cmd3 == 1 || cmd3 == 2 || cmd3 == 3 || cmd3 == 0x0d) ) {
-				/* selection */
-				GetSelection(d);
-				is_special = 1;
-			}
-		}
-		/* 一般引数のもの */
-		if (!is_special) {
-			dprintf(" 0x23 - cmd %02x-%02x:%04x:%02x[%2d]  : %s\n",cmd1,cmd2,cmd3,cmd4,argc,CmdDescr(cmd1,cmd2,cmd3,cmd4));
-			dprintf("\t");
-			if (cmd1 == 1 && cmd2 == 0x22 && (cmd3 == 0xc1c || cmd3 == 0x835)) GetArgsSpecial(3, d);
-			else if (cmd1 == 1 && cmd2 == 0x0b && cmd3 == 0x65) GetArgsSpecial(0, d);
-			else if (cmd1 == 1 && cmd2 == 0x15 && cmd3 == 0x28) GetArgsSpecial(0, d);
-			else if (cmd1 == 1 && cmd2 == 4 && (cmd3 == 0x26c || cmd3 == 0x26d || cmd3 == 0x270 || cmd3 == 0x276)) GetArgsSpecial(0, d);
-			else if (cmd1 == 1 && (cmd2 == 0x21 && cmd3 == 0x4b) || (cmd2 == 0x28 && cmd3 == 0x64)) GetArgsSpecial(2,d);
-			else GetArgs(d);
-			dprintf("\n");
-
-		}
-		if (cmd2 == 3 && cmd3 == 0x78 && cmd4 == 0) ruby_flag = true;
-		if (cmd2 == 3 && cmd3 == 0x11) ret_flag = true;
-	} else if (*d == 0x24) { /* 代入演算 */
-		if (d[1] == 0x12 || d[2] != 0x5b) SetError();
-		dprintf("expr: ");
-		sprintf(cmdstr, "expr");
-
-		VarInfo info;
-		int value = GetLeftToken(d, info);
-		if (d[0] != 0x5c) SetError();
-		int type = d[1];
-		if (type < 20 || type > 30) SetError();
-		else dprintf("%s",op_str[type]);
-		d += 2;
-		int value2 = GetExpression(d);
-		// 代入情報を埋め込む
-		if (type != 30) value2 = eval(value, type-20, value2);
-		cmd_type = CMD_FLAGS;
-		args.push_back(info);
-		args.push_back(value2);
-		dprintf("\n");
-	} else if (StrType(d)) { /* 文字出力 */
-		VarInfo info;
-		info.type = TYPE_STR;
-		info.value = GetString(d);
-		args.push_back(info);
-		cmd_type = CMD_TEXT;
-		text_flag = true;
-		dprintf("\n");
-	} else if (*d == 0x0a || *d == 0x40 || *d == 0x21) { /* デバッグ用データと既読フラグ */
-		cmd_type = CMD_OTHER;
-		if (*d == 0x0a) {
-			dprintf("line ");
-			d++;
-			int l;
-			if (system_version == 0) {
-				l = read_little_endian_int(d);
-				d += 4;
-			} else {
-				l = read_little_endian_short(d);
-				d += 2;
-			}
-			dprintf("%d\n", l);
-		} else { /* 0x40, 0x21 */
-			// 既読マーカーらしい。エントリーポイントとセーブポイントも使われる。
-			// RealLive 1.2.5から、0x40はセーブポイント、0x21はエントリーポイント。
-			// 1.2.5以前、どちらも0x40が使われる。
-			int kidoku_index;
-			d++;
-			if (system_version == 0) {
-				kidoku_index = read_little_endian_int(d);
-				d += 4;
-			} else {
-				kidoku_index = read_little_endian_short(d);
-				d += 2;
-			}
-			dprintf("kidoku marker %d\n", kidoku_index);
-			// text_readflagは、このkidoku_indexを使ったら良いかな。
-		}
-	} else if (*d == 0x2c) { /* ??? */
-		dprintf("commd;0x2c\n"); // conditional jump の行き先によくあるらしい(常に、かはわからない)
-		d++;
-	} else { 
-		SetError();
-	}
-	return;
-}
-
-char Cmd::strtype[256] = {
-	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +00 */
-	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +10 */
-	0,0,3,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +20 */
-	1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,1, /* +30 */
-	0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, /* +40 */
-	1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,1, /* +50 */
-	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +60 */
-	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +70 */
-	2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* +80 */
-	2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* +90 */
-	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +A0 */
-	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +B0 */
-	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +C0 */
-	0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* +D0 */
-	2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* +E0 */
-	2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,0,0  /* +F0 */
-};
-
-int Cmd::GetString(const char*& d) {
-	int retnum = -1;
-	while(1) {
-		if (*d == '\\') {
-			d++;
-			strheap[strend++] = *d++;
-		} else if (*d == '"') {
-			d++;
-			if (retnum == -1) retnum = strend;
-			while(*d != '"') strheap[strend++] = *d++;
-			d++;
-		} else if (StrType(d)) {
-			if (retnum == -1) retnum = strend;
-			int stype;
-			while( (stype = StrType(d)) ) {
-				if (stype == 3) break; // 文中に '"' が現れた場合
-				strheap[strend++] = *d++;
-				if (stype == 2) strheap[strend++] = *d++;
-			}
-		} else break;
-	}
-	if (retnum != -1) strheap[strend++] = 0;
-	dprintf("\"%s\"", strheap + retnum);
-	if (strend >= STRHEAP_SIZE) {
-		dprintf("Error: string heap overflow\n");
-	}
-	return retnum;
-}
-
-int Cmd::StrVar(int var_num) {
-	int retnum = strend;
-	flags.Str(var_num, strheap+strend, STRHEAP_SIZE-strend);
-	strend += strlen(strheap+strend)+1;
-	return retnum;
-}
 
 void usage(void) {
 	fprintf(stderr,"usage : scn2kdump [inputfile] [outputfile]\n");
@@ -946,8 +84,12 @@ void usage(void) {
 	fprintf(stderr,"  outputfile: seen.txt_out(default)\n");
 	exit(-1);
 }
+
+extern int debug_flag;
+
 int main(int argc, char** argv) {
 	/* determine file names */
+	debug_flag = true;
 	bool verbose = false;
 	char* inname = "seen.txt";
 	char* outname = 0;
@@ -1011,7 +153,7 @@ int main(int argc, char** argv) {
 		/* 最初から最後までコマンド取得 -> 出力を繰り返す */
 		while(dcur<dend) {
 			const char* dprev = dcur;
-			Cmd cmd(flags); cmd.ClearError();
+			CmdD cmd(flags, system_version); cmd.ClearError();
 
 			/* end? */
 			if (*dcur == -1) {
@@ -1123,7 +265,7 @@ CmdDescrItem cmd_descr_orig[] = {
 	{0,0,0x01,0x04,0xcc, "ShowMouseCursor"},
 	{0,0,0x01,0x04,0xcd, "HideMouseCursor"},
 	{0,0,0x01,0x04,0xcf, "SetCursorType"},
-	// scn2k_cmd.cc; Cmd::GetCmd()
+	// scn2k_cmd.cc; CmdD::GetCmd()
 	{0,0,0x00,0x01,0,    "local jump"},
 	{0,0,0x00,0x01,1,    "local jump-if"},
 	{0,0,0x00,0x01,2,    "local jump-unless"},
@@ -1331,8 +473,8 @@ CmdDescrItem cmd_descr_orig[] = {
 	{0,0,0x02,0x54,0x44c,"GetGrpObj_wh(2)"},
 	{0,0,0,0,0,0}
 };
-map<int, CmdDescrItem*> Cmd::cmd_descr;
-const char* Cmd::CmdDescr(int cmd1, int cmd2, int cmd3, int cmd4) {
+map<int, CmdDescrItem*> CmdD::cmd_descr;
+const char* CmdD::CmdDescr(int cmd1, int cmd2, int cmd3, int cmd4) {
 	if (cmd_descr.empty()) {
 		int i;
 		for (i=0; cmd_descr_orig[i].cmd_descr != 0; i++) {