misc/crtmod16.s
;========================================================================================
;  crtmod16.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	dosconst.equ
	.include	doswork.equ
	.include	iocscall.mac
	.include	mfp.equ
	.include	misc.mac
	.include	push2.mac
	.include	sprc.equ
	.include	sram.equ
	.include	sysport.equ
	.include	vicon.equ

;----------------------------------------------------------------
;	crtmod16.x (2025-06-29)
;
;	説明
;		crtmod16.xはIPLROM 1.6に含まれるCRTMOD/G_CLR_ONを常駐プログラムにしたものです。
;		一般的な液晶モニタで768x512ドットの画面をはみ出さないように表示できます。
;		384x256ドット、512x512ドット(正方形)などの画面モードが追加されます。
;
;	補足
;		IPLROM 1.0~1.3にあったグラフィックパレットに関するバグが修正されます。
;		バグに依存しているソフトウェアが誤動作する場合はcrtmrb16.xを組み込んでください。
;
;	オプション
;		-e         常駐します。
;		-l 0~1    0でCRT向けの同期周波数、1でLCD向けの同期周波数を選択します。
;		-m 0~73   画面モードを選択します。crtmodtest.xを参照してください。
;		-r         常駐を解除します。
;
;	更新履歴
;		2022-02-19
;			IPLROM 1.6の_CRTMODと_G_CLR_ONを抜き出したもの
;			IPLROM 1.0~1.3のバグを修正
;			CRT向けとLCD向けを選択できる
;			28~39を追加。384x256、512x512(正方形)、256x256(正方形)
;		2022-02-21
;			crtmod16.xを公開
;		2022-06-08
;		2023-01-10
;		2023-10-12
;			$56FFを追加。バージョンを返す
;		2023-11-15
;			$16FFを追加。CRTorLCDとバージョンを返す
;		2024-03-13
;			crtmrb16.xを追加。IPLROM 1.0~1.3のバグを再現する。バグに依存しているソフトウェアを修正できないときの救済策
;		2024-08-25
;			40~47を追加。512x256、512x256(スプライトは512x512)
;		2025-03-23
;			$00ED0095が$6xでないとき$60を書き込む。実機でSRAMが壊れているとき予期せずLCDモードになってしまうことがある問題の対策
;		2025-04-19
;			stouを修正。Thanks TcbnErik
;		2025-06-29
;			48~73を追加。拡張グラフィック画面に対応
;			$76FFを追加。$16000000+画面モードの最大値を返す
;			$xxFFを除いて設定後の画面モードが範囲外のとき-1を返す
;			拡張グラフィック画面がないのに拡張グラフィック画面が必要な画面モードが指定されたとき-2を返す
;
;----------------------------------------------------------------
;IOCSコール$10 _CRTMOD 画面モードの取得と設定
;<d1.w:設定後の画面モード
;	$16FF	バージョンの確認。$16xxxxxx(CRT向け)または$96xxxxxx(LCD向け)を返す
;	$56FF	バージョンの確認。$16xxxxxxを返す
;	$76FF	画面モードの最大値の確認。$160000xxを返す
;	$43xx	CRT向け。SRAMに保存する。$43FFはSRAMの変更のみ
;	$4Cxx	LCD向け。SRAMに保存する。$4CFFはSRAMの変更のみ
;	$xxFF	取得のみ
;	$01xx	初期化しない
;>d0.l:設定前の画面モード。-1=設定後の画面モードが範囲外,-2=拡張グラフィック画面がない
;	バージョンの確認のとき$16xxxxxxまたは$96xxxxxx
;	画面モードの最大値の確認のとき$160000xx
;----------------------------------------------------------------
;IOCSコール$90 _G_CLR_ON グラフィック画面の消去とパレット初期化と表示ON
;>d0.l:0
;----------------------------------------------------------------

DEVICE_NAME	reg	'CRTM16*/'
  .ifdef CRTMOD_REPRODUCE_BUG		;バグを再現させる
TITLE_STRING	reg	'crtmrb16.x (2025-06-29)'
  .else
TITLE_STRING	reg	'crtmod16.x (2025-06-29)'
  .endif
CRTMOD_VERSION	equ	$16250629	;_CRTMODのバージョン

PATCH_jsr	.macro	name,label
	bsr	label
	.endm

;----------------------------------------------------------------
;プログラムの先頭
	.text
program_head:

;デバイスヘッダ
	.dc.l	-1			;次のデバイスヘッダ。-1=デバイスヘッダのリストの末尾
	.dc.w	$8000			;デバイスタイプ。キャラクタデバイス
	.dc.l	strategy_routine	;ストラテジルーチン
	.dc.l	interrupt_routine	;インタラプトルーチン
	.dc.b	DEVICE_NAME		;デバイス名

;----------------------------------------------------------------
;リクエストヘッダのアドレス
request_header:
	.dc.l	0

;ベクタテーブル
vector_table:
	.dc.w	4*($100+_CRTMOD)	;オフセット
	.dc.l	iocs_10_CRTMOD		;新しいベクタ
	.dc.l	0			;古いベクタ
	.dc.w	4*($100+_G_CLR_ON)
	.dc.l	iocs_90_G_CLR_ON
	.dc.l	0
	.dc.w	0

;----------------------------------------------------------------
;ストラテジルーチン
strategy_routine:
	move.l	a5,request_header
	rts

;インタラプトルーチン
interrupt_routine:
	push	d0-d7/a0-a6
	movea.l	request_header(pc),a5
	moveq.l	#0,d0
	move.b	2(a5),d0		;コマンド番号
	if	<cmp.w #(jump_table_end-jump_table)/2,d0>,hs	;範囲外
		moveq.l	#(jump_table_end-jump_table)/2,d0
	endif
	add.w	d0,d0
	move.w	jump_table(pc,d0.w),d0
	jsr	jump_table(pc,d0.w)
	move.b	d0,3(a5)		;エラーコード下位
	lsr.w	#8,d0
	move.b	d0,4(a5)		;エラーコード上位
	pop
	rts

;デバイスコマンドのジャンプテーブル
jump_table:
	.dc.w	initialize-jump_table		;デバイスコマンド0 初期化
	.dc.w	command_error-jump_table	;デバイスコマンド1 ディスク交換チェック
	.dc.w	command_error-jump_table	;デバイスコマンド2 BPBテーブルの再構築
	.dc.w	ioctrl_input-jump_table		;デバイスコマンド3 _IOCTRLによる入力
	.dc.w	input-jump_table		;デバイスコマンド4 入力
	.dc.w	control_sense-jump_table	;デバイスコマンド5 コントロール/センス
	.dc.w	input_status-jump_table		;デバイスコマンド6 入力ステータス
	.dc.w	input_flush-jump_table		;デバイスコマンド7 入力バッファフラッシュ
	.dc.w	output-jump_table		;デバイスコマンド8 出力(ベリファイなし)
	.dc.w	output-jump_table		;デバイスコマンド9 出力(ベリファイあり)
	.dc.w	output_status-jump_table	;デバイスコマンド10 出力ステータス
	.dc.w	no_error-jump_table		;デバイスコマンド11 正常終了
	.dc.w	ioctrl_output-jump_table	;デバイスコマンド12 _IOCTRLによる出力
jump_table_end:
	.dc.w	command_error-jump_table	;範囲外 コマンドエラー

;デバイスコマンド1 ディスク交換チェック
;デバイスコマンド2 BPBテーブルの再構築
;コマンドエラー
command_error:
	move.w	#IGNORE|ABORT|UNKNOWN_COMMAND,d0	;無視(I) 中止(A) デバイスドライバに無効なコマンドを指定しました
	rts

;デバイスコマンド3 _IOCTRLによる入力
ioctrl_input:
;	movea.l	14(a5),a1		;アドレス
	goto	command_error

;デバイスコマンド4 入力
input:
	movea.l	14(a5),a1		;アドレス
	move.l	18(a5),d3		;長さ
	docontinue
		clr.b	(a1)+
	while	<subq.l #1,d3>,cc
	moveq.l	#0,d0			;常に成功する(終わるまで復帰しない)
	rts

;デバイスコマンド5 コントロール/センス
control_sense:
	clr.b	13(a5)			;データ
	moveq.l	#0,d0			;常に成功する
	rts

;デバイスコマンド6 入力ステータス
input_status:
	moveq.l	#1,d0			;0=入力バッファが空ではないので入力できる,1=入力バッファが空なので入力できない
	rts

;デバイスコマンド7 入力バッファフラッシュ
input_flush:
	moveq.l	#0,d0			;常に成功する
	rts

;デバイスコマンド8 出力(ベリファイなし)
;デバイスコマンド9 出力(ベリファイあり)
output:
;	movea.l	14(a5),a1		;アドレス
;	move.l	18(a5),d3		;長さ
	moveq.l	#0,d0			;常に成功する(終わるまで復帰しない)
	rts

;デバイスコマンド10 出力ステータス
output_status:
	moveq.l	#1,d0			;0=出力バッファが満杯ではないので出力できる,1=出力バッファが満杯なので出力できない
	rts

;デバイスコマンド11 正常終了
no_error:
	moveq.l	#0,d0			;常に成功する
	rts

;デバイスコマンド12 _IOCTRLによる出力
ioctrl_output:
;	movea.l	14(a5),a1		;アドレス
	goto	command_error



