changeset 58:0aaa5bb3dde5

Moved all opcodes from scn2k_text.cc to scn2k_textimpl.cc
author Thibaut GIRKA <thib@sitedethib.com>
date Fri, 18 Dec 2009 14:25:56 +0100
parents 6d9146f56ccf
children 36d92d21300f
files scn2k/scn2k_text.cc scn2k/scn2k_text.h scn2k/scn2k_textimpl.cc
diffstat 3 files changed, 509 insertions(+), 277 deletions(-) [+]
line wrap: on
line diff
--- a/scn2k/scn2k_text.cc
+++ b/scn2k/scn2k_text.cc
@@ -71,7 +71,7 @@ using namespace std;
 */
 Text::Text(Event::Container& _event, PicContainer& _parent) :
 	text(0),status(Text::NORMAL), status_saved(Text::NORMAL), status_mask(Text::NORMAL), ruby_text_flag(false),
-	old_time(0), base_time(0), text_window_number(0), text_parsing(false), skip_mode(SKIP_NO), save_selectcount(0), sel_widget(0),
+	old_time(0), text_window_number(0), text_parsing(false), skip_mode(SKIP_NO), save_selectcount(0), sel_widget(0),
 	backlog_widget(0), parent(_parent), event(_event),
 	kcursor(0), sel_bg1(0), sel_bg2(0), sel_bg_rect(0,0,0,0) {
 	config = AyuSysConfig::GetInstance();
@@ -101,20 +101,74 @@ Text::Text(Event::Container& _event, Pic
 	RegisterCommand(0, 3, 104, "NormalText", NULL);
 	RegisterCommand(0, 3, 152, "msgClear", (CmdImpl) &Text::impl_msgClear);
 
+	RegisterCommand(1, 4, 2600, "DefMessageSpeed", (CmdImpl) &Text::impl_GetDefConfig);
+	RegisterCommand(1, 4, 2601, "DefMessageNoWait", (CmdImpl) &Text::impl_GetDefConfig);
+	RegisterCommand(1, 4, 2604, "DefAutoMode", (CmdImpl) &Text::impl_GetDefConfig);
+	RegisterCommand(1, 4, 2605, "DefAutoCharTime", (CmdImpl) &Text::impl_GetDefConfig);
+	RegisterCommand(1, 4, 2606, "DefAutoBaseTime", (CmdImpl) &Text::impl_GetDefConfig);
+
+	RegisterCommand(1, 4, 2323, "MessageSpeed", (CmdImpl) &Text::impl_GetConfig);
+	RegisterCommand(1, 4, 2324, "MessageNoWait", (CmdImpl) &Text::impl_GetConfig);
+	RegisterCommand(1, 4, 2350, "AutoMode", (CmdImpl) &Text::impl_GetConfig);
+	RegisterCommand(1, 4, 2351, "AutoCharTime", (CmdImpl) &Text::impl_GetConfig);
+	RegisterCommand(1, 4, 2352, "AutoBaseTime", (CmdImpl) &Text::impl_GetConfig);
+
+	RegisterCommand(1, 4, 2223, "SetMessageSpeed", (CmdImpl) &Text::impl_SetConfig);
+	RegisterCommand(1, 4, 2224, "SetMessageNoWait", (CmdImpl) &Text::impl_SetConfig);
+	RegisterCommand(1, 4, 2250, "SetAutoMode", (CmdImpl) &Text::impl_SetConfig);
+	RegisterCommand(1, 4, 2251, "SetAutoCharTime", (CmdImpl) &Text::impl_SetConfig);
+	RegisterCommand(1, 4, 2252, "SetAutoBaseTime", (CmdImpl) &Text::impl_SetConfig);
+
+	RegisterCommand(1, 4, 1300, "GetName", (CmdImpl) &Text::impl_GetName);
+	RegisterCommand(1, 4, 1301, "SetName", (CmdImpl) &Text::impl_SetName);
+	RegisterCommand(1, 4, 1310, "GetLocalName", (CmdImpl) &Text::impl_GetLocalName);
+	RegisterCommand(1, 4, 1311, "SetLocalName", (CmdImpl) &Text::impl_SetLocalName);
+
 	RegisterCommand(0, 2, 1, "select", (CmdImpl) &Text::impl_createSelect);
 	RegisterCommand(0, 2, 3, "select2?", (CmdImpl) &Text::impl_createSelect); //FIXME: What difference with select?
 
 	RegisterCommand(0, 4, 1000, "ShowBackground", (CmdImpl) &Text::impl_ShowBackground);
 	RegisterCommand(0, 4, 1100, "SetSkipMode", (CmdImpl) &Text::impl_SetSkipMode);
+
+	RegisterCommand(1, 4, 2260, "SetWindowAttrR", (CmdImpl) &Text::impl_SetWindowAttr);
+	RegisterCommand(1, 4, 2261, "SetWindowAttrG", (CmdImpl) &Text::impl_SetWindowAttr);
+	RegisterCommand(1, 4, 2262, "SetWindowAttrB", (CmdImpl) &Text::impl_SetWindowAttr);
+	RegisterCommand(1, 4, 2263, "SetWindowAttrA", (CmdImpl) &Text::impl_SetWindowAttr);
+	RegisterCommand(1, 4, 2264, "SetWindowAttrF", (CmdImpl) &Text::impl_SetWindowAttr);
+	RegisterCommand(1, 4, 2267, "SetWindowAttr", (CmdImpl) &Text::impl_SetWindowAttr);
+	RegisterCommand(1, 4, 2367, "GetWindowAttr", (CmdImpl) &Text::impl_GetWindowAttr);
+	RegisterCommand(1, 4, 2617, "DefWindowAttr", (CmdImpl) &Text::impl_GetWindowAttr);
+
 	RegisterCommand(1, 4, 100, "wait", (CmdImpl) &Text::impl_Wait);
 	RegisterCommand(1, 4, 111, "time", (CmdImpl) &Text::impl_Wait);
 	RegisterCommand(1, 4, 121, "timeEx", (CmdImpl) &Text::impl_Wait);
-
 	RegisterCommand(1, 4, 101, "waitC", (CmdImpl) &Text::impl_Wait);
 	RegisterCommand(1, 4, 112, "timeC", (CmdImpl) &Text::impl_Wait);
 	RegisterCommand(1, 4, 131, "GetClick", (CmdImpl) &Text::impl_GetClick);
 
+	RegisterCommand(1, 4, 364, "PauseCursor", (CmdImpl) &Text::impl_PauseCursor);
+	RegisterCommand(1, 4, 3009, "load", (CmdImpl) &Text::impl_load);
+
+	RegisterCommand(1, 4, 500, "InitFrame", (CmdImpl) &Text::impl_InitFrame);
 	RegisterCommand(1, 4, 510, "ReadFrame", (CmdImpl) &Text::impl_ReadFrame);
+	RegisterCommand(1, 4, 620, "InitExFrames", (CmdImpl) &Text::impl_InitFrames);
+	RegisterCommand(1, 4, 624, "InitExFramesDecel", NULL);
+	RegisterCommand(1, 4, 630, "ReadExFrames", (CmdImpl) &Text::impl_ReadFrames);
+
+	RegisterCommand(1, 4, 110, "ResetTimer", (CmdImpl) &Text::impl_ResetTimer);
+	RegisterCommand(1, 4, 120, "ResetExTimer", (CmdImpl) &Text::impl_ResetTimer);
+	RegisterCommand(1, 4, 114, "Timer", (CmdImpl) &Text::impl_Timer);
+
+	RegisterCommand(1, 4, 800, "index_series", (CmdImpl) &Text::impl_index_series);
+
+	RegisterCommand(1, 4, 1000, "rnd", (CmdImpl) &Text::impl_rnd);
+	RegisterCommand(1, 4, 1001, "pcnt", (CmdImpl) &Text::impl_pcnt);
+	RegisterCommand(1, 4, 1002, "abs", (CmdImpl) &Text::impl_abs);
+	RegisterCommand(1, 4, 1003, "power", NULL);
+	RegisterCommand(1, 4, 1004, "sin", NULL);
+	RegisterCommand(1, 4, 1007, "min", (CmdImpl) &Text::impl_min);
+	RegisterCommand(1, 4, 1008, "max", (CmdImpl) &Text::impl_max);
+	RegisterCommand(1, 4, 1009, "constrain", (CmdImpl) &Text::impl_constrain);
 }
 
 Text::~Text() {
@@ -733,273 +787,6 @@ void Text::Exec(Cmd& cmd) {
 	if (cmd.cmd_type != CMD_OTHER) return;
 
 	CommandHandler::Exec(cmd);
-
-	//RegisterCommand(1, 4, 110, "ResetTimer", NULL);
-	//RegisterCommand(1, 4, 120, "ResetExTimer", NULL);
-	if (cmd.cmd1 == 1 && cmd.cmd2 == 4) {
-		/* ウェイト関連命令 */
-		if (cmd.cmd3 == 0x6e || cmd.cmd3 == 0x78) { // set basetime
-			if (cmd.cmd4 == 1) {
-				eprintf("set basetime\n");
-				base_time = old_time;
-				cmd.clear();
-			} else if (cmd.cmd4 == 0) { // n-th base time
-				int index = cmd.args[0].value;
-				eprintf("set basetime (%d)\n",index);
-				TimerAtom& atom = timer_var[index];
-				atom.from = 0;
-				atom.to = 0;
-				atom.total_time = 0;
-				atom.start_time = old_time;
-				cmd.clear();
-			}
-		} else if (cmd.cmd3 == 0x72 || cmd.cmd3 == 0x7c) { // get time
-			if (cmd.cmd4 == 1) { // get time
-				eprintf("get time\n");
-				cmd.SetSysvar(old_time - base_time);
-			} else if (cmd.cmd4 == 0) { // n-th get time
-				int index = cmd.args[0].value;
-				eprintf("get time %dth\n",index);
-				if (timer_var.find(index) == timer_var.end()) cmd.SetSysvar(0);
-				else cmd.SetSysvar(old_time - timer_var[index].start_time);
-			}
-		} else if (cmd.cmd3 == 0x26c || cmd.cmd3 == 0x270) { // set basetime(multi)
-			int j = 0;
-			eprintf("set basetime\n");
-			int i; for (i=0; i<cmd.argc; i++) {
-				int cnt = cmd.args[j++].value; // 3なので無視
-				int num = cmd.args[j++].value;
-				TimerAtom& atom = timer_var[num];
-				atom.from = cmd.args[j++].value;
-				atom.to = cmd.args[j++].value;
-				atom.total_time = cmd.args[j++].value;
-				atom.start_time = old_time;
-			}
-			cmd.clear();
-		} else if (cmd.cmd3 == 0x276) { // get time (multi)
-			eprintf("get timer value\n");
-			vector<VarInfo> args = cmd.args;
-			vector<VarInfo>::iterator it = args.begin();
-			int argc = cmd.argc;
-			int active_timers = 0;
-			int i; for (i=0; i<argc; i++) {
-				int cnt = (it++)->value;
-				int num = (it++)->value;
-				
-				if (timer_var.find(num) == timer_var.end()) {
-					cmd.SetFlagvar(*it++, 0);
-				} else {
-					TimerAtom& atom = timer_var[num];
-					if (atom.total_time <= 0) atom.total_time = 1;
-					int cur_tm = old_time - atom.start_time;
-					if (cur_tm < 0) cur_tm = atom.total_time; // エラーなら最終時間に合わせる
-					if (cur_tm > atom.total_time) cur_tm = atom.total_time;
-					// use 'long long'(64bit) or 'double'(80bit) type, since total_time, to and from is 32 bit.
-					int v = atom.from + (long long)(atom.to-atom.from)*cur_tm/int(atom.total_time);
-					cmd.SetFlagvar(*it++, v);
-					if (atom.total_time != -1 && cur_tm < atom.total_time) active_timers++;
-				}
-			}
-			if (active_timers) active_timers = 1;
-			cmd.SetSysvar(active_timers);
-		} else if (cmd.cmd3 == 0x1f4) {
-			TimerAtom& atom = timer_var[cmd.args[0].value];
-			atom.from = cmd.args[1].value;
-			atom.to = cmd.args[2].value;
-			atom.total_time = cmd.args[3].value;
-			atom.start_time = old_time;
-			cmd.clear();
-		} else if (cmd.cmd3 == 0x3e8) {
-			/* rand() */
-			int min = 0, max;
-			if (cmd.args.size() == 2) {
-				min = cmd.args[0].value;
-				max = cmd.args[1].value;
-			} else {
-				max = cmd.args[1].value;
-			}
-			if (min > max) {
-				int tmp = max;
-				max = min;
-				min = tmp;
-			}
-			int r = random();
-			if (min == max) r = min;
-			else r = (r % (max-min)) + min;
-			cmd.SetSysvar(r);
-		} else if (cmd.cmd3 == 0x3ea) {
-			int val = cmd.args[0].value;
-			if (val < 0) val = -val;
-			cmd.SetSysvar(val);
-		} else if (cmd.cmd3 == 0x3ec) {
-			/* min だよなあ・・・*/
-			int min = cmd.args[0].value;
-			int max = cmd.args[1].value;
-			if (max < min) min = max;
-			cmd.SetSysvar(min);
-		} else if (cmd.cmd3 == 0x3ef) {
-			/* min */
-			int min = cmd.args[0].value;
-			int max = cmd.args[1].value;
-			if (max < min) min = max;
-			cmd.SetSysvar(min);
-		} else if (cmd.cmd3 == 0x320) {
-			/* range conversion : 比率に丸める */
-			// アルゴリズムは間違えてるような気がする
-			// 
-			if (cmd.args.size() >= 7) {
-				int val = cmd.args[0].value;
-				int offset = cmd.args[1].value;
-				int r_min = cmd.args[2].value;
-				int v_min = cmd.args[3].value;
-				int v_max = cmd.args[4].value;
-				int r_max = cmd.args[5].value;
-				int mode = cmd.args[6].value;
-				// rldev : mode == 1,3 : 'acceralating curve', 2,3: 'decelerating curve'
-				// 複数の引数リスト(r_minからmodeまでのリスト)もつこともあり、その場合は
-				// "cancel out in some way" らしい
-				if (mode == 1 || mode == 3) val += offset;
-				else if (mode == 2 || mode == 4) val -= offset;
-if (cmd.args.size() != 7)
-	fprintf(stderr,"\n%d/%d: cmd 01-04:0320 : XXXX NOT SUPPORTED LIST : DOUBLE RANGE CONVERSION!   XXXXXXXXXXX\n",cmd.scn,cmd.pos);
-				if (val < v_min) val = v_min;
-				if (val > v_max) val = v_max;
-				val = (r_max-r_min)*(val-v_min)/(v_max-v_min) + r_min;
-				cmd.SetSysvar(val);
-			}
-		} else if (cmd.cmd3 == 0x3f1) {
-			/* range 内に丸める */
-			int min = cmd.args[0].value;
-			int val = cmd.args[1].value;
-			int max = cmd.args[2].value;
-			if (min > max) {
-				int tmp = max;
-				max = min;
-				min = tmp;
-			}
-			if (val < min) val = min;
-			if (val > max) val = max;
-			cmd.SetSysvar(val);
-		} else if (cmd.cmd3 == 0x16c && cmd.cmd4 == 0) {
-		/* なんかよくわからないけどカーソル形状変更にしとく */
-			SetCursor(cmd.args[0].value);
-			cmd.clear();
-		} else if (cmd.cmd3 == 0x0bc1) { // メニューからのロード
-			cmd.cmd_type = CMD_LOADREQ;
-		} else if ( (cmd.cmd3 >= 0x8d4 && cmd.cmd3 <= 0x8d8) || cmd.cmd3 == 0x8db || cmd.cmd3 == 0x93f || cmd.cmd3 == 0xa39) {
-			// テキストウィンドウの色設定
-			int r, g, b, a, flag;
-			if (cmd.cmd3 == 0xa39) { // 元設定を取り出す
-				config->GetOriginalParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
-			} else {
-				config->GetParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
-			}
-			if (cmd.cmd3 == 0xa39 || cmd.cmd3 == 0x93f) { // 設定を変数に取り出す
-				if (cmd.args.size() != 5) {
-					fprintf(stderr,"cmd 01-04:%4d : invalid arg size\n", cmd.cmd3);
-				} else {
-					vector<VarInfo> args(cmd.args);
-					cmd.SetFlagvar(args[0], r);
-					cmd.SetFlagvar(args[1], g);
-					cmd.SetFlagvar(args[2], b);
-					cmd.SetFlagvar(args[3], a);
-					cmd.SetFlagvar(args[4], flag);
-				}
-			} else {
-				switch(cmd.cmd3) {
-				case 0x8d4: r = cmd.args[0].value; break;
-				case 0x8d5: g = cmd.args[0].value; break;
-				case 0x8d6: b = cmd.args[0].value; break;
-				case 0x8d7: a = cmd.args[0].value; break;
-				case 0x8d8: flag = cmd.args[0].value; break;
-				case 0x8db: 
-					r = cmd.args[0].value;
-					g = cmd.args[1].value;
-					b = cmd.args[2].value;
-					a = cmd.args[3].value;
-					flag = cmd.args[4].value;
-					break;
-				}
-				config->SetParam("#WINDOW_ATTR", 5, r, g, b, a, flag);
-				SetWindowColor(r, g, b, a, flag);
-				cmd.clear();
-			}
-		} else if (cmd.cmd3 == 0xa28 || cmd.cmd3 == 0xa29 || cmd.cmd3 == 0xa2c || cmd.cmd3 == 0xa2d || cmd.cmd3 == 0xa2e) {
-			int v = 0;
-			switch(cmd.cmd3) {
-			case 0xa28: case 0xa2d: config->GetOriginalParam("#INIT_MESSAGE_SPEED", 1, &v); break;
-			case 0xa29: config->GetOriginalParam("#INIT_MESSAGE_SPEED_MOD", 1, &v); break;
-			case 0xa2c: config->GetOriginalParam("#MESSAGE_KEY_WAIT_USE", 1, &v); break;
-			case 0xa2e: config->GetOriginalParam("#MESSAGE_KEY_WAIT_TIME", 1, &v); break;
-			}
-			cmd.SetSysvar(v);
-		} else if (cmd.cmd3 == 0x913 || cmd.cmd3 == 0x914 || cmd.cmd3 == 0x92f || cmd.cmd3 == 0x8af || cmd.cmd3 == 0x8b0 || cmd.cmd3 == 0x8cb) {
-			// テキスト表示速度関連
-			int m, speed;
-			config->GetParam("#INIT_MESSAGE_SPEED", 1, &speed);
-			config->GetParam("#INIT_MESSAGE_SPEED_MOD", 1, &m);
-if (cmd.cmd3 == 0x913 || cmd.cmd3 == 0x92f) fprintf(stderr,"TEXT speed %d\n",speed);
-else if (cmd.cmd3 == 0x914) fprintf(stderr,"TEXT mode %d\n",m);
-else if (cmd.cmd3 == 0x8af || cmd.cmd3 == 0x8cb) fprintf(stderr,"TEXT %d, %d <- speed %d\n",m,speed,cmd.args[0].value);
-else fprintf(stderr,"TEXT %d, %d <- mode %d\n",m,speed,cmd.args[0].value);
-			if (cmd.cmd3 == 0x913 || cmd.cmd3 == 0x92f) cmd.SetSysvar(speed);
-			else if (cmd.cmd3 == 0x914) cmd.SetSysvar(m);
-			else {
-				if (cmd.cmd3 == 0x8af || cmd.cmd3 == 0x8cb) speed = cmd.args[0].value;
-				else m = cmd.args[0].value;
-				if (speed < 10) speed = 10;
-				else if (speed > 1000) speed = 1000;
-				config->SetParam("#INIT_MESSAGE_SPEED", 1, speed);
-				config->SetParam("#INIT_MESSAGE_SPEED_MOD", 1, m);
-				if (m) speed = -1;
-				SetTextSpeed(speed);
-				cmd.clear();
-			}
-		} else if (cmd.cmd3 == 0x92e || cmd.cmd3 == 0x930 || cmd.cmd3 == 0x8ca || cmd.cmd3 == 0x8cc) {
-			// テキストオートモード関連
-			int m, wait;
-			config->GetParam("#MESSAGE_KEY_WAIT_USE", 1, &m);
-			config->GetParam("#MESSAGE_KEY_WAIT_TIME", 1, &wait);
-if (cmd.cmd3 == 0x92e) fprintf(stderr,"AUTO mode %d\n",m);
-else if (cmd.cmd3 == 0x930) fprintf(stderr,"AUTO wait %d\n",wait);
-else if (cmd.cmd3 == 0x8ca) fprintf(stderr,"AUTO %d,%d <- mode %d\n",m,wait,cmd.args[0].value);
-else fprintf(stderr,"AUTO %d,%d <- wait %d\n",m,wait,cmd.args[0].value);
-
-			if (cmd.cmd3 == 0x92e) cmd.SetSysvar(m);
-			else if (cmd.cmd3 == 0x930) cmd.SetSysvar(wait);
-			else {
-				if (cmd.cmd3 == 0x8ca) m = cmd.args[0].value;
-				else wait = cmd.args[1].value;
-				if (wait < 0) wait = 0;
-				else if (wait > 60000) wait = 60000;
-				config->SetParam("#MESSAGE_KEY_WAIT_USE", 1, m);
-				config->SetParam("#MESSAGE_KEY_WAIT_TIME", 1, wait);
-				if (m) SetTextWait(wait);
-				else SetTextWait(-1);
-				cmd.clear();
-			}
-		} else if (cmd.cmd3 == 0x51f && cmd.cmd4 == 0) { // replace_name2 の設定
-			int n = cmd.args[0].value;
-			if (n>=0 && n<26) {
-				replace_name2[n] = cmd.Str(cmd.args[1]);
-			}
-			cmd.clear();
-		} else if (cmd.cmd3 == 0x51e && cmd.cmd4 == 0) { // replace_name2 を得る
-			int n = cmd.args[0].value;
-			if (n >= 0 && n < 26) {
-				cmd.SetStrvar(cmd.args[1], replace_name2[n]);
-			} else {
-				cmd.SetStrvar(cmd.args[1], "");
-			}
-		} else if (cmd.cmd3 == 0x514 && cmd.cmd4 == 0) { // replace_name を得る
-			int n = cmd.args[0].value;
-			if (n >= 0 && n < 26) {
-				cmd.SetStrvar(cmd.args[1], replace_name[n]);
-			} else {
-				cmd.SetStrvar(cmd.args[1], "");
-			}
-		}
-	}
 }
 
 extern int print_blit;
--- a/scn2k/scn2k_text.h
+++ b/scn2k/scn2k_text.h
@@ -60,9 +60,12 @@ string kconv_rev(const string& s);
 */
 
 struct TimerAtom {
+	unsigned int start_time;
+};
+
+struct FrameTimerAtom : TimerAtom {
 	int from;
 	int to;
-	unsigned int start_time;
 	unsigned int total_time;
 };
 
@@ -195,7 +198,6 @@ class Text : public CommandHandler {
 		bool ruby_text_flag;
 		unsigned int wait_time;
 		unsigned int old_time;
-		unsigned int base_time;
 		int text_window_number;
 		bool text_parsing;
 		TextStream text_stream;
@@ -203,6 +205,12 @@ class Text : public CommandHandler {
 		int save_selectcount;
 
 		std::map<int, TimerAtom> timer_var;
+		//TODO: Handle EX Timer set
+		std::map<int, TimerAtom> timer_var_ex;
+		//TODO: Handle Frame Timers
+		std::map<int, FrameTimerAtom> frame_var;
+		std::map<int, FrameTimerAtom> frame_var_ex;
+
 		std::vector<WidTextButton*> selects;
 		std::vector<int> sel_backlog_pos;
 		string replace_name[26];
@@ -227,6 +235,7 @@ class Text : public CommandHandler {
 		PicContainer& parent;
 
 		//Opcode handling
+		// Text
 		void impl_txtClear(Cmd& cmd);
 		void impl_logKoe(Cmd& cmd);
 		void impl_pause(Cmd& cmd);
@@ -238,11 +247,39 @@ class Text : public CommandHandler {
 		void impl_msgClear(Cmd& cmd);
 		void impl_FastText(Cmd& cmd);
 		void impl_createSelect(Cmd& cmd);
-		void impl_ShowBackground(Cmd& cmd);
 		void impl_SetSkipMode(Cmd& cmd);
 		void impl_Wait(Cmd& cmd);
+		void impl_PauseCursor(Cmd& cmd);
+		void impl_SetWindowAttr(Cmd& cmd);
+		void impl_GetWindowAttr(Cmd& cmd);
+		void impl_GetName(Cmd& cmd);
+		void impl_SetName(Cmd& cmd);
+		void impl_GetLocalName(Cmd& cmd);
+		void impl_SetLocalName(Cmd& cmd);
+		// Misc (related with text)
+		void impl_ShowBackground(Cmd& cmd);
+		void impl_GetDefConfig(Cmd& cmd);
+		void impl_GetConfig(Cmd& cmd);
+		void impl_SetConfig(Cmd& cmd);
+		// Misc
+		void impl_index_series(Cmd& cmd);
+		void impl_load(Cmd& cmd);
 		void impl_GetClick(Cmd& cmd);
+		// Time/Frame
+		void impl_InitFrame(Cmd& cmd);
 		void impl_ReadFrame(Cmd& cmd);
+		void impl_InitFrames(Cmd& cmd);
+		void impl_ReadFrames(Cmd& cmd);
+		void impl_ResetTimer(Cmd& cmd);
+		void impl_Timer(Cmd& cmd);
+		// Maths
+		void impl_rnd(Cmd& cmd);
+		void impl_pcnt(Cmd& cmd);
+		void impl_abs(Cmd& cmd);
+		void impl_power(Cmd& cmd);
+		void impl_min(Cmd& cmd);
+		void impl_max(Cmd& cmd);
+		void impl_constrain(Cmd& cmd);
 };
 
 #endif
--- a/scn2k/scn2k_textimpl.cc
+++ b/scn2k/scn2k_textimpl.cc
@@ -62,6 +62,13 @@ void Text::impl_pause(Cmd& cmd) {
 	cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 糸祉祉(skip鴻祉)
 }
 
+void Text::impl_PauseCursor(Cmd& cmd)
+{
+	/* 若純綵∝九眼 */
+	SetCursor(cmd.args[0].value);
+	cmd.clear();
+}
+
 void Text::impl_br(Cmd& cmd) {
 	text_stream.AddReturn();
 	cur_backlog_item.DeleteTextPos();
@@ -192,7 +199,14 @@ void Text::impl_Wait(Cmd& cmd) {
 	}
 
 	if (cmd.cmd3 == 111 || cmd.cmd3 == 112 || cmd.cmd3 == 121)
-		wait_time = base_time + cmd.args[0].value; //FIXME: second argument, counter. See ReadFrame for this
+	{
+		int index;
+		if (cmd.cmd4 == 1)
+			index = 0;
+		else
+			index = cmd.args[1].value;
+		wait_time = timer_var[index].start_time + cmd.args[0].value;
+	}
 	else
 		wait_time = old_time + cmd.args[0].value;
 
@@ -213,19 +227,413 @@ void Text::impl_GetClick(Cmd& cmd) {
 	cmd.clear();
 }
 
+void Text::impl_ResetTimer(Cmd& cmd) {
+	int index;
+
+	if (cmd.cmd4 == 1)
+		index = 0;
+	else
+		index = cmd.args[0].value;
+
+	eprintf("set basetime (%d)\n",index);
+	//TODO: Handle EX timer set
+	TimerAtom& atom = timer_var[index];
+	atom.start_time = old_time;
+
+	cmd.clear();
+}
+
+void Text::impl_Timer(Cmd& cmd) {
+	int index;
+
+	if (cmd.cmd4 == 1)
+		index = 0;
+	else
+		index = cmd.args[0].value;
+
+	eprintf("get time %dth\n",index);
+	if (timer_var.find(index) == timer_var.end())
+		cmd.SetSysvar(0);
+	else
+		cmd.SetSysvar(old_time - timer_var[index].start_time);
+}
+
 void Text::impl_ReadFrame(Cmd& cmd) {
-	eprintf("get timer value[%d]\n",cmd.args[0].value);
-	if (timer_var.find(cmd.args[0].value) == timer_var.end())
+	eprintf("get timer value[%d]\n", cmd.args[0].value);
+	if (frame_var.find(cmd.args[0].value) == frame_var.end())
 		cmd.SetSysvar(0);
 	else {
-		TimerAtom& atom = timer_var[cmd.args[0].value];
+		FrameTimerAtom& atom = frame_var[cmd.args[0].value];
 		if (atom.total_time <= 0) atom.total_time = 1;
 		int cur_tm = old_time - atom.start_time;
 		if (cur_tm < 0) cur_tm = atom.total_time; // 若腟
 		if (cur_tm > atom.total_time) cur_tm = atom.total_time;
 		// use 'long long'(64bit) or 'double'(80bit) type, since total_time, to and from is 32 bit.
-		int v = atom.from + (long long)(atom.to-atom.from)*cur_tm/int(atom.total_time);
+		int v = atom.from + (long long)(atom.to - atom.from)*cur_tm/int(atom.total_time);
 		cmd.SetSysvar(v);
 	}
 }
 
+void Text::impl_InitFrame(Cmd& cmd) {
+	FrameTimerAtom& atom = frame_var[cmd.args[0].value];
+	atom.from = cmd.args[1].value;
+	atom.to = cmd.args[2].value;
+	atom.total_time = cmd.args[3].value;
+	atom.start_time = old_time;
+	cmd.clear();
+}
+
+void Text::impl_InitFrames(Cmd& cmd) {
+	int i, j = 0;
+	for (i = 0; i < cmd.argc; i++)
+	{
+		int cnt = cmd.args[j++].value; // 贈続袖損谷
+		int num = cmd.args[j++].value;
+		FrameTimerAtom& atom = frame_var[num];
+		atom.from = cmd.args[j++].value;
+		atom.to = cmd.args[j++].value;
+		atom.total_time = cmd.args[j++].value;
+		atom.start_time = old_time;
+	}
+	cmd.clear();
+}
+
+void Text::impl_ReadFrames(Cmd& cmd) {
+	vector<VarInfo> args = cmd.args;
+	vector<VarInfo>::iterator it = args.begin();
+	int argc = cmd.argc;
+	int timers_active = 0;
+	int i;
+	for (i=0; i < argc; i++)
+	{
+		int cnt = (it++)->value;
+		int num = (it++)->value;
+
+		if (frame_var.find(num) == frame_var.end()) {
+			cmd.SetFlagvar(*it++, 0);
+		}
+		else
+		{
+			FrameTimerAtom& atom = frame_var[num];
+			if (atom.total_time <= 0)
+				atom.total_time = 1;
+			int cur_tm = old_time - atom.start_time;
+			if (cur_tm < 0)
+				cur_tm = atom.total_time; // 促邸促辿臓辿尊捉損綻貼孫巽誰損谷
+			if (cur_tm > atom.total_time)
+				cur_tm = atom.total_time;
+			// use 'long long'(64bit) or 'double'(80bit) type, since total_time, to and from is 32 bit.
+			int v = atom.from + (long long)(atom.to-atom.from)*cur_tm/int(atom.total_time);
+			cmd.SetFlagvar(*it++, v);
+			if (atom.total_time != -1 && cur_tm < atom.total_time)
+				timers_active = 1;
+		}
+	}
+	cmd.SetSysvar(timers_active);
+}
+
+void Text::impl_rnd(Cmd& cmd)
+{
+	/* rand() */
+	int min, max;
+	if (cmd.args.size() == 2)
+	{
+		min = cmd.args[0].value;
+		max = cmd.args[1].value;
+	}
+	else
+	{
+		min = 0;
+		max = cmd.args[0].value;
+	}
+	if (min > max)
+	{
+		int tmp = max;
+		max = min;
+		min = tmp;
+	}
+	int r = random();
+	if (min == max)
+		r = min;
+	else
+		r = (r % (max-min)) + min;
+	cmd.SetSysvar(r);
+}
+
+void Text::impl_pcnt(Cmd& cmd)
+{
+	cmd.SetSysvar(100 * cmd.args[0].value / cmd.args[1].value);
+}
+
+void Text::impl_abs(Cmd& cmd)
+{
+	cmd.SetSysvar(abs(cmd.args[0].value));
+}
+
+void Text::impl_power(Cmd& cmd)
+{
+	//TODO
+	//cmd.SetSysvar(pow(cmd.args[0].value, cmd.args[1].value));
+}
+
+void Text::impl_min(Cmd& cmd)
+{
+	int a = cmd.args[0].value;
+	int b = cmd.args[1].value;
+	cmd.SetSysvar((a < b) ? a : b);
+}
+
+void Text::impl_max(Cmd& cmd)
+{
+	int a = cmd.args[0].value;
+	int b = cmd.args[1].value;
+	cmd.SetSysvar((a > b) ? a : b);
+}
+
+void Text::impl_index_series(Cmd& cmd)
+{
+	//TODO: This one is not fully documented in
+	// http://dev.haeleth.net/rldev/manual.html
+	// Try to figure out what's it...
+
+	/* range conversion : 罸筝吾 */
+	// ≪眼冴羂
+	// 
+	if (cmd.args.size() >= 7)
+	{
+		int val = cmd.args[0].value;
+		int offset = cmd.args[1].value;
+		int r_min = cmd.args[2].value;
+		int v_min = cmd.args[3].value;
+		int v_max = cmd.args[4].value;
+		int r_max = cmd.args[5].value;
+		int mode = cmd.args[6].value;
+		// rldev : mode == 1,3 : 'acceralating curve', 2,3: 'decelerating curve'
+		// 茲違綣違鴻(r_minmode障с鴻)ゃ翫
+		// "cancel out in some way" 
+		if (mode == 1 || mode == 3)
+			val += offset;
+		else if (mode == 2 || mode == 4)
+			val -= offset;
+if (cmd.args.size() != 7)
+	fprintf(stderr,"\n%d/%d: cmd 01-04:0320 : XXXX NOT SUPPORTED LIST : DOUBLE RANGE CONVERSION!   XXXXXXXXXXX\n",cmd.scn,cmd.pos);
+		if (val < v_min)
+			val = v_min;
+		if (val > v_max)
+			val = v_max;
+		val = (r_max-r_min)*(val-v_min)/(v_max-v_min) + r_min;
+		cmd.SetSysvar(val);
+	}
+}
+
+void Text::impl_constrain(Cmd& cmd)
+{
+	/* range 筝吾 */
+	int min = cmd.args[0].value;
+	int val = cmd.args[1].value;
+	int max = cmd.args[2].value;
+	if (min > max) {
+		max = cmd.args[0].value;
+		min = cmd.args[2].value;
+	}
+	if (val < min)
+		val = min;
+	if (val > max)
+		val = max;
+	cmd.SetSysvar(val);
+}
+
+
+void Text::impl_load(Cmd& cmd)
+{
+	// <ャ若若
+	cmd.cmd_type = CMD_LOADREQ;
+}
+
+void Text::impl_GetWindowAttr(Cmd& cmd)
+{
+	// 鴻c潟画┃絎
+	int r, g, b, a, flag;
+
+	if (cmd.cmd3 == 2617) // 荐絎冴
+		config->GetOriginalParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
+	else
+		config->GetParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
+
+	if (cmd.args.size() != 5) {
+		fprintf(stderr,"cmd 01-04:%4d : invalid arg size\n", cmd.cmd3);
+	} else {
+		vector<VarInfo> args(cmd.args);
+		cmd.SetFlagvar(args[0], r);
+		cmd.SetFlagvar(args[1], g);
+		cmd.SetFlagvar(args[2], b);
+		cmd.SetFlagvar(args[3], a);
+		cmd.SetFlagvar(args[4], flag);
+	}
+}
+
+void Text::impl_SetWindowAttr(Cmd& cmd)
+{
+	int r, g, b, a, flag;
+	config->GetParam("#WINDOW_ATTR", 5, &r, &g, &b, &a, &flag);
+
+	switch(cmd.cmd3) {
+		case 2260:
+			r = cmd.args[0].value;
+			break;
+		case 2261:
+			g = cmd.args[0].value;
+			break;
+		case 2262:
+			b = cmd.args[0].value;
+			break;
+		case 2263:
+			a = cmd.args[0].value;
+			break;
+		case 2264:
+			flag = cmd.args[0].value;
+			break;
+		case 2267: 
+			r = cmd.args[0].value;
+			g = cmd.args[1].value;
+			b = cmd.args[2].value;
+			a = cmd.args[3].value;
+			flag = cmd.args[4].value;
+			break;
+	}
+	config->SetParam("#WINDOW_ATTR", 5, r, g, b, a, flag);
+	SetWindowColor(r, g, b, a, flag);
+	cmd.clear();
+}
+
+void Text::impl_GetDefConfig(Cmd& cmd)
+{
+	int v = 0;
+	switch(cmd.cmd3) {
+		case 2600:
+		case 2605:
+			config->GetOriginalParam("#INIT_MESSAGE_SPEED", 1, &v);
+			break;
+		case 2601:
+			config->GetOriginalParam("#INIT_MESSAGE_SPEED_MOD", 1, &v);
+			break;
+		case 2604:
+			config->GetOriginalParam("#MESSAGE_KEY_WAIT_USE", 1, &v);
+			break;
+		case 2606:
+			config->GetOriginalParam("#MESSAGE_KEY_WAIT_TIME", 1, &v);
+			break;
+	}
+	cmd.SetSysvar(v);
+}
+
+void Text::impl_GetConfig(Cmd& cmd)
+{
+	int v;
+	switch (cmd.cmd3)
+	{
+		case 2323:
+		case 2351:
+			config->GetParam("#INIT_MESSAGE_SPEED", 1, &v);
+			break;
+		case 2324:
+			config->GetParam("#INIT_MESSAGE_SPEED_MOD", 1, &v);
+			break;
+		case 2350:
+			config->GetParam("#MESSAGE_KEY_WAIT_USE", 1, &v);
+			break;
+		case 2352:
+			config->GetParam("#MESSAGE_KEY_WAIT_TIME", 1, &v);
+			break;
+	}
+
+	cmd.SetSysvar(v);
+}
+
+void Text::impl_SetConfig(Cmd& cmd)
+{
+	int speed, use_speed_mod, wait, use_wait_mod;
+	config->GetParam("#INIT_MESSAGE_SPEED", 1, &speed);
+	config->GetParam("#INIT_MESSAGE_SPEED_MOD", 1, &use_speed_mod);
+	config->GetParam("#MESSAGE_KEY_WAIT_USE", 1, &use_wait_mod);
+	config->GetParam("#MESSAGE_KEY_WAIT_TIME", 1, &wait);
+	switch (cmd.cmd3)
+	{
+		case 2223:
+		case 2251:
+			speed = cmd.args[0].value;
+			if (speed < 10) //FIXME: ??? 0 ???
+				speed = 10;
+			if (speed > 10000) //FIXME: ??? 255 ???
+				speed = 10000;
+			config->SetParam("#INIT_MESSAGE_SPEED", 1, speed);
+			break;
+		case 2224:
+			use_speed_mod = cmd.args[0].value;
+			config->SetParam("#INIT_MESSAGE_SPEED_MOD", 1, use_speed_mod);
+			break;
+		case 2250:
+			use_wait_mod = cmd.args[0].value;
+			config->SetParam("#MESSAGE_KEY_WAIT_USE", 1, use_wait_mod);
+			break;
+		case 2252:
+			int wait = cmd.args[0].value;
+			if (wait < 0)
+				wait = 0;
+			else if (wait > 60000)
+				wait = 60000;
+			config->SetParam("#MESSAGE_KEY_WAIT_TIME", 1, wait);
+			break;
+	}
+
+	if (use_speed_mod) // FIXME: Not the other way around?
+		SetTextSpeed(-1);
+	else
+		SetTextSpeed(speed);
+
+	if (use_wait_mod)
+		SetTextWait(wait);
+	else
+		SetTextWait(-1);
+
+	cmd.clear();
+}
+
+void Text::impl_GetName(Cmd& cmd)
+{
+	// replace_name 緇
+	int n = cmd.args[0].value;
+	if (n >= 0 && n < 26) // FIXME: Should go up to 702, but otakunoraifu is not ready for that yet
+		cmd.SetStrvar(cmd.args[1], replace_name[n]);
+	else
+		cmd.SetStrvar(cmd.args[1], "");
+}
+
+void Text::impl_SetName(Cmd& cmd)
+{
+	// replace_name 緇
+	int n = cmd.args[0].value;
+	if (n >= 0 && n < 26) // FIXME: Should go up to 702, but otakunoraifu is not ready for that yet
+		replace_name[n] = cmd.Str(cmd.args[1]);
+}
+
+void Text::impl_GetLocalName(Cmd& cmd)
+{
+	// replace_name2 緇
+	int n = cmd.args[0].value;
+	if (n >= 0 && n < 26) // FIXME: Should go up to 702, but otakunoraifu is not ready for that yet
+		cmd.SetStrvar(cmd.args[1], replace_name2[n]);
+	else
+		cmd.SetStrvar(cmd.args[1], "");
+}
+
+void Text::impl_SetLocalName(Cmd& cmd)
+{
+	// replace_name2 荐絎
+	int n = cmd.args[0].value;
+	if (n >= 0 && n < 26) // FIXME: Should go up to 702, but otakunoraifu is not ready for that yet
+		replace_name2[n] = cmd.Str(cmd.args[1]);
+
+	cmd.clear();
+}
+