misc/crtmodfnc.s
;========================================================================================
;  crtmodfnc.s
;  Copyright (C) 2003-2025 Makoto Kamada
;
;  This file is part of the XEiJ (X68000 Emulator in Java).
;  You can use, modify and redistribute the XEiJ if the conditions are met.
;  Read the XEiJ License for more details.
;  https://stdkmd.net/xeij/
;========================================================================================

	.include	bioswork.equ
	.include	control2.mac
	.include	crtc.equ
	.include	doscall.mac
	.include	fnc.equ
	.include	iocscall.mac
	.include	misc.mac
	.include	vicon.equ

;----------------------------------------------------------------
;	crtmod.fnc (2025-06-29)
;----------------------------------------------------------------
;int crtmod(char mode,[char gon])
;	画面モードを設定します。
;	mode	0~	画面モード
;	gon	0~1	グラフィック画面を表示するか
;	戻り値	0	正常終了
;		1	X-BASICのバージョンが違います
;		2	引数が範囲外です
;----------------------------------------------------------------

	.text
	.even

;インフォメーションテーブル
information_table:
	.dc.l	init_routine		;初期化ルーチン
	.dc.l	run_routine		;RUNルーチン
	.dc.l	end_routine		;ENDルーチン
	.dc.l	system_routine		;SYSTEM/EXITルーチン
	.dc.l	break_routine		;BREAK/CTRL+Cルーチン
	.dc.l	ctrld_routine		;CTRL+D(外部関数初期化)ルーチン
	.dcb.l	2,reserved		;予約
	.dc.l	token_table		;トークンテーブル
	.dc.l	param_table		;パラメータテーブル
	.dc.l	func_table		;実行アドレステーブル
	.dcb.l	5,0			;空き

;初期化ルーチン
init_routine:
;RUNルーチン
run_routine:
;ENDルーチン
end_routine:
;SYSTEM/EXITルーチン
system_routine:
;BREAK/CTRL+Cルーチン
break_routine:
;CTRL+D(外部関数初期化)ルーチン
ctrld_routine:
;予約
reserved:
	rts

;トークンテーブル
token_table:
	.dc.b	'crtmod',0
	.dc.b	0
	.even

;パラメータテーブル
param_table:
	.dc.l	param_crtmod

;int crtmod(char mode,[char gon])
param_crtmod:
	.dc.w	P_CHAR			;char mode
	.dc.w	P_OPT|P_CHAR		;[char gon]
	.dc.w	R_INT			;int crtmod

;実行アドレステーブル
func_table:
	.dc.l	func_crtmod

;----------------------------------------------------------------
;int crtmod(char mode,[char gon])
;	画面モードを設定します。
;	mode	0~	画面モード
;	gon	0~1	グラフィック画面を表示するか
;	戻り値	0	正常終了
;		1	X-BASICのバージョンが違います
;		2	引数が範囲外です
;----------------------------------------------------------------
;>d0.l:エラーコード
;>a0.l:戻り値
;>a1.l:エラーメッセージ
;?d1-d5/a2-a3
func_crtmod:

;X-BASICのバージョンを確認する
aBAS	reg	a2			;basic.xの先頭+$8000
bas	reg	-$8000(aBAS)
	movea.l	basic_base(pc),aBAS
	if	<move.l aBAS,d0>,eq
		DOS	_GETPDB
		movea.l	d0,aBAS			;basic.xのプロセス管理ポインタ
		adda.l	#240+$8000,aBAS		;basic.xの先頭+$8000
		move.l	aBAS,basic_base
		lea.l	($000002)bas,a0		;識別子
		lea.l	basic202(pc),a1
		moveq.l	#1,d0			;'X-BASICのバージョンが違います'
		moveq.l	#14/2-1,d1
		for	d1
			goto	<cmp.w (a0)+,(a1)+>,ne,error_exit	;識別子が一致しない
		next
	endif