;----------------------------------------------------------------
;IOCSコール$10 _CRTMOD 画面モードの取得と設定
;<d1.w:設定後の画面モード
;	$16FF	バージョンの確認。$16xxxxxx(CRT向け)または$96xxxxxx(LCD向け)を返す
;	$56FF	バージョンの確認。$16xxxxxxを返す
;	$76FF	画面モードの最大値の確認。$160000xxを返す
;	$43xx	CRT向け。SRAMに保存する。$43FFはSRAMの変更のみ
;	$4Cxx	LCD向け。SRAMに保存する。$4CFFはSRAMの変更のみ
;	$xxFF	取得のみ
;	$01xx	初期化しない
;>d0.l:設定前の画面モード。-1=設定後の画面モードが範囲外,-2=拡張グラフィック画面がない
;	バージョンの確認のとき$16xxxxxxまたは$96xxxxxx
;	画面モードの最大値の確認のとき$160000xx
;----------------------------------------------------------------
;	画面モード
;
;	画面モード	解像度	画面サイズ	実画面サイズ	色数	ページ数
;	0		高	512x512		1024x1024	16	1
;	1		低	512x512		1024x1024	16	1
;	2		高	256x256		1024x1024	16	1
;	3		低	256x256		1024x1024	16	1
;	4		高	512x512		512x512		16	4
;	5		低	512x512		512x512		16	4
;	6		高	256x256		512x512		16	4
;	7		低	256x256		512x512		16	4
;	8		高	512x512		512x512		256	2
;	9		低	512x512		512x512		256	2
;	10		高	256x256		512x512		256	2
;	11		低	256x256		512x512		256	2
;	12		高	512x512		512x512		65536	1
;	13		低	512x512		512x512		65536	1
;	14		高	256x256		512x512		65536	1
;	15		低	256x256		512x512		65536	1
;	16		高	768x512		1024x1024	16	1
;	17		中	1024x424	1024x1024	16	1
;	18		中	1024x848	1024x1024	16	1
;	19		VGA	640x480		1024x1024	16	1
;	20		高	768x512		512x512		256	2
;	21		中	1024x424	512x512		256	2
;	22		中	1024x848	512x512		256	2
;	23		VGA	640x480		512x512		256	2
;	24		高	768x512		512x512		65536	1
;	25		中	1024x424	512x512		65536	1
;	26		中	1024x848	512x512		65536	1
;	27		VGA	640x480		512x512		65536	1
;	$100+(0~27)	初期化しない
;	-1	取得のみ
;
;	以下は拡張
;	28		高	384x256		1024x1024	16	1
;	29		高	384x256		512x512		16	4
;	30		高	384x256		512x512		256	2
;	31		高	384x256		512x512		65536	1
;	32		高	512x512(正方形)	1024x1024	16	1
;	33		高	512x512(正方形)	512x512		16	4
;	34		高	512x512(正方形)	512x512		256	2
;	35		高	512x512(正方形)	512x512		65536	1
;	36		高	256x256(正方形)	1024x1024	16	1
;	37		高	256x256(正方形)	512x512		16	4
;	38		高	256x256(正方形)	512x512		256	2
;	39		高	256x256(正方形)	512x512		65536	1
;	40		高	512x256		1024x1024	16	1
;	41		高	512x256		512x512		16	4
;	42		高	512x256		512x512		256	2
;	43		高	512x256		512x512		65536	1
;	44		高	512x256(※)	1024x1024	16	1
;	45		高	512x256(※)	512x512		16	4
;	46		高	512x256(※)	512x512		256	2
;	47		高	512x256(※)	512x512		65536	1
;	※スプライトは512x512
;
;	以下は拡張グラフィック画面が必要
;	0,1,2,3,16,17,18,19,28,32,36,40,44を256色にしたもの
;	48		高	512x512		1024x1024	256	1
;	49		低	512x512		1024x1024	256	1
;	50		高	256x256		1024x1024	256	1
;	51		低	256x256		1024x1024	256	1
;	52		高	768x512		1024x1024	256	1
;	53		中	1024x424	1024x1024	256	1
;	54		中	1024x848	1024x1024	256	1
;	55		VGA	640x480		1024x1024	256	1
;	56		高	384x256		1024x1024	256	1
;	57		高	512x512(正方形)	1024x1024	256	1
;	58		高	256x256(正方形)	1024x1024	256	1
;	59		高	512x256		1024x1024	256	1
;	60		高	512x256(※)	1024x1024	256	1
;	0,1,2,3,16,17,18,19,28,32,36,40,44を65536色にしたもの
;	61		高	512x512		1024x1024	65536	1
;	62		低	512x512		1024x1024	65536	1
;	63		高	256x256		1024x1024	65536	1
;	64		低	256x256		1024x1024	65536	1
;	65		高	768x512		1024x1024	65536	1
;	66		中	1024x424	1024x1024	65536	1
;	67		中	1024x848	1024x1024	65536	1
;	68		VGA	640x480		1024x1024	65536	1
;	69		高	384x256		1024x1024	65536	1
;	70		高	512x512(正方形)	1024x1024	65536	1
;	71		高	256x256(正方形)	1024x1024	65536	1
;	72		高	512x256		1024x1024	65536	1
;	73		高	512x256(※)	1024x1024	65536	1
;
;----------------------------------------------------------------
;	いろいろ
;
;	CRT向けとLCD向け
;		各画面モードの同期周波数をそれぞれCRT向けとLCD向けに分ける
;		SRAM_XEIJのSRAM_XEIJ_LCD_BITが0のときCRT向け、1のときLCD向けの同期周波数で出力する
;
;	画面モード17
;		水平24.699kHz、垂直53.116Hz、1024x424、実画面1024x1024、16色
;		X68000初代からあるが未公開
;		LCD向けのときは画面モード16の上下を削る
;
;	画面モード18
;		水平24.699kHz、垂直53.116Hz、1024x848(インターレース)、実画面1024x1024、16色
;		X68000初代からあるが未公開
;		LCD向けのときは画面モード16の上下を削ってインターレースにする
;
;	画面モード19(VGAモード)
;		水平31.469kHz、垂直59.940Hz、640x480、実画面1024x1024、16色
;		X68000 Compactで追加された
;		CRT向けのときは画面モード16の周囲を削る
;		LCD向けのときはそのまま
;
;	画面モード20~23
;		画面モード16~19を実画面512x512、256色に変更したもの
;		X68030で追加された。未公開
;
;	画面モード24~27
;		画面モード16~19を実画面512x512、65536色に変更したもの
;		X68030で追加された。未公開
;
;	グラフィックパレットのバグ(IPLROM 1.0~1.3)
;		_CRTMODが指定された画面モードと異なる色数でグラフィックパレットを初期化する
;			https://stdkmd.net/bugsx68k/#rom_crtmod_gpalet
;		256x256は16色、512x512は256色、それ以外は65536色になる
;
;	画面モード20~27のバグ(IPLROM 1.3)
;		画面モードに20~27が指定されたとき画面モードを16~19にしてから256色または65536色に変更しているが、
;		このときBIOSワークエリアの画面モードを16~19のまま放置している
;		続けて_G_CLR_ONを呼び出すと画面モードが16~19なので16色に戻ってしまう
;
;	クリッピングエリアのバグ(IPLROM 1.3)
;		_CRTMODで画面モードを22または26にするとクリッピングエリアが512x848になる
;
;	VGAオシレータの問題
;		初代~XVIにはVGAオシレータがないのでVGAモードが正しい同期周波数で出力されない
;		VGAオシレータがある場合
;			(50.350MHz/2)/(8*100)=31.469kHz
;			(50.350MHz/2)/(8*100*525)=59.940Hz
;		VGAオシレータがない場合
;			(69.552MHz/3)/(8*100)=28.980kHz
;			(69.552MHz/3)/(8*100*525)=55.200Hz
;		大きく外れるわけではないのでマルチスキャンモニタは追従できるが気持ち悪い
;
;	VGAオシレータの有無の判別
;		VGAモードの垂直周期はVGAオシレータがあるとき16.683ms、ないとき18.116ms
;		垂直同期割り込みの間にTimer-Cが1周10msと7.5ms進んだかどうかでVGAオシレータの有無を判別できるはず
;		後で試す?
;
;----------------------------------------------------------------
;	同期信号とCRTC設定値の関係
;
;	HT	水平周期カラム数
;	HS	水平同期パルスカラム数
;	HB	水平バックポーチカラム数
;	HD	水平映像期間カラム数
;	HF	水平フロントポーチカラム数
;	VT	垂直周期ラスタ数
;	VS	垂直同期パルスラスタ数
;	VB	垂直バックポーチラスタ数
;	VD	垂直映像期間ラスタ数
;	VF	垂直フロントポーチラスタ数
;
;	R00	HT-1=HS+HB+HD+HF-1	水平フロントポーチ終了カラム
;	R01	HS-1			水平同期パルス終了カラム
;	R02	HS+HB-5			水平バックポーチ終了カラム-4
;	R03	HS+HB+HD-5		水平映像期間終了カラム-4
;	R04	VT-1=VS+VB+VD+VF-1	垂直フロントポーチ終了ラスタ
;	R05	VS-1			垂直同期パルス終了ラスタ
;	R06	VS+VB-1			垂直バックポーチ終了ラスタ
;	R07	VS+VB+VD-1		垂直映像期間終了ラスタ
;
;----------------------------------------------------------------
;	オシレータと分周比とR20LとHRLの関係
;
;	OSC/DIV	R20L	HRL
;	38/8	%0**00	*
;	38/4	%0**01	*
;	38/8	%0**1*	*
;	69/6	%1**00	0
;	69/8	%1**00	1
;	69/3	%1**01	0
;	69/4	%1**01	1
;	69/2	%1**10	*	スプライト不可
;	50/2	%1**11	*	スプライト不可。Compactから
;
;----------------------------------------------------------------
;	CRTC設定値(CRT向け)
;
;	CRT 0/4/8/12/48/61: 512x512 31.500kHz 55.458Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10101   0   91   9  17  81      567   5  40 552     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   3   92  10  12  64   6  568   6  35 512  15 |
;	  +------------------------------------------------------+
;	  (69.552MHz/3)/(8*92)=31.500kHz (69.552MHz/3)/(8*92*568)=55.458Hz
;	  64/92=0.696 512/568=0.901 (0.696/0.901)/(512/512)=0.772
;	  31k
;
;	CRT 1/5/9/13/49/62: 512x512 15.980kHz 61.463Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %00101   0   75   3   5  69      259   2  16 256     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 38.864   4   76   4   6  64   2  260   3  14 240   3 |
;	  +------------------------------------------------------+
;	  (38.864MHz/4)/(8*76)=15.980kHz (38.864MHz/4)/(8*76*260)=61.463Hz
;	  64/76=0.842 240/260=0.923 (0.842/0.923)/(512/512)=0.912
;	  15k インターレース
;
;	CRT 2/6/10/14/50/63: 256x256 31.500kHz 55.458Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10000   0   45   4   6  38      567   5  40 552     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   6   46   5   6  32   3  568   6  35 512  15 |
;	  +------------------------------------------------------+
;	  (69.552MHz/6)/(8*46)=31.500kHz (69.552MHz/6)/(8*46*568)=55.458Hz
;	  32/46=0.696 512/568=0.901 (0.696/0.901)/(256/256)=0.772
;	  31k ラスタ2度読み
;
;	CRT 3/7/11/15/51/64: 256x256 15.980kHz 61.463Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %00000   0   37   1   0  32      259   2  16 256     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 38.864   8   38   2   3  32   1  260   3  14 240   3 |
;	  +------------------------------------------------------+
;	  (38.864MHz/8)/(8*38)=15.980kHz (38.864MHz/8)/(8*38*260)=61.463Hz
;	  32/38=0.842 240/260=0.923 (0.842/0.923)/(256/256)=0.912
;	  15k
;
;	CRT 16/20/24/52/65: 768x512 31.500kHz 55.458Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10110   0  137  14  28 124      567   5  40 552     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   2  138  15  18  96   9  568   6  35 512  15 |
;	  +------------------------------------------------------+
;	  (69.552MHz/2)/(8*138)=31.500kHz (69.552MHz/2)/(8*138*568)=55.458Hz
;	  96/138=0.696 512/568=0.901 (0.696/0.901)/(768/512)=0.514
;	  31k
;
;	CRT 17/21/25/53/66: 1024x424 24.699kHz 53.116Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10110   0  175  15  31 159      464   7  32 456     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   2  176  16  20 128  12  465   8  25 424   8 |
;	  +------------------------------------------------------+
;	  (69.552MHz/2)/(8*176)=24.699kHz (69.552MHz/2)/(8*176*465)=53.116Hz
;	  128/176=0.727 424/465=0.912 (0.727/0.912)/(1024/424)=0.330
;	  24k
;
;	CRT 18/22/26/54/67: 1024x848 24.699kHz 53.116Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %11010   0  175  15  31 159      464   7  32 456     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   2  176  16  20 128  12  465   8  25 424   8 |
;	  +------------------------------------------------------+
;	  (69.552MHz/2)/(8*176)=24.699kHz (69.552MHz/2)/(8*176*465)=53.116Hz
;	  128/176=0.727 424/465=0.912 (0.727/0.912)/(1024/848)=0.661
;	  24k インターレース
;
;	CRT 19/23/27/55/68: 640x480 31.500kHz 55.458Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10110   0  137  14  36 116      567   5  56 536     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   2  138  15  26  80  17  568   6  51 480  31 |
;	  +------------------------------------------------------+
;	  (69.552MHz/2)/(8*138)=31.500kHz (69.552MHz/2)/(8*138*568)=55.458Hz
;	  80/138=0.580 480/568=0.845 (0.580/0.845)/(640/480)=0.514
;	  31k
;
;	CRT 28/29/30/31/56/69: 384x256 31.963kHz 56.273Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10001   1   67   6  11  59      567   5  40 552     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   4   68   7   9  48   4  568   6  35 512  15 |
;	  +------------------------------------------------------+
;	  (69.552MHz/4)/(8*68)=31.963kHz (69.552MHz/4)/(8*68*568)=56.273Hz
;	  48/68=0.706 512/568=0.901 (0.706/0.901)/(384/256)=0.522
;	  31k ラスタ2度読み
;
;	CRT 32/33/34/35/57/70: 512x512 31.500kHz 55.458Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10110   0  137  14  44 108      567   5  40 552     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   2  138  15  34  64  25  568   6  35 512  15 |
;	  +------------------------------------------------------+
;	  (69.552MHz/2)/(8*138)=31.500kHz (69.552MHz/2)/(8*138*568)=55.458Hz
;	  64/138=0.464 512/568=0.901 (0.464/0.901)/(512/512)=0.514
;	  31k
;
;	CRT 36/37/38/39/58/71: 256x256 31.963kHz 56.273Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10001   1   67   6  19  51      567   5  40 552     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   4   68   7  17  32  12  568   6  35 512  15 |
;	  +------------------------------------------------------+
;	  (69.552MHz/4)/(8*68)=31.963kHz (69.552MHz/4)/(8*68*568)=56.273Hz
;	  32/68=0.471 512/568=0.901 (0.471/0.901)/(256/256)=0.522
;	  31k ラスタ2度読み
;
;	CRT 40/41/42/43/44/45/46/47/59/60/72/73: 512x256 31.500kHz 55.458Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10001   0   91   9  17  81      567   5  40 552     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   3   92  10  12  64   6  568   6  35 512  15 |
;	  +------------------------------------------------------+
;	  (69.552MHz/3)/(8*92)=31.500kHz (69.552MHz/3)/(8*92*568)=55.458Hz
;	  64/92=0.696 512/568=0.901 (0.696/0.901)/(512/256)=0.386
;	  31k
;
;----------------------------------------------------------------
;	CRTC設定値(LCD向け)
;
;	LCD 0/4/8/12/48/61: 512x512 35.341kHz 56.546Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10101   0   81   5  11  75      624   1  67 579     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   3   82   6  10  64   2  625   2  66 512  45 |
;	  +------------------------------------------------------+
;	  (69.552MHz/3)/(8*82)=35.341kHz (69.552MHz/3)/(8*82*625)=56.546Hz
;	  64/82=0.780 512/625=0.819 (0.780/0.819)/(512/512)=0.953
;	  SVGA
;
;	LCD 1/5/9/13/49/62: 512x512 35.341kHz 56.546Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10101   0   81   5  11  75      624   1  83 563     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   3   82   6  10  64   2  625   2  82 480  61 |
;	  +------------------------------------------------------+
;	  (69.552MHz/3)/(8*82)=35.341kHz (69.552MHz/3)/(8*82*625)=56.546Hz
;	  64/82=0.780 480/625=0.768 (0.780/0.768)/(512/512)=1.016
;	  SVGA
;
;	LCD 2/6/10/14/50/63: 256x256 34.500kHz 55.200Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10000   0   41   2   3  35      624   1  67 579     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   6   42   3   5  32   2  625   2  66 512  45 |
;	  +------------------------------------------------------+
;	  (69.552MHz/6)/(8*42)=34.500kHz (69.552MHz/6)/(8*42*625)=55.200Hz
;	  32/42=0.762 512/625=0.819 (0.762/0.819)/(256/256)=0.930
;	  SVGA ラスタ2度読み
;
;	LCD 3/7/11/15/51/64: 256x256 34.500kHz 55.200Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10000   0   41   2   3  35      624   1  83 563     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   6   42   3   5  32   2  625   2  82 480  61 |
;	  +------------------------------------------------------+
;	  (69.552MHz/6)/(8*42)=34.500kHz (69.552MHz/6)/(8*42*625)=55.200Hz
;	  32/42=0.762 480/625=0.768 (0.762/0.768)/(256/256)=0.992
;	  SVGA ラスタ2度読み
;
;	LCD 16/20/24/52/65: 768x512 35.056kHz 56.090Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10110   0  123   8  19 115      624   1  67 579     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   2  124   9  15  96   4  625   2  66 512  45 |
;	  +------------------------------------------------------+
;	  (69.552MHz/2)/(8*124)=35.056kHz (69.552MHz/2)/(8*124*625)=56.090Hz
;	  96/124=0.774 512/625=0.819 (0.774/0.819)/(768/512)=0.630
;	  SVGA
;
;	LCD 17/21/25/53/66: 768x600 35.056kHz 56.090Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10110   0  123   8  19 115      624   1  23 623     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   2  124   9  15  96   4  625   2  22 600   1 |
;	  +------------------------------------------------------+
;	  (69.552MHz/2)/(8*124)=35.056kHz (69.552MHz/2)/(8*124*625)=56.090Hz
;	  96/124=0.774 600/625=0.960 (0.774/0.960)/(768/600)=0.630
;	  SVGA
;
;	LCD 18/22/26/54/67: 768x1024 35.056kHz 56.090Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %11010   0  123   8  19 115      624   1  67 579     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   2  124   9  15  96   4  625   2  66 512  45 |
;	  +------------------------------------------------------+
;	  (69.552MHz/2)/(8*124)=35.056kHz (69.552MHz/2)/(8*124*625)=56.090Hz
;	  96/124=0.774 512/625=0.819 (0.774/0.819)/(768/1024)=1.260
;	  SVGA インターレース
;
;	LCD 19/23/27/55/68: 640x480 31.469kHz 59.940Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10111   0   99  11  13  93      524   1  34 514     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 50.350   2  100  12   6  80   2  525   2  33 480  10 |
;	  +------------------------------------------------------+
;	  (50.350MHz/2)/(8*100)=31.469kHz (50.350MHz/2)/(8*100*525)=59.940Hz
;	  80/100=0.800 480/525=0.914 (0.800/0.914)/(640/480)=0.656
;	  VGA
;
;	LCD 28/29/30/31/56/69: 384x256 31.963kHz 51.141Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10001   1   67   6  11  59      624   1  67 579     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   4   68   7   9  48   4  625   2  66 512  45 |
;	  +------------------------------------------------------+
;	  (69.552MHz/4)/(8*68)=31.963kHz (69.552MHz/4)/(8*68*625)=51.141Hz
;	  48/68=0.706 512/625=0.819 (0.706/0.819)/(384/256)=0.574
;	  ラスタ2度読み
;
;	LCD 32/33/34/35/57/70: 512x512 35.056kHz 56.090Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10110   0  123   8  35  99      624   1  67 579     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   2  124   9  31  64  20  625   2  66 512  45 |
;	  +------------------------------------------------------+
;	  (69.552MHz/2)/(8*124)=35.056kHz (69.552MHz/2)/(8*124*625)=56.090Hz
;	  64/124=0.516 512/625=0.819 (0.516/0.819)/(512/512)=0.630
;	  SVGA
;
;	LCD 36/37/38/39/58/71: 256x256 31.963kHz 51.141Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10001   1   67   6  19  51      624   1  67 579     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   4   68   7  17  32  12  625   2  66 512  45 |
;	  +------------------------------------------------------+
;	  (69.552MHz/4)/(8*68)=31.963kHz (69.552MHz/4)/(8*68*625)=51.141Hz
;	  32/68=0.471 512/625=0.819 (0.471/0.819)/(256/256)=0.574
;	  ラスタ2度読み
;
;	LCD 40/41/42/43/44/45/46/47/59/60/72/73: 512x256 35.341kHz 56.546Hz
;	  +------------------------------------------------------+
;	  |   R20L HRL  R00 R01 R02 R03      R04 R05 R06 R07     |
;	  | %10001   0   81   5  11  75      624   1  67 579     |
;	  +------------------------------------------------------+
;	  |    OSC DIV   HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 69.552   3   82   6  10  64   2  625   2  66 512  45 |
;	  +------------------------------------------------------+
;	  (69.552MHz/3)/(8*82)=35.341kHz (69.552MHz/3)/(8*82*625)=56.546Hz
;	  64/82=0.780 512/625=0.819 (0.780/0.819)/(512/256)=0.476
;	  SVGA
;
;	【参考】VGA: 640x480 31.469kHz 59.940Hz
;	  +------------------------------------------------------+
;	  |    OSC       HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 25.175      100  12   6  80   2  525   2  33 480  10 |
;	  +------------------------------------------------------+
;	  25.175MHz/(8*100)=31.469kHz (25.175MHz/1)/(8*100*525)=59.940Hz
;	  80/100=0.800 480/525=0.914 (0.800/0.914)/(640/480)=0.656
;
;	【参考】SVGA: 800x600 35.156kHz 56.250Hz
;	  +------------------------------------------------------+
;	  |    OSC       HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 36.000      128   9  16 100   3  625   2  22 600   1 |
;	  +------------------------------------------------------+
;	  36.000MHz/(8*128)=35.156kHz (36.000MHz/1)/(8*128*625)=56.250Hz
;	  100/128=0.781 600/625=0.960 (0.781/0.960)/(800/600)=0.610
;
;	【参考】SVGA: 800x600 37.879kHz 60.317Hz
;	  +------------------------------------------------------+
;	  |    OSC       HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 40.000      132  16  11 100   5  628   4  23 600   1 |
;	  +------------------------------------------------------+
;	  40.000MHz/(8*132)=37.879kHz (40.000MHz/1)/(8*132*628)=60.317Hz
;	  100/132=0.758 600/628=0.955 (0.758/0.955)/(800/600)=0.595
;
;	【参考】SVGA: 800x600 46.875kHz 75.000Hz
;	  +------------------------------------------------------+
;	  |    OSC       HT  HS  HB  HD  HF   VT  VS  VB  VD  VF |
;	  | 49.500      132  10  20 100   2  625   3  21 600   1 |
;	  +------------------------------------------------------+
;	  49.500MHz/(8*132)=46.875kHz (49.500MHz/1)/(8*132*625)=75.000Hz
;	  100/132=0.758 600/625=0.960 (0.758/0.960)/(800/600)=0.592
;
;----------------------------------------------------------------

