;	私製ライブラリ・グラフィック篇
;	(c) MATSUUCHI Ryosuke in Dec,1992
;
;	ginit.asm : 初期化
;
;	1992. 6.11 ... 6.13
;	1992.12.28(Sun)

		.386p

		public	_ginit, ginit, _egbwork
		public	_callEGB, __SetVramSeg
		public	__AddVramBase_ebx
		public	__AddVramBase_esi
		public	__AddVramBase_edi
		public	__getpadrs
		public	__getpscrmod
		public	_egbwork, _scrmod, _wrtpage, _nowscrmod
		public	_vscrbase, _vscrmod
		public	_gramscr, gramscr

		extrn	EGB_work : dword

		assume	cs:cseg, ds:dseg



dseg segment dword 'DATA'

		align	4
__dmy__		db	4 dup (0)
_egbwork	db	1536 dup (0)	;EGBライブラリ用ワークエリア
_scrmod		dd	0		;ページ0の画面モード
		dd	0		;ページ1の画面モード
_vscrmod	dd	0,0,0,0		;仮想画面(0〜3)の画面モード
_vscrbase	dd	0,0,0,0		;仮想画面(0〜3)のベースオフセット
_nowscrmod	dd	0		;現在ページの画面モード
_wrtpage	dd	0		;現在の書き込みページ番号
					;(bit7=1 なら、仮想画面を意味する)


__scrbase	dd	0,40000h	;実画面各ページのベースオフセット
__scrsel	dd	104h,104h,104h	;各画面モードのセレクタ値
		dd	104h,104h,104h
		dd	104h,104h,104h
		dd	104h,104h,104h
		dd	10ch,10ch,10ch
		dd	10ch,10ch,10ch
		dd	10ch,10ch,10ch

dseg ends



cseg segment dword 'CODE'

;---------------------------------------------------------------
;	_callEGB : グラフィックBIOSの呼び出し
;		in  AH     機能コード
;		    DS:ESI パラメータ領域のアドレス
;---------------------------------------------------------------

		align	4

_callEGB	proc
		push	edi
		push	ds
		pop	gs
		mov	edi,offset _egbwork
		push	dword ptr 0110h
		pop	fs
		call	pword ptr fs:[20h]
		pop	edi
		ret
_callEGB	endp

;---------------------------------------------------------------
;	_ginit : Rio's Graphic Library の初期化
;		in  none
;		out none
;
;	void	ginit()
;---------------------------------------------------------------

ginit		proc	near
_ginit:
		push	eax
		push	ecx
		xor	ax,ax
		mov	ecx,1536
		call	_callEGB
		mov	eax,3
		mov	[_nowscrmod],eax
		mov	[_scrmod+0],eax
		mov	[_scrmod+4],eax
		xor	al,al
		mov	byte ptr [_wrtpage],al
		mov	eax,offset _egbwork
		mov	[EGB_work],eax
		pop	ecx
		pop	eax
		ret
ginit		endp

;-------------------------------------------------------------------------
;	__setvramseg : es を、現在の書き込みページのセグメントに設定する
;		       ※（私製ライブラリの内部ルーチン）
;		in  none
;		out none
;		reg es
;-------------------------------------------------------------------------

__SetVramSeg	proc near
		push	eax
		mov	eax,[_wrtpage]
		bt	eax,7
		jc	#vscr
			;実画面の場合
			mov	eax,[_scrmod + eax*4]
			cmp	eax,11
			jg	#1
				mov	eax,104h  ;モード 1〜11: セレクタ 104h
				jmp	#2
			#1:
				mov	eax,10ch  ;モード 12〜 : セレクタ 10Ch
			#2:
			mov	es,ax
			jmp	#end
		#vscr:
			;仮想画面の場合 : 単に es←ds を行うだけ
			push	ds
			pop	es
		#end:
		pop	eax
		ret
__SetVramSeg	endp

;-------------------------------------------------------------------------
;	__AddVramBase_ebx
;		ebx に、現在の書き込みページのベースオフセットを加算する
;		（私製ライブラリの内部ルーチン）
;		in  none
;		out none
;		reg ebx
;-------------------------------------------------------------------------

__AddVramBase_ebx proc near
		push	eax
		mov	eax,[_wrtpage]
		bt	eax,7
		jc	#0
			or	eax,eax
			jz	#1
				add	ebx,40000h
			#1:
			jmp	#2
		#0:
			and	eax,7fh
			add	ebx,[_vscrbase + eax*4]
		#2:
		pop	eax
		ret
__AddVramBase_ebx endp


;-------------------------------------------------------------------------
;	__AddVramBase_edi
;		edi に、現在の書き込みページのベースオフセットを加算する
;		（私製ライブラリの内部ルーチン）
;		in  none
;		out none
;		reg ebx
;-------------------------------------------------------------------------

