;==============================================================================
;	<< 386ASM V2.0 >>  for  FM TOWNS
;==============================================================================
.386p
		PAGE		60,132
		NAME		VSYNC
		TITLE		VSYNC Interrupt
;==============================================================================
;	VSYNC 割り込み
;
;	CREATE : 1990.06.01
;	FINISH : 1990.06.02
;
;	< High C からの呼出形式 >
;	extern	int (*VSYNC_entry)() ;
;	extern	VSYNC_init() ;
;	extern	VSYNC_end() ;
;
;	static int vsync_func1() ;
;	VSYNC_entry = vsync_func1 ;
;	VSYNC_init() ;
;	VSYNC_end();
;
;	< note > : TABS = 4
;
;	< History >
;	1990.06.01 : CREATE
;	1990.08.03 : vsync_release 時のﾊﾞｸﾞ修正
;	1991.04.13 : 清書
;
;	★注意
;		このプログラムを呼ぶプログラムの
;		オブジェクトは、ネイティブの最初に
;		おいて下さい｡(先頭から64K以内に入る
;		ようにするため｡)
;
;	Programmed by Y.Hirata ( Nifty-ID : NAB03321 )
;==============================================================================
;
INCLUDE	hc.inc								;
;
CGROUP	GROUP pmcode, CODE					;
DGROUP	GROUP rmcode, DATA					;
;
;--------------------------------------------
		public	VSYNC_init					; VSYNC 割り込み登録
		public	VSYNC_end					; VSYNC 割り込み解除
;
		public	VSYNC_entry					; VSYNC ﾊﾝﾄﾞﾗ･ｱﾄﾞﾚｽ(ﾈｲﾃｨﾌﾞ)
;--------------------------------------------
;
;********************************************
;			定数定義
;********************************************
;
INT_NUM		EQU			00Bh				; IRQ B (ｵﾌﾟｼｮﾝﾎﾞｰﾄﾞ)
IRQ_0B_ON	EQU			08h					; IRQ B 割り込み許可 (11 ﾋﾞｯﾄ)
IRQ_0B_OFF	EQU			0F7h				; IRQ B 割り込み不許可 (11 ﾋﾞｯﾄ)
VSYNC_CLR	EQU			05CAh				; VSYNC割り込み原因ｸﾘｱﾚｼﾞｽﾀ
;
;
;////////////////////////////////////////////
;			リアル部
;////////////////////////////////////////////
;
rmcode	SEGMENT								;
		ASSUME	cs:rmcode					;
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;	ﾈｲﾃｨﾌﾞ-ﾘｱﾙの場合､ｾｸﾞﾒﾝﾄﾚｼﾞｽﾀは､ ﾘｱﾙから
;	ﾈｲﾃｨﾌﾞに戻った場合にﾈｲﾃｨﾌﾞｵﾘｼﾞﾅﾙの値に
;	DOS-Extenderが復元してくれるので保存/復元
;	は省略。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;********************************************
;	VSYNC ﾘｱﾙﾊﾝﾄﾞﾗ内での使用データ領域
;********************************************
;
PROT_entry		DD		?					; ﾘｱﾙﾓｰﾄﾞDOS-Extenderﾌﾟﾛｼｼﾞｬｱﾄﾞﾚｽ
;
vsync_flg		DB		0					; VSYNC割り込みは許可されているか？
;
int_mask_data	LABEL	byte				; 割り込み許可ﾃﾞｰﾀ
				DB		?					; ﾋﾞｯﾄ 31〜24		+0
				DB		?					; ﾋﾞｯﾄ 23〜16		+1
				DB		?					; ﾋﾞｯﾄ 15〜 8		+2
				DB		?					; ﾋﾞｯﾄ  7〜 0		+3
;
vsync_offset	DW		?					; 割り込みﾃﾞｰﾀﾌﾞﾛｯｸ･ｵﾌｾｯﾄ
vsync_segment	DW		?					; 割り込みﾃﾞｰﾀﾌﾞﾛｯｸ･ｾｸﾞﾒﾝﾄ
;
vsync_adrs		DB		0					; 割り込みﾃﾞｰﾀﾌﾞﾛｯｸ..
				DB		0					;
				DW		OFFSET vsync_hook	; ﾊﾝﾄﾞﾗｱﾄﾞﾚｽ･ｵﾌｾｯﾄ
				DW		?					; ﾊﾝﾄﾞﾗｱﾄﾞﾚｽ･ｾｸﾞﾒﾝﾄ