;パラメータ1
	.offset	0
crtmod_param_1_width:	.ds.w	1
crtmod_param_1_height:	.ds.w	1
crtmod_param_1_r20h:	.ds.b	1
			.ds.b	1
crtmod_param_1_2nd:	.ds.w	1
crtmod_param_1_size:
	.text

;パラメータ2
	.offset	0
crtmod_param_2_r20l:	.ds.b	1
crtmod_param_2_hrl:	.ds.b	1
crtmod_param_2_r00:	.ds.w	1
crtmod_param_2_r01:	.ds.w	1
crtmod_param_2_r02:	.ds.w	1
crtmod_param_2_r03:	.ds.w	1
crtmod_param_2_r04:	.ds.w	1
crtmod_param_2_r05:	.ds.w	1
crtmod_param_2_r06:	.ds.w	1
crtmod_param_2_r07:	.ds.w	1
crtmod_param_2_r08:	.ds.w	1
crtmod_param_2_size:
	.text

crtmod_param_1	.macro	width,height,r20h,offset2nd
	.dc.w	width
	.dc.w	height
	.dc.b	r20h			;R20H
	.dc.b	0
	.dc.w	crtmod_param_2_size*offset2nd
	.endm

crtmod_param_2	.macro	r20l,hrl,ht,hs,hb,hd,hf,vt,vs,vb,vd,vf,r08
	.fail	(ht.and.1)!=0
	.fail	ht!=hs+hb+hd+hf
	.fail	vt!=vs+vb+vd+vf
	.dc.b	r20l			;R20L
	.dc.b	hrl			;HRL
	.dc.w	hs+hb+hd+hf-1		;R00
	.dc.w	hs-1			;R01
	.dc.w	hs+hb-5			;R02
	.dc.w	hs+hb+hd-5		;R03
	.dc.w	vs+vb+vd+vf-1		;R04
	.dc.w	vs-1			;R05
	.dc.w	vs+vb-1			;R06
	.dc.w	vs+vb+vd-1		;R07
	.dc.w	r08			;R08
	.endm

crtmod_modes	equ	(crtmod_table_1_crt_end-crtmod_table_1_crt)/crtmod_param_1_size	;画面モードの数

iocs_10_CRTMOD:
dMM	reg	d3			;メモリモード
dPM	reg	d4			;設定前の画面モード
dGVRAM	reg	d5			;$00C00000
aE8	reg	a2			;(~)E8のベースアドレス
aEB	reg	a3			;(~)EBのベースアドレス
aED	reg	a4			;(~)EDのベースアドレス
aP1	reg	a5			;パラメータ1のアドレス
aP2	reg	a6			;パラメータ2のアドレス
	push	d1-d2/dMM/dPM/dGVRAM/a0-a1/aE8/aEB/aED/aP1/aP2
	move.l	#$00C00000,dGVRAM

;(~)E8でアクセスする
;	$00E80000	CRTC
;	$00E82000	VICON
;	$00E84000	DMAC
;	$00E86000	SUPERAREA
;	$00E88000	MFP
;	$00E8A000	RTC
;	$00E8C000	PRNPORT
;	$00E8E000	SYSPORT
	lea.l	$00E88000,aE8
E8	reg	-$00E88000(aE8)

;(~)EBでアクセスする
;	$00EB0000	SPRC
	lea.l	$00EB8000,aEB
EB	reg	-$00EB8000(aEB)

;(~)EDでアクセスする
;	$00ED0000	SRAM
	lea.l	$00ED8000,aED
ED	reg	-$00ED8000(aED)

;SRAMを初期化する
	moveq.l	#$60,d0
	moveq.l	#$F0,d2
	and.b	(SRAM_XEIJ)ED,d2
	if	<cmp.b d0,d2>,ne	;初期化されていない
		move.b	#$31,(SYSPORT_SRAM)E8	;unlocksram
		move.b	d0,(SRAM_XEIJ)ED	;初期化する
		clr.b	(SYSPORT_SRAM)E8	;locksram
	endif

;バージョンの確認
	move.l	#CRTMOD_VERSION,d0
	goto	<cmp.w #$56FF,d1>,eq,@f
	if	<cmp.w #$16FF,d1>,eq
		if	<btst.b #SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED>,ne
			bset.l	#31,d0
		endif
@@:		goto	crtmod_pop
	endif

;画面モードの最大値の確認
	if	<cmp.w #$76FF,d1>,eq
		move.l	#$16000000+crtmod_modes-1,d0
	;	goto	crtmod_pop
		goto	@b
	endif

;設定前の画面モードを確認する
	moveq.l	#0,dPM
	move.b	BIOS_CRTMOD.w,dPM	;設定前の画面モード
	swap.w	dPM
;<dPM.l:設定前の画面モード<<16

;初期化するか
	move.w	d1,dPM
	clr.b	dPM
	sub.w	dPM,d1
;<d1.w:画面モード
;<dPM.w:$0000=初期化する,$0100=初期化しない,$4300=CRT向け,$4C00=LCD向け

;CRT向けとLCD向けのスイッチの切り替え
	if	<cmp.w #$4300,dPM>,eq	;CRT向け
		move.b	#$31,(SYSPORT_SRAM)E8	;unlocksram
		bclr.b	#SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED
		clr.b	(SYSPORT_SRAM)E8	;locksram
		clr.w	dPM			;初期化する
	elif	<cmp.w #$4C00,dPM>,eq	;LCD向け
		move.b	#$31,(SYSPORT_SRAM)E8	;unlocksram
		bset.b	#SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED
		clr.b	(SYSPORT_SRAM)E8	;locksram
		clr.w	dPM			;初期化する
	endif
;<dPM.w:$0000=初期化する,$0100=初期化しない

;取得のみか
;	IPLROM 1.0~1.3は$FFFFが取得のみ
;	ここでは$xxFFを取得のみとする
;	ただし$43FFと$4CFFはCRT向けとLCD向けのスイッチの切り替えだけ行う
	goto	<cmp.w #$00FF,d1>,eq,crtmod_end	;取得のみ

