misc/crtmodtest.s
;========================================================================================
;  crtmodtest.s
;  Copyright (C) 2003-2026 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/
;========================================================================================

;----------------------------------------------------------------
;	crtmodtest.x (2026-03-16)
;
;	説明
;		crtmodtest.xはCRTMODの実装とモニタの性能を確認するための画面を表示します。
;		ESCキーを押すと画面モードを変更したまま終了、他のキーを押すと元に戻して終了します。
;
;	オプション
;		-l 0~1    0でCRT向けの同期周波数、1でLCD向けの同期周波数を選択します。
;		-m 0~73   画面モードを選択します。
;		-s         -lの選択をSRAMに保存します。
;
;	更新履歴
;		2022-02-21
;			公開。
;		2023-01-10
;			長いヘルプメッセージをページ毎に区切って表示するようにしました。
;		2023-11-14
;			-lを指定したときCRTorLCDモードを変更したまま終了していましたが、元に戻して終了するようにしました。
;			-sを追加しました。-sを指定すると-lで指定されたCRTorLCDモードに変更したまま終了します。
;		2024-08-25
;			画面モード40~47に対応しました。
;		2024-08-26
;			IPLROM 1.0~1.3のIOCS _SP_INITのバグを踏まないようにしました。
;			ESCキーで終了したとき、スプライトとグラフィックを非表示に、テキストを消去、テキストパレットを復元します。
;			コードを整理しました。
;		2025-04-01
;			IPLROM 1.6/crtmod16.x以外の環境で動かすと画面が乱れる問題を修正しました。
;		2025-04-13
;			stouを修正しました。
;		2025-06-29
;			画面モード48~73に対応しました。
;			IPLROM 1.6/crtmod16.xを確認して選択できる画面モードか確認します。
;			スプライト画面が拡張されていてsprdrv.xが組み込まれているとき、
;			・768x512でスプライト画面が表示されます。
;			・512x512でBG1が表示されます。
;		2026-03-16
;			ハイフンを撤去しました。
;
;----------------------------------------------------------------

	.include	bioswork.equ
	.include	control2.mac
	.include	crtc.equ
	.include	doscall.mac
	.include	iocscall.mac
	.include	misc.mac
	.include	push2.mac
	.include	sprc.equ
	.include	vector.equ

TITLE_STRING	reg	'crtmodtest.x (2026-03-16)'

MODE_MAX	equ	73		;画面モードの最大値

TEXT_LINE	equ	3
GRAPHIC_LINE	equ	4		;4,5,6,7
SPRITE_LINE	equ	8
BG_LINE		equ	9		;9,10

	.text

base:
	lea.l	base(pc),a6
r	reg	-base(a6)

;オプションを確認する
	moveq.l	#-1,d6			;CRTorLCDモードは指定されていない
	moveq.l	#-1,d7			;画面モードは指定されていない
	sf.b	(save_to_sram)r		;CRTorLCDモードをSRAMに保存しない
	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 #'l',d0>,eq	;-l
			goto	<tst.l d6>,pl,usage_exit	;CRTorLCDモードは既に指定されている
			bsr	nextword
			bsr	stou
			gotoor	<>,cs,<cmp.l #1,d0>,hi,usage_exit	;10進数がないか範囲外
			move.l	d0,d6			;CRTorLCDモードが指定された
		elif	<cmp.b #'m',d0>,eq	;-m
			goto	<tst.l d7>,pl,usage_exit	;画面モードは既に指定されている
			bsr	nextword
			bsr	stou
			gotoor	<>,cs,<cmp.l #MODE_MAX,d0>,hi,usage_exit	;10進数がないか範囲外
			move.l	d0,d7			;画面モードが指定された
		elif	<cmp.b #'s',d0>,eq	;-s
			st.b	(save_to_sram)r		;CRTorLCDモードをSRAMに保存する
		else				;-l,-m,-s以外
			goto	usage_exit
		endif
	start
		bsr	nextword
	while	ne
	goto	<tst.l d7>,mi,usage_exit	;画面モードが指定されていない
	gotoand	<tst.l d6>,mi,<tst.b (save_to_sram)r>,ne,usage_exit	;CRTorLCDモードが指定されていないのでSRAMに保存できない
;<d6.l:CRTorLCDモード。0=CRT向け,1=LCD向け,-1=指定されていない
;<d7.l:画面モード

;_CRTMODを確認する
	move.w	#$56FF,d1
	IOCS	_CRTMOD
;標準の_CRTMODはd1.wが$FFFFでなくd1.bが範囲外のとき何もせず何も返さない。d0.lにはゼロ拡張されたIOCSコール番号$00000010が入っているはず
	rol.l	#8,d0
	if	<cmp.b #$16,d0>,eq	;_CRTMODはIPLROM 1.6/crtmod16.x
		ror.l	#8,d0
	else				;_CRTMODがIPLROM 1.6/crtmod16.xでないかバージョンが古すぎる
		moveq.l	#0,d0
	endif
	moveq.l	#0,d1
	if	<cmp.w #48,d7>,hs	;48~73
		move.l	#$16_250629,d1
	elif	<cmp.w #40,d7>,hs	;40~47
		move.l	#$16_240825,d1
	elifor	<cmp.w #28,d7>,hs,<tst.l d6>,gt	;28~39またはLCD向け
		move.l	#$16_231012,d1		;これより古いIPLROM 1.6/crtmod16.xはバージョンを返さないので不可とする
	endif
	if	<cmp.l d1,d0>,lo	;_CRTMODがIPLROM 1.6/crtmod16.xでないかバージョンが古すぎる
		leastr	<'_CRTMODがIPLROM 1.6/crtmod16.xでないかバージョンが古すぎます',13,10>,a0
		bsr	print
		goto	exit

	endif

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