__AddVramBase_edi proc near
		push	eax
		mov	eax,[_wrtpage]
		bt	eax,7
		jc	#0
			or	eax,eax
			jz	#1
				add	edi,40000h
			#1:
			jmp	#2
		#0:
			and	eax,7fh
			add	edi,[_vscrbase + eax*4]
		#2:
		pop	eax
		ret
__AddVramBase_edi endp


;-------------------------------------------------------------------------
;	__AddVramBase_esi
;		esi に、現在の書き込みページのベースオフセットを加算する
;		（私製ライブラリの内部ルーチン）
;		in  none
;		out none
;		reg ebx
;-------------------------------------------------------------------------

__AddVramBase_esi proc near
		push	eax
		mov	eax,[_wrtpage]
		bt	eax,7
		jc	#0
			or	eax,eax
			jz	#1
				add	esi,40000h
			#1:
			jmp	#2
		#0:
			and	eax,7fh
			add	esi,[_vscrbase + eax*4]
		#2:
		pop	eax
		ret
__AddVramBase_esi endp


;-------------------------------------------------------------------------
;	__getpscrmod
;		指定ページの画面モードを得る
;		（私製ライブラリの内部ルーチン）
;		in  eax     : ページ(bit7=1 → 仮想画面)
;		out eax     : 画面モード
;-------------------------------------------------------------------------


__getpscrmod	proc	near
		bt	eax,7
		jc	#0
		mov	eax,[_scrmod + eax*4]	;eax ← 画面モード
		ret
#0:		and	eax,7fh
		mov	eax,[_vscrmod + eax*4]
		ret
__getpscrmod	endp


;-------------------------------------------------------------------------
;	__getpadrs
;		指定ページの指定座標のアドレスのセレクタとオフセットを得る
;		（私製ライブラリの内部ルーチン）
;		in  eax     : ページ(bit7=1 → 仮想画面)
;		    ebx,ecx : 座標
;		out eax     : セレクタ
;		    ebx     : オフセット
;		reg eax,ebx
;-------------------------------------------------------------------------

__getpadrs	proc	near
		push	edx
		push	esi
		push	edi
		bt	eax,7
		jc	#0
			;（実画面ページの場合）
			mov	edi,[__scrbase + eax*4]	;edi ←ベースオフセット
			mov	eax,[_scrmod + eax*4]	;eax ← 画面モード
			mov	edx,[__scrsel + eax*4]	;edx ← セレクタ
			jmp	#1
		#0:
			;（仮想画面ページの場合）
			and	eax,7fh
			mov	edi,[_vscrbase+eax*4]	;edi ←ベースオフセット
			mov	eax,[_vscrmod+eax*4]	;eax ←画面モード
			sub	edx,edx			;edx ←セレクタ
			mov	dx,ds
		#1:
		cmp	eax,4
		jg	#2
			;画面モード３〜４の場合（１〜２は無視）
			mov	esi,ecx	;esi=y*512+(x/2)
			shl	esi,9
			mov	eax,ebx
			shr	eax,1
			add	esi,eax
			jmp	#3
		#2:
		cmp	eax,8
		jg	#4
			;画面モード５〜８の場合
			mov	esi,ecx	;edi=y*512+x*2
			shl	esi,9
			lea	esi,[esi+ebx*2]
			jmp	#3
		#4:
		cmp	eax,11
		jg	#5
			;画面モード９〜１１の場合
			mov	esi,ecx	;esi=y*1024+x*2
			shl	esi,10
			lea	esi,[esi+ebx*2]
			jmp	#3
		#5:
		cmp	eax,14
		jg	#6
			;画面モード１２〜１４の場合
			mov	esi,ecx	;esi=y*1024+x
			shl	esi,10
			add	esi,ebx
			jmp	#3
		#6:
			;画面モード１５〜の場合
			mov	esi,ecx
			shl	esi,10
			lea	esi,[esi+ebx*2]
		#3:
		add	edi,esi
		mov	ebx,edi
		mov	eax,edx
		pop	edi
		pop	esi
		pop	edx
		ret
__getpadrs	endp


;---------------------------------------------------------------
;	_gramscr : 仮想画面の設定
;		in  eax : 設定する仮想画面ページ (0x80 | page)
;		    ebx : どの画面モードにするか
;		    ecx : 画面バッファへのポインタ (256K / 512K bytes)
;	void gramscr(page, mode, buf)
;---------------------------------------------------------------

_gramscr	proc
		push	eax
		and	eax,7fh
		mov	[_vscrmod+eax*4],ebx
		mov	[_vscrbase+eax*4],ecx
		pop	eax
		ret
_gramscr	endp


gramscr		proc
		push	ebx
	#para	equ	8
		mov	eax,[esp+#para+0]
		mov	ebx,[esp+#para+4]
		mov	ecx,[esp+#para+8]
		call	_gramscr
		pop	ebx
		ret
gramscr		endp





cseg ends

end
