misc/ppcon.s
;========================================================================================
; ppcon.s
; Copyright (C) 2003-2024 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 sram.equ
DEVICE_NAME reg 'CON '
TITLE_STRING reg 'Proportional-Pitch CONsole'
VERSION_STRING reg '0.11'
MAGIC_STRING reg 'PPCON011'
;----------------------------------------------------------------
;プログラムの先頭
.text
program_head:
;デバイスヘッダ
.dc.l -1 ;次のデバイスヘッダ。-1=デバイスヘッダのリストの末尾
.dc.w $8003 ;デバイスタイプ。キャラクタデバイス、標準出力、標準入力
.dc.l strategy_routine ;ストラテジルーチン
.dc.l interrupt_routine ;インタラプトルーチン
.dc.b DEVICE_NAME ;デバイス名
;----------------------------------------------------------------
;マジック
magic:
.dc.b MAGIC_STRING
;ベクタテーブル
vector_table:
;カーソル点滅処理ルーチン
.dc.w BIOS_TC_CURSOR_HANDLE ;オフセット
.dc.l timer_c_cursor ;新しいベクタ
.dc.l 0 ;古いベクタ
;_B_CURON
.dc.w 4*($100+_B_CURON)
.dc.l iocs_1E_B_CURON
.dc.l 0
;_B_CUROFF
.dc.w 4*($100+_B_CUROFF)
.dc.l iocs_1F_B_CUROFF
.dc.l 0
;_B_PUTC
.dc.w 4*($100+_B_PUTC)
.dc.l iocs_20_B_PUTC
.dc.l 0
;_B_PRINT
.dc.w 4*($100+_B_PRINT)
.dc.l iocs_21_B_PRINT
.dc.l 0
;_B_COLOR
.dc.w 4*($100+_B_COLOR)
.dc.l iocs_22_B_COLOR
.dc.l 0
;_B_LOCATE
.dc.w 4*($100+_B_LOCATE)
.dc.l iocs_23_B_LOCATE
.dc.l 0
;_B_DOWN_S
.dc.w 4*($100+_B_DOWN_S)
.dc.l iocs_24_B_DOWN_S
.dc.l 0
;_B_UP_S
.dc.w 4*($100+_B_UP_S)
.dc.l iocs_25_B_UP_S
.dc.l 0
;_B_UP
.dc.w 4*($100+_B_UP)
.dc.l iocs_26_B_UP
.dc.l 0
;_B_DOWN
.dc.w 4*($100+_B_DOWN)
.dc.l iocs_27_B_DOWN
.dc.l 0
;_B_RIGHT
.dc.w 4*($100+_B_RIGHT)
.dc.l iocs_28_B_RIGHT
.dc.l 0
;_B_LEFT
.dc.w 4*($100+_B_LEFT)
.dc.l iocs_29_B_LEFT
.dc.l 0
;_B_CLR_ST
.dc.w 4*($100+_B_CLR_ST)
.dc.l iocs_2A_B_CLR_ST
.dc.l 0
;_B_ERA_ST
.dc.w 4*($100+_B_ERA_ST)
.dc.l iocs_2B_B_ERA_ST
.dc.l 0
;_B_INS
.dc.w 4*($100+_B_INS)
.dc.l iocs_2C_B_INS
.dc.l 0
;_B_DEL
.dc.w 4*($100+_B_DEL)
.dc.l iocs_2D_B_DEL
.dc.l 0
;_B_CONSOL
.dc.w 4*($100+_B_CONSOL)
.dc.l iocs_2E_B_CONSOL
.dc.l 0
;_OS_CURON
.dc.w 4*($100+_OS_CURON)
.dc.l iocs_AE_OS_CURON
.dc.l 0
;_OS_CUROF
.dc.w 4*($100+_OS_CUROF)
.dc.l iocs_AF_OS_CUROF
.dc.l 0
;_PUTCHAR
.dc.w $1800+4*(_PUTCHAR-$FF00)
.dc.l dos_FF02_PUTCHAR
old_putchar:
.dc.l 0
;_INPOUT
.dc.w $1800+4*(_INPOUT-$FF00)
.dc.l dos_FF06_INPOUT
old_inpout:
.dc.l 0
;_PRINT
.dc.w $1800+4*(_PRINT-$FF00)
.dc.l dos_FF09_PRINT
old_print:
.dc.l 0
;_FPUTC
.dc.w $1800+4*(_FPUTC-$FF00)
.dc.l dos_FF1D_FPUTC
old_fputc:
.dc.l 0
;_FPUTS
.dc.w $1800+4*(_FPUTS-$FF00)
.dc.l dos_FF1E_FPUTS
old_fputs:
.dc.l 0
;_CONCTRL
.dc.w $1800+4*(_CONCTRL-$FF00)
.dc.l dos_FF23_CONCTRL
old_conctrl:
.dc.l 0
;_WRITE
.dc.w $1800+4*(_WRITE-$FF00)
.dc.l dos_FF40_WRITE
old_write:
.dc.l 0
.dc.w 0
;----------------------------------------------------------------
;リクエストヘッダのアドレス
request_header:
.dc.l 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 ;長さ
dostart
clr.w -(sp) ;1文字入力
.if 0
DOS _KEYCTRL
.else
movea.l sp,a6
movea.l $1800+4*(_KEYCTRL-$FF00).w,a0
jsr (a0)
.endif
addq.l #2,sp
move.b d0,(a1)+ ;文字コード
.if 0
break <cmp.b #13,d0>,eq
.endif
start
subq.l #1,d3
while cc
; move.l 18(a5),18(a5) ;入力した長さ
moveq.l #0,d0 ;常に成功する(終わるまで復帰しない)
rts
;デバイスコマンド5 コントロール/センス
control_sense:
move.w #1,-(sp) ;1文字センス
.if 0
DOS _KEYCTRL
.else
movea.l sp,a6
movea.l $1800+4*(_KEYCTRL-$FF00).w,a0
jsr (a0)
.endif
addq.l #2,sp
move.b d0,13(a5) ;文字コード
moveq.l #0,d0 ;常に成功する
rts
;デバイスコマンド6 入力ステータス
input_status:
move.w #1,-(sp) ;1文字センス
.if 0
DOS _KEYCTRL
.else
movea.l sp,a6
movea.l $1800+4*(_KEYCTRL-$FF00).w,a0
jsr (a0)
.endif
addq.l #2,sp
if <tst.b d0>,ne
moveq.l #0,d0 ;0=入力バッファが空ではないので入力できる
else
moveq.l #1,d0 ;1=入力バッファが空なので入力できない
endif
rts
;デバイスコマンド7 入力バッファフラッシュ
input_flush:
dostart
clr.w -(sp) ;1文字入力
.if 0
DOS _KEYCTRL
.else
movea.l sp,a6
movea.l $1800+4*(_KEYCTRL-$FF00).w,a0
jsr (a0)
.endif
addq.l #2,sp
start
move.w #1,-(sp) ;1文字センス
.if 0
DOS _KEYCTRL
.else
movea.l sp,a6
movea.l $1800+4*(_KEYCTRL-$FF00).w,a0
jsr (a0)
.endif
addq.l #2,sp
while <tst.b d0>,ne
moveq.l #0,d0 ;常に成功する
rts
;デバイスコマンド8 出力(ベリファイなし)
;デバイスコマンド9 出力(ベリファイあり)
output:
movea.l 14(a5),a1 ;アドレス
move.l 18(a5),d3 ;長さ
dostart
moveq.l #0,d1
move.b (a1)+,d1 ;文字コード
.if 0
move.w d1,-(sp)
clr.w -(sp) ;1文字表示
DOS _CONCTRL
addq.l #4,sp
.else
bsr putc ;1文字表示
.endif
start
subq.l #1,d3
while cc
; move.l 18(a5),18(a5) ;出力した長さ
moveq.l #0,d0 ;常に成功する(終わるまで復帰しない)
rts
;デバイスコマンド10 出力ステータス
output_status:
moveq.l #0,d0 ;0=出力バッファが満杯ではないので出力できる
; moveq.l #1,d0 ;1=出力バッファが満杯なので出力できない
rts
;デバイスコマンド11 正常終了
no_error:
moveq.l #0,d0 ;常に成功する
rts
;デバイスコマンド12 _IOCTRLによる出力
ioctrl_output:
; movea.l 14(a5),a1 ;アドレス
goto command_error
;hiocs.xが高速化するDOSコールは$FF02,$FF06,$FF09,$FF1D,$FF1E,$FF23,$FF40。すべて上書きする
;----------------------------------------------------------------
;DOSコール$FF02 _PUTCHAR 標準出力に1バイト出力
;<(a6).w:1バイトデータ
dos_FF02_PUTCHAR:
;標準出力はCONか
bsr is_stdout_con ;標準出力はCONか
if pl ;エラーなし
if ne ;CONではない
;元の処理へ
movea.l old_putchar(pc),a0
jmp (a0)
endif
;出力する
moveq.l #0,d1
move.b 1(a6),d1
bsr putchar_to_con ;CONへ1バイト出力する。プリンタ出力,^S,^P,^N,^Cを処理する
moveq.l #0,d0
endif
rts
;----------------------------------------------------------------
;CONへ1バイト出力する。プリンタ出力,^S,^P,^N,^Cを処理する
;<d1.l:1バイトデータ
putchar_to_con:
push d0-d7/a0-a6
;CONへ出力する
bsr putc ;1文字表示
;標準プリンタへ出力する
if <tst.b DOS_CTRL_P_MODE.w>,ne
move.w #STDPRN,-(sp) ;標準プリンタ出力
move.w d1,-(sp)
movea.l sp,a6
movea.l old_fputc(pc),a0
jsr (a0)
addq.l #2+2,sp
endif
;^Sを処理する
move.w #$00FE,-(sp) ;$00FE。標準入力の先読み。0でも戻る。BREAKチェックあり
movea.l sp,a6
movea.l old_inpout(pc),a0
jsr (a0)
addq.l #2,sp
if <cmp.w DOS_CTRL_S_CODE.w,d1>,eq ;^Sが押された
move.w #$00FF,-(sp) ;$00FF。標準入力から入力。0でも戻る。BREAKチェックあり
movea.l sp,a6
movea.l old_inpout(pc),a0
jsr (a0)
addq.l #2,sp
.if 0
DOS _INKEY
.else
movea.l $1800+4*(_INKEY-$FF00).w,a0
jsr (a0)
.endif
endif
;^P,^N,^Cを処理する
.if 0
DOS _KEYSNS
.else
movea.l $1800+4*(_KEYSNS-$FF00).w,a0
jsr (a0)
.endif
pop
rts
;----------------------------------------------------------------
;DOSコール$FF06 _INPOUT 標準ハンドラへの入出力
;<(a6).w:1バイトデータ
; $FE 標準入力の先読み。0でも戻る。BREAKチェックあり
; $FF 標準入力から入力。0でも戻る。BREAKチェックあり
; その他 標準出力へ1バイト出力
;>d0.l:入力した1バイトデータ
dos_FF06_INPOUT:
;先読みまたは入力か
if <cmp.b #$FE,1(a6)>,hs ;先読みまたは入力
;元の処理へ
movea.l old_inpout(pc),a0
jmp (a0)
endif
;標準出力はCONか
bsr is_stdout_con ;標準出力はCONか
if pl ;エラーなし
if ne ;CONではない
;元の処理へ
movea.l old_inpout(pc),a0
jmp (a0)
endif
;CONへ出力する
moveq.l #0,d1
move.b 1(a6),d1
bsr putc ;1文字表示
;標準プリンタへ出力する
if <tst.b DOS_CTRL_P_MODE.w>,ne
move.w #STDPRN,-(sp) ;標準プリンタ出力
move.w d1,-(sp)
movea.l sp,a6
movea.l old_fputc(pc),a0
jsr (a0)
addq.l #2+2,sp
endif
moveq.l #0,d0
;^S,^P,^N,^Cは処理しない
endif
rts
;----------------------------------------------------------------
;DOSコール$FF09 _PRINT 標準出力に文字列を出力
;<(a6).l:文字列
dos_FF09_PRINT:
;標準出力はCONか
bsr is_stdout_con ;標準出力はCONか
if pl ;エラーなし
if ne ;CONではない
;元の処理へ
movea.l old_print(pc),a0
jmp (a0)
endif
;CONへ出力する
movea.l (a6),a1 ;文字列
dostart
bsr putchar_to_con ;CONへ1バイト出力する。プリンタ出力,^S,^P,^N,^Cを処理する
start
moveq.l #0,d1
move.b (a1)+,d1
while ne
moveq.l #0,d0
endif
rts
;----------------------------------------------------------------
;DOSコール$FF1D _FPUTC ハンドラへ1バイト出力
;<(a6).w:文字
;<2(a6).w:ハンドラ番号
;>d0.l:出力した長さまたはエラーコード
dos_FF1D_FPUTC:
;ハンドラはCONか
move.w 2(a6),d0 ;ハンドラ番号
bsr is_handle_con ;ハンドラはCONか
if pl ;エラーなし
if ne ;CONではない
;元の処理へ
movea.l old_fputc(pc),a0
jmp (a0)
endif
;書き込めるか
moveq.l #$0F,d0
and.b 14(a0),d0 ;ファイルオープンモード
if ne ;書き込める
;CONへ出力する。プリンタ出力,^S,^P,^N,^Cは処理しない
moveq.l #0,d1
move.b 1(a6),d1 ;文字
bsr putc ;1文字表示
moveq.l #1,d0 ;出力した長さ
else ;書き込めない
moveq.l #INVALID_ACCESS_MODE,d0 ;オープンのアクセスモードが異常
endif
endif
rts
;----------------------------------------------------------------
;DOSコール$FF1E _FPUTS ハンドラへ文字列を出力
;<(a6).l:文字列
;<4(a6).w:ハンドラ番号
;>d0.l:出力した長さまたはエラーコード
dos_FF1E_FPUTS:
;文字列の長さは0か
movea.l (a6),a0 ;文字列
tst.b (a0)
if eq ;文字列の長さは0
;ハンドラ番号に関係なく正常終了する
moveq.l #0,d0 ;出力した長さ
else ;文字列の長さは0ではない
;ハンドラはCONか
move.w 4(a6),d0 ;ハンドラ番号
bsr is_handle_con ;ハンドラはCONか
if pl ;エラーなし
if ne ;CONではない
;元の処理へ
movea.l old_fputs(pc),a0
jmp (a0)
endif
;書き込めるか
moveq.l #$0F,d0
and.b 14(a0),d0 ;ファイルオープンモード
if ne ;書き込める
;CONへ出力する。プリンタ出力,^S,^P,^N,^Cは処理しない
movea.l (a6),a1 ;文字列
move.l a1,d0
dostart
bsr putc ;1文字表示
start
moveq.l #0,d1
move.b (a1)+,d1
while ne
subq.l #1,a1
exg.l d0,a1
sub.l a1,d0 ;出力した長さ
else ;書き込めない
moveq.l #INVALID_ACCESS_MODE,d0 ;オープンのアクセスモードが異常
endif
endif
endif
rts
;----------------------------------------------------------------
;DOSコール$FF23 _CONCTRL コンソール出力の制御
;<(a6).w:モード
; 0 1文字表示
; <2(a6).w:1バイトデータ
; 1 文字列表示
; <2(a6).l:文字列
; 2 文字属性の設定
; <2(a6).w:属性
; 3 カーソルの移動
; <2(a6).w:X座標
; <4(a6).w:Y座標
; 4 カーソルを1行下へ移動(下端ではスクロールアップ)
; 5 カーソルを1行上へ移動(上端ではスクロールダウン)
; 6 カーソルをN行上へ移動
; <2(a6).w:N
; 7 カーソルをN行下へ移動
; <2(a6).w:N
; 8 カーソルをN桁右へ移動
; <2(a6).w:N
; 9 カーソルをN桁左へ移動
; <2(a6).w:N
; 10 画面消去
; <2(a6).w:モード
; 0
; 1
; 2
; 11 行消去
; <2(a6).w:モード
; 0
; 1
; 2
; 12 N行挿入
; <2(a6).w:N
; 13 N行削除
; <2(a6).w:N
; 14 ファンクション表示行のモードの取得と設定
; <2(a6).w:モード
; -1 取得
; 0 ノーマル
; 1 シフト
; 2 表示しない
; 3 普通の行
; 15 スクロール範囲の設定
; <2(a6).w:スクロール範囲の開始行のY座標
; <4(a6).w:スクロール範囲の行数
; 16 画面モードの設定
; <2(a6).w:画面モード
; 0 768x512,グラフィックなし
; 1 768x512,グラフィック16色
; 2 512x512,グラフィックなし
; 3 512x512,グラフィック16色
; 4 512x512,グラフィック256色
; 5 512x512,グラフィック65536色
; 17 カーソル表示
; 18 カーソル消去
dos_FF23_CONCTRL:
move.w (a6),d0 ;モード
if <cmp.w #13,d0>,hi ;IOCSコール以外
;元の処理へ
movea.l old_conctrl(pc),a0
jmp (a0)
endif
movea.l 2(a6),a1
move.l a1,d1
swap.w d1
move.l a1,d2
add.w d0,d0
move.w 100f(pc,d0.w),d0
jmp 100f(pc,d0.w)
100:
.dc.w iocs_20_B_PUTC-100b
.dc.w iocs_21_B_PRINT-100b
.dc.w iocs_22_B_COLOR-100b
.dc.w iocs_23_B_LOCATE-100b
.dc.w iocs_24_B_DOWN_S-100b
.dc.w iocs_25_B_UP_S-100b
.dc.w iocs_26_B_UP-100b
.dc.w iocs_27_B_DOWN-100b
.dc.w iocs_28_B_RIGHT-100b
.dc.w iocs_29_B_LEFT-100b
.dc.w iocs_2A_B_CLR_ST-100b
.dc.w iocs_2B_B_ERA_ST-100b
.dc.w iocs_2C_B_INS-100b
.dc.w iocs_2D_B_DEL-100b
;----------------------------------------------------------------
;DOSコール$FF40 _WRITE ハンドラへ指定されたサイズのデータを書き込む
;<(a6).w:ハンドラ番号
;<2(a6).l:文字列
;<6(a6).l:文字列の長さ
;>d0.l:出力した長さ
dos_FF40_WRITE:
;ハンドラはCONか
move.w (a6),d0 ;ハンドラ番号
bsr is_handle_con ;ハンドラはCONか
if pl ;エラーなし
if ne ;CONではない
;元の処理へ
movea.l old_write(pc),a0
jmp (a0)
endif
;書き込めるか
moveq.l #$0F,d0
and.b 14(a0),d0 ;ファイルオープンモード
if ne ;書き込める
;CONへ出力する。プリンタ出力,^S,^P,^N,^Cを処理する
movea.l 2(a6),a1 ;文字列
move.l 6(a6),d0 ;文字列の長さ
move.l d0,d2
dostart
moveq.l #0,d1
move.b (a1)+,d1
bsr putchar_to_con ;CONへ1バイト出力する。プリンタ出力,^S,^P,^N,^Cを処理する
start
subq.l #1,d2
while cc
else ;書き込めない
moveq.l #INVALID_ACCESS_MODE,d0 ;オープンのアクセスモードが異常
endif
endif
rts
;----------------------------------------------------------------
;標準出力はCONか
;>d0.l:FCBテーブルまたはエラーコード
;>a0.l:FCBテーブル
;>n:pl=エラーなし,mi=エラーあり
;>z:ne=CONではない,eq=CON
;?d1-d7/a1-a5
is_stdout_con:
moveq.l #1,d0
;----------------------------------------------------------------
;ハンドラはCONか
;<d0.w:ハンドラ番号
;>d0.l:FCBテーブルまたはエラーコード
;>a0.l:FCBテーブル
;>n:pl=エラーなし,mi=エラーあり
;>z:ne=CONではない,eq=CON
;?d1-d7/a1-a5
is_handle_con:
.if 0
move.w d0,-(sp)
DOS _GETFCB
addq.l #2,sp
.else
push a6
move.w d0,-(sp)
movea.l sp,a6
movea.l $1800+4*(_GETFCB-$FF00).w,a0
jsr (a0)
addq.l #2,sp
pop
.endif
if <tst.l d0>,pl ;エラーなし
movea.l d0,a0 ;FCBテーブル
if <tst.b 1(a0)>,mi ;キャラクタデバイス
cmpi.l #'CON ',36(a0) ;デバイス名またはファイル名1
endif
endif
rts
;コンソール拡張
BIOS_ATTRIBUTE_2 equ $0D30 ;.b 文字属性2。-|上付き|下付き|上線|丸囲み|四角囲み|プロポーショナル|波線
BIOS_SUPERSCRIPT_BIT equ 6 ;上付き
BIOS_SUPERSCRIPT equ %01000000
BIOS_SUBSCRIPT_BIT equ 5 ;下付き
BIOS_SUBSCRIPT equ %00100000
BIOS_OVERLINE_BIT equ 4 ;上線
BIOS_OVERLINE equ %00010000
BIOS_ENCIRCLE_BIT equ 3 ;丸囲み
BIOS_ENCIRCLE equ %00001000
BIOS_FRAME_BIT equ 2 ;四角囲み
BIOS_FRAME equ %00000100
BIOS_PROPORTIONAL_BIT equ 1 ;プロポーショナル
BIOS_PROPORTIONAL equ %00000010
BIOS_WAVELINE_BIT equ 0 ;波線
BIOS_WAVELINE equ %00000001
BIOS_CURSOR_FRACTION equ $0D31 ;.b カーソルの桁座標の端数。0~7
BIOS_SAVED_ATTRIBUTE_2 equ $0D32 ;.b ESC [sで保存された文字属性2
BIOS_SAVED_FRACTION equ $0D33 ;.b ESC [sで保存されたカーソルの桁座標の端数
BIOS_BUFFER_REQUEST equ $0D34 ;.w バッファの文字列を表示する領域のドット幅。0=バッファ出力中ではない
BIOS_BUFFER_WIDTH equ $0D36 ;.w バッファの文字列のドット幅
BIOS_BUFFER_POINTER equ $0D38 ;.l バッファの書き込み位置
BIOS_BUFFER_ARRAY equ $0D3C ;.w[64] バッファ。右寄せ、中央寄せで使う
BIOS_CONSOLE_STATUS equ $0DBC ;.b コンソールの状態。----|左寄せ|中央寄せ|右寄せ|連結
BIOS_ALIGN_LEFT_BIT equ 3 ;左寄せ
BIOS_ALIGN_LEFT equ %00001000
BIOS_ALIGN_CENTER_BIT equ 2 ;中央寄せ
BIOS_ALIGN_CENTER equ %00000100
BIOS_ALIGN_RIGHT_BIT equ 1 ;右寄せ
BIOS_ALIGN_RIGHT equ %00000010
BIOS_CONNECTION_BIT equ 0 ;連結。最後に描画した文字は斜体でその後カーソルを動かしていない。次も斜体ならば詰めて描画する
BIOS_CONNECTION equ %00000001
; $0DBD ;.b[3]
;----------------------------------------------------------------
;カーソル点滅処理ルーチン
; Timer-C割り込みルーチンから500ms間隔で呼ばれる
timer_c_cursor:
if <tst.b BIOS_CURSOR_ON.w>,ne ;カーソルを表示するとき
ifor <tst.w BIOS_CURSOR_NOT_BLINK.w>,eq,<tst.b BIOS_CURSOR_DRAWN.w>,eq ;点滅させるか、描かれていないとき
if <btst.b #1,CRTC_ACCESS>,eq ;CRTCのマスクが使用中でないとき
bsr toggle_cursor ;カーソルを反転させる
not.b BIOS_CURSOR_DRAWN.w ;カーソルが描かれているか。0=描かれていない,-1=描かれている
endif
endif
endif
rts
;----------------------------------------------------------------
;カーソルを反転させる
toggle_cursor:
push d0-d2/a0-a2
move.w BIOS_CURSOR_ROW.w,d0 ;カーソルの行座標
swap.w d0
clr.w d0 ;65536*行座標
lsr.l #5,d0 ;128*16*行座標
move.w BIOS_CURSOR_COLUMN.w,d1 ;カーソルの桁座標
if <cmp.w BIOS_CONSOLE_RIGHT.w,d1>,hi
move.w BIOS_CONSOLE_RIGHT.w,d1 ;右端で止まる
endif
add.w d1,d0
add.l BIOS_CONSOLE_OFFSET.w,d0
add.l #$00E00000,d0 ;カーソルのアドレス
movea.l d0,a2
move.w CRTC_ACCESS,-(sp)
bclr.b #0,CRTC_ACCESS ;同時アクセスOFF
*** move.w BIOS_CURSOR_PATTERN.w,d1
*** if eq
*** moveq.l #-1,d1
*** endif
moveq.l #$80,d1
move.b BIOS_CURSOR_FRACTION.w,d0
lsr.b d0,d1
bsr toggle_cursor_1 ;プレーン0を反転
*** lsr.w #8,d1
adda.l #$00020000,a2
bsr toggle_cursor_1 ;プレーン1を反転
move.w (sp)+,CRTC_ACCESS
pop
rts
toggle_cursor_1:
move.w BIOS_CURSOR_START.w,d2 ;カーソル描画開始ライン*4
jmp @f(pc,d2.w)
@@: eor.b d1,(a2)
movea.l a0,a0 ;nop
.irp row,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
eor.b d1,128*row(a2)
.endm
rts
;----------------------------------------------------------------
;IOCSコール$1E _B_CURON カーソルを表示する
iocs_1E_B_CURON:
ifand <tst.b BIOS_CURSOR_PROHIBITED.w>,eq,<tst.b BIOS_CURSOR_ON.w>,eq ;許可されていて表示していないとき
move.w #5,BIOS_TC_CURSOR_COUNTER.w ;タイマカウンタ。1回目を10ms*5=50ms後に発生させる
st.b BIOS_CURSOR_ON.w ;表示している
clr.b BIOS_CURSOR_DRAWN.w ;描かれていない
endif
rts
;----------------------------------------------------------------
;IOCSコール$1F _B_CUROFF カーソルを表示しない
iocs_1F_B_CUROFF:
if <tst.b BIOS_CURSOR_PROHIBITED.w>,eq ;許可されているとき
move.w #5,BIOS_TC_CURSOR_COUNTER.w ;タイマカウンタ。1回目を10ms*5=50ms後に発生させる
clr.b BIOS_CURSOR_ON.w ;表示していない
if <tst.b BIOS_CURSOR_DRAWN.w>,ne ;描かれているとき
bsr toggle_cursor ;カーソルを反転させる
clr.b BIOS_CURSOR_DRAWN.w ;描かれていない
endif
endif
rts
;----------------------------------------------------------------
;IOCSコール$20 _B_PUTC 文字を表示する
;<d1.w:文字コード
;>d0.l:表示後のカーソルの桁座標<<16|カーソルの行座標
iocs_20_B_PUTC:
bsr putc ;1文字表示
move.l BIOS_CURSOR_COLUMN.w,d0 ;カーソルの桁座標<<16|カーソルの行座標
rts
;----------------------------------------------------------------
;IOCSコール$21 _B_PRINT 文字列を表示する
;<a1.l:文字列のアドレス
;>d0.l:表示後のカーソルの桁座標<<16|カーソルの行座標
;>a1.l:文字列の末尾の0の次のアドレス。マニュアルに書いてある。変更不可
iocs_21_B_PRINT:
push d1
dostart
bsr putc ;1文字表示
start
moveq.l #0,d1
move.b (a1)+,d1
while ne
pop
move.l BIOS_CURSOR_COLUMN.w,d0 ;カーソルの桁座標<<16|カーソルの行座標
rts
;----------------------------------------------------------------
;IOCSコール$22 _B_COLOR 文字属性を設定する
;<d1.w:文字属性。-1=取得のみ
; 0 黒
; 1 水色
; 2 黄色
; 3 白
; 4+ 太字
; 8+ 反転
;>d0.l:設定前の文字属性。-1=設定値が範囲外
iocs_22_B_COLOR:
push d1
moveq.l #0,d0
move.b BIOS_ATTRIBUTE_1.w,d0 ;文字属性2。-|上付き|下付き|上線|丸囲み|四角囲み|プロポーショナル|波線
lsl.w #8,d0
move.b BIOS_ATTRIBUTE_1.w,d0 ;文字属性1。取り消し線|下線|斜体|細字|反転|太字|プレーン##
if <cmp.w #-1,d1>,ne ;設定するとき
if <cmp.w #$7FFF,d1>,ls ;設定値が範囲内のとき
move.b d1,BIOS_ATTRIBUTE_1.w
lsr.w #8,d1
move.b d1,BIOS_ATTRIBUTE_2.w
else ;設定値が範囲外のとき
moveq.l #-1,d0
endif
endif
pop
rts
;----------------------------------------------------------------
;IOCSコール$23 _B_LOCATE カーソルの座標を設定する
;<d1.w:カーソルの桁座標の端数<<8|カーソルの桁座標。-1=取得のみ
;<d2.w:カーソルの行座標
;>d0.l:設定前のカーソルの座標。カーソルの桁座標の端数<<24|カーソルの桁座標<<16|カーソルの行座標。-1=設定値が範囲外
;>d1.l:(IOCS.X,1.3以上)取得のみのときd0.lと同じ
iocs_23_B_LOCATE:
moveq.l #0,d0
move.b BIOS_CURSOR_FRACTION.w,d0
ror.l #8,d0
or.l BIOS_CURSOR_COLUMN.w,d0 ;BIOS_CURSOR_ROW。カーソルの桁座標の端数<<24|カーソルの桁座標<<16|カーソルの行座標
if <cmp.w #-1,d1>,eq ;取得のみ
move.l d0,d1
rts
endif
push d1/d3
move.w d1,d3
and.w #$00FF,d1 ;カーソルの桁座標
lsr.w #8,d3 ;カーソルの桁座標の端数
ifand <cmp.w BIOS_CONSOLE_RIGHT.w,d1>,ls,<cmp.w BIOS_CONSOLE_BOTTOM.w,d2>,ls,<cmp.w #7,d3>,ls ;設定値が範囲内のとき
; push d0
bsr iocs_1F_B_CUROFF
move.w d1,BIOS_CURSOR_COLUMN.w
move.w d2,BIOS_CURSOR_ROW.w
move.b d3,BIOS_CURSOR_FRACTION.w
bsr iocs_1E_B_CURON
; pop d0
else ;設定値が範囲外のとき
moveq.l #-1,d0
endif
pop
rts
;----------------------------------------------------------------
;IOCSコール$24 _B_DOWN_S カーソルを1行下へ。下端ではスクロールアップ
;>d0.l:0
iocs_24_B_DOWN_S:
push d1-d2
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_ROW.w,d0
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,lo ;下端ではないとき
addq.w #1,d0 ;1行下へ
move.w d0,BIOS_CURSOR_ROW.w
else ;下端のとき
moveq.l #1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
moveq.l #0,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
bsr iocs_1E_B_CURON
pop
moveq.l #0,d0
rts
;----------------------------------------------------------------
;IOCSコール$25 _B_UP_S カーソルを1行上へ。上端ではスクロールダウン
;>d0.l:0
iocs_25_B_UP_S:
push d1-d2
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_ROW.w,d0
if <tst.w d0>,hi ;上端ではないとき
subq.w #1,d0 ;1行上へ
move.w d0,BIOS_CURSOR_ROW.w
else ;上端のとき
moveq.l #0,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1
subq.w #1,d1 ;コピー元の下端の行座標
moveq.l #1,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
moveq.l #0,d0 ;上端の行座標
moveq.l #0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
bsr iocs_1E_B_CURON
pop
moveq.l #0,d0
rts
;----------------------------------------------------------------
;IOCSコール$26 _B_UP カーソルをn行上へ。上端を超えるときは動かない
;<d1.b:移動する行数。0=1行
;>d0.l:0=成功,-1=失敗。上端を超える。このときカーソルは動かない
iocs_26_B_UP:
push d1
bsr iocs_1F_B_CUROFF
and.w #$00FF,d1
if eq
moveq.l #1,d1
endif
move.w BIOS_CURSOR_ROW.w,d0 ;カーソルの行座標
sub.w d1,d0 ;n行上へ
if mi ;上端を超える
moveq.l #-1,d1
else ;上端を超えない
move.w d0,BIOS_CURSOR_ROW.w
moveq.l #0,d1
endif
bsr iocs_1E_B_CURON
move.l d1,d0
pop
rts
;----------------------------------------------------------------
;IOCSコール$27 _B_DOWN カーソルをn行下へ。下端で止まる
;<d1.b:移動する行数。0=1行
;>d0.l:0
iocs_27_B_DOWN:
push d1
bsr iocs_1F_B_CUROFF
and.w #$00FF,d1
if eq
moveq.l #1,d1
endif
move.w BIOS_CURSOR_ROW.w,d0 ;カーソルの行座標
add.w d1,d0 ;n行下へ
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,hi ;下端を超える
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;下端で止まる
endif
move.w d0,BIOS_CURSOR_ROW.w
bsr iocs_1E_B_CURON
pop
moveq.l #0,d0
rts
;----------------------------------------------------------------
;IOCSコール$28 _B_RIGHT カーソルをn桁右へ。右端で止まる
;<d1.w:移動する桁数。0=1桁
;>d0.l:0
iocs_28_B_RIGHT:
push d1
bsr iocs_1F_B_CUROFF
and.w #$00FF,d1
if eq
moveq.l #1,d1
endif
move.w BIOS_CURSOR_COLUMN.w,d0 ;カーソルの桁座標
add.w d1,d0 ;n行右へ
if <cmp.w BIOS_CONSOLE_RIGHT.w,d0>,hi ;右端を超える
move.w BIOS_CONSOLE_RIGHT.w,d0 ;右端で止まる
endif
move.w d0,BIOS_CURSOR_COLUMN.w
clr.b BIOS_CURSOR_FRACTION.w
bsr iocs_1E_B_CURON
pop
moveq.l #0,d0
rts
;----------------------------------------------------------------
;IOCSコール$29 _B_LEFT カーソルをn桁左へ。左端で止まる
;<d1.w:移動する桁数。0=1桁
;>d0.l:0
iocs_29_B_LEFT:
push d1
bsr iocs_1F_B_CUROFF
and.w #$00FF,d1
if eq
moveq.l #1,d1
endif
move.w BIOS_CURSOR_COLUMN.w,d0 ;カーソルの桁座標
sub.w d1,d0 ;n行左へ
if mi ;左端を超える
clr.w d0 ;左端で止まる
endif
move.w d0,BIOS_CURSOR_COLUMN.w
clr.b BIOS_CURSOR_FRACTION.w
bsr iocs_1E_B_CURON
pop
moveq.l #0,d0
rts
;----------------------------------------------------------------
;IOCSコール$2A _B_CLR_ST 範囲を選択して画面を消去
;<d1.b:範囲。0=カーソルから右下まで,1=左上からカーソルまで,2=左上から右下まで。カーソルを左上へ
;>d0.l:0=成功,-1=失敗。引数がおかしい
iocs_2A_B_CLR_ST:
push d1
bsr iocs_1F_B_CUROFF
if <subq.b #1,d1>,lo ;0=カーソルから右下まで
bsr putc_csi_0J ;ESC [0J カーソルから右下まで消去する
moveq.l #0,d1
elif eq ;1=左上からカーソルまで
bsr putc_csi_1J ;ESC [1J 左上からカーソルまで消去する
moveq.l #0,d1
elif <subq.b #3-1,d1>,lo ;2=左上から右下まで
bsr putc_csi_2J ;ESC [2J 左上から右下まで消去する。カーソルを左上へ
moveq.l #0,d1
else
moveq.l #-1,d1
endif
bsr iocs_1E_B_CURON
move.l d1,d0
pop
rts
;----------------------------------------------------------------
;IOCSコール$2B _B_ERA_ST 範囲を選択して行を消去
;<d1.b:範囲。0=カーソルから右端まで,1=左端からカーソルまで,2=左端から右端まで
;>d0.l:0=成功,-1=失敗。引数がおかしい
iocs_2B_B_ERA_ST:
push d1
bsr iocs_1F_B_CUROFF
if <subq.b #1,d1>,lo ;0=カーソルから右端まで
bsr putc_csi_0K ;ESC [0K カーソルから右端まで消去する
moveq.l #0,d1
elif eq ;1=左端からカーソルまで
bsr putc_csi_1K ;ESC [1K 左端からカーソルまで消去する
moveq.l #0,d1
elif <subq.b #3-1,d1>,lo ;2=左端から右端まで
bsr putc_csi_2K ;ESC [2K 左端から右端まで消去する
moveq.l #0,d1
else ;引数がおかしい
moveq.l #-1,d1
endif
bsr iocs_1E_B_CURON
move.l d1,d0
pop
rts
;----------------------------------------------------------------
;IOCSコール$2C _B_INS カーソルから下にn行挿入。カーソルを左端へ
;<d1.w:挿入する行数。0=1行
;>d0.l:0
iocs_2C_B_INS:
push d1
bsr iocs_1F_B_CUROFF
bsr putc_csi_L ;ESC [nL カーソルから下にn行挿入。カーソルを左端へ
bsr iocs_1E_B_CURON
moveq.l #0,d0
pop
rts
;----------------------------------------------------------------
;IOCSコール$2D _B_DEL カーソルから下をn行削除。カーソルを左端へ
;<d1.w:削除する行数。0=1行
;>d0.l:0
iocs_2D_B_DEL:
push d1
bsr iocs_1F_B_CUROFF
bsr putc_csi_M ;ESC [nM カーソルから下をn行削除。カーソルを左端へ
bsr iocs_1E_B_CURON
moveq.l #0,d0
pop
rts
;----------------------------------------------------------------
;IOCSコール$2E _B_CONSOL コンソールの範囲を設定。カーソルを左上へ
;<d1.l:左上Xドット座標<<16|左上Yドット座標。-1=取得のみ。左上Xドット座標は8の倍数、左上Yドット座標は4の倍数
;<d2.l:右端の桁座標<<16|下端の行座標。-1=取得のみ
;>d0.l:0
;>d1.l:設定前の左上Xドット座標<<16|左上Yドット座標
;>d2.l:設定前の右端の桁座標<<16|下端の行座標
iocs_2E_B_CONSOL:
bsr iocs_1F_B_CUROFF
move.l BIOS_CONSOLE_OFFSET.w,d0
if <cmp.l #-1,d1>,ne
and.l #($03F8<<16)|$03FC,d1
move.l d1,d0
swap.w d0 ;左上Xドット座標
lsr.w #3,d0 ;左上Xドット座標/8
ext.l d1
lsl.l #7,d1 ;左上Yドット座標*128
add.w d0,d1
move.l BIOS_CONSOLE_OFFSET.w,d0
move.l d1,BIOS_CONSOLE_OFFSET.w
clr.l BIOS_CURSOR_COLUMN.w ;BIOS_CURSOR_ROW.w。カーソルを左上へ
endif
moveq.l #127,d1
and.w d0,d1 ;左上Xドット座標/8
lsl.w #3,d1 ;左上Xドット座標
swap.w d1
lsr.l #7,d0 ;左上Yドット座標
move.w d0,d1 ;設定前の左上Xドット座標<<16|左上Yドット座標
move.l BIOS_CONSOLE_RIGHT.w,d0 ;BIOS_CONSOLE_BOTTOM.w
if <cmp.l #-1,d2>,ne
and.l #127<<16|63,d2
move.l d2,BIOS_CONSOLE_RIGHT.w ;BIOS_CONSOLE_BOTTOM.w
clr.l BIOS_CURSOR_COLUMN.w ;BIOS_CURSOR_ROW.w。カーソルを左上へ
endif
move.l d0,d2 ;設定前の右端の桁座標<<16|下端の行座標
bsr iocs_1E_B_CURON
moveq.l #0,d0
rts
;----------------------------------------------------------------
;IOCSコール$AE _OS_CURON カーソルの表示を許可する
iocs_AE_OS_CURON:
move.w BIOS_TC_CURSOR_PERIOD.w,BIOS_TC_CURSOR_COUNTER.w ;タイマカウンタを初期値にする
di ;割込み禁止
ifor <tst.b BIOS_CURSOR_PROHIBITED.w>,ne,<tst.b BIOS_CURSOR_DRAWN.w>,eq ;禁止されているか描かれていないとき
bsr toggle_cursor ;カーソルを反転させる
st.b BIOS_CURSOR_DRAWN.w ;描かれている
endif
st.b BIOS_CURSOR_ON.w ;表示している
sf.b BIOS_CURSOR_PROHIBITED.w ;許可されている
ei ;割り込み許可
rts
;----------------------------------------------------------------
;IOCSコール$AF _OS_CUROF カーソルの表示を禁止する
iocs_AF_OS_CUROF:
bsr iocs_1F_B_CUROFF
st.b BIOS_CURSOR_PROHIBITED.w ;禁止されている
rts
;----------------------------------------------------------------
;1文字表示
;<d1.w:文字コード
putc:
push d0-d1
if <move.b BIOS_PUTC_POOL.w,d0>,eq ;1バイト目のとき
if <cmp.w #$001F,d1>,ls ;$0000~$001Fのとき
bsr putc_control ;制御文字を処理する
elif <cmp.w #$007F,d1>,ls ;$0020~$007Fのとき
if <cmp.w #$005C,d1>,eq ;$005Cのとき
if <btst.b #0,SRAM_XCHG>,ne ;文字変換フラグ。-----|$7C|/$82�|$7E ̄/$81~|$5C¥/$80\
move.w #$0080,d1 ;$5C→$80
endif
elif <cmp.w #$007E,d1>,eq ;$007Eのとき
if <btst.b #1,SRAM_XCHG>,ne ;文字変換フラグ。-----|$7C|/$82�|$7E ̄/$81~|$5C¥/$80\
move.w #$0081,d1 ;$7E→$81
endif
elif <cmp.w #$007C,d1>,eq ;$007Cのとき
if <btst.b #2,SRAM_XCHG>,ne ;文字変換フラグ。-----|$7C|/$82�|$7E ̄/$81~|$5C¥/$80\
move.w #$0082,d1 ;$7C→$82
endif
endif
bsr putc_output ;画面に描くまたはバッファに出力する
elif <cmp.w #$009F,d1>,ls ;$0080~$009Fのとき
move.b d1,BIOS_PUTC_POOL.w ;1バイト目のプール
elif <cmp.w #$00DF,d1>,ls ;$00A0~$00DFのとき
bsr putc_output ;画面に描くまたはバッファに出力する
elif <cmp.w #$00FF,d1>,ls ;$00E0~$00FFのとき
move.b d1,BIOS_PUTC_POOL.w ;1バイト目のプール
else ;$0100~$FFFFのとき
bsr putc_output ;画面に描くまたはバッファに出力する
endif
else ;2バイト目のとき
if <cmp.b #$1B,d0>,eq ;1バイト目が$1Bのとき。エスケープシーケンスの出力中
bsr putc_escape ;エスケープシーケンスを処理する
else ;1バイト目が$1Bではないとき
clr.b BIOS_PUTC_POOL.w ;1バイト目を消費する
lsl.w #8,d0 ;1バイト目<<8
move.b d1,d0 ;1バイト目<<8|2バイト目
move.w d0,d1 ;1バイト目<<8|2バイト目。1バイト目があるときd1.wの上位バイトは無視される
bsr putc_output ;画面に描くまたはバッファに出力する
endif
endif
pop
rts
;----------------------------------------------------------------
;バッファ出力を終了する
putc_finish_buffer:
push d0-d6/a0-a1
move.w BIOS_BUFFER_REQUEST.w,d0
goto eq,putc_finish_buffer_end ;バッファ出力中ではない
;<d0.w:バッファの文字列を表示する領域のドット幅
move.w BIOS_BUFFER_WIDTH.w,d1
;<d1.w:バッファの文字列のドット幅
movea.l BIOS_BUFFER_POINTER.w,a0
;<a0.l:バッファの書き込み位置=文字列の直後
lea.l BIOS_BUFFER_ARRAY.w,a1
;<a1.l:バッファ=文字列の先頭
clr.w BIOS_BUFFER_REQUEST.w ;バッファ出力終了。再帰呼び出しで表示するのでその前に終了すること
clr.w BIOS_BUFFER_WIDTH.w
move.l a1,BIOS_BUFFER_POINTER.w
sub.w d1,d0 ;余るドット数
;<d0.w:余るドット数
if ls ;余らないとき
;文字列を表示する
do
move.w (a1)+,d1
bsr putc_output
while <cmpa.w a0,a1>,lo
elif <bclr.b #BIOS_ALIGN_LEFT_BIT,BIOS_CONSOLE_STATUS.w>,ne ;左寄せで余るとき
;文字列を表示する
do
move.w (a1)+,d1
bsr putc_output
while <cmpa.w a0,a1>,lo
;右側の余った範囲を消去する
moveq.l #0,d4
move.b BIOS_CURSOR_FRACTION.w,d4 ;d4=左端の桁座標の端数
add.w d4,d0
subq.w #1,d0
moveq.l #7,d5
and.w d0,d5 ;d5=右端の桁座標の端数
lsr.w #3,d0
move.w BIOS_CURSOR_COLUMN.w,d2 ;d2=左端の桁座標
add.w d2,d0
move.w d0,d3 ;d3=右端の桁座標
move.w BIOS_CURSOR_ROW.w,d0 ;d0=上端の行座標
move.w d0,d1 ;d1=下端の行座標
bsr putc_clear
;カーソルを動かす
addq.w #1,d5
if <cmp.w #8,d5>,hs
subq.w #8,d5
addq.w #1,d3
endif
move.w d3,BIOS_CURSOR_COLUMN.w
move.b d5,BIOS_CURSOR_FRACTION.w
elif <bclr.b #BIOS_ALIGN_RIGHT_BIT,BIOS_CONSOLE_STATUS.w>,ne ;右寄せで余るとき
;左側の余った範囲を消去する
moveq.l #0,d4
move.b BIOS_CURSOR_FRACTION.w,d4 ;d4=左端の桁座標の端数
add.w d4,d0
subq.w #1,d0
moveq.l #7,d5
and.w d0,d5 ;d5=右端の桁座標の端数
lsr.w #3,d0
move.w BIOS_CURSOR_COLUMN.w,d2 ;d2=左端の桁座標
add.w d2,d0
move.w d0,d3 ;d3=右端の桁座標
move.w BIOS_CURSOR_ROW.w,d0 ;d0=上端の行座標
move.w d0,d1 ;d1=下端の行座標
bsr putc_clear
;カーソルを動かす
addq.w #1,d5
if <cmp.w #8,d5>,hs
subq.w #8,d5
addq.w #1,d3
endif
move.w d3,BIOS_CURSOR_COLUMN.w
move.b d5,BIOS_CURSOR_FRACTION.w
;文字列を表示する
do
move.w (a1)+,d1
bsr putc_output
while <cmpa.w a0,a1>,lo
elif <bclr.b #BIOS_ALIGN_CENTER_BIT,BIOS_CONSOLE_STATUS.w>,ne ;中央寄せで余るとき
;左側の余った範囲を消去する
move.w d0,d6
lsr.w #1,d0 ;左側の余った範囲のドット幅
sub.w d0,d6 ;右側の余った範囲のドット幅
moveq.l #0,d4
move.b BIOS_CURSOR_FRACTION.w,d4 ;d4=左端の桁座標の端数
add.w d4,d0
subq.w #1,d0
moveq.l #7,d5
and.w d0,d5 ;d5=右端の桁座標の端数
lsr.w #3,d0
move.w BIOS_CURSOR_COLUMN.w,d2 ;d2=左端の桁座標
add.w d2,d0
move.w d0,d3 ;d3=右端の桁座標
move.w BIOS_CURSOR_ROW.w,d0 ;d0=上端の行座標
move.w d0,d1 ;d1=下端の行座標
bsr putc_clear
;カーソルを動かす
addq.w #1,d5
if <cmp.w #8,d5>,hs
subq.w #8,d5
addq.w #1,d3
endif
move.w d3,BIOS_CURSOR_COLUMN.w
move.b d5,BIOS_CURSOR_FRACTION.w
;文字列を表示する
do
move.w (a1)+,d1
bsr putc_output
while <cmpa.w a0,a1>,lo
;右側の余った範囲を消去する
move.w d6,d0
moveq.l #0,d4
move.b BIOS_CURSOR_FRACTION.w,d4 ;d4=左端の桁座標の端数
add.w d4,d0
subq.w #1,d0
moveq.l #7,d5
and.w d0,d5 ;d5=右端の桁座標の端数
lsr.w #3,d0
move.w BIOS_CURSOR_COLUMN.w,d2 ;d2=左端の桁座標
add.w d2,d0
move.w d0,d3 ;d3=右端の桁座標
move.w BIOS_CURSOR_ROW.w,d0 ;d0=上端の行座標
move.w d0,d1 ;d1=下端の行座標
bsr putc_clear
;カーソルを動かす
addq.w #1,d5
if <cmp.w #8,d5>,hs
subq.w #8,d5
addq.w #1,d3
endif
move.w d3,BIOS_CURSOR_COLUMN.w
move.b d5,BIOS_CURSOR_FRACTION.w
endif
putc_finish_buffer_end:
pop
rts
;----------------------------------------------------------------
;制御文字を処理する
;<d1.w:文字コード
putc_control:
push d0-d1
;バッファ出力を終了する
if <tst.w BIOS_BUFFER_REQUEST.w>,ne ;バッファ出力中
bsr putc_finish_buffer ;バッファ出力を終了する
endif
;カーソルが右端からはみ出しているときBSでなければ改行する
move.w BIOS_CURSOR_COLUMN.w,d0 ;カーソルの桁座標
ifand <cmp.w BIOS_CONSOLE_RIGHT.w,d0>,hi,<cmp.w #$0008,d1>,ne ;カーソルが右端からはみ出しているかつBSではないとき
move.w BIOS_CURSOR_ROW.w,d0
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,lo ;下端ではないとき
addq.w #1,d0 ;1行下へ
move.w d0,BIOS_CURSOR_ROW.w
else ;下端のとき
moveq.l #1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
moveq.l #0,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.w BIOS_CURSOR_COLUMN.w ;左端へ
clr.b BIOS_CURSOR_FRACTION.w
endif
;制御文字を処理する
add.w d1,d1
move.w putc_control_jump_table(pc,d1.w),d1
jsr putc_control_jump_table(pc,d1.w)
pop
rts
putc_control_jump_table:
.dc.w putc_00_NL-putc_control_jump_table ;制御文字$00 NL
.dc.w putc_01_SH-putc_control_jump_table ;制御文字$01 SH
.dc.w putc_02_SX-putc_control_jump_table ;制御文字$02 SX
.dc.w putc_03_EX-putc_control_jump_table ;制御文字$03 EX
.dc.w putc_04_ET-putc_control_jump_table ;制御文字$04 ET
.dc.w putc_05_EQ-putc_control_jump_table ;制御文字$05 EQ
.dc.w putc_06_AK-putc_control_jump_table ;制御文字$06 AK
.dc.w putc_07_BL-putc_control_jump_table ;制御文字$07 BL ベルを鳴らす
.dc.w putc_08_BS-putc_control_jump_table ;制御文字$08 BS カーソルを1桁左へ。左端では1行上の右端へ。上端では何もしない
.dc.w putc_09_HT-putc_control_jump_table ;制御文字$09 HT カーソルを次のタブ桁へ。なければ1行下の左端へ。下端ではスクロールアップして左端へ
.dc.w putc_0A_LF-putc_control_jump_table ;制御文字$0A LF カーソルを1行下へ。下端ではスクロールアップ
.dc.w putc_0B_VT-putc_control_jump_table ;制御文字$0B VT カーソルを1行上へ。上端では何もしない
.dc.w putc_0C_FF-putc_control_jump_table ;制御文字$0C FF カーソルを1桁右へ。右端では1行下の左端へ。下端ではスクロールアップして左端へ
.dc.w putc_0D_CR-putc_control_jump_table ;制御文字$0D CR カーソルを左端へ
.dc.w putc_0E_SO-putc_control_jump_table ;制御文字$0E SO
.dc.w putc_0F_SI-putc_control_jump_table ;制御文字$0F SI
.dc.w putc_10_DE-putc_control_jump_table ;制御文字$10 DE
.dc.w putc_11_D1-putc_control_jump_table ;制御文字$11 D1
.dc.w putc_12_D2-putc_control_jump_table ;制御文字$12 D2
.dc.w putc_13_D3-putc_control_jump_table ;制御文字$13 D3
.dc.w putc_14_D4-putc_control_jump_table ;制御文字$14 D4
.dc.w putc_15_NK-putc_control_jump_table ;制御文字$15 NK
.dc.w putc_16_SN-putc_control_jump_table ;制御文字$16 SN
.dc.w putc_17_EB-putc_control_jump_table ;制御文字$17 EB
.dc.w putc_18_CN-putc_control_jump_table ;制御文字$18 CN
.dc.w putc_19_EM-putc_control_jump_table ;制御文字$19 EM
.dc.w putc_1A_SB-putc_control_jump_table ;制御文字$1A SB 左上から右下まで消去。カーソルを左上へ
.dc.w putc_1B_EC-putc_control_jump_table ;制御文字$1B EC エスケープシーケンス開始
.dc.w putc_1C_FS-putc_control_jump_table ;制御文字$1C FS
.dc.w putc_1D_GS-putc_control_jump_table ;制御文字$1D GS
.dc.w putc_1E_RS-putc_control_jump_table ;制御文字$1E RS カーソルを左上へ
.dc.w putc_1F_US-putc_control_jump_table ;制御文字$1F US
;----------------------------------------------------------------
;制御文字$00 NL
putc_00_NL:
rts
;----------------------------------------------------------------
;制御文字$01 SH
putc_01_SH:
rts
;----------------------------------------------------------------
;制御文字$02 SX
putc_02_SX:
rts
;----------------------------------------------------------------
;制御文字$03 EX
putc_03_EX:
rts
;----------------------------------------------------------------
;制御文字$04 ET
putc_04_ET:
rts
;----------------------------------------------------------------
;制御文字$05 EQ
putc_05_EQ:
rts
;----------------------------------------------------------------
;制御文字$06 AK
putc_06_AK:
rts
;----------------------------------------------------------------
;制御文字$07 BL ベルを鳴らす
putc_07_BL:
push d0-d2/a0-a1
move.l BIOS_BEEP_DATA.w,d0 ;BEEP音のADPCMデータのアドレス。-1=BIOS_BEEP_EXTENSIONを使う
moveq.l #-1,d1
if <cmp.l d1,d0>,eq
movea.l BIOS_BEEP_EXTENSION.w,a0 ;BEEP処理まるごと差し換えルーチンのアドレス。BIOS_BEEP_DATA=-1のとき有効
jsr (a0)
else
move.w #4<<8|3,d1
moveq.l #0,d2
move.w BIOS_BEEP_LENGTH.w,d2 ;BEEP音のADPCMデータのバイト数。0=無音
movea.l d0,a1
IOCS _ADPCMOUT
endif
pop
rts
;----------------------------------------------------------------
;制御文字$08 BS カーソルを1桁左へ。左端では1行上の右端へ。上端では何もしない
putc_08_BS:
push d0
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_COLUMN.w,d0
if ne
subq.w #1,d0 ;1桁左へ
move.w d0,BIOS_CURSOR_COLUMN.w
clr.b BIOS_CURSOR_FRACTION.w
else
move.w BIOS_CURSOR_ROW.w,d0
if ne
subq.w #1,d0 ;1行上へ
move.w d0,BIOS_CURSOR_ROW.w
move.w BIOS_CONSOLE_RIGHT.w,BIOS_CURSOR_COLUMN.w ;右端へ
clr.b BIOS_CURSOR_FRACTION.w
endif
endif
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;制御文字$09 HT カーソルを次のタブ桁へ。なければ1行下の左端へ。下端ではスクロールアップして左端へ
putc_09_HT:
push d0-d2
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_COLUMN.w,d0
addq.w #8,d0
and.w #-8,d0 ;次のタブ桁へ
if <cmp.w BIOS_CONSOLE_RIGHT.w,d0>,ls ;範囲内
move.w d0,BIOS_CURSOR_COLUMN.w
clr.b BIOS_CURSOR_FRACTION.w
else ;範囲外
move.w BIOS_CURSOR_ROW.w,d0
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,lo ;下端ではないとき
addq.w #1,d0 ;1行下へ
move.w d0,BIOS_CURSOR_ROW.w
else ;下端のとき
moveq.l #1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
moveq.l #0,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.w BIOS_CURSOR_COLUMN.w ;左端へ
clr.b BIOS_CURSOR_FRACTION.w
endif
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;制御文字$0A LF カーソルを1行下へ。下端ではスクロールアップ
putc_0A_LF:
push d0-d2
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_ROW.w,d0
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,lo ;下端ではないとき
addq.w #1,d0 ;1行下へ
move.w d0,BIOS_CURSOR_ROW.w
else ;下端のとき
moveq.l #1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
moveq.l #0,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;制御文字$0B VT カーソルを1行上へ。上端では何もしない
putc_0B_VT:
push d0
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_ROW.w,d0
if hi
subq.w #1,d0 ;1行上へ
move.w d0,BIOS_CURSOR_ROW.w
endif
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;制御文字$0C FF カーソルを1桁右へ。右端では1行下の左端へ。下端ではスクロールアップして左端へ
putc_0C_FF:
push d0-d2
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_COLUMN.w,d0
if <cmp.w BIOS_CONSOLE_RIGHT.w,d0>,lo ;右端ではないとき
addq.w #1,d0 ;1桁右へ
move.w d0,BIOS_CURSOR_COLUMN.w
clr.b BIOS_CURSOR_FRACTION.w
else ;右端のとき
move.w BIOS_CURSOR_ROW.w,d0
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,lo ;下端ではないとき
addq.w #1,d0 ;1行下へ
move.w d0,BIOS_CURSOR_ROW.w
else ;下端のとき
moveq.l #1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
moveq.l #0,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.w BIOS_CURSOR_COLUMN.w ;左端へ
clr.b BIOS_CURSOR_FRACTION.w
endif
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;制御文字$0D CR カーソルを左端へ
putc_0D_CR:
push d0
bsr iocs_1F_B_CUROFF
clr.w BIOS_CURSOR_COLUMN.w ;左端へ
clr.b BIOS_CURSOR_FRACTION.w
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;制御文字$0E SO
putc_0E_SO:
rts
;----------------------------------------------------------------
;制御文字$0F SI
putc_0F_SI:
rts
;----------------------------------------------------------------
;制御文字$10 DE
putc_10_DE:
rts
;----------------------------------------------------------------
;制御文字$11 D1
putc_11_D1:
rts
;----------------------------------------------------------------
;制御文字$12 D2
putc_12_D2:
rts
;----------------------------------------------------------------
;制御文字$13 D3
putc_13_D3:
rts
;----------------------------------------------------------------
;制御文字$14 D4
putc_14_D4:
rts
;----------------------------------------------------------------
;制御文字$15 NK
putc_15_NK:
rts
;----------------------------------------------------------------
;制御文字$16 SN
putc_16_SN:
rts
;----------------------------------------------------------------
;制御文字$17 EB
putc_17_EB:
rts
;----------------------------------------------------------------
;制御文字$18 CN
putc_18_CN:
rts
;----------------------------------------------------------------
;制御文字$19 EM
putc_19_EM:
rts
;----------------------------------------------------------------
;制御文字$1A SB 左上から右下まで消去。カーソルを左上へ
putc_1A_SB:
push d0-d1
bsr iocs_1F_B_CUROFF
clr.w d0 ;上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
clr.l BIOS_CURSOR_COLUMN.w ;左上へ
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;制御文字$1B EC エスケープシーケンス開始
putc_1B_EC:
move.b #$1B,BIOS_PUTC_POOL.w ;1バイト目のプール
move.l #BIOS_ESCAPE_BUFFER,BIOS_ESCAPE_POINTER.w ;エスケープシーケンスバッファの書き込み位置
rts
;----------------------------------------------------------------
;制御文字$1C FS
putc_1C_FS:
rts
;----------------------------------------------------------------
;制御文字$1D GS
putc_1D_GS:
rts
;----------------------------------------------------------------
;制御文字$1E RS カーソルを左上へ
putc_1E_RS:
bsr iocs_1F_B_CUROFF
clr.l BIOS_CURSOR_COLUMN.w
bsr iocs_1E_B_CURON
rts
;----------------------------------------------------------------
;制御文字$1F US
putc_1F_US:
rts
;----------------------------------------------------------------
;エスケープシーケンスを処理する
;<d1.w:文字コード
putc_escape:
push d0/a0
movea.l BIOS_ESCAPE_POINTER.w,a0
move.b d1,(a0)+
if <cmpa.l #BIOS_ESCAPE_BUFFER+10,a0>,lo
move.l a0,BIOS_ESCAPE_POINTER.w
endif
move.b BIOS_ESCAPE_BUFFER.w,d0 ;エスケープシーケンスの最初の文字
if <cmp.b #'[',d0>,eq ;ESC [
moveq.l #$20,d0
or.b d1,d0
ifand <cmp.b #'`',d0>,hs,<cmp.b #'z',d0>,ls ;'@'~'Z','`'~'z'
bsr putc_csi
endif
elif <cmp.b #'*',d0>,eq ;ESC *
bsr putc_esc_ast
elif <cmp.b #'=',d0>,eq ;ESC =
if <cmpa.l #BIOS_ESCAPE_BUFFER+3,a0>,eq
bsr putc_esc_equ
endif
elif <cmp.b #'D',d0>,eq ;ESC D
bsr putc_esc_D
elif <cmp.b #'E',d0>,eq ;ESC E
bsr putc_esc_E
elif <cmp.b #'M',d0>,eq ;ESC M
bsr putc_esc_M
else ;その他
clr.b BIOS_PUTC_POOL.w
endif
pop
rts
;----------------------------------------------------------------
;ESC *
; 左上から右下まで消去。カーソルを左上へ
putc_esc_ast:
push d0-d1
bsr iocs_1F_B_CUROFF
clr.w d0 ;上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
clr.l BIOS_CURSOR_COLUMN.w ;カーソルを左上へ
clr.b BIOS_PUTC_POOL.w
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;ESC = r c
; カーソルをr-' '行,c-' '桁へ。rとcは文字
putc_esc_equ:
push d0-d2
bsr iocs_1F_B_CUROFF
moveq.l #0,d1
moveq.l #0,d2
move.b BIOS_ESCAPE_BUFFER+2.w,d1 ;桁。' '=0
move.b BIOS_ESCAPE_BUFFER+1.w,d2 ;行。' '=0
moveq.l #' ',d0
sub.w d0,d1 ;桁座標
sub.w d0,d2 ;行座標
ifand <cmp.w BIOS_CONSOLE_RIGHT.w,d1>,ls,<cmp.w BIOS_CONSOLE_BOTTOM.w,d2>,ls ;コンソールの範囲内のとき
move.w d1,BIOS_CURSOR_COLUMN.w
move.w d2,BIOS_CURSOR_ROW.w
clr.b BIOS_CURSOR_FRACTION.w
endif
clr.b BIOS_PUTC_POOL.w
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;ESC D
; カーソルを1行下へ。下端ではスクロールアップ
; _B_DOWN_Sと同じ
putc_esc_D:
push d0-d2
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_ROW.w,d0
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,lo ;下端ではないとき
addq.w #1,d0 ;1行下へ
move.w d0,BIOS_CURSOR_ROW.w
else ;下端のとき
moveq.l #1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
moveq.l #0,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.b BIOS_PUTC_POOL.w
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;ESC E
; カーソルを1行下の左端へ。下端ではスクロールアップ
putc_esc_E:
push d0-d2
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_ROW.w,d0
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,lo ;下端ではないとき
addq.w #1,d0 ;1行下へ
move.w d0,BIOS_CURSOR_ROW.w
else ;下端のとき
moveq.l #1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
moveq.l #0,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.w BIOS_CURSOR_COLUMN.w ;左端へ
clr.b BIOS_CURSOR_FRACTION.w
clr.b BIOS_PUTC_POOL.w
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;ESC M
; カーソルを1行上へ。上端ではスクロールダウン
; _B_UP_Sと同じ
putc_esc_M:
push d0-d2
bsr iocs_1F_B_CUROFF
move.w BIOS_CURSOR_ROW.w,d0
if <tst.w d0>,hi ;上端ではないとき
subq.w #1,d0 ;1行上へ
move.w d0,BIOS_CURSOR_ROW.w
else ;上端のとき
moveq.l #0,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1
subq.w #1,d1 ;コピー元の下端の行座標
moveq.l #1,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
moveq.l #0,d0 ;上端の行座標
moveq.l #0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.b BIOS_PUTC_POOL.w
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;ESC [
; https://en.wikipedia.org/wiki/ANSI_escape_code
; http://nanno.dip.jp/softlib/man/rlogin/ctrlcode.html
putc_csi:
push d0-d3/a0
bsr iocs_1F_B_CUROFF
move.l BIOS_CSI_EXTENSION.w,d0 ;エスケープシーケンス丸ごと差し替えルーチン
if ne
lea.l BIOS_ESCAPE_BUFFER.w,a0
movejsr d0
else
lea.l BIOS_ESCAPE_BUFFER.w,a0
move.w (a0)+,d0
if <cmp.w #'[>',d0>,eq ;ESC [>
move.w (a0)+,d0
if <cmp.w #'5l',d0>,eq ;ESC [>5l カーソルON
sf.b BIOS_CURSOR_PROHIBITED.w
elif <cmp.w #'5h',d0>,eq ;ESC [>5h カーソルOFF
st.b BIOS_CURSOR_PROHIBITED.w
else
bsr putc_csi_extension
endif
elif <cmp.w #'[?',d0>,eq ;ESC [?
move.w (a0)+,d0
if <cmp.w #'4l',d0>,eq ;ESC [?4l ジャンプスクロール
clr.w BIOS_SMOOTH_SCROLL.w
elif <cmp.w #'4h',d0>,eq ;ESC [?4h 8ドットスムーススクロール
move.w #2,BIOS_SMOOTH_SCROLL.w
else
bsr putc_csi_extension
endif
else
lea.l BIOS_ESCAPE_BUFFER+1.w,a0 ;[の次
moveq.l #0,d0
moveq.l #-1,d1 ;1番目の数値
moveq.l #-1,d2 ;2番目の数値
moveq.l #-1,d3 ;3番目の数値
do
move.b (a0)+,d0
while <cmp.b #' ',d0>,eq
ifand <cmp.b #'0',d0>,hs,<cmp.b #'9',d0>,ls
moveq.l #0,d1
do
sub.b #'0',d0
mulu.w #10,d1
add.w d0,d1
move.b (a0)+,d0
whileand <cmp.b #'0',d0>,hs,<cmp.b #'9',d0>,ls
if <cmp.b #';',d0>,eq
do
move.b (a0)+,d0
while <cmp.b #' ',d0>,eq
ifand <cmp.b #'0',d0>,hs,<cmp.b #'9',d0>,ls
moveq.l #0,d2
do
sub.b #'0',d0
mulu.w #10,d2
add.w d0,d2
move.b (a0)+,d0
whileand <cmp.b #'0',d0>,hs,<cmp.b #'9',d0>,ls
if <cmp.b #';',d0>,eq
do
move.b (a0)+,d0
while <cmp.b #' ',d0>,eq
ifand <cmp.b #'0',d0>,hs,<cmp.b #'9',d0>,ls
moveq.l #0,d3
do
sub.b #'0',d0
mulu.w #10,d3
add.w d0,d3
move.b (a0)+,d0
whileand <cmp.b #'0',d0>,hs,<cmp.b #'9',d0>,ls
endif
endif
endif
endif
endif
if <cmp.b #'@',d0>,eq
bsr putc_csi_at ;ESC [n@ カーソルから右にn桁挿入
elif <cmp.b #'A',d0>,eq
bsr putc_csi_A ;ESC [nA カーソルをn行上へ。上端を超えるときは動かない
elif <cmp.b #'B',d0>,eq
bsr putc_csi_B ;ESC [nB カーソルをn行下へ。下端で止まる
elif <cmp.b #'C',d0>,eq
bsr putc_csi_C ;ESC [nC カーソルをn桁右へ。右端で止まる
elif <cmp.b #'D',d0>,eq
bsr putc_csi_D ;ESC [nD カーソルをn桁左へ。左端で止まる
elif <cmp.b #'H',d0>,eq
bsr putc_csi_H ;ESC [r;cH カーソルをr-1行,c-1桁へ
elif <cmp.b #'J',d0>,eq
bsr putc_csi_J ;ESC [nJ 画面を消去する
elif <cmp.b #'K',d0>,eq
bsr putc_csi_K ;ESC [nK 行を消去する
elif <cmp.b #'L',d0>,eq
bsr putc_csi_L ;ESC [nL カーソルから下にn行挿入。カーソルを左端へ
elif <cmp.b #'M',d0>,eq
bsr putc_csi_M ;ESC [nM カーソルから下をn行削除。カーソルを左端へ
elif <cmp.b #'P',d0>,eq
bsr putc_csi_P ;ESC [nP カーソルから右をn桁削除
elif <cmp.b #'R',d0>,eq
bsr putc_csi_R ;ESC [r;cR CSR(Cursor Position Report)
elif <cmp.b #'X',d0>,eq
bsr putc_csi_X ;ESC [nX カーソルから右をn桁消去
elif <cmp.b #'c',d0>,eq
bsr putc_csi_c ;ESC [nc 中央寄せ
elif <cmp.b #'f',d0>,eq
bsr putc_csi_f ;ESC [r;cf カーソルをr-1行,c-1桁へ
elif <cmp.b #'l',d0>,eq
bsr putc_csi_l ;ESC [nl 左寄せ
elif <cmp.b #'m',d0>,eq
bsr putc_csi_m ;ESC [nm 文字属性を設定する
elif <cmp.b #'n',d0>,eq
bsr putc_csi_n ;ESC [nn DSR(Device Status Report)
elif <cmp.b #'r',d0>,eq
bsr putc_csi_r ;ESC [nr 右寄せ
elif <cmp.b #'s',d0>,eq
bsr putc_csi_s ;ESC [ns カーソルの座標と文字属性を保存する
elif <cmp.b #'u',d0>,eq
bsr putc_csi_u ;ESC [nu カーソルの座標と文字属性を復元する
else
bsr putc_csi_extension
endif
endif
endif
clr.b BIOS_PUTC_POOL.w
bsr iocs_1E_B_CURON
pop
rts
;----------------------------------------------------------------
;拡張エスケープシーケンス処理ルーチンを呼び出す
putc_csi_extension:
push d0/a0
move.l BIOS_ESCAPE_EXTENSION.w,d0
if ne
lea.l BIOS_ESCAPE_BUFFER.w,a0
movejsr d0
endif
pop
rts
;----------------------------------------------------------------
;ESC [n@ カーソルから右にn桁挿入
;<d1.w:挿入する桁数。0=1桁
putc_csi_at:
push d0-d5/a0-a3
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=1桁
endif
;
; ABCDEFGHI
; ABC DE
;
move.w BIOS_CURSOR_COLUMN.w,d4
add.w d1,d4 ;カーソルの桁座標+挿入する桁数=移動先の桁座標
move.w BIOS_CONSOLE_RIGHT.w,d3
sub.w d4,d3 ;コンソールの右端-移動先の桁座標=移動する部分の桁数-1
if lo ;すべて押し出される
bsr putc_csi_0K ;ESC [0K カーソルから右端まで消去する
else ;移動する部分がある
move.w BIOS_CURSOR_ROW.w,d0 ;行座標
swap.w d0
clr.w d0 ;65536*行座標
lsr.l #5,d0 ;128*16*行座標
add.l BIOS_CONSOLE_OFFSET.w,d0
add.l #$00E00000,d0
movea.l d0,a2 ;行の左端のアドレス
movea.l a2,a3
adda.w BIOS_CURSOR_COLUMN.w,a2 ;カーソルのアドレス
adda.w d3,a2 ;移動元の右端のアドレス
adda.w BIOS_CONSOLE_RIGHT.w,a3 ;行の右端のアドレス=移動先の右端のアドレス
do ;プレーンのループ
moveq.l #16-1,d2
for d2 ;ラスタのループ
lea.l 1(a2),a0 ;移動元の右端のアドレス+1
lea.l 1(a3),a1 ;移動先の右端のアドレス+1
move.w d3,d1 ;移動する部分の桁数-1
for d1 ;桁のループ
move.b -(a0),-(a1)
next
lea.l 128(a2),a2 ;次のラスタ
lea.l 128(a3),a3
next
adda.l #-128*16+128*1024,a2 ;次のプレーン
adda.l #-128*16+128*1024,a3
while <cmpa.l #$00E40000,a2>,lo
move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
move.w BIOS_CURSOR_COLUMN.w,d2 ;左端の桁座標
move.w d4,d3
subq.w #1,d3 ;右端の桁座標
moveq.l #0,d4 ;左端の桁座標の端数
moveq.l #7,d5 ;右端の桁座標の端数
bsr putc_clear ;行を消去する
endif
pop
rts
;----------------------------------------------------------------
;ESC [nA カーソルをn行上へ。上端を超えるときは動かない
;<d1.w:移動する行数。0=1行
putc_csi_A:
push d0-d1
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=1行
endif
move.w BIOS_CURSOR_ROW.w,d0
sub.w d1,d0 ;n行上へ
if hs ;上端を超えないとき
move.w d0,BIOS_CURSOR_ROW.w
endif
pop
rts
;----------------------------------------------------------------
;ESC [nB カーソルをn行下へ。下端で止まる
;<d1.w:移動する行数。0=1桁
putc_csi_B:
push d0-d1
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=1行
endif
move.w BIOS_CURSOR_ROW.w,d0
add.w d1,d0 ;n行下へ
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,hi ;下端を超えるとき
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;下端で止まる
endif
move.w d0,BIOS_CURSOR_ROW.w
pop
rts
;----------------------------------------------------------------
;ESC [nC カーソルをn桁右へ。右端で止まる
;<d1.w:移動する桁数。0=1桁
putc_csi_C:
push d0-d1
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=1桁
endif
move.w BIOS_CURSOR_COLUMN.w,d0
add.w d1,d0 ;n桁右へ
if <cmp.w BIOS_CONSOLE_RIGHT.w,d0>,hi ;右端を超えるとき
move.w BIOS_CONSOLE_RIGHT.w,d0 ;右端で止まる
endif
move.w d0,BIOS_CURSOR_COLUMN.w
clr.b BIOS_CURSOR_FRACTION.w
pop
rts
;----------------------------------------------------------------
;ESC [nD カーソルをn桁左へ。左端で止まる
;<d1.w:移動する桁数。0=1桁
putc_csi_D:
push d0-d1
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=1桁
endif
move.w BIOS_CURSOR_COLUMN.w,d0
sub.w d1,d0 ;n桁左へ
if lo ;左端を超えるとき
moveq.l #0,d0 ;左端で止まる
endif
move.w d0,BIOS_CURSOR_COLUMN.w
clr.b BIOS_CURSOR_FRACTION.w
pop
rts
;----------------------------------------------------------------
;ESC [r;cf カーソルをr-1行,c-1桁へ
;<d1.w:移動先の行座標+1。0=上端。下端で止まる
;<d2.w:移動先の桁座標+1。0=左端。右端で止まる
putc_csi_f:
;----------------------------------------------------------------
;ESC [r;cH カーソルをr-1行,c-1桁へ
;<d1.w:移動先の行座標+1。0=上端。下端で止まる
;<d2.w:移動先の桁座標+1。0=左端。右端で止まる
putc_csi_H:
push d1-d2
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=上端
endif
subq.w #1,d1
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d1>,hi
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;下端で止まる
endif
ifor <cmp.w #-1,d2>,eq,<tst.w d2>,eq
moveq.l #1,d2 ;0=左端
endif
subq.w #1,d2
if <cmp.w BIOS_CONSOLE_RIGHT.w,d2>,hi
move.w BIOS_CONSOLE_RIGHT.w,d2 ;右端で止まる
endif
move.w d2,BIOS_CURSOR_COLUMN.w
move.w d1,BIOS_CURSOR_ROW.w
clr.b BIOS_CURSOR_FRACTION.w
pop
rts
;----------------------------------------------------------------
;ESC [nJ 画面を消去する
;<d1.w:0=カーソルから右下まで,1=左上からカーソルまで,2=左上から右下まで。カーソルを左上へ
putc_csi_J:
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
bsr putc_csi_0J ;ESC [0J カーソルから右下まで消去する
elif <cmp.w #1,d1>,eq
bsr putc_csi_1J ;ESC [1J 左上からカーソルまで消去する
elif <cmp.w #2,d1>,eq
bsr putc_csi_2J ;ESC [2J 左上から右下まで消去する。カーソルを左上へ
endif
rts
;----------------------------------------------------------------
;ESC [0J カーソルから右下まで消去する
putc_csi_0J:
push d0-d5
move.w BIOS_CURSOR_ROW.w,d0
move.w BIOS_CONSOLE_BOTTOM.w,d1
if <cmp.w d1,d0>,lo ;下端ではないとき
; move.w BIOS_CURSOR_ROW.w,d0
addq.w #1,d0 ;上端の行座標
; move.w BIOS_CONSOLE_BOTTOM.w,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
move.w BIOS_CURSOR_COLUMN.w,d2 ;左端の桁座標
move.w BIOS_CONSOLE_RIGHT.w,d3 ;右端の桁座標
moveq.l #0,d4
move.b BIOS_CURSOR_FRACTION.w,d4 ;左端の桁座標の端数
moveq.l #7,d5 ;右端の桁座標の端数
bsr putc_clear ;消去する
pop
rts
;----------------------------------------------------------------
;ESC [1J 左上からカーソルまで消去する
putc_csi_1J:
push d0-d5
move.w BIOS_CURSOR_ROW.w,d1
if <tst.w d1>,hi ;上端ではないとき
clr.w d0 ;上端の行座標
; move.w BIOS_CURSOR_ROW.w,d1
subq.w #1,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
moveq.l #0,d2 ;左端の桁座標
move.w BIOS_CURSOR_COLUMN.w,d3 ;右端の桁座標
moveq.l #0,d4 ;左端の桁座標の端数
moveq.l #7,d5
add.b BIOS_CURSOR_FRACTION.w,d5 ;右端の桁座標の端数
if <cmp.w #7,d5>,hi ;次の桁のとき
if <cmp.w BIOS_CONSOLE_RIGHT.w,d3>,lo ;右端ではないとき
addq.w #1,d3
subq.w #8,d5
else ;右端のとき
moveq.l #7,d5
endif
endif
bsr putc_clear ;消去する
pop
rts
;----------------------------------------------------------------
;ESC [2J 左上から右下まで消去する。カーソルを左上へ
putc_csi_2J:
push d0-d1
moveq.l #0,d0 ;上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
clr.l BIOS_CURSOR_COLUMN.w
pop
rts
;----------------------------------------------------------------
;ESC [nK 行を消去する
;<d1.w:0=カーソルから右端まで,1=左端からカーソルまで,2=左端から右端まで
putc_csi_K:
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
bsr putc_csi_0K ;ESC [0K カーソルから右端まで消去する
elif <cmp.w #1,d1>,eq
bsr putc_csi_1K ;ESC [1K 左端からカーソルまで消去する
elif <cmp.w #2,d1>,eq
bsr putc_csi_2K ;ESC [2K 左端から右端まで消去する
endif
rts
;----------------------------------------------------------------
;ESC [0K カーソルから右端まで消去する
putc_csi_0K:
push d0-d5
move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
move.w BIOS_CURSOR_COLUMN.w,d2 ;左端の桁座標
move.w BIOS_CONSOLE_RIGHT.w,d3 ;右端の桁座標
moveq.l #0,d4 ;左端の桁座標の端数
moveq.l #7,d5 ;右端の桁座標の端数
bsr putc_clear ;消去する
pop
rts
;----------------------------------------------------------------
;ESC [1K 左端からカーソルまで消去する
putc_csi_1K:
push d0-d5
move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
moveq.l #0,d2 ;左端の桁座標
move.w BIOS_CURSOR_COLUMN.w,d3 ;右端の桁座標
moveq.l #0,d4 ;左端の桁座標の端数
moveq.l #7,d5 ;右端の桁座標の端数
bsr putc_clear ;消去する
pop
rts
;----------------------------------------------------------------
;ESC [2K 左端から右端まで消去する
putc_csi_2K:
push d0-d1
move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
pop
rts
;----------------------------------------------------------------
;ESC [nL カーソルから下にn行挿入。カーソルを左端へ
;<d1.w:挿入する行数。0=1行
putc_csi_L:
push d0-d2
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=1行
endif
move.w BIOS_CURSOR_ROW.w,d0
;<d0.w:カーソルの行座標
move.w BIOS_CONSOLE_BOTTOM.w,d2 ;コンソールの行数-1
addq.w #1,d2 ;コンソールの行数
sub.w d0,d2 ;カーソルから下の行数
sub.w d1,d2 ;画面内に残る行数
;<d2.w:画面内に残る行数
if ls ;画面内に残る行がない。すべて画面外に押し出される
; ┌───┐ ┌───┐
; │ │ │ │
; │ │ │ │
;d0│●●●│→│□□□│
; │▲▲▲│ │□□□│
; │■■■│ │□□□│
; └───┘ └───┘
;;; move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
else ;画面内に残る行がある
; ┌───┐ ┌───┐
; │ │ │ │
; │ │ │ │
;d0│●●●│→│□□□│\d1
; │▲▲▲│ │□□□│/
; │■■■│ │●●●│)d2
; └───┘ └───┘
add.w d0,d2
subq.w #1,d2 ;コピー元の下端の行座標
add.w d0,d1 ;コピー先の上端の行座標
exg.l d1,d2
;;; move.w BIOS_CURSOR_ROW.w,d0 ;コピー元の上端の行座標
bsr putc_copy_rows ;行をコピーする
exg.l d1,d2
subq.w #1,d1 ;下端の行座標
;;; move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.w BIOS_CURSOR_COLUMN.w ;左端へ
clr.b BIOS_CURSOR_FRACTION.w
pop
rts
;----------------------------------------------------------------
;ESC [nM カーソルから下をn行削除。カーソルを左端へ
;<d1.w:削除する行数。0=1行
putc_csi_M:
push d0-d3
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=1行
endif
move.w BIOS_CURSOR_ROW.w,d0
;<d0.w:カーソルの行座標
move.w BIOS_CONSOLE_BOTTOM.w,d3 ;コンソールの行数-1
addq.w #1,d3 ;コンソールの行数
sub.w d0,d3 ;カーソルから下の行数
sub.w d1,d3 ;画面内に残る行数
;<d3.w:画面内に残る行数
if ls ;画面内に残る行がない。すべて削除される
; ┌───┐ ┌───┐
; │ │ │ │
; │ │ │ │
;d0│●●●│→│□□□│
; │▲▲▲│ │□□□│
; │■■■│ │□□□│
; └───┘ └───┘
;;; move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
else ;画面内に残る行がある
; ┌───┐ ┌───┐
; │ │ │ │
; │ │ │ │
;d0│●●●│→│■■■│)d3
; │▲▲▲│ │□□□│\d1
; │■■■│ │□□□│/
; └───┘ └───┘
;;; move.w BIOS_CURSOR_ROW.w,d0
move.w d0,d2 ;コピー先の上端の行座標
add.w d1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
bsr putc_copy_rows ;行をコピーする
move.w d2,d0
add.w d3,d0 ;上端の行座標
;;; move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.w BIOS_CURSOR_COLUMN.w ;左端へ
clr.b BIOS_CURSOR_FRACTION.w
pop
rts
;----------------------------------------------------------------
;ESC [nP カーソルから右をn桁削除
;<d1.w:削除する桁数。0=1桁
putc_csi_P:
push d0-d5/a0-a3
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=1桁
endif
;
; ABCDEFGHI
; ABCHI
;
move.w BIOS_CURSOR_COLUMN.w,d4 ;カーソルの桁座標
add.w d1,d4 ;カーソルの桁座標+削除する桁数=移動元の左端の桁座標
move.w BIOS_CONSOLE_RIGHT.w,d3 ;コンソールの右端の桁座標=移動元の右端の桁座標
sub.w d4,d3 ;移動元の右端の桁座標-移動元の左端の桁座標=移動する部分の桁数-1
if lo ;すべて削除される
bsr putc_csi_0K ;ESC [0K カーソルから右端まで消去する
else ;移動する部分がある
move.w BIOS_CURSOR_ROW.w,d0 ;カーソルの行座標
swap.w d0
clr.w d0 ;65536*カーソルの行座標
lsr.l #5,d0 ;128*16*カーソルの行座標
add.l BIOS_CONSOLE_OFFSET.w,d0
add.l #$00E00000,d0
movea.l d0,a2 ;カーソルの行の左端のアドレス
movea.l a2,a3
adda.w d4,a2 ;カーソルの行の左端のアドレス+移動元の左端の桁座標=移動元の左端のアドレス
adda.w BIOS_CURSOR_COLUMN.w,a3 ;カーソルの行の左端のアドレス+カーソルの桁座標=カーソルのアドレス=移動先の左端のアドレス
do ;プレーンのループ
moveq.l #16-1,d2
for d2 ;ラスタのループ
movea.l a2,a0 ;移動元の左端のアドレス
movea.l a3,a1 ;移動先の左端のアドレス
move.w d3,d1 ;移動する部分の桁数-1
for d1 ;桁のループ
move.b (a0)+,(a1)+
next
lea.l 128(a2),a2 ;次のラスタ
lea.l 128(a3),a3
next
adda.l #-128*16+128*1024,a2 ;次のプレーン
adda.l #-128*16+128*1024,a3
while <cmpa.l #$00E40000,a2>,lo
move.w BIOS_CURSOR_ROW.w,d0 ;カーソルの行座標=消去する範囲の上端の行座標
move.w d0,d1 ;カーソルの行座標=消去する範囲の下端の行座標
move.w BIOS_CURSOR_COLUMN.w,d2 ;カーソルの桁座標
add.w d3,d2 ;カーソルの桁座標+移動する範囲の桁数-1
addq.w #1,d2 ;カーソルの桁座標+移動する範囲の桁数=消去する範囲の左端の桁座標
move.w BIOS_CONSOLE_RIGHT.w,d3 ;コンソールの右端の桁座標=消去する範囲の右端の桁座標
moveq.l #0,d4 ;消去する範囲の左端の桁座標の端数
moveq.l #7,d5 ;消去する範囲の右端の桁座標の端数
bsr putc_clear ;行を消去する
endif
pop
rts
;----------------------------------------------------------------
;ESC [r;cR CPR(Cursor Position Report)
; DSR(Device Status Report)の返答。ここでは何もしない
putc_csi_R:
rts
;----------------------------------------------------------------
;ESC [nX カーソルから右をn桁消去
;<d1.w:消去する桁数。0=1桁
putc_csi_X:
push d0-d5
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1 ;0=1桁
endif
move.w BIOS_CURSOR_COLUMN.w,d2 ;左端の桁座標
move.w d2,d3
add.w d1,d3
subq.w #1,d3 ;右端の桁座標
if <cmp.w BIOS_CONSOLE_RIGHT.w,d3>,hi ;右端を超えるとき
move.w BIOS_CONSOLE_RIGHT.w,d3 ;右端で止まる
endif
move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
moveq.l #7,d4
and.b BIOS_CURSOR_FRACTION.w,d4 ;左端の桁座標の端数
moveq.l #7,d5 ;右端の桁座標の端数
bsr putc_clear ;消去する
pop
rts
;----------------------------------------------------------------
;ESC [nc 中央寄せ
;<d1.w:ドット幅
putc_csi_c:
push d0-d1
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1
endif
move.w BIOS_CONSOLE_RIGHT.w,d0
addq.w #1,d0
lsl.w #3,d0 ;コンソールのドット幅
if <cmp.w d0,d1>,ls ;大きすぎない
bset.b #BIOS_ALIGN_CENTER_BIT,BIOS_CONSOLE_STATUS.w ;中央寄せ
move.l #BIOS_BUFFER_ARRAY,BIOS_BUFFER_POINTER.w
clr.w BIOS_BUFFER_WIDTH.w
move.w d1,BIOS_BUFFER_REQUEST.w ;バッファ出力開始
endif
pop
rts
;----------------------------------------------------------------
;ESC [nl 左寄せ
;<d1.w:ドット幅
putc_csi_l:
push d0-d1
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1
endif
move.w BIOS_CONSOLE_RIGHT.w,d0
addq.w #1,d0
lsl.w #3,d0 ;コンソールのドット幅
if <cmp.w d0,d1>,ls ;大きすぎない
bset.b #BIOS_ALIGN_LEFT_BIT,BIOS_CONSOLE_STATUS.w ;左寄せ
move.l #BIOS_BUFFER_ARRAY,BIOS_BUFFER_POINTER.w
clr.w BIOS_BUFFER_WIDTH.w
move.w d1,BIOS_BUFFER_REQUEST.w ;バッファ出力開始
endif
pop
rts
;----------------------------------------------------------------
;ESC [nm 文字属性を設定する
; 0 リセット
; 1 太字
; 2 細字
; 3 斜体
; 4 下線
; 5 (遅い点滅)
; 6 (速い点滅)
; 7 反転
; 8 (秘密)
; 9 取り消し線
; 11~19 (代替フォント1~9)
; 20 (ブラックレター)
; 21 波線
; 22 太字、細字解除
; 23 斜体解除、(ブラックレター解除)
; 24 下線、波線解除
; 25 (遅い点滅解除、速い点滅解除)
; 26 プロポーショナル
; 27 反転解除
; 28 (秘密解除)
; 29 取り消し線解除
; 30 黒
; 31 水色
; 32 黄色
; 33 白
; 34 太字、黒
; 35 太字、水色
; 36 太字、黄色
; 37 太字、白
; 40 反転、黒
; 41 反転、水色
; 42 反転、黄色
; 43 反転、白
; 44 反転、太字、黒
; 45 反転、太字、水色
; 46 反転、太字、黄色
; 47 反転、太字、白
; 50 プロポーショナル解除
; 51 四角囲み
; 52 丸囲み
; 53 上線
; 54 四角囲み、丸囲み解除
; 55 上線解除
; 73 上付き
; 74 下付き
; 75 上付き、下付き解除
;<d1.w:属性。-1=指定なし
;<d2.w:属性。-1=指定なし
;<d3.w:属性。-1=指定なし
putc_csi_m:
push d1
bsr putc_csi_m_1
if <cmp.w #-1,d2>,ne
move.w d2,d1
bsr putc_csi_m_1
endif
if <cmp.w #-1,d3>,ne
move.w d3,d1
bsr putc_csi_m_1
endif
pop
rts
;?d1
putc_csi_m_1:
;太字と反転のみトグル動作。その他はONまたはOFFのどちらか
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
move.b #3,BIOS_ATTRIBUTE_1.w ;文字属性1。取り消し線|下線|斜体|細字|反転|太字|プレーン##
clr.b BIOS_ATTRIBUTE_2.w ;文字属性2。-|上付き|下付き|上線|丸囲み|四角囲み|プロポーショナル|波線
elif <cmp.w #1,d1>,eq
bchg.b #BIOS_BOLD_BIT,BIOS_ATTRIBUTE_1.w ;太字
if eq ;OFF→ONのとき
bclr.b #BIOS_FAINT_BIT,BIOS_ATTRIBUTE_1.w ;細字解除
endif
elif <cmp.w #2,d1>,eq
bclr.b #BIOS_BOLD_BIT,BIOS_ATTRIBUTE_1.w ;太字解除
bset.b #BIOS_FAINT_BIT,BIOS_ATTRIBUTE_1.w ;細字
elif <cmp.w #3,d1>,eq
bset.b #BIOS_ITALIC_BIT,BIOS_ATTRIBUTE_1.w ;斜体
elif <cmp.w #4,d1>,eq
bset.b #BIOS_UNDERLINE_BIT,BIOS_ATTRIBUTE_1.w ;下線
bclr.b #BIOS_WAVELINE_BIT,BIOS_ATTRIBUTE_2.w ;波線解除
elif <cmp.w #7,d1>,eq
bchg.b #BIOS_REVERSE_BIT,BIOS_ATTRIBUTE_1.w ;反転
elif <cmp.w #9,d1>,eq
bset.b #BIOS_STRIKETHROUGH_BIT,BIOS_ATTRIBUTE_1.w ;取り消し線
elif <cmp.w #21,d1>,eq
bclr.b #BIOS_UNDERLINE_BIT,BIOS_ATTRIBUTE_1.w ;下線解除
bset.b #BIOS_WAVELINE_BIT,BIOS_ATTRIBUTE_2.w ;波線
elif <cmp.w #22,d1>,eq
bclr.b #BIOS_BOLD_BIT,BIOS_ATTRIBUTE_1.w ;太字解除
bclr.b #BIOS_FAINT_BIT,BIOS_ATTRIBUTE_1.w ;細字解除
elif <cmp.w #23,d1>,eq
bclr.b #BIOS_ITALIC_BIT,BIOS_ATTRIBUTE_1.w ;斜体解除
elif <cmp.w #24,d1>,eq
bclr.b #BIOS_UNDERLINE_BIT,BIOS_ATTRIBUTE_1.w ;下線解除
bclr.b #BIOS_WAVELINE_BIT,BIOS_ATTRIBUTE_2.w ;波線解除
elif <cmp.w #26,d1>,eq
bset.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w ;プロポーショナル
elif <cmp.w #27,d1>,eq
bclr.b #BIOS_REVERSE_BIT,BIOS_ATTRIBUTE_1.w ;反転解除
elif <cmp.w #29,d1>,eq
bclr.b #BIOS_STRIKETHROUGH_BIT,BIOS_ATTRIBUTE_1.w ;取り消し線解除
elifand <cmp.w #30,d1>,hs,<cmp.w #37,d1>,ls
sub.w #30,d1
andi.b #$F0,BIOS_ATTRIBUTE_1.w
or.b d1,BIOS_ATTRIBUTE_1.w
elifand <cmp.w #40,d1>,hs,<cmp.w #47,d1>,ls
sub.w #40,d1
addq.b #8,d1
andi.b #$F0,BIOS_ATTRIBUTE_1.w
or.b d1,BIOS_ATTRIBUTE_1.w
elif <cmp.w #50,d1>,eq
bclr.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w ;プロポーショナル解除
elif <cmp.w #51,d1>,eq
bset.b #BIOS_FRAME_BIT,BIOS_ATTRIBUTE_2.w ;四角囲み
bclr.b #BIOS_ENCIRCLE_BIT,BIOS_ATTRIBUTE_2.w ;丸囲み解除
elif <cmp.w #52,d1>,eq
bclr.b #BIOS_FRAME_BIT,BIOS_ATTRIBUTE_2.w ;四角囲み解除
bset.b #BIOS_ENCIRCLE_BIT,BIOS_ATTRIBUTE_2.w ;丸囲み
elif <cmp.w #53,d1>,eq
bset.b #BIOS_OVERLINE_BIT,BIOS_ATTRIBUTE_2.w ;上線
elif <cmp.w #54,d1>,eq
bclr.b #BIOS_FRAME_BIT,BIOS_ATTRIBUTE_2.w ;四角囲み解除
bclr.b #BIOS_ENCIRCLE_BIT,BIOS_ATTRIBUTE_2.w ;丸囲み解除
elif <cmp.w #55,d1>,eq
bclr.b #BIOS_OVERLINE_BIT,BIOS_ATTRIBUTE_2.w ;上線解除
elif <cmp.w #73,d1>,eq
bset.b #BIOS_SUPERSCRIPT_BIT,BIOS_ATTRIBUTE_2.w ;上付き
bclr.b #BIOS_SUBSCRIPT_BIT,BIOS_ATTRIBUTE_2.w ;下付き解除
elif <cmp.w #74,d1>,eq
bclr.b #BIOS_SUPERSCRIPT_BIT,BIOS_ATTRIBUTE_2.w ;上付き解除
bset.b #BIOS_SUBSCRIPT_BIT,BIOS_ATTRIBUTE_2.w ;下付き
elif <cmp.w #75,d1>,eq
bclr.b #BIOS_SUPERSCRIPT_BIT,BIOS_ATTRIBUTE_2.w ;上付き解除
bclr.b #BIOS_SUBSCRIPT_BIT,BIOS_ATTRIBUTE_2.w ;下付き解除
endif
rts
;----------------------------------------------------------------
;ESC [nn DSR(Device Status Report)
;<d1.w:6
putc_csi_n:
push d0-d2/a0
if <cmp.w #6,d1>,eq ;CPR(Cursor Position Report)
move.w #$0100+27,d2
bsr 20f
move.w #$1C00+'[',d2
bsr 20f
move.w BIOS_CURSOR_ROW.w,d0
bsr 10f
move.w #$2700+';',d2
bsr 20f
move.w BIOS_CURSOR_COLUMN.w,d0
bsr 10f
move.w #$1400+'R',d2
bsr 20f
endif
pop
rts
;数値+1を文字列に変換してキー入力バッファに書き込む
;<d0.b:数値。255は不可。ここでは1を省略しない
;?d0-d2/a0
10: addq.b #1,d0
move.l #(1<<24)+(10<<16)+(100<<8),d1
do
lsr.l #8,d1
while <cmp.b d1,d0>,lo
do
moveq.l #-2,d2
do
addq.w #2,d2
sub.b d1,d0
while hs
move.w 15f(pc,d2.w),d2
bsr 20f
add.b d1,d0
lsr.l #8,d1
while <tst.b d1>,ne
rts
15: .dc.w $0B00+'0'
.dc.w $0200+'1'
.dc.w $0300+'2'
.dc.w $0400+'3'
.dc.w $0500+'4'
.dc.w $0600+'5'
.dc.w $0700+'6'
.dc.w $0800+'7'
.dc.w $0900+'8'
.dc.w $0A00+'9'
;キー入力バッファに書き込む
;<d2.w:(スキャンコード<<8)+文字コード
;?a0
20: di
if <cmpi.w #64,BIOS_KEY_REMAINING.w>,lo ;キー入力バッファに残っているデータの数が64未満のとき
movea.l BIOS_KEY_WRITTEN.w,a0 ;最後に書き込んだ位置
addq.l #2,a0 ;今回書き込む位置
if <cmpa.w #BIOS_KEY_BUFFER+2*64.w,a0>,hs ;末尾を超えたら
lea.l BIOS_KEY_BUFFER.w,a0 ;先頭に戻る
endif
move.w d2,(a0) ;書き込む
move.l a0,BIOS_KEY_WRITTEN.w ;最後に書き込んだ位置
addq.w #1,BIOS_KEY_REMAINING.w ;キー入力バッファに残っているデータの数
endif
ei
rts
;----------------------------------------------------------------
;ESC [nr 右寄せ
;<d1.w:ドット幅
putc_csi_r:
push d0-d1
ifor <cmp.w #-1,d1>,eq,<tst.w d1>,eq
moveq.l #1,d1
endif
move.w BIOS_CONSOLE_RIGHT.w,d0
addq.w #1,d0
lsl.w #3,d0 ;コンソールのドット幅
if <cmp.w d0,d1>,ls ;大きすぎない
bset.b #BIOS_ALIGN_RIGHT_BIT,BIOS_CONSOLE_STATUS.w ;右寄せ
move.l #BIOS_BUFFER_ARRAY,BIOS_BUFFER_POINTER.w
clr.w BIOS_BUFFER_WIDTH.w
move.w d1,BIOS_BUFFER_REQUEST.w ;バッファ出力開始
endif
pop
rts
;----------------------------------------------------------------
;ESC [ns カーソルの座標と文字属性を保存する
;<d1.w:-1
putc_csi_s:
if <cmp.w #-1,d1>,eq
move.w BIOS_CURSOR_ROW.w,BIOS_SAVED_ROW.w
move.w BIOS_CURSOR_COLUMN.w,BIOS_SAVED_COLUMN.w
move.b BIOS_CURSOR_FRACTION.w,BIOS_SAVED_FRACTION.w
move.b BIOS_ATTRIBUTE_1.w,BIOS_SAVED_ATTRIBUTE_1.w
move.b BIOS_ATTRIBUTE_2.w,BIOS_SAVED_ATTRIBUTE_2.w
endif
rts
;----------------------------------------------------------------
;ESC [nu カーソルの座標と文字属性を復元する
;<d1.w:-1
putc_csi_u:
if <cmp.w #-1,d1>,eq
move.w BIOS_SAVED_ROW.w,BIOS_CURSOR_ROW.w
move.w BIOS_SAVED_COLUMN.w,BIOS_CURSOR_COLUMN.w
move.b BIOS_SAVED_FRACTION.w,BIOS_CURSOR_FRACTION.w
move.b BIOS_SAVED_ATTRIBUTE_1.w,BIOS_ATTRIBUTE_1.w
move.b BIOS_SAVED_ATTRIBUTE_2.w,BIOS_ATTRIBUTE_2.w
endif
rts
;----------------------------------------------------------------
;画面に描くまたはバッファに出力する
;<d1.w:文字コード
putc_output:
push d0-d7/a0-a2
lea.l -4*16-4*16(sp),sp ;フォントデータとマスクデータ
;<(sp).l[16]:フォントデータ
;<4*16(sp).l[16]:マスクデータ
move.w d1,d7
;<d7.w:文字コード
;----------------
;フォントアドレスとドット幅を求める
ifand <btst.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w>,ne,<cmp.w #$0020,d1>,hs,<cmp.w #$0082,d1>,ls ;プロポーショナルにする
lea.l proportional_font(pc),a0 ;プロポーショナルフォント($20~$82)
sub.w #$0020,d1
mulu.w #2+2*16,d1
adda.l d1,a0 ;フォントアドレス
move.w (a0)+,d6 ;ドット幅。1~16
moveq.l #1,d2 ;16ドットデータ
else ;プロポーショナルにしない
moveq.l #8,d2
IOCS _FNTADR
;<d0.l:フォントアドレス
;<d1.w:横方向のドット数<<16|横方向のバイト数-1
;<d2.w:縦方向のドット数-1
movea.l d0,a0 ;フォントアドレス
move.w d1,d2 ;0=8ドットデータ,1=16ドットデータ
swap.w d1
move.w d1,d6 ;ドット幅。1~16
endif
;<d2.w:0=8ドットデータ,1=16ドットデータ
;<d6.w:ドット幅。1~16
;<(a0).b[16]:8ドットデータ
;または
;<(a0).w[16]:16ドットデータ
;----------------
;バッファに出力するか
if <tst.w BIOS_BUFFER_REQUEST.w>,ne ;バッファ出力中
movea.l BIOS_BUFFER_POINTER.w,a0 ;バッファの書き込み位置
goto <cmpa.l #BIOS_BUFFER_ARRAY+2*64,a0>,hs,putc_output_end ;バッファが一杯のときは無視する
move.w d7,(a0)+ ;文字コード
move.l a0,BIOS_BUFFER_POINTER.w ;書き込み位置を進める
if <btst.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w>,ne ;プロポーショナルのとき
if <btst.b #BIOS_BOLD_BIT,BIOS_ATTRIBUTE_1.w>,ne ;太字のとき
addq.w #1,d6 ;幅が1ドット増える
endif
if <btst.b #BIOS_ITALIC_BIT,BIOS_ATTRIBUTE_1.w>,ne ;斜体のとき
addq.w #3,d6 ;幅が3ドット増える
bset.b #BIOS_CONNECTION_BIT,BIOS_CONSOLE_STATUS.w
if ne ;連結のとき
subq.w #3,BIOS_BUFFER_WIDTH.w ;3ドット詰める
if cs
clr.w BIOS_BUFFER_WIDTH.w ;念の為
endif
endif
else ;斜体ではないとき
bclr.b #BIOS_CONNECTION_BIT,BIOS_CONSOLE_STATUS.w
endif
endif
add.w d6,BIOS_BUFFER_WIDTH.w ;幅を加える
goto putc_output_end
endif
;----------------
;カーソルOFF
; 斜体のとき位置がずれるのでその前にカーソルを消す
bsr iocs_1F_B_CUROFF
;----------------
;フォントデータを作る
movea.l sp,a1 ;フォントデータ
moveq.l #0,d0
if <tst.w d2>,eq ;8ドットデータのとき
moveq.l #16-1,d3
for d3
move.b (a0)+,(a1)+
move.b d0,(a1)+ ;clr
move.w d0,(a1)+ ;clr
next
else ;16ドットデータのとき
moveq.l #16-1,d3
for d3
move.w (a0)+,(a1)+
move.w d0,(a1)+ ;clr
next
endif
;<(sp).l[16]:フォントデータ
;----------------
;太字
; 全体を右に1ドットずらしてORする
; プロポーショナルのときは幅が1ドット増える
;<d6.w:ドット幅。1~16
;<(sp).l[16]:フォントデータ
;>d6.w:ドット幅。1~17
if <btst.b #BIOS_BOLD_BIT,BIOS_ATTRIBUTE_1.w>,ne ;太字のとき
movea.l sp,a1 ;フォントデータ
if <btst.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w>,ne ;プロポーショナルのとき
moveq.l #16-1,d3
for d3
move.l (a1),d0
move.l d0,d1
lsr.l #1,d0 ;右に1ドットずらして
or.l d1,d0 ;ORする
move.l d0,(a1)+
next
addq.w #1,d6 ;幅が1ドット増える
else ;プロポーショナルではないとき
moveq.l #1,d2
ror.l d6,d2
neg.l d2
moveq.l #16-1,d3
for d3
move.l (a1),d0
move.l d0,d1
lsr.l #1,d0 ;右に1ドットずらして
or.l d1,d0 ;ORする
and.l d2,d0 ;幅を増やさない
move.l d0,(a1)+
next
endif
endif
;----------------
;細字
; 上下左右のいずれかが1で、メッシュが1のとき、1を0にする
;<d6.w:ドット幅。1~16
;<(sp).l[16]:フォントデータ
if <btst.b #BIOS_FAINT_BIT,BIOS_ATTRIBUTE_1.w>,ne ;細字のとき
movea.l sp,a1 ;フォントデータ
move.l #$AAAAAAAA,d2
moveq.l #1,d0
and.b BIOS_CURSOR_FRACTION.w,d0
rol.l d0,d2
moveq.l #16-1,d3
for d3
move.l (a1),d0
move.l d0,d1
lsr.l #1,d1 ;左
lsl.l #1,d0 ;右
or.l d1,d0
if <cmpa.l sp,a1>,ne
or.l -4(a1),d0 ;上
endif
if <tst.w d3>,ne
or.l 4(a1),d0 ;下
endif
and.l d2,d0 ;メッシュ
not.l d0
and.l d0,(a1)+
rol.l #1,d2
next
endif
;----------------
;下線
;<d6.w:ドット幅。1~17
;<(sp).l[16]:フォントデータ
if <btst.b #BIOS_UNDERLINE_BIT,BIOS_ATTRIBUTE_1.w>,ne ;下線のとき
movea.l sp,a1 ;フォントデータ
moveq.l #1,d0
ror.l d6,d0
neg.l d0
or.l d0,4*15(a1)
endif
;----------------
;取り消し線
;<d6.w:ドット幅。1~17
;<(sp).l[16]:フォントデータ
if <btst.b #BIOS_STRIKETHROUGH_BIT,BIOS_ATTRIBUTE_1.w>,ne ;取り消し線のとき
movea.l sp,a1 ;フォントデータ
moveq.l #1,d0
ror.l d6,d0
neg.l d0
or.l d0,4*8(a1)
endif
;----------------
;波線
;<d6.w:ドット幅。1~17
;<(sp).l[16]:フォントデータ
if <btst.b #BIOS_WAVELINE_BIT,BIOS_ATTRIBUTE_2.w>,ne ;波線のとき
movea.l sp,a1 ;フォントデータ
moveq.l #1,d2
ror.l d6,d2
neg.l d2
moveq.l #3,d0
and.b BIOS_CURSOR_FRACTION.w,d0
.if 0
move.l #$CCCCCCCC,d1
rol.l d0,d1
move.l d1,d0 ;11001100
not.l d1 ;00110011
and.l d2,d0
and.l d2,d1
or.l d0,4*14(a1)
or.l d1,4*15(a1)
.else
move.l #$88888888,d1
move.l #$55555555,d3
rol.l d0,d1 ;10001000
rol.l d0,d3 ;01010101
move.l d1,d0
rol.l #2,d0 ;00100010
and.l d2,d0
and.l d2,d1
and.l d2,d3
or.l d0,4*13(a1)
or.l d3,4*14(a1)
or.l d1,4*15(a1)
.endif
endif
;----------------
;四角囲み
if <btst.b #BIOS_FRAME_BIT,BIOS_ATTRIBUTE_2.w>,ne ;四角囲みのとき
;16x16の中央に寄せる
moveq.l #16,d1
sub.w d6,d1
if hs
lsr.w #1,d1
movea.l sp,a1
moveq.l #16-1,d3
for d3
move.l (a1),d0
lsr.l d1,d0
move.l d0,(a1)+
next
moveq.l #16,d6
endif
;16x16を12x12に縮小する
lea.l subscript_pattern(pc),a2
lea.l 4*0(sp),a0
lea.l 4*0(sp),a1
moveq.l #0,d0
moveq.l #4-1,d3
for d3
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.b 4(a0),d0
move.b (a2,d0.w),d2
lsl.w #6,d2
move.b 5(a0),d0
move.b (a2,d0.w),d2
lsl.w #2,d2
or.w d2,d1
move.w d1,(a1)
addq.l #8,a0
addq.l #4,a1
;
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.w d1,(a1)
addq.l #4,a0
addq.l #4,a1
;
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.w d1,(a1)
addq.l #4,a0
addq.l #4,a1
next
clr.l 4*12(sp)
clr.l 4*13(sp)
clr.l 4*14(sp)
clr.l 4*15(sp)
;16x16の中央に寄せる
lea.l 4*12(sp),a0
lea.l 4*14(sp),a1
moveq.l #12-1,d3
for d3
move.l -(a0),d0
lsr.l #2,d0
move.l d0,-(a1)
next
clr.l 4*0(sp)
clr.l 4*1(sp)
;四角を付ける
movea.l sp,a0
or.l #$FFFF0000,(a0)+
moveq.l #14-1,d3
for d3
or.l #$80010000,(a0)+
next
or.l #$FFFF0000,(a0)+
endif
;----------------
;丸囲み
if <btst.b #BIOS_ENCIRCLE_BIT,BIOS_ATTRIBUTE_2.w>,ne ;丸囲みのとき
;16x16の中央に寄せる
moveq.l #16,d1
sub.w d6,d1
if hs
lsr.w #1,d1
movea.l sp,a1
moveq.l #16-1,d3
for d3
move.l (a1),d0
lsr.l d1,d0
move.l d0,(a1)+
next
moveq.l #16,d6
endif
;16x16を12x12に縮小する
lea.l subscript_pattern(pc),a2
lea.l 4*0(sp),a0
lea.l 4*0(sp),a1
moveq.l #0,d0
moveq.l #4-1,d3
for d3
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.b 4(a0),d0
move.b (a2,d0.w),d2
lsl.w #6,d2
move.b 5(a0),d0
move.b (a2,d0.w),d2
lsl.w #2,d2
or.w d2,d1
move.w d1,(a1)
addq.l #8,a0
addq.l #4,a1
;
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.w d1,(a1)
addq.l #4,a0
addq.l #4,a1
;
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.w d1,(a1)
addq.l #4,a0
addq.l #4,a1
next
clr.l 4*12(sp)
clr.l 4*13(sp)
clr.l 4*14(sp)
clr.l 4*15(sp)
;16x16の中央に寄せる
lea.l 4*12(sp),a0
lea.l 4*14(sp),a1
moveq.l #12-1,d3
for d3
move.l -(a0),d0
lsr.l #2,d0
move.l d0,-(a1)
next
clr.l 4*0(sp)
clr.l 4*1(sp)
;丸を付ける
movea.l sp,a0
; perl -e "for$y(0..15){print qq(\t\tandi.l\t#%);for$x(0..15){$t=($x-7.5)*($x-7.5)+($y-7.5)*($y-7.5);print($t<=8**2?'1':'0');}print qq(_0000000000000000,(a0)+\n);}"
andi.l #%0000011111100000_0000000000000000,(a0)+
andi.l #%0001111111111000_0000000000000000,(a0)+
andi.l #%0011111111111100_0000000000000000,(a0)+
andi.l #%0111111111111110_0000000000000000,(a0)+
andi.l #%0111111111111110_0000000000000000,(a0)+
andi.l #%1111111111111111_0000000000000000,(a0)+
andi.l #%1111111111111111_0000000000000000,(a0)+
andi.l #%1111111111111111_0000000000000000,(a0)+
andi.l #%1111111111111111_0000000000000000,(a0)+
andi.l #%1111111111111111_0000000000000000,(a0)+
andi.l #%1111111111111111_0000000000000000,(a0)+
andi.l #%0111111111111110_0000000000000000,(a0)+
andi.l #%0111111111111110_0000000000000000,(a0)+
andi.l #%0011111111111100_0000000000000000,(a0)+
andi.l #%0001111111111000_0000000000000000,(a0)+
andi.l #%0000011111100000_0000000000000000,(a0)+
movea.l sp,a0
; perl -e "for$y(0..15){print qq(\t\tori.l\t#%);for$x(0..15){$t=($x-7.5)*($x-7.5)+($y-7.5)*($y-7.5);print(7**2<=$t&&$t<=8**2?'1':'0');}print qq(_0000000000000000,(a0)+\n);}"
ori.l #%0000011111100000_0000000000000000,(a0)+
ori.l #%0001100000011000_0000000000000000,(a0)+
ori.l #%0011000000001100_0000000000000000,(a0)+
ori.l #%0110000000000110_0000000000000000,(a0)+
ori.l #%0100000000000010_0000000000000000,(a0)+
ori.l #%1000000000000001_0000000000000000,(a0)+
ori.l #%1000000000000001_0000000000000000,(a0)+
ori.l #%1000000000000001_0000000000000000,(a0)+
ori.l #%1000000000000001_0000000000000000,(a0)+
ori.l #%1000000000000001_0000000000000000,(a0)+
ori.l #%1000000000000001_0000000000000000,(a0)+
ori.l #%0100000000000010_0000000000000000,(a0)+
ori.l #%0110000000000110_0000000000000000,(a0)+
ori.l #%0011000000001100_0000000000000000,(a0)+
ori.l #%0001100000011000_0000000000000000,(a0)+
ori.l #%0000011111100000_0000000000000000,(a0)+
endif
;----------------
;上線
;<d6.w:ドット幅。1~17
;<(sp).l[16]:フォントデータ
if <btst.b #BIOS_OVERLINE_BIT,BIOS_ATTRIBUTE_2.w>,ne ;上線のとき
movea.l sp,a1 ;フォントデータ
moveq.l #1,d0
ror.l d6,d0
neg.l d0
or.l d0,4*0(a1)
endif
;----------------
;下付き
; 4x4の上2ドットと左2ドットをそれぞれORで1ドットにすることで、4x4を3x3に縮小する
; SX-Windowと同じ方法
; 縦16ドットを12ドットに縮小し、下から1ドットの高さに配置する
;<d6.w:ドット幅。1~16
;<(sp).l[16]:フォントデータ
;>d6.w:ドット幅。1~12
if <btst.b #BIOS_SUBSCRIPT_BIT,BIOS_ATTRIBUTE_2.w>,ne ;下付きのとき
lea.l subscript_pattern(pc),a2
lea.l 4*16(sp),a0
lea.l 4*15(sp),a1
moveq.l #0,d0
moveq.l #4-1,d3
for d3
subq.l #8,a0
subq.l #4,a1
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.b 4(a0),d0
move.b (a2,d0.w),d2
lsl.w #6,d2
move.b 5(a0),d0
move.b (a2,d0.w),d2
lsl.w #2,d2
or.w d2,d1
move.w d1,(a1)
;
subq.l #4,a0
subq.l #4,a1
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.w d1,(a1)
;
subq.l #4,a0
subq.l #4,a1
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.w d1,(a1)
next
clr.l 4*0(sp)
clr.l 4*1(sp)
clr.l 4*2(sp)
clr.l 4*15(sp)
moveq.l #3,d0
and.w d6,d0
lsr.w #2,d6
move.w d6,d1
add.w d6,d6
add.w d1,d6
add.w d0,d6
endif
;----------------
;上付き
; 4x4の上2ドットと左2ドットをそれぞれORで1ドットにすることで、4x4を3x3に縮小する
; SX-Windowと同じ方法
; 縦16ドットを12ドットに縮小し、上から0ドットの高さに配置する
;<d6.w:ドット幅。1~16
;<(sp).l[16]:フォントデータ
;>d6.w:ドット幅。1~12
if <btst.b #BIOS_SUPERSCRIPT_BIT,BIOS_ATTRIBUTE_2.w>,ne ;上付きのとき
lea.l subscript_pattern(pc),a2
lea.l 4*0(sp),a0
lea.l 4*0(sp),a1
moveq.l #0,d0
moveq.l #4-1,d3
for d3
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.b 4(a0),d0
move.b (a2,d0.w),d2
lsl.w #6,d2
move.b 5(a0),d0
move.b (a2,d0.w),d2
lsl.w #2,d2
or.w d2,d1
move.w d1,(a1)
addq.l #8,a0
addq.l #4,a1
;
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.w d1,(a1)
addq.l #4,a0
addq.l #4,a1
;
move.b (a0),d0
move.b (a2,d0.w),d1
lsl.w #6,d1
move.b 1(a0),d0
move.b (a2,d0.w),d1
lsl.w #2,d1
move.w d1,(a1)
addq.l #4,a0
addq.l #4,a1
next
clr.l 4*12(sp)
clr.l 4*13(sp)
clr.l 4*14(sp)
clr.l 4*15(sp)
moveq.l #3,d0
and.w d6,d0
lsr.w #2,d6
move.w d6,d1
add.w d6,d6
add.w d1,d6
add.w d0,d6
endif
;----------------
;反転
; 全体を反転させる
;<d6.w:ドット幅。1~17
;<(sp).l[16]:フォントデータ
if <btst.b #BIOS_REVERSE_BIT,BIOS_ATTRIBUTE_1.w>,ne ;反転のとき
movea.l sp,a1 ;フォントデータ
moveq.l #1,d0
ror.l d6,d0
neg.l d0
moveq.l #16-1,d3
for d3
eor.l d0,(a1)+
next
endif
;----------------
;マスクデータを作る
;<d6.w:ドット幅。1~17
;>4*16(sp).l[16]:マスクデータ
lea.l 4*16(sp),a1 ;マスクデータ
moveq.l #1,d0
ror.l d6,d0
neg.l d0
moveq.l #16-1,d3
for d3
move.l d0,(a1)+
next
;----------------
;斜体
; 全体を右に0~3ドットずらす
; プロポーショナルのとき幅が3ドット増える
; 斜体を続けて描画するときカーソルが動かなかったら3ドット詰める
;<d6.w:ドット幅。1~17
;<(sp).l[16]:フォントデータ
;<4*16(sp).l[16]:マスクデータ
;>d6.w:ドット幅。1~20
if <btst.b #BIOS_ITALIC_BIT,BIOS_ATTRIBUTE_1.w>,ne ;斜体のとき
movea.l sp,a0 ;フォントデータ
lea.l 4*16(sp),a1 ;マスクデータ
* if <btst.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w>,ne ;プロポーショナルのとき
moveq.l #3,d3
do
moveq.l #4-1,d2
for d2
move.l (a0),d0
lsr.l d3,d0
move.l d0,(a0)+
move.l (a1),d0
lsr.l d3,d0
move.l d0,(a1)+
next
subq.w #1,d3
while ne
addq.w #3,d6 ;幅が3ドット増える
bset.b #BIOS_CONNECTION_BIT,BIOS_CONSOLE_STATUS.w
if ne ;連結のとき
subq.b #3,BIOS_CURSOR_FRACTION.w ;3ドット詰める
if cs
addq.b #8,BIOS_CURSOR_FRACTION.w
subq.w #1,BIOS_CURSOR_COLUMN.w
if cs
clr.w BIOS_CURSOR_COLUMN.w ;念の為
clr.b BIOS_CURSOR_FRACTION.w
endif
endif
endif
* else ;プロポーショナルではないとき
* moveq.l #1,d4
* ror.l d6,d4
* neg.l d4
* moveq.l #4-1,d2
* for d2
* move.l (a0),d0
* lsr.l #2,d0
* and.l d4,d0 ;幅を増やさない
* move.l d0,(a0)+
* move.l (a1),d0
* lsr.l #2,d0
* and.l d4,d0 ;幅を増やさない
* move.l d0,(a1)+
* next
* moveq.l #4-1,d2
* for d2
* move.l (a0),d0
* lsr.l #1,d0
* and.l d4,d0 ;幅を増やさない
* move.l d0,(a0)+
* move.l (a1),d0
* lsr.l #1,d0
* and.l d4,d0 ;幅を増やさない
* move.l d0,(a1)+
* next
* lea.l 4*4(a0),a0
* lea.l 4*4(a1),a1
* moveq.l #4-1,d2
* for d2
* move.l (a0),d0
* lsl.l #1,d0
* move.l d0,(a0)+
* move.l (a1),d0
* lsl.l #1,d0
* move.l d0,(a1)+
* next
* endif
else ;斜体ではないとき
bclr.b #BIOS_CONNECTION_BIT,BIOS_CONSOLE_STATUS.w
endif
;----------------
;現在の行に入り切らなければ改行する
;<d6.w:ドット幅
move.w BIOS_CONSOLE_RIGHT.w,d0
addq.w #1,d0
lsl.w #3,d0 ;コンソールのドット幅
move.w BIOS_CURSOR_COLUMN.w,d1
lsl.w #3,d1
add.b BIOS_CURSOR_FRACTION.w,d1 ;カーソルのXドット座標
sub.w d1,d0 ;コンソールのドット幅-カーソルのXドット座標=残りドット幅
if le ;残りドット幅<=0。既にはみ出している
;改行する
move.w BIOS_CURSOR_ROW.w,d0
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,lo ;下端ではないとき
addq.w #1,d0 ;1行下へ
move.w d0,BIOS_CURSOR_ROW.w
else ;下端のとき
moveq.l #1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
moveq.l #0,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.w BIOS_CURSOR_COLUMN.w ;左端へ
clr.b BIOS_CURSOR_FRACTION.w
elif <cmp.w d6,d0>,lt ;残りドット幅<ドット幅。入り切らない
;残りを空白で埋める
move.w BIOS_CURSOR_ROW.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
move.w BIOS_CURSOR_COLUMN.w,d2 ;左端の桁座標
move.w BIOS_CONSOLE_RIGHT.w,d3 ;右端の桁座標
moveq.l #7,d4
and.b BIOS_CURSOR_FRACTION.w,d4 ;左端の桁座標の端数
moveq.l #7,d5 ;右端の桁座標の端数
bsr putc_clear ;消去する
;改行する
move.w BIOS_CURSOR_ROW.w,d0
if <cmp.w BIOS_CONSOLE_BOTTOM.w,d0>,lo ;下端ではないとき
addq.w #1,d0 ;1行下へ
move.w d0,BIOS_CURSOR_ROW.w
else ;下端のとき
moveq.l #1,d0 ;コピー元の上端の行座標
move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コピー元の下端の行座標
moveq.l #0,d2 ;コピー先の上端の行座標
bsr putc_copy_rows ;行をコピーする
move.w BIOS_CONSOLE_BOTTOM.w,d0 ;上端の行座標
move.w d0,d1 ;下端の行座標
bsr putc_clear_rows ;行を消去する
endif
clr.w BIOS_CURSOR_COLUMN.w ;左端へ
clr.b BIOS_CURSOR_FRACTION.w
endif
;----------------
;文字を描く
;<d6.w:ドット幅
;<(sp).l[16]:フォントデータ
;<4*16(sp).l[16]:マスクデータ
move.w BIOS_CURSOR_ROW.w,d0 ;行座標
move.w BIOS_CURSOR_COLUMN.w,d1 ;桁座標
moveq.l #7,d2
and.b BIOS_CURSOR_FRACTION.w,d2 ;桁座標の端数
move.w d6,d3 ;ドット幅
moveq.l #3,d4
and.b BIOS_ATTRIBUTE_1.w,d4 ;プレーン
movea.l sp,a0 ;フォントデータ
lea.l 4*16(sp),a1 ;マスクデータ
bsr putc_draw ;文字を描く
;----------------
;カーソルを進める
;<d6.w:ドット幅
add.b BIOS_CURSOR_FRACTION.w,d6 ;カーソルの桁座標の端数+ドット幅
moveq.l #7,d0
and.w d6,d0
move.b d0,BIOS_CURSOR_FRACTION.w ;カーソルの桁座標の端数
lsr.w #3,d6
add.w d6,BIOS_CURSOR_COLUMN.w ;カーソルの桁座標。ちょうど右端になる場合があるがここでは改行しない
;----------------
;カーソルON
bsr iocs_1E_B_CURON
;----------------
putc_output_end:
lea.l 4*16+4*16(sp),sp ;フォントデータとマスクデータ
pop
rts
;----------------------------------------------------------------
;下付きで使うパターン
; □□■□■■□■
subscript_pattern:
.irp ff,%00000000,%10000000,%10000000,%10000000
.irp ee,%00000000,%01000000
.irp dd,%00000000,%00100000
.irp cc,%00000000,%00010000,%00010000,%00010000
.irp bb,%00000000,%00001000
.irp aa,%00000000,%00000100
.dc.b ff+ee+dd+cc+bb+aa
.endm
.endm
.endm
.endm
.endm
.endm
;----------------------------------------------------------------
;文字を描く
;<d0.l:行座標
;<d1.l:桁座標
;<d2.l:桁座標の端数
;<d3.l:ドット幅
;<d4.l:プレーン。文字属性1の下位2ビット
;<(a0).l[16]:フォントデータ。左寄せ。リバースを含めて加工済み
;<(a1).l[16]:マスクデータ。左寄せ。書き込むビットが1
putc_draw:
push d0-d5/a0-a4
;----------------
;アドレスを求める
swap.w d0
clr.w d0 ;65536*行座標
lsr.l #5,d0 ;128*16*行座標
add.w d1,d0 ;128*16*行座標+桁座標
add.l BIOS_CONSOLE_OFFSET.w,d0 ;描き始めるアドレスのオフセット
add.l #$00E00000,d0 ;描き始めるアドレス
bclr.l #0,d0 ;偶数にする
if ne
addq.w #8,d2
endif
;<d2.w:桁座標の端数。0~15
movea.l d0,a4
;<a4.l:描き始めるアドレス。偶数
;?d0-d1
;----------------
add.w d2,d3 ;桁座標の端数+ドット幅
;<d3.w:桁座標の端数+ドット幅
;----------------
;1ワードに収まるか、2ワードに跨るか、3ワードに跨るか
if <cmp.w #16,d3>,ls
;----------------
;1ワードに収まるとき
do ;プレーンのループ
lsr.b #1,d4
if cs ;プレーンに描画するとき
movea.l a0,a2 ;フォントデータ
movea.l a1,a3 ;マスクデータ
moveq.l #16-1,d5
for d5 ;ラスタのループ
move.w (a2)+,d0 ;フォント
move.w (a3)+,d1 ;マスク
lsr.w d2,d0
lsr.w d2,d1
not.w d1
and.w (a4),d1 ;くり抜いて
or.w d1,d0 ;合わせて
move.w d0,(a4)+ ;書き込む
addq.l #4-2,a2
addq.l #4-2,a3
lea.l 128-2(a4),a4 ;次のラスタ
next
else ;プレーンを消去するとき
movea.l a1,a3 ;マスクデータ
moveq.l #16-1,d5
for d5 ;ラスタのループ
move.w (a3)+,d1 ;マスク
lsr.w d2,d1
not.w d1
and.w d1,(a4)+ ;くり抜く
addq.l #4-2,a3
lea.l 128-2(a4),a4 ;次のラスタ
next
endif
adda.l #-128*16+128*1024,a4 ;次のプレーン
while <cmpa.l #$00E40000,a4>,lo
elif <cmp.w #32,d3>,ls
;----------------
;2ワードに跨るとき
do ;プレーンのループ
lsr.b #1,d4
if cs ;プレーンに描画するとき
movea.l a0,a2 ;フォントデータ
movea.l a1,a3 ;マスクデータ
moveq.l #16-1,d5
for d5 ;ラスタのループ
move.l (a2)+,d0 ;フォント
move.l (a3)+,d1 ;マスク
lsr.l d2,d0
lsr.l d2,d1
not.l d1
and.l (a4),d1 ;くり抜いて
or.l d1,d0 ;合わせて
move.l d0,(a4)+ ;書き込む
; addq.l #4-4,a2
; addq.l #4-4,a3
lea.l 128-4(a4),a4 ;次のラスタ
next
else ;プレーンを消去するとき
movea.l a1,a3 ;マスクデータ
moveq.l #16-1,d5
for d5 ;ラスタのループ
move.l (a3)+,d1 ;マスク
lsr.l d2,d1
not.l d1
and.l d1,(a4)+ ;くり抜く
; addq.l #4-4,a3
lea.l 128-4(a4),a4 ;次のラスタ
next
endif
adda.l #-128*16+128*1024,a4 ;次のプレーン
while <cmpa.l #$00E40000,a4>,lo
else
;----------------
;3ワードに跨るとき
do ;プレーンのループ
lsr.b #1,d4
if cs ;プレーンに描画するとき
movea.l a0,a2 ;フォントデータ
movea.l a1,a3 ;マスクデータ
moveq.l #16-1,d5
for d5 ;ラスタのループ
move.l (a2)+,d0 ;フォント
move.l (a3)+,d1 ;マスク
lsr.l d2,d0
lsr.l d2,d1
not.l d1
and.l (a4),d1 ;くり抜いて
or.l d1,d0 ;合わせて
move.l d0,(a4)+ ;書き込む
move.w -2(a2),d0 ;フォント
move.w -2(a3),d1 ;マスク
swap.w d0
swap.w d1
clr.w d0
clr.w d1
lsr.l d2,d0
lsr.l d2,d1
not.w d1
and.w (a4),d1 ;くり抜いて
or.w d1,d0 ;合わせて
move.w d0,(a4)+ ;書き込む
; addq.l #4-4,a2
; addq.l #4-4,a3
lea.l 128-6(a4),a4 ;次のラスタ
next
else ;プレーンを消去するとき
movea.l a1,a3 ;マスクデータ
moveq.l #16-1,d5
for d5 ;ラスタのループ
move.l (a3)+,d1 ;マスク
lsr.l d2,d1
not.l d1
and.l d1,(a4)+ ;くり抜く
move.w -2(a3),d1 ;マスク
swap.w d1
clr.w d1
lsr.l d2,d1
not.w d1
and.w d1,(a4)+ ;くり抜く
; addq.l #4-4,a3
lea.l 128-6(a4),a4 ;次のラスタ
next
endif
adda.l #-128*16+128*1024,a4 ;次のプレーン
while <cmpa.l #$00E40000,a4>,lo
endif
pop
rts
;----------------------------------------------------------------
;行をコピーする
; ┌─────┐ ┌─────┐
; │ │┌├─────┤
; ├─────┤┘│ ↓ │d2
; d0│ ↓ │ │ ↓ │
; │ ↓ │ │ ↓ │
; d1│ ↓ │┌├─────┤
; ├─────┤┘│ │
; └─────┘ └─────┘
; ┌─────┐ ┌─────┐
; ├─────┤┐│ │
; d0│ ↑ │└├─────┤
; │ ↑ │ │ ↑ │d2
; d1│ ↑ │ │ ↑ │
; ├─────┤┐│ ↑ │
; │ │└├─────┤
; └─────┘ └─────┘
;<d0.w:コピー元の上端の行座標
;<d1.w:コピー元の下端の行座標
;<d2.w:コピー先の上端の行座標
putc_copy_rows:
push d0-d3/a0
move.l BIOS_CONSOLE_OFFSET.w,d3 ;コンソールの左上のアドレスのオフセット
lsr.l #7,d3 ;コンソールの上端のYドット座標
lsr.w #2,d3 ;コンソールの上端のラスタブロック番号
sub.w d0,d1 ;コピー元の下端の行座標-コピー元の上端の行座標=コピーする行数-1
lsl.w #2,d1 ;コピーするラスタブロック数-4
addq.w #3,d1 ;コピーするラスタブロック数-1
;<d1.w:コピーするラスタブロック数-1
lsl.w #2,d0
add.w d3,d0 ;コピー元の上端のラスタブロック番号
;<d0.w:コピー元の上端のラスタブロック番号
lsl.w #2,d2
add.w d3,d2 ;コピー先の上端のラスタブロック番号
;<d2.w:コピー先の上端のラスタブロック番号
if <cmp.w d0,d2>,ls ;上にずらすとき
move.w #$0101,d3 ;ラスタブロック番号の増分
else ;下にずらすとき
add.w d1,d0 ;コピー元の下端のラスタブロック番号
add.w d1,d2 ;コピー先の下端のラスタブロック番号
move.w #$FEFF,d3 ;ラスタブロック番号の増分
endif
;<d0.w:コピー元のラスタブロック番号
;<d2.w:コピー先のラスタブロック番号
;<d3.w:ラスタブロック番号の増分
lsl.w #8,d0 ;コピー元のラスタブロック番号<<8
move.b d2,d0 ;コピー元のラスタブロック番号<<8|コピー先のラスタブロック番号
;<d0.w:コピー元のラスタブロック番号<<8|コピー先のラスタブロック番号
aGPDR reg a0
lea.l MFP_GPDR,aGPDR ;GPIPデータレジスタ。HSYNC|RINT|-|VDISP|OPMIRQ|POWER|EXPWON|ALARM
move.w sr,d2
for d1 ;ラスタブロックのループ
do
while <tst.b (aGPDR)>,mi ;水平表示期間を待つ
ori.w #$0700,sr ;割り込みを禁止する
do
while <tst.b (aGPDR)>,pl ;水平帰線期間を待つ
move.w d0,CRTC_BLOCK-MFP_GPDR(aGPDR) ;ラスタブロック番号を設定する
move.w #$0008,CRTC_ACTION-MFP_GPDR(aGPDR) ;ラスタコピーをONにする。2回目以降は不要
move.w d2,sr ;割り込みを許可する
add.w d3,d0 ;次のラスタブロックへ
next
do
while <tst.b (aGPDR)>,mi ;水平表示期間を待つ
ori.w #$0700,sr ;割り込みを禁止する
do
while <tst.b (aGPDR)>,pl ;水平帰線期間を待つ
move.w d2,sr ;割り込みを許可する
clr.w CRTC_ACTION-MFP_GPDR(aGPDR) ;ラスタコピーをOFFにする。必要
pop
rts
;----------------------------------------------------------------
;行を消去する
;<d0.w:上端の行座標
;<d1.w:下端の行座標
putc_clear_rows:
push d2-d5
moveq.l #0,d2 ;左端の桁座標
move.w BIOS_CONSOLE_RIGHT.w,d3 ;右端の桁座標
moveq.l #0,d4 ;左端の桁座標の端数
moveq.l #7,d5 ;右端の桁座標の端数
bsr putc_clear ;消去する
pop
rts
;----------------------------------------------------------------
;消去する
; 消去は空白の描画と同じ。背景色で塗り潰す
; 文字属性 文字色 背景色
; 0 黒 黒
; 1 水色 黒
; 2 黄色 黒
; 3 白 黒
; 4 太字 黒 黒
; 5 太字 水色 黒
; 6 太字 黄色 黒
; 7 太字 白 黒
; 8 反転 黒 黒
; 9 反転 黒 水色
; 10 反転 黒 黄色
; 11 反転 黒 白
; 12 反転 太字 黒 黒
; 13 反転 太字 黒 水色
; 14 反転 太字 黒 黄色
; 15 反転 太字 黒 白
;<d0.w:上端の行座標
;<d1.w:下端の行座標
;<d2.w:左端の桁座標
;<d3.w:右端の桁座標
;<d4.w:左端の桁座標の端数。0~7。これを含む
;<d5.w:右端の桁座標の端数。0~7。これを含む
putc_clear:
push d0-d7/a0-a3
;----------------
;ラスタ数を求める
sub.w d0,d1 ;下端の行座標-上端の行座標=行数-1
addq.w #1,d1 ;行数
lsl.w #4,d1 ;16*行数=ラスタ数
subq.w #1,d1 ;ラスタ数-1
movea.w d1,a3
;<a3.w:ラスタ数-1
;?d1
;----------------
;アドレスを求める
swap.w d0
clr.w d0 ;65536*行座標
lsr.l #5,d0 ;128*16*行座標
add.l BIOS_CONSOLE_OFFSET.w,d0 ;上端の行の左上のアドレスのオフセット
add.l #$00E00000,d0 ;上端の行の左上のアドレス
ext.l d2
ext.l d3
add.l d0,d2 ;左上のアドレス
add.l d0,d3 ;右上のアドレス
;<d2.l:左上のアドレス
;<d3.l:右上のアドレス
;?d0
;----------------
;アドレスを偶数にする
; 桁座標ではなくアドレスを偶数にする
; _B_CONSOLはコンソールの左端のアドレスを偶数に制限していない
bclr.l #0,d2
if ne
addq.w #8,d4
endif
;<d2.l:左上のアドレス。偶数
;<d4.w:左端の桁座標の端数。0~15
bclr.l #0,d3
if ne
addq.w #8,d5
endif
;<d3.l:右上のアドレス。偶数
;<d5.w:右端の桁座標の端数。0~15
movea.l d2,a2
;<a2.l:左上のアドレス。偶数
;----------------
;ワード数を求める
sub.w d2,d3 ;右端のアドレス-左端のアドレス=2*(ワード数-1)
lsr.w #1,d3 ;ワード数-1
;<d3.w:ワード数-1
;?d2
;----------------
;マスクを作る
moveq.l #-1,d6
move.w #$8000,d7
lsr.w d4,d6 ;左端の書き込む部分が1のマスク。$FFFF,$7FFF,…,$0003,$0001
asr.w d5,d7 ;右端の書き込む部分が1のマスク。$8000,$C000,…,$FFFE,$FFFF
;<d6.w:左端の書き込む部分が1のマスク。$FFFF,$7FFF,…,$0003,$0001
;<d7.w:右端の書き込む部分が1のマスク。$8000,$C000,…,$FFFE,$FFFF
;?d4-d5
;----------------
;データを作る
moveq.l #%1111,d0
and.b BIOS_ATTRIBUTE_1.w,d0 ;プレーン##
; 111111
; 5432109876543210
move.w #%1100110000000000,d2 ;背景色が黄色または白。プレーン1を塗り潰す
btst.l d0,d2
sne.b d2
ext.w d2
swap.w d2
; 111111
; 5432109876543210
move.w #%1010101000000000,d2 ;背景色が水色または白。プレーン0を塗り潰す
btst.l d0,d2
sne.b d2
ext.w d2
;<d2.l:プレーン1のデータ<<16|プレーン0のデータ
;----------------
;1ワードか1ワードではないか
if <tst.w d3>,eq
;----------------
;1ワードのとき
and.w d7,d6
;<d6.w:書き込む部分が1のマスク
and.w d6,d2
swap.w d2
and.w d6,d2
swap.w d2
;<d2.l:プレーン1のデータ<<16|プレーン0のデータ
not.w d6
;<d6.w:書き込まない部分が1のマスク
do ;プレーンのループ
movea.l a2,a0 ;左上のアドレス→左端のアドレス
move.w a3,d1 ;ラスタ数-1
for d1 ;ラスタのループ
move.w (a0),d0
and.w d6,d0 ;マスク
or.w d2,d0 ;データ
move.w d0,(a0)
lea.l 128(a0),a0 ;次の左端のアドレス
next
swap.w d2 ;次のプレーンのデータ
adda.l #128*1024,a2 ;次のプレーンの左上のアドレス
while <cmpa.l #$00E40000,a2>,lo
else
;----------------
;1ワードではないとき
subq.w #1,d3
;<d3.w:左端と右端の間のワード数。0~
move.l d2,d4
move.l d2,d5
;<d4.l:プレーン1のデータ<<16|プレーン0のデータ
;<d5.l:プレーン1のデータ<<16|プレーン0のデータ
and.w d6,d4
and.w d7,d5
swap.w d4
swap.w d5
and.w d6,d4
and.w d7,d5
swap.w d4
swap.w d5
;<d4.l:プレーン1の左端のデータ<<16|プレーン0の左端のデータ
;<d5.l:プレーン1の右端のデータ<<16|プレーン0の右端のデータ
not.w d6
not.w d7
;<d6.w:左端の書き込まない部分が1のマスク。$0000,$8000,…,$FFFC,$FFFE
;<d7.w:右端の書き込まない部分が1のマスク。$7FFF,$3FFF,…,$0001,$0000
do ;プレーンのループ
movea.l a2,a1 ;左上のアドレス→左端のアドレス
move.w a3,d1 ;ラスタ数-1
for d1 ;ラスタのループ
movea.l a1,a0 ;左端のアドレス→桁のアドレス
;左端
move.w (a0),d0
and.w d6,d0 ;左端のマスク
or.w d4,d0 ;左端のデータ
move.w d0,(a0)+
;左端と右端の間
move.w d3,d0 ;左端と右端の間のワード数。0~
forcontinue d0
move.w d2,(a0)+ ;データ
next
;右端
move.w (a0),d0
and.w d7,d0 ;右端のマスク
or.w d5,d0 ;右端のデータ
move.w d0,(a0)+
lea.l 128(a1),a1 ;次の左端のアドレス
next
swap.w d2 ;次のプレーンのデータ
swap.w d4 ;次のプレーンの左端のデータ
swap.w d5 ;次のプレーンの右端のデータ
adda.l #128*1024,a2 ;次のプレーンの左上のアドレス
while <cmpa.l #$00E40000,a2>,lo
endif
pop
rts
;----------------------------------------------------------------
;プロポーショナルフォント($20~$82)
proportional_font:
.dc.w 6 ;$20
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$21 !
.dc.w %0000000000000000
.dc.w %0010000000000000
.dc.w %0111000000000000
.dc.w %0111000000000000
.dc.w %0111000000000000
.dc.w %0111000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0010000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$22 ”
.dc.w %0000000000000000
.dc.w %0110011000000000
.dc.w %0110011000000000
.dc.w %0010001000000000
.dc.w %0010001000000000
.dc.w %0100010000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$23 #
.dc.w %0000000000000000
.dc.w %0001001000000000
.dc.w %0001001000000000
.dc.w %0001001000000000
.dc.w %0111111100000000
.dc.w %0010010000000000
.dc.w %0010010000000000
.dc.w %0010010000000000
.dc.w %1111111000000000
.dc.w %0100100000000000
.dc.w %0100100000000000
.dc.w %0100100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$24 $
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0111110000000000
.dc.w %1001001000000000
.dc.w %1101000000000000
.dc.w %0111100000000000
.dc.w %0011110000000000
.dc.w %0001011000000000
.dc.w %1001001000000000
.dc.w %0111110000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$25 %
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %1001000010000000
.dc.w %1001000100000000
.dc.w %1001001000000000
.dc.w %0110010000000000
.dc.w %0000100000000000
.dc.w %0001001100000000
.dc.w %0010010010000000
.dc.w %0100010010000000
.dc.w %1000010010000000
.dc.w %0000001100000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$26 &
.dc.w %0000000000000000
.dc.w %0111000000000000
.dc.w %1000100000000000
.dc.w %1000100000000000
.dc.w %1000100000000000
.dc.w %0101000000000000
.dc.w %0011000000000000
.dc.w %0100100100000000
.dc.w %1000010100000000
.dc.w %1000001000000000
.dc.w %1000010100000000
.dc.w %0111100010000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 5 ;$27 ’
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 5 ;$28 (
.dc.w %0000000000000000
.dc.w %0001000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %1000000000000000
.dc.w %1000000000000000
.dc.w %1000000000000000
.dc.w %1000000000000000
.dc.w %1000000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0010000000000000
.dc.w %0001000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 5 ;$29 )
.dc.w %0000000000000000
.dc.w %1000000000000000
.dc.w %0100000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %1000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$2A *
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0001000000000000
.dc.w %1001001000000000
.dc.w %0101010000000000
.dc.w %0011100000000000
.dc.w %0101010000000000
.dc.w %1001001000000000
.dc.w %0001000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$2B +
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %1111111000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 5 ;$2C ,
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %0000000000000000
.dc.w 6 ;$2D -
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1111100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$2E .
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0011000000000000
.dc.w %0011000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$2F /
.dc.w %0000000000000000
.dc.w %0000100000000000
.dc.w %0000100000000000
.dc.w %0000100000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %1000000000000000
.dc.w %1000000000000000
.dc.w %1000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$30 0
.dc.w %0000000000000000
.dc.w %0011110000000000
.dc.w %0110011000000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %0110011000000000
.dc.w %0011110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$31 1
.dc.w %0000000000000000
.dc.w %0000100000000000
.dc.w %0001100000000000
.dc.w %0011100000000000
.dc.w %0111100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0111111000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$32 2
.dc.w %0000000000000000
.dc.w %0011110000000000
.dc.w %0110011000000000
.dc.w %1100001100000000
.dc.w %0000001100000000
.dc.w %0000011000000000
.dc.w %0000110000000000
.dc.w %0001100000000000
.dc.w %0011000000000000
.dc.w %0110000000000000
.dc.w %1100000000000000
.dc.w %1111111100000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$33 3
.dc.w %0000000000000000
.dc.w %0011110000000000
.dc.w %0110011000000000
.dc.w %1100001100000000
.dc.w %0000001100000000
.dc.w %0000011000000000
.dc.w %0001110000000000
.dc.w %0000011000000000
.dc.w %0000001100000000
.dc.w %1100001100000000
.dc.w %0110011000000000
.dc.w %0011110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$34 4
.dc.w %0000000000000000
.dc.w %0000001000000000
.dc.w %0000011000000000
.dc.w %0000111000000000
.dc.w %0001111000000000
.dc.w %0011011000000000
.dc.w %0110011000000000
.dc.w %1100011000000000
.dc.w %1111111100000000
.dc.w %0000011000000000
.dc.w %0000011000000000
.dc.w %0000011000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$35 5
.dc.w %0000000000000000
.dc.w %0111111000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0111110000000000
.dc.w %0000011000000000
.dc.w %0000001100000000
.dc.w %0000001100000000
.dc.w %1100001100000000
.dc.w %0110011000000000
.dc.w %0011110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$36 6
.dc.w %0000000000000000
.dc.w %0000110000000000
.dc.w %0001100000000000
.dc.w %0011000000000000
.dc.w %0110000000000000
.dc.w %0111110000000000
.dc.w %1110011000000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %0110011000000000
.dc.w %0011110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$37 7
.dc.w %0000000000000000
.dc.w %1111111100000000
.dc.w %1100001100000000
.dc.w %1100011000000000
.dc.w %0000011000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$38 8
.dc.w %0000000000000000
.dc.w %0011110000000000
.dc.w %0110011000000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %0110011000000000
.dc.w %0011110000000000
.dc.w %0110011000000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %0110011000000000
.dc.w %0011110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$39 9
.dc.w %0000000000000000
.dc.w %0011110000000000
.dc.w %0110011000000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %0110011100000000
.dc.w %0011111000000000
.dc.w %0000011000000000
.dc.w %0000110000000000
.dc.w %0001100000000000
.dc.w %0011000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 5 ;$3A :
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 5 ;$3B ;
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$3C <
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000100000000000
.dc.w %0001000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %1000000000000000
.dc.w %0100000000000000
.dc.w %0010000000000000
.dc.w %0001000000000000
.dc.w %0000100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$3D =
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1111100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1111100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$3E >
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1000000000000000
.dc.w %0100000000000000
.dc.w %0010000000000000
.dc.w %0001000000000000
.dc.w %0000100000000000
.dc.w %0001000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %1000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$3F ?
.dc.w %0000000000000000
.dc.w %1111000000000000
.dc.w %0011100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0100000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$40 @
.dc.w %0000000000000000
.dc.w %0001111100000000
.dc.w %0010000010000000
.dc.w %0100000001000000
.dc.w %1000111001000000
.dc.w %1001001001000000
.dc.w %1001001001000000
.dc.w %1001001001000000
.dc.w %1001110110000000
.dc.w %1000000000000000
.dc.w %0100000000000000
.dc.w %0011111110000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$41 A
.dc.w %0000000000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0001011000000000
.dc.w %0001011000000000
.dc.w %0001011000000000
.dc.w %0010001100000000
.dc.w %0010001100000000
.dc.w %0011111100000000
.dc.w %0100000110000000
.dc.w %0100000110000000
.dc.w %1110001111000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$42 B
.dc.w %0000000000000000
.dc.w %1111110000000000
.dc.w %0110011100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110011000000000
.dc.w %0111111000000000
.dc.w %0110001100000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110001100000000
.dc.w %1111110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$43 C
.dc.w %0000000000000000
.dc.w %0001111010000000
.dc.w %0110000110000000
.dc.w %1100000010000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %1100000010000000
.dc.w %0110000100000000
.dc.w %0001111000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$44 D
.dc.w %0000000000000000
.dc.w %1111110000000000
.dc.w %0110001100000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110001100000000
.dc.w %1111110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$45 E
.dc.w %0000000000000000
.dc.w %1111111110000000
.dc.w %0110000110000000
.dc.w %0110000010000000
.dc.w %0110000000000000
.dc.w %0110001000000000
.dc.w %0111111000000000
.dc.w %0110001000000000
.dc.w %0110000000000000
.dc.w %0110000010000000
.dc.w %0110000110000000
.dc.w %1111111110000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$46 F
.dc.w %0000000000000000
.dc.w %1111111110000000
.dc.w %0110000110000000
.dc.w %0110000010000000
.dc.w %0110000000000000
.dc.w %0110001000000000
.dc.w %0111111000000000
.dc.w %0110001000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %1111000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$47 G
.dc.w %0000000000000000
.dc.w %0001111010000000
.dc.w %0110000110000000
.dc.w %1100000010000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %1100001111000000
.dc.w %1100000010000000
.dc.w %1100000010000000
.dc.w %0110000100000000
.dc.w %0001111000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$48 H
.dc.w %0000000000000000
.dc.w %1111001111000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0111111110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %1111001111000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 7 ;$49 I
.dc.w %0000000000000000
.dc.w %1111110000000000
.dc.w %0011000000000000
.dc.w %0011000000000000
.dc.w %0011000000000000
.dc.w %0011000000000000
.dc.w %0011000000000000
.dc.w %0011000000000000
.dc.w %0011000000000000
.dc.w %0011000000000000
.dc.w %0011000000000000
.dc.w %1111110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$4A J
.dc.w %0000000000000000
.dc.w %0001111000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %1100110000000000
.dc.w %0011000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$4B K
.dc.w %0000000000000000
.dc.w %1111001110000000
.dc.w %0110000100000000
.dc.w %0110001000000000
.dc.w %0110010000000000
.dc.w %0110100000000000
.dc.w %0111110000000000
.dc.w %0110011000000000
.dc.w %0110011000000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %1111011110000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$4C L
.dc.w %0000000000000000
.dc.w %1111000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000010000000
.dc.w %0110000110000000
.dc.w %1111111110000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 13 ;$4D M
.dc.w %0000000000000000
.dc.w %1110000001110000
.dc.w %0110000001100000
.dc.w %0111000001100000
.dc.w %0111000011100000
.dc.w %0111100011100000
.dc.w %0101100101100000
.dc.w %0101110101100000
.dc.w %0100111001100000
.dc.w %0100111001100000
.dc.w %0100010001100000
.dc.w %1110010011110000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 12 ;$4E N
.dc.w %0000000000000000
.dc.w %1100000011100000
.dc.w %0110000001000000
.dc.w %0111000001000000
.dc.w %0111100001000000
.dc.w %0101110001000000
.dc.w %0100111001000000
.dc.w %0100011101000000
.dc.w %0100001111000000
.dc.w %0100000111000000
.dc.w %0100000011000000
.dc.w %1110000001000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$4F O
.dc.w %0000000000000000
.dc.w %0001111000000000
.dc.w %0110000110000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %0110000110000000
.dc.w %0001111000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$50 P
.dc.w %0000000000000000
.dc.w %1111111000000000
.dc.w %0110000110000000
.dc.w %0110000011000000
.dc.w %0110000011000000
.dc.w %0110000011000000
.dc.w %0110000110000000
.dc.w %0111111000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %1111000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$51 Q
.dc.w %0000000000000000
.dc.w %0001111000000000
.dc.w %0110000110000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %1100000011000000
.dc.w %1101110011000000
.dc.w %1111011110000000
.dc.w %0110001100000000
.dc.w %0001111100000000
.dc.w %0000000110000000
.dc.w %0000000011000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$52 R
.dc.w %0000000000000000
.dc.w %1111111000000000
.dc.w %0110000110000000
.dc.w %0110000011000000
.dc.w %0110000011000000
.dc.w %0110000011000000
.dc.w %0110000110000000
.dc.w %0111111000000000
.dc.w %0110111000000000
.dc.w %0110011100000000
.dc.w %0110001110000000
.dc.w %1111000111000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$53 S
.dc.w %0000000000000000
.dc.w %0001110100000000
.dc.w %0110001100000000
.dc.w %1100000100000000
.dc.w %1110000000000000
.dc.w %0111000000000000
.dc.w %0011110000000000
.dc.w %0000111000000000
.dc.w %0000011100000000
.dc.w %1000001100000000
.dc.w %1100011000000000
.dc.w %1011100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$54 T
.dc.w %0000000000000000
.dc.w %1111111111000000
.dc.w %1100110011000000
.dc.w %1000110001000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0011111100000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$55 U
.dc.w %0000000000000000
.dc.w %1111000111000000
.dc.w %0110000010000000
.dc.w %0110000010000000
.dc.w %0110000010000000
.dc.w %0110000010000000
.dc.w %0110000010000000
.dc.w %0110000010000000
.dc.w %0110000010000000
.dc.w %0110000010000000
.dc.w %0011000100000000
.dc.w %0000111000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$56 V
.dc.w %0000000000000000
.dc.w %1111000111000000
.dc.w %0110000010000000
.dc.w %0110000010000000
.dc.w %0011000100000000
.dc.w %0011000100000000
.dc.w %0011000100000000
.dc.w %0001101000000000
.dc.w %0001101000000000
.dc.w %0001101000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 16 ;$57 W
.dc.w %0000000000000000
.dc.w %1111000110001110
.dc.w %0110000110000100
.dc.w %0011000111000100
.dc.w %0011000111000100
.dc.w %0011001011001000
.dc.w %0001101001101000
.dc.w %0001101001101000
.dc.w %0001101001101000
.dc.w %0000110000110000
.dc.w %0000110000110000
.dc.w %0000110000110000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$58 X
.dc.w %0000000000000000
.dc.w %1111000111000000
.dc.w %0110000010000000
.dc.w %0011000100000000
.dc.w %0011001000000000
.dc.w %0001110000000000
.dc.w %0000110000000000
.dc.w %0000111000000000
.dc.w %0001001100000000
.dc.w %0010001100000000
.dc.w %0100000110000000
.dc.w %1110001111000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$59 Y
.dc.w %0000000000000000
.dc.w %1111000111000000
.dc.w %0110000010000000
.dc.w %0011000100000000
.dc.w %0011000100000000
.dc.w %0001101000000000
.dc.w %0001101000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0000110000000000
.dc.w %0001111000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 11 ;$5A Z
.dc.w %0000000000000000
.dc.w %1111111111000000
.dc.w %1100000011000000
.dc.w %1000000110000000
.dc.w %0000001100000000
.dc.w %0000011000000000
.dc.w %0000110000000000
.dc.w %0001100000000000
.dc.w %0011000000000000
.dc.w %0110000001000000
.dc.w %1100000011000000
.dc.w %1111111111000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$5B [
.dc.w %0000000000000000
.dc.w %0111000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0111000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$5C ¥
.dc.w %0000000000000000
.dc.w %1000001000000000
.dc.w %1000001000000000
.dc.w %0100010000000000
.dc.w %0100010000000000
.dc.w %0010100000000000
.dc.w %0010100000000000
.dc.w %0111110000000000
.dc.w %0001000000000000
.dc.w %0111110000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$5D ]
.dc.w %0000000000000000
.dc.w %0111000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0111000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$5E ^
.dc.w %0000000000000000
.dc.w %0001000000000000
.dc.w %0010100000000000
.dc.w %0100010000000000
.dc.w %1000001000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$5F _
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1111100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 5 ;$60 `
.dc.w %0000000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$61 a
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0111110000000000
.dc.w %1100111000000000
.dc.w %0000011000000000
.dc.w %0011111000000000
.dc.w %0110011000000000
.dc.w %1100011000000000
.dc.w %1100111000000000
.dc.w %0111011100000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$62 b
.dc.w %0000000000000000
.dc.w %1110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110111000000000
.dc.w %0111001100000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0110000110000000
.dc.w %0111001100000000
.dc.w %1101111000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$63 c
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0011110000000000
.dc.w %0110011000000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %0110011000000000
.dc.w %0011110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$64 d
.dc.w %0000000000000000
.dc.w %0000011100000000
.dc.w %0000001100000000
.dc.w %0000001100000000
.dc.w %0011101100000000
.dc.w %0110011100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %0110011100000000
.dc.w %0011101110000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$65 e
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0011110000000000
.dc.w %0110011000000000
.dc.w %1100001000000000
.dc.w %1111111000000000
.dc.w %1100000000000000
.dc.w %1100000000000000
.dc.w %0110011000000000
.dc.w %0011110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 7 ;$66 f
.dc.w %0000000000000000
.dc.w %0011100000000000
.dc.w %0110110000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %1111100000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %1111000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$67 g
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0111110100000000
.dc.w %1100011000000000
.dc.w %1100011000000000
.dc.w %1100011000000000
.dc.w %0111110000000000
.dc.w %1100000000000000
.dc.w %0111111000000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %0111111000000000
.dc.w %0000000000000000
.dc.w 10 ;$68 h
.dc.w %0000000000000000
.dc.w %1110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110111000000000
.dc.w %0111011100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %1111011110000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 5 ;$69 i
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0000000000000000
.dc.w %1110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %1111000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$6A j
.dc.w %0000000000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0000000000000000
.dc.w %0011100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %0001100000000000
.dc.w %1101100000000000
.dc.w %0111000000000000
.dc.w %0000000000000000
.dc.w 9 ;$6B k
.dc.w %0000000000000000
.dc.w %1110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110111000000000
.dc.w %0110010000000000
.dc.w %0110100000000000
.dc.w %0111000000000000
.dc.w %0111100000000000
.dc.w %0110110000000000
.dc.w %0110011000000000
.dc.w %1111011100000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 5 ;$6C l
.dc.w %0000000000000000
.dc.w %1110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %1111000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 15 ;$6D m
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1101111011110000
.dc.w %0111011110111000
.dc.w %0110001100011000
.dc.w %0110001100011000
.dc.w %0110001100011000
.dc.w %0110001100011000
.dc.w %0110001100011000
.dc.w %1111011110111100
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$6E n
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1110111000000000
.dc.w %0111011100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %1111011110000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$6F o
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0011110000000000
.dc.w %0110011000000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %1100001100000000
.dc.w %0110011000000000
.dc.w %0011110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$70 p
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1110111000000000
.dc.w %0111011100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0111011100000000
.dc.w %0110111000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %1111000000000000
.dc.w %0000000000000000
.dc.w 9 ;$71 q
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0111011100000000
.dc.w %1110111000000000
.dc.w %1100011000000000
.dc.w %1100011000000000
.dc.w %1100011000000000
.dc.w %1100011000000000
.dc.w %1110111000000000
.dc.w %0111011000000000
.dc.w %0000011000000000
.dc.w %0000011000000000
.dc.w %0000111100000000
.dc.w %0000000000000000
.dc.w 9 ;$72 r
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1110111000000000
.dc.w %0111001100000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %1111000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$73 s
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0111101000000000
.dc.w %1100011000000000
.dc.w %1100001000000000
.dc.w %0111100000000000
.dc.w %0011110000000000
.dc.w %1000011000000000
.dc.w %1100011000000000
.dc.w %1011110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 7 ;$74 t
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %1111100000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110000000000000
.dc.w %0110110000000000
.dc.w %0011100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$75 u
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1110011100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110001100000000
.dc.w %0110011100000000
.dc.w %0011110110000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 9 ;$76 v
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1111011100000000
.dc.w %0110001000000000
.dc.w %0110010000000000
.dc.w %0011010000000000
.dc.w %0011100000000000
.dc.w %0011100000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 14 ;$77 w
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1111001000111000
.dc.w %0110001100010000
.dc.w %0110001100010000
.dc.w %0011010110100000
.dc.w %0011010110100000
.dc.w %0001110011100000
.dc.w %0001100011000000
.dc.w %0000100001000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$78 x
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1111011100000000
.dc.w %0110001000000000
.dc.w %0011010000000000
.dc.w %0001100000000000
.dc.w %0001110000000000
.dc.w %0010011000000000
.dc.w %0100001100000000
.dc.w %1110011110000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 10 ;$79 y
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1111001110000000
.dc.w %0110000100000000
.dc.w %0110000100000000
.dc.w %0011001000000000
.dc.w %0011001000000000
.dc.w %0001110000000000
.dc.w %0001110000000000
.dc.w %0000100000000000
.dc.w %0000100000000000
.dc.w %0001000000000000
.dc.w %0110000000000000
.dc.w %0000000000000000
.dc.w 8 ;$7A z
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %1111111000000000
.dc.w %1000011000000000
.dc.w %0000110000000000
.dc.w %0001100000000000
.dc.w %0011000000000000
.dc.w %0110000000000000
.dc.w %1100001000000000
.dc.w %1111111000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$7B {
.dc.w %0000000000000000
.dc.w %0001100000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0100000000000000
.dc.w %1000000000000000
.dc.w %0100000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0001100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$7C |
.dc.w %0000000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$7D }
.dc.w %0000000000000000
.dc.w %1100000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0001000000000000
.dc.w %0000100000000000
.dc.w %0001000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %1100000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$7E  ̄
.dc.w %0000000000000000
.dc.w %1111100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$7F DL
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$80 \
.dc.w %0000000000000000
.dc.w %1000000000000000
.dc.w %1000000000000000
.dc.w %1000000000000000
.dc.w %0100000000000000
.dc.w %0100000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0001000000000000
.dc.w %0001000000000000
.dc.w %0000100000000000
.dc.w %0000100000000000
.dc.w %0000100000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 8 ;$81 ~
.dc.w %0000000000000000
.dc.w %0110000000000000
.dc.w %1001001000000000
.dc.w %0000110000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w 6 ;$82 �
.dc.w %0000000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0010000000000000
.dc.w %0000000000000000
.dc.w %0000000000000000
;----------------------------------------------------------------
;デバイスドライバの末尾
device_tail:
;----------------------------------------------------------------
;デバイスコマンド0 初期化
initialize:
;パラメータを確認する
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 ;-,/の後に文字がない
st.b option_flag ;オプションあり
bsr tolower
if <cmp.b #'f',d0>,eq ;-f
st.b fixed_flag
sf.b proportional_flag
elif <cmp.b #'p',d0>,eq ;-p
sf.b fixed_flag
st.b proportional_flag
elif <cmp.b #'q',d0>,eq ;-q
st.b quiet_flag
sf.b verbose_flag
elif <cmp.b #'s',d0>,eq ;-s
st.b sample_flag
elif <cmp.b #'v',d0>,eq ;-v
sf.b quiet_flag
st.b verbose_flag
else
goto parameter_error
endif
tst.b (a0)+ ;区切り
goto ne,parameter_error ;余分な文字がある
start
move.b (a0)+,d0
while ne
;ワークエリアを初期化する
bsr initialize_workarea ;ワークエリアを初期化する
;ベクタを変更する
IOCS _OS_CUROF
lea.l vector_table(pc),a0 ;ベクタテーブル
bsr set_vector ;ベクタを変更する
IOCS _OS_CURON
;固定ピッチまたはプロポーショナルピッチを設定する
if <tst.b fixed_flag>,ne ;固定ピッチ
bclr.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w
elif <tst.b proportional_flag>,ne ;プロポーショナルピッチ
bset.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w
endif
;改行とタイトルを表示する
if <tst.b quiet_flag>,eq
lea.l crlf_title(pc),a0
bsr print
endif
;サンプルを表示する
if <tst.b sample_flag>,ne
lea.l sample(pc),a0
bsr print
endif
;デバイスドライバの末尾を設定する
move.l #device_tail,14(a5) ;デバイスドライバの末尾
;デバイスドライバを組み込む
moveq.l #0,d0
rts
;パラメータエラー
parameter_error:
;改行とタイトルとエラーメッセージを表示する
lea.l crlf_title(pc),a0
bsr print
lea.l parameter_message(pc),a0
bsr print
;デバイスドライバを組み込まない
move.w #ABORT|MISCELLANEOUS_ERROR,d0 ;中止(A) エラーが発生しました
rts
;----------------------------------------------------------------
;実行開始
execution_start:
;オプションを確認する
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 ;-,/の後に文字がない
st.b option_flag ;オプションあり
bsr tolower
if <cmp.b #'f',d0>,eq ;-f
st.b fixed_flag
sf.b proportional_flag
elif <cmp.b #'k',d0>,eq ;-k
st.b keeppr_flag
sf.b release_flag
elif <cmp.b #'p',d0>,eq ;-p
sf.b fixed_flag
st.b proportional_flag
elif <cmp.b #'q',d0>,eq ;-q
st.b quiet_flag
sf.b verbose_flag
elif <cmp.b #'r',d0>,eq ;-r
sf.b keeppr_flag
st.b release_flag
elif <cmp.b #'s',d0>,eq ;-s
st.b sample_flag
elif <cmp.b #'v',d0>,eq ;-v
sf.b quiet_flag
st.b verbose_flag
else
goto usage_exit
endif
move.b (a0),d0
break eq
bsr isspace
goto ne,usage_exit ;余分な文字がある
start
bsr nonspace
while ne
goto <tst.b option_flag>,eq,usage_exit ;オプションなし
;スーパーバイザモードへ移行する
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デバイスドライバを探す。必ずある
;<a2.l:NULデバイスドライバの先頭
dostart
lea.l magic-program_head(a2),a0 ;常駐部分のマジック
lea.l magic(pc),a1 ;自分のマジック
gotoand <cmpm.l (a0)+,(a1)+>,eq,<cmpm.l (a0)+,(a1)+>,eq,device_found ;一致したら終了
start
movea.l a2,a3 ;デバイスドライバ→直前のデバイスドライバ
movea.l DH_NEXT(a2),a2 ;次のデバイスドライバ
while <cmpa.l #-1,a2>,ne
suba.l a2,a2
device_found:
;<a2.l:デバイスドライバの先頭,0=デバイスドライバがない
;<a3.l:(デバイスドライバがあるとき)直前のデバイスドライバ,(デバイスドライバがないとき)最後のデバイスドライバ
;----------------------------------------------------------------
;常駐プログラムを探す
lea.l program_head(pc),a4 ;自分の先頭
dostart
movea.l d0,a4
lea.l MM_PROGRAM(a4),a4 ;常駐部分の先頭
lea.l magic+8-program_head(a4),a0 ;常駐部分のマジックの末尾
if <cmpa.l MM_TAIL-MM_PROGRAM(a4),a0>,ls ;メモリブロックの長さを確認する
lea.l magic-program_head(a4),a0 ;常駐部分のマジック
lea.l magic(pc),a1 ;自分のマジック
gotoand <cmpm.l (a0)+,(a1)+>,eq,<cmpm.l (a0)+,(a1)+>,eq,keeppr_found ;一致したら終了
endif
start
move.l MM_PREV-MM_PROGRAM(a4),d0 ;直前のメモリ管理テーブル
while ne
lea.l program_head(pc),a4 ;自分の先頭
dostart
movea.l d0,a4
lea.l MM_PROGRAM(a4),a4 ;常駐部分の先頭
lea.l magic+8-program_head(a4),a0 ;常駐部分のマジックの末尾
if <cmpa.l MM_TAIL-MM_PROGRAM(a4),a0>,ls ;メモリブロックの長さを確認する
lea.l magic-program_head(a4),a0 ;常駐部分のマジック
lea.l magic(pc),a1 ;自分のマジック
gotoand <cmpm.l (a0)+,(a1)+>,eq,<cmpm.l (a0)+,(a1)+>,eq,keeppr_found ;一致したら終了
endif
start
move.l MM_NEXT-MM_PROGRAM(a4),d0 ;直後のメモリ管理テーブル
while ne
suba.l a4,a4
keeppr_found:
;<a4.l:常駐プログラムの先頭,0=常駐プログラムがない
;----------------------------------------------------------------
move.l a2,d0 ;デバイスドライバの先頭
if eq ;デバイスドライバがない
;----------------------------------------------------------------
;常駐していない
if <tst.b keeppr_flag>,eq ;常駐しない
;ユーザモードへ復帰する
usermode
;タイトルとメッセージを表示する
if <tst.b quiet_flag>,eq
lea.l title(pc),a0
bsr print
endif
lea.l not_installed_message(pc),a0
bsr eprint
;エラー終了する
move.w #1,-(sp)
DOS _EXIT2
endif
;----------------------------------------------------------------
;常駐する
;ワークエリアを初期化する
bsr initialize_workarea ;ワークエリアを初期化する
;固定ピッチまたはプロポーショナルピッチを設定する
if <tst.b fixed_flag>,ne ;固定ピッチ
bclr.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w
elif <tst.b proportional_flag>,ne ;プロポーショナルピッチ
bset.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w
endif
;ベクタを変更する
IOCS _OS_CUROF
lea.l vector_table(pc),a0 ;ベクタテーブル
bsr set_vector ;ベクタを変更する
IOCS _OS_CURON
;デバイスドライバを接続する
move.l #program_head,(a3) ;最後のデバイスドライバの次のデバイスドライバを自分にする
bsr reset_con_device ;標準入出力に現在のCONデバイスを接続し直す
;ユーザモードへ復帰する
usermode
;タイトルとメッセージを表示する
if <tst.b quiet_flag>,eq
lea.l title(pc),a0
bsr print
lea.l install_message(pc),a0
bsr print
endif
;サンプルを表示する
if <tst.b sample_flag>,ne
lea.l sample(pc),a0
bsr print
endif
;常駐終了する
clr.w -(sp)
move.l #device_tail-program_head,-(sp)
DOS _KEEPPR
else ;デバイスドライバがある
;----------------------------------------------------------------
;常駐している
if <tst.b keeppr_flag>,ne ;常駐する
;ユーザモードへ復帰する
usermode
;タイトルとメッセージを表示する
if <tst.b quiet_flag>,eq
lea.l title(pc),a0
bsr print
endif
lea.l already_message(pc),a0
bsr eprint
;エラー終了する
move.w #1,-(sp)
DOS _EXIT2
endif
;----------------------------------------------------------------
;常駐しない
;固定ピッチまたはプロポーショナルピッチを設定する
if <tst.b fixed_flag>,ne ;固定ピッチ
bclr.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w
elif <tst.b proportional_flag>,ne ;プロポーショナルピッチ
bset.b #BIOS_PROPORTIONAL_BIT,BIOS_ATTRIBUTE_2.w
endif
;サンプルを表示する
if <tst.b sample_flag>,ne
lea.l sample(pc),a0
bsr print
endif
if <tst.b release_flag>,eq ;解除しない
;ユーザモードへ復帰する
usermode
;正常終了する
DOS _EXIT
endif
;----------------------------------------------------------------
;解除する
;ベクタを確認する
lea.l (vector_table-program_head)(a2),a0 ;常駐部分のベクタテーブル
bsr check_vector ;ベクタを確認する
if ne ;ベクタが変更されている
;ユーザモードへ復帰する
usermode
;タイトルとメッセージを表示する
if <tst.b quiet_flag>,eq
lea.l title(pc),a0
bsr print
endif
lea.l vector_message(pc),a0
bsr eprint
;エラー終了する
move.w #1,-(sp)
DOS _EXIT2
endif
;ベクタが変更されていない
;デバイスドライバを切り離す
move.l (a2),(a3) ;前のデバイスドライバに次のデバイスドライバを繋ぐ
bsr reset_con_device ;標準入出力に現在のCONデバイスを接続し直す
;ベクタを復元する
IOCS _OS_CUROF
lea.l (vector_table-program_head)(a2),a0 ;常駐部分のベクタテーブル
bsr release_vector ;ベクタを復元する
IOCS _OS_CURON
;常駐プログラムを開放する
move.l a4,d0 ;常駐プログラムの先頭
if ne ;常駐プログラムがある
;常駐プログラムを開放する
pea.l MM_SIZE-MM_PROGRAM(a4) ;常駐プログラムのメモリブロックの先頭
DOS _MFREE
addq.l #4,sp
endif
;ユーザモードへ復帰する
usermode
;タイトルとメッセージを表示する
if <tst.b quiet_flag>,eq
lea.l title(pc),a0
bsr print
lea.l release_message(pc),a0
bsr print
endif
;正常終了する
DOS _EXIT
endif
;----------------------------------------------------------------
;使用法を表示する
usage_exit:
if <tst.b quiet_flag>,eq
lea.l title_usage(pc),a0
bsr more
endif
;正常終了する
DOS _EXIT
;----------------------------------------------------------------
;ベクタを変更する
;<a0.l:ベクタテーブル
set_vector:
push d0/a0-a1
dostart
movea.w d0,a1 ;オフセット
move.l (a1),d0
move.l (a0)+,(a1) ;新しいベクタ
move.l d0,(a0)+ ;古いベクタ
start
move.w (a0)+,d0
while ne
pop
rts
;----------------------------------------------------------------
;ベクタを確認する
;<a0.l:常駐部分のベクタテーブル
;>ccr:eq=ベクタは変更されていない,ne=ベクタが変更されている
check_vector:
push d0/a0-a1
dostart
movea.w d0,a1 ;オフセット
move.l (a1),d0
break <cmp.l (a0)+,d0>,ne ;新しいベクタが現在のベクタと一致しなければ失敗
addq.l #4,a0 ;古いベクタを読み飛ばす
start
move.w (a0)+,d0
while ne
pop
rts
;----------------------------------------------------------------
;ベクタを復元する
;<a0.l:常駐部分のベクタテーブル
release_vector:
push d0/a0-a1
dostart
movea.w d0,a1 ;オフセット
addq.l #4,a0 ;新しいベクタを読み飛ばす
move.l (a0)+,(a1) ;古いベクタ
start
move.w (a0)+,d0
while ne
pop
rts
;----------------------------------------------------------------
;標準入出力に現在のCONデバイスを接続し直す
reset_con_device:
push d0
clr.w -(sp)
DOS _CLOSE
addq.w #1,(sp)
DOS _CLOSE
addq.w #1,(sp)
DOS _CLOSE
addq.l #2,sp
pop
rts
;----------------------------------------------------------------
;ワークエリアを初期化する
initialize_workarea:
push d0-d1/a0
moveq.l #0,d0
lea.l $0D30.w,a0
move.w #($0DC0-$0D30)/4-1,d1
for d1
move.l d0,(a0)+
next
pop
rts
;----------------------------------------------------------------
;メッセージ
parameter_message: .dc.b '指定できないパラメータです',13,10,0
not_installed_message: .dc.b '常駐していません',13,10,0
install_message: .dc.b '常駐しました',13,10,0
already_message: .dc.b '既に常駐しています',13,10,0
vector_message: .dc.b 'ベクタが変更されています。解除できません',13,10,0
release_message: .dc.b '解除しました',13,10,0
;改行とタイトル
crlf_title: .dc.b 13,10
;タイトル
title: .dc.b TITLE_STRING,' version ',VERSION_STRING,13,10,0
;タイトルと使用法
title_usage: .dc.b TITLE_STRING,' version ',VERSION_STRING,13,10
.dc.b 13,10
.dc.b 'オプション',13,10
.dc.b ' -f 固定ピッチに切り替える',13,10
.dc.b ' -k 常駐する',13,10
.dc.b ' -p プロポーショナルピッチに切り替える',13,10
.dc.b ' -q 表示を減らす',13,10
.dc.b ' -r 解除する',13,10
.dc.b ' -s サンプルを表示する',13,10
.dc.b ' -v 表示を増やす',13,10
.dc.b 13,10
.dc.b '制御文字',13,10
.dc.b ' ^G $07 BL ベルを鳴らす',13,10
.dc.b ' ^H $08 BS カーソルを1桁左へ。左端では1行上の右端へ。上端では何もしない',13,10
.dc.b ' ^I $09 HT カーソルを次のタブ桁へ。なければ1行下の左端へ。下端ではスクロールアップして左端へ',13,10
.dc.b ' ^J $0A LF カーソルを1行下へ。下端ではスクロールアップ',13,10
.dc.b ' ^K $0B VT カーソルを1行上へ。上端では何もしない',13,10
.dc.b ' ^L $0C FF カーソルを1桁右へ。右端では1行下の左端へ。下端ではスクロールアップして左端へ',13,10
.dc.b ' ^M $0D CR カーソルを左端へ',13,10
.dc.b ' ^Z $1A SB 左上から右下まで消去。カーソルを左上へ',13,10
.dc.b ' ^[ $1B EC エスケープシーケンス開始',13,10
.dc.b ' ^^ $1E RS カーソルを左上へ',13,10
.dc.b 13,10
.dc.b 'エスケープシーケンス',13,10
.dc.b ' ^[* 左上から右下まで消去。カーソルを左上へ',13,10
.dc.b ' ^[=rc カーソルをr-$20行,c-$20桁へ。rとcは文字',13,10
.dc.b ' ^[D カーソルを1行下へ。下端ではスクロールアップ',13,10
.dc.b ' ^[E カーソルを1行下の左端へ。下端ではスクロールアップ',13,10
.dc.b ' ^[M カーソルを1行上へ。上端ではスクロールダウン',13,10
.dc.b ' ^[[>5l カーソルON',13,10
.dc.b ' ^[[>5h カーソルOFF',13,10
.dc.b ' ^[[?4l ジャンプスクロール',13,10
.dc.b ' ^[[?4h 8ドットスムーススクロール',13,10
.dc.b ' ^[[n@ カーソルから右にn桁挿入',13,10
.dc.b ' ^[[nA カーソルをn行上へ。上端を超えるときは動かない',13,10
.dc.b ' ^[[nB カーソルをn行下へ。下端で止まる',13,10
.dc.b ' ^[[nC カーソルをn桁右へ。右端で止まる',13,10
.dc.b ' ^[[nD カーソルをn桁左へ。左端で止まる',13,10
.dc.b ' ^[[r;cH カーソルをr-1行,c-1桁へ。下端で止まる。右端で止まる',13,10
.dc.b ' ^[[r;cf カーソルをr-1行,c-1桁へ。下端で止まる。右端で止まる',13,10
.dc.b ' ^[[0J カーソルから右下まで消去する',13,10
.dc.b ' ^[[1J 左上からカーソルまで消去する',13,10
.dc.b ' ^[[2J 左上から右下まで消去する。カーソルを左上へ',13,10
.dc.b ' ^[[0K カーソルから右端まで消去する',13,10
.dc.b ' ^[[1K 左端からカーソルまで消去する',13,10
.dc.b ' ^[[2K 左端から右端まで消去する',13,10
.dc.b ' ^[[nL カーソルから下にn行挿入。カーソルを左端へ',13,10
.dc.b ' ^[[nM カーソルから下をn行削除。カーソルを左端へ',13,10
.dc.b ' ^[[nP カーソルから右をn桁削除',13,10
.dc.b ' ^[[nX カーソルから右をn桁消去',13,10
.dc.b ' ^[[nc 中央寄せ',13,10
.dc.b ' ^[[nl 左寄せ',13,10
.dc.b ' ^[[0m リセット',13,10
.dc.b ' ^[[1m 太字',13,10
.dc.b ' ^[[2m 細字',13,10
.dc.b ' ^[[3m 斜体',13,10
.dc.b ' ^[[4m 下線',13,10
.dc.b ' ^[[7m 反転',13,10
.dc.b ' ^[[9m 取り消し線',13,10
.dc.b ' ^[[21m 波線',13,10
.dc.b ' ^[[22m 太字、細字解除',13,10
.dc.b ' ^[[23m 斜体解除',13,10
.dc.b ' ^[[24m 下線、波線解除',13,10
.dc.b ' ^[[26m プロポーショナル',13,10
.dc.b ' ^[[27m 反転解除',13,10
.dc.b ' ^[[29m 取り消し線解除',13,10
.dc.b ' ^[[30m 黒',13,10
.dc.b ' ^[[31m 水色',13,10
.dc.b ' ^[[32m 黄色',13,10
.dc.b ' ^[[33m 白',13,10
.dc.b ' ^[[34m 太字、黒',13,10
.dc.b ' ^[[35m 太字、水色',13,10
.dc.b ' ^[[36m 太字、黄色',13,10
.dc.b ' ^[[37m 太字、白',13,10
.dc.b ' ^[[40m 反転、黒',13,10
.dc.b ' ^[[41m 反転、水色',13,10
.dc.b ' ^[[42m 反転、黄色',13,10
.dc.b ' ^[[43m 反転、白',13,10
.dc.b ' ^[[44m 反転、太字、黒',13,10
.dc.b ' ^[[45m 反転、太字、水色',13,10
.dc.b ' ^[[46m 反転、太字、黄色',13,10
.dc.b ' ^[[47m 反転、太字、白',13,10
.dc.b ' ^[[50m プロポーショナル解除',13,10
.dc.b ' ^[[51m 四角囲み',13,10
.dc.b ' ^[[52m 丸囲み',13,10
.dc.b ' ^[[53m 上線',13,10
.dc.b ' ^[[54m 四角囲み、丸囲み解除',13,10
.dc.b ' ^[[55m 上線解除',13,10
.dc.b ' ^[[73m 上付き',13,10
.dc.b ' ^[[74m 下付き',13,10
.dc.b ' ^[[75m 上付き、下付き解除',13,10
.dc.b ' ^[[6n カーソル位置報告。^[[r;cRを入力',13,10
.dc.b ' ^[[nr 右寄せ',13,10
.dc.b ' ^[[s カーソルの座標と文字属性を保存する',13,10
.dc.b ' ^[[u カーソルの座標と文字属性を復元する',13,10
.dc.b 0
;サンプル
sample: .dc.b 27,'[s',27,'[m',13,10
.dc.b 'サンプル',13,10
.dc.b ' ',27,'[1m太字',27,'[m'
.dc.b ' ',27,'[7m反転',27,'[m'
.dc.b ' ',27,'[31m水色',27,'[m'
.dc.b ' ',27,'[32m黄色',27,'[m',13,10
.dc.b ' ',27,'[2m細字',27,'[m'
.dc.b ' ',27,'[3m斜体',27,'[m'
.dc.b ' ',27,'[4m下線',27,'[m'
.dc.b ' ',27,'[53m上線',27,'[m'
.dc.b ' ',27,'[9m取り消し線',27,'[m'
.dc.b ' ',27,'[21m波線',27,'[m',13,10
.dc.b ' ',27,'[51m四角囲み',27,'[m'
.dc.b ' ',27,'[52m丸囲み',27,'[m'
.dc.b ' ',27,'[73m上付き',27,'[m'
.dc.b ' ',27,'[74m下付き',27,'[m',13,10
.dc.b ' ',27,'[7m',27,'[150l左寄せ',27,'[m',13,10
.dc.b ' ',27,'[7m',27,'[150c中央寄せ',27,'[m',13,10
.dc.b ' ',27,'[7m',27,'[150r右寄せ',27,'[m',13,10
.dc.b ' ',27,'[26mProportional-Pitch',27,'[m',13,10
.dc.b 13,10
.dc.b ' ',27,'[26m Alice was beginning to get very tired of sitting by her sister on the bank, and',13,10
.dc.b ' of having nothing to do: once or twice she had peeped into the book her sister was',13,10
.dc.b ' reading, but it had no pictures or conversations in it, `and what is the use of a book,',39,13,10
.dc.b ' thought Alice `without pictures or conversation?',39,13,10
.dc.b ' ',27,'[640r-- from Alice in Wonderland by Lewis Carroll --',27,'[m',13,10
.dc.b 13,10,27,'[u'
.dc.b 0
.data
;----------------------------------------------------------------
;フラグ
option_flag: .dc.b 0 ;-1=オプションが指定された
fixed_flag: .dc.b 0 ;-f。-1=固定ピッチ
keeppr_flag: .dc.b 0 ;-k。-1=常駐する
proportional_flag: .dc.b 0 ;-p。-1=プロポーショナルピッチ
quiet_flag: .dc.b 0 ;-q。-1=表示を減らす
release_flag: .dc.b 0 ;-r。-1=解除する
sample_flag: .dc.b 0 ;-s。-1=サンプル
verbose_flag: .dc.b 0 ;-v。-1=表示を増やす
.text
.even
;----------------------------------------------------------------
;文字列をエラー表示する
;<a0.l:文字列
eprint:
move.l d0,-(sp)
bsr strlen
move.l d0,-(sp)
move.l a0,-(sp)
move.w #2,-(sp)
DOS _WRITE
lea.l 10(sp),sp
move.l (sp)+,d0
rts
;----------------------------------------------------------------
;改行をエラー表示する
eprintcrlf:
move.l a0,-(sp)
lea.l 100f(pc),a0 ;13,10
bsr eprint
movea.l (sp)+,a0
rts
100: .dc.b 13,10,0
.even
;----------------------------------------------------------------
;文字列と改行をエラー表示する
;<a0.l:文字列
eprintln:
bsr eprint
bsr eprintcrlf
rts
;----------------------------------------------------------------
;-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
;----------------------------------------------------------------
;空白か
;<d0.b:文字
;>z:eq=空白,ne=空白ではない
isspace:
ifor <cmp.b #' ',d0>,eq,<cmp.b #9,d0>,eq,<cmp.b #10,d0>,eq,<cmp.b #11,d0>,eq,<cmp.b #12,d0>,eq,<cmp.b #13,d0>,eq ; \t\n\v\f\r
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
;----------------------------------------------------------------
;文字列を表示する
;<a0.l:文字列
print:
move.l d0,-(sp)
bsr strlen
move.l d0,-(sp)
move.l a0,-(sp)
move.w #1,-(sp)
DOS _WRITE
lea.l 10(sp),sp
move.l (sp)+,d0
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
;----------------------------------------------------------------
;文字列と改行を表示する
;<a0.l:文字列
println:
bsr print
bsr printcrlf
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,80f ;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,80f ;オーバーフローした
start
move.b (a0)+,d1 ;次の文字
sub.b #'0',d1 ;整数にする
whileand <>,hs,<cmp.b #10,d1>,lo ;10進数の文字ならば繰り返す
subq.l #1,a0 ;進み過ぎた分戻る
if <cmpa.l a1,a0>,eq ;進んでいない。10進数の文字がない
move.w #%00001,ccr ;vc,cs
else
tst.l d0 ;eq or ne,vc,cc
endif
goto 90f
;オーバーフローしたとき
80: moveq.l #-1,d0 ;オーバーフロー
movea.l a1,a0 ;変化しない
move.w #%00011,ccr ;vs,cs
90: pop
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
;----------------------------------------------------------------
;プログラムの末尾
.bss
.even
program_end:
.end execution_start