;拡張グラフィック画面を確認する
	ifand	<cmp.w #48,d7>,hs,<cmp.w #73,d7>,ls	;48~73
		lea.l	CRTC_MODE_BYTE,a1
		move.b	(a1),-(sp)		;メモリモードを保存
		move.b	#7,(a1)			;メモリモードを7に変更
		movea.l	#$00C00000,a0
		move.w	(a0),d1			;保存
		not.w	(a0)			;反転
		move.w	(a0),d0			;d0=反転してから読み出したもの
		move.w	d1,(a0)			;復元
		move.b	(sp)+,(a1)		;メモリモードを復元
		not.w	d1			;d2=読み出してから反転したもの
		if	<cmp.w d1,d0>,ne	;反転できていない
			usermode
			leastr	<'拡張グラフィック画面がありません',13,10>,a0
			bsr	print
			goto	exit

		endif
	endif

;CRTorLCDモードを保存する
	move.w	#$16FF,d1
	IOCS	_CRTMOD
	rol.l	#8,d0
	cmp.b	#$96,d0
	seq.b	(saved_crtlcd)r

;CRTorLCDモードを変更する
	if	<tst.l d6>,pl		;CRTorLCDモードが指定されている。_CRTMODがIPLROM 1.6/crtmod16.xであることは確認済み
		if	eq			;CRT向け
			move.w	#$43FF,d1
		else				;LCD向け
			move.w	#$4CFF,d1
		endif
		IOCS	_CRTMOD			;CRTorLCDモードを変更する
	endif

;画面モードを設定する
	move.l	d7,d1			;画面モード
	IOCS	_CRTMOD
	IOCS	_G_CLR_ON

;情報を集める
;画面モード
	moveq.l	#0,d0
	move.b	BIOS_CRTMOD.w,(screen_mode)r
;CRTorLCDモード
	move.w	#$16FF,d1
	IOCS	_CRTMOD
	rol.l	#8,d0
	cmp.b	#$96,d0
	seq.b	(crtlcd_mode)r
;グラフィックページ数
	move.b	BIOS_GRAPHIC_PAGES.w,d0
	move.b	d0,(pages)r
;BGサイズ
	moveq.l	#3,d0
	and.w	SPRC_RESOLUTION,d0
	sne.b	(bg_size)r
;スプライト画面の有無
	moveq.l	#.not.%10010,d0
	or.b	CRTC_RESOLUTION_BYTE,d0	;R20L。%1xx1xのときだけ%11111111
	not.b	d0			;%1xx1xのときだけ%00000000
	if	ne			;%1xx1xではない
		st.b	(sprite_exists)r	;スプライト画面を使用できる
	else				;%1xx1x
		moveq.l	#-1,d0
		move.l	OFFSET_BUS_ERROR.w,-(sp)
		movea.l	sp,a0
		move.l	#@f,OFFSET_BUS_ERROR.w
		nop
		move.w	SPRC_SCROLL,d0		;スプライトスクロールレジスタをリードしてみる
		nop
	@@:	movea.l	a0,sp
		move.l	(sp)+,OFFSET_BUS_ERROR.w
		tst.w	d0			;バスエラーが発生したかX座標が負のときmi、さもなくばpl
		spl.b	(sprite_exists)r	;plのときスプライト画面を使用できる
	endif
;画面の幅
	move.w	BIOS_GRAPHIC_RIGHT.w,d0
	addq.w	#1,d0
	move.w	BIOS_CONSOLE_RIGHT.w,d1
	addq.w	#1,d1
	lsl.w	#3,d1
	if	<cmp.w d1,d0>,lo
		move.w	d1,d0
	endif
	move.w	d0,(screen_width)r
;画面の高さ
	moveq.l	#0,d0
	move.w	BIOS_GRAPHIC_BOTTOM.w,d0
	addq.l	#1,d0
	moveq.l	#0,d1
	move.w	BIOS_CONSOLE_BOTTOM.w,d1
	addq.w	#1,d1
	lsl.w	#4,d1
	if	<cmp.l d1,d0>,lo
		move.l	d1,d0
	endif
	move.w	d0,(screen_height)r
;スプライト画面の高さ
	move.w	(screen_height)r,(sprite_height)r
	move.b	(screen_mode)r,d0
	if	<cmp.b #44,d0>,hs
		ifor	<cmp.b #47,d0>,ls,<cmp.b #60,d0>,eq,<cmp.b #73,d0>,eq	;44/45/46/47/60/73
			lsl.w	(sprite_height)r	;画面モード44~47はスプライト画面の高さを2倍にする
		endif
	endif
;実画面サイズ
	move.l	BIOS_GRAPHIC_Y_OFFSET.w,d0
	lsr.l	#1,d0
	move.w	d0,(real_size)r
;グラフィック色数
	moveq.l	#0,d0
	move.w	BIOS_GRAPHIC_PALETS.w,d0
	addq.l	#1,d0
	move.l	d0,(palets)r

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

;テキスト画面を描く
;パレットを設定する
	moveq.l	#3,d1			;パレットコード
	move.w	(text_color)r,d2	;カラーコード
	IOCS	_TPALET
;画面モードを表示する
	lea.l	(string_buffer)r,a0
	movestr	'CRTMOD(',a1
	bsr	strcpy
	moveq.l	#0,d0
	move.b	(screen_mode)r,d0
	bsr	utos
	if	<tst.b (crtlcd_mode)r>,eq
		movestr	') CRT',a1
	else
		movestr	') LCD',a1
	endif
	bsr	strcpy
	moveq.l	#3,d1			;パレットコード
	moveq.l	#2,d2			;X座標
	moveq.l	#TEXT_LINE-2,d3		;Y座標
	lea.l	(string_buffer)r,a1	;文字列
	move.l	a0,d4
	sub.l	a1,d4
	subq.w	#1,d4			;桁数-1
	IOCS	_B_PUTMES
