misc/crtmodtest.s- Source code ソースコード - XEiJ - STUDIO KAMADA
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	'ＴＥＸＴ',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	'ＧＲＡＰＨＩＣ　ＰＡＧＥ　',a1
    		bsr	strcpy
    		move.w	#'０',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	'ＳＰＲＩＴＥＢＡＣＫＧＲＯＵＮＤ　０１',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

STUDIO KAMADA
Copyright © 1999-2026 Makoto Kamada