;設定後の画面モードが範囲外か
;	IPLROM 1.0~1.3は$FFFFを除いて設定後の画面モードが範囲外のとき何も返さない
;	ここでは$xxFFを除いて設定後の画面モードが範囲外のとき-1を返す
	if	<cmp.w #crtmod_modes,d1>,hs
		moveq.l	#-1,d0		;設定後の画面モードが範囲外
		goto	crtmod_pop
	endif

;設定する

;パラメータ1のアドレスを求める
	lea.l	crtmod_table_1_crt(pc),aP1
	if	<btst.b #SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED>,ne	;LCD向け
		lea.l	crtmod_table_1_lcd(pc),aP1
	endif
	move.w	d1,d0
  .if crtmod_param_1_size=8
	lsl.w	#3,d0
  .else
	mulu.w	#crtmod_param_1_size,d0
  .endif
	adda.w	d0,aP1
;<aP1.l:パラメータ1のアドレス

;パラメータ2のアドレスを求める
	lea.l	crtmod_table_2(pc),aP2
	adda.w	crtmod_param_1_2nd(aP1),aP2
;<aP2.l:パラメータ2のアドレス

;メモリモードを確認する
	moveq.l	#7,dMM
	and.b	crtmod_param_1_r20h(aP1),dMM	;メモリモード。0~7
;<dMM.w:メモリモード。0~7

;拡張グラフィック画面を確認する
;	拡張グラフィック画面がないのに拡張グラフィック画面が必要な画面モードが指定されたとき-2を返す
;		              76543210
	if	<btst.b dMM,#%10100000>,ne	;メモリモード5,7。拡張グラフィック画面が必要
		move.b	(CRTC_MODE_BYTE)E8,-(sp)	;メモリモードを保存
		move.b	#7,(CRTC_MODE_BYTE)E8	;メモリモードを7に変更
		movea.l	dGVRAM,a0
		move.w	(a0),d2			;保存
		not.w	(a0)			;反転
		move.w	(a0),d0			;d0=反転してから読み出したもの
		move.w	d2,(a0)			;復元
		move.b	(sp)+,(CRTC_MODE_BYTE)E8	;メモリモードを復元
		not.w	d2			;d2=読み出してから反転したもの
		if	<cmp.w d2,d0>,ne	;反転できていない
			moveq.l	#-2,d0			;拡張グラフィック画面がない
			goto	crtmod_pop
		endif
	endif

;初期化するか
	if	<tst.w dPM>,eq

	;初期化する

	;設定後の画面モードを保存する
		move.b	d1,BIOS_CRTMOD.w	;設定後の画面モード

	;グラフィック画面OFF、テキスト画面OFF、スプライト画面OFF
		clr.w	(VICON_VISIBLE)E8

	;テキストカーソルOFF
		IOCS	_B_CUROFF

	;テキストプレーン0~1をクリアする
	;	ラスタコピーを使うと速いがコードが長くなる
	;	初回はCRTCが動いていないのでラスタコピーが終わらない
		move.w	#$0133,(CRTC_ACCESS)E8	;同時アクセス開始
		moveq.l	#0,d0
		lea.l	$00E00000,a0		;テキストVRAM
		move.w	#($00E20000-$00E00000)/(4*2)-1,d1	;16384回
		for	d1
			move.l	d0,(a0)+
			move.l	d0,(a0)+
		next
		move.w	#$0033,(CRTC_ACCESS)E8	;同時アクセス終了

	;グラフィック画面使用不可
		clr.w	BIOS_GRAPHIC_PALETS.w	;グラフィック画面の色数-1。0=グラフィック画面使用不可

	;初期化する/しない共通
		bsr	crtmod_common

	;CRTCコマンド停止
		clr.w	(CRTC_ACTION)E8

	;グラフィックパレットを初期化する
  .ifdef CRTMOD_REPRODUCE_BUG		;バグを再現させる
		moveq.l	#3,d0
		and.b	crtmod_param_2_r20l(aP2),d0	;水平解像度。256x256=256色,512x512=512色,768x512=65536色
  .else
		move.w	dMM,d0			;メモリモード。0~7
  .endif
		PATCH_jsr	g_clr_on,initialize_gpalet	;グラフィックパレットを初期化する

	;グラフィックストレージON
	;	IPLROM 1.0~1.3の_CRTMODはグラフィックストレージONの状態で復帰する
		bset.b	#CRTC_GRAPHIC_STORAGE_BIT,(CRTC_MODE_BYTE)E8	;グラフィックストレージON

	;テキストカーソルON
		IOCS	_B_CURON

	;テキストパレットを初期化する
		lea.l	(SRAM_TEXT_PALET_0)ED,a0
		lea.l	(VICON_TSPALET)E8,a1
		move.l	(a0)+,(a1)+		;0,1
		move.l	(a0)+,(a1)+		;2,3
		move.l	(a0),d0			;d0=4|8
		move.l	d0,d1			;d1=4|8
		swap.w	d0			;d0=8|4
		move.w	d0,(a1)+		;4
		move.w	d0,(a1)+		;5
		move.w	d0,(a1)+		;6
		move.w	d0,(a1)+		;7
		move.w	d1,d0			;d0=8|8
		move.l	d0,(a1)+		;8,9
		move.l	d0,(a1)+		;10,11
		move.l	d0,(a1)+		;12,13
		move.l	d0,(a1)+		;14,15

	;コントラストを初期化する
		move.b	(SRAM_CONTRAST)ED,(SYSPORT_CONTRAST)E8

	;スプライトコントローラを設定する
~i = SPRC_SPRITE_OFF|SPRC_BG_1_TEXT_1|SPRC_BG_1_OFF|SPRC_BG_0_TEXT_0|SPRC_BG_0_OFF
		move.w	#~i,(SPRC_CONTROL)EB

	;テキスト画面ON
		move.w	#VICON_TXON_MASK,(VICON_VISIBLE)E8

	;優先順位を設定する
~i = 0<<VICON_SPPR_BIT|1<<VICON_TXPR_BIT|2<<VICON_GRPR_BIT			;SP>TX>GR
~j = 3<<VICON_G4TH_BIT|2<<VICON_G3RD_BIT|1<<VICON_G2ND_BIT|0<<VICON_G1ST_BIT	;G1>G2>G3>G4
		move.w	#~i|~j,(VICON_PRIORITY)E8

	else

	;初期化しない

	;設定後の画面モードを保存する
		move.b	d1,BIOS_CRTMOD.w	;設定後の画面モード

	;グラフィック画面使用不可
		clr.w	BIOS_GRAPHIC_PALETS.w	;グラフィック画面の色数-1。0=グラフィック画面使用不可

	;初期化する/しない共通
		bsr	crtmod_common

	;グラフィック画面が表示されているか
		moveq.l	#VICON_GXON_MASK|VICON_G4ON_MASK|VICON_G3ON_MASK|VICON_G2ON_MASK|VICON_G1ON_MASK,d0
		and.w	(VICON_VISIBLE)E8,d0
		if	ne			;グラフィック画面が表示されているとき

		;メモリモードを設定する
		;	ストレージは変化しない
			moveq.l	#.not.7,d0
			and.b	(CRTC_MODE_BYTE)E8,d0
			or.b	dMM,d0
			move.b	d0,(CRTC_MODE_BYTE)E8
			move.w	dMM,(VICON_MEMORY_MODE)E8

		;BIOSワークエリアを初期化する
			lea.l	BIOS_GRAPHIC_PAGE.w,a0	;BIOS_GRAPHIC_Y_OFFSET,BIOS_GRAPHIC_PALETS
			move.l	dGVRAM,(a0)+		;描画ページ先頭アドレス
			move.l	#2*512,d0
			if	<cmp.w #4,dMM>,hs	;4~7
				add.w	d0,d0			;2*1024
			endif
			move.l	d0,(a0)+		;Y方向オフセット
			moveq.l	#16-1,d0
		;		              76543210
			if	<btst.b dMM,#%00100010>,ne	;1,5
				st.b	d0			;256-1
		;		              76543210
			elif	<btst.b dMM,#%10001100>,ne	;2,3,7
				moveq.l	#-1,d0			;65536-1
			endif
			move.w	d0,(a0)			;色数-1

		endif

	endif

;終了
;<dPM.l:設定前の画面モード<<16
crtmod_end:
	clr.w	dPM
	swap.w	dPM			;設定前の画面モード
	move.l	dPM,d0
crtmod_pop:
	pop
	rts

;初期化する/しない共通
crtmod_common:

;CRTCとシステムポートのR20,HRL,R00~R07を設定する
;	すべての画面モードがメモリモード3になる
;	ストレージはOFFになる
	move.w	#3<<8,d2		;R20H(新)
	move.b	crtmod_param_2_r20l(aP2),d2	;R20L(新)
;<d2.w:R20(新)
	lea.l	dot_clock_rank(pc),a0
	moveq.l	#%00011111,d0
	and.b	(CRTC_RESOLUTION_BYTE)E8,d0	;R20L(古)
	moveq.l	#SYSPORT_HRL,d1
	and.b	(SYSPORT_MISC)E8,d1
	neg.b	d1
	addx.b	d0,d0				;R20L<<1|HRL(古)
	move.b	(a0,d0.w),d0			;古いドットクロックのランク
	moveq.l	#%00011111,d1
	and.b	d2,d1				;R20L(新)
	add.b	d1,d1
	add.b	crtmod_param_2_hrl(aP2),d1	;R20L<<1|HRL(新)
	move.b	(a0,d1.w),d1			;新しいドットクロックのランク
	if	<cmp.b d0,d1>,lo	;ドットクロックが下がる
		move.w	d2,(CRTC_MODE_RESOLUTION)E8	;R20
		tst.b	crtmod_param_2_hrl(aP2)
		bsne.b	#SYSPORT_HRL_BIT,(SYSPORT_MISC)E8	;HRL
		lea.l	(CRTC_H_SYNC_END)E8,a0	;R01
		lea.l	crtmod_param_2_r01(aP2),a1
		move.w	(a1)+,(a0)+		;R01
		move.l	(a1)+,(a0)+		;R02,R03
		move.l	(a1)+,(a0)+		;R04,R05
		move.l	(a1)+,(a0)+		;R06,R07
		move.w	crtmod_param_2_r00(aP2),(CRTC_H_FRONT_END)E8	;R00
	else				;ドットクロックが同じか上がる
		lea.l	(CRTC_H_FRONT_END)E8,a0	;R00
		lea.l	crtmod_param_2_r00(aP2),a1
		move.l	(a1)+,(a0)+		;R00,R01
		move.l	(a1)+,(a0)+		;R02,R03
		move.l	(a1)+,(a0)+		;R04,R05
		move.l	(a1)+,(a0)+		;R06,R07
		move.w	d2,(CRTC_MODE_RESOLUTION)E8	;R20
		tst.b	crtmod_param_2_hrl(aP2)
		bsne.b	#SYSPORT_HRL_BIT,(SYSPORT_MISC)E8	;HRL
	endif

;CRTCのR08を設定する
;	外部同期水平アジャスト
;	スーパーインポーズするときビデオの映像とX68000の映像を重ねるために、
;	ビデオとX68000の水平同期パルスの先頭の時間差を38.863632MHzのサイクル数で指定する
;	低解像度512x512のとき
;		水平同期パルス幅は4キャラクタ。R01=4-1=3
;		水平バックポーチは6キャラクタ。R02=4+6-5=5
;		外部同期水平アジャストは44
;		perl -e "print((4.7+4.7)*38.863632-(4*8*(4+6))-1)"
;		44.3181408
;	低解像度256x256のとき。1ドット追加する
;		水平同期パルス幅は2キャラクタ。R01=2-1=1
;		水平バックポーチは3キャラクタ。R02=2+3-5=0
;		外部同期水平アジャストは36
;		perl -e "print((4.7+4.7)*38.863632-(8*(8*(2+3)+1))-1)"
;		36.3181408
	move.w	crtmod_param_2_r08(aP2),(CRTC_ADJUST)E8	;R08

;CRTCのR09~R19,R21~R24を初期化する
	moveq.l	#0,d0
	lea.l	(CRTC_RASTER)E8,a0	;R09
	move.w	d0,(a0)+		;R09
	move.l	d0,(a0)+		;R10,R11
	move.l	d0,(a0)+		;R12,R13
	move.l	d0,(a0)+		;R14,R15
	move.l	d0,(a0)+		;R16,R17
	move.l	d0,(a0)+		;R18,R19
	addq.l	#2,a0
	move.w	#$0033,(a0)+		;R21
	move.l	d0,(a0)+		;R22,R23
	move.w	d0,(a0)+		;R24

;ビデオコントローラのメモリモードを設定する
;	すべての画面モードがメモリモード3になる
	move.w	#3,(VICON_MEMORY_MODE)E8

;スプライトコントローラを初期化する
;解像度
	moveq.l	#%1_11_11,d1
	and.b	crtmod_param_2_r20l(aP2),d1	;R20L
;<d1.w:解像度
;水平バックポーチ終了カラム
	moveq.l	#4,d0
	add.w	crtmod_param_2_r02(aP2),d0
	move.w	d0,(SPRC_H_BACK_END)EB	;スプライト水平バックポーチ終了カラム。R02+4