;画面サイズを表示する
	lea.l	(string_buffer)r,a0
	moveq.l	#0,d0
	move.w	(screen_width)r,d0
	bsr	utos
	move.b	#'x',(a0)+
	moveq.l	#0,d0
	move.w	(screen_height)r,d0
	bsr	utos
	move.b	#'/',(a0)+
	moveq.l	#0,d0
	move.w	(real_size)r,d0
	bsr	utos
	move.b	#'x',(a0)+
	moveq.l	#0,d0
	move.w	(real_size)r,d0
	bsr	utos
	move.b	#' ',(a0)+
	move.l	(palets)r,d0
	bsr	utos
	move.b	#' ',(a0)+
	moveq.l	#0,d0
	move.b	(pages)r,d0
	bsr	utos
	moveq.l	#3,d1			;パレットコード
	moveq.l	#2,d2			;X座標
	moveq.l	#TEXT_LINE-1,d3		;Y座標
	lea.l	(string_buffer)r,a1	;文字列
	move.l	a0,d4
	sub.l	a1,d4
	subq.w	#1,d4			;桁数-1
	IOCS	_B_PUTMES
;TEXTと書く
	moveq.l	#3,d1			;パレットコード
	moveq.l	#2,d2			;X座標
	moveq.l	#TEXT_LINE,d3		;Y座標
	moveq.l	#8-1,d4			;桁数-1
	movestr	'TEXT',a1		;文字列
	IOCS	_B_PUTMES

;グラフィック画面を描く
;パレットを設定する
	if	<cmp.l #65536,(palets)r>,lo
		moveq.l	#0,d1			;パレットコード0
		moveq.l	#0,d2			;カラーコード
		IOCS	_GPALET
		lea.l	(graphic_color)r,a0
		moveq.l	#1,d3
		do
			move.w	d3,d1			;パレットコード1~4
			move.w	(a0)+,d2		;カラーコード
			IOCS	_GPALET
			addq.w	#1,d3
		while	<cmp.w #4,d3>,ls
	endif
;枠を描く
	move.w	#$F0F0,-(sp)		;ラインスタイル
	moveq.l	#1,d0
	if	<cmp.l #65536,(palets)r>,eq
		move.w	(graphic_color)r,d0
	endif
	move.w	d0,-(sp)		;パレットコード
	move.w	(screen_height)r,d0
	subq.w	#1,d0
	move.w	d0,-(sp)		;終点Y座標
	move.w	(screen_width)r,d0
	subq.w	#1,d0
	move.w	d0,-(sp)		;終点X座標
	clr.w	-(sp)			;始点Y座標
	clr.w	-(sp)			;始点X座標
	moveq.l	#2-1,d1			;外側,内側
	for	d1
		movea.l	sp,a1
		IOCS	_BOX
		addq.w	#4,(sp)			;始点X座標
		addq.w	#4,2(sp)		;始点Y座標
		subq.w	#4,4(sp)		;終点X座標
		subq.w	#4,6(sp)		;終点Y座標
	next
	lea.l	12(sp),sp
;GRAPHIC PAGE 0/1/2/3と書く
	moveq.l	#0,d5			;ページ番号 0,1,2,3
	do
	;文字列を作る
		lea.l	(string_buffer)r,a0
		movestr	'GRAPHIC PAGE ',a1
		bsr	strcpy
		move.w	#'0',d0
		add.w	d5,d0
		rol.w	#8,d0
		move.b	d0,(a0)+
		rol.w	#8,d0
		move.b	d0,(a0)+
		clr.b	d0
	;ページを選択する
		move.l	d5,d1
		IOCS	_APAGE
	;描く
		move.w	#1<<8|0,-(sp)		;サイズ 1 角度 0
		moveq.l	#1,d0
		add.w	d5,d0
		if	<cmp.l #65536,(palets)r>,eq
			move.w	d5,d0
			lea.l	(graphic_color)r,a0
			add.w	d0,d0
			move.w	(a0,d0.w),d0
		endif
		move.w	d0,-(sp)		;パレットコード
		move.w	#1<<8|1,-(sp)		;X方向の倍率 1 Y方向の倍率 1
		pea.l	(string_buffer)r	;文字列
		moveq.l	#GRAPHIC_LINE,d0
		add.w	d5,d0
		lsl.w	#4,d0
		move.w	d0,-(sp)		;Y座標
		move.w	#8*2,-(sp)		;X座標
		movea.l	sp,a1
		IOCS	_SYMBOL
		lea.l	14(sp),sp
		addq.w	#1,d5
	while	<cmp.b (pages)r,d5>,lo

