#include "kernel32.as"
#include "advapi32.as"

#module "API_SCFH_DSF"
#defcfunc tofloat double p1
	temp = p1
	return lpeek(temp)>>29&7|(p1<0)<<31|lpeek(temp,4)-(p1!0)*0x38000000<<3

#deffunc Search_SCFH_DSF var fnamelist,array pidlist

		// ミューテックスオープン
		mutex = "SCFH_DSF_GMUTEX"
		CreateMutex 0,1,varptr(mutex)
		hMutex = stat

		GetLastError
		if stat != 0xB7 : CloseHandle hMutex : return -1	// 対象のミューテックスが見つからない
		
		// 見つかった場合、共有メモリのオープン（PIDを調べるため）
		
		name = "SCFH_DSF_PIDS"
		CreateFileMapping -1, 0, 4, 0, (4+260)*32, varptr(name)
		hMapobj = stat
		
		if hMapobj = 0 {
			CloseHandle hMutex
   			return -2	// 対象の共有メモリが見つからない
		}
		
		MapViewOfFile hMapobj, 4, 0, 0, 0
		lpdata = stat           // 先頭アドレス

		sdim buf,(4+260)*32
		dupptr buf, lpdata, (4+260)*32, 2

		sdim pname,260
		_pid = -1

		sdim fnamelist,1024
		dim pidlist,32

		i = 0
		
		repeat 32
		
			dupptr _pid,varptr(buf)+cnt*264,4,4	; memcpy でも ok
			dupptr pname,varptr(buf)+cnt*264+4,260,2
			; メモリノートパッド形式で格納
			if _pid > 0 {
				fnamelist+=""+pname+"\n" 
				pidlist(i) = _pid
				i++
			}
			
		loop

		UnmapViewOfFile lpdata
		CloseHandle hMapobj
		CloseHandle hMutex
		dim _pid : dim pname : sdim buf

		if i = 0 { 
			return -3	// プロセスが見つからない
		}

	return i
#deffunc WriteData_SCFH_DSF int pid, int active1, int active2, int _hwnd, int x1, int y1, int x2, int y2, \
	double l, double t, double r, double b, int zoom, int fixAspect, int showCursor, int showLW, \
	int resizeMode, int threadNum, int overSampling 

		// ミューテックスのオープン

		mutex = "SCFH_DSF_MUTEX" + pid
		CreateMutex 0,1,varptr(mutex)
		hMutex = stat

		GetLastError
		if stat != 0xB7 : CloseHandle hMutex : return -1	// ミューテックスが見つからない

		// 共有メモリデータ書き込み
		
		name = "SCFH_DSF_AREA" + pid
		CreateFileMapping -1, 0, 4, 0, 408, varptr(name)
		hMapobj = stat
		if hMapobj = 0 {
			CloseHandle hMutex
   			return -2	// 共有メモリが存在しない
		}
		
		MapViewOfFile hMapobj, 4+2, 0, 0, 0
		lpdata = stat           // 先頭アドレス

		sdim _buf, 408
		
		dupptr _buf, lpdata, 408, 2

		// データ書き込み
		lpoke _buf, 0, active1				// [inout] SCFH DSF有効化
		
		lpoke _buf, 4, active2				// 出力範囲有効化
		lpoke _buf, 8, _hwnd				// ウィンドウのハンドル
		lpoke _buf, 12, x1					// 取込範囲
		lpoke _buf, 16, y1					// 取込範囲
		lpoke _buf, 20, x2					// 取込範囲
		lpoke _buf, 24, y2					// 取込範囲
		lpoke _buf, 28, tofloat(l)			// 出力範囲
		lpoke _buf, 32, tofloat(t)			// 出力範囲
		lpoke _buf, 36, tofloat(r)			// 出力範囲
		lpoke _buf, 40, tofloat(b)			// 出力範囲
		poke _buf, 44, zoom					// 取込範囲が出力範囲より小さい場合に拡大するか否か
		poke _buf, 45, fixAspect			// 取込範囲と出力範囲のアスペクトが異なる場合にアスペクト比を調整するか
		poke _buf, 46, showCursor			// マウスカーソルを取り込むか否か
		poke _buf, 47, showLW				// レイヤードウィンドウを取り込むか否か

		lpoke _buf, 368, resizeMode			// [in] 縮小モード (RESIZE_MODE_*)
		lpoke _buf, 400, threadNum			// [in] ソフトウェア縮小スレッド数
		lpoke _buf, 404, overSampling		// [in] オーバーサンプリング有効化

		UnmapViewOfFile lpdata
		CloseHandle hMapobj
		CloseHandle hMutex 
		sdim _buf
		
	return 0
	
#deffunc ReadData_SCFH_DSF int pid, var active1, var aveTime, var _width, var _height, var framerate

		// ミューテックスのオープン

		mutex = "SCFH_DSF_MUTEX" + pid
		CreateMutex 0,1,varptr(mutex)
		hMutex = stat

		GetLastError
		if stat != 0xB7 : CloseHandle hMutex : return -1	// ミューテックスが見つからない

		// 共有メモリデータ読み込み
		
		name = "SCFH_DSF_AREA" + pid
		CreateFileMapping -1, 0, 4, 0, 408, varptr(name)
		hMapobj = stat
		
		if hMapobj = 0 {
			CloseHandle hMutex
   			return -2	// 共有メモリが存在しない
		}
		
		MapViewOfFile hMapobj, 4+2, 0, 0, 0
		lpdata = stat           // 先頭アドレス

		sdim _buf, 408
		
		dupptr _buf, lpdata, 408, 2

		// データ読み取り
		active1 = 0		 : active1 = lpeek(_buf, 0)
		aveTime = 0.0	 : memcpy aveTime, _buf, 8, 0, 374
		_width = 0		 : memcpy _width, _buf, 4, 0, 380
		_height = 0		 : memcpy _height, _buf, 4, 0, 384
		framerate = 0.0	 : memcpy framerate, _buf, 8, 0, 388
		
		UnmapViewOfFile lpdata
		CloseHandle hMapobj
		CloseHandle hMutex 
		sdim _buf

	return 0
	