;
stackOff		DW		0					; ｽﾀｯｸ退避用(ﾎﾟｲﾝﾀ)
stackSeg		DW		0					; ｽﾀｯｸ退避用(ｾｸﾞﾒﾝﾄ)
;
				DB 		512 DUP(0) 			; local stack
tmpRstack		LABEL	byte				;
;
;
;--------------------------------------------
;	VSYNC ﾘｱﾙﾊﾝﾄﾞﾗの登録
;--------------------------------------------
vsync_setup	PROC	FAR						; VSYNCﾊﾝﾄﾞﾗの登録
			push	ds						;
			push	di						;
			push	dx						;
;
			mov		ah,1					;
			mov		dl,INT_NUM				; 割り込み要因ｺｰﾄﾞ
			int		INT_INT					; 割り込みﾃﾞｰﾀﾌﾞﾛｯｸｱﾄﾞﾚｽの取り出し
;
			mov		cs:vsync_offset,di		; ﾃﾞｰﾀﾌﾞﾛｯｸｱﾄﾞﾚｽ･ｵﾌｾｯﾄ
			mov		cs:vsync_segment,ds		; ﾃﾞｰﾀﾌﾞﾛｯｸｱﾄﾞﾚｽ･ｾｸﾞﾒﾝﾄ
;
			mov		word PTR cs:[vsync_adrs+4],cs
											; VSYNC ﾊﾝﾄﾞﾗのｾｸﾞﾒﾝﾄ
			push	cs						;
			pop		ds						; ds = cs
			mov		ah,00h					;
			mov		dl,INT_NUM				; 割り込み要因ｺｰﾄﾞ
			mov		di,OFFSET vsync_adrs	;
			int		INT_INT					; 割り込みﾃﾞｰﾀﾌﾞﾛｯｸｱﾄﾞﾚｽの登録
;
			mov		ah,3					;
			mov		di,OFFSET int_mask_data	; 割り込み許可ﾃﾞｰﾀ
			int		INT_INT					; 割り込み管理ﾃﾞｰﾀの取り出し
;
			mov		cs:vsync_flg,FALSE		;
			test	byte PTR cs:[di+2],IRQ_0B_ON
			jz		int_enable				;
			mov		cs:vsync_flg,TRUE		; VSYNC割り込み許可済
;
int_enable:									;
			or		byte PTR cs:[di+2],IRQ_0B_ON
											; VSYNC 割り込みの許可
			mov		ah,2					;
			int		INT_INT					; 割り込み許可ﾃﾞｰﾀの書き込み
;
			pop		dx						;
			pop		di						;
			pop		ds						;
			ret								;
vsync_setup	ENDP							;
;
;--------------------------------------------
;	VSYNC ﾘｱﾙﾊﾝﾄﾞﾗの登録解除
;--------------------------------------------
vsync_release	PROC	FAR					; VSYNC 解除
			push	ds						;
			push	di						;
			push	dx						;
;
			push	cs						;
			pop		ds						; ds = cs
			mov		di,OFFSET int_mask_data	; 割り込み許可ﾃﾞｰﾀ
			and 	byte PTR cs:[di+2],IRQ_0B_OFF
											; VSYNC 割り込みの禁止
			cmp		cs:vsync_flg,TRUE		;
			jne		vsync_permission		;
			or		byte PTR cs:[di+2],IRQ_0B_ON
											; VSYNC 割り込み許可
;
vsync_permission:							;
			mov		ah,2					;
			int		INT_INT					; 割り込み許可ﾃﾞｰﾀの書き込み
;
			mov		ah,0					;
			mov		dl,INT_NUM				; 割り込み要因ｺｰﾄﾞ
			lds		di,dword PTR cs:vsync_offset
											; 割り込みﾃﾞｰﾀﾌﾞﾛｯｸ
			int		INT_INT					; 割り込みﾃﾞｰﾀﾌﾞﾛｯｸｱﾄﾞﾚｽの登録