;スプライト画面を描く
;	パターン
;		1	四隅のスプライト
;		2	BG0の枠
;		3	BG1の枠
;		4~23	文字
;	スプライト
;		0~3	四隅のスプライト
;		4~9	SPRITEの文字
;	パレットブロック
;		1	四隅のスプライト、SPRITEの文字
;		2	BG0の枠
;		3	BG1の枠
	do
		break	<tst.b (sprite_exists)r>,eq	;スプライト画面を使用できない
	;初期化する
		moveq.l	#0,d1			;バンクは使用しない
		IOCS	_SP_INIT
		break	<tst.l d0>,mi		;スプライト画面を使用できるが%1xx1xでsprdrv.xが組み込まれていない
		IOCS	_SP_ON
	;パレットを設定する
		lea.l	(sprite_color)r,a0
		moveq.l	#1,d4			;パレットブロック 1,2,3
		do
			moveq.l	#0,d1			;パレットコード 0
			move.l	d4,d2			;パレットブロック 1,2,3
			moveq.l	#0,d3			;カラーコード 0
			IOCS	_SPALET
			moveq.l	#1,d1			;パレットコード 1
			move.l	d4,d2			;パレットブロック 1,2,3
			move.w	(a0)+,d3		;カラーコード
			IOCS	_SPALET
			addq.w	#1,d4
		while	<cmp.w #3,d4>,ls
	;パターンを定義する
		moveq.l	#1,d1			;パターン番号 1~3
		moveq.l	#1,d2			;サイズ 16x16
		lea.l	(pattern_data)r,a1	;パターンデータ
		do
			IOCS	_SP_DEFCG		;パターンを定義する
			addq.w	#1,d1
			lea.l	128(a1),a1
		while	<cmp.w #3,d1>,ls	;次のパターン番号
	;文字のパターンを定義する
	;		  4 5 6 7 8 910111213141516171819202122
		movestr	'SPRITEBACKGROUND 01',a4
		moveq.l	#4,d6			;パターン番号 4~23
		dostart
			lsl.w	#8,d1
			move.b	(a4)+,d1		;文字コード下位
			moveq.l	#8,d2			;サイズ 16x16
			lea.l	(font_buffer)r,a1	;フォントバッファ
			IOCS	_FNTGET			;フォントデータを取り出す
			lea.l	(pattern_buffer)r,a0	;パターンバッファ
			moveq.l	#0,d7			;0固定
			moveq.l	#-2,d5			;-2=左半分,-1=右半分
			do
				lea.l	(font_buffer+4)r,a1	;フォントデータの本体
				moveq.l	#16-1,d3		;縦16ドット
				for	d3
				;	moveq.l	#0,d0
					move.b	2(a1,d5.w),d1		;左半分または右半分
					moveq.l	#8-1,d2			;横8ドット
					for	d2
						lsl.l	#4,d0			;0を0000に、1を0001にする
						add.b	d1,d1			;d1.bの上位から押し出して
						addx.b	d7,d0			;d0.lの下位へ押し込む
					next
					move.l	d0,(a0)+		;パターンデータ
					addq.l	#2,a1
				next
				addq.w	#1,d5
			while	ne
			move.w	d6,d1			;パターン番号 4~23
			moveq.l	#1,d2			;サイズ 16x16
			lea.l	(pattern_buffer)r,a1	;パターンデータ
			IOCS	_SP_DEFCG		;パターンを定義する
			addq.w	#1,d6			;次のパターン番号
		start
			moveq.l	#0,d1
			move.b	(a4)+,d1		;文字コード上位
		while	ne
	;四隅のスプライトを表示する
		moveq.l	#0,d6			;位置=スプライト番号 0=左上,1=右上,2=左下,3=右下
		do
			move.l	d6,d1			;スプライト番号 0~3
			moveq.l	#16,d2			;X座標左端
			if	<btst.l #0,d6>,ne
				move.w	(screen_width)r,d2	;X座標右端
			endif
			moveq.l	#16,d3			;Y座標上端
			if	<btst.l #1,d6>,ne
				move.w	(sprite_height)r,d3	;Y座標下端
			endif
			move.w	#1<<8|1,d4		;パレットブロック 1 パターン番号 1
			moveq.l	#3,d5			;プライオリティ 3
			IOCS	_SP_REGST
			addq.w	#1,d6			;次の位置=次のスプライト番号
		while	<cmp.w #3,d6>,ls
	;SPRITEと書く
		moveq.l	#16+16*1,d2
		movea.l	d2,a2			;X座標
		moveq.l	#SPRITE_LINE,d3
		move.w	(screen_height)r,d0
		if	<cmp.w (sprite_height)r,d0>,ne
			add.w	d3,d3
		endif
		lsl.w	#4,d3
		add.w	#16,d3
		movea.l	d3,a3			;Y座標
	;		 S P R I T E
		movestr	<4,5,6,7,8,9>,a4	;パターン番号
		moveq.l	#4,d7			;スプライト番号
		dostart
			move.l	d7,d1			;スプライト番号 4~9
			move.w	a2,d2			;X座標
			move.w	a3,d3			;Y座標
			move.w	#1<<8,d4		;パレットブロック 1
			move.b	d0,d4			;パターン番号
			moveq.l	#3,d5			;プライオリティ 3
			IOCS	_SP_REGST
			addq.w	#1,d7			;次のスプライト番号
			adda.w	#16,a2			;次のX座標
		start
			moveq.l	#0,d0
			move.b	(a4)+,d0		;パターン番号
		while	ne
	;BGを描く
		if	<tst.b (bg_size)r>,eq	;8x8/512x512x2
			moveq.l	#0,d5			;BGテキストエリア 0~1
			do
			;枠のパターンで塗り潰す
				move.l	d5,d1			;BGテキストエリア 0~1
				move.l	d5,d2
				addq.b	#2,d2			;パレットブロック 2~3
				lsl.w	#8,d2
				move.b	d5,d2
				addq.b	#2,d2			;16x16パターン番号 2~3
				lsl.b	#2,d2			;8x8パターン番号
				IOCS	_BGTEXTCL
			;枠を残して内側をくり抜く
				move.l	d5,d1			;BGテキストエリア 0~1
				moveq.l	#0<<8|0,d4		;パレットブロック 0 パターン番号 0
				moveq.l	#1,d3			;BGテキストY座標。枠の1個
				move.w	(sprite_height)r,d7
				lsr.w	#3,d7			;8x8が縦に並ぶ数
				subq.w	#2+1,d7			;枠の2個
				for	d7			;縦
					moveq.l	#1,d2			;BGテキストX座標。枠の1個
					move.w	(screen_width)r,d6
					lsr.w	#3,d6			;8x8が横に並ぶ数
					subq.w	#2+1,d6			;枠の2個
					for	d6			;横
						IOCS	_BGTEXTST
						addq.w	#1,d2			;次のBGテキストX座標
					next
					addq.w	#1,d3			;次のBGテキストY座標
				next
			;BACK-GROUND 0/1と書く
				moveq.l	#2*1,d2
				movea.l	d2,a2			;X座標
				moveq.l	#BG_LINE,d3
				add.w	d5,d3
				move.w	(screen_height)r,d0
				if	<cmp.w (sprite_height)r,d0>,ne
					add.w	d3,d3
				endif
				add.w	d3,d3
				movea.l	d3,a3			;Y座標
			;		  B  A  C  K  G  R  O  U  N  D     0
				movestr	<10,11,12,13,14,15,16,17,18,19,20,21>,a4	;パターン番号
				dostart
					move.l	d5,d4
					addq.b	#2,d4			;パレットブロック 2~3
					lsl.w	#8,d4
					if	<cmp.b #21,d0>,eq	;0/1
						add.b	d5,d0			;21(0)→22(1)
					endif
					move.b	d0,d4			;16x16パターン番号
					lsl.b	#2,d4			;8x8パターン番号
					moveq.l	#4-1,d6			;左上,左下,右上,右下
					for	d6
						move.l	d5,d1			;BGテキストエリア 0~1
						moveq.l	#2,d2
						and.b	d4,d2
						lsr.w	#1,d2
						add.w	a2,d2			;BGテキストX座標
						moveq.l	#1,d3
						and.b	d4,d3
						add.w	a3,d3			;BGテキストY座標
						IOCS	_BGTEXTST
						addq.b	#1,d4			;次の8x8パターン番号
					next
					addq.w	#2,a2			;BGテキストX座標
				start
					moveq.l	#0,d0
					move.b	(a4)+,d0		;パターン番号
				while	ne
			;表示ON
				move.l	d5,d1			;BGページ 0~1
				move.l	d5,d2			;BGテキストエリア 0~1
				moveq.l	#1,d3			;表示ON
				IOCS	_BGCTRLST
			;
				addq.w	#1,d5			;次のBGテキストエリア
			while	<cmp.w #1,d5>,ls
		else				;16x16/1024x1024x2 拡張対応
			moveq.l	#0,d5			;BGテキストエリア 0~1
			do
			;枠のパターンで塗り潰す
				move.l	d5,d1			;BGテキストエリア 0~1
				move.l	d5,d2
				addq.b	#2,d2			;パレットブロック 2~3
				lsl.w	#8,d2
				move.b	d5,d2
				addq.b	#2,d2			;16x16パターン番号 2~3
				IOCS	_BGTEXTCL
			;枠を残して内側をくり抜く
				move.l	d5,d1			;BGテキストエリア 0~1
				moveq.l	#0<<8|0,d4		;パレットブロック 0 パターン番号 0
				moveq.l	#1,d3			;BGテキストY座標。枠の1個
				move.w	(sprite_height)r,d7
				lsr.w	#4,d7			;16x16が縦に並ぶ数
				subq.w	#2+1,d7			;枠の2個
				for	d7			;縦
					moveq.l	#1,d2			;BGテキストX座標。枠の1個
					move.w	(screen_width)r,d6
					lsr.w	#4,d6			;16x16が横に並ぶ数
					subq.w	#2+1,d6			;枠の2個
					for	d6			;横
						IOCS	_BGTEXTST
						addq.w	#1,d2			;次のBGテキストX座標
					next
					addq.w	#1,d3			;次のBGテキストY座標
				next
			;BACK-GROUND 0/1と書く
				moveq.l	#1*1,d2
				movea.l	d2,a2			;X座標
				moveq.l	#BG_LINE,d3
				add.w	d5,d3
				move.w	(screen_height)r,d0
				if	<cmp.w (sprite_height)r,d0>,ne
					add.w	d3,d3
				endif
				movea.l	d3,a3			;Y座標
			;		  B  A  C  K  G  R  O  U  N  D     0
				movestr	<10,11,12,13,14,15,16,17,18,19,20,21>,a4	;パターン番号
				dostart
					move.l	d5,d4
					addq.b	#2,d4			;パレットブロック 2~3
					lsl.w	#8,d4
					if	<cmp.b #21,d0>,eq	;0/1
						add.b	d5,d0			;21(0)→22(1)
					endif
					move.b	d0,d4			;16x16パターン番号
					move.l	d5,d1			;BGテキストエリア 0~1
					move.w	a2,d2			;BGテキストX座標
					move.w	a3,d3			;BGテキストY座標
					IOCS	_BGTEXTST
					addq.w	#1,a2			;BGテキストX座標
				start
					moveq.l	#0,d0
					move.b	(a4)+,d0		;パターン番号
				while	ne
			;表示ON
				move.l	d5,d1			;BGページ 0~1
				move.l	d5,d2			;BGテキストエリア 0~1
				moveq.l	#1,d3			;表示ON
				IOCS	_BGCTRLST
			;
				addq.w	#1,d5			;次のBGテキストエリア
			while	<cmp.w #1,d5>,ls
		endif
	while	f