;引数を受け取る
	moveq.l	#0,d4
	move.b	P1_CHAR(sp),d4		;d4.w=画面モード
	if	<tst.w P2_TYPE(sp)>,pl
		move.b	P2_CHAR(sp),d5		;d5.b=グラフィック画面を表示するか
	endif

;引数の範囲を確認する
	moveq.l	#$FE,d2			;d2=画面モードの最大値
	move.w	#$76FF,d1		;画面モードの最大値の取得を試みる
	IOCS	_CRTMOD
	rol.l	#8,d0
	if	<cmp.b #$16,d0>,eq	;取得できた
		ror.l	#8,d0
		move.b	d0,d2			;画面モードの最大値
	endif
	moveq.l	#2,d0			;'引数が範囲外です'
	goto	<cmp.b d2,d4>,hi,error_exit	;画面モードが範囲外
	goto	<cmp.b #1,d5>,hi,error_exit	;グラフィック画面を表示するかが範囲外

;ファンクション表示を消す
	move.w	#3,-(sp)		;普通の行
	move.w	#14,-(sp)		;ファンクション表示行のモードの取得と設定
	DOS	_CONCTRL
	addq.l	#4,sp

;画面モードを設定する
	move.w	d4,d1
	IOCS	_CRTMOD

;グラフィック画面を表示する
	if	<tst.b d5>,ne
		IOCS	_G_CLR_ON
	endif

;basic.xのワークエリアを設定する
	moveq.l	#-1,d1
	moveq.l	#-1,d2
	IOCS	_B_CONSOL
	move.w	d2,d3			;d3.w=行数-1
	swap.w	d2			;d2.w=桁数-1
	move.w	#-1,($00A13A)bas	;screenの画面モード番号。サイズ<<3|実画面と色数<<1|解像度。-1=未設定
	clr.w	($00A13C)bas		;最上行Y座標
	move.w	d3,($00A13E)bas		;最下行Y座標
	clr.w	($00A140)bas		;ファンクション表示行の有無
	addq.w	#1,d2			;d2.w=桁数
	addq.w	#1,d3			;d3.w=行数
	move.w	d2,($00918E)bas		;画面の桁数
	move.w	d3,($009190)bas		;画面の行数
	addq.w	#1,d2			;d2.w=桁数+1
	add.w	d2,d2			;d2.w=2*(桁数+1)
	ext.l	d2			;d2.l=2*(桁数+1)
	move.l	d2,($009192)bas		;テキスト画面バッファのY方向のオフセット
	move.l	#text_buffer,($009196)bas	;テキスト画面バッファの先頭アドレス

;テキスト画面バッファを初期化する
	jsr	($00625E)bas		;CTRL+L CLR テキスト画面を消去する

;戻り値は0
	moveq.l	#0,d0

;正常終了
;<d0.l:戻り値
normal_exit:
	lea.l	return_value(pc),a0	;戻り値。voidのときは不要
	move.l	d0,R1_INT(a0)		;戻り値
	moveq.l	#0,d0			;終了コードは0。エラーメッセージは不要
	rts

;エラー終了
;<d0.l:エラーコード。0以外。負はDOSコールエラー
error_exit:
	lea.l	return_value(pc),a0	;戻り値。voidのときは不要
	move.l	d0,R1_INT(a0)		;error offのときの戻り値。エラーコード
	lea.l	error_message(pc),a1	;エラーメッセージ。DOSコールエラーのときは不要
	move.w	d0,d1
	subq.w	#2,d1
	if	pl
		for	d1
			do
				tst.b	(a1)+
			while	ne
		next
	endif
	rts

;エラーメッセージ
error_message:
	.dc.b	'X-BASICのバージョンが違います',0	;1
	.dc.b	'引数が範囲外です',0			;2
	.even

;識別子
basic202:
	.dc.b	'V2.02-8906    '

	.bss
	.even

;戻り値。voidのときは不要
return_value:
	.ds.b	R1_SIZE

;basic.xの先頭+$8000
basic_base:
	.ds.l	1

;テキスト画面バッファ
;	basic.xのバッファは96桁32行を超えられないので新しく確保する
text_buffer:
	.ds.w	(128+1)*64