HSPに投稿されたコード一覧

HSP 【HSP3】DXライブラリのDxDLL.cs(C#)をHSPのasに変換するアレ(手抜き)Ver.3(2015/08/10)

#module
// 指定オフセットから右から検索していき見つけた位置を返す。(1byteのみ)
#defcfunc searchR1 str _in, int ps, int sh
	idx = -1
	in = _in
	max = strlen(in)
	repeat max, ps
		if peek(in, max-cnt) == sh : idx = max-cnt : break
	loop
return idx
// instr 右から検索版
#defcfunc instrl var s1, str s2
ind = 0
repeat
	res = instr(s1, ind, s2)
	if res == -1 : break
	ind += res + 1
loop
return ind-1
#defcfunc GetMacroName str _tmp, var macro, var const
	sdim tmp, 1024
	tmp = _tmp
	sdim macro, 128
	sdim const, 128
	flag = 0
	if instr(tmp, 0, "public const int ") != -1{
		flag = 1
		sdim res, 128
		split tmp, " ", res
		;markpos = -1
		repeat length(res)
			if res(cnt) == "="{
				tmpcnt = cnt
				// スペースの可能性を考慮して検索(マクロ名を取得)
				repeat tmpcnt
					tmpcnt--
					if res(tmpcnt) != ""{
						macro = res(tmpcnt)
						break
					}
				loop
				// スペースの場合があるので連結処理をする(定数値を取得)
				tmpcnt = cnt + 1	// 足しておく
				sdim tmpconst, 128
				repeat length(res)-tmpcnt, tmpcnt
					tmpconst += res(cnt)+" "
				loop
				// セミコロンを除去
				tmpconst = strtrim(tmpconst, 0, ' ')
				const = strtrim(tmpconst, 0, ';')
						//
			}
		loop
	}
return flag
// 戻り値の型を取得します。とれないときは空。
#defcfunc GetFuncReturn str _lineTmp, str _funcName
	sdim lineTmp, 1024
	lineTmp = _lineTmp
	if instr(lineTmp, 0, "extern") != -1{
		_posFuncName = instr(lineTmp, 0, _funcName)
		if _posFuncName != -1{
			_trimedFuncLine = strmid(lineTmp, 0, _posFuncName)
			strrep _trimedFuncLine, "extern unsafe static ", ""
			strrep _trimedFuncLine, "extern static ", ""
			strrep _trimedFuncLine, "\t", ""
			_trimedFuncLine = strtrim(_trimedFuncLine, 0, ' ')
			return _trimedFuncLine
		}
	}
return ""
#defcfunc GetFuncName str _tmp, var _fnc, array _arg, var _retType
	sdim tmp, 1024
	tmp = _tmp
	sdim _arg, 256 : sdim _fnc, 128
	num = -1
	if instr(tmp, 0, "extern") != -1{
		num = 0
		ks = instr(tmp, 0, "(")
		ke = instrl(tmp, ")")
		if ks != -1 | ke != -1{
			args = strmid(tmp, ks+1, ke-ks-1)
			tmp2 = strmid(tmp, 0, ks)
			tmp2 = strtrim(tmp2, 0, ' ')
			ps = searchR1(tmp2, 0, ' ')
			if ps != -1 {
				// 関数名を取得
				tmp3 = strmid(tmp2, ps, strlen(tmp2))
				_fnc = strtrim(tmp3, 0, ' ')

				// 末尾が_x64の場合(対象外として-1を返す)
				if "_x64" == strmid(_fnc, -1, strlen("_x64")){
					return -1
				}

				// 末尾が_x86の場合(取り除きます)
				if "_x86" == strmid(_fnc, -1, strlen("_x86")){
					_fnc = strmid(_fnc, 0, strlen(_fnc) - strlen("_x86"))
				}

				// 戻り値の型を取得
				_retType = GetFuncReturn(tmp, _fnc)

				// 引き続き引数を取得
				// 引数がないケースを取得
				cargs = args
				cargs = strtrim(cargs, 3, ' ')
				cargs = strtrim(cargs, 3, '\t')
				if cargs == "" : num = 0 : return num
				// 引数ありのケース
				sdim tmp2
				split args, ",", tmp2
				num = stat
				repeat num
					tmp3 = tmp2(cnt)
					tmp3 = strtrim(tmp3, 3, '\t')
					tmp3 = strtrim(tmp3, 0, ' ')
					ps = searchR1(tmp3, 0, ' ')
					if ps != -1{
						tmp4 = strmid(tmp3, 0, ps)
						tmp4 = strtrim(tmp4, 0, ' ')
						_arg(cnt) = tmp4
					}
				loop
			}
		}
	}
return num
#global

	dialog "cs",16
	if stat == 0 : end
	fname = refstr

	notesel buf
	noteload fname

	sdim def, 1024*512
	sdim fncs, 1024*512

	repeat notemax
		noteget tmp, cnt
		if GetMacroName(tmp, macro, const){
			def += "#define global "+ macro +" "+ const +"\n"
		}
		num = GetFuncName(tmp, fnc, arg, ret)
		if num != -1{
			sdim outargs
			repeat num
				// 引数で使われているものだけピックアップしているので構造体は全部ではない。
				if arg(cnt) == "int" || arg(cnt) == "ulong" || arg(cnt) == "uint" || arg(cnt) == "char"{
					outargs += "int"
				}else:if arg(cnt) == "System.Text.StringBuilder" || arg(cnt) == "string"{
					outargs += "str"
				}else:if arg(cnt) == "double"{
					outargs += "double"
				}else:if arg(cnt) == "float"{
					outargs += "float"
				}else:if arg(cnt) == "VECTOR"{
					outargs += "float,float,float"
				}else:if arg(cnt) == "VECTOR_D"{
					outargs += "double,double,double"
				}else:if arg(cnt) == "UV"{
					outargs += "float,float"
				}else:if arg(cnt) == "COLOR_F" || arg(cnt) == "FLOAT4"{
					outargs += "float,float,float,float"
				}else:if arg(cnt) == "COLOR_U8"{
					outargs += "int"
				}else:if arg(cnt) == "IPDATA" || arg(cnt) == "IPDATA_IPv6"{
					outargs += "int"
				}else:if arg(cnt) == "RECT" || arg(cnt) == "INT4"{	// ポインタとかは "RECT *" といった感じに来ます。
					outargs += "int,int,int,int"
				}else:if arg(cnt) == "MATRIX"{
					outargs += "float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float"
				}else:if arg(cnt) == "MATRIX_D"{
					outargs += "double,double,double,double,double,double,double,double,double,double,double,double,double,double,double,double"
				}else:if arg(cnt) == "MV1_COLL_RESULT_POLY"{
					outargs += "int,float,float,float,int,int,int,float,float,float,float,float,float,float,float,float,float,float,float"
				}else:if arg(cnt) == "MV1_REF_POLYGON"{
					outargs += "int,int,int,int,int,float,float,float,float,float,float"
				}else:if arg(cnt) == "MV1_REF_VERTEX"{
					outargs += "float,float,float,float,float,float"
				}else:if arg(cnt) == "MATERIALPARAM"{
					outargs += "float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float"
				}else:if arg(cnt) == "HITRESULT_LINE"{
					outargs += "int,float,float,float"
				}else:if arg(cnt) == "MV1_COLL_RESULT_POLY_DIM"{
					outargs += "int,int"
				}else:if arg(cnt) == "System.IntPtr"{
					outargs += "sptr"
				}else:if arg(cnt) == "void"{
					outargs += ""
				}else{
					// out~、*は気にしない
					// logmes arg(cnt)
					outargs += "sptr"
				}
				// 最後以外は , をつける
				if cnt != num - 1 : outargs += ","
			loop

			// 戻り値の型をチェックします(構造体のもの)
			retTypeStruct = 0
			if ((ret == "COLOR_F") || (ret == "COLOR_U8") || (ret == "DISPLAYMODEDATA") || (ret == "DOUBLE4") || (ret == "FLOAT4") || (ret == "HITRESULT_LINE") || (ret == "MATRIX") || (ret == "MATRIX_D") || 	(ret == "MV1_COLL_RESULT_POLY") ||(ret == "MV1_COLL_RESULT_POLY_DIM") || (ret == "VECTOR") ||(ret == "VECTOR_D")){
				retTypeStruct = 1
		 	}

		 	if retTypeStruct == 1{
				fncs += "// 戻り値が構造体です(" + ret +")\n// 第一引数に戻り値を返却します。パラメタは第二引数以降にずれます。\n"
				outargs = "var," + outargs
			}

			// 接頭辞の dx_ を外す(手抜き)
			split fnc, "dx_", fnc2
			fncs += "#func global "+ fnc2(1) +" \""+ fnc +"\" "+outargs+"\n"
		}
	loop

	def2 = {"// VECTOR => float, float, float
#define global ctype VGet(%1,%2,%3) %1, %2, %3
#define global ctype VAdd(%1,%2,%3,%4,%5,%6) %1+%4, %2+%5, %3+%6
#define global ctype VSub(%1,%2,%3,%4,%5,%6) %1-%4, %2-%5, %3-%6
#define global ctype VDot(%1,%2,%3,%4,%5,%6) %1*%4+%2*%5+%3*%6
#define global ctype VCross(%1,%2,%3,%4,%5,%6) %2*%6-%3*%5, %3*%4-%1*%6, %1*%5-%2*%4
#define global ctype VScale(%1,%2,%3,%4) %1*%4, %2*%4, %3*%4
#define global ctype VSquareSize(%1,%2,%3) %1*%1+%2*%2+%3*%3
// 行列だからdimの方が良いのか…(MATRIX 4x4)
#define global ctype VTransform(%1,%2,%3, %4,%5,%6,%7, %8,%9,%10,%11, %12,%13,%14,%15, %16,%17,%18,%19) %1*%4 + %2*%8 + %3*%12 + %16, %1*%5 + %2*%9 + %3*%13 + %17, %1*%6 + %2*%10 + %3*%14 + %18
#define global ctype VTransformSR(%1,%2,%3, %4,%5,%6,%7, %8,%9,%10,%11, %12,%13,%14,%15, %16,%17,%18,%19) %1*%4 + %2*%8 + %3*%12, %1*%5 + %2*%9 + %3*%13, %1*%6 + %2*%10 + %3*%14
// VConvFtoD, VConvDtoF未実装
#define global VGetD VGet
#define global VAddD VAdd
#define global VSubD VSub
#define global VDotD VDot
#define global VCrossD VCross
#define global VScaleD VScale
#define global VSquareSizeD VSquareSize
#define global VTransformD VTransform
#define global VTransformSRD VTransformSR
"}

	sdim outbuf, 1024*5120
	notesel outbuf
	noteadd "// "
	noteadd "// DxLib for HSP " + strf("(%04d/%02d/%02d)", gettime(0), gettime(1), gettime(3))
	noteadd "// http://hsp.moe/"
	noteadd "// https://twitter.com/hk1v"
	noteadd "// by inovia."
	noteadd "// "
	noteadd "// 【本モジュールを利用するにはC#版に付属しているDxLib.dllが必要です】"
	noteadd "// http://homepage2.nifty.com/natupaji/DxLib/dxdload.html"
	noteadd "// "
	noteadd "// ※本モジュールをスムーズに使用するには、構造体に対する理解が必要です。"
	noteadd "// また、C言語で書いてあるソースがそれとなく分かるぐらいの知識が必要です。"
	noteadd "// (世の中にあるDxLibのサンプルコードのほとんどがC/C++/C#なので)"
	noteadd "// HSPの知識だけですと、かなりきついと思います。"
	noteadd "// 推奨レベル:★★★★☆(Lv.4) 当社比...?"
	noteadd "// "
	noteadd "// 【旧バージョンのDxLib.as】"
	noteadd "// http://hsp.moe/download/DxLib_old.as"
	noteadd "// 【TIPS】"
	noteadd "// 構造体が戻り値の場合、HSPがクラッシュする問題(解決方法)"
	noteadd "// http://codetter.com/?p=1192"
	noteadd "// DxLib関連のサンプル(HSP用)"
	noteadd "// http://codetter.com/?extag=dxlib"
	noteadd "// HSPとDxLibで2D描画の基礎ら辺とか(えくー氏)"
	noteadd "// http://fe0km.blog.fc2.com/blog-entry-53.html"
	noteadd "// hspからDXlibの利用方法について"
	noteadd "// http://hsp.tv/play/pforum.php?mode=all&num=70321"
	noteadd "#ifndef __DXLIB__"
	noteadd "#define __DXLIB__"
	noteadd "// 定義ファイルのバージョン(=作成時のDxLibのバージョン+連番4桁数字)"
	noteadd "#define DEFINE_DXLIB_VERSION \"3.14f0000\""
	noteadd "#uselib \"DxLib.dll\""
	noteadd fncs
	noteadd def
	noteadd def2
	noteadd "#endif"
	notesave "DxLib.as"

	end

HSP 【HSP3】構造体を戻り値とするDXライブラリの関数をHSPで呼び出すテスト

// http://sprocket.babyblue.jp/html/hsp_koneta3.htm
#module
#defcfunc todouble int p1
	temp = 0.0
	lpoke temp, 4, (p1 & 0x80000000) | (((p1 & 0x7fffffff) >> 3) + ((p1 & 0x7fffffff) ! 0) * 0x38000000)
	lpoke temp, 0, p1 << 29
return temp
#global
;
#runtime "hsp3cl"
#include "DxLib.as"
;
// 【参考】元の形式
; #func global ConvWorldPosToScreenPos "dx_ConvWorldPosToScreenPos" float,float,float
;
// 第一引数に戻り値を格納するポインタを指定する(そのため、引数が1つずれます)
#func global _ConvWorldPosToScreenPos "dx_ConvWorldPosToScreenPos" var,float,float,float
;
	ChangeWindowMode TRUE			// ウィンドウモードになる
	SetDoubleStartValidFlag TRUE	// 多重起動を許可
;
	DxLib_Init
;
	px = 0.0f
	py = 0.0f
	pz = 100.0f
;
	; 戻り値を格納するVECTOR構造体(12bytes)
	dim VECTOR, 3
	_ConvWorldPosToScreenPos VECTOR, VGet(px, py, pz)
;
	; ポインタ(同じ値を指します)
	mes "ptr:" + stat
	mes "ptr:" + varptr(VECTOR)
;
	; 結果
	mes todouble(vector.0)
	mes todouble(vector.1)
	mes todouble(vector.2)
;

HSP 二重振り子RK4シミュonHSP

#packopt name "expt"

*mkwnds
	#define wsizex 800
	#define wsizey 600
	screen 0, wsizex,wsizey, 0

*init
	#define dt	0.01	;[s] タイムステップ
	#const double hdt dt/2	;[s] dt/2
	#define g	9.8	;[m/s^2]
	#define σ	1.0	;[kg/m^2] 錘の面密度
	#define l1	2.5	;[m]
	#define l2	1.5	;[m]
	#define r1	0.5	;[m] 錘1の半径
	#define r2	0.3	;[m] 〃2
	#const double m1	4.0*m_pi*σ*r1*r1
	#const double m2	4.0*m_pi*σ*r2*r2
		//#const double η		(m1+m2)/m2	;コンパイルエラー
		//↓
		η = (m1+m2)/m2
	θ1 = deg2rad(135)
	θ2 = deg2rad(180)
	ω1 = 0.0
	ω2 = 0.0

	#define mtr2px	100.0	;[px/meter] メートル→ピクセル 変換係数
	#const double wOx	wsizex/2	;[px] 物理系原点のウィンドウ上でのx座標
	#const double wOy	200.0
	#const double l1w	l1*mtr2px	;[px] l1のウィンドウ上での長さ
	#const double l2w	l2*mtr2px	;[px]
	#const double r1w	r1*mtr2px	;[px]
	#const double r2w	r2*mtr2px	;[px]
	#define frmIntvl	16	;[ms] フレーム間隔

*main
	etlf = frmIntvl	;[ms] 前回画面更新からの経過時間
	repeat
		gosub *step
		if etlf >= frmIntvl : gosub *draw : etlf = -dt*1000
		await dt*1000 : etlf += dt*1000
	loop

*step	//dt後の状態を計算
	ξn = θ1,θ2,ω1,ω2 : k1 = f1(ξn),f2(ξn),f3(ξn),f4(ξn)
	ξn2 = ξn+hdt*k1, ξn(1)+hdt*k1(1), ξn(2)+hdt*k1(2), ξn(3)+hdt*k1(3) : k2 = f1(ξn2),f2(ξn2),f3(ξn2),f4(ξn2)
	ξn3 = ξn+hdt*k2, ξn(1)+hdt*k2(1), ξn(2)+hdt*k2(2), ξn(3)+hdt*k2(3) : k3 = f1(ξn3),f2(ξn3),f3(ξn3),f4(ξn3)
	ξn4 = ξn+dt*k3, ξn(1)+dt*k3(1), ξn(2)+dt*k3(2), ξn(2)+dt*k3(3) : k4 = f1(ξn4),f2(ξn4),f3(ξn4),f4(ξn4)
	θ1 += dt/6*(k1+k2+k3+k4)
	θ2 += dt/6*(k1(1)+k2(1)+k3(1)+k4(1))
	ω1 += dt/6*(k1(2)+k2(2)+k3(2)+k4(2))
	ω2 += dt/6*(k1(3)+k2(3)+k3(3)+k4(3))
	return

#module func
	#define g	g@
	#define l1	l1@
	#define l2	l2@
	#define η	η@

	#defcfunc f1 array ξ
		return ξ(2)

	#defcfunc f2 array ξ
		return ξ(3)

	#defcfunc f3 array ξ
		θ1 = ξ : θ2 = ξ(1) : ω1 = ξ(2) : ω2 = ξ(3)
		φ = θ1-θ2 : cosφ = cos(φ)
		return (g*(cosφ*sin(θ2)-η*sin(θ1))-(l1*ω1*ω1*cosφ+l2*ω2*ω2)*sin(φ))/l1/(η-cosφ*cosφ)

	#defcfunc f4 array ξ
		θ1 = ξ : θ2 = ξ(1) : ω1 = ξ(2) : ω2 = ξ(3)
		φ = ξ-ξ(1) : cosφ = cos(φ)
		return (g*η*(cosφ*sin(θ1)-sin(θ2))+(η*l1*ω1*ω1+l2*ω2*ω2*cosφ)*sin(φ))/l2/(η-cosφ*cosφ)
#global

*draw	//描画
	redraw 0
		color : boxf
		color 100,100,100
		line -1,wOy, wsizex,wOy : line wOx,-1, wOx,wsizey
		color 255,255,255
		xtmp = wOx+l1w*sin(θ1) : ytmp = wOy+l1w*cos(θ1)
		line wOx,wOy, xtmp,ytmp : circle xtmp-r1w,ytmp-r1w, xtmp+r1w,ytmp+r1w, 0
		xtmp2 = xtmp + l2w*sin(θ2) : ytmp2 = ytmp + l2w*cos(θ2)
		line xtmp,ytmp,xtmp2,ytmp2 : circle xtmp2-r2w,ytmp2-r2w, xtmp2+r2w,ytmp2+r2w, 0
	redraw 1
	return

HSP 任意の型の引数を任意の数だけ取る関数(可変長引数を取る関数)の実装

//-----------------------------------------------------------------------------------------
// 可変長引数(笑)                                                                       |
//                                                                       2015/07/04  Flat |
//-----------------------------------------------------------------------------------------

/*
■特徴
    コードセグメントを直に読みます
    ですので無限に引数を付けられます
    更にあらゆる型の引数を受け付けます
    言い換えれば型の自動変換がありません

    尤も、あらゆる型を受け付けられてもその型の処理ができなければ意味がありませんがね!

■使用できる型
    現在対応している型は
      ・空引数
      ・ユーザー定義命令・関数
      ・変数、配列(※)
      ・その他HSPの変数に格納できる全ての型
    となります
    vfunc関数を編集すれば他の型にも対応可能です

    ※配列は正常に動作しないことがあります(文字列型など)
      おそらくHSPのバグまたは仕様なので、ランタイムの方を編集してください

■注意
    ・vfuncから呼び出された関数の中でvfuncを呼び出すとreturn時に死にます
      これはvfuncから他の関数を呼び出す際に定義情報を無理矢理書き換えている関係です
      根本的な解決策は現在見つかっていません…

    ・関数内からvfuncを呼び出す際、引数に関数の引数(ローカル変数含む)は使えません
      これは引数の評価処理がvfunc内部で行われているためで、根本的な解決策は(略)

■その他
    vfuncは命令形式の呼び出しですが、少し書き換えるだけで関数形式の呼び出しにできます
    つまり、今まで夢だった関数へのラベル渡しもできます

■使い方
    使い方はサンプルを見たほうが早いので、ここでは割愛します
*/

// 引数格納庫
// タイプが-1のときは引数の変数をクローンする
#module ParameterStore m_type, m_var
#modinit int p_type, array p_var
	m_type = p_type
	if m_type == -1 {
		dup m_var, p_var
	} else {
		m_var = p_var
	}
	return

#modcfunc gettype
	return m_type

#modcfunc getparam
	return m_var

#modfunc  dupparam var p_var
	dup p_var, m_var
	return
#global

// 可変長引数モジュール
#module Variadic
// PVal取得関数
// http://d.hatena.ne.jp/chaperatta/20081012/1223803468
#defcfunc local getpval var
#deffunc local _getpval int p_pval
	return p_pval

// コールバック用ダミー関数
#deffunc local callback
	return

// 可変長引数で任意の関数を呼び出す関数
// vfunc 呼び出す関数, 引数1, 引数2, 引数3, …
#deffunc vfunc \
local param, local param_index, local param_num, \
local hspctx, local hsphed, local mcs, local cs, local callback_st, \
local pcs, local old_pcs, local code_num, \
local info, local is48, local ex0, local ex1, local ex2, local type, local code, \
local params, local size, local label, local vtype, local bytecode, local func_st, \
local flag, local t_offset, local t_type, local t_code, \
local func

	// ローカル変数paramのインデックスを取得
	// 次がparamの参照となるようなラベルを作成
	newlab label, 0
	param = 0
	// その場所のコードを取得
	dupptr cs, lpeek(label, 0), 6, 2
	// インデックス(=Code)を取得
	if wpeek(cs, 0) & 0x8000 {
		param_index = lpeek(cs, 2)
	} else {
		param_index = wpeek(cs, 2)
	}

	// CSを取得
	// HSPCTX取得
	mref hspctx, 68
	// HSPHED取得
	dupptr hsphed, hspctx(0), 96, 4
	// 関数呼び出し元のCSポインタ取得
	dupptr mcs, hspctx(207) - 16, 4
	// CSポインタからCSを取得
	dupptr cs, mcs, hsphed(5) - (hspctx(2) - mcs)

	// CSをなめる
	// http://codetter.com/?p=1165 からパクった
	pcs       = 0
	old_pcs   = 0
	param_num = 0
	code_num  = 0
	repeat
		// ExやType等取得
		info = wpeek(cs, pcs)
		is48 = info & 0x8000
		ex2  = info & 0x4000
		ex1  = info & 0x2000
		ex0  = info & 0x1000
		type = info & 0x0FFF

		// 引数の区切り
		if ex1 | ex2 {
			// 引数のコードサイズ
			size = pcs - old_pcs

			// 例外処理
			vtype = 0
			switch wpeek(cs, old_pcs) & 0x0FFF
				// 空引数
				case 0
					if wpeek(cs, old_pcs) & 0x8000 {
						t_code = lpeek(cs, old_pcs + 2)
					} else {
						t_code = wpeek(cs, old_pcs + 2)
					}
					if t_code != 0x3F : swbreak

					// とりあえず0にでもしておく
					param = 0
					// vtypeセット
					vtype = -3
					swbreak

				// 変数及び配列の要素
				case 1/*TYPE_VAR*/
					flag = 0
					if code_num == 1 {
						// 変数
						flag = 1
					} else : if code_num >= 4 {
						// 配列の要素?
						// TYPE_VARの直後が'('で末尾が')'なら配列の要素とみなす
						// a(3) * a(2) などはコンパイル後 a(3) a(2) * となるので問題はなさそう
						flag = 1
						t_offset = old_pcs
						repeat code_num
							t_type = wpeek(cs, t_offset) & 0x0FFF

							if wpeek(cs, t_offset) & 0x8000 {
								t_code = lpeek(cs, t_offset + 2)
								t_offset += 6
							} else {
								t_code = wpeek(cs, t_offset + 2)
								t_offset += 4
							}

							if type == 11/*TYPE_CMPCMD*/ {
								t_offset += 2
							}

							switch cnt
								// 先頭のチェック
								case 1
									if t_type ==  0x000 : swbreak
									if t_code == 0x0028 : swbreak

									flag = 0
									break

								// 末尾のチェック
								case code_num - 1
									if t_type ==  0x000 : swbreak
									if t_code == 0x0029 : swbreak

									flag = 0
									break
							swend
						loop
					}
					if flag {
						// バイトコードの生成
						sdim bytecode, size + 18
						wpoke bytecode, 0, 0x200F					// dup
						wpoke bytecode, 2, 0x000E
						wpoke bytecode, 4, 0x8005					// param
						lpoke bytecode, 6, param_index
						memcpy bytecode, cs, size, 10, old_pcs		// 変数、配列の要素
						wpoke bytecode, size + 10, 0x200F			// return
						wpoke bytecode, size + 12, 0x0002
						wpoke bytecode, size + 14, 0x200F			// return(なんでもいいので何かひとつ必要)
						wpoke bytecode, size + 16, 0x0002

						// 先頭のEx2フラグを立てる
						wpoke bytecode, 10, wpeek(bytecode, 10) | 0x4000

						// バイトコード呼び出し
						newlab label, 0
						lpoke label, 0, varptr(bytecode)
						gosub label

						// vtypeセット
						vtype = -1
					}
					swbreak

				// ユーザー定義関数
				case 12/*TYPE_MODCMD*/
					if code_num != 1 : swbreak

					// バイトコードの生成
					sdim bytecode, size + 20
					wpoke bytecode,  0, 0x200F					// return
					wpoke bytecode,  2, 0x0002
					wpoke bytecode,  4, 0x0011					// libptr
					wpoke bytecode,  6, 0x0103
					wpoke bytecode,  8, 0x0000					// (
					wpoke bytecode, 10, 0x0028
					memcpy bytecode, cs, size, 12, old_pcs		// 関数
					wpoke bytecode, size + 12, 0x0000			// )
					wpoke bytecode, size + 14, 0x0029
					wpoke bytecode, size + 16, 0x200F			// return(なんでもいいので何かひとつ必要)
					wpoke bytecode, size + 18, 0x0002

					// 先頭のEx2フラグを下ろす
					wpoke bytecode, 12, wpeek(bytecode, 12) & 0xBFFF

					// バイトコード呼び出し
					newlab label, 0
					lpoke label, 0, varptr(bytecode)
					gosub label

					// param、vtypeセット
					param = stat
					vtype = -2
					swbreak
			swend

			if vtype == 0 {
				// バイトコードの生成
				sdim bytecode, size + 18
				wpoke bytecode, 0, 0xA005					// param
				lpoke bytecode, 2, param_index
				wpoke bytecode, 6, 0x0000					// =
				wpoke bytecode, 8, 0x0008
				memcpy bytecode, cs, size, 10, old_pcs		// 引数
				wpoke bytecode, size + 10, 0x200F			// return
				wpoke bytecode, size + 12, 0x0002
				wpoke bytecode, size + 14, 0x200F			// return(なんでもいいので何かひとつ必要)
				wpoke bytecode, size + 16, 0x0002

				// 先頭のEx2フラグを下ろす
				wpoke bytecode, 10, wpeek(bytecode, 10) & 0xBFFF

				// バイトコード呼び出し
				newlab label, 0
				lpoke label, 0, varptr(bytecode)
				gosub label

				// vtypeセット
				vtype = vartype(param)
			}

			// 処理
			if param_num < 1 {
				// vfuncが使用する引数
				switch param_num
					// 最初の引数(呼び出す関数)
					case 0
						if (vtype != -2) && (vartype(param) != 4) {
							// エラーを引き起こす
							_errorfunc@Variadic 123
						}
						func = param
						swbreak
				swend
			} else {
				// ユーザー定義関数に渡す引数
				newmod params, ParameterStore, vtype, param
			}

			// paramクリア
			dim param

			// 情報更新
			code_num = 0
			old_pcs  = pcs
			param_num++
		}

		// 引数終了
		if ex1 {
			break
		}

		// ポインタを進める
		pcs += 2

		// Code取得
		if is48 {
			code = lpeek(cs, pcs)
			pcs += 4
		} else {
			code = wpeek(cs, pcs)
			pcs += 2
		}

		// TYPE_CMPCMDのときはジャンプ先が記録されている
		// 一応書いておいたが、不要かもしれない
		if type == 11/*TYPE_CMPCMD*/ {
			pcs += 2
		}

		// デバッグ用
		;mes strf("%08X %d %d %d %d %4d %08X", pcs, is48!=0, ex0!=0, ex1!=0, ex2!=0, type, code)

		// コード数更新(あとで使用する)
		code_num++
	loop

	// 引数不足のチェック
	if param_num < 1 {
		// エラーを引き起こす
		_errorfunc@Variadic
		return
	}

	// callbackを弄る
	dupptr callback_st, libptr(callback@Variadic), 28, 2
	dupptr func_st, func, 28, 2
	memcpy callback_st, func_st, 28

	// callback呼び出し
	callback@Variadic params

	// 引数解放
	foreach params
		delmod params(cnt)
	loop

	// 戻り先を修正
	mcs += pcs
	return

#deffunc local _errorfunc str a
	return
#global

// 以下サンプル、#if 0を#if 1にして動作
#if 0
// テスト関数
#module
#deffunc testfunc array p_params, \
local type, local var
	mes strf("NUM OF PARAMS: %d", length(p_params))
	foreach p_params
		// 引数の種類を取得
		type = gettype(p_params(cnt))

		// 引数を変数にクローン
		dupparam p_params(cnt), var

		// 表示してみる
		switch type
			case -3
				mes strf("TYPE: EMPTY")
				swbreak

			case -2
				mes strf("TYPE: FUNCTION,  PTR TO STRUCTDAT: %08X", var)
				swbreak

			case -1
				if length(var) > 1 {
					mes strf("TYPE: ARRAY[%d],  DATA[0]:          %s", length(var), str(var(0)))
				} else {
					mes strf("TYPE: VARIABLE,  DATA:             %s", str(var))
				}
				swbreak

			case 1
				mes strf("TYPE: LABEL,     DESTINATION:      %08X", lpeek(var, 0))
				swbreak

			case 2
				mes strf("TYPE: STRING,    DATA:             %s", var)
				swbreak

			case 3
				mes strf("TYPE: DOUBLE,    DATA:             %g", var)
				swbreak

			case 4
				mes strf("TYPE: INTEGER,   DATA:             %d", var)
				swbreak

			default
				mes strf("TYPE: %d", var)
				swbreak
		swend
	loop
	return
#global

*label
	abc = "a", "b", "c"
	def = 1, 2, 3, 4

	vfunc testfunc, 2, "xyz", 3.14, *label, 4 * 5, "3" + 4, 4.6
	mes

	vfunc testfunc, abc, def, abc(1), def(2), testfunc
	mes

	vfunc testfunc, , , , 5
	mes
#endif

HSP モジュール配列の自動拡張

// モジュール配列の自動拡張のテスト

#module
#deffunc func var p
	return
#global

#module testmod q
#modinit int r
	q = r
	mes "### newmod " + q
	return

#modterm
	mes "### delmod " + q
	return
#global

	// 実験用に5つほど作成
	newmod test, testmod, 0
	newmod test, testmod, 1
	newmod test, testmod, 2
	newmod test, testmod, 3
	newmod test, testmod, 4

	// 初期状態の要素数を確認
	mes "length(test) = " + length(test)

	// 領域外の添字の要素に対してdelmod
	mes
	mes "delmod test(123)"
	delmod test(123)
	mes "length(test) = " + length(test)

	// 領域外の添字の要素に対してvaruse
	mes
	mes "varuse(test(234)) = " + varuse(test(234))
	mes "length(test) = " + length(test)

	// ユーザー定義関数に領域外の添字の要素を渡す
	mes
	mes "func test(345)"
	func test(345)
	mes "length(test) = " + length(test)

	// 領域外の添字の要素に対してvarptr
	mes
	mes "varptr(test(456)) = " + varptr(test(456))
	mes "length(test) = " + length(test)

	// 適当な変数を領域外の添字の要素のクローンにする
	mes
	mes "dup a, test(567)"
	dup a, test(567)
	mes "length(test) = " + length(test)

	// 適当な変数に領域外の添字の要素を代入する
	mes
	mes "b = test(678)"
	b = test(678)
	mes "length(test) = " + length(test)
	// これはエラー
	

HSP 配列の自動拡張

// 配列の自動拡張のテスト

#module
#deffunc func var p
	return
#global

	// 実験用に5つほど作成
	dim test, 5

	// 初期状態の要素数を確認
	mes "length(test) = " + length(test)

	// ユーザー定義関数に領域外の添字の要素を渡す
	mes
	mes "func test(123)"
	func test(123)
	mes "length(test) = " + length(test)

	// 領域外の添字の要素に対してvarptr
	mes
	mes "varptr(test(234)) = " + varptr(test(234))
	mes "length(test) = " + length(test)

	// 適当な変数を領域外の添字の要素のクローンにする
	mes
	mes "dup a, test(345)"
	dup a, test(345)
	mes "length(test) = " + length(test)

	// 適当な変数に領域外の添字の要素を代入する
	mes
	mes "b = test(456)"
	b = test(456)
	mes "length(test) = " + length(test)
	// これはエラー
	

HSP HSPで例外(マクロ)

#define global try %tException %i=0:%i=0:if'%i'
#define global finally %tException if 1
#define global ctype catch(%1) %tException *%o:%1=%o:if %o
#define global throw(%1) %tException %p1=%1:%p2=1:goto*%p0

	mes "--------------------"

	try {
		mes "--try1"
		throw 1234567
		// throw "Test"
	} catch(e) {
		mes "--catch1 " + e
	} finally {
		mes "--finally1"
	}

	mes "--------------------"

	try {
		mes "--try2"
		// throw 1234567
		throw "Test"
	} catch(e) {
		mes "--catch2 " + e
	} finally {
		mes "--finally2"
	}

	mes "--------------------"

	try {
		mes "--try3"
		// throw 1234567
		// throw "Test"
	} catch(e) {
		mes "--catch3 " + e
	} finally {
		mes "--finally3"
	}

	mes "--------------------"

	try {
		mes "--try4"
		throw 1.234567
	} catch(e) {
		mes "--catch4 " + e
	}

	mes "--------------------"

	try {
		mes "--try5"
	} catch(e) {
		mes "--catch5 " + e
	}

	mes "--------------------"

	stop

HSP キュー

// データを保存するだけのモジュール
// 各種データをモジュール変数として扱う用
#module DataContainer m_data, m_size, m_rsize
#modinit var p_data, int p_size, \
local index
	if p_size < 0 {
		delmod thismod
		return -1
	}
	m_size = p_size
	if m_size > 0 {
		dimtype m_data, vartype(p_data), m_size
		switch vartype(p_data)
			case vartype("int")    : m_rsize = m_size << 2 : swbreak
			case vartype("str")    : m_rsize = m_size      : swbreak
			case vartype("double") : m_rsize = m_size << 3 : swbreak
			case vartype("label")  : m_rsize = m_size << 2 : swbreak	// TODO: 64Bit版
			case vartype("struct") : delmod thismod : return -1			// 未実装
			default                : delmod thismod : return -1			// 実装する気ナシ
		swend
		memcpy m_data, p_data, m_rsize
	} else {
		dimtype m_data, vartype(p_data), 1
		m_rsize = 0
	}
	mref index, 2
	return index

// 格納されたデータを取得
#modfunc  local GetData var p_data
	if m_size > 0 {
		dimtype p_data, vartype(m_data), m_size
		memcpy p_data, m_data, m_rsize
	} else {
		dimtype p_data, vartype(m_data), 1
	}
	return

// 格納されたデータのサイズを取得
#modcfunc local GetSize
	return m_size

// 格納されたデータの実サイズを取得
#modcfunc local GetRealSize
	return m_rsize
#global

// キューのモジュール
#module Queue m_data, m_index, m_num
#modinit \
local index
	dimtype m_data, vartype("struct"), 1
	dim m_index, 1
	dim m_num
	mref index, 2
	return index

// キューにデータを追加
// Enqueue@Queue [VAR]モジュール変数, [VAR]追加するデータ, [INT]データの大きさ
// 戻り値:正常終了だと1、処理に失敗すると0
#modfunc  local Enqueue var p_data, int p_size
	newmod m_data, DataContainer, p_data, p_size
	if stat < 0 : return 0
	m_index(m_num) = stat
	m_num++
	return 1

// キューからデータを取得
// Dequeue@Queue [VAR]モジュール変数, [VAR]出力先変数
// 戻り値:正常終了だと1、処理に失敗すると0
#modfunc  local Dequeue var p_data
	if m_num <= 0 : return 0
	GetData@DataContainer m_data(m_index(0)), p_data
	m_num--
	memcpy m_index, m_index, m_num << 2, 0, 4
	return 1

// キューのデータ数を取得
// RET = GetDataNum@Queue([VAR]モジュール変数)
// 戻り値:データ数
#modcfunc local GetDataNum
	return m_num

// 次のデータのサイズを取得
// RET = GetNextDataSize@Queue([VAR]モジュール変数)
// 戻り値:データサイズ、ただしデータがないときは-1
#modcfunc local GetNextDataSize
	if m_num <= 0 : return -1
	return GetSize@DataContainer(m_data(m_index(0)))
#global

// 以下サンプル、#if 0を#if 1にして動作
#if 0
	newmod mod, Queue
	sdim text

	objsize 60, 20
	pos   0, 0 : input text, 200, 20
	pos 200, 0 : button "Enqueue",  *enqueue
	pos 260, 0 : button "Dequeue",  *dequeue
	pos 320, 0 : button "Count",    *count
	pos 380, 0 : button "Get Size", *getsize
	pos 10, 30
	stop

*enqueue
	if text == "" {
		mes "No Data Specified"
		stop
	}
	Enqueue@Queue mod, text, strlen(text)
	mes "Enqueued ["+text+"]"
	objprm 0, ""
	sdim text
	stop

*dequeue
	sdim data
	Dequeue@Queue mod, data
	if stat {
		mes "Dequeued ["+data+"]"
	} else {
		mes "No Data in Queue"
	}
	stop

*count
	mes "There are "+GetDataNum@Queue(mod)+" Data in Queue"
	stop

*getsize
	size = GetNextDataSize@Queue(mod)
	if size >= 0 {
		mes "Next Data is "+size+" Bytes Long"
	} else {
		mes "No Data in Queue"
	}
	stop
#endif

HSP モジュール変数の配列の空きを求める

#module
#defcfunc findUnusedModuleIndex array modules, \
local index
	index = 0
	foreach modules
		if cnt != index : break
		index++
	loop
	return index
#global

// 以下テストコード、#if 1にして動作
#if 0
	#module test index, var
	#modinit int p_val, \
	local l_index
		mref l_index, 2
		var = p_val
		index = l_index
		mes strf("CREATED #%d (%d)", index, var)
		return
	#modterm
		mes strf("DELETED #%d (%d)", index, var)
		return
	#global

	newmod m, test, 0
	newmod m, test, 1
	newmod m, test, 2
	newmod m, test, 3
	delmod m(1)
	newmod m, test, 4
	newmod m, test, 5
	newmod m, test, 6
	mes strf("VACANT: #%d", findUnusedModuleIndex(m))
	delmod m(4)
	mes strf("VACANT: #%d", findUnusedModuleIndex(m))
	delmod m(2)
	mes strf("VACANT: #%d", findUnusedModuleIndex(m))
	newmod m, test, 7
	mes strf("VACANT: #%d", findUnusedModuleIndex(m))
	newmod m, test, 8
	mes strf("VACANT: #%d", findUnusedModuleIndex(m))
	newmod m, test, 9
	mes strf("VACANT: #%d", findUnusedModuleIndex(m))
#endif

HSP BlendModeのVividLight

	screen 1, 256, 256
	title "base color : bottom layer"
	repeat 256
		y = cnt
		repeat 256
			x = cnt
			i = x
			color i, i, i
			pset x, y
		loop
	loop

	screen 2, 256, 256
	title "blend color : top layer"
	repeat 256
		y = cnt
		repeat 256
			x = cnt
			i = 255 -y
			color i, i, i
			pset x, y
		loop
	loop

	screen 0, 256, 256
	title "final output"
	repeat 256
		y = cnt
		repeat 256
			x = cnt

			base_i = double(x) /255.0
			blend_i = double( 255 -y ) /255.0
		#if 0
				// まちがい
			if ( blend_i < 0.5 ) {
				final_i = base_i / ( 1.0 - 2.0*blend_i )
			} else {
				final_i = 1.0 - ( 1.0-base_i ) / ( 2.0 * ( blend_i - 0.5 ) )
			}
		#else
				// ただしくはこっち
					// 0除算扱いになってしまうのでガードを適当に
			if ( blend_i < 0.5 ) {
				div = ( 2.0 * blend_i )
				if ( div > 0.0 ) {
					final_i = 1.0 - ( 1.0-base_i ) / div
				} else {
					final_i = 0.0
				}
			} else {
				div = ( 1.0 - 2.0*(blend_i-0.5) )
				if ( div > 0.0 ) {
					final_i = base_i / div
				} else {
					final_i = 1.0
				}
			}
		#endif
				// clamp
			final_i = limitf( final_i, 0.0 , 1.0 )

			i = int( 255.0 * final_i )
			color i, i, i
			pset x, y
		loop
	loop
Total Pages: 2 / 22123451020...最後 »

よく投稿されているコード

タグ

最近投稿されたコード