;キー入力を待ってから画面モードを復元する
	IOCS	_B_CUROFF
	DOS	_GETC
	if	<cmp.b #27,d0>,eq	;ESCキーが押されたとき
	;スプライト画面とグラフィック画面をOFFにする
		moveq.l	#$0020,d1
		IOCS	_CRTMOD2
	;テキスト画面を消去する
		moveq.l	#2,d1
		IOCS	_B_CLR_ST
	;テキストパレットを復元する
		moveq.l	#3,d1
		moveq.l	#-2,d2
		IOCS	_TPALET
	else				;ESCキー以外が押されたとき
	;CRTorLCDモードを復元する
		if	<tst.b (save_to_sram)r>,eq	;CRTorLCDモードをSRAMに保存しない
			if	<tst.b (saved_crtlcd)r>,eq	;CRT向けだった
				move.w	#$43FF,d1
			else				;LCD向けだった
				move.w	#$4CFF,d1
			endif
			IOCS	_CRTMOD			;CRTorLCDモードを復元する
		endif
	;OSの画面モードを復元する
		move.l	#(16<<16)|$FFFF,-(sp)
		DOS	_CONCTRL
		move.w	d0,2(sp)
		DOS	_CONCTRL
		addq.l	#4,sp
	endif
	IOCS	_B_CURON

