COPYキーの活用

X68000をPC用モニタをつなぐのに、コネクタ変換ケーブルを自作して使っていますが、
本格的に実機を使おうと思った矢先、画面全体が映っていないという問題にぶつかりました。

具体的には、画面下の方のファンクションキーガイダンス表示が見えないという状態で、
モニターのボタンで表示位置を調整すれば、せりあがって見えるようになる、という状況です。

しかし、漢字変換するたびにいちいちモニタの調整などやってられませんので、
「COPYキーを押したらテキストのスクロール座標を64に設定する(トグル動作)」
のような手軽な調整手段が欲しいと思いました。

ちなみに、同じような問題をIOCSをフックしてCRTCの設定変更で解決するという、
768.x(LeDA様 http://www.asahi-net.or.jp/~YY8A-IMI/20040913/x68/prog/768.hed.htm)というのも試しましたが、
管理人が使っているiiyamaとI・O DATAのモニタでは、残念ながら映像が表示されませんでした。

プログラミングの方針

COPYキーを押すと、一般的な環境だと「プリンタがつながっていません」の白帯が出るとおもいます。
プリンタがつながっていれば標準で画面のハードコピーができたと思いますが、
今となっては使い道がありません。

そこでこの処理をフックして、テキスト画面のスクロール座標Y(CRTCレジスタ $E80016)を
書き換えるプログラムに置き換えようと思います。

INTERRUPT:
	movem.l	d0/a5-a6,-(sp)

	moveq.l	#16,d0
	lea	homeY(pc),a6
	move.w	(a6),d0
	eori.w	#64,d0
	move.l	#SCROLL_ADDR,a5
	move.w	d0,(a5)
	move.w	d0,(a6)

	movem.l	(sp)+,d0/a5-a6
	rte

homeY:	.dc.w	0

COPYキー割り込み(trap #12)の処理はこれだけなのですが、テキストエディタなど
他の作業中に使いたいというのが目的ですので、プログラムを「常駐しておく」ために、
いろいろと根回しが必要になります。

プログラムのしくみ

常駐するときにはINTVCSというDOSコールがありますので、それを使ってtrap#12をフックし、
KEEPPRでプログラムをメモリ上に常駐させた状態でcommand.xに復帰します。
これで、COPYキーを押すたびにY座標が切り替わってくれるようになりました。

常駐プログラムの作法として、実行時にオプションで「/r」を指定したら、
常駐を解除できるようにしないといけません。
試作したプログラムでも、コマンドラインの解析を行い、処理を分岐するようにしました。

常駐解除処理は、既にプログラムが常駐しているので書き換えられている trap #12のベクタをもとに、
(1)常駐プログラムのメモリ上に保存しておいた元々のベクタ(白帯処理)を参照し、
(2)それをINTVCSで復元してから、
(3)常駐プログラムのメモリを解放する、
という流れになっています。

さらに、ここで最初躓いたのですが、常駐プログラムをEXITしたときには、
親プロセス(通常、command.x)のプロセス管理ポインタ内に保存されているtrap #12のベクタの控えが
自動的に設定
されます。常駐解除しているプロセスの管理ポインタではありません。

このベクタの控えは、常駐解除プログラムを起動した時点のtrap#12ベクタの値、すなわち、
先ほど常駐解除してメモリ解放までしてしまった古いプログラムのアドレスになっています。
このままでは、EXIT後にベクタの値が無法地帯を指してしまいますので、
親プロセスの管理ポインタ(自分のプロセス管理ポインタの4バイト目にある)を参照し、 その内のtrap#12ベクタ控え値を書き換えてからEXITする、ということをする必要があるみたいです。

理屈から言って、POWER OFF割り込みやBREAKキー、CTRL+Cなどの割り込みをフックするときも
同じことを気を付ける必要がありそうです。

(参考)ソースコード

プログラミングのご参考に、作成したプログラムのソースを公開しておきます。
割り込みルーチンを書き換えれば、COPYキーを押したときにいろいろなことをさせられるので、
応用が利くと思います。

常駐解除の仕方がIOCSコールをフックしたときの方法と違うのに気付かなくて苦労しましたが、
無事解決しましたので、これにて完成とします。

お気づきの点などありましたら、最近、2ちゃんねる掲示板の こちらをチェックしていますので、
コメントいただけましたら幸いです。

	.include	doscall.mac
	* A0:メモリ管理ポインタ
	* A1:プログラムの最終アドレス+1
	* A2:コマンドライン
	* A3:環境変数
	* A4:プログラム実行先頭アドレス

VECTOR_NUMBER	equ	(32+12)		* trap #12 : COPY KEY
SCROLL_ADDR	equ	$E80016

	.text
	.even
PROGRAM_START:
old_vector_address:			* ここに、ベクタアドレスを求めておく
	bra.w	start

check_code:	.dc.b	'ADHM'		* 常駐判定用
*---- 割り込みルーチン ----
INTERRUPT:
	movem.l	d0/a5-a6,-(sp)

	moveq.l	#16,d0
	lea	homeY(pc),a6
	move.w	(a6),d0
	eori.w	#64,d0
	move.l	#SCROLL_ADDR,a5
	move.w	d0,(a5)
	move.w	d0,(a6)

	movem.l	(sp)+,d0/a5-a6
	rte

homeY:	.dc.w	0


KEEP_END:

title_message:	.dc.b	'COPYキーでテキストのy座標を切り替えるプログラム(2014年 甘亀庵謹製)',$d,$a,0
	.even
start:
	* タイトルメッセージを表示
	pea	title_message(pc)
	DOS	_PRINT
	addq.l	#4,sp

	* COPYキーの割り込みベクタを参照する
	move.w	#VECTOR_NUMBER,-(sp)
	DOS	_INTVCG
	addq.l	#2,sp
	lea	old_vector_address(pc),a5
	move.l	d0,(a5)

	* コマンドラインを確認する
	tst.b	(a2)+
	beq	Check_KEEP

	move.b	(a2)+,d0
	cmpi.b	#'-',d0
	beq	check_option
	cmpi.b	#'/',d0
	bne	print_usage

check_option:
	move.b	(a2)+,d0
	ori.b	#32,d0			* 強制的に小文字にする
	cmpi.b	#'r',d0
	beq	Check_RELEASE


	* 使い方を表示する
print_usage:
	pea	usage(pc)
	DOS	_PRINT
	addq.l	#4,sp
	DOS	_EXIT
usage:		.dc.b	'使用方法: adjusthome [/r]',$d,$a,0
	.even

*-------------------------------------------------

* これから常駐しようとするとき *
Check_KEEP:
	* ベクタの先が、常駐プログラムかどうか確認する
	bsr	CHECK_PROGRAM_KEEPING
	beq	ALREADY_KEEP_ERROR

	* 割り込みベクタを設定する
	pea	INTERRUPT(pc)
	move.w	#VECTOR_NUMBER,-(sp)
	DOS	_INTVCS
	addq.l	#6,sp

	* 常駐終了
	pea	keeped(pc)	* '常駐しました'
	DOS	_PRINT
	addq.l	#4,sp

	clr.w	-(sp)		* 終了コード
	move.l	#KEEP_END-PROGRAM_START,-(sp)
	DOS	_KEEPPR
keeped:		.dc.b	'常駐しました。COPYキーでホーム座標を調整できます。',$d,$a,0
	.even
*-------------------------------------------------

* 常駐を解除するとき *
Check_RELEASE:
	* ベクタの先が、常駐プログラムかどうか確認する
	bsr	CHECK_PROGRAM_KEEPING
	bne	NO_KEEPING_ERROR

	* 割り込みベクタを復元する
	move.l	old_vector_address(pc),a5		* a5:現在のCOPYキーのベクタ
	move.l	old_vector_address-INTERRUPT(a5),a1	* a1:常駐するときに控えてあったベクタ

	move.l	a1,-(sp)
	move.w	#VECTOR_NUMBER,-(sp)
	DOS	_INTVCS
	addq.l	#6,sp

	lea	PROGRAM_START-256(pc),a2	* プロセス管理ポインタ
	move.l	4(a2),a2			* 親プロセスのポインタ[★ここが肝心★]
	move.l	a1,$054(a2)			* $54:TRAP#12(COPYキー)

	* 常駐プログラムのメモリを解放する
	pea	-240-8(a5)
	DOS	_MFREE
	addq.l	#4,sp

	* 正常終了
	pea	released(pc)
	DOS	_PRINT		* '常駐解除しました'
	addq.l	#4,sp

	bsr	Wait	* 動作テスト。この時点でCOPYキーを押すと白帯が出れば正常。

	DOS	_EXIT
released:	.dc.b	'常駐解除しました。',$d,$a,0
	.even

*-------------------------------------------------

ALREADY_KEEP_ERROR:
	pea	keeping(pc)
	DOS	_PRINT			* 'すでに常駐しています'
	addq.l	#4,sp
	DOS	_EXIT
keeping:	.dc.b	'すでに常駐しています。-rで解除できます。',$d,$a,0
	.even

*-------------------------------------------------

NO_KEEPING_ERROR:
	pea	no_keeping(pc)
	DOS	_PRINT			* 'まだ常駐していません'
	addq.l	#4,sp
	DOS	_EXIT
no_keeping:	.dc.b	'まだ常駐していません。',$d,$a,0
	.even

*-------------------------------------------------

*--- 同じプログラムがすでに常駐しているか調べる --
* out	d0=0: 常駐している
CHECK_PROGRAM_KEEPING:
	clr.l	-(sp)		* スーパーバイザーモードにする
	DOS	_SUPER
	move.l	d0,(sp)

	move.l	#SCROLL_ADDR,a1		* ついでなので、スクロール座標をもとに戻しておく
	clr.w	(a1)
	
	move.l	old_vector_address(pc),a5	* a5:現在のCOPYキーのベクタ値
	move.l	check_code-INTERRUPT(a5),d1	* d1:常駐プログラム判定キー

	DOS	_SUPER		* ユーザモードに戻す
	addq.l	#4,sp

	* 常駐判定キーが一致するか調べる
	move.l	check_code(pc),d0
	sub.l	d1,d0
	rts

	.bss
	.even

トップページへ

Copyright©2014 甘亀庵管理人

inserted by FC2 system