;
			pop		dx						;
			pop		di						;
			pop		ds						;
			ret								;
vsync_release	ENDP						;
;
;--------------------------------------------
;	VSYNC ﾘｱﾙﾊﾝﾄﾞﾗ
;--------------------------------------------
;	ここから、ﾈｲﾃｨﾌﾞﾊﾝﾄﾞﾗを呼び出すが、その
;	時には、ここのｽﾀｯｸが使用されるために、
;	ﾛｰｶﾙｽﾀｯｸを確保しておく必要がある。
;	(ﾘｱﾙからﾈｲﾃｨﾌﾞを呼び出す時には、かなりの
;	ｽﾀｯｸが呼出し側で必要となるので、注意する
;	必要がある。)
;
vsync_hook	PROC	FAR						;
			cli								;
			mov		word PTR cs:stackSeg,ss	; ｽﾀｯｸ退避
			mov		word PTR cs:stackOff,sp	;
;
			push	cs						;
			pop		ss						; ss = cs
			mov		sp,OFFSET tmpRstack		; ﾛｰｶﾙｽﾀｯｸ使用
;
			push	cs						;
			pop		ds						; ds = cs
			pushad							; ﾚｼﾞｽﾀ退避
;
			mov		dx,VSYNC_CLR			;
			out		dx,al					; ﾀﾞﾐｰﾗｲﾄ (VSYNC割り込み原因ｸﾘｱ)
;
			push	word PTR 0				;
			push	dword PTR 0				;
			push	word PTR CODESEG		;
			push	dword PTR OFFSET VSYNC_handler
											; 呼び出すﾈｲﾃｨﾌﾞﾙｰﾁﾝｱﾄﾞﾚｽ
			sti								;
			call	cs:PROT_entry			; ﾈｲﾃｨﾌﾞﾌﾟﾛｼｼﾞｬの呼出し
			cli								;
			add		sp,12					;
;
			popad							; ﾚｼﾞｽﾀ復帰
			mov		ss,word PTR cs:stackSeg	; ｽﾀｯｸを元に戻す
			mov		sp,word PTR cs:stackOff	;
;
			lds		di,dword PTR cs:vsync_offset
											; 本来のVSYNCﾊﾝﾄﾞﾗに処理を移す
			jmp		dword PTR ds:[di+2]		; Jump Real Handler
;
vsync_hook	ENDP							;
;
rmcode		ENDS							;
;
;
;////////////////////////////////////////////
;			ネイティブ部
;////////////////////////////////////////////
;
;********************************************
;	VSYNC ﾈｲﾃｨﾌﾞﾊﾝﾄﾞﾗ内での使用データ領域
;********************************************
;
DATA	SEGMENT								;
;
REG_esp			DD		0					; ｽﾀｯｸ退避用(ﾎﾟｲﾝﾀ)
REG_ss			DW		0					; ｽﾀｯｸ退避用(ｾｸﾞﾒﾝﾄ)
;
				DB		32768 DUP (?)		; ﾈｲﾃｨﾌﾞ･ﾛｰｶﾙｽﾀｯｸｻｲｽﾞ(適当)
TmpSTACK 		LABEL	byte				;
;
DATA	ENDS								;
;
;
;********************************************
;	VSYNC ﾈｲﾃｨﾌﾞ処理
;********************************************
;
pmcode	SEGMENT								;
		ASSUME	cs:CGROUP, ds:DGROUP		;
;
VSYNC_entry		DD		?					; VSYNC ﾈｲﾃｨﾌﾞﾊﾝﾄﾞﾗ ｱﾄﾞﾚｽ
;
;--------------------------------------------
;	VSYNC ﾈｲﾃｨﾌﾞﾊﾝﾄﾞﾗ
;--------------------------------------------
		ALIGN	4							; dword boundary
VSYNC_handler	PROC	FAR					;
			cli								;
			push	ds						;
;
			mov		ax,DATASEG				;
			mov		ds,ax					;
			mov		word PTR REG_ss,ss		; ｽﾀｯｸ退避
			mov		dword PTR REG_esp,esp	;