;終了する
exit:
	DOS	_EXIT

;タイトルと使用法を表示して終了する
usage_exit:
	lea.l	title_usage(pc),a0
	bsr	more
	goto	exit

;タイトルと使用法
title_usage:
	.dc.b	TITLE_STRING,13,10
	.dc.b	13,10
	.dc.b	'説明',13,10
	.dc.b	'  crtmodtest.xはCRTMODの実装とモニタの性能を確認するための画面を表示します。',13,10
	.dc.b	'  ESCキーを押すと画面モードを変更したまま終了、他のキーを押すと元に戻して終了します。',13,10
	.dc.b	13,10
	.dc.b	'オプション',13,10
	.dc.b	'  -l 0~1    0でCRT向けの同期周波数、1でLCD向けの同期周波数を選択します。',13,10
	.dc.b	'  -m 0~73   画面モードを選択します。',13,10
	.dc.b	'  -s         -lの選択をSRAMに保存します。',13,10
	.dc.b	13,10
	.dc.b	'画面モードの一覧',13,10
	.dc.b	'  ┌────┬─────┬────┬───┬─────────┬─────────┐',13,10
	.dc.b	'  │  画面  │  実画面  │色数    │ 画面 │      CRT向け     │      LCD向け     │',13,10
	.dc.b	'  │ サイズ │  サイズ  │ページ数│モード│水平同期  垂直同期│水平同期  垂直同期│',13,10
	.dc.b	'  ├────┼─────┼────┼───┼─────────┼─────────┤',13,10
	.dc.b	'  │ 256x256│  512x512 │   16  4│   6  │31.500kHz 55.458Hz│34.500kHz 55.200Hz│',13,10
	.dc.b	'  │        │    〃    │  256  2│  10  │   ラスタ2度読み  │   ラスタ2度読み  │',13,10
	.dc.b	'  │        │    〃    │65536  1│  14  │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│   2  │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  50* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  63* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┼─────────┼─────────┤',13,10
	.dc.b	'  │ 256x256│  512x512 │   16  4│  37* │31.963kHz 56.273Hz│31.963kHz 51.141Hz│',13,10
	.dc.b	'  │ 正方形 │    〃    │  256  2│  38* │   ラスタ2度読み  │   ラスタ2度読み  │',13,10
	.dc.b	'  │        │    〃    │65536  1│  39* │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│  36* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  58* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  71* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┤                  │                  │',13,10
	.dc.b	'  │ 384x256│  512x512 │   16  4│  29* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256  2│  30* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536  1│  31* │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│  28* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  56* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  69* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┼─────────┼─────────┤',13,10
	.dc.b	'  │ 512x256│  512x512 │   16  4│  41* │31.500kHz 55.458Hz│35.341kHz 56.546Hz│',13,10
	.dc.b	'  │        │    〃    │  256  2│  42* │   ラスタ2度読み  │   ラスタ2度読み  │',13,10
	.dc.b	'  │        │    〃    │65536  1│  43* │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│  40* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  59* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  72* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┤                  │                  │',13,10
	.dc.b	'  │ 512x256│  512x512 │   16  4│  45* │                  │                  │',13,10
	.dc.b	'  │SP:     │    〃    │  256  2│  46* │                  │                  │',13,10
	.dc.b	'  │ 512x512│    〃    │65536  1│  47* │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│  44* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  60* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  73* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┼─────────┼─────────┤',13,10
	.dc.b	'  │ 512x512│  512x512 │   16  4│   4  │31.500kHz 55.458Hz│35.341kHz 56.546Hz│',13,10
	.dc.b	'  │        │    〃    │  256  2│   8  │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536  1│  12  │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│   0  │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  48* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  61* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┤                  ├─────────┤',13,10
	.dc.b	'  │ 512x512│  512x512 │   16  4│  33* │                  │35.056kHz 56.090Hz│',13,10
	.dc.b	'  │ 正方形 │    〃    │  256  2│  34* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536  1│  35* │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│  32* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  57* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  70* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┤                  │                  │',13,10
	.dc.b	'  │ 768x512│  512x512 │  256  2│  20  │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536  1│  24  │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│  16  │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  52* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  65* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┤                  ├─────────┤',13,10
	.dc.b	'  │ 640x480│  512x512 │  256  2│  23  │                  │31.469kHz 59.940Hz│',13,10
	.dc.b	'  │        │    〃    │65536  1│  27  │                  │        VGA       │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│  19  │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  55* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  68* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┼─────────┼─────────┤',13,10
	.dc.b	'  │ 256x240│  512x512 │   16  4│   7  │15.980kHz 61.463Hz│34.500kHz 55.200Hz│',13,10
	.dc.b	'  │        │    〃    │  256  2│  11  │                  │   ラスタ2度読み  │',13,10
	.dc.b	'  │        │    〃    │65536  1│  15  │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│   3  │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  51* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  64* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┼─────────┼─────────┤',13,10
	.dc.b	'  │ 512x480│  512x512 │   16  4│   5  │15.980kHz 61.463Hz│35.341kHz 56.546Hz│',13,10
	.dc.b	'  │        │    〃    │  256  2│   9  │  インターレース  │                  │',13,10
	.dc.b	'  │        │    〃    │65536  1│  13  │                  │                  │',13,10
	.dc.b	'  │        │ 1024x1024│   16  1│   1  │                  │                  │',13,10
	.dc.b	'  │        │    〃    │  256* 1│  49* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  62* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┼─────────┼─────────┤',13,10
	.dc.b	'  │CRT:    │  512x512 │  256  2│  21  │24.699kHz 53.116Hz│35.056kHz 56.090Hz│',13,10
	.dc.b	'  │1024x424│    〃    │65536  1│  25  │                  │                  │',13,10
	.dc.b	'  │LCD:    │ 1024x1024│   16  1│  17  │                  │                  │',13,10
	.dc.b	'  │ 768x600│    〃    │  256* 1│  53* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  66* │                  │                  │',13,10
	.dc.b	'  ├────┼─────┼────┼───┼─────────┼─────────┤',13,10
	.dc.b	'  │CRT:    │  512x512 │  256  2│  22  │24.699kHz 53.116Hz│35.056kHz 56.090Hz│',13,10
	.dc.b	'  │1024x848│    〃    │65536  1│  26  │  インターレース  │  インターレース  │',13,10
	.dc.b	'  │LCD:    │ 1024x1024│   16  1│  18  │                  │                  │',13,10
	.dc.b	'  │768x1024│    〃    │  256* 1│  54* │                  │                  │',13,10
	.dc.b	'  │        │    〃    │65536* 1│  67* │                  │                  │',13,10
	.dc.b	'  └────┴─────┴────┴───┴─────────┴─────────┘',13,10
	.dc.b	0
	.even