;水平フロントポーチ終了カラム
;	水平バックポーチ終了カラムを設定後130us待ってから水平フロントポーチ終了カラムを設定する
;	水平フロントポーチ終了カラムは水平256ドットのときはR00と同じ値、それ以外は255
;		Inside X68000に低解像度256x256のときだけR00と同じ値を、それ以外は255を設定すると書かれているが、
;		高解像度256x256のときも255にするとスプライトが崩れる場合がある
;		水平512ドットのときは255にしないと水平256ドットから水平512ドットに切り替えたときスプライトの水平方向の位置がずれることがある
;	IPLROM 1.3はdbraでX68030 25MHzのとき500us待っている。060turboのときウエイトが不足する
	moveq.l	#500/50,d0		;500us
	bsr	wait_50us		;50us単位のウェイト
	moveq.l	#%0_00_11,d0
	and.b	d1,d0
	if	eq			;水平256ドット
		move.w	crtmod_param_2_r00(aP2),(SPRC_H_FRONT_END)EB	;スプライト水平フロントポーチ終了カラム。R00
	else				;水平256ドット以外
		move.w	#255,(SPRC_H_FRONT_END)EB	;スプライト水平フロントポーチ終了カラム。255
	endif
;垂直バックポーチ終了ラスタ
	move.w	crtmod_param_2_r06(aP2),(SPRC_V_BACK_END)EB	;スプライト垂直バックポーチ終了ラスタ。R06
;解像度
	move.b	BIOS_CRTMOD.w,d0
	if	<cmp.b #36,d0>,hs	;36~
		if	<cmp.b #40,d0>,lo	;36/37/38/39 256x256(正方形)
			moveq.l	#%10000,d1		;スプライトは256x256
		elif	<cmp.b #44,d0>,hs	;44~
			ifor	<cmp.b #48,d0>,lo,<cmp.b #60,d0>,eq,<cmp.b #73,d0>,eq	;44/45/46/47/60/73 512x256(※)
				moveq.l	#%10101,d1		;スプライトは512x512
			endif
		endif
	endif
	move.w	d1,(SPRC_RESOLUTION)EB	;スプライト解像度。--------|---|高解像度|垂直サイズ##|水平サイズ##

;グラフィック画面のクリッピングエリア
;	画面モード20~27は表示画面が実画面より大きいことに注意する
	move.w	crtmod_param_1_width(aP1),d0	;幅
	move.w	crtmod_param_1_height(aP1),d1	;高さ
	if	<cmp.w #4,dMM>,lo	;メモリモード0~3。512x512まで
		move.w	#512,d2
		if	<cmp.w d2,d0>,hi
			move.w	d2,d0
		endif
		if	<cmp.w d2,d1>,hi
			move.w	d2,d1
		endif
	endif
	subq.w	#1,d0			;X最大
	subq.w	#1,d1			;Y最大
	clr.l	BIOS_GRAPHIC_LEFT.w	;BIOS_GRAPHIC_TOP
	move.w	d0,BIOS_GRAPHIC_RIGHT.w
	move.w	d1,BIOS_GRAPHIC_BOTTOM.w

;グラフィックVRAMのY方向のオフセット
					;dMM=   0    1    2    3    4    5    6    7
	moveq.l	#4,d0			; d0=   4    4    4    4    4    4    4    4
	and.w	dMM,d0			; d0=   0    0    0    0    4    4    4    4
	addq.w	#4,d0			; d0=   4    4    4    4    8    8    8    8
	lsl.w	#8,d0			; d0=1024 1024 1024 1024 2048 2048 2048 2048
	move.l	d0,BIOS_GRAPHIC_Y_OFFSET.w

;グラフィック画面のページ数
					;dMM=0 1 2  3  4  5  6  7
	moveq.l	#4,d0			; d0=4 4 4  4  4  4  4  4
	lsr.b	dMM,d0			; d0=4 2 1  0  0  0  0  0
	seq.b	d1			; d1=0 0 0 -1 -1 -1 -1 -1
	sub.b	d1,d0			; d0=4 2 1  1  1  1  1  1
	move.b	d0,BIOS_GRAPHIC_PAGES.w

;テキスト画面の位置
	move.l	#$00E00000,BIOS_TEXT_PLANE.w
	clr.l	BIOS_CONSOLE_OFFSET.w

;テキスト画面の大きさ
	move.w	crtmod_param_1_width(aP1),d0	;幅
	move.w	crtmod_param_1_height(aP1),d1	;高さ
	lsr.w	#3,d0			;幅/8
	lsr.w	#4,d1			;高さ/16。424は16で割り切れないことに注意
	subq.w	#1,d0			;幅/8-1
	subq.w	#1,d1			;高さ/16-1
	move.w	d0,BIOS_CONSOLE_RIGHT.w
	move.w	d1,BIOS_CONSOLE_BOTTOM.w

;テキストカーソルの位置
	clr.l	BIOS_CURSOR_COLUMN.w	;BIOS_CURSOR_ROW

;マウスカーソルの移動範囲
	clr.l	d1
	move.l	BIOS_GRAPHIC_RIGHT,d2	;BIOS_GRAPHIC_BOTTOM
	IOCS	_MS_LIMIT		;IOCSコール$77 _MS_LIMIT マウスカーソルの移動範囲を設定する

	rts

;パラメータ1(CRT向け)
crtmod_table_1_crt:
;			 WIDTH HEIGHT R20H  2ND    1ST
	crtmod_param_1	   512,   512,   4,   0  ; CRT 0
	crtmod_param_1	   512,   512,   4,   1  ; CRT 1
	crtmod_param_1	   256,   256,   4,   2  ; CRT 2
	crtmod_param_1	   256,   256,   4,   3  ; CRT 3
	crtmod_param_1	   512,   512,   0,   0  ; CRT 4
	crtmod_param_1	   512,   512,   0,   1  ; CRT 5
	crtmod_param_1	   256,   256,   0,   2  ; CRT 6
	crtmod_param_1	   256,   256,   0,   3  ; CRT 7
	crtmod_param_1	   512,   512,   1,   0  ; CRT 8
	crtmod_param_1	   512,   512,   1,   1  ; CRT 9
	crtmod_param_1	   256,   256,   1,   2  ; CRT 10
	crtmod_param_1	   256,   256,   1,   3  ; CRT 11
	crtmod_param_1	   512,   512,   3,   0  ; CRT 12
	crtmod_param_1	   512,   512,   3,   1  ; CRT 13
	crtmod_param_1	   256,   256,   3,   2  ; CRT 14
	crtmod_param_1	   256,   256,   3,   3  ; CRT 15
	crtmod_param_1	   768,   512,   4,   4  ; CRT 16
	crtmod_param_1	  1024,   424,   4,   5  ; CRT 17
	crtmod_param_1	  1024,   848,   4,   6  ; CRT 18
	crtmod_param_1	   640,   480,   4,   7  ; CRT 19
	crtmod_param_1	   768,   512,   1,   4  ; CRT 20
	crtmod_param_1	  1024,   424,   1,   5  ; CRT 21
	crtmod_param_1	  1024,   848,   1,   6  ; CRT 22
	crtmod_param_1	   640,   480,   1,   7  ; CRT 23
	crtmod_param_1	   768,   512,   3,   4  ; CRT 24
	crtmod_param_1	  1024,   424,   3,   5  ; CRT 25
	crtmod_param_1	  1024,   848,   3,   6  ; CRT 26
	crtmod_param_1	   640,   480,   3,   7  ; CRT 27
	crtmod_param_1	   384,   256,   4,   8  ; CRT 28
	crtmod_param_1	   384,   256,   0,   8  ; CRT 29
	crtmod_param_1	   384,   256,   1,   8  ; CRT 30
	crtmod_param_1	   384,   256,   3,   8  ; CRT 31
	crtmod_param_1	   512,   512,   4,   9  ; CRT 32
	crtmod_param_1	   512,   512,   0,   9  ; CRT 33
	crtmod_param_1	   512,   512,   1,   9  ; CRT 34
	crtmod_param_1	   512,   512,   3,   9  ; CRT 35
	crtmod_param_1	   256,   256,   4,  10  ; CRT 36
	crtmod_param_1	   256,   256,   0,  10  ; CRT 37
	crtmod_param_1	   256,   256,   1,  10  ; CRT 38
	crtmod_param_1	   256,   256,   3,  10  ; CRT 39
	crtmod_param_1	   512,   256,   4,  22  ; CRT 40
	crtmod_param_1	   512,   256,   0,  22  ; CRT 41
	crtmod_param_1	   512,   256,   1,  22  ; CRT 42
	crtmod_param_1	   512,   256,   3,  22  ; CRT 43
	crtmod_param_1	   512,   256,   4,  22  ; CRT 44
	crtmod_param_1	   512,   256,   0,  22  ; CRT 45
	crtmod_param_1	   512,   256,   1,  22  ; CRT 46
	crtmod_param_1	   512,   256,   3,  22  ; CRT 47
	crtmod_param_1	   512,   512,   5,   0  ; CRT 48
	crtmod_param_1	   512,   512,   5,   1  ; CRT 49
	crtmod_param_1	   256,   256,   5,   2  ; CRT 50
	crtmod_param_1	   256,   256,   5,   3  ; CRT 51
	crtmod_param_1	   768,   512,   5,   4  ; CRT 52
	crtmod_param_1	  1024,   424,   5,   5  ; CRT 53
	crtmod_param_1	  1024,   848,   5,   6  ; CRT 54
	crtmod_param_1	   640,   480,   5,   7  ; CRT 55
	crtmod_param_1	   384,   256,   5,   8  ; CRT 56
	crtmod_param_1	   512,   512,   5,   9  ; CRT 57
	crtmod_param_1	   256,   256,   5,  10  ; CRT 58
	crtmod_param_1	   512,   256,   5,  22  ; CRT 59
	crtmod_param_1	   512,   256,   5,  22  ; CRT 60
	crtmod_param_1	   512,   512,   7,   0  ; CRT 61
	crtmod_param_1	   512,   512,   7,   1  ; CRT 62
	crtmod_param_1	   256,   256,   7,   2  ; CRT 63
	crtmod_param_1	   256,   256,   7,   3  ; CRT 64
	crtmod_param_1	   768,   512,   7,   4  ; CRT 65
	crtmod_param_1	  1024,   424,   7,   5  ; CRT 66
	crtmod_param_1	  1024,   848,   7,   6  ; CRT 67
	crtmod_param_1	   640,   480,   7,   7  ; CRT 68
	crtmod_param_1	   384,   256,   7,   8  ; CRT 69
	crtmod_param_1	   512,   512,   7,   9  ; CRT 70
	crtmod_param_1	   256,   256,   7,  10  ; CRT 71
	crtmod_param_1	   512,   256,   7,  22  ; CRT 72
	crtmod_param_1	   512,   256,   7,  22  ; CRT 73
crtmod_table_1_crt_end:

;パラメータ1(LCD向け)
crtmod_table_1_lcd:
;			 WIDTH HEIGHT R20H  2ND    1ST
	crtmod_param_1	   512,   512,   4,  11  ; LCD 0
	crtmod_param_1	   512,   512,   4,  12  ; LCD 1
	crtmod_param_1	   256,   256,   4,  13  ; LCD 2
	crtmod_param_1	   256,   256,   4,  14  ; LCD 3
	crtmod_param_1	   512,   512,   0,  11  ; LCD 4
	crtmod_param_1	   512,   512,   0,  12  ; LCD 5
	crtmod_param_1	   256,   256,   0,  13  ; LCD 6
	crtmod_param_1	   256,   256,   0,  14  ; LCD 7
	crtmod_param_1	   512,   512,   1,  11  ; LCD 8
	crtmod_param_1	   512,   512,   1,  12  ; LCD 9
	crtmod_param_1	   256,   256,   1,  13  ; LCD 10
	crtmod_param_1	   256,   256,   1,  14  ; LCD 11
	crtmod_param_1	   512,   512,   3,  11  ; LCD 12
	crtmod_param_1	   512,   512,   3,  12  ; LCD 13
	crtmod_param_1	   256,   256,   3,  13  ; LCD 14
	crtmod_param_1	   256,   256,   3,  14  ; LCD 15
	crtmod_param_1	   768,   512,   4,  15  ; LCD 16
	crtmod_param_1	   768,   600,   4,  16  ; LCD 17
	crtmod_param_1	   768,  1024,   4,  17  ; LCD 18
	crtmod_param_1	   640,   480,   4,  18  ; LCD 19
	crtmod_param_1	   768,   512,   1,  15  ; LCD 20
	crtmod_param_1	   768,   600,   1,  16  ; LCD 21
	crtmod_param_1	   768,  1024,   1,  17  ; LCD 22
	crtmod_param_1	   640,   480,   1,  18  ; LCD 23
	crtmod_param_1	   768,   512,   3,  15  ; LCD 24
	crtmod_param_1	   768,   600,   3,  16  ; LCD 25
	crtmod_param_1	   768,  1024,   3,  17  ; LCD 26
	crtmod_param_1	   640,   480,   3,  18  ; LCD 27
	crtmod_param_1	   384,   256,   4,  19  ; LCD 28
	crtmod_param_1	   384,   256,   0,  19  ; LCD 29
	crtmod_param_1	   384,   256,   1,  19  ; LCD 30
	crtmod_param_1	   384,   256,   3,  19  ; LCD 31
	crtmod_param_1	   512,   512,   4,  20  ; LCD 32
	crtmod_param_1	   512,   512,   0,  20  ; LCD 33
	crtmod_param_1	   512,   512,   1,  20  ; LCD 34
	crtmod_param_1	   512,   512,   3,  20  ; LCD 35
	crtmod_param_1	   256,   256,   4,  21  ; LCD 36
	crtmod_param_1	   256,   256,   0,  21  ; LCD 37
	crtmod_param_1	   256,   256,   1,  21  ; LCD 38
	crtmod_param_1	   256,   256,   3,  21  ; LCD 39
	crtmod_param_1	   512,   256,   4,  23  ; LCD 40
	crtmod_param_1	   512,   256,   0,  23  ; LCD 41
	crtmod_param_1	   512,   256,   1,  23  ; LCD 42
	crtmod_param_1	   512,   256,   3,  23  ; LCD 43
	crtmod_param_1	   512,   256,   4,  23  ; LCD 44
	crtmod_param_1	   512,   256,   0,  23  ; LCD 45
	crtmod_param_1	   512,   256,   1,  23  ; LCD 46
	crtmod_param_1	   512,   256,   3,  23  ; LCD 47
	crtmod_param_1	   512,   512,   5,  11  ; LCD 48
	crtmod_param_1	   512,   512,   5,  12  ; LCD 49
	crtmod_param_1	   256,   256,   5,  13  ; LCD 50
	crtmod_param_1	   256,   256,   5,  14  ; LCD 51
	crtmod_param_1	   768,   512,   5,  15  ; LCD 52
	crtmod_param_1	   768,   600,   5,  16  ; LCD 53
	crtmod_param_1	   768,  1024,   5,  17  ; LCD 54
	crtmod_param_1	   640,   480,   5,  18  ; LCD 55
	crtmod_param_1	   384,   256,   5,  19  ; LCD 56
	crtmod_param_1	   512,   512,   5,  20  ; LCD 57
	crtmod_param_1	   256,   256,   5,  21  ; LCD 58
	crtmod_param_1	   512,   256,   5,  23  ; LCD 59
	crtmod_param_1	   512,   256,   5,  23  ; LCD 60
	crtmod_param_1	   512,   512,   7,  11  ; LCD 61
	crtmod_param_1	   512,   512,   7,  12  ; LCD 62
	crtmod_param_1	   256,   256,   7,  13  ; LCD 63
	crtmod_param_1	   256,   256,   7,  14  ; LCD 64
	crtmod_param_1	   768,   512,   7,  15  ; LCD 65
	crtmod_param_1	   768,   600,   7,  16  ; LCD 66
	crtmod_param_1	   768,  1024,   7,  17  ; LCD 67
	crtmod_param_1	   640,   480,   7,  18  ; LCD 68
	crtmod_param_1	   384,   256,   7,  19  ; LCD 69
	crtmod_param_1	   512,   512,   7,  20  ; LCD 70
	crtmod_param_1	   256,   256,   7,  21  ; LCD 71
	crtmod_param_1	   512,   256,   7,  23  ; LCD 72
	crtmod_param_1	   512,   256,   7,  23  ; LCD 73

;パラメータ2
crtmod_table_2:
;			   R20L  HRL    HT   HS   HB   HD   HF    VT   VS   VB   VD   VF   R08    2ND  1ST
	crtmod_param_2	 %10101,   0,   92,  10,  12,  64,   6,  568,   6,  35, 512,  15,   27  ;   0  CRT 0/4/8/12/48/61
	crtmod_param_2	 %00101,   0,   76,   4,   6,  64,   2,  260,   3,  14, 240,   3,   44  ;   1  CRT 1/5/9/13/49/62
	crtmod_param_2	 %10000,   0,   46,   5,   6,  32,   3,  568,   6,  35, 512,  15,   27  ;   2  CRT 2/6/10/14/50/63
	crtmod_param_2	 %00000,   0,   38,   2,   3,  32,   1,  260,   3,  14, 240,   3,   36  ;   3  CRT 3/7/11/15/51/64
	crtmod_param_2	 %10110,   0,  138,  15,  18,  96,   9,  568,   6,  35, 512,  15,   27  ;   4  CRT 16/20/24/52/65
	crtmod_param_2	 %10110,   0,  176,  16,  20, 128,  12,  465,   8,  25, 424,   8,   27  ;   5  CRT 17/21/25/53/66
	crtmod_param_2	 %11010,   0,  176,  16,  20, 128,  12,  465,   8,  25, 424,   8,   27  ;   6  CRT 18/22/26/54/67
	crtmod_param_2	 %10110,   0,  138,  15,  26,  80,  17,  568,   6,  51, 480,  31,   27  ;   7  CRT 19/23/27/55/68
	crtmod_param_2	 %10001,   1,   68,   7,   9,  48,   4,  568,   6,  35, 512,  15,   27  ;   8  CRT 28/29/30/31/56/69
	crtmod_param_2	 %10110,   0,  138,  15,  34,  64,  25,  568,   6,  35, 512,  15,   27  ;   9  CRT 32/33/34/35/57/70
	crtmod_param_2	 %10001,   1,   68,   7,  17,  32,  12,  568,   6,  35, 512,  15,   27  ;  10  CRT 36/37/38/39/58/71
	crtmod_param_2	 %10101,   0,   82,   6,  10,  64,   2,  625,   2,  66, 512,  45,   27  ;  11  LCD 0/4/8/12/48/61
	crtmod_param_2	 %10101,   0,   82,   6,  10,  64,   2,  625,   2,  82, 480,  61,   27  ;  12  LCD 1/5/9/13/49/62
	crtmod_param_2	 %10000,   0,   42,   3,   5,  32,   2,  625,   2,  66, 512,  45,   27  ;  13  LCD 2/6/10/14/50/63
	crtmod_param_2	 %10000,   0,   42,   3,   5,  32,   2,  625,   2,  82, 480,  61,   27  ;  14  LCD 3/7/11/15/51/64
	crtmod_param_2	 %10110,   0,  124,   9,  15,  96,   4,  625,   2,  66, 512,  45,   27  ;  15  LCD 16/20/24/52/65
	crtmod_param_2	 %10110,   0,  124,   9,  15,  96,   4,  625,   2,  22, 600,   1,   27  ;  16  LCD 17/21/25/53/66
	crtmod_param_2	 %11010,   0,  124,   9,  15,  96,   4,  625,   2,  66, 512,  45,   27  ;  17  LCD 18/22/26/54/67
	crtmod_param_2	 %10111,   0,  100,  12,   6,  80,   2,  525,   2,  33, 480,  10,   27  ;  18  LCD 19/23/27/55/68
	crtmod_param_2	 %10001,   1,   68,   7,   9,  48,   4,  625,   2,  66, 512,  45,   27  ;  19  LCD 28/29/30/31/56/69
	crtmod_param_2	 %10110,   0,  124,   9,  31,  64,  20,  625,   2,  66, 512,  45,   27  ;  20  LCD 32/33/34/35/57/70
	crtmod_param_2	 %10001,   1,   68,   7,  17,  32,  12,  625,   2,  66, 512,  45,   27  ;  21  LCD 36/37/38/39/58/71
	crtmod_param_2	 %10001,   0,   92,  10,  12,  64,   6,  568,   6,  35, 512,  15,   27  ;  22  CRT 40/41/42/43/44/45/46/47/59/60/72/73
	crtmod_param_2	 %10001,   0,   82,   6,  10,  64,   2,  625,   2,  66, 512,  45,   27  ;  23  LCD 40/41/42/43/44/45/46/47/59/60/72/73

;R20L<<1|HRL→ドットクロックのランク
;	rank	R20L	HRL	osc	div	dotclk	mode
;	7	1**10	*	69.552	2	34.776	768x512(高)
;	6	1**11	*	50.350	2	25.175	640x480
;	5	1**01	0	69.552	3	23.184	512x512(高)
;	4	1**01	1	69.552	4	17.388	384x256
;	3	1**00	0	69.552	6	11.592	256x256(高)
;	2	0**01	*	38.864	4	9.716	512x512(低)
;	1	1**00	1	69.552	8	8.694
;	0	0**00	*	38.864	8	4.858	256x256(低)
;	0	0**1*	*	38.864	8	4.858
dot_clock_rank:
  .rept 4
	.dc.b	0	;0**00 0
	.dc.b	0	;0**00 1
	.dc.b	2	;0**01 0
	.dc.b	2	;0**01 1
	.dc.b	0	;0**10 0
	.dc.b	0	;0**10 1
	.dc.b	0	;0**11 0
	.dc.b	0	;0**11 1
  .endm
  .rept 4
	.dc.b	3	;1**00 0
	.dc.b	1	;1**00 1
	.dc.b	5	;1**01 0
	.dc.b	4	;1**01 1
	.dc.b	7	;1**10 0
	.dc.b	7	;1**10 1
	.dc.b	6	;1**11 0
	.dc.b	6	;1**11 1
  .endm



;----------------------------------------------------------------
;IOCSコール$90 _G_CLR_ON グラフィック画面の消去とパレット初期化と表示ON
;>d0.l:0
;----------------------------------------------------------------
iocs_90_G_CLR_ON:
dMM	reg	d3			;メモリモード
dGVRAM	reg	d5			;$00C00000
aE8	reg	a2			;(~)E8のベースアドレス
aED	reg	a4			;(~)EDのベースアドレス
aP1	reg	a5			;パラメータ1のアドレス
	push	d0-d2/dMM/dGVRAM/a0/aE8/aED/aP1
	move.l	#$00C00000,dGVRAM

;(~)E8でアクセスする
;	$00E80000	CRTC
;	$00E82000	VICON
;	$00E84000	DMAC
;	$00E86000	SUPERAREA
;	$00E88000	MFP
;	$00E8A000	RTC
;	$00E8C000	PRNPORT
;	$00E8E000	SYSPORT
	lea.l	$00E88000,aE8
E8	reg	-$00E88000(aE8)

;(~)EDでアクセスする
;	$00ED0000	SRAM
	lea.l	$00ED8000,aED
ED	reg	-$00ED8000(aED)

;現在の画面モードを確認する
	moveq.l	#0,d1
	move.b	BIOS_CRTMOD.w,d1	;現在の画面モード
	if	<cmp.w #crtmod_modes,d1>,hs	;現在の画面モードが範囲外のとき
		move.b	(SRAM_CRTMOD)ED,d1		;起動時の画面モードを使う
		if	<cmp.w #crtmod_modes,d1>,hs	;起動時の画面モードも範囲外のとき
			moveq.l	#16,d1			;16を使う
  .if 0
			move.b	#$31,(SYSPORT_SRAM)E8	;unlocksram
			move.b	d1,(SRAM_CRTMOD)ED
			clr.b	(SYSPORT_SRAM)E8	;locksram
  .endif
		endif
	endif

;<d1.l:画面モード

;パラメータ1のアドレスを求める
	lea.l	crtmod_table_1_crt,aP1
	if	<btst.b #SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED>,ne	;LCD向け
		lea.l	crtmod_table_1_lcd,aP1
	endif
	move.w	d1,d0
  .if crtmod_param_1_size=8
	lsl.w	#3,d0
  .else
	mulu.w	#crtmod_param_1_size,d0
  .endif
	adda.w	d0,aP1
;<aP1.l:パラメータ1のアドレス

;メモリモードを確認する
	moveq.l	#7,dMM
	and.b	crtmod_param_1_r20h(aP1),dMM	;メモリモード。0~7
;<dMM.w:メモリモード。0~7

;テキスト画面のみON
	move.w	#VICON_TXON_MASK,(VICON_VISIBLE)E8

;メモリモードを設定する
	move.b	dMM,(CRTC_MODE_BYTE)E8
	move.w	dMM,(VICON_MEMORY_MODE)E8

;グラフィックVRAMをクリアする
	bset.b	#CRTC_GRAPHIC_STORAGE_BIT,(CRTC_MODE_BYTE)E8	;グラフィックストレージON
	movea.l	dGVRAM,a0
	moveq.l	#0,d0
	moveq.l	#1-1,d2
;		              76543210
	if	<btst.b dMM,#%10100000>,ne	;5,7
	;メモリモードだけでクリアする範囲を決めている
	;拡張グラフィック画面がないとき拡張グラフィック画面が必要な画面モードはCRTMODが弾くのでここを通ることはないはず
		moveq.l	#4-1,d2
	endif
	for	d2
		moveq.l	#-1,d1			;2*512*512/8=65536
		for	d1
			move.l	d0,(a0)+
			move.l	d0,(a0)+
		next
	next
	bclr.b	#CRTC_GRAPHIC_STORAGE_BIT,(CRTC_MODE_BYTE)E8	;グラフィックストレージOFF