#deffunc WriteReg_SCFH_DSF str _name, double _fps, int _w, int _h

		// ミューテックスオープン
		mutex = "SCFH_DSF_GMUTEX"
		CreateMutex 0,1,varptr(mutex)
		hMutex = stat

		GetLastError
		if stat != 0xB7 : CloseHandle hMutex : return -1	// 対象のミューテックスが見つからない

		RegCreateKeyEx 0x80000001, "SOFTWARE\\SCFH DSF\\"+_name, 0, 0, 0, 0x00020006, 0, varptr(hKey), 0
		if stat : CloseHandle hMutex : return -2			// レジストリエラー
		
		RegSetValueEx hkey, "Framerate", 0, 0x00000001, str(_fps), strlen(str(_fps))+1
		RegSetValueEx hkey, "Width", 0, 0x00000001, str(_w), strlen(str(_w))+1
		RegSetValueEx hkey, "Height", 0, 0x00000001, str(_h), strlen(str(_h))+1
	
		RegCloseKey hkey

		CloseHandle hMutex

	return 0
	
#global

// 以下サンプル開始

	gsel 0, -1
	

// 映像ソース画面(bufferではなくscreenで)

	screen 5, 640, 480, 0, 0, 0 : gsel 5,2
	title "プロセス検索中 | このウィンドウがソースになります" : _hwnd = hwnd

	font "",128,16+2
	mes "Broadcast\nTest\nfor HSP!!"
	redraw 1

*GetList
	
	// SCFH_DSFを使用しているプロセスを見つかるまで検索
	repeat
		// プロセスを検索する命令
		// p1 = プロセス名を入れる変数（メモリノートパッド形式）, p2 = PIDを入れる数値型配列変数
		Search_SCFH_DSF fnamelist, pidlist
		if stat > 0 : break
		
		wait 12
		
	loop

	// どのProcessを使用するか選択する画面

	screen 2, 480, 60, 0, 0, 480+30 : gsel 2,2 
	title "プロセス一覧" : objsize 480, 20
	combox id, 0, fnamelist
	button gosub "このプロセスを使用する" , *Write
	button "再検索" , *GetList

	gsel 5, 0
	title "このウィンドウがソースになります"
	gsel 2, 0
	
	stop
	
*Write
	
	// キャプチャ対象を HSPウィンドウに変更する
	
	notesel fnamelist
	noteget fname, id

	// レジストリに必要なデータ書き込み（プロセス名ごとに設定ファイルが存在するため）
	// p1 = プロセス名 , p2 = フレームレート , p3,p4 = サイズ
	WriteReg_SCFH_DSF fname, 30.0, 640, 480

	// キャプチャ対象をセットする命令
	// p1 = PID , p2,p3 = 有効フラグ(常に1) , p4 = 対象のウィンドウハンドル
	// p5,p6,p7,p8 =  取り込み範囲（ 0 〜 ）
	// p9,p10,p11,p12 = 出力範囲( 0.0 〜 1.0 ) (double 型 ですが、内部で float に変換されます)
	// p13 = 取込範囲が出力範囲より小さい場合に拡大するか否か ( 0 or 1 )
	// p14 = 取込範囲と出力範囲のアスペクトが異なる場合にアスペクト比を調整するか ( 0 or 1 )
	// p15 = マウスカーソルを取り込むか否か ( 0 or 1 )
	// p16 = レイヤードウィンドウを取り込むか否か ( 0 or 1 )
	// p17 = 縮小モード ( 0〜3 ) ; 0 = ソフトウェア縮小 (最近傍補間)
	//                           ; 1 = ソフトウェア縮小 (バイリニア補完)
	//                           ; 2 = DirectDraw縮小 1Pass (Vista以降では使用禁止)
	//                           ; 3 = DirectDraw縮小 2Pass (Vista以降では使用禁止)
	// p18 = ソフトウェア縮小スレッド数 ( 1 以上でよいと思います。お使いのCPUとの相談。 )
	// p19 = オーバーサンプリング有効化 ( 0 or 1 )
	
	WriteData_SCFH_DSF pidlist(id), 1, 1, _hwnd, 0, 0, 640, 480, 0.0, 0.0, 1.0, 1.0, 0, 0, 0, 0, 0, 1, 1

	// 現在のデータを取得する命令
	// p1 = PID , p2 = 有効フラグ(プロセスからアンロードされたときにFALSEに設定される)を入れる変数
	// p3 = 一フレームの平均処理時間(double)を入れる変数
	// p4,p5 = 出力サイズを入れる変数
	// p6 = フレームレート(double)を入れる変数
	ReadData_SCFH_DSF pidlist(id), active, aveTime, w, h, fps

	gsel 5, 0
	dialog "設定を変更しました。"
	gsel 2, 0
	
	return