;色
text_color:	dchsv	0,24,31
graphic_color:	dchsv	24,24,31
		dchsv	48,24,31
		dchsv	72,24,31
		dchsv	96,24,31
sprite_color:	dchsv	120,24,31
		dchsv	144,24,31
		dchsv	168,24,31

;パターンデータ
pattern_data:
	.dc.l	$00001111		;1 四隅のスプライト
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$11110000

	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$00001111
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$11110000
	.dc.l	$11110000

	.dc.l	$00110011		;2 BG0の枠
	.dc.l	$00110011
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$00110011
	.dc.l	$00110011
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$00110011
	.dc.l	$00110011
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$00110011
	.dc.l	$00110011
	.dc.l	$00000000
	.dc.l	$00000000

	.dc.l	$00110011
	.dc.l	$00110011
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$00110011
	.dc.l	$00110011
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$00110011
	.dc.l	$00110011
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$00110011
	.dc.l	$00110011
	.dc.l	$00000000
	.dc.l	$00000000

	.dc.l	$00000000		;3 BG1の枠
	.dc.l	$00000000
	.dc.l	$11001100
	.dc.l	$11001100
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$11001100
	.dc.l	$11001100
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$11001100
	.dc.l	$11001100
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$11001100
	.dc.l	$11001100

	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$11001100
	.dc.l	$11001100
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$11001100
	.dc.l	$11001100
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$11001100
	.dc.l	$11001100
	.dc.l	$00000000
	.dc.l	$00000000
	.dc.l	$11001100
	.dc.l	$11001100

	.bss

save_to_sram:	.ds.b	1		;CRTorLCDモードをSRAMに保存するか。0=しない,-1=する
saved_crtlcd:	.ds.b	1		;元の画面モード
screen_mode:	.ds.b	1		;画面モード
crtlcd_mode:	.ds.b	1		;CRTorLCDモード。0=CRT向け,-1=LCD向け
pages:		.ds.b	1		;グラフィックページ数
bg_size:	.ds.b	1		;BGサイズ。0=8x8/512x512x2,-1=16x16/1024x1024x1
sprite_exists:	.ds.b	1		;スプライト画面の有無。0=なし,-1=あり
	.even
screen_width:	.ds.w	1		;画面の幅
screen_height:	.ds.w	1		;画面の高さ
sprite_height:	.ds.w	1		;スプライト画面の高さ
real_size:	.ds.w	1		;実画面サイズ
palets:		.ds.l	1		;グラフィック色数
font_buffer:	.ds.w	2+2+3*24	;フォントバッファ
pattern_buffer:	.ds.l	8*4		;スプライトパターンバッファ
string_buffer:	.ds.b	256		;文字列バッファ

	.text



;----------------------------------------------------------------
;-more-を挟みながら文字列を表示する
;<a0.l:文字列
more::
	push	d0-d5/a0-a2
;標準入力を確認する
	clr.l	-(sp)			;(0<<16)|0
	DOS	_IOCTRL
	addq.l	#4,sp
;<d0.b:標準入力のFCBフラグ
	and.b	#$81,d0			;キャラクタデバイス、標準入力
	goto	<cmp.b #$81,d0>,ne,90f	;標準入力がリダイレクトされている。moreしない
;標準出力を確認する
	pea.l	1.w			;(0<<16)|1
	DOS	_IOCTRL
	addq.l	#4,sp
;<d0.b:標準出力のFCBフラグ
	and.b	#$82,d0			;キャラクタデバイス、標準出力
	goto	<cmp.b #$82,d0>,ne,90f	;標準出力がリダイレクトされている。moreしない
;CONDRV.SYSを確認する
	move.w	#$0100+_KEY_INIT,-(sp)
	DOS	_INTVCG
	addq.l	#2,sp
	movea.l	d0,a1
	subq.l	#4,a1
	IOCS	_B_LPEEK
	goto	<cmp.l #'hmk*',d0>,eq,90f	;CONDRV.SYSが組み込まれている。moreしない
;画面の大きさを確認する
	moveq.l	#-1,d1
	moveq.l	#-1,d2
	IOCS	_B_CONSOL
;<d2.l:右端の桁座標<<16|下端の行座標
	move.w	d2,d3
	swap.w	d2
	addq.w	#1,d2
;<d2.w:画面の桁数
;<d3.w:下端の行座標。-more-の行を除いた画面の行数
	gotoor	<cmp.w #8,d2>,lo,<tst.w d3>,eq,90f	;画面が狭すぎる。moreしない。タブを含めて1文字以上書けなければならないので8桁x1行が下限