;BIOSワークエリアを初期化する
	lea.l	BIOS_GRAPHIC_PAGE.w,a0	;BIOS_GRAPHIC_Y_OFFSET,BIOS_GRAPHIC_PALETS
	move.l	dGVRAM,(a0)+		;描画ページ先頭アドレス
	move.l	#2*512,d0
	if	<cmp.w #4,dMM>,hs	;4~7
		add.w	d0,d0			;2*1024
	endif
	move.l	d0,(a0)+		;Y方向オフセット
	moveq.l	#16-1,d0
;		              76543210
	if	<btst.b dMM,#%00100010>,ne	;1,5
		st.b	d0			;256-1
;		              76543210
	elif	<btst.b dMM,#%10001100>,ne	;2,3,7
		moveq.l	#-1,d0			;65536-1
	endif
	move.w	d0,(a0)			;色数-1

;グラフィックパレットを初期化する
	move.w	dMM,d0
	bsr	initialize_gpalet

;テキスト画面ON、グラフィック画面ON
;	if	<cmp.w #4,dMM>,lo	;メモリモード0~3。512x512ドット
;		move.w	#VICON_TXON_MASK|VICON_G4ON_MASK|VICON_G3ON_MASK|VICON_G2ON_MASK|VICON_G1ON_MASK,(VICON_VISIBLE)E8
;	else				;メモリモード4~7。1024x1024ドット
;		move.w	#VICON_TXON_MASK|VICON_GXON_MASK,(VICON_VISIBLE)E8
;	endif
;	IPLROM 1.0~1.3は1024x1024ドットと512x512ドットを両方ONにしている
	move.w	#VICON_TXON_MASK|VICON_GXON_MASK|VICON_G4ON_MASK|VICON_G3ON_MASK|VICON_G2ON_MASK|VICON_G1ON_MASK,(VICON_VISIBLE)E8

	moveq.l	#0,d0
	pop
	rts

;----------------------------------------------------------------
;グラフィックパレットを初期化する
;<d0.w:メモリモード。0~7
initialize_gpalet:
	push	d0-d4/a0-a1
	lea.l	VICON_GPALET,a0
	ifor	<tst.w d0>,eq,<cmp.w #4,d0>,eq,<cmp.w #6,d0>,eq	;メモリモード0,4,6。16色
		lea.l	gpalet_16_array(pc),a1
		moveq.l	#16/2-1,d0
		for	d0
			move.l	(a1)+,(a0)+
		next
	elifor	<cmp.w #1,d0>,eq,<cmp.w #5,d0>,eq	;メモリモード1,5。256色
	;greenは増分10.5で4階調(10.5*3=31.5)、redとblueは増分4.5で8階調(4.5*7=31.5)、端数は切り捨て
		move.l	#((9<<1)<<16)|(9<<1),d1	;blueの増分4.5+4.5
		moveq.l	#0,d3			;green=0
		do
			moveq.l	#(4<<1),d2		;red=0,blue=(0,4.5)
			moveq.l	#8-1,d4
			for	d4
				move.l	d3,d0			;green
				and.l	#.not.(((1<<10)<<16)|(1<<10)),d0	;greenの端数を切り捨てる
				add.l	d2,d0			;red,blue=(0,4.5)
				and.l	#.not.(((1<<5)<<16)|(1<<5)),d0	;redの端数を切り捨てる
				move.l	d0,(a0)+
				add.l	d1,d0			;blue+=4.5+4.5
				move.l	d0,(a0)+
				add.l	d1,d0			;blue+=4.5+4.5
				move.l	d0,(a0)+
				add.l	d1,d0			;blue+=4.5+4.5
				move.l	d0,(a0)+
				add.l	#((9<<5)<<16)|(9<<5),d2	;red+=4.5
			next
			add.l	#((21<<10)<<16)|(21<<10),d3	;green+=10.5
		while	cc
	else				;メモリモード2,3,7。65536色
		move.l	#$00_01_00_01,d0	;(L00,L01,H00,H01),(L02,L03,H02,H03),…,(LFE,LFF,HFE,HFF)
		move.l	#$02_02_02_02,d2
		moveq.l	#256/2-1,d1
		for	d1
			move.l	d0,(a0)+
			add.l	d2,d0
		next
	endif
	pop
	rts

;グラフィック16色パレット
gpalet_16_array:
	dcrgb	0,0,0
	dcrgb	10,10,10
	dcrgb	0,0,16
	dcrgb	0,0,31
	dcrgb	16,0,0
	dcrgb	31,0,0
	dcrgb	16,0,16
	dcrgb	31,0,31
	dcrgb	0,16,0
	dcrgb	0,31,0
	dcrgb	0,16,16
	dcrgb	0,31,31
	dcrgb	16,16,0
	dcrgb	31,31,0
	dcrgb	21,21,21
	dcrgb	31,31,31

;----------------------------------------------------------------
;50us単位のウェイト
;<d0.l:時間(50us単位)
	.text
	.even
wait_50us:
  .if 0
;Timer-Cを使う
;	Timer-Cが1/200プリスケール(50us)で動作していなければならない
aTCDR	reg	a0
	push	d0-d2/aTCDR
	lea.l	MFP_TCDR,aTCDR
	moveq.l	#0,d1
	move.b	(aTCDR),d1
	move.b	(aTCDR),d1
	do
		moveq.l	#0,d2
		move.b	(aTCDR),d2
		redo	<cmp.b (aTCDR),d2>,cs
		sub.w	d2,d1
		if	cs
			add.w	#200,d1
		endif
		exg.l	d1,d2
		sub.l	d2,d0
	while	hi
	pop
	rts
  .else
;dbra空ループを使う
;	BIOS_MPU_SPEED_ROM.wとBIOS_MPU_TYPE.wが設定されていなければならない
	push	d0-d3
	subq.l	#1,d0
	if	cc
		move.l	BIOS_MPU_SPEED_ROM_LONG.w,d1
		if	eq
			move.w	BIOS_MPU_SPEED_ROM.w,d1
		endif
	;	上限を20bitとして50usあたりのdbraの回数を求める
		if	<cmpi.b #4,BIOS_MPU_TYPE.w>,lo	;000/010/020/030
			move.w	#205,d2			;2**12*50/1000=204.8
		elif	eq			;040
			move.w	#307,d2			;2**12*50/1000*6/4=307.2
		else				;060
			move.w	#1229,d2		;2**12*50/1000*6/1=1228.8
		endif
		move.l	d1,d3			;d3=H|L
		swap.w	d3			;d3=L|H
		mulu.w	d2,d3			;d3=c*H
		mulu.w	d2,d1			;d1=c*L
		swap.w	d3
		clr.w	d3			;d3=c*H|0
		add.l	d3,d1			;d1=c*(H|L)
		and.w	#$F000,d1		;43210___
		rol.l	#4,d1			;3210___4
		swap.w	d1			;___43210  50usあたりのdbraの回数
		subq.l	#1,d1
		move.l	d1,d2
		forlong	d0
			move.l	d2,d1
			.align	16,$2048
			forlong	d1
			next
		next
	endif
	pop
	rts
  .endif



;----------------------------------------------------------------
;デバイスドライバの末尾
device_tail:

;----------------------------------------------------------------
;デバイスコマンド0 初期化
initialize:

;パラメータを確認する
	moveq.l	#-1,d6			;CRT/LCDは指定されていない
	moveq.l	#-1,d7			;画面モードは指定されていない
	movea.l	18(a5),a0		;パラメータ。区切りは0、末尾は0,0。先頭はデバイスファイル名
	do
	while	<tst.b (a0)+>,ne	;デバイスファイル名を読み飛ばす
	dostart
		gotoand	<cmp.b #'-',d0>,ne,<cmp.b #'/',d0>,ne,parameter_error	;-,/以外
		move.b	(a0)+,d0
		goto	eq,parameter_error	;-,/の後に文字がない
		bsr	tolower
		if	<cmp.b #'l',d0>,eq	;-l
			goto	<tst.l d6>,pl,parameter_error	;CRT/LCDは既に指定されている
			ifand	<tst.b (a0)>,eq,<tst.b 1(a0)>,ne	;10進数が離れている
				addq.l	#1,a0
			endif
			bsr	nonspace
			bsr	stou
			gotoor	<>,cs,<cmp.l #1,d0>,hi,parameter_error	;10進数がないか範囲外
			move.l	d0,d6			;CRT/LCDが指定された
		elif	<cmp.b #'m',d0>,eq	;-m
			goto	<tst.l d7>,pl,parameter_error	;画面モードは既に指定されている
			ifand	<tst.b (a0)>,eq,<tst.b 1(a0)>,ne	;10進数が離れている
				addq.l	#1,a0
			endif
			bsr	nonspace
			bsr	stou
			gotoor	<>,cs,<cmp.l #47,d0>,hi,parameter_error	;10進数がないか範囲外
			move.l	d0,d7			;画面モードが指定された
		else				;-l,-m以外
			goto	parameter_error
			noreturn
		endif
		goto	<tst.b (a0)+>,ne,parameter_error	;余分な文字がある
	start
		move.b	(a0)+,d0
	while	ne
;<d6.l:0=CRT,1=LCD,-1=指定されていない
;<d7.l:画面モード,-1=指定されていない

;ベクタを変更する
	lea.l	vector_table(pc),a0	;ベクタテーブル
	bsr	set_vector		;ベクタを変更する

;画面モードを設定する
	bsr	set_screen_mode

;タイトルを表示する
	pea.l	crlf_title(pc)
	DOS	_PRINT
	peastrdata	<'CRTMOD/G_CLR_ONを拡張します',13,10>
	DOS	_PRINT
	addq.l	#8,sp

;デバイスドライバの末尾を設定する
	move.l	#device_tail,14(a5)	;デバイスドライバの末尾

;デバイスドライバを組み込む
	moveq.l	#0,d0
	rts

;パラメータエラー
parameter_error:

;タイトルとエラーメッセージを表示する
	pea.l	crlf_title(pc)
	DOS	_PRINT
	peastrdata	<'指定できないパラメータです',13,10>
	DOS	_PRINT
	addq.l	#8,sp

;デバイスドライバを組み込まない
	move.w	#ABORT|MISCELLANEOUS_ERROR,d0	;中止(A) エラーが発生しました
	rts

;----------------------------------------------------------------
;実行開始
execution_start:

;オプションを確認する
	moveq.l	#-1,d5			;常駐/解除は指定されていない
	moveq.l	#-1,d6			;CRT/LCDは指定されていない
	moveq.l	#-1,d7			;画面モードは指定されていない
	lea.l	1(a2),a0
	dostart
		gotoand	<cmp.b #'-',d0>,ne,<cmp.b #'/',d0>,ne,usage_exit	;-,/以外
		addq.l	#1,a0
		move.b	(a0)+,d0
		goto	eq,usage_exit		;-,/の後に文字がない
		bsr	tolower
		if	<cmp.b #'e',d0>,eq	;-e
			goto	<tst.l d5>,pl,usage_exit	;常駐/解除は既に指定されている
			moveq.l	#0,d5			;常駐
		elif	<cmp.b #'l',d0>,eq	;-l
			goto	<tst.l d6>,pl,usage_exit	;CRT/LCDは既に指定されている
			bsr	nonspace
			bsr	stou
			gotoor	<>,cs,<cmp.l #1,d0>,hi,usage_exit	;10進数がないか範囲外
			move.l	d0,d6			;CRT/LCDが指定された
		elif	<cmp.b #'m',d0>,eq	;-m
			goto	<tst.l d7>,pl,usage_exit	;画面モードは既に指定されている
			bsr	nonspace
			bsr	stou
			gotoor	<>,cs,<cmp.l #47,d0>,hi,usage_exit	;10進数がないか範囲外
			move.l	d0,d7			;画面モードが指定された
		elif	<cmp.b #'r',d0>,eq	;-r
			goto	<tst.l d5>,pl,usage_exit	;常駐/解除は既に指定されている
			moveq.l	#1,d5			;解除
		else				;-e,-l,-m,-r以外
			goto	usage_exit
			noreturn
		endif
	start
		bsr	nonspace
	while	ne
;<d5.l:0=常駐,1=解除,-1=指定されていない
;<d6.l:0=CRT,1=LCD,-1=指定されていない
;<d7.l:画面モード,-1=指定されていない

;常駐/解除が指定されていないときは画面モードだけ設定する
	if	<tst.l d5>,mi	;常駐/解除が指定されていない
		gotoand	<tst.l d6>,mi,<tst.l d7>,mi,usage_exit	;CRT/LCDと画面モードも指定されていない
		bsr	set_screen_mode		;画面モードを設定する
		goto	exit			;終了する
		noreturn
	endif

;スーパーバイザモードへ移行する
	supervisormode

;常駐部分を探す

;デバイスドライバを探す
	movea.l	DOS_HUMAN_MEMORY.w,a2	;Human68kの先頭
	do
		addq.l	#2,a2
	whileor	<cmpi.l #'NUL ',DH_NAME(a2)>,ne,<cmpi.l #'    ',DH_NAME+4(a2)>,ne,<cmpi.w #$8024,DH_TYPE(a2)>,ne	;NULデバイスまで進む。必ずある
	while	<movea.l a2,a3>,<movea.l DH_NEXT(a2),a2>,<cmpa.l #-1,a2>,ne	;次のデバイスドライバ
		lea.l	DH_NAME(a2),a0		;常駐部分のデバイス名
		lea.l	program_head+DH_NAME(pc),a1	;自分のデバイス名
		gotoand	<cmpm.l (a0)+,(a1)+>,eq,<cmpm.l (a0)+,(a1)+>,eq,end_of_search	;一致したら終了
	endwhile
	suba.l	a3,a3			;常駐部分はデバイスドライバではない