;
			mov		es,ax					;
			mov		ss,ax					; ss = es = ds
			mov		esp,OFFSET TmpSTACK		; ﾛｰｶﾙｽﾀｯｸの確保
			pushad							; ﾚｼﾞｽﾀ退避
			sti								;
;
			call	dword PTR cs:VSYNC_entry
											; VSYNC ﾈｲﾃｨﾌﾞﾊﾝﾄﾞﾗを呼ぶ(HighC用)
;
			cli								;
			popad							; ﾚｼﾞｽﾀ復帰
			mov		ss,word PTR REG_ss		; ｽﾀｯｸを元に戻す
			mov		esp,dword PTR REG_esp	;
			pop		ds						;
			xor		eax,eax					; Return Code = 0
			sti								;
			ret								;
VSYNC_handler	ENDP						;
;
;--------------------------------------------
;	VSYNC 割り込み登録
;--------------------------------------------
		ALIGN	4							; dword boundary
VSYNC_init	PROC	NEAR					;
			push	ebp						;
			mov		ebp,esp					; ｽﾀｯｸﾌﾚｰﾑ形成
;
			push	es						;
			push	ds						;
			push	ecx						;
			push	ebx						;
;
			mov		ax,0250dh				;
			int		INT_DOS					; ﾘｱﾙﾓｰﾄﾞﾘﾝｸ情報の取得
			mov		PROT_entry,eax			; ﾘｱﾙﾓｰﾄﾞDOS-Extenderﾌﾟﾛｼｼﾞｬｱﾄﾞﾚｽ
											; ﾘｱﾙ から ﾈｲﾃｨﾌﾞ を call するため
											; の処理｡
;
			push	ds						;
			pop		es						; es = ds
			xor		ebx,ebx					;
			lea		ecx,_realend			;
			mov		ax,0250fh				;
			int		INT_DOS					; ﾈｲﾃｨﾌﾞ->ﾘｱﾙ の ｱﾄﾞﾚｽ変換
;
			mov		ebx,ecx					; ｾｸﾞﾒﾝﾄ
			lea		bx,vsync_setup			; ｵﾌｾｯﾄ
			xor		ecx,ecx					; ecx = 0
			mov		ax,0250eh				;
			int		INT_DOS					; ﾘｱﾙﾓｰﾄﾞﾌﾟﾛｼｼﾞｬの呼出
;
			pop		ebx						;
			pop		ecx						;
			pop		ds						;
			pop		es						;
			xor		eax,eax					; return code = 0
;
			pop		ebp						; ｽﾀｯｸﾌﾚｰﾑ開放
			ret								;
VSYNC_init	ENDP							;
;
;--------------------------------------------
;	VSYNC 割り込み解除
;--------------------------------------------
		ALIGN	4							; dword boundary
VSYNC_end	PROC	NEAR					;
			push	ebp						;
			mov		ebp,esp					; ｽﾀｯｸﾌﾚｰﾑ形成
;
			push	es						;
			push	ds						;
			push	ecx						;
			push	ebx						;
;
			push	ds						;
			pop		es						; es = ds
			xor		ebx,ebx					;
			lea		ecx,_realend			;
			mov		ax,0250fh				;
			int		INT_DOS					; ﾈｲﾃｨﾌﾞ->ﾘｱﾙ の ｱﾄﾞﾚｽ変換
;
			mov		ebx,ecx					; ｾｸﾞﾒﾝﾄ
			lea		bx,vsync_release		; ｵﾌｾｯﾄ
			xor		ecx,ecx					; ecx = 0
			mov		ax,0250eh				;
			int		INT_DOS					; ﾘｱﾙﾓｰﾄﾞﾌﾟﾛｼｼﾞｬの呼出
;
			pop		ebx						;
			pop		ecx						;
			pop		ds						;
			pop		es						;
			xor		eax,eax					; return code = 0
;
			pop		ebp						; ｽﾀｯｸﾌﾚｰﾑ開放
			ret								;
VSYNC_end	ENDP							;
;
pmcode		ENDS							;
;
		END
	