;ページループ
	do
		move.l	#0,d4			;桁座標
		move.l	#0,d5			;行座標
		movea.l	a0,a2			;ページ先頭
	;文字ループ
		do
			movea.l	a0,a1			;文字先頭
			move.b	(a0)+,d0		;1バイト目
			if	eq			;00 終了
				subq.l	#1,a0
				break
			elif	<cmp.b #$09,d0>,eq	;09 タブ
				moveq.l	#7,d1
				and.w	d4,d1
				subq.w	#8,d1
				neg.w	d1		;タブの桁数
			elif	<cmp.b #$0A,d0>,eq	;0A 改行
				moveq.l	#0,d4		;左端へ
				addq.w	#1,d5		;次の行へ
				break	<cmp.w d3,d5>,eq	;下端。ページ終わり
				continue
			elif	<cmp.b #$0C,d0>,eq	;0C 改ページ
				break
			elif	<cmp.b #$1F,d0>,ls	;01-08,0B,0D-1F 無視する
				continue
			else				;20-FF
				do
					moveq.l	#1,d1			;半角の桁数
					break	<tst.b d0>,pl		;20-7F アスキー
					breakand	<cmp.b #$A0,d0>,hs,<cmp.b #$DF,d0>,ls	;A0-DF 半角カタカナ
					addq.l	#1,a0			;2バイト目
					break	<cmp.b #$80,d0>,eq	;8000-80FF 半角ひらがな
					break	<cmp.b #$F0,d0>,hs	;F000-FFFF 1/4角、半角外字
					moveq.l	#2,d1			;全角の桁数
				while	f
			endif
			add.w	d1,d4			;表示した後の桁座標
			if	<cmp.w d2,d4>,hi	;はみ出す
				sub.w	d1,d4			;進み過ぎた分戻る
				movea.l	a1,a0
				addq.w	#1,d5			;次の行へ
				break	<cmp.w d3,d5>,eq	;下端。ページ終わり
				moveq.l	#0,d4			;左端へ
			endif
		while	t
	;1ページ表示する
		move.l	a0,d0			;末尾
		sub.l	a2,d0			;末尾-先頭=長さ
		move.l	d0,-(sp)		;長さ
		move.l	a2,-(sp)		;先頭
		move.w	#1,-(sp)		;標準出力
		DOS	_WRITE
		lea.l	10(sp),sp
	;続きがなければ終了する
		break	<tst.b (a0)>,eq
	;必要ならば改行する
		ifand	<tst.w d4>,ne,<cmp.w d2,d4>,ne	;左端でも右端でもない
			bsr	printcrlf
		endif
	;-more-を表示する
		pea.l	6.w
		pea.l	100f(pc)		;'-more-'
		move.w	#1,-(sp)
		DOS	_WRITE
		lea.l	10(sp),sp
	;キー入力を待つ
		DOS	_GETC
		move.l	d0,d1
	;改行する
		bsr	printcrlf
	whileand	<cmp.b #$1B,d1>,ne,<cmp.b #'Q',d1>,ne,<cmp.b #'q',d1>,ne	;ESCまたはQが押されたときは終了する
99:	pop
	rts

;moreしない
90:	bsr	print
	goto	99b

100:	.dc.b	'-more-'
	.even

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

;----------------------------------------------------------------
;文字列を表示する
;<a0.l:文字列
print::
	push	d0
	bsr	strlen
	move.l	d0,-(sp)
	move.l	a0,-(sp)
	move.w	#1,-(sp)
	DOS	_WRITE
	lea.l	(10,sp),sp
	pop
	rts

;----------------------------------------------------------------
;改行を表示する
printcrlf::
	move.l	a0,-(sp)
	lea.l	100f(pc),a0		;13,10
	bsr	print
	movea.l	(sp)+,a0
	rts

100:	.dc.b	13,10,0
	.even

;----------------------------------------------------------------
;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

;----------------------------------------------------------------
;文字列をコピーする
;<a0.l:コピー先
;<a1.l:コピー元
;>a0.l:コピー先の0の位置
;>a1.l:コピー元の0の次の位置
strcpy::
	do
		move.b	(a1)+,(a0)+
	while	ne			;0でなければ繰り返す
	subq.l	#1,a0			;進み過ぎた分戻る
	rts

;----------------------------------------------------------------
;文字列の長さを数える
;<a0.l:文字列
;>d0.l:長さ
strlen::
	move.l	a0,d0			;d0=先頭
	do
		tst.b (a0)+
	while	ne			;0でなければ繰り返す
	subq.l	#1,a0			;進み過ぎた分戻る。a0=末尾
	exg.l	d0,a0			;d0=末尾,a0=先頭
	sub.l	a0,d0			;d0=末尾-先頭=長さ
	rts

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

;----------------------------------------------------------------
;32ビット符号なし整数を10進数の文字列に変換する
;<d0.l:符号なし整数
;<a0.l:バッファ。10進数の文字列の先頭
;>a0.l:10進数の文字列の末尾の0の位置
utos::
	if	<tst.l d0>,eq		;0
		move.b	#'0',(a0)+
	else				;0以外
		push	d0-d2/a1
		lea.l	utos_table(pc),a1
		do
			move.l	(a1)+,d1
		while	<cmp.l d1,d0>,lo	;引けるところまで進む。ゼロサプレス
		do
			moveq.l	#'0'-1,d2
			do
				addq.b	#1,d2
				sub.l	d1,d0
			while	hs			;引ける回数を数える
			move.b	d2,(a0)+
			add.l	d1,d0			;引き過ぎた分を加え戻す
			move.l	(a1)+,d1
		while	ne
		pop
	endif
	clr.b	(a0)
	rts

utos_table::
	.dc.l	1000000000
	.dc.l	100000000
	.dc.l	10000000
	.dc.l	1000000
	.dc.l	100000
	.dc.l	10000
	.dc.l	1000
	.dc.l	100
	.dc.l	10
	.dc.l	1
	.dc.l	0



	.end