;手前にある常駐プログラムを探す
	lea.l	program_head(pc),a2	;常駐部分の先頭
	while	<movea.l MM_PREV-MM_PROGRAM(a2),a2>,<move.l a2,d0>,ne	;直前のメモリ管理テーブル
		lea.l	MM_PROGRAM(a2),a2	;常駐部分の先頭
		lea.l	DH_SIZE(a2),a0		;常駐部分のデバイスヘッダの末尾
		continue	<cmpa.l MM_TAIL-MM_PROGRAM(a2),a0>,hi	;メモリブロックが短すぎる
		lea.l	DH_NAME(a2),a0		;常駐部分のデバイス名
		lea.l	program_head+DH_NAME(pc),a1	;自分のデバイス名
		gotoand	<cmpm.l (a0)+,(a1)+>,eq,<cmpm.l (a0)+,(a1)+>,eq,end_of_search	;一致したら終了
	endwhile

;後ろにある常駐プログラムを探す
	lea.l	program_head(pc),a2	;常駐部分の先頭
	while	<movea.l MM_NEXT-MM_PROGRAM(a2),a2>,<move.l a2,d0>,ne	;直後のメモリ管理テーブル
		lea.l	MM_PROGRAM(a2),a2	;常駐部分の先頭
		lea.l	DH_SIZE(a2),a0		;常駐部分のデバイスヘッダの末尾
		continue	<cmpa.l MM_TAIL-MM_PROGRAM(a2),a0>,hi	;メモリブロックが短すぎる
		lea.l	DH_NAME(a2),a0		;常駐部分のデバイス名
		lea.l	program_head+DH_NAME(pc),a1	;自分のデバイス名
		gotoand	<cmpm.l (a0)+,(a1)+>,eq,<cmpm.l (a0)+,(a1)+>,eq,end_of_search	;一致したら終了
	endwhile

end_of_search:
;<a2.l:常駐部分の先頭,0=常駐部分が見つからない
;<a3.l:(常駐部分が見つかったとき)常駐部分の前のデバイスドライバ。0=常駐部分はデバイスドライバではない

	if	<move.l a2,d0>,eq	;常駐していない

		if	<tst.l d5>,ne		;解除

		;ユーザモードへ復帰する
			usermode

		;エラーメッセージを表示する
			move.w	#2,-(sp)
			peastrdata	<'常駐していません',13,10>
			DOS	_FPUTS
			addq.l	#6,sp

		;エラー終了する
			move.w	#1,-(sp)
			DOS	_EXIT2
			noreturn

		endif

	;常駐

	;ベクタを変更する
		lea.l	vector_table(pc),a0	;ベクタテーブル
		bsr	set_vector		;ベクタを変更する

	;ユーザモードへ復帰する
		usermode

	;画面モードを設定する
		bsr	set_screen_mode

	;常駐メッセージを表示する
		pea.l	title(pc)
		DOS	_PRINT
		peastrdata	<'常駐しました',13,10>
		DOS	_PRINT
		addq.l	#8,sp

	;常駐終了する
		clr.w	-(sp)
		move.l	#device_tail-program_head,-(sp)
		DOS	_KEEPPR
		noreturn

	else				;常駐している

		if	<tst.l d5>,eq		;常駐

		;ユーザモードに復帰する
			usermode

		;エラーメッセージを表示する
			move.w	#2,-(sp)
			peastrdata	<'常駐しています',13,10>
			DOS	_FPUTS
			addq.l	#6,sp

		;エラー終了する
			move.w	#1,-(sp)
			DOS	_EXIT2
			noreturn

		endif

	;解除

	;ベクタを確認する
		lea.l	(vector_table-program_head)(a2),a0	;常駐部分のベクタテーブル
		bsr	check_vector		;ベクタを確認する

		if	ne			;ベクタが変更されている

		;ユーザモードに復帰する
			usermode

		;エラーメッセージを表示する
			move.w	#2,-(sp)
			peastrdata	<'ベクタが変更されています。解除できません',13,10>
			DOS	_FPUTS
			addq.l	#6,sp

		;エラー終了する
			move.w	#1,-(sp)
			DOS	_EXIT2
			noreturn

		endif

	;ベクタが変更されていない

	;ベクタを復元する
		lea.l	(vector_table-program_head)(a2),a0	;常駐部分のベクタテーブル
		bsr	release_vector		;ベクタを復元する

		if	<move.l a3,d0>,ne	;常駐部分はデバイスドライバ

			;デバイスドライバを切り離す
			move.l	(a2),(a3)		;前のデバイスドライバに次のデバイスドライバを繋ぐ

		else				;常駐部分は常駐プログラム

			;常駐部分を開放する
			pea.l	MM_SIZE-MM_PROGRAM(a2)	;常駐部分のメモリブロックの先頭
			DOS	_MFREE
			addq.l	#4,sp

		endif

	;ユーザモードに復帰する
		usermode

	;メッセージを表示する
		peastrdata	<'解除しました',13,10>
		DOS	_PRINT
		addq.l	#4,sp

	;終了する
		DOS	_EXIT
		noreturn

	endif

;タイトルと使用法を表示する
usage_exit:
	pea.l	title(pc)
	DOS	_PRINT
	pea.l	usage(pc)
	DOS	_PRINT
	addq.l	#8,sp

;終了する
exit:
	DOS	_EXIT

;----------------------------------------------------------------
;ベクタを変更する
;<a0.l:ベクタテーブル
set_vector:
	push	d0/a0-a1
	docontinue
		movea.w	d0,a1			;オフセット
		move.l	(a1),d0
		move.l	(a0)+,(a1)		;新しいベクタ
		move.l	d0,(a0)+		;古いベクタ
	while	<move.w (a0)+,d0>,ne
	pop
	rts

;----------------------------------------------------------------
;ベクタを確認する
;<a0.l:常駐部分のベクタテーブル
;>ccr:eq=ベクタは変更されていない,ne=ベクタが変更されている
check_vector:
	push	d0/a0-a1
	docontinue
		movea.w	d0,a1			;オフセット
		move.l	(a1),d0
		break	<cmp.l (a0)+,d0>,ne	;新しいベクタが現在のベクタと一致しなければ失敗
		addq.l	#4,a0			;古いベクタを読み飛ばす
	while	<move.w (a0)+,d0>,ne
	pop
	rts

;----------------------------------------------------------------
;ベクタを復元する
;<a0.l:常駐部分のベクタテーブル
release_vector:
	push	d0/a0-a1
	docontinue
		movea.w	d0,a1			;オフセット
		addq.l	#4,a0			;新しいベクタを読み飛ばす
		move.l	(a0)+,(a1)		;古いベクタ
	while	<move.w (a0)+,d0>,ne
	pop
	rts

;----------------------------------------------------------------
;画面モードを設定する
;<d6.l:0=CRT,1=LCD,-1=指定されていない
;<d7.l:画面モード,-1=指定されていない
set_screen_mode:
	if	<tst.l d7>,pl		;画面モードが指定されている
		move.l	#(14<<16)|3,-(sp)	;ファンクションを表示しない
		DOS	_CONCTRL
		addq.l	#4,sp
		move.l	d7,d1			;画面モード
		if	<tst.l d6>,pl		;LCDモードが指定されている
			if	eq			;CRT向け
				or.w	#$4300,d1
			else				;LCD向け
				or.w	#$4C00,d1
			endif
		endif
		IOCS	_CRTMOD
	;	IOCS	_G_CLR_ON
	elif	<tst.l d6>,pl		;LCDモードが指定されている
		if	eq			;CRT向け
			move.w	#$43FF,d1
		else				;LCD向け
			move.w	#$4CFF,d1
		endif
		IOCS	_CRTMOD
		move.l	#(16<<16)|$FFFF,-(sp)	;DOSレベルの画面モードを再設定する
		DOS	_CONCTRL
		move.w	d0,2(sp)
		DOS	_CONCTRL
		addq.l	#4,sp
		move.l	#(14<<16)|0,-(sp)	;ファンクションを表示する
		DOS	_CONCTRL
		addq.l	#4,sp
	endif
	rts

;----------------------------------------------------------------
;空白以外の文字まで読み飛ばす
;<a0.l:文字列
;>d0.l:空白以外の文字または0
;>a0.l:空白以外の文字または0の位置
;>z:eq=0
nonspace:
	moveq.l	#0,d0
	do
		move.b	(a0)+,d0		;次の文字
		redoand	<cmp.b #9,d0>,hs,<cmp.b #13,d0>,ls	;\t\n\v\f\rならば繰り返す
	while	<cmp.b #' ',d0>,eq		;空白ならば繰り返す
	subq.l	#1,a0			;進み過ぎた分戻る
	tst.l	d0
	rts

;----------------------------------------------------------------
;10進数の文字列を符号なし整数に変換する
;<a0.l:10進数の文字列。先頭の空白は認めない
;>d0.l:(ccのとき)符号なし整数。(csのとき)0=10進数の文字がない,-1=オーバーフロー
;>a0.l:(ccのとき)10進数の文字列の次の位置。(csのとき)変化しない
;>z:(ccのとき)eq=符号なし整数が0
;>v:(csのとき)vc=10進数の文字がない,vs=オーバーフロー
;>c:cs=10進数の文字がないまたはオーバーフロー
stou::
	push	d1-d2/a1
	moveq.l	#0,d0			;符号なし整数
	moveq.l	#0,d1			;文字
	movea.l	a0,a1			;開始位置
	dostart
		goto	<cmp.l #$1999999A,d0>,hs,20f	;10倍したらオーバーフローする
		move.l	d0,d2			;1倍
		lsl.l	#2,d0			;4倍
		add.l	d2,d0			;5倍
		add.l	d0,d0			;10倍して
		add.l	d1,d0			;1桁加える
		goto	cs,20f			;オーバーフローした
	start
		move.b	(a0)+,d1		;次の文字
		sub.b	#'0',d1			;整数にする
	whileand	<>,hs,<cmp.b #10,d1>,lo	;10進数の文字ならば繰り返す
	subq.l	#1,a0			;進み過ぎた分戻る
	goto	<cmpa.l a1,a0>,eq,30f	;進んでいない。10進数の文字がない
	tst.l	d0			;ne/eq,vc,cc
10:	pop
	rts

;オーバーフロー
20:
  .if 0
	do
		move.b	(a0)+,d1		;次の文字
		sub.b	#'0',d1			;整数にする
	whileand	<>,hs,<cmp.b #10,d1>,lo	;10進数の文字を読み飛ばす
	subq.l	#1,a0			;進み過ぎた分戻る
  .else
	movea.l	a1,a0			;開始位置に戻る
  .endif
	moveq.l	#-1,d0			;オーバーフロー
	move.w	#%00011,ccr		;ne,vs,cs
	goto	10b

;10進数の文字がない
30:
;	moveq.l	#0,d0			;10進数の文字がない
	move.w	#%00101,ccr		;eq,vc,cs
	goto	10b

;----------------------------------------------------------------
;小文字にする
;<d0.b:文字
;>d0.b:文字
tolower:
	ifand	<cmp.b #'A',d0>,hs,<cmp.b #'Z',d0>,ls	;大文字
		add.b	#'a'-'A',d0		;小文字にする
	endif
	rts

	.data

;----------------------------------------------------------------
;タイトル
crlf_title:
	.dc.b	13,10
title:
	.dc.b	TITLE_STRING,13,10,0
	.even

;使用法
usage:
	.dc.b	13,10
	.dc.b	'説明',13,10
	.dc.b	'  crtmod16.xはIPLROM 1.6に含まれるCRTMOD/G_CLR_ONを常駐プログラムにしたものです。',13,10
	.dc.b	'  一般的な液晶モニタで768x512ドットの画面をはみ出さないように表示できます。',13,10
	.dc.b	'  384x256ドット、512x512ドット(正方形)などの画面モードが追加されます。',13,10
	.dc.b	13,10
	.dc.b	'補足',13,10
	.dc.b	'  IPLROM 1.0~1.3にあったグラフィックパレットに関するバグが修正されます。',13,10
	.dc.b	'  バグに依存しているソフトウェアが誤動作する場合はcrtmrb16.xを組み込んでください。',13,10
	.dc.b	13,10
	.dc.b	'オプション',13,10
	.dc.b	'  -e         常駐します。',13,10
	.dc.b	'  -l 0~1    0でCRT向けの同期周波数、1でLCD向けの同期周波数を選択します。',13,10
	.dc.b	'  -m 0~73   画面モードを選択します。crtmodtest.xの説明を参照してください。',13,10
	.dc.b	'  -r         常駐を解除します。',13,10
	.dc.b	13,10
	.dc.b	0
	.even

	.end	execution_start