# mod_layerbutton-emes.hsp

common\ mod_layerbutton-emes.hsp

    /* /////////////////////////////////////////////////////////////////////////////
    mod_layerbutton-emes モジュール
    --------------------------------------------------------------------------------
    %dll ; モジュール名
    mod_layerbutton-emes
    %ver ; バージョン
    1.1
    %date ; 更新日
    2026/1/7
    %author ; 著作者
    MIZUSHIKI
    %note
    layerbutton命令を利用した1文字ずつ表示するlayeremesオブジェクトを作成
    %type
    拡張命令
    %url
    https://suwa.pupu.jp/HSP/index.html
    %port ; 対応環境
    Win
    */ /////////////////////////////////////////////////////////////////////////////
    #if 0
    %index ;========================================================================
    layeremes
    layerbuttonを利用したlayeremesオブジェクトを作成
    %group ;------------------------------------------------------------------------
    オブジェクト制御命令
    %prm   ;------------------------------------------------------------------------
    p1,p2,p3,p4,"string",p5,p6,p7,p8 {}
    p1,p2 : layeremesオブジェクトのXYサイズ（ドット単位）
    p3=0〜(0) : オプション値
    p4=0〜(0) : グループID
    "strings" : 表示するメッセージ、または変数
    p5=0〜(0) : オプション[mes命令と同様]
    p6=(0) : 1文字表示するのに掛けるフレーム数
    p7, p8 : アラインメント モード (0, 0)
    %inst  ;------------------------------------------------------------------------
    layerbuttonを利用した1文字ずつ文字を表示するlayeremesオブジェクトを配置します。
    layerbutton命令と同様、命令末尾に {} を記述してサブルーチンを指定する少し特殊な構文を用います。
    サブルーチンの最後には必ず return を記述してください。

    p1〜p4 は layerbutton と同様のものです。

    "string" には表示するメッセージを指定します。
    文中に以下の制御記号を挿入できます。
    ・"~"(チルダ) : 文字送り待機
    ・"^"(ハット) ： ページ送り待機 (行末のみ指定可能)
    また、行頭に「;」、文中に「/＊＊/」を書くことで、文字の色やフォントを変更するコマンドコメントを記述できます。
    使用可能なコマンドは以下の通りです。
    html{
    <table border="1" cellpadding="10">
    <tr>
      <td scope="col"><b>コマンド</b></td>
      <td scope="col"><b>効果</b></td>
    </tr>
    <tr>
      <td>font "フォント名",p1,p2,p3</td>
      <td>標準のfont命令に準拠。
      <br>引数を省略した場合は、前回の設定が引き継がれます。</td>
    </tr>
    <tr>
      <td>rgbcolor p1</td>
      <td>$RRGGBB(または0xRRGGBB)形式での文字色の指定。</td>
    </tr>
    <tr>
      <td>color p1,p2,p3</td>
      <td>R,G,B輝度形式での文字色の指定。</td>
    </tr>
    <tr>
      <td>objcolor p1,p2,p3</td>
      <td>layeremesのp5オプションで影付き文字、縁取り文字を指定したときの装飾色をR,G,B輝度形式で指定。</td>
    </tr>
    <tr>
      <td>mes p1,p2</td>
      <td>p1は必ず無視されます。p2で影付き文字、縁取り文字を指定するためのコマンドです。</td>
    </tr>
    <tr>
      <td>text p1</td>
      <td>「1文字表示フレーム数」を変更。
      <br>「-1」を指定したときは無視します。(「-1」は、objprmを利用してください。)</td>
    </tr>
    </table>
    }html
    コマンドコメントは内部で自力解析を行っているため、単純な値指定のみ対応しています。
    計算式や変数の使用はできません。

    p6 に 0 以上を指定すると、そのフレーム数ごとに文字が1つずつ表示されます。
    負数を指定すると、「1フレームあたりに表示する文字数」を指定できます。
    ・例： p6 = -3 → 1フレームに3文字ずつ表示
    ・特殊値 -1 → "^"(ハット)ページ区切りまでを一気に表示。このとき "~"(チルダ) の待機は無視されます。

    引数 p7, p8 で、横方向, 縦方向のアラインメントを指定できます。
    p7 : 0 = 左寄せ, 1 = 中央寄せ, 2 = 右寄せ
    p8 : 0 = 上寄せ, 1 = 中央寄せ, 2 = 下寄せ

    サブルーチンは文字が表示される直前に呼び出されます。
    背景装飾や、メッセージ表示完了の検知などに利用できます。
    ・現在の状態はシステム変数 layemes_stat で確認可能です。
    ・ステータスが変化してからのフレーム数は layemes_cnt に格納されます。
    ・サブルーチン呼出時には、stat に「表示済み文字数」が代入され、カレントポジションは文末位置になります。
    　（ただし カレントポジションの x, y が -1 のときは使用しないでください。）
    layerbutton 命令のサブルーチン内で動作しているため、laybtn_ezbox や layerbtn_stat などの命令・変数も利用可能です。

    通常、layeremesオブジェクトはメッセージ表示完了後に自動削除されます。
    layemes_settings で、メッセージ表示完了後も削除されないようにできます。

    layeremesオブジェクトは objprm でパラメータを変更することができます。
    ・objprm id,"string" : 新たなメッセージ表示を開始
    ・objprm id,int : 「1文字表示するのに掛けるフレーム数」を変更
    %href  ;-----------------------------------------------------------------------
    layemes_font
    layemes_settings
    layemes_frames
    layemes_stat
    layemes_cnt

    %index ;========================================================================
    layemes_font
    layeremesオブジェクトのフォント設定
    %group ;------------------------------------------------------------------------
    オブジェクト制御命令
    %prm   ;------------------------------------------------------------------------
    "fontname",p1,p2,p3,p4,p5,p6
    "fontname" : フォント名
    p1=1〜(20) : フォントの大きさ
    p2=0〜(0) : フォントのスタイル
    p3=1〜(1) : フォント修飾の幅
    %inst  ;------------------------------------------------------------------------
    layemes_font 命令は layeremes サブルーチン{}内の先頭に書いてください。
    "fontname", p1〜p3 は font 命令と同じ指定方法です。
    "fontname"の初期値は「msgothic」になっています。
    %href  ;------------------------------------------------------------------------
    layeremes
    layemes_settings
    layemes_frames
    layemes_stat
    layemes_cnt

    %index ;========================================================================
    layemes_settings
    layeremesオブジェクトの動作を設定
    %group ;------------------------------------------------------------------------
    オブジェクト制御命令
    %prm   ;------------------------------------------------------------------------
    p1,p2,p3,p4,p5,p6
    p1=0〜(0) : オプション値
    p2=0〜(0) : 文字間の隙間
    p3=0〜(0) : 行間の隙間
    p4=0〜(-1) : メッセージ表示時の効果音メディアバッファID(mmloadで割り当てたID)
    p5=0〜(16|32|256) : ページ送り等の操作キー
    p6=0〜(0) : 文字フェードに掛けるフレーム数
    %inst  ;------------------------------------------------------------------------
    layemes_settings 命令は layeremes サブルーチン{}内の先頭に書いてください。

    p1 オプション値では、layeremes の動作設定を変更できます。
    複数の設定を同時に有効にする場合は、値を加算して指定します。
    html{
    <table border="1" cellpadding="10">
    <tr>
      <td scope="col"><b>p1</b></td>
      <td scope="col"><b>設定内容</b></td>
    </tr>
    <tr>
      <td>+1</td>
      <td>メッセージ表示が完了しても削除されなくなります。
      <br>※ 削除は clrobj や laybtn_hide 等を使用してください。</td>
    </tr>
    <tr>
      <td>+2</td>
      <td>メッセージ表示の途中でキー操作をしても、メッセージをスキップしなくなります。</td>
    </tr>
    </table>
    }html

    p2,p3 は、それぞれ文字間と行間の隙間を設定します。
    p4 に mmload で読み込んだメディアバッファIDを指定すると、メッセージ表示時に効果音を再生します。
    p5 に値を指定すると、ページ送りなどの操作に使用するキーを変更できます。(stick 命令で使用する値と同じ)
    キー入力やクリック、タッチ操作を一切受け付けないようにする場合は、0 を指定してください。
    また、ゲームパッドなどの入力でページ送り等を操作したい場合は、layerbtn_stickVar グローバル変数を利用してください。
    p6 に値を設定すると、指定フレーム数をかけて文字が徐々にフェード表示されるようになります。(HSP3Dish限定)
    %href  ;------------------------------------------------------------------------
    layeremes
    layemes_font
    layemes_frames
    layemes_stat
    layemes_cnt

    %index ;========================================================================
    layemes_frames
    layeremesオブジェクトにSHOW_IN等のフレーム数を設定
    %group ;------------------------------------------------------------------------
    オブジェクト制御命令
    %prm   ;------------------------------------------------------------------------
    p1,p2,p3,p4,p5,p6
    p1=0〜(0) : SHOW_IN フレーム数
    p2=0〜(0) : FOCUS_IN フレーム数
    p3=0〜(0) : PRESS_IN フレーム数
    p4=0〜(0) : SHOW_OUT フレーム数
    p5=0〜(0) : FOCUS_OUT フレーム数
    p6=0〜(0) : PRESS_OUT フレーム数
    %inst  ;------------------------------------------------------------------------
    layemes_frames 命令は layeremes サブルーチン{}内の先頭に書いてください。

    layeremes では、layerbuttonで使用される各フレーム数の初期値はすべて 0 に設定されています。
    SHOW_IN などのフレーム数を指定することで、layerbutton と同様に、例えばサブルーチン内で描画するメッセージボックスにフェードイン演出を加えること等ができます。
    また、SHOW_OUT を指定すると、メッセージ表示が完了して自動削除される際に、メッセージがフェードアウトしながら消えるようになります（HSP3Dish限定）。
    ただし、FOCUS や PRESS のフレーム数を設定しても、laybtn_settings 1,1,0 としてキー入力やマウス／タッチ操作が無効化されているため、基本的には効果はありません。
    %href  ;------------------------------------------------------------------------
    layeremes
    layemes_font
    layemes_settings
    layemes_stat
    layemes_cnt

    %index ;========================================================================
    layemes_stat
    layeremesオブジェクトの処理状態が代入される
    %group ;------------------------------------------------------------------------
    拡張システム変数
    %inst  ;------------------------------------------------------------------------
    layeremes のサブルーチン内で利用するもので、現在の処理状態が代入されています。
    [処理状態]
    0 : まだメッセージが設定されていない
    1 : メッセージ表示中
    2 : 文字送り待機中
    3 : ページ送り待機中
    4 : メッセージ表示完了 (layemes_settingsで削除されない設定にしたとき)
    %href  ;------------------------------------------------------------------------
    layeremes
    layemes_font
    layemes_settings
    layemes_frames
    layemes_cnt

    %index ;========================================================================
    layemes_cnt
    layeremesオブジェクトの処理状態が変更されてからの経過フレーム数
    %group ;------------------------------------------------------------------------
    拡張システム変数
    %inst  ;------------------------------------------------------------------------
    layerbutton のサブルーチン内で利用するもので、処理状態が変更されて何フレーム目かの値が代入されます。
    %href  ;------------------------------------------------------------------------
    layeremes
    layemes_font
    layemes_settings
    layemes_frames
    layemes_stat
    % ;=============================================================================
    #endif

    #include "mod_layerbutton.hsp"

    #ifndef layeremes

    #module modlayemes
    //--------------------------------------
    // モジュール内定数
    //--------------------------------------
    #define FLAGEMES_OPTION_NOSKIP 2

    //--------------------------------------
    // 未初期化警告避け
    //--------------------------------------
    lastMmplayTime=0
    platform=0
    stkemes=0
    emesOption=0
    msTime=0
    cmds=0
    prms=0
    prm=0
    now_layerbtn_stickvar=0
    maeframe_layerbtn_stickvar=0

    //--------------------------------------
    // layeremes
    //--------------------------------------
    #define global layeremes(%1,%2,%3=0, %4=0,%5="",%6=0,%7=0,%8=0,%9=0) %tmodlayemes if(1):p2@modlayemes=%2:p3@modlayemes=%3:p4@modlayemes=%4:p5@modlayemes=%5:p6@modlayemes=%6:p7@modlayemes=%7:p8@modlayemes=%8:p9@modlayemes=%9}:layerbutton %1,p2@modlayemes,p3@modlayemes,p4@modlayemes,0,0,0,0,0,0 {  :\
    laybtn_settings 1,1,32  :\
    if lparam == objlayer_cmdinit {  :\
    nowFontName@%i="" : FontName@%p=""  :\
    if 0{chardelay@%p=0:charspacing@%p=0:linespacing@%p=0:fadeframe@%p=0:mmindex@%p=0:xx@%p=0:yy@%p=0:stkvalue@%p=0:emesoption@%p=0:startframe@%p=0:startindex@%p=0:mae_startindex@%p=0:analyzedindex@%p=0:lastdrawindex@%p=0:lastdrawindex_formm@%p=0:lastmmplaytime@%p=0:lastdraw_cx@%p=0:lastdraw_cy@%p=0:p_allmesx@%p=0:p_allmesy@%p=0:splitnum@%p=0:nowfontsize@%p=0:nowfontstyle@%p=0:nowfontdecosize@%p=0:nowfontcolor@%p=0:nowfontdecocolor@%p=0:nowmesstyle@%p=0:nowchardelay@%p=0:fontsize@%p=0:fontstyle@%p=0:fontdecosize@%p=0:fontcolor@%p=0:fontdecocolor@%p=0:messtyle@%p=0:state@%p=0:count@%p=0:splitchars@%p=0:splitchars_cmdindex@%p=0:splitchars_cmd@%p=0:splitCharsLineNumY@%p=0:splitcharsmesxSum@%p=0:splitcharsmesx@%p=0:splitcharsmesy@%p=0:splitcharsmesymax@%p=0:splitcharsstartframe@%p=0:splitcharsdelay@%p=0}:\
    } :\
    dup charDelay@modlayemes, charDelay@%p  :\
    dup charSpacing@modlayemes, charSpacing@%p  :\
    dup lineSpacing@modlayemes, lineSpacing@%p  :\
    dup fadeFrame@modlayemes, fadeFrame@%p  :\
    dup mmIndex@modlayemes, mmIndex@%p  :\
    dup xx@modlayemes, xx@%p  :\
    dup yy@modlayemes, yy@%p  :\
    dup stkValue@modlayemes, stkValue@%p  :\
    dup emesOption@modlayemes, emesOption@%p  :\
    dup startFrame@modlayemes, startFrame@%p  :\
    dup startIndex@modlayemes, startIndex@%p  :\
    dup mae_startIndex@modlayemes, mae_startIndex@%p  :\
    dup analyzedIndex@modlayemes, analyzedIndex@%p  :\
    dup lastDrawIndex@modlayemes, lastDrawIndex@%p  :\
    dup lastDrawIndex_forMM@modlayemes, lastDrawIndex_forMM@%p  :\
    dup lastMmplayTime@modlayemes, lastMmplayTime@%p  :\
    dup lastDraw_cx@modlayemes, lastDraw_cx@%p  :\
    dup lastDraw_cy@modlayemes, lastDraw_cy@%p  :\
    dup p_allmesx@modlayemes, p_allmesx@%p  :\
    dup p_allmesy@modlayemes, p_allmesy@%p  :\
    dup splitNum@modlayemes, splitNum@%p  :\
    dup nowFontName@modlayemes, nowFontName@%p  :\
    dup nowFontSize@modlayemes, nowFontSize@%p  :\
    dup nowFontStyle@modlayemes, nowFontStyle@%p  :\
    dup nowFontDecoSize@modlayemes, nowFontDecoSize@%p  :\
    dup nowFontColor@modlayemes, nowFontColor@%p  :\
    dup nowFontDecoColor@modlayemes, nowFontDecoColor@%p  :\
    dup nowMesStyle@modlayemes, nowMesStyle@%p  :\
    dup nowCharDelay@modlayemes, nowCharDelay@%p  :\
    dup FontName@modlayemes, FontName@%p  :\
    dup FontSize@modlayemes, FontSize@%p  :\
    dup FontStyle@modlayemes, FontStyle@%p  :\
    dup FontDecoSize@modlayemes, FontDecoSize@%p  :\
    dup FontColor@modlayemes, FontColor@%p  :\
    dup FontDecoColor@modlayemes, FontDecoColor@%p  :\
    dup MesStyle@modlayemes, MesStyle@%p  :\
    dup charDelay@modlayemes, charDelay@%p  :\
    dup state@modlayemes, state@%p  :\
    dup count@modlayemes, count@%p  :\
    if lparam == objlayer_cmdinit {  :\
    	layeremes_cmdinit@modlayemes p5@modlayemes,p6@modlayemes,p7@modlayemes,p8@modlayemes,p9@modlayemes, splitChars@%p, splitChars_cmdIndex@%p, splitChars_cmd@%p, splitCharsLineNumY@%p, splitCharsMesxSum@%p, splitCharsMesx@%p, splitCharsMesy@%p, splitCharsMesyMax@%p, splitCharsStartFrame@%p, splitCharsDelay@%p  :\
    }else: if lparam == objlayer_cmdprmi {  :\
    	layeremes_cmdprmi@modlayemes splitChars@%p, splitChars_cmdIndex@%p, splitChars_cmd@%p, splitCharsLineNumY@%p, splitCharsMesxSum@%p, splitCharsMesx@%p, splitCharsMesy@%p, splitCharsMesyMax@%p, splitCharsStartFrame@%p, splitCharsDelay@%p  :\
    	return  :\
    }else: if lparam == objlayer_cmdprms {  :\
    	layeremes_cmdprms@modlayemes splitChars@%p, splitChars_cmdIndex@%p, splitChars_cmd@%p, splitCharsLineNumY@%p, splitCharsMesxSum@%p, splitCharsMesx@%p, splitCharsMesy@%p, splitCharsMesyMax@%p, splitCharsStartFrame@%p, splitCharsDelay@%p  :\
    	return  :\
    }else: if lparam==objlayer_cmddraw{  :\
    	if state@%p{  :\
    		laybtn_stick stkemes@modlayemes  :\
    		if GlobalFrame@modlaybtn - maeFrame_layerbtn_stickVar@modlayemes > 1 { mae_layerbtn_stickVar@modlayemes = 0 }  :\
    		maeFrame_layerbtn_stickVar@modlayemes = GlobalFrame@modlaybtn  :\
    		now_layerbtn_stickVar@modlayemes = layerbtn_stickVar | mae_layerbtn_stickVar@modlayemes ^ mae_layerbtn_stickVar@modlayemes  :\
    		mae_layerbtn_stickVar@modlayemes = layerbtn_stickVar  :\
    		stkemes@modlayemes |= now_layerbtn_stickVar@modlayemes  :\
    	}  :\
    	Set_pos_lastChar@modlayemes splitChars@%p, splitChars_cmdIndex@%p, splitChars_cmd@%p, splitCharsLineNumY@%p, splitCharsMesxSum@%p, splitCharsMesx@%p, splitCharsMesy@%p, splitCharsMesyMax@%p, splitCharsStartFrame@%p, splitCharsDelay@%p  :\
    }  :\
    gosub *%p  :\
    if lparam == objlayer_cmddraw {  :\
    	count@%p++  :\
    	layeremes_cmddraw@modlayemes splitChars@%p, splitChars_cmdIndex@%p, splitChars_cmd@%p, splitCharsLineNumY@%p, splitCharsMesxSum@%p, splitCharsMesx@%p, splitCharsMesy@%p, splitCharsMesyMax@%p, splitCharsStartFrame@%p, splitCharsDelay@%p  :\
    }  :\
    return  :\
    *%o

    // cmdinit
    #deffunc layeremes_cmdinit@modlayemes str emes_text, int emes_p2, int _char_delay, int _x_x, int _y_y, array splitChars, array splitChars_cmdIndex, array splitChars_cmd, array splitCharsLineNumY, array splitCharsMesxSum, array splitCharsMesx, array splitCharsMesy, array splitCharsMesyMax, array splitCharsStartFrame, array splitCharsDelay
    	charDelay = _char_delay
    	charSpacing = 0
    	lineSpacing = 0
    	fadeFrame = 0
    	mmIndex = -1
    	xx=_x_x
    	yy=_y_y
    	stkValue = 16|32|256

    	nowFontName = ""+msgothic
    	#ifdef _HSP3DISH
    		getreq platform, SYSREQ_PLATFORM
    		if platform == PLATFORM_WEBGL : nowFontName = "sans-serif"
    	#endif
    	nowFontSize = 20
    	nowFontStyle = 0
    	nowFontDecoSize = 1
    	nowFontColor = (ginfo_r<<16) | (ginfo_g<<8) | (ginfo_b)
    	#ifdef _HSP3DISH
    		dupptr bm, objinfo_bmscr(0), 177*4
    		nowFontDecoColor = ((bm(176)&$FF)<<16) | (bm(176)&$FF00) | ((bm(176)>>16)&$FF)  ; COLORREF値(0xBBGGRR) → 0xRRGGBBにして格納
    	#else
    		dupptr bm, objinfo_bmscr(0), 87*4
    		nowFontDecoColor = bm(86)&$FFFFFF
    	#endif
    	nowMesStyle = emes_p2
    	nowCharDelay = charDelay

    	FontName = nowFontName
    	FontSize = nowFontSize
    	FontStyle = nowFontStyle
    	FontDecoSize = nowFontDecoSize
    	FontColor = nowFontColor
    	FontDecoColor = nowFontDecoColor
    	MesStyle = nowMesStyle
    	charDelay = nowCharDelay

    	state = 0
    	count = 0
    	if emes_text != "" : Set_splitChars emes_text, splitChars, splitChars_cmdIndex, splitChars_cmd, splitCharsLineNumY, splitCharsMesxSum, splitCharsMesx, splitCharsMesy, splitCharsMesyMax, splitCharsStartFrame, splitCharsDelay
    	return

    // (ローカル命令) 文字列を一文字ごとに分けて配列に格納 → 表示スタート[state=1]
    #deffunc local Set_splitChars str emes_text, array splitChars, array splitChars_cmdIndex, array splitChars_cmd, array splitCharsLineNumY, array splitCharsMesxSum, array splitCharsMesx, array splitCharsMesy, array splitCharsMesyMax, array splitCharsStartFrame, array splitCharsDelay
    	split_char_emes emes_text, splitChars, splitChars_cmdIndex, splitChars_cmd
    	if stat > 0 {
    		splitNum = stat
    		dim splitCharsLineNumY, splitNum
    		dim splitCharsMesxSum, splitNum
    		dim splitCharsMesx, splitNum
    		dim splitCharsMesy, splitNum
    		dim splitCharsMesyMax, splitNum
    		dim splitCharsStartFrame, splitNum
    		dim splitCharsDelay, splitNum  ; ← delay値を残して、何フレームで何文字表示すればいいかを計算できるようにするもの。
    		                               ;   - splitCharsMesxSumなどと共に先行して代入される。
    		                               ;   - クリック(state==3)したり、<p>や<d>まで来たら、後にstartFrame=iparamするので、そこまでのsplitCharsDelayは0に上書きされる。
    		startFrame = -1  ; cmddraw以外ではiparamカウントは取得できないので
    		startIndex = 0
    		mae_startIndex = -1
    		analyzedIndex = -1
    		state = 1
    		count = 0
    		lastDrawIndex = -1
    		lastDrawIndex_forMM = -1
    		lastDraw_cx = 0
    		lastDraw_cy = 0
    		p_allmesx = 0
    		p_allmesy = 0

    		FontName = nowFontName
    		FontSize = nowFontSize
    		FontStyle = nowFontStyle
    		FontDecoSize = nowFontDecoSize
    		FontColor = nowFontColor
    		FontDecoColor = nowFontDecoColor
    		MesStyle = nowMesStyle
    		charDelay = nowCharDelay
    	}else {
    		state = 0
    		count = 0
    	}
    	return

    // cmdprmi
    #deffunc layeremes_cmdprmi@modlayemes array splitChars, array splitChars_cmdIndex, array splitChars_cmd, array splitCharsLineNumY, array splitCharsMesxSum, array splitCharsMesx, array splitCharsMesy, array splitCharsMesyMax, array splitCharsStartFrame, array splitCharsDelay
    	charDelay = iparam  ; 「1文字表示するのに掛けるフレーム数」を変更
    	nowCharDelay = charDelay

    	anaFontName = nowFontName
    	anaFontSize = nowFontSize
    	anaFontStyle = nowFontStyle
    	anaFontDecoSize = nowFontDecoSize
    	anaFontColor = nowFontColor
    	anaFontDecoColor = nowFontDecoColor
    	anaMesStyle = nowMesStyle
    	anaCharDelay = nowCharDelay
    	breakReason = 0
    	cnt_ = lastDrawIndex+1

    	// 設定変更をsplitChars_cmdに追記する
    	if cnt_ < splitNum {
    		if splitChars_cmdIndex(cnt_) != -1 {
    			splitChars_cmd(splitChars_cmdIndex(cnt_)) += ":text "+iparam+":"
    		}else{
    			splitChars_cmdIndex(cnt_) = length(splitChars_cmd)
    			splitChars_cmd(splitChars_cmdIndex(cnt_)) = "text "+iparam+":"
    		}
    	}
    	// 既に設定済みのsplitCharsDelayを上書き
    	repeat
    		if cnt_ >= splitNum : break
    		anapx = 0
    		repeat , cnt_
    			if cnt >= splitNum : break
    			cnt_ = cnt
    			if splitChars_cmdIndex(cnt) != -1 {
    				_anaCharDelay = anaCharDelay
    				execHspEmesCommand splitChars_cmd(splitChars_cmdIndex(cnt)), anaFontName, anaFontSize, anaFontStyle, anaFontDecoSize, anaFontColor, anaFontDecoColor, anaMesStyle, _anaCharDelay
    				if anaCharDelay != -1 : anaCharDelay = _anaCharDelay * (_anaCharDelay!=-1)
    			}
    			if splitChars(cnt) == "<br>" {break}
    			if splitChars(cnt) == "<d>" : continue
    			if splitChars(cnt) == "<w>" : continue
    			if splitChars(cnt) == "<x>" : continue
    			if splitChars(cnt) == "<p>" {breakReason=1:break}
    			splitCharsDelay(cnt) = anaCharDelay * (anaCharDelay!=-1)
    			if anapx + splitCharsMesxSum(cnt) > objlayer_size_x : break
    			anapx += splitCharsMesxSum(cnt) + charSpacing
    		loop
    		if (xx!=0 || yy!=0) && breakReason==0 :cnt_++: continue
    		break
    	loop
    	return

    // cmdprms
    #deffunc layeremes_cmdprms@modlayemes array splitChars, array splitChars_cmdIndex, array splitChars_cmd, array splitCharsLineNumY, array splitCharsMesxSum, array splitCharsMesx, array splitCharsMesy, array splitCharsMesyMax, array splitCharsStartFrame, array splitCharsDelay
    	Set_splitChars refstr, splitChars, splitChars_cmdIndex, splitChars_cmd, splitCharsLineNumY, splitCharsMesxSum, splitCharsMesx, splitCharsMesy, splitCharsMesyMax, splitCharsStartFrame, splitCharsDelay
    	return

    // cmddraw
    #deffunc layeremes_cmddraw@modlayemes array splitChars, array splitChars_cmdIndex, array splitChars_cmd, array splitCharsLineNumY, array splitCharsMesxSum, array splitCharsMesx, array splitCharsMesy, array splitCharsMesyMax, array splitCharsStartFrame, array splitCharsDelay
    	if startFrame == -1 : startFrame = iparam  ; cmddraw以外ではiparamカウントは取得できないのでここで取得
    	if state {
    		// キー・マウス入力 処理 (各状態での入力振り分け)
    		if stkemes {
    			objsel -1
    			if stat != wparam {
    				laybtn_focus -1, -2  ; p1=-1,p2=-2 のとき隠し機能で FLAGBT_OPTION_NO_OBJECT_FOCUS を無視してフォーカスを探す
    				if stat != -1 : stkemes=0 | now_layerbtn_stickVar@modlayemes  ; 他のlayerbuttonをクリックやタップしている入力では文字送り等をさせない
    			}
    		}
    		if state == 1 {
    			if (emesOption & FLAGEMES_OPTION_NOSKIP)==0 {
    				if analyzedIndex != -1 {
    					if stkemes & stkValue {
    						state = 5 : count = 0
    						if (xx==0 && yy==0) {  ; 寄せ描画している場合は、<p>までの全文を調査済み
    							if splitCharsLineNumY(analyzedIndex) == 0 {
    								analyzedIndex == -1
    							}else {
    								temp = analyzedIndex
    								anaLineNumY = splitCharsLineNumY(analyzedIndex)
    								repeat analyzedIndex
    									analyzedIndex--
    									if anaLineNumY != splitCharsLineNumY(analyzedIndex) : break
    								loop
    							}
    						}
    					}
    				}
    			}
    		}else: if state == 2 {
    			if stkemes & stkValue {
    				startFrame = iparam
    				state = 1
    				count = 0
    			}
    		}else : if state == 3 {
    			if stkemes & stkValue {
    				if lastDrawIndex+1 >= splitNum {  ; 終わり
    					if option_keepVisible@_modlaybtn {
    						state = 4
    						count = 0
    					}else {
    						_layobjIndex = getLayobjverIndex@modlaybtn(ginfo_sel)
    						if _layobjIndex != -1 {
    							Add_flagBits_@modlaybtn _layobjIndex,wparam, FLAGBT_SHOWOUT@modlaybtn  ; showoutビットを立ててSHOW_OUT開始
    						}else {
    							clrobj wparam,wparam
    							return
    						}
    					}
    				}else {
    					startIndex = lastDrawIndex+1
    					startFrame = iparam
    					FontName = nowFontName
    					FontSize = nowFontSize
    					FontStyle = nowFontStyle
    					FontDecoSize = nowFontDecoSize
    					FontColor = nowFontColor
    					FontDecoColor = nowFontDecoColor
    					MesStyle = nowMesStyle
    					charDelay = nowCharDelay
    					state = 1
    					count = 0
    					lastDraw_cx = 0
    					lastDraw_cy = 0
    				}
    			}
    		}
    		px = 0 : py = 0

    		// 文字描画処理
    		nowFontName = FontName
    		nowFontSize = FontSize
    		nowFontStyle = FontStyle
    		nowFontDecoSize = FontDecoSize
    		nowFontColor = FontColor
    		nowFontDecoColor = FontDecoColor
    		nowMesStyle = MesStyle
    		nowCharDelay = charDelay  ; 文字送りの速度はsplitCharsDelay(cnt)の一文字々々々によって加算されている。splitChars_cmd(index)内のtextによって文章の途中でnowCharDelayを更新する
    		font_ nowFontName, nowFontSize, nowFontStyle, nowFontDecoSize
    		rgbcolor nowFontColor : objcolor (nowFontDecoColor>>16)&$FF, (nowFontDecoColor>>8)&$FF, (nowFontDecoColor)&$FF
    		frm=0.0 : isFading = 0
    		tamePx = 0 : resetKuhakuWidth=1 : tameCharsArrayNum = 0
    		repeat , startIndex
    			if cnt >= splitNum {
    				if state!=4 : state=0:count=0 : startIndex = splitNum
    				break
    			}
    			if state!=4 {
    				// 次の改行まで解析する
    				//  通常 : splitCharsMesyMaxが欲しい。どこで改行するかまでは問わない。
    				//  (state == 5 || xx!=0 || yy!=0) : 文字を一気に表示や中央寄せ等にする場合は<p>までの文章全体のXYサイズが必要になるので<p>までの解析が行われる
    				if (analyzedIndex < cnt && analyzedIndex < splitNum-1) {
    					anaFontName = nowFontName
    					anaFontSize = nowFontSize
    					anaFontStyle = nowFontStyle
    					anaFontDecoSize = nowFontDecoSize
    					anaFontColor = nowFontColor
    					anaFontDecoColor = nowFontDecoColor
    					anaMesStyle = nowMesStyle
    					anaCharDelay = nowCharDelay
    					breakReason = 0
    					cnt_ = cnt
    					__cnt = cnt
    					if analyzedIndex == -1 {  ; 最初の行
    						anaLineNumY = 0
    					}else {
    						anaLineNumY = splitCharsLineNumY(cnt-1) + 1
    					}
    					repeat
    						anaKitenX = cnt_ : anaKitenChars="" : anaKitenCharsNum=0
    						anapx = 0
    						anaMesxSum = 0
    						takasa = 0
    						breakReason = 0
    						repeat , cnt_
    							if cnt >= splitNum : break
    							analyzedIndex = cnt
    							__cnt = cnt
    							willChangeFont = 0
    							if splitChars_cmdIndex(cnt) != -1 {
    								_anaCharDelay = anaCharDelay
    								preExecHspEmesCommand splitChars_cmd(splitChars_cmdIndex(cnt)), anaFontName, anaFontSize, anaFontStyle, anaFontDecoSize, anaFontColor, anaFontDecoColor, anaMesStyle, _anaCharDelay
    								willChangeFont = stat
    								if anaCharDelay != -1 : anaCharDelay = _anaCharDelay * (_anaCharDelay!=-1)  ; -1 も 0 になる
    							}
    							if splitChars(cnt) == "<br>" {
    								if takasa==0 {takasa=anaFontSize}:splitCharsMesxSum(cnt)=-2:splitCharsMesx(cnt)=-1:splitCharsMesy(cnt)=1
    								break
    							}
    							if splitChars(cnt) == "<d>" :splitCharsMesxSum(cnt)=-2:splitCharsMesx(cnt)=-1:splitCharsMesy(cnt)=1: continue
    							if splitChars(cnt) == "<w>" :splitCharsMesxSum(cnt)=-2:splitCharsMesx(cnt)=-1:splitCharsMesy(cnt)=1: continue
    							if splitChars(cnt) == "<x>" :splitCharsMesxSum(cnt)=-2:splitCharsMesx(cnt)=-1:splitCharsMesy(cnt)=1: continue
    							if splitChars(cnt) == "<p>" {
    								if takasa==0 {takasa=anaFontSize}:splitCharsMesxSum(cnt)=-2:splitCharsMesx(cnt)=-1:splitCharsMesy(cnt)=1
    								breakReason = 2
    								break
    							}
    							;if splitCharsMesy(cnt) == 0 {
    								splitCharsDelay(cnt) = anaCharDelay
    								if willChangeFont {
    									if anaKitenCharsNum > 0 {
    										pos -ginfo_sx,-ginfo_sy : mes anaKitenChars, anaMesStyle
    										if takasa < ginfo_mesy : takasa = ginfo_mesy
    										if anaKitenCharsNum == 1 : splitCharsMesx(cnt) = ginfo_mesx
    										if anapx + anaMesxSum + charSpacing*((anapx+anaMesxSum)>0) + ginfo_mesx+charSpacing*(anaKitenCharsNum-1) > objlayer_size_x {
    											breakReason = 1
    											break
    										}
    										repeat limit(cnt-anaKitenX,0),anaKitenX
    											splitCharsMesxSum(cnt)=-1
    											splitCharsMesy(cnt)=ginfo_mesy
    										loop
    										splitCharsMesxSum(anaKitenX)=-(ginfo_mesx+charSpacing*(anaKitenCharsNum-1))
    										anaMesxSum += charSpacing*((anapx+anaMesxSum)>0) + -splitCharsMesxSum(anaKitenX)
    										anaKitenChars = "" : anaKitenCharsNum = 0
    										anaKitenX = cnt
    									}
    									execHspEmesCommand splitChars_cmd(splitChars_cmdIndex(cnt)), anaFontName, anaFontSize, anaFontStyle, anaFontDecoSize, anaFontColor, anaFontDecoColor, anaMesStyle, _anaCharDelay
    								}
    							;}
    							anaKitenChars += splitChars(cnt) : anaKitenCharsNum++
    							if cnt+1 < splitNum {
    								switch splitChars(cnt+1)
    								case "ぁ":case "ぃ":case "ぅ":case "ぇ":case "ぉ":case "ゃ":case "ゅ":case "ょ":case "っ":case "ゎ":
    								case "ァ":case "ィ":case "ゥ":case "ェ":case "ォ":case "ャ":case "ュ":case "ョ":case "ッ":case "ヮ":
    								anaKitenChars += splitChars(cnt+1) : anaKitenCharsNum++
    								continue cnt+2
    								swend
    							}
    						loop
    						if anaKitenCharsNum > 0 {
    							if breakReason != 1 {
    								pos -ginfo_sx,-ginfo_sy : mes anaKitenChars, anaMesStyle
    								if takasa < ginfo_mesy : takasa = ginfo_mesy
    								if anaKitenCharsNum == 1 : splitCharsMesx(cnt) = ginfo_mesx
    							}
    							if state == 5 || xx!=0 || yy!=0 || platform == 3 {
    								// - クリックスキップや寄せとは別に、Dish.jsでは1行分だけ解析しておく必要がある。(ginfo_mesxが積み立てできない[?])
    								if anapx + anaMesxSum + charSpacing*((anapx+anaMesxSum)>0) + ginfo_mesx+charSpacing*(anaKitenCharsNum-1) > objlayer_size_x {
    									low = anaKitenX
    									high = __cnt
    									while low < high
    										mid = (low + high + 1) / 2
    										anaKitenChars = "" : anaKitenCharsNum=0
    										repeat mid-anaKitenX, anaKitenX
    											if splitChars(cnt) == "<d>" : continue
    											if splitChars(cnt) == "<w>" : continue
    											if splitChars(cnt) == "<x>" : continue
    											anaKitenChars += splitChars(cnt) : anaKitenCharsNum++
    											if cnt+1 < splitNum {
    												switch splitChars(cnt+1)
    													case "ぁ":case "ぃ":case "ぅ":case "ぇ":case "ぉ":case "ゃ":case "ゅ":case "ょ":case "っ":
    													case "ァ":case "ィ":case "ゥ":case "ェ":case "ォ":case "ャ":case "ュ":case "ョ":case "ッ":
    													anaKitenChars += splitChars(cnt+1) : anaKitenCharsNum++
    													continue cnt+2
    												swend
    											}
    										loop
    										pos -ginfo_sx,-ginfo_sy : mes anaKitenChars, anaMesStyle
    										if anaKitenCharsNum == 1 : splitCharsMesx(anaKitenX) = ginfo_mesx
    										if anapx + anaMesxSum + charSpacing*((anapx+anaMesxSum)>0) + ginfo_mesx+charSpacing*(anaKitenCharsNum-1) < objlayer_size_x {
    											low = mid
    										}else {
    											high = mid -1
    										}
    									wend
    									if low == anaKitenX {
    										if ginfo_mesx > objlayer_size_x : low = anaKitenX+1
    									}
    									anaKitenChars = "" : anaKitenCharsNum=0
    									repeat low-anaKitenX, anaKitenX
    										if splitChars(cnt) == "<d>" : continue
    										if splitChars(cnt) == "<w>" : continue
    										if splitChars(cnt) == "<x>" : continue
    										anaKitenChars += splitChars(cnt) : anaKitenCharsNum++
    									loop
    									pos -ginfo_sx,-ginfo_sy : mes anaKitenChars, anaMesStyle
    									if anaKitenCharsNum == 1 : splitCharsMesx(anaKitenX) = ginfo_mesx
    									__cnt = low-1
    								}
    								splitCharsMesxSum(anaKitenX)=-(ginfo_mesx+charSpacing*(anaKitenCharsNum-1))
    								if takasa < ginfo_mesy : takasa = ginfo_mesy
    								repeat limit(__cnt-anaKitenX,0),anaKitenX+1
    									splitCharsMesxSum(cnt)=-1
    								loop
    							}
    							repeat limit(__cnt-anaKitenX+1,0),anaKitenX
    								splitCharsMesy(cnt)=ginfo_mesy
    							loop
    						}
    						// 設定
    						repeat , cnt_
    							if cnt >= splitNum : break
    							if cnt > __cnt : break
    							splitCharsMesyMax(cnt) = takasa
    							splitCharsLineNumY(cnt) = anaLineNumY
    						loop
    						// - Dish.jsの1行分だけ解析した証明を残しておく。(tameKaihouで改行位置を把握するのに使う)
    						if platform == 3 {
    							if __cnt+1 < splitNum {
    								splitCharsLineNumY(__cnt+1) = -1
    							}
    						}
    						if state == 5 || xx!=0 || yy!=0 {
    							if __cnt < splitNum && __cnt >= 0 : if splitChars(__cnt) == "<p>" : break
    							cnt_ = __cnt + 1
    							anaLineNumY += 1
    							if cnt_ < splitNum : continue
    						}
    						break
    					loop
    					font_ nowFontName, nowFontSize, nowFontStyle, nowFontDecoSize
    					rgbcolor nowFontColor : objcolor (nowFontDecoColor>>16)&$FF, (nowFontDecoColor>>8)&$FF, (nowFontDecoColor)&$FF

    				}
    				// 中央寄せ等にしている場合、<p>までの文章の全体XYサイズが必要なので算出 -> p_allmesx, p_allmesy
    				if mae_startIndex != startIndex {
    					mae_startIndex = startIndex
    					if (xx!=0 || yy!=0) {
    						p_allmesx = 0
    						p_allmesy = 0
    						anapx=0
    						anaLineNumY = -1
    						repeat , startIndex
    							if cnt >= splitNum : break
    							if cnt > analyzedIndex : break
    							if anaLineNumY != splitCharsLineNumY(cnt) {
    								anaLineNumY = splitCharsLineNumY(cnt)
    								if p_allmesy > 0 : p_allmesy += lineSpacing
    								p_allmesy += splitCharsMesyMax(cnt)
    								anapx = 0
    							}
    							if splitChars(cnt) == "<br>" {
    								anapx = 0
    								continue
    							}
    							if splitChars(cnt) == "<d>" : continue
    							if splitChars(cnt) == "<w>" : continue
    							if splitChars(cnt) == "<x>" : continue
    							if splitChars(cnt) == "<p>" : break

    							if splitCharsMesxSum(cnt) > 0 {
    								mesx = splitCharsMesxSum(cnt)
    							}else : if splitCharsMesxSum(cnt) < -2 {
    								mesx = -splitCharsMesxSum(cnt)
    							}else {
    								mesx = 0
    							}
    							anapx += mesx
    							if p_allmesx < anapx : p_allmesx = anapx
    							anapx += charSpacing
    						loop
    					}
    				}
    				if state == 5 || nowCharDelay == -1 : splitCharsDelay(cnt) = 0 : splitCharsStartFrame(cnt) = -fadeFrame  ; クリックスキップや表示速度-1のとき、delayを0にしたりフェードが255になるようにする
    				if splitCharsDelay(cnt)>=0 {
    					frm += splitCharsDelay(cnt)
    				}else {
    					frm += 1.0/-splitCharsDelay(cnt)
    				}
    				if int(frm)+startFrame > iparam {
    					break
    				}
    				// 最後のインデックス値を控えておく
    				if lastDrawIndex < cnt {
    					lastDrawIndex = cnt
    				}
    			}

    			// コマンドコメントが付いていた場合、フォント設定等を変更
    			if splitChars_cmdIndex(cnt) != -1 {
    				_nowCharDelay = nowCharDelay
    				execHspEmesCommand splitChars_cmd(splitChars_cmdIndex(cnt)), nowFontName, nowFontSize, nowFontStyle, nowFontDecoSize, nowFontColor, nowFontDecoColor, nowMesStyle, _nowCharDelay
    				resetKuhakuWidth |= stat&1
    				if nowCharDelay != -1 : nowCharDelay = _nowCharDelay * (_nowCharDelay!=-1)  ; コメントからのtextでは-1にならない。かつ強制-1されていた場合は-1を継続する。
    			}

    			// 改行、ページ送り待ち、文字送り待ちのとき
    			if splitChars(cnt) == "<br>" {
    				px = 0
    				py += splitCharsMesyMax(cnt) + lineSpacing
    				continue
    			}
    			if splitChars(cnt) == "<p>" {
    				if state!=4 {
    					repeat cnt+1
    						splitCharsDelay(cnt) = 0
    					loop
    					lastDrawIndex_forMM = cnt
    					if isFading == 0 {
    						if state != 3 : count = 0
    						state = 3
    					}
    				}
    				break
    			}
    			if state == 1 && splitChars(cnt) == "<w>" : splitChars(cnt) == "<x>"
    			if splitChars(cnt) == "<d>" || splitChars(cnt) == "<w>" {
    				if state!=4 {
    					if state == 5 || nowCharDelay == -1 {
    						splitChars(cnt) == "<x>"
    					}else {
    						splitChars(cnt) == "<w>"
    						repeat cnt+1
    							splitCharsDelay(cnt) = 0
    						loop
    						lastDrawIndex_forMM = cnt
    						;if isFading == 0 {
    							if state != 2 : count = 0
    							state = 2
    						;}
    						break
    					}
    				}
    			}

    			// 文字が(簡易調査も含めて)未調査の場合、出力文字のサイズを測っておく(一文字後。二文字後は拗音促音のときのみ)
    			if cnt+1 < splitNum {
    				if splitCharsMesxSum(cnt+1) == 0 {
    					switch splitChars(cnt+1)
    					case "<br>" : case "<p>" : case "<w>" : case "<x>" : case "<d>":
    						splitCharsMesxSum(cnt+1)=-2 : splitCharsMesy(cnt+1)=1
    						splitCharsMesx(cnt+2)=ginfo_mesx
    						swbreak
    					default
    						anaFontName = nowFontName
    						anaFontSize = nowFontSize
    						anaFontStyle = nowFontStyle
    						anaFontDecoSize = nowFontDecoSize
    						anaFontColor = nowFontColor
    						anaFontDecoColor = nowFontDecoColor
    						anaMesStyle = nowMesStyle
    						_nowCharDelay = nowCharDelay
    						isChangedFontOrColor = 0
    						if splitChars_cmdIndex(cnt+1) != -1 {
    							execHspEmesCommand splitChars_cmd(splitChars_cmdIndex(cnt+1)), nowFontName, nowFontSize, nowFontStyle, nowFontDecoSize, nowFontColor, nowFontDecoColor, nowMesStyle, _nowCharDelay
    							isChangedFontOrColor |= stat
    						}
    						pos -ginfo_sx,-ginfo_sy
    						mes splitChars(cnt+1),nowMesStyle
    						splitCharsMesxSum(cnt+1)=ginfo_mesx : splitCharsMesy(cnt+1)=ginfo_mesy
    						splitCharsMesx(cnt+1)=ginfo_mesx
    						if cnt+2 < splitNum {
    							if splitCharsMesxSum(cnt+2) == 0 {
    								switch splitChars(cnt+2)
    								case "<br>" : case "<p>" : case "<w>" : case "<x>" : case "<d>":
    									splitCharsMesxSum(cnt+2)=-2 : splitCharsMesy(cnt+2)=1
    									splitCharsMesx(cnt+2)=-1
    									swbreak
    								case "ぁ":case "ぃ":case "ぅ":case "ぇ":case "ぉ":case "ゃ":case "ゅ":case "ょ":case "っ":
    								case "ァ":case "ィ":case "ゥ":case "ェ":case "ォ":case "ャ":case "ュ":case "ョ":case "ッ":
    									if splitChars_cmdIndex(cnt+2) != -1 {
    										execHspEmesCommand splitChars_cmd(splitChars_cmdIndex(cnt+2)), nowFontName, nowFontSize, nowFontStyle, nowFontDecoSize, nowFontColor, nowFontDecoColor, nowMesStyle, _nowCharDelay
    										isChangedFontOrColor |= stat
    									}
    									pos -ginfo_sx,-ginfo_sy
    									mes splitChars(cnt+2),nowMesStyle
    									splitCharsMesxSum(cnt+2)=ginfo_mesx : splitCharsMesy(cnt+2)=ginfo_mesy
    									splitCharsMesx(cnt+2)=ginfo_mesx
    									swbreak
    								swend
    							}
    						}
    						if isChangedFontOrColor {
    							nowFontName = anaFontName
    							nowFontSize = anaFontSize
    							nowFontStyle = anaFontStyle
    							nowFontDecoSize = anaFontDecoSize
    							nowFontColor = anaFontColor
    							nowFontDecoColor = anaFontDecoColor
    							nowMesStyle = anaMesStyle
    							font_ nowFontName, nowFontSize, nowFontStyle, nowFontDecoSize
    							rgbcolor nowFontColor : objcolor (nowFontDecoColor>>16)&$FF, (nowFontDecoColor>>8)&$FF, (nowFontDecoColor)&$FF
    						}
    					swend
    				}
    			}
    			// 文字が(簡易調査も含めて)未調査の場合、出力文字のサイズを測っておく
    			if splitCharsMesxSum(cnt) == 0 {
    				if splitChars(cnt) != "<x>" {  ; <x>だけは貫通させたいので一応分岐
    					pos -ginfo_sx,-ginfo_sy
    					mes splitChars(cnt),nowMesStyle
    					splitCharsMesxSum(cnt)=ginfo_mesx : splitCharsMesy(cnt)=ginfo_mesy
    					splitCharsMesx(cnt)=ginfo_mesx
    				}else {
    					splitCharsMesxSum(cnt)=-1 : splitCharsMesy(cnt)=1
    					splitCharsMesx(cnt)=-1
    				}
    			}
    			// 文字描画幅 取り出し。splitCharsMesxSumには次のタイプがある 0以上:一文字の幅、-1未満:複数文字の幅、-1:複数文字に重ねられた文字
    			if splitCharsMesxSum(cnt) != 0 {
    				if splitCharsMesxSum(cnt) > 0 {
    					mesx = splitCharsMesxSum(cnt)
    				}else : if splitCharsMesxSum(cnt) < -2 {
    					mesx = -splitCharsMesxSum(cnt)
    				}else {
    					mesx = 0
    				}
    			}else {
    				mesx = 0
    			}

    			// 枠から文字あふれで改行
    			if px + mesx > objlayer_size_x {
    				px = 0
    				if cnt > 0 : py += splitCharsMesyMax(cnt-1) + lineSpacing
    			}else : if cnt+1 < splitNum {
    				mesx2 = splitCharsMesxSum(cnt+1)  ; マイナス値が入ることがあるが、その場合は拗音促音で改行になることはない
    				if px + mesx + charSpacing + mesx2 > objlayer_size_x {
    					switch splitChars(cnt+1)
    						case "ぁ":case "ぃ":case "ぅ":case "ぇ":case "ぉ":case "ゃ":case "ゅ":case "ょ":case "っ":
    						case "ァ":case "ィ":case "ゥ":case "ェ":case "ォ":case "ャ":case "ュ":case "ョ":case "ッ":
    						px = 0
    						if cnt > 0 : py += splitCharsMesyMax(cnt-1) + lineSpacing
    					swend
    				}
    			}

    			// 文字フェード設定
    			if splitCharsStartFrame(cnt) == 0 : splitCharsStartFrame(cnt) = iparam
    			fd = 255
    			#ifdef _HSP3DISH
    			if layerbtn_stat & LAYBTN_SHOW_OUT {
    				setease 255, 0, ease_quad_out
    				fd = getease(layerbtn_cnt, SHOW_OUT_FRAME@modlaybtn)
    				gmode 3,,,fd
    			}else : if layerbtn_stat & LAYBTN_COMPLETE {
    				fd = 0
    				gmode 3,,,fd
    			}else : if fadeFrame > 0 {
    				setease 0, 255, ease_quad_in
    				fd = getease(iparam-splitCharsStartFrame(cnt), fadeFrame)
    				gmode 3,,,fd
    				isFading |= (fd<255)
    			}
    			#endif

    			// 一気に表示できる文字は貯める
    			if tameCharsArrayNum == 0 : tamePx = px : tameCharsArray = "" : tameHeadIndex = cnt
    			if splitChars(cnt) != "<x>" {
    				tameCharsArray(tameCharsArrayNum)=splitChars(cnt)
    				tameCharsFades(tameCharsArrayNum)=fd
    				tameCharsArrayNum++
    			}
    			// 貯め開放調査
    			tameKaihou = 0
    			if cnt+1 < splitNum {
    				if platform == 3 {
    					if tameKaihou == 0 {
    						// - Dish.jsでの1行分だけ解析した証明があれば、そこが改行位置
    						if splitCharsLineNumY(cnt+1) == -1 : tameKaihou = 2 : splitCharsLineNumY(cnt+1) = splitCharsLineNumY(cnt)
    					}
    				}
    				if tameKaihou ==0 {
    					charSpacing_1 = 0
    					if splitCharsMesxSum(cnt+1) > 0 {
    						_mesx1 = splitCharsMesxSum(cnt+1)
    						charSpacing_1 = charSpacing
    					}else: if splitCharsMesxSum(cnt+1) < -2 {
    						_mesx1 = -splitCharsMesxSum(cnt+1)
    						if cnt+2 < splitNum {
    							if splitCharsMesxSum(cnt+1) != -1 && splitCharsLineNumY(cnt+1) == splitCharsLineNumY(cnt+2) : charSpacing_1 = charSpacing  ; 自身が複数文字でサイズ計測したものであれば、次の文字がsplitCharsMesxSum!=-1ときにcharSpacingを追加する。事前に改行だと分かっている場合は
    						}
    					}else {
    						_mesx1 = 0
    						if cnt+2 < splitNum {
    							if splitCharsMesxSum(cnt+1) != -1 && splitCharsLineNumY(cnt+1) == splitCharsLineNumY(cnt+2) : charSpacing_1 = charSpacing  ; 自身が複数文字でサイズ計測したものであれば、次の文字がsplitCharsMesxSum!=-1ときにcharSpacingを追加する
    						}
    					}
    					if px + mesx + charSpacing_1 + _mesx1 > objlayer_size_x {
    						tameKaihou = 2
    					}else : if cnt+2 < splitNum {
    						_mesx2 = splitCharsMesxSum(cnt+2)  ; マイナス値が入ることがあるが、その場合は拗音促音で改行になることはない
    						if px + mesx + charSpacing_1 + _mesx1 + charSpacing + _mesx2 > objlayer_size_x {
    							switch splitChars(cnt+2)
    								case "ぁ":case "ぃ":case "ぅ":case "ぇ":case "ぉ":case "ゃ":case "ゅ":case "ょ":case "っ":
    								case "ァ":case "ィ":case "ゥ":case "ェ":case "ォ":case "ャ":case "ュ":case "ョ":case "ッ":
    								tameKaihou = 2
    							swend
    						}
    					}
    				}
    				if tameKaihou == 0 {
    					if splitCharsDelay(cnt+1)>=0 {
    						if int(frm + splitCharsDelay(cnt+1))+startFrame > iparam : tameKaihou = 1
    					}else {
    						if int(frm + 1.0/-splitCharsDelay(cnt+1))+startFrame > iparam : tameKaihou = 1
    					}
    				}
    				if tameKaihou == 0 {
    					if splitChars_cmdIndex(cnt+1) != -1 {
    						preExecHspEmesCommand splitChars_cmd(splitChars_cmdIndex(cnt+1)), nowFontName, nowFontSize, nowFontStyle, nowFontDecoSize, nowFontColor, nowFontDecoColor, nowMesStyle, nowCharDelay
    						if stat : tameKaihou = 1
    					}
    				}
    				if tameKaihou == 0 : if splitChars(cnt+1) == "<br>" : tameKaihou = 3
    				if tameKaihou == 0 : if splitChars(cnt+1) == "<p>"  : tameKaihou = 3
    				if tameKaihou == 0 : if state != 5 : if splitChars(cnt+1) == "<d>" || splitChars(cnt+1) == "<w>" : tameKaihou = 1
    			}else {
    				tameKaihou = 1
    			}

    			if tameKaihou >= 2 {
    				// 次のcntは、改行する必要がある行頭の文字。簡易analyzed状態の場合はanalyzedIndexを戻して、再analayzedする。
    				if state == 1 : if cnt+2 < splitNum : if splitCharsLineNumY(cnt+(tameKaihou-2)) == splitCharsLineNumY(cnt+(tameKaihou-2)+1) : analyzedIndex = cnt+(tameKaihou-2)
    			}
    			// 貯め開放して文字描画
    			if tameKaihou {
    				if resetKuhakuWidth : pos -ginfo_sx,-ginfo_sy : mes " ",nowMesStyle : kuhakuWidth = ginfo_mesx : resetKuhakuWidth=0
    				_cnt = cnt : tameChars="" : tameCharsNum=0
    				repeat tameCharsArrayNum
    					tameChars += tameCharsArray(cnt) : tameCharsNum++
    					if platform!=3||fadeFrame==0 : if charSpacing == 0 : if cnt < tameCharsArrayNum-1 : if tameCharsFades(cnt) == tameCharsFades(cnt+1) : continue
    					fadeStyle = 0
    					#ifdef _HSP3DISH
    						if (layerbtn_stat & LAYBTN_SHOW_OUT)!=0 || (layerbtn_stat & LAYBTN_COMPLETE)!=0 || fadeFrame > 0 {
    							gmode 3,,,tameCharsFades(cnt) : fadeStyle = 16
    						}
    					#endif
    					pos objlayer_axis_x+(objlayer_size_x-p_allmesx)*limit(xx,0,2)/2 + tamePx, objlayer_axis_y+(objlayer_size_y-p_allmesy)*limit(yy,0,2)/2 + py+splitCharsMesyMax(_cnt)-splitCharsMesy(_cnt)
    					mes tameChars+" ",nowMesStyle|fadeStyle
    					tamePx += ginfo_mesx - kuhakuWidth + charSpacing
    					if tameCharsNum == 1 : splitCharsMesx(tameHeadIndex+cnt) = ginfo_mesx - kuhakuWidth
    					tameChars = "" : tameCharsNum=0
    					lastDraw_cx = (objlayer_size_x-p_allmesx)*limit(xx,0,2)/2 + tamePx - charSpacing
    					lastDraw_cy = (objlayer_size_y-p_allmesy)*limit(yy,0,2)/2 + py + splitCharsMesyMax(_cnt)
    				loop
    				tameCharsArrayNum = 0
    			}
    			px += mesx
    			if cnt+1 < splitNum : if splitCharsMesxSum(cnt+1) != -1 : px += charSpacing

    			// テキスト音鳴らし
    			if state!=4 {
    				if mmIndex >= 0 {
    					if lastDrawIndex_forMM < cnt {
    						#ifdef _HSP3DISH
    							getreq msTime, SYSREQ_TIMER
    						#else
    							#uselib "winmm.dll"
    							#cfunc timeGetTime "timeGetTime"
    							msTime = timeGetTime()
    						#endif
    						if msTime-lastMmplayTime >= 60 {  ; mmplay:最低60ms間隔を空ける
    							lastDrawIndex_forMM = cnt
    							if splitChars(cnt)!=" " && splitChars(cnt)!="　" : mmplay mmIndex : lastMmplayTime = msTime
    						}
    					}
    				}
    			}
    		loop
    	}
    	return

    //--------------------------------------
    // システム変数・拡張命令
    //--------------------------------------
    // 拡張システム変数
    #define global layemes_stat state@modlayemes
    #define global layemes_cnt count@modlayemes

    // フォント設定
    #define global layemes_font(%1="",%2=-1,%3=-1,%4=-1) layemes_font@modlayemes %1,%2,%3,%4
    #deffunc layemes_font@modlayemes str ___fontName, int ___fontSize, int ___fontStyle, int ___fontDecoSize, int ___mesStyle
    	if lparam != objlayer_cmdinit : return
    	if ___fontName != "" : nowFontName = ___fontName
    	if ___fontSize != -1 : nowFontSize = ___fontSize
    	if ___fontStyle != -1 : nowFontStyle = ___fontStyle
    	if ___fontDecoSize != -1 : nowFontDecoSize = ___fontDecoSize
    	FontName = nowFontName
    	FontSize = nowFontSize
    	FontStyle = nowFontStyle
    	FontDecoSize = nowFontDecoSize
    	return

    // 各種設定
    #define global layemes_settings(%1=0,%2=0,%3=0,%4=-1,%5=-1,%6=0) layemes_settings@modlayemes %1,%2,%3,%4,%5,%6
    #deffunc layemes_settings@modlayemes int _option, int _charSpacing, int _lineSpacing, int _mmId, int _keys, int _fade
    	if lparam != objlayer_cmdinit : return
    	;;; 表示関係
    	// 文章を描画し終わった後に非表示にしない
    	if _option & 1 {
    		Add_flagBits@_modlaybtn FLAGBT_OPTION_KEEP_VISIBLE@modlaybtn
    	}else {
    		Clear_flagBits@_modlaybtn FLAGBT_OPTION_KEEP_VISIBLE@modlaybtn
    	}
    	emesOption = _option
    	charSpacing = _charSpacing
    	lineSpacing = _lineSpacing
    	if _mmId != -1 : mmIndex = _mmId
    	if _keys != -1 : stkValue = _keys
    	fadeFrame = _fade
    	return

    // layerbutton の各種表示フレーム数設定
    #deffunc layemes_frames int _p5, int _p6, int _p7, int _p8, int _p9, int _p10
    	if lparam != objlayer_cmdinit : return
    	p5@_modlaybtn = _p5
    	p6@_modlaybtn = _p6
    	p7@_modlaybtn = _p7
    	p8@_modlaybtn = _p8
    	p9@_modlaybtn = _p9
    	p10@_modlaybtn = _p10
    	return

    //--------------------------------------
    // モジュール内で使用するローカル命令
    //--------------------------------------
    // 最後に描画した文字の後ろにカレントポジションを移動させる
    #deffunc Set_pos_lastChar@modlayemes array splitChars, array splitChars_cmdIndex, array splitChars_cmd, array splitCharsLineNumY, array splitCharsMesxSum, array splitCharsMesx, array splitCharsMesy, array splitCharsMesyMax, array splitCharsStartFrame, array splitCharsDelay
    	// このSet_posは文字が描画される前に呼び出される。残してあるlastDraw_cx(cy)より一文字多いターンかもしれないので確認。多ければ次の文字の分を考慮する。
    	_lastDrawIndex=-1
    	frm=0.0
    	if state == 1 && startFrame != -1 {
    		repeat , startIndex
    			if cnt >= splitNum : break
    			if splitCharsDelay(cnt)>=0 {
    				frm += splitCharsDelay(cnt)
    			}else {
    				frm += 1.0/-splitCharsDelay(cnt)
    			}
    			if int(frm)+startFrame > iparam : break
    			if splitChars(cnt) == "<p>" : break
    			if splitChars(cnt) == "<d>" || splitChars(cnt) == "<w>" : break
    			if lastDrawIndex < cnt {
    				_lastDrawIndex = cnt
    			}
    		loop
    	}
    	if lastDrawIndex != -1 && _lastDrawIndex != -1 && lastDrawIndex < _lastDrawIndex && _lastDrawIndex < splitNum && ((_lastDrawIndex-lastDrawIndex)==1 || (charDelay<-1&&(_lastDrawIndex-lastDrawIndex)<=-charDelay)) {
    		if splitCharsLineNumY(lastDrawIndex) == splitCharsLineNumY(_lastDrawIndex) {
    			plusMesx=0
    			repeat _lastDrawIndex-lastDrawIndex, lastDrawIndex+1
    				if cnt >= splitNum : break
    				if splitCharsMesx(cnt) > 0 : plusMesx += splitCharsMesx(cnt)
    			loop
    			if (lastDraw_cx+charSpacing + plusMesx) <= objlayer_size_x {
    				pos objlayer_axis_x + lastDraw_cx+charSpacing + plusMesx, objlayer_axis_y + lastDraw_cy
    			}else {
    				if splitCharsMesyMax(_lastDrawIndex) {
    					pos objlayer_axis_x + 0, objlayer_axis_y + lastDraw_cy+lineSpacing+splitCharsMesyMax(_lastDrawIndex)
    				}else {
    					pos objlayer_axis_x + lastDraw_cx, objlayer_axis_y + lastDraw_cy
    				}
    			}
    		}else {
    			if splitCharsMesyMax(_lastDrawIndex) {
    				pos objlayer_axis_x + 0, objlayer_axis_y + lastDraw_cy+lineSpacing+splitCharsMesyMax(_lastDrawIndex)
    			}else {
    				pos objlayer_axis_x + lastDraw_cx, objlayer_axis_y + lastDraw_cy
    			}
    		}
    	}else {
    		_lastDrawIndex = -1
    		pos objlayer_axis_x + lastDraw_cx, objlayer_axis_y + lastDraw_cy
    	}
    	if state == 0 || (lastDraw_cx == 0 && lastDraw_cy == 0) : pos -1, -1
    	if _lastDrawIndex != -1 : return _lastDrawIndex
    	return lastDrawIndex

    // 一文字ずつに分けつつ、コメント部分もコマンドテキストとして配列に格納
    #deffunc local split_char_emes str __str, array dst, array dst_cmdIndex, array dst_cmd
    	_str = __str
    	// 末尾の改行を削除
    	repeat
    		if strlen(_str)<2 : break
    		if wpeek(_str, strlen(_str)-2) != 0x0a0d : break
    		poke _str, strlen(_str)-2, 0
    	loop
    	if strlen(_str) > 0 : if strmid(_str,-1,1) != "$" : _str += "\n^"
        sdim dst, 32
    	dst_num = 0
    	sdim dst_cmd, 512
    	dim dst_cmdIndex
    	dst_cmd_num = 0
        len = strlen(_str)
        i = 0 : maeKaigyo = 1 : comment = 0 : commentStr = ""
        repeat
            if i >= len : break
            c = peek(_str, i)
    		if hspstat & $20000 {  ; utf8
    			if c < $80 {
    				bytes = 1
    			}else : if c < $E0 {
    				bytes = 2
    			}else : if c < $F0 {
    				bytes = 3
    			}else : if c < $F8 {
    				bytes = 4
    			}else : if c < $FC {
    				bytes = 5
    			}else {
    				bytes = 6
    			}
    		}else {  ; sjis
    			if (c >= $81 && c <= $9F) || (c >= $E0 && c <= $FC) {
    				bytes = 2
    			} else {
    				bytes = 1
    			}
    		}
            s = strmid(_str, i, bytes)
    		if i+1 < len : if wpeek(_str,i) == 0x0a0d : kaigyo=1: bytes=2 : else : kaigyo=0  ; 改行
    		if comment == 0 {
    			if s == ";" {
    				if maeKaigyo == 1 : comment=1: s=""  ; 行末までコメント
    			}else: if s == "^" {  ; 行末に「^」は『ページ送り』
    				s3 = strmid(_str, i, 3)
    				if s3 == "^\n" : bytes=strlen(s3) : kaigyo=1
    			}
    			if i+1 < len : if wpeek(_str,i) == 0x2a2f : comment=2: bytes=2: s=""  ; コメント開始「/*」
    		}
    		if comment {
    			// コメント
    			if comment == 1 && kaigyo {  ; コメントタイプ「;」 : 改行まで来たら処理
    				commentStr += ":"
    				comment = 0
    			}
    			if comment == 2 {  ; コメントタイプ「/* ... */」 : 終了まで来たら処理
    				if i+1 < len { if wpeek(_str,i) == 0x2f2a {
    					commentStr += ":"
    					comment = 0
    					bytes = 2
    				}}
    			}
    			if comment {
    				commentStr += s
    			}
    		}else {
    			// 文字記憶
    			if s=="~" {
    				dst(dst_num) = "<d>"
    			}else: if s=="^" {
    				if dst_num>0 : if dst(dst_num-1) == "<br>" : dst_num--  ; 一応、「^」ページ送り直前の改行は削除
    				dst(dst_num) = "<p>"
    			}else: if kaigyo {
    				dst(dst_num) = "<br>"
    			}else {
    				dst(dst_num) = s
    			}
    			// コメントがあれば記憶
    			if commentStr != "" {
    				dst_cmd(dst_cmd_num) = commentStr
    				dst_cmdIndex(dst_num) = dst_cmd_num
    				dst_cmd_num++
    				commentStr = ""
    			}else {
    				dst_cmdIndex(dst_num) = -1
    			}
    			dst_num++
    		}
            i += bytes : maeKaigyo = kaigyo
        loop
    	if dst_num <= 0 : return 0
    	if dst(dst_num-1) == "<br>" : dst_num--
    	if dst_num <= 0 : return 0
    	if dst(dst_num-1) != "<p>" && dst(dst_num-1) != "$" {
    		dst(dst_num) = "<p>"
    		dst_cmdIndex(dst_num) = -1
    		dst_num++
    	}
    	if dst(dst_num-1) == "$" : dst_num--
    	return dst_num

    // テキストのコメント部分のコマンドを抽出実行
    #deffunc local preExecHspEmesCommand  str __str, var fontName_, var fontSize_, var fontStyle_, var fontDecoSize_, var fontColor_, var decoColor_, var mesStyle_, var delay_
    	execHspEmesCommand  __str, fontName_, fontSize_, fontStyle_, fontDecoSize_, fontColor_, decoColor_, mesStyle_, delay_, 1
    	return
    #deffunc local execHspEmesCommand str __str, var fontName_, var fontSize_, var fontStyle_, var fontDecoSize_, var fontColor_, var decoColor_, var mesStyle_, var delay_, int pre
    	_str = __str
    	fontName__ = fontName_
    	fontSize__ = fontSize_
    	fontStyle__ = fontStyle_
    	fontDecoSize__ = fontDecoSize_
    	fontColor__ = fontColor_
    	decoColor__ = decoColor_
    	mesStyle__ = mesStyle_
    	delay__ = delay_
    	_isChangedFont = 0
    	_isChangedFontOrColor = 0
    	split _str, ":", cmds : cmdNum = stat
    	repeat cmdNum
    		split cmds(cnt), ",", prms : prmNum = stat
    		cmd = strtrim(prms(0), 0, ' ')
    		split cmd, " ", cmd, prm : prms(0) = prm
    		switch getpath(cmd,16)
    		case "font"
    			_isChanged = 0
    			if prmNum >= 1 : _fontName = strtrim(prms(0),0,' ') : _fontName = strtrim(_fontName,0,'"') : if _fontName != "" : if _fontName != fontName__ : _isChanged=1 : fontName__ = _fontName : if pre==0 : fontName_ = _fontName
    			if prmNum >= 2 : __fontSize = strtrim(prms(1),0,' ') : if __fontSize != "" : _fontSize = int(__fontSize) : if _fontSize != fontSize__ : _isChanged=1 : fontSize__ = _fontSize : if pre==0 : fontSize_ = _fontSize
    			if prmNum >= 3 : __fontStyle = strtrim(prms(2),0,' ') : if __fontStyle != "" : _fontStyle = int(__fontStyle) : if _fontStyle != fontStyle__ : _isChanged=1 : fontStyle__ = _fontStyle : if pre==0 : fontStyle_ = _fontStyle
    			if prmNum >= 4 : __fontDecoSize = strtrim(prms(3),0,' ') : if __fontDecoSize != "" : _fontDecoSize = int(__fontDecoSize) : if _fontDecoSize != fontDecoSize__ : _isChanged=1 : fontDecoSize__ = _fontDecoSize : if pre==0 : fontDecoSize_ = _fontDecoSize
    			if _isChanged {
    				if pre == 0 : font_ fontName_, fontSize_, fontStyle_, fontDecoSize_
    				_isChangedFont = 1
    			}
    			swbreak
    		case "rgbcolor"
    			rgb = 0
    			if prmNum >= 1 {
    				rgbstr = strtrim(prms(0),0,' ')
    				if strmid(rgbstr,0,2) == "0x" {
    					rgb = int("$"+strmid(rgbstr,2,32))
    				}else : if strmid(rgbstr,0,1) == "#" {
    					rgb = int("$"+strmid(rgbstr,1,32))
    				}else{
    					rgb = int(rgbstr)
    				}
    			}
    			if fontColor__ != rgb {
    				fontColor__ = rgb
    				if pre == 0 : fontColor_ = rgb : rgbcolor fontColor_
    				_isChangedFontOrColor = 2
    			}
    			swbreak
    		case "color"
    			r=0 : g=0 : b=0
    			if prmNum >= 1 : r = int(strtrim(prms(0),0,' ')) & $FF
    			if prmNum >= 2 : g = int(strtrim(prms(1),0,' ')) & $FF
    			if prmNum >= 3 : b = int(strtrim(prms(2),0,' ')) & $FF
    			rgb = (r<<16) | (g<<8) | b
    			if fontColor__ != rgb {
    				fontColor__ = rgb
    				if pre == 0 : fontColor_ = rgb : rgbcolor fontColor_
    				_isChangedFontOrColor = 2
    			}
    			swbreak
    		case "objcolor"
    			r=0 : g=0 : b=0
    			if prmNum >= 1 : r = int(strtrim(prms(0),0,' ')) & $FF
    			if prmNum >= 2 : g = int(strtrim(prms(1),0,' ')) & $FF
    			if prmNum >= 3 : b = int(strtrim(prms(2),0,' ')) & $FF
    			rgb = (r<<16) | (g<<8) | b
    			if decoColor__ != rgb {
    				decoColor__ = rgb
    				if pre == 0 : decoColor_ = rgb : objcolor (decoColor_>>16)&$FF, (decoColor_>>8)&$FF, (decoColor_)&$FF
    				_isChangedFontOrColor = 2
    			}
    			swbreak
    		case "mes"
    			if prmNum >= 2 {
    				_style = int(strtrim(prms(1),0,' '))
    				if _style != mesStyle__ {
    					mesStyle__ = _style
    					if pre == 0 : mesStyle_ = _style
    					_isChangedFontOrColor = 2
    				}
    			}
    			swbreak
    		case "text"
    			if prmNum >= 1 {
    				_delay = int(strtrim(prms(0),0,' '))
    				if _delay != delay__ {
    					delay__ = _delay : delay_ = _delay
    				}
    			}
    			swbreak
    		swend
    	loop
    	return _isChangedFont + _isChangedFontOrColor

    #deffunc local font_ str __fontname, int __p1, int __p2, int __p3
    	#ifdef _HSP3DISH
    		dupptr bm, objinfo_bmscr(0), 178*4
    		dupptr fname, objinfo_bmscr(0)+142*4, 64, 2
    		if __p1 != bm(158) || __p2 != bm(159) || __p3 != bm(177) || __fontname != fname {
    			font __fontname, __p1, __p2, __p3
    		}
    	#else
    		font __fontname, __p1, __p2, __p3
    	#endif
    	return
    #global
    #endif