Mercurial > otakunoraifu
view scn2k/scn2k_textimpl.cc @ 59:36d92d21300f
Implemented sin opcode
author | Thibaut GIRKA <thib@sitedethib.com> |
---|---|
date | Fri, 18 Dec 2009 18:51:44 +0100 |
parents | 0aaa5bb3dde5 |
children | 043d5db57474 |
line wrap: on
line source
/* * Copyright (c) 2009 Thibaut GIRKA * Copyright (c) 2004-2006 Kazunori "jagarl" Ueno * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "scn2k_text.h" void Text::impl_txtClear(Cmd& cmd) { if (text != NULL) { text->ResetFace(); if (cmd.cmd2 == 3 && cmd.cmd3 == 151) text->wid->Clear(); } cur_backlog_item.face = ""; if (cmd.cmd2 == 3 && cmd.cmd3 == 151) text_stream.Clear(); hide(); } void Text::impl_logKoe(Cmd& cmd) { // PlayKoe ; 声出力コマンドをチェックする */ cur_backlog_item.koe = cmd.args[0].value; } void Text::impl_pause(Cmd& cmd) { if (text != NULL) { eprintf("start\n"); text->StartText(text_stream); if (skip_mode & SKIP_TEXT) text->wid->Flush(); else if (kcursor) kcursor->show(); status = WAIT_TEXT; text_parsing = false; } backlog_item = cur_backlog_item; if (cur_backlog_item.scn == 0 && cur_backlog_item.pos == -1) backlog_item.text = text_stream; cur_backlog_item.Clear(); cmd.clear(); 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(); cmd.clear(); } void Text::impl_FaceOpen(Cmd& cmd) { if (text == NULL) show(); string s = cmd.Str(cmd.args[0]); s += ".g00"; if (text != NULL) text->ShowFace(s.c_str()); cur_backlog_item.face = s; cmd.cmd_type = CMD_SAVECMD_ONCE; } void Text::impl_FaceClear(Cmd& cmd) { if (text == NULL) show(); if (text) text->ResetFace(); cur_backlog_item.face = ""; cmd.cmd_type = CMD_SAVECMD_ONCE; } void Text::impl_doRuby(Cmd& cmd) { if (text == NULL) { show(); } if (cmd.cmd4 == 1) { ruby_text_flag = true; eprintf("SetRubyText."); cmd.clear(); } else if (cmd.cmd4 == 0) { if (ruby_text.length() == 0) { // ルビを振るテキストがない eprintf("Cannot find ruby text.\n"); return; } if (cmd.args.size() != 1) return; char debug1[1024], debug2[1024]; kconv( (unsigned char*)ruby_text.c_str(), (unsigned char*)debug1); kconv( (unsigned char*)cmd.Str(cmd.args[0]), (unsigned char*)debug2); eprintf("SetRuby. %s, %s",debug1, debug2); text_stream.AddRuby(ruby_text.c_str(), cmd.Str(cmd.args[0])); cur_backlog_item.DeleteTextPos(); cmd.clear(); } } void Text::impl_TextWindow(Cmd& cmd) { if (cmd.cmd4 == 0) { eprintf("set text window <- %d\n",cmd.args[0].value); if (text != NULL) show(cmd.args[0].value); else text_window_number = cmd.args[0].value; } else if (cmd.cmd4 == 1) { // default value eprintf("set text window <- default\n"); if (text != NULL) show(0); else text_window_number = 0; } cmd.clear(); } void Text::impl_FastText(Cmd& cmd) { //I think it's broken. For now, it's disabled. if (cmd.cmd3 == 103) { // テキストウィンドウ表示? show(); // 表示の際はテキストをクリアしない? // if (text) text->wid->Clear(); // text_stream.Clear(); cmd.clear(); } else if (cmd.cmd3 == 104) { // テキスト表示? // 全テキスト表示 if (text != NULL) { text->StartText(text_stream); text->wid->Flush(); } cmd.clear(); } } void Text::impl_msgClear(Cmd& cmd) { show(); if (text != NULL) text->wid->Clear(); text_stream.Clear(); cmd.clear(); } void Text::impl_createSelect(Cmd& cmd) { if (cmd.cmd4 == 0) { // 選択肢 CreateSelect(cmd); //FIXME: Check if it's really clean if (text_parsing) { show(); text->StartText(text_stream); if (skip_mode & SKIP_TEXT) text->wid->Flush(); else if (kcursor) kcursor->hide(); text_parsing = false; text_stream.Clear(); } cmd.cmd_type = CMD_ROLLBACKPOINT; /* 選択肢はセーブ位置 / シナリオ巻き戻し位置 */ // cmd.clear(); } else PrintCmd(cmd); //FIXME } void Text::impl_ShowBackground(Cmd& cmd) { status_mask = Status(CLEARSCR_MASK | status_mask); cmd.clear(); } void Text::impl_SetSkipMode(Cmd& cmd) { status_mask = Status(SKIPMASK | status_mask); cmd.clear(); } void Text::impl_Wait(Cmd& cmd) { eprintf("wait %dmsec\n",cmd.args[0].value); if (cmd.cmd3 == 100 && text != NULL) { /* 0x64 だと文字描画中の待ちに使うことがある */ text->StartText(text_stream); text->wid->Flush(); } if (cmd.cmd3 == 111 || cmd.cmd3 == 112 || cmd.cmd3 == 121) { 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; if (cmd.cmd3 == 101 || cmd.cmd3 == 112) status = WAIT_CLICK; else status = WAIT; cmd.cmd_type = CMD_WAITFRAMEUPDATE; // 画像描画に戻る(skip時にテキストが描画されやすくするため) } void Text::impl_GetClick(Cmd& cmd) { eprintf("wait and get mouse pos at click\n"); wait_time = old_time + 1000 * 1000; status = WAIT_CLICK_MOUSEPOS; wait_savedvar[0] = cmd.args[0]; wait_savedvar[1] = cmd.args[1]; 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 (frame_var.find(cmd.args[0].value) == frame_var.end()) cmd.SetSysvar(0); else { 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); 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); } #include "math.h" 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) { cmd.SetSysvar(pow(cmd.args[0].value, cmd.args[1].value)); } void Text::impl_sin(Cmd& cmd) { cmd.SetSysvar(sin(cmd.args[0].value * M_PI / 180) * 32640 / 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_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); } } 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) { // テキストウィンドウの色設定 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(); }