;======================================================================================== ; rom16pat.s ; Copyright (C) 2003-2025 Makoto Kamada ; ; This file is part of the XEiJ (X68000 Emulator in Java). ; You can use, modify and redistribute the XEiJ if the conditions are met. ; Read the XEiJ License for more details. ; https://stdkmd.net/xeij/ ;======================================================================================== ;---------------------------------------------------------------- ; ; rom16pat.x ; IPLROM 1.3からIPLROM 1.6を作るためのパッチデータ ; ; 最終更新 ; 2025-08-03 ; ; 作り方 ; has060 -i include -o rom16pat.o -w rom16pat.s ; lk -b fea000 -o rom16pat.x rom16pat.o ; ; SASI IOCS ; IPLROM 1.2のSASI IOCSの範囲は$00FF95B6~$00FF9E7D(2248バイト) ; IPLROM 1.3のSCSI IOCSの範囲は$00FFCCB8~$00FFDCE3(4140バイト) ; IPLROM 1.3のSCSI IOCSの場所にIPLROM 1.2のSASI IOCSをコピーしてからこのパッチを適用する ; ; 6x12フォント ; IPLROM 1.2の6x12 ANKフォントの範囲は$00FFD45E~$00FFE045(3048バイト) ; IPLROM 1.6の6x12 ANKフォントの範囲は$00FEF400~$00FEFFFF(3072バイト) ; コピーして、末尾の24バイトを$00で充填する ; ; SHARPロゴ ; X68000ロゴを大きくできるようにSHARPロゴを ; $00FF138C~$00FF144F(196バイト)から ; $00FFD680~$00FFD743(196バイト)へ移動させる ; $00FFD580~$00FFD67F(256バイト)はSASI IOCSのパッチ用に空けておく ; ;---------------------------------------------------------------- .include bioswork.equ .include control2.mac .include crtc.equ .include dmac.equ .include dosconst.equ .include hdc.equ .include iocscall.mac .include key.equ .include mfp.equ .include misc.mac .include ppi.equ .include push2.mac .include rtc.equ .include scsicall.mac .include spc.equ .include sprc.equ .include sram.equ .include sysport.equ .include vector.equ .include vicon.equ .include patch.mac VERSION_NUMBER equ $16_250803 ;バージョンと日付 VERSION_STRING reg '1.6 (2025-08-03)' CRTMOD_VERSION equ $16_250629 ;_CRTMODのバージョン TEXT_START equ $00FEA000 ;テキストセクションの先頭 TEXT_END equ $00FEF3FF ;テキストセクションの末尾 REMOVE_CRTMOD_G_CLR_ON equ 0 ;1=_CRTMODと_G_CLR_ONを外す USE_PROPORTIONAL_IOCS equ 0 ;1=IOCSでプロポーショナルフォントを使う ;---------------------------------------------------------------- ; ; パッチデータの先頭 ; ;---------------------------------------------------------------- PATCH_START TEXT_START,TEXT_END .cpu 68000 ;---------------------------------------------------------------- ; _ROMVER ; 00FF0030 203C13921127 move.l #$13921127,d0 ; 00FF0036 ;---------------------------------------------------------------- PATCH_DATA iocs_romver,$00FF0030,$00FF0035,$203C1392 move.l #VERSION_NUMBER,d0 PATCH_TEXT .dc.b 'XEiJ IPLROM ',VERSION_STRING,13,10 .dc.b 'CAUTION: Distribution is prohibited.',13,10 .dc.b 26,0 ;---------------------------------------------------------------- ;メッセージのスタイル ; bit0 0=ノーマルピッチ,1=プロポーショナルピッチ ; bit1 0=左寄せ,1=中央寄せ ; bit2 0=隙間なし,1=隙間あり message_style:: .dc.b 7 .even ;---------------------------------------------------------------- ; 制御レジスタの初期化とMPU/MMU/FPUのチェック ; サブルーチンがアドレス変換を無効にするとスタックエリアが移動して戻ってこれなくなるのでjsrではなくjmpを使う ; 00FF005A 61000CE2 bsr.w $00FF0D3E ;MPU,MMU,FPU/FPCPチェック ; 00FF005E 2E00 move.l d0,d7 ; 00FF0060 4A07 tst.b d7 ; 00FF0062 6710 beq.s $00FF0074 ;68000 ; 00FF0064 7000 moveq.l #$00,d0 ; 00FF0066 4E7B0801 movec.l d0,vbr ; 00FF006A 0C070001 cmpi.b #$01,d7 ; 00FF006E 6704 beq.s $00FF0074 ;68010 ; 00FF0070 4E7B0002 movec.l d0,cacr ;キャッシュOFF ; 00FF0074 ;---------------------------------------------------------------- PATCH_DATA mpu_check,$00FF005A,$00FF0073,$61000CE2 jmp mpu_check PATCH_TEXT ;---------------------------------------------------------------- ;MPUチェック ; 起動直後に割り込み禁止、スタック未使用の状態でジャンプしてくる ; IPLROM 1.3のTRAP#10はホットスタートするときMMUのアドレス変換の状態を確認せずに$00FF0038にジャンプしている ; 060turbo.sysがTRAP#10をフックしているのでホットスタートした場合もアドレス変換は既に無効化されているはずだが、 ; 念のためアドレス変換が有効になっていた場合を考慮する ; ROMのコードは変化しないので問題ないが、 ; ベクタテーブルとスタックエリアとワークエリアの内容はアドレス変換を無効にした瞬間に失われる ; ホットスタートしたらスタックエリアやワークエリアを使う前にアドレス変換を無効にしなければならない ;<d5.l:0=コールドスタート(d0d1!='HotStart'),-1=ホットスタート(d0d1=='HotStart') ;<d6.l:エミュレータ割り込みベクタ([OFFSET_EMULATOR_INTERRUPT.w].l)&$00FFFFFF。コールドスタートのとき未定義例外処理ルーチンを指していなければ電源ON、指していればリセット ;>d7.l:MPUの種類とFPU/FPCPの有無とMMUの有無 ; bit31 MMUの有無。0=なし,1=あり ; bit15 FPU/FPCPの有無。0=なし,1=あり ; bit7-0 MPUの種類。0=68000,1=68010,2=68020,3=68030,4=68040,6=68060 ;?d0/a1 mpu_check: movea.l sp,a1 ;---------------------------------------------------------------- ;MOVEC to VBR(-12346)がなければMC68000 ; MC68000かどうかのテストとVBRのクリアを同時に行う ; 不当命令例外ベクタが$0010.wにあるのはMC68000の場合とMC68010以上でVBRが0の場合 ; MC68010以上でVBRが0でないとき$0010.wを書き換えても不当命令例外を捉えられないので、 ; MC68010以上のときは最初にVBRをクリアする必要がある ; VBRをクリアする命令はMC68000で不当命令なのでMC68000かどうかのテストを兼ねる lea.l dummy_trap(pc),a0 move.l a0,OFFSET_ILLEGAL_INSTRUCTION.w ;例外ベクタ$04 不当命令 lea.l mpu_check_done(pc),a0 moveq.l #0,d7 ;MC68000 moveq.l #0,d0 .cpu 68010 movec.l d0,vbr .cpu 68000 lea.l dummy_trap(pc),a0 move.l a0,OFFSET_ILLEGAL_INSTRUCTION.w ;例外ベクタ$04 不当命令 move.l a0,OFFSET_LINE_1111_EMULATOR.w ;例外ベクタ$0B ライン1111エミュレータ ;---------------------------------------------------------------- ;MOVEC to VBR(-12346)があってスケールファクタ(--2346)がなければMC68010 moveq.l #1,d7 ;MC68010 @@: moveq.l #1,d0 ;$70,$01 .cpu 68020 and.b (@b-1,pc,d0.w*2),d0 ;スケールファクタなし(([@b-1+1].b==$70)&1)==0,スケールファクタあり(([@b-1+1*2].b=$01)&1)==1 .cpu 68000 beq mpu_check_done ;---------------------------------------------------------------- ;CALLM(--2---)があればMC68020 .cpu 68020 lea.l 9f(pc),a0 callm #0,1f(pc) moveq.l #2,d7 ;MC68020 ; 3 2 1 0 ; C CE F E move.l #%1__0_0_0,d0 movec.l d0,cacr ;命令キャッシュクリア、命令キャッシュOFF lea.l @f(pc),a0 fnop bset.l #15,d7 ;FPUあり @@: ;MC68851のチェックは省略 bra mpu_check_done ;モジュールデスクリプタ 1: .dc.l %0<<13|0<<24|0<<16 ;option=0,type=0,accesslevel=0 .dc.l 2f ;モジュールエントリポインタ .dc.l 0 ;モジュールデータ領域ポインタ .dc.l 0 ;モジュールエントリ 2: .dc.w 15<<12 ;Rn=sp rtm sp 9: movea.l a1,sp .cpu 68000 ;---------------------------------------------------------------- ;CALLM(--2---)がなくてMOVEC from CAAR(--23--)があればMC68030 .cpu 68030 lea.l 9f(pc),a0 movec.l caar,d0 moveq.l #3,d7 ;MC68030 ; D C B A 9 8 765 4 3 2 1 0 ; WA DBE CD CED FD ED IBE CI CEI FI EI move.l #%_0___0__1___0__0__0_000___0__1___0__0__0,d0 movec.l d0,cacr ;データキャッシュクリア、データキャッシュOFF、命令キャッシュクリア、命令キャッシュOFF ; F ECDBA 9 8 7654 3210 FEDC BA98 7654 3210 ; E SRE FCL PS IS TIA TIB TIC TID move.l #%0_00000___0___0_1101_1000_0011_0100_0100_0000,-(sp) pmove.l (sp),tc ;アドレス変換OFF ; FEDCBA98 76543210 F EDCB A 9 8 7 654 3 210 ; BASE MASK E CI R/W RWM FCBASE FCMASK move.l #%00000000_00000000_0_0000__0___0___0_0____000_0____000,(sp) pmove.l (sp),tt0 ;透過変換OFF pmove.l (sp),tt1 addq.l #4,sp lea.l @f(pc),a0 fnop bset.l #15,d7 ;FPUあり @@: bsr mmu_check_3 ;MMUチェック(MC68030) bra mpu_check_done 9: .cpu 68000 ;---------------------------------------------------------------- ;MOVEC from MMUSR(----4-)があればMC68040 .cpu 68040 lea.l 9f(pc),a0 movec.l mmusr,d0 moveq.l #4,d7 ;MC68040 ; F EDCBA9876543210 F EDCBA9876543210 ; DE 000000000000000 IE 000000000000000 move.l #%_0_000000000000000__0_000000000000000,d0 movec.l d0,cacr ;データキャッシュOFF、命令キャッシュOFF cinva bc ;データキャッシュクリア、命令キャッシュクリア ; F E DCBA9876543210 ; E P 00000000000000 move.l #%0_0_00000000000000,d0 movec.l d0,tc ;アドレス変換無効 pflusha ;アドレス変換キャッシュクリア ; FEDCBA98 76543210 F ED CBA 9 8 7 65 43 2 10 ; BASE MASK E SFIELD U1 U0 CM W move.l #%00000000_00000000_0_____00_000__0__0_0_00_00_0_00,d0 movec.l d0,itt0 ;透過変換OFF movec.l d0,itt1 movec.l d0,dtt0 movec.l d0,dtt1 lea.l @f(pc),a0 fnop bset.l #15,d7 ;FPUあり @@: bsr mmu_check_46 ;MMUチェック(MC68040/MC68060) bra mpu_check_done 9: .cpu 68000 ;---------------------------------------------------------------- ;MOVEC from PCR(-----6)があればMC68060 .cpu 68060 lea.l 9f(pc),a0 movec.l pcr,d1 moveq.l #6,d7 ;MC68060 ; F E D C B A98 7 6 5 43210 F E D CBA9876543210 ; EDC NAD ESB DPI FOC EBC CABC CUBC EIC NAI FIC move.l #%__0___0___0___0___0_000___1____0____0_00000___0___0___0_0000000000000,d0 movec.l d0,cacr ;データキャッシュOFF、ストアバッファOFF、分岐キャッシュON、命令キャッシュOFF ; リセットでキャッシュはクリアされない ; リセットされたらキャッシュを有効にする前にキャッシュをクリアしなければならない(MC68060UM 5.3) cinva bc ;データキャッシュクリア、命令キャッシュクリア ; F E D C B A 98 76 5 43 21 0 ; E P NAD NAI FOTC FITC DCO DUO DWO DCI DUI move.l #%0_0___0___0____0____0__10__00___0__10__00_0,d0 movec.l d0,tc ;アドレス変換OFF、データキャッシュOFFプリサイスモード、命令キャッシュOFFプリサイスモード ; リセットでアドレス変換キャッシュはクリアされない ; リセットされたらアドレス変換を有効にする前にアドレス変換キャッシュをクリアしなければならない(MC68060UM 4.6.1) pflusha ;アドレス変換キャッシュクリア ; FEDCBA98 76543210 F ED CBA 9 8 7 65 43 2 10 ; BASE MASK E SFIELD U1 U0 CM W move.l #%00000000_00000000_0_____00_000__0__0_0_00_00_0_00,d0 movec.l d0,itt0 ;透過変換OFF movec.l d0,itt1 movec.l d0,dtt0 movec.l d0,dtt1 ; FEDCBA9876543210 FEDCBA98 7 65432 1 0 ; 0000010000110000 REVISION EDEBUG DFP ESS move.l #%0000000000000000_00000000______0_00000___0___1,d0 movec.l d0,pcr ;FPU ON,スーパースカラON lea.l @f(pc),a0 fnop bset.l #15,d7 ;FPUあり @@: bsr mmu_check_46 ;MMUチェック(MC68040/MC68060) bra mpu_check_done 9: .cpu 68000 ;---------------------------------------------------------------- ;不明 moveq.l #0,d7 ;---------------------------------------------------------------- ;終了 mpu_check_done: jmp $00FF0074 ;---------------------------------------------------------------- ;ダミーの例外処理 ; a1をspにコピーしてa0にジャンプする dummy_trap: movea.l a1,sp jmp (a0) ;---------------------------------------------------------------- ;MMUチェック(MC68030) mmu_check_3: .cpu 68030 lea.l -128(sp),sp movea.l sp,a0 ; L/U LIMIT DT move.l #%0_111111111111111_00000000000000_10,(a0)+ move.l sp,d0 lsr.l #4,d0 addq.l #2,d0 lsl.l #4,d0 move.l d0,(a0) ; CI M U WP DT lea.l $00000000|%0__0_0_0_0__0_01.w,a0 movea.l d0,a1 moveq.l #8-1,d0 for d0 move.l a0,(a1)+ adda.l #$00200000,a0 next ;アドレス変換を有効にする ; CI M U WP DT move.l #$00F00000|%0__0_0_0_0__0_01,-4*8+4(a1) ;$00200000を$00F00000に変換する pmove.q (sp),crp ; E SRE FCL PS IS TIA TIB TIC TID move.l #%1_00000___0___0_1101_1000_0011_0100_0100_0000,-(sp) pflusha pmove.l (sp),tc ;8KB比較する lea.l $00F00000,a1 lea.l $00200000,a0 move.w #2048-1,d0 @@: cmpm.l (a1)+,(a0)+ dbne d0,@b bne @f bset.l #31,d7 ;MMUあり @@: ;アドレス変換を解除する bclr.b #7,(sp) ;E=0 pmove.l (sp),tc ;アドレス変換無効 pflusha lea.l 4+128(sp),sp .cpu 68000 rts ;---------------------------------------------------------------- ;MMUチェック(MC68040/MC68060) mmu_check_46: .cpu 68040 lea.l $2000.w,a1 ;ルートテーブルを作る ; U W UDT lea.l 512|%00000_0_0__10(a1),a0 moveq.l #128-1,d0 for d0 move.l a0,(a1)+ next ;ポインタテーブルを作る ; U W UDT lea.l 512|%00000_0_0__10(a1),a0 moveq.l #128-1,d0 for d0 move.l a0,(a1)+ next ;ページテーブルを作る moveq.l #32-1,d0 for d0 ; UR G U1 U0 S CM M U W PDT move.l #$00FF0000|%00_1__0__0_0_10_0_0_0__01,(a1)+ next ;$80000000~$FFFFFFFFを透過変換にする ; BASE MASK E SFIELD U1 U0 CM W movea.l #%00000000_01111111_1_____10_000__0__0_0_10_00_0_00,a1 movec.l a1,itt0 movec.l a1,dtt0 movec.l a1,itt1 movec.l a1,dtt1 ;アドレス変換を有効にする lea.l $2000.w,a1 movec.l a1,srp ;MMUがなくてもエラーにならない(MC68060UM B.2) movec.l a1,urp ; E P NAD NAI FOTC FITC DCO DUO DWO DCI DUI movea.l #%1_1___0___0____0____0__00__00___0__00__00_0,a1 pflusha cinva bc movec.l a1,tc ;8KB比較する lea.l $80FF0000,a0 lea.l $80F00000,a1 move.w #2048-1,d0 @@: cmpm.l (a0)+,(a1)+ dbne d0,@b bne @f bset.l #31,d7 ;MMUあり @@: ;アドレス変換とトランスペアレント変換を解除する if <cmp.b #6,d7>,lo ;68040 ; E P movea.l #%0_0___0___0____0____0__00__00___0__00__00_0,a1 else ;68060 ; E P NAD NAI FOTC FITC DCO DUO DWO DCI DUI movea.l #%0_0___0___0____0____0__10__00___0__00__00_0,a1 endif movec.l a1,tc pflusha cinva bc suba.l a1,a1 movec.l a1,itt0 movec.l a1,dtt0 movec.l a1,itt1 movec.l a1,dtt1 .cpu 68000 rts ;---------------------------------------------------------------- ; 未定義例外ベクタと未定義IOCSコールベクタのハイメモリ対策 ; 68060のとき ; 未定義例外ベクタと未定義IOCSコールベクタのbit28が1のときベクタ番号を消す ; $01xxxxxxにハイメモリがあるとき未定義ベクタを踏んでも暴走しないようにする ; 060turboのROMに合わせてハイメモリの有無に関係なく68060のときだけ行う ; TRAP#n($002x)、MFP($004x)、IOI/DMA/SPC($006x)などはベクタ番号を消さない ; SCC($005x)、_OPMDRV($01F0)などはベクタ番号を消す ; 未実装整数命令例外ベクタを設定する ; スプリアス割り込みベクタを設定する ; 変更前 ; 00FF008E 41FAFF70_00000000 lea.l $00FF0000(pc),a0 ; 00FF0092 2408 move.l a0,d2 ; 00FF0094 ;---------------------------------------------------------------- PATCH_DATA p008E,$00FF008E,$00FF0093,$41FAFF70 jsr p008E PATCH_TEXT ;<d7.l:MPUの種類とFPU/FPCPの有無とMMUの有無 ; bit31 MMUの有無。0=なし,1=あり ; bit15 FPU/FPCPの有無。0=なし,1=あり ; bit7-0 MPUの種類。0=68000,1=68010,2=68020,3=68030,4=68040,6=68060 ;>d6.l:$00FF0000 ;?a0-a1 p008E: if <cmpi.b #6,d7>,eq ;68060のとき ;未定義例外ベクタと未定義IOCSコールベクタのbit28が1のときベクタ番号を消す ;NMIベクタだけ未定義ではないが問題ない suba.l a0,a0 ;例外ベクタテーブルの先頭から do if <btst.b #4,(a0)>,ne ;bit28が1のとき clr.b (a0) ;ベクタ番号を消す endif addq.l #4,a0 while <cmpa.w #$0800,a0>,lo ;IOCSコールベクタテーブルの末尾まで ;未実装整数命令例外処理ベクタを設定する lea.l uii(pc),a1 ;未実装整数命令例外処理ルーチン move.l a1,OFFSET_INTEGER_INSTRUCTION.w ;例外ベクタ$3D 未実装整数命令 endif ;スプリアス割り込みベクタを設定する lea.l uii_rte(pc),a1 ;未実装整数命令例外処理ルーチンのrte move.l a1,OFFSET_SPURIOUS_INTERRUPT.w ;例外ベクタ$18 スプリアス割り込み ;IOCSコールベクタの設定に戻る move.l #$00FF0000,d2 rts ;---------------------------------------------------------------- ;未実装整数命令例外処理ルーチン .cpu 68060 uii: pea.l (8,sp) ;例外発生時のssp movem.l d0-d7/a0-a6,-(sp) moveq.l #5,d2 ;スーパーバイザデータアクセスのファンクションコード btst.b #5,(4*16,sp) ;例外発生時のsrのS bne 1f ;スーパーバイザモード ;ユーザモード moveq.l #1,d2 ;ユーザデータアクセスのファンクションコード move.l usp,a0 ;例外発生時のusp move.l a0,(4*15,sp) ;例外発生時のsp ;命令コードを読み取る 1: movea.l (4*16+2,sp),a0 ;a0=例外発生時のpc move.w (a0)+,d1 ;d1=命令コード,a1=pc+2 ;MOVEPかどうか調べる move.w d1,d0 ; 0000qqq1ws001rrr and.w #%1111000100111000,d0 cmp.w #%0000000100001000,d0 beq 2f ;MOVEP ;MOVEP以外 movem.l (sp),d0-d2 ;d0/d1/d2を復元 movea.l (4*8,sp),a0 ;a0を復元 lea.l (4*16,sp),sp ;破壊されていないレジスタの復元を省略する jmp $00FF0770 ;未定義例外処理 ;MOVEP ;実効アドレスを求める 2: moveq.l #7,d0 ;d0=0000000000000111 and.w d1,d0 ;d0=0000000000000rrr movea.l (4*8,sp,d0.w*4),a1 ;a1=Ar adda.w (a0)+,a1 ;a0=pc+4,a1=d16+Ar=実効アドレス ;復帰アドレスを更新する move.l a0,(4*16+2,sp) ;pc=pc+4 ;Dqのアドレスを求める move.w d1,d0 ;d0=0000qqq1ws001rrr lsr.w #8,d0 ;d0=000000000000qqq1 lea.l (-2,sp,d0.w*2),a0 ;d0*2=00000000000qqq10,a0=Dqのアドレス ;リード/ライト,ワード/ロングで分岐する add.b d1,d1 ;c=w,d1=s001rrr0 bcs 5f ;ライト ;リード movec.l sfc,d1 ;ファンクションコードを保存 movec.l d2,sfc ;ファンクションコードを変更 bmi 3f ;リードロング ;リードワード ;MOVEP.W (d16,Ar),Dq moves.b (a1),d0 ;メモリから上位バイトをリード lsl.w #8,d0 moves.b (2,a1),d0 ;メモリから下位バイトをリード move.w d0,(2,a0) ;データレジスタの下位ワードへライト bra 4f ;リードロング ;MOVEP.L (d16,Ar),Dq 3: moves.b (a1),d0 ;メモリから上位ワードの上位バイトをリード lsl.l #8,d0 moves.b (2,a1),d0 ;メモリから上位ワードの下位バイトをリード lsl.l #8,d0 moves.b (4,a1),d0 ;メモリから下位ワードの上位バイトをリード lsl.l #8,d0 moves.b (6,a1),d0 ;メモリから下位ワードの下位バイトをリード move.l d0,(a0) ;データレジスタへライト 4: movec.l d1,sfc ;ファンクションコードを復元 movem.l (sp),d0-d7 ;データレジスタのどれか1個が更新されている bra 8f ;ライト 5: movec.l dfc,d1 ;ファンクションコードを保存 movec.l d2,dfc ;ファンクションコードを変更 bmi 6f ;ライトロング ;ライドワード ;MOVEP.W Dq,(d16,Ar) move.w (2,a0),d0 ;データレジスタの下位ワードからリード rol.w #8,d0 moves.b d0,(a1) ;メモリへ上位バイトをライト rol.w #8,d0 moves.b d0,(2,a1) ;メモリへ下位バイトをライト bra 7f ;ライトロング ;MOVEP.L Dq,(d16,Ar) 6: move.l (a0),d0 ;データレジスタからリード rol.l #8,d0 moves.b d0,(a1) ;メモリへ上位ワードの上位バイトをライト rol.l #8,d0 moves.b d0,(2,a1) ;メモリへ上位ワードの下位バイトをライト rol.l #8,d0 moves.b d0,(4,a1) ;メモリへ下位ワードの上位バイトをライト rol.l #8,d0 moves.b d0,(6,a1) ;メモリへ下位ワードの下位バイトをライト 7: movec.l d1,dfc ;ファンクションコードを復元 movem.l (sp),d0-d2 ;d0/d1/d2を復元 8: movem.l (4*8,sp),a0-a1 ;a0/a1を復元 lea.l (4*16,sp),sp ;破壊されていないレジスタの復元を省略する tst.b (sp) ;例外発生時のsrのT bpl 9f ;トレースなし ;トレースあり ori.w #$8000,sr ;RTEの前にsrのTをセットしてMOVEPをトレースしたように振る舞う 9: ;未実装整数命令例外処理ルーチンのrte uii_rte: rte .cpu 68000 ;---------------------------------------------------------------- ; IOCS $F5ベクタの設定 ; 000000C4 2039(01)0000934E move.l device_installer_parameter,d0 ;ROM起動ルーチン-12 SCSIデバイスドライバ組み込みルーチンのパラメータ ; 000000CA 21C007D4 move.l d0,4*($100+_SCSIDRV).w ;IOCSコール$F5 _SCSIDRV ; 削除。SCSI内蔵機のときもscsi_init_routineで設定するのでここは削除 ;---------------------------------------------------------------- PATCH_DATA p00C4,$00FF00C4,$00FF00C4+9,$203900FF bra.s (*)-$00C4+$00CE ;---------------------------------------------------------------- ; SRAMの初期化 ; SRAMを初期化するときメインメモリのサイズを搭載しているサイズに合わせる ; SASI内蔵機のとき、ROM起動ハンドルを$00E80400に、ハードディスクの台数を1にする ; SCSI内蔵機のとき、ROM起動ハンドルを$00FC0000に、ハードディスクの台数を0にする ; ROM起動ハンドルを標準の$00BFFFFCにするとメインメモリを12MBに増設したとき正常に動作しなくなる ; $00E80400はすべての機種でバスエラーになるはず ; メモリサイズの判別とSASI内蔵機とSCSI内蔵機の判別もここで行う ; 変更前 ; 000000CE 41F900ED0000 lea.l SRAM_MAGIC,a0 ; : ; 0000010C*423900E8E00D locksram ;SRAM書き込み禁止 ;---------------------------------------------------------------- PATCH_DATA p00ce,$00FF00CE,$00FF0111,$41F900ED jsr p00ce bra.s (*)-$00D4+$0112 PATCH_TEXT p00ce: bsr check_memory_size bsr check_hard_disk_interface bsr check_sram rts ;メインメモリのサイズを確認する check_memory_size: push d2-d3/a2/a5 suba.l a2,a2 move.l #$55AAAA55,d3 ;テストデータ di ;sr保存、割り込み禁止 move.l OFFSET_BUS_ERROR.w,-(sp) ;バスエラーベクタ保存 movea.l sp,a5 ;sp保存 move.l #@f,OFFSET_BUS_ERROR.w ;バスエラーでループを終了する do move.l (a2),d2 ;保存 nop move.l d3,(a2) ;テストデータ書き込み nop cmp.l (a2),d3 ;テストデータ読み出し、比較 nop break ne nop move.l d2,(a2) ;復元 nop adda.l #$00100000,a2 ;次の1MB while <cmpa.l #$00C00000,a2>,lo ;最大12MB @@: movea.l a5,sp ;sp復元 move.l (sp)+,OFFSET_BUS_ERROR.w ;バスエラーベクタ復元 ei ;sr復元 move.l a2,BIOS_MEMORY_SIZE.w ;起動時に確認したメインメモリのサイズ pop rts ;SASI内蔵機とSCSI内蔵機を判別する check_hard_disk_interface: isSASI sne.b BIOS_BUILTIN_SCSI.w ;0=SASI内蔵機,-1=SCSI内蔵機 rts check_sram: push d0/a0-a3 lea.l SRAM_MAGIC,a2 ;SRAMマジック lea.l $00FF09E8,a3 ;SRAM初期データ movea.l a2,a0 movea.l a3,a1 ifor <cmpm.l (a0)+,(a1)+>,ne,<cmpm.l (a0)+,(a1)+>,ne ;SRAMは壊れている ;SRAM書き込み許可 unlocksram ;SRAMの先頭256バイトをクリア movea.l a2,a0 moveq.l #256/4-1,d0 for d0 clr.l (a0)+ next ;SRAM初期データを書き込む movea.l a2,a0 movea.l a3,a1 moveq.l #$00FF0A43-$00FF09E8-1,d0 ;SRAM初期データの長さ-1 for d0 move.b (a1)+,(a0)+ next ;メモリサイズを修正する move.l BIOS_MEMORY_SIZE.w,SRAM_MEMORY_SIZE-SRAM_MAGIC(a2) ;ROM起動ハンドルとハードディスクの台数を修正する if <tst.b BIOS_BUILTIN_SCSI.w>,eq ;SASI内蔵機 move.l #$00E80400,SRAM_ROM_BOOT_HANDLE-SRAM_MAGIC(a2) move.b #1,SRAM_HDMAX-SRAM_MAGIC(a2) else ;SCSI内蔵機 move.l #$00FC0000,SRAM_ROM_BOOT_HANDLE-SRAM_MAGIC(a2) clr.b SRAM_HDMAX-SRAM_MAGIC(a2) endif ;SRAM常駐プログラムを無効にする clr.w SRAM_PROGRAM_START-SRAM_MAGIC(a2) ;SRAM書き込み禁止 locksram endif pop rts ;---------------------------------------------------------------- ; 整合を確認する ; SCSIINROMの整合を確認する ; 判別されたメモリサイズとSRAMの設定値が合っていないときSRAMの設定値を修正するか問い合わせる ; CLRキーが押されていたらSRAM初期化の位置に押し込む ; 変更前 ; 00FF01D4 083800070807 btst.b #7,BIOS_BITSNS+7.w ;CLR|↓|→|↑|←|UNDO|ROLL DOWN|ROLL UP ;---------------------------------------------------------------- PATCH_DATA p01d4,$00FF01D4,$00FF01D4+5,$08380007 jsr p01d4 PATCH_TEXT p01d4: if <btst.b #KEY_TENCLR&7,BIOS_BITSNS+(KEY_TENCLR>>3).w>,eq ;CLRキーが押されていない。押されているときneで復帰するためtst.bではなくbtst.bを使う bsr check_memory_size bsr check_hard_disk_interface bsr test_scsiinrom bsr confirm_memory_size moveq.l #0,d0 ;eqで復帰する endif rts ;SCSIINROMの整合を確認する ; SASI内蔵機のときSCSIINROMがあればエラーを報告して停止する ; SCSI内蔵機のときSCSIINROM 16がなければエラーを報告して停止する test_scsiinrom: push d0-d1/a0 lea.l $00FC0024,a0 ;'SCSIIN' clr.w d1 ;0=SCSIINROMがない bsr read_long if <cmp.l #'SCSI',d0>,eq bsr read_word if <cmp.w #'IN',d0>,eq addq.w #1,d1 ;1=SCSIINROMがある bsr read_word if <cmp.w #16,d0>,eq addq.w #1,d1 ;2=SCSIINROM 16がある endif endif endif ;<d1.w:0=SCSIINROMがない,1=SCSIINROMがある,2=SCSIINROM 16がある if <tst.b BIOS_BUILTIN_SCSI.w>,eq ;SASI内蔵機のとき if <tst.w d1>,ne ;SCSIINROMがある lea.l 100f(pc),a1 ;13,10,' SCSIINROM is not required' goto 20f endif else ;SCSI内蔵機のとき if <cmp.w #2,d1>,ne ;SCSIINROM 16がない lea.l 101f(pc),a1 ;13,10,' SCSIINROM 16 is required' goto 20f endif endif pop rts 20: bsr iocs_21_B_PRINT do while t 100: .dc.b 13,10,' SCSIINROM is not required',0 101: .dc.b 13,10,' SCSIINROM 16 is required',0 .even ;判別されたメモリサイズとSRAMの設定値が合っていないときSRAMの設定値を修正するか問い合わせる confirm_memory_size: push d0-d1/a0-a1 move.l SRAM_MEMORY_SIZE,d0 ;SRAMの設定値のメモリサイズ if <cmp.l BIOS_MEMORY_SIZE.w,d0>,ne ;起動時に確認したメインメモリのサイズ。合っていない lea.l -128(sp),sp movea.l sp,a0 lea.l 100f(pc),a1 ;13,10,' Modify memory size setting from ' bsr strcpy ; move.l SRAM_MEMORY_SIZE,d0 ;SRAMの設定値のメモリサイズ moveq.l #20,d1 lsr.l d1,d0 bsr utos lea.l 101f(pc),a1 ;'MB to ' bsr strcpy move.l BIOS_MEMORY_SIZE.w,d0 ;起動時に確認したメインメモリのサイズ ; moveq.l #20,d1 lsr.l d1,d0 bsr utos lea.l 102f(pc),a1 ;'MB? (Y/N)' bsr strcpy movea.l sp,a1 bsr iocs_21_B_PRINT bsr kflush do bsr inkey bsr toupper whileand <cmp.b #'Y',d0>,ne,<cmp.b #'N',d0>,ne if <cmp.b #'Y',d0>,eq unlocksram move.l BIOS_MEMORY_SIZE.w,SRAM_MEMORY_SIZE locksram endif lea.l 103f(pc),a1 ;26 bsr iocs_21_B_PRINT lea.l 128(sp),sp endif pop rts 100: .dc.b 13,10 .dc.b ' Modify memory size setting from ',0 101: .dc.b 'MB to ',0 102: .dc.b 'MB? (y/n)',0 103: .dc.b 26,0 .even ;---------------------------------------------------------------- ;改行をコピーする ;<a0.l:コピー先 ;>a0.l:コピー先の0の位置 crlf: move.b #13,(a0)+ move.b #10,(a0)+ clr.b (a0) rts ;---------------------------------------------------------------- ;符号なし整数を16進数4桁の文字列に変換する ;<d0.w:符号なし整数 ;<a0.l:バッファ ;>a0.l:バッファの0の位置 h4tos: push d1-d2 moveq.l #4-1,d1 for d1 rol.w #4,d0 moveq.l #15,d2 and.w d0,d2 move.b 100f(pc,d2.w),(a0)+ next clr.b (a0) pop rts 100: .dc.b '0123456789ABCDEF' .even ;---------------------------------------------------------------- ;符号なし整数を16進数8桁の文字列に変換する ;<d0.l:符号なし整数 ;<a0.l:バッファ ;>a0.l:バッファの0の位置 h8tos: push d1-d2 moveq.l #8-1,d1 for d1 rol.l #4,d0 moveq.l #15,d2 and.w d0,d2 move.b 100f(pc,d2.w),(a0)+ next clr.b (a0) pop rts 100: .dc.b '0123456789ABCDEF' .even ;---------------------------------------------------------------- ;文字コードが0でないキーが押されるまで待つ ;>d0.b:文字コード inkey: do IOCS _B_KEYINP while <tst.b d0>,eq rts ;---------------------------------------------------------------- ;キー入力バッファを空にする kflush: push d0 IOCS _B_KEYSNS while <tst.l d0>,ne IOCS _B_KEYINP IOCS _B_KEYSNS endwhile pop rts ;---------------------------------------------------------------- ;文字列をコピーする ;<a0.l:コピー先 ;<a1.l:コピー元 ;>a0.l:コピー先の0の位置 ;>a1.l:コピー元の0の次の位置 strcpy: do move.b (a1)+,(a0)+ while ne subq.l #1,a0 rts ;---------------------------------------------------------------- ;大文字にする ;<d0.b:文字コード ;>d0.b:文字コード toupper: ifand <cmp.b #'a',d0>,hs,<cmp.b #'z',d0>,ls add.b #'A'-'a',d0 endif rts ;---------------------------------------------------------------- ;符号なし整数を10進数の文字列に変換する ;<d0.l:符号なし整数 ;<a0.l:バッファ ;>a0.l:バッファの0の位置 utos: push d0-d2/a1 if <tst.l d0>,eq move.b #'0',(a0)+ else lea.l utos_table(pc),a1 do move.l (a1)+,d1 while <cmp.l d1,d0>,lo ;引けるところまで進む do moveq.l #'0'-1,d2 do addq.b #1,d2 sub.l d1,d0 while hs ;引ける回数を数える move.b d2,(a0)+ add.l d1,d0 ;引きすぎた分を加え戻す move.l (a1)+,d1 while ne endif clr.b (a0) pop rts utos_table: .dc.l 1000000000 .dc.l 100000000 .dc.l 10000000 .dc.l 1000000 .dc.l 100000 .dc.l 10000 .dc.l 1000 .dc.l 100 .dc.l 10 .dc.l 1 .dc.l 0 ;---------------------------------------------------------------- ;符号なし整数を10進数の文字列に変換する(ゼロ充填) ;<d0.l:符号なし整数 ;<d1.l:最小桁数 ;<a0.l:バッファ ;>a0.l:バッファの0の位置 utosz: push d0-d2/a1 moveq.l #10,d2 sub.l d1,d2 if lo do move.b #'0',(a0)+ addq.l #1,d2 while ne ;足りない0を並べる endif lea.l utos_table(pc),a1 for d2 move.l (a1)+,d1 next <cmp.l d1,d0>,lo ;最小桁数または引けるところまで進む do moveq.l #'0'-1,d2 do addq.b #1,d2 sub.l d1,d0 while hs ;引ける回数を数える move.b d2,(a0)+ add.l d1,d0 ;引きすぎた分を加え戻す move.l (a1)+,d1 while ne clr.b (a0) pop rts .if 0 ;---------------------------------------------------------------- ;バスエラーを無視して1バイト読み出す ;<a0.l:アドレス ;>d0.b:データ。バスエラーのとき0 ;>a0.l:アドレス+1 ;>c:cc=バスエラーなし,cs=バスエラーあり read_byte: push d1/a1 di ;sr保存、割り込み禁止 move.l OFFSET_BUS_ERROR.w,-(sp) ;バスエラーベクタ保存 lea.l @f(pc),a1 move.l a1,OFFSET_BUS_ERROR.w movea.l sp,a1 ;sp保存 moveq.l #0,d0 ; XNZVC moveq.l #%00001,d1 ;c=1 nop move.b (a0)+,d0 ;1バイト読み出す nop moveq.l #%00000,d1 ;c=0 @@: movea.l a1,sp ;sp復元 move.l (sp)+,OFFSET_BUS_ERROR.w ;バスエラーベクタ復元 ei ;sr復元 move.w d1,ccr pop rts .endif ;---------------------------------------------------------------- ;バスエラーを無視して1ワード読み出す ;<a0.l:アドレス。奇数は不可 ;>d0.w:データ。バスエラーのとき0 ;>a0.l:アドレス+2 ;>c:cc=バスエラーなし,cs=バスエラーあり read_word: push d1/a1 di ;sr保存、割り込み禁止 move.l OFFSET_BUS_ERROR.w,-(sp) ;バスエラーベクタ保存 lea.l @f(pc),a1 move.l a1,OFFSET_BUS_ERROR.w movea.l sp,a1 ;sp保存 moveq.l #0,d0 ; XNZVC moveq.l #%00001,d1 ;c=1 nop move.w (a0)+,d0 ;1ワード読み出す nop moveq.l #%00000,d1 ;c=0 @@: movea.l a1,sp ;sp復元 move.l (sp)+,OFFSET_BUS_ERROR.w ;バスエラーベクタ復元 ei ;sr復元 move.w d1,ccr pop rts ;---------------------------------------------------------------- ;バスエラーを無視して1ロング読み出す ;<a0.l:アドレス。奇数は不可 ;>d0.l:データ。バスエラーのとき0 ;>a0.l:アドレス+2 ;>c:cc=バスエラーなし,cs=バスエラーあり read_long: push d1/a1 di ;sr保存、割り込み禁止 move.l OFFSET_BUS_ERROR.w,-(sp) ;バスエラーベクタ保存 lea.l @f(pc),a1 move.l a1,OFFSET_BUS_ERROR.w movea.l sp,a1 ;sp保存 moveq.l #0,d0 ; XNZVC moveq.l #%00001,d1 ;c=1 nop move.l (a0)+,d0 ;1ロング読み出す nop moveq.l #%00000,d1 ;c=0 @@: movea.l a1,sp ;sp復元 move.l (sp)+,OFFSET_BUS_ERROR.w ;バスエラーベクタ復元 ei ;sr復元 move.w d1,ccr pop rts ;---------------------------------------------------------------- ; 起動できないSCSI-IDのフラグの保存 ; このまま ; _B_SCSIの元のベクタを移動させることにしたので起動できないSCSI-IDのフラグは移動していない ; SASI内蔵機のときも衝突することはないはず ; 00000112 1A380CC3 move.b BIOS_SCSI_UNBOOTABLE.w,d5 ; 00000138 11C50CC3 move.b d5,BIOS_SCSI_UNBOOTABLE.w ;---------------------------------------------------------------- ;---------------------------------------------------------------- ; クロック計測 ; 00FF013C 0C3800010CBC cmpi.b #$01,BIOS_MPU_TYPE.w ; : ; 00FF019C ;---------------------------------------------------------------- PATCH_DATA clock_check,$00FF013C,$00FF019B,$0C380001 jsr clock_check bra ($00FF019C)PATCH_ZL PATCH_TEXT ;---------------------------------------------------------------- ;クロック計測 clock_check: ;システムクロックの確認 moveq.l #0,d0 move.b SYSPORT_MODEL,d0 ;機種判別。$DC=X68030,$FE=XVIで16MHz,$FF=XVI以前で10MHz ;$00FF=10MHz,$00FE=16MHz,$00DC=25MHz not.b d0 ;$0000=10MHz,$0001=16MHz,$0023=25MHz lsl.w #4,d0 ;$0000=10MHz,$0010=16MHz,$0230=25MHz lsr.b #4,d0 ;$0000=10MHz,$0001=16MHz,$0203=25MHz move.w d0,BIOS_CLOCK_SWITCH.w ;クロックスイッチ。$0000=10MHz,$0001=16MHz,$0203=25MHz ;クロック計測のためのキャッシュON ; 68030のときは命令キャッシュとデータキャッシュをONにする ; 68040/68060のデータキャッシュと68060のストアバッファはMMUを有効にするまでONにできないので命令キャッシュだけONにする ; SRAMのキャッシュの設定はこれより後で反映される if <cmpi.b #2,BIOS_MPU_TYPE.w>,hs ;68000/68010はキャッシュなし move.l #$00002101,d0 ;68020/68030は命令キャッシュON(bit0)、68030はデータキャッシュON(bit8) if <cmpi.b #4,BIOS_MPU_TYPE.w>,hs if hi .cpu 68060 movec.l pcr,d0 bset.l #0,d0 ;68060はスーパースカラON(bit0) movec.l d0,pcr .cpu 68000 move.l #$00800000,d0 ;68060はストアバッファOFF(bit29),分岐キャッシュON(bit23) endif move.w #$8000,d0 ;68040/68060はデータキャッシュOFF(bit31),命令キャッシュON(bit15) endif .cpu 68030 movec.l d0,cacr .cpu 68000 clr.b SYSPORT_WAIT endif ;クロック計測 ;ROM計測 lea.l clock_loop(pc),a0 ;計測ループ bsr clock_sub ;計測サブ move.l d0,BIOS_MPU_SPEED_ROM_LONG.w if <cmp.l #$0000FFFF,d0>,hi moveq.l #-1,d0 endif move.w d0,BIOS_MPU_SPEED_ROM.w ;RAM計測 lea.l -30(sp),sp move.l sp,d0 add.w #14,d0 and.w #-16,d0 movea.l d0,a0 ;16バイト境界から始まる16バイトのワークエリア movem.l clock_loop(pc),d0-d2/a1 ;計測ループをワークエリアにコピーする movem.l d0-d2/a1,(a0) ; スタックエリアが命令キャッシュに乗っていることはないのでキャッシュフラッシュは省略する bsr clock_sub ;計測サブ lea.l 30(sp),sp move.l d0,BIOS_MPU_SPEED_RAM_LONG.w if <cmp.l #$0000FFFF,d0>,hi moveq.l #-1,d0 endif move.w d0,BIOS_MPU_SPEED_RAM.w rts ;計測サブ ;>d0.l:計測値。0=失敗 ;?d1-d2/a1 clock_sub: aTCDCR reg a1 lea.l MFP_TCDCR,aTCDCR ;回数初期化 moveq.l #22-8+1,d2 do subq.w #1,d2 move.l #1<<22,d0 lsr.l d2,d0 subq.l #1,d0 ;割り込み禁止 di ;タイマ保存 move.b MFP_IERB-MFP_TCDCR(aTCDCR),-(sp) move.b MFP_IMRB-MFP_TCDCR(aTCDCR),-(sp) move.b MFP_TCDCR-MFP_TCDCR(aTCDCR),-(sp) ;タイマ設定 andi.b #.notb.(MFP_B_TIMERC_MASK|MFP_B_TIMERD_MASK),MFP_IMRB-MFP_TCDCR(aTCDCR) ;Timer-C/D割り込み禁止 andi.b #.notb.(MFP_B_TIMERC_MASK|MFP_B_TIMERD_MASK),MFP_IERB-MFP_TCDCR(aTCDCR) ;Timer-C/D割り込み停止。IPRBクリア ;カウント停止 move.b #0,(aTCDCR) ;Timer-C/Dカウント停止 do while <tst.b (aTCDCR)>,ne ;完全に停止するまで待つ ;カウント開始 move.b #0,MFP_TCDR-MFP_TCDCR(aTCDCR) ;Timer-Cカウンタクリア move.b #0,MFP_TDDR-MFP_TCDCR(aTCDCR) ;Timer-Dカウンタクリア move.b #MFP_50US<<4|MFP_1US,(aTCDCR) ;Timer-C/Dカウント開始 ;Timer-Cは1/200プリスケール(50us) ;Timer-Dは1/4プリスケール(1us) ;計測 jsr (a0) ;カウント停止 move.b #0,(aTCDCR) ;Timer-C/Dカウント停止 do while <tst.b (aTCDCR)>,ne ;完全に停止するまで待つ ;タイマ取得 moveq.l #0,d0 moveq.l #0,d1 sub.b MFP_TCDR-MFP_TCDCR(aTCDCR),d0 ;Timer-Cカウント数 sub.b MFP_TDDR-MFP_TCDCR(aTCDCR),d1 ;Timer-Dカウント数(オーバーフローあり) ;タイマ復元 move.b #200,MFP_TCDR-MFP_TCDCR(aTCDCR) ;Timer-Cカウンタ復元 move.b #0,MFP_TDDR-MFP_TCDCR(aTCDCR) ;Timer-Dカウンタクリア move.b (sp)+,(aTCDCR) move.b (sp)+,MFP_IMRB-MFP_TCDCR(aTCDCR) move.b (sp)+,MFP_IERB-MFP_TCDCR(aTCDCR) ;割り込み許可 ei ;カウンタ合成 mulu.w #50,d0 if <cmp.b d1,d0>,hi add.w #256,d0 endif move.b d1,d0 ;0|us whileand <tst.w d2>,ne,<cmp.w #5000,d0>,lo ;5000usに満たなければ回数を2倍にして計測し直す if <tst.w d0>,ne ;補正 lea.l clock_scale(pc),a1 moveq.l #0,d1 move.b BIOS_MPU_TYPE.w,d1 if <cmp.w #6,d1>,ls lsl.w #2,d1 adda.w d1,a1 endif move.l (a1),d1 lsr.l d2,d1 ;d1=H|L divu.w d0,d1 ;d1=vc?(H|L)%us|(H|L)/us:H|L if vc move.w d1,d0 ;d0=0|(H|L)/us else move.l d1,d2 ;d2=H|L clr.w d2 ;d2=H|0 swap.w d2 ;d2=0|H divu.w d0,d2 ;d2=(0|H)%us|(0|H)/us swap.w d0 ;d0=us|0 move.w d2,d0 ;d0=us|(0|H)/us swap.w d0 ;d0=(0|H)/us|us move.w d1,d2 ;d2=(0|H)%us|L divu.w d0,d2 ;d2=((0|H)%us|L)%us|((0|H)%us|L)/us move.w d2,d0 ;d0=(0|H)/us|((0|H)%us|L)/us endif endif rts ;計測ループ .align 16,$2048 ;内側のdbraを.align 4にする。RAM計測が.align 16なのでROM計測も.align 16にする clock_loop: forlong d0 next rts .align 4 clock_scale: .dc.l 4194304000 ;68000 .dc.l 4194304000 ;68010 .dc.l 4194304000 ;68020 .dc.l 4194304000 ;68030 .dc.l 2796202667 ;68040 .dc.l 0 .dc.l 699050667 ;68060 ; +-----------+---+-------+---------+----+--------+-----+------------------------+-----------------------------------------+-----------------------+ ; | |c/n| f |u/n=c/n/f| n | u=u/n*n| J | K=c/n/J*2^22 | CB8=K/(2^22/n)/u | f=CB8*J | ; +-----------+---+-------+---------+----+--------+-----+------------------------+-----------------------------------------+-----------------------+ ; |68000/68010| 12| 10.000| 1.200 |2^13|9830.400|0.012|4194304000=12/0.012*2^22| 833.333=4194304000/(2^22/2^13)/9830.400| 10.000= 833.333*0.012| ; | | | 16.667| 0.720 |2^13|5898.240| | | 1388.889=4194304000/(2^22/2^13)/5898.240| 16.667= 1388.889*0.012| ; | | | 25.000| 0.480 |2^14|7864.320| | | 2083.333=4194304000/(2^22/2^14)/7864.320| 25.000= 2083.333*0.012| ; | | | 33.333| 0.360 |2^14|5898.240| | | 2777.778=4194304000/(2^22/2^14)/5898.240| 33.333= 2777.778*0.012| ; | | | 50.000| 0.240 |2^15|7864.320| | | 4166.667=4194304000/(2^22/2^15)/7864.320| 50.000= 4166.667*0.012| ; | | | 66.666| 0.180 |2^15|5898.240| | | 5555.556=4194304000/(2^22/2^15)/5898.240| 66.667= 5555.556*0.012| ; | | |100.000| 0.120 |2^16|7864.320| | | 8333.333=4194304000/(2^22/2^16)/7864.320|100.000= 8333.333*0.012| ; | | |750.000| 0.016 |2^19|8388.608| | |62500.000=4194304000/(2^22/2^19)/8388.608|750.000=62500.000*0.012| ; +-----------+---+-------+---------+----+--------+-----+------------------------+-----------------------------------------+-----------------------+ ; |68020/68030| 6| 25.000| 0.240 |2^15|7864.320|0.006|4194304000= 6/0.006*2^22| 4166.667=4194304000/(2^22/2^15)/7864.320| 25.000= 4166.667*0.006| ; | | | 33.333| 0.180 |2^15|5898.240| | | 5555.556=4194304000/(2^22/2^15)/5898.240| 33.333= 5555.556*0.006| ; | | | 50.000| 0.120 |2^16|7864.320| | | 8333.333=4194304000/(2^22/2^16)/7864.320| 50.000= 8333.333*0.006| ; | | |375.000| 0.016 |2^19|8388.608| | |62500.000=4194304000/(2^22/2^19)/8388.608|375.000=62500.000*0.006| ; +-----------+---+-------+---------+----+--------+ +------------------------+-----------------------------------------+-----------------------+ ; | 68040 | 4| 25.000| 0.160 |2^15|5242.880| |2796202667= 4/0.006*2^22| 4166.667=2796202667/(2^22/2^15)/5242.880| 25.000= 4166.667*0.006| ; +-----------+---+-------+---------+----+--------+ +------------------------+-----------------------------------------+-----------------------+ ; | 68060 | 1| 33.333| 0.030 |2^18|7864.320| | 699050667= 1/0.006*2^22| 5555.556= 699050667/(2^22/2^18)/7864.320| 33.333= 5555.556*0.006| ; | | | 50.000| 0.020 |2^18|5242.880| | | 8333.333= 699050667/(2^22/2^18)/5242.880| 50.000= 8333.333*0.006| ; | | | 66.667| 0.015 |2^19|7864.320| | |11111.111= 699050667/(2^22/2^19)/7864.320| 66.667=11111.111*0.006| ; | | | 75.000| 0.013 |2^19|6990.507| | |12500.000= 699050667/(2^22/2^19)/6990.507| 75.000=12500.000*0.006| ; +-----------+---+-------+---------+----+--------+-----+------------------------+-----------------------------------------+-----------------------+ ; 凡例 ; c/n dbraループ1回のサイクル数 ; f 動作周波数(MHz) ; u/n dbraループ1回の所要時間(マイクロ秒) ; n dbraループ回数。2の累乗でuが5000以上10000未満になるように調整する ; u dbraループn回の所要時間(マイクロ秒) ; J 68000/68010のとき0.012、68020/68030/68030/68060は0.006 ; dbraで分岐するときのサイクル数が68000は12サイクル、68030は6サイクルであることに由来する ; K c/n/J*2^22。テーブルから取り出す。2^22はKを2^32未満で最大にして誤差を減らすための係数 ; CB8 [$0CB8].wの値。ROMで計測した動作周波数。X68000はf*250/3、X68030はf*500/3。12倍または6倍することでf*1000として用いる ; 補足 ; 68000/68010のdbraは10サイクルだがROMのときはウエイトがかかるので12サイクルになる ; RAMのときはDRAMのリフレッシュの影響で(1+0.22/f)倍くらいになる ;---------------------------------------------------------------- ; 不具合 ; MC68000のときエリアセットのポートをリードしようとして起動できない ; 解説 ; IPLROM 1.2までMOVE.B $00,$00E86001だったところがIPLROM 1.3でCLR.B $00E86001に変更された ; MC68000のCLR.Bはライトの前にリードする ; エリアセットのポート$00E86001は真にライトオンリーでリードするとバスエラーになる ; したがってMC68000ではCLR.B $00E86001がバスエラーになる ; X68000にX68030のROMを乗せると起動できない原因の1つ ; エミュレータでCLR.Bのリードが省略されている場合は起動できる ; 対策 ; SF.BもリードするのでCLR.BをSF.Bに変更しても駄目 ; 直前のアラーム起動の処理$00FF05BEから復帰したときA0は常にRTCのアドレス$00E8A000を指しているのでこれを使う ; 参考 ; ふってぃさんの一連の考察 ; https://twitter.com/futtyt/status/1332591514963197953 ; 変更前 ; 00FF01B2 423900E86001 clr.b $00E86001 ; 00FF01B8 ;---------------------------------------------------------------- PATCH_DATA area_set,$00FF01B2,$00FF01B7,$423900E8 ;<a0.l:$00E8A000 move.b #$00,$00E86001-$00E8A000(a0) ;---------------------------------------------------------------- ; LCD対応キー ; 変更前 ; 00FF0252 7213 moveq.l #$13,d1 ; 00FF0254 43F80800 lea.l BIOS_BITSNS.w,a1 ; 00FF0258 082900050005 btst.b #5,5(a1) ;Vキー。N|B|V|C|X|Z|]}|:* ; 00FF025E 660A bne.s $00FF026A ; 00FF0260 7210 moveq.l #$10,d1 ; 00FF0262 082900070005 btst.b #7,5(a1) ;Nキー。N|B|V|C|X|Z|]}|:* ; 00FF0268 6718 beq.s $00FF0282 ; 00FF026A 13FC003100E8E00D move.b #$31,$00E8E00D ;SRAM書き込み許可 ; 00FF0272 13C100ED001D move.b d1,$00ED001D ;起動時の画面モード ; 00FF0278 423900E8E00D clr.b $00E8E00D ;SRAM書き込み禁止 ; 00FF027E 70104E4F IOCS _CRTMOD ; 00FF0282 ;---------------------------------------------------------------- PATCH_DATA lcd_key,$00FF0252,$00FF0281,$721343F8 jsr lcd_key bra ($00FF0282)PATCH_ZL PATCH_TEXT lcd_key: moveq.l #0,d1 if <btst.b #KEY_L&7,BIOS_BITSNS+(KEY_L>>3).w>,ne ;Lキーが押されている move.w #$4C00+16,d1 ;画面モード16(768x512)LCD向け ; elif <btst.b #KEY_N&7,BIOS_BITSNS+(KEY_N>>3).w>,mi ;Nキーが押されている elif <tst.b BIOS_BITSNS+(KEY_N>>3).w>,mi ;Nキーが押されている move.w #$4300+16,d1 ;画面モード16(768x512)CRT向け elif <btst.b #KEY_T&7,BIOS_BITSNS+(KEY_T>>3).w>,ne ;Tキーが押されている move.w #$4300+3,d1 ;画面モード3(256x240ノンインターレース)CRT向け elif <btst.b #KEY_V&7,BIOS_BITSNS+(KEY_V>>3).w>,ne ;Vキーが押されている move.w #$4C00+19,d1 ;画面モード19(640x480)LCD向け endif bclr.b #0,BIOS_STARTUP_FLAGS.w ;HITANYKEY=0 if <tst.w d1>,ne bset.b #0,BIOS_STARTUP_FLAGS.w ;HITANYKEY=1 unlocksram move.b d1,SRAM_CRTMOD ;起動時の画面モード locksram IOCS _CRTMOD endif rts ;---------------------------------------------------------------- ; ROMデバッガ ; OPT.2キーが押されているとき、SRAMにあるROMデバッガ起動フラグをOFFまたはCONのときAUXに、AUXのときOFFに変更します ; Dキーが押されているとき、SRAMにあるROMデバッガ起動フラグをOFFまたはAUXのときCONに、CONのときOFFに変更します ; OPT.2キーの効果が一時的なものから永続的なものに変更されていることに注意してください ; 変更前 ; 00FF0286 423809DE clr.b $09DE.w ; 00FF028A 1038080E move.b $080E.w,d0 ; 00FF028E 123900ED0058 move.b $00ED0058,d1 ; 00FF0294 B300 eor.b d1,d0 ; 00FF0296 08000003 btst.l #3,d0 ; 00FF029A 670C beq $00FF02A8 ; 00FF029C 11FC000109DE move.b #1,$09DE.w ; 00FF02A2 207AFD64 movea.l $00FF0008(pc),a0 ; 00FF02A6 4E90 jsr (a0) ; 00FF02A8 ;---------------------------------------------------------------- PATCH_DATA p0286,$00FF0286,$00FF02A7,$423809DE jsr p0286 bra ($00FF02A8)PATCH_ZL PATCH_TEXT p0286: lea.l SRAM_ROMDB,a0 move.b (a0),d0 ;0=OFF,-1=AUX,1=CON do moveq.l #1,d1 ;1=CON if <btst.b #KEY_D&7,BIOS_BITSNS+(KEY_D>>3).w>,eq ;Dキーが押されていない neg.b d1 ;-1=AUX break <btst.b #KEY_OPT2&7,BIOS_BITSNS+(KEY_OPT2>>3).w>,eq ;OPT.2キーが押されていない endif ;DキーまたはOPT.2キーが押されている if <cmp.b d0,d1>,eq ;フラグと同じキーが押されている clr.b d1 ;0=OFF endif if <cmp.b d0,d1>,ne ;フラグが変化する move.b d1,d0 lea.l SYSPORT_SRAM,a1 move.b #$31,(a1) move.b d0,(a0) clr.b (a1) endif while f neg.b d0 ;0=OFF,1=AUX,-1=CON move.b d0,BIOS_ROMDB.w if ne ;1=AUX,-1=CON movea.l $00FF0008,a0 ;ROMデバッガの開始アドレス jsr (a0) ;ROMデバッガを起動する endif rts ;---------------------------------------------------------------- ; 68040/68060のときデバイスドライバがMMUを有効にするまでデータキャッシュをOFFにする ; 変更前 ; 00FF02A8 7202 moveq.l #$02,d1 ; 00FF02AA 70AC moveq.l #_SYS_STAT,d0 ; 00FF02AC 4E4F trap #15 ; 00FF02AE ;---------------------------------------------------------------- PATCH_DATA cache_start,$00FF02A8,$00FF02AD,$720270AC jsr cache_start PATCH_TEXT cache_start: push d2 moveq.l #0,d2 move.b SRAM_CACHE,d2 ;キャッシュ設定。------|データ|命令 if <cmpi.b #4,BIOS_MPU_TYPE.w>,hs ;68040/68060 and.b #.notb.%10,d2 ;データキャッシュOFF endif bsr cache_set ;キャッシュ設定 pop rts ;---------------------------------------------------------------- ; Hit any key ; 変更前 ; 00FF02B2 43FA08D4 lea.l $00FF0B88(pc),a1 ;$1A ; 00FF02B6 61000470 bsr.w $00FF0728 ;文字列表示 ; 00FF02BA ;---------------------------------------------------------------- PATCH_DATA hitanykey,$00FF02B2,$00FF02B9,$43FA08D4 jsr hitanykey PATCH_TEXT hitanykey: if <btst.b #0,BIOS_STARTUP_FLAGS.w>,ne ;HITANYKEY lea.l -64(sp),sp movea.l sp,a0 bsr crlf bsr start_proportional lea.l 100f(pc),a1 ;' Hit any key' bsr strcpy bsr end_proportional bsr crlf movea.l sp,a1 bsr iocs_21_B_PRINT lea.l 64(sp),sp do redo <btst.b #KEY_L&7,BIOS_BITSNS+(KEY_L>>3).w>,ne ;Lキーが押されている ; redo <btst.b #KEY_N&7,BIOS_BITSNS+(KEY_N>>3).w>,ne ;Nキーが押されている redo <tst.b BIOS_BITSNS+(KEY_N>>3).w>,mi ;Nキーが押されている redo <btst.b #KEY_T&7,BIOS_BITSNS+(KEY_T>>3).w>,ne ;Tキーが押されている redo <btst.b #KEY_V&7,BIOS_BITSNS+(KEY_V>>3).w>,ne ;Vキーが押されている while f ;L/N/T/Vキーが離されるまで待つ bsr kflush ;キーバッファを空にする bsr inkey ;キーが押されるまで待つ endif rts 100: .dc.b ' Hit any key',0 .even ;---------------------------------------------------------------- ;プロポーショナルピッチ開始 start_proportional: lea.l 100f(pc),a1 bra 10f ;プロポーショナルピッチ終了 end_proportional: lea.l 101f(pc),a1 10: goto <btst.b #0,message_style(pc)>,ne,strcpy ;プロポーショナルピッチ clr.b (a0) rts 100: .dc.b 27,'[26m',0 101: .dc.b 27,'[50m',0 .even ;---------------------------------------------------------------- ; XF3,XF4,XF5を押しながら起動したときのキャッシュOFF ; 変更前 ; 00FF0336 7000 moveq.l #$00,d0 ; 00FF0338 4E7B0002 movec.l d0,cacr ;キャッシュOFF ; 00FF033C ;---------------------------------------------------------------- PATCH_DATA xf345_cache_off,$00FF0336,$00FF033B,$70004E7B jsr cache_off ;キャッシュOFF ;---------------------------------------------------------------- ; XF1,XF2を押しながら起動したときのキャッシュOFF ; 変更前 ; 00FF0380 7000 moveq.l #$00,d0 ; 00FF0382 4E7B0002 movec.l d0,cacr ;キャッシュOFF ; 00FF0386 ;---------------------------------------------------------------- PATCH_DATA xf12_cache_off,$00FF0380,$00FF0385,$70004E7B jsr cache_off ;キャッシュOFF ;---------------------------------------------------------------- ; 未定義例外処理 ; 68000のときバスエラーとアドレスエラーの例外スタックフレームを掘り起こさない ; TRAP#14(エラー表示)がSSWとACCESS ADDRESSとINSTRUCTION REGISTERにアクセスできる ; 68000以外のときPCの最上位バイトが$02~$0Fならばそれをベクタ番号として使う ; X68030で未定義のFライン命令を実行したとき「エラー($000B)が発生しました」ではなく ; 「おかしな命令を実行しました」と表示される ; 変更前 ; 00FF0762 7E00 moveq.l #$00,d7 ; 00FF0764 3E2F0006 move.w $0006(sp),d7 ; 00FF0768 CE7C0FFF and.w #$0FFF,d7 ;ベクタオフセット ; 00FF076C E44F lsr.w #2,d7 ;ベクタ番号 ; 00FF076E 6042_000007B2 bra $00FF07B2 ;白窓表示 ; 00FF0770 61000002_00000774 bsr $00FF0774 ; 00FF0774 2E1F move.l (sp)+,d7 ;$00FF0774そのもの ; 00FF0776 4A380CBC tst.b BIOS_MPU_TYPE.w ; 00FF077A 66E6_00000762 bne $00FF0762 ; 00FF077C 4247 clr.w d7 ; 00FF077E 4847 swap.w d7 ; 00FF0780 E04F lsr.w #8,d7 ; 00FF0782 BE7C0003 cmp.w #$0003,d7 ; 00FF0786 622A_000007B2 bhi $00FF07B2 ; 00FF0788 5C8F addq.l #6,sp ; 00FF078A 4847 swap.w d7 ; 00FF078C 3E1F move.w (sp)+,d7 ;命令コード ; 00FF078E 2C6F0002 movea.l $0002(sp),a6 ;PC ; 00FF0792 BE56 cmp.w (a6),d7 ; 00FF0794 6714_000007AA beq $00FF07AA ; 00FF0796 BE66 cmp.w -(a6),d7 ; 00FF0798 6710_000007AA beq $00FF07AA ; 00FF079A BE66 cmp.w -(a6),d7 ; 00FF079C 670C_000007AA beq $00FF07AA ; 00FF079E BE66 cmp.w -(a6),d7 ; 00FF07A0 6708_000007AA beq $00FF07AA ; 00FF07A2 BE66 cmp.w -(a6),d7 ; 00FF07A4 6704_000007AA beq $00FF07AA ; 00FF07A6 BE66 cmp.w -(a6),d7 ; 00FF07A8 6604_000007AE bne $00FF07AE ; 00FF07AA 2F4E0002 move.l a6,$0002(sp) ;PCをエラーが発生した命令まで戻す ; 00FF07AE 4247 clr.w d7 ; 00FF07B0 4847 swap.w d7 ; 00FF07B2 2C4F movea.l sp,a6 ; 00FF07B4 4E4E trap #14 ; 00FF07B6 303C00FF move.w #_ABORTJOB,d0 ; 00FF07BA 4E4F trap #15 ; 00FF07BC 60F8_000007B6 bra $00FF07B6 ;無限ループ ; 00FF07BE ;---------------------------------------------------------------- PATCH_DATA p0770,$00FF0770,$00FF0775,$61000002 jsr p0770 ;ここでPCをプッシュする。jmpはPCの最上位バイトが消えてしまうので不可 PATCH_TEXT p0770: moveq.l #0,d7 move.b (sp),d7 ;PCの最上位バイト addq.l #4,sp movea.l sp,a6 ;SRの位置。68000のバスエラーとアドレスエラーを除く if <tst.b BIOS_MPU_TYPE.w>,eq ;68000 ifor <cmp.b #$02,d7>,eq,<cmp.b #$03,d7>,eq ;バスエラーとアドレスエラー ; MC68000UM 6-17 ; 0.w ; 15-5 4 3 2-0 ; X R/W I/N FC ; R/W 0=Write,1=Read ; I/N 0=Instruction,1=Not ; 2.l ACCESS ADDRESS ; 6.w INSTRUCTION REGISTER ; 8.w STATUS REGISTER ; 10.l PROGRAM COUNTER swap.w d7 move.w 6(sp),d7 ;命令コード movea.l 10(sp),a6 ;PC do if <cmp.w (a6),d7>,ne if <cmp.w -(a6),d7>,ne if <cmp.w -(a6),d7>,ne if <cmp.w -(a6),d7>,ne if <cmp.w -(a6),d7>,ne break <cmp.w -(a6),d7>,ne endif endif endif endif move.l a6,10(sp) ;PCをエラーが発生した命令まで戻す endif while f clr.w d7 swap.w d7 lea.l 8(sp),a6 ;SRの位置。SPを掘り起こさない endif else ;68000以外 ifor <cmp.b #$02,d7>,lo,<cmp.b #$0F,d7>,hi ;$02~$0F以外 move.w 6(sp),d7 ;フォーマットとベクタオフセット and.w #$0FFF,d7 ;ベクタオフセット lsr.w #2,d7 ;ベクタ番号 endif endif trap #14 ;TRAP#14(エラー表示) 10: IOCS _ABORTJOB goto 10b ;無限ループ ;---------------------------------------------------------------- ; IOCS _ABORTJOB ; TRAP#14(エラー表示)の変更に合わせて表示を変更する ; 変更前 ; 00FF07BE 6128 bsr $00FF07E8 ;画面モードによってテキスト画面の表示位置を調節する ; 00FF07C0 43F900FF0B53 lea.l $00FF0B53,a1 ;エラーが発生しました。リセットしてください。 ; 00FF07C6 6100FF60 bsr $00FF0728 ;文字列表示 ; 00FF07CA 60FE bra $00FF07CA ;無限ループ ;---------------------------------------------------------------- PATCH_DATA p07BE,$00FF07BE,$00FF07CB,$612843F9 jsr p07BE PATCH_TEXT p07BE: lea.l -64(sp),sp movea.l sp,a0 bsr start_proportional lea.l 100f(pc),a1 ;' Press the RESET switch' bsr strcpy bsr end_proportional movea.l sp,a1 bsr iocs_21_B_PRINT lea.l 64(sp),sp 10: goto 10b ;無限ループ 100: .dc.b ' Press the RESET switch',0 .even ;---------------------------------------------------------------- ; 起動画面 ; 変更前 ; 00FF0E76 48E7F0E0 movem.l d0-d3/a0-a2,-(sp) ; 00FF0E7A 6100025C bsr $00FF10D8 ;起動音 ; 00FF0E7E 6120 bsr $00FF0EA0 ;ロゴ ; 00FF0E80 7200 moveq.l #$00,d1 ; 00FF0E82 70AC4E4F IOCS _SYS_STAT ; 00FF0E86 2600 move.l d0,d3 ; 00FF0E88 61000182 bsr $00FF100C ;ROMのバージョン ; 00FF0E8C 615C bsr $00FF0EEA ;MPUの種類と動作周波数 ; 00FF0E8E 610000EE bsr $00FF0F7E ;FPU/FPCPの有無 ; 00FF0E92 610000F8 bsr $00FF0F8C ;MMUの有無 ; 00FF0E96 61000104 bsr $00FF0F9C ;メインメモリのサイズ ; 00FF0E9A 4CDF070F movem.l (sp)+,d0-d3/a0-a2 ; 00FF0E9E 4E75 rts ; 00FF0EA0 ;---------------------------------------------------------------- PATCH_DATA ipl_message,$00FF0E76,$00FF0E9F,$48E7F0E0 jmp ipl_message PATCH_TEXT ;---------------------------------------------------------------- ;起動画面を表示する ipl_message: push d0-d7/a0-a6,128 ;キー確認 ; SRAM_XEIJは_CRTMODで初期化済み lea.l SRAM_XEIJ,a0 lea.l SYSPORT_SRAM,a1 moveq.l #$31,d2 if <btst.b #0,BIOS_STARTUP_FLAGS.w>,ne ;HITANYKEY move.b d2,(a1) ;unlocksram bclr.b #SRAM_XEIJ_QUIET_BIT,(a0) ;起動画面を表示する clr.b (a1) ;locksram elif <btst.b #KEY_Q&7,BIOS_BITSNS+(KEY_Q>>3).w>,ne ;Qキーが押されている move.b d2,(a1) ;unlocksram bset.b #SRAM_XEIJ_QUIET_BIT,(a0) ;起動画面を表示しない clr.b (a1) ;locksram endif if <btst.b #SRAM_XEIJ_QUIET_BIT,(a0)>,eq ;起動画面を表示する jsr $00FF10D8 ;起動音 jsr $00FF0EA0 ;ロゴ moveq.l #0,d1 IOCS _SYS_STAT move.l d0,d7 ;MPUステータス ;<d7.l:MPUステータス movea.l sp,a6 ;文字列バッファ ;<a6.l:文字列バッファ movea.l a6,a0 if <btst.b #2,message_style(pc)>,ne ;隙間あり bsr crlf endif bsr start_proportional movea.l a6,a1 bsr iocs_21_B_PRINT ;メッセージ bsr ipl_message_romver ;ROMのバージョンを表示する bsr ipl_message_model ;機種を表示する bsr ipl_message_series ;シリーズを表示する bsr ipl_message_mpu ;MPUの種類と動作周波数を表示する bsr ipl_message_mmu ;MMUの有無を表示する bsr ipl_message_fpu ;FPU/FPCPの有無と種類を表示する bsr ipl_message_memory ;メインメモリの範囲と容量を表示する bsr ipl_message_exmemory ;拡張メモリの範囲と容量を表示する bsr ipl_message_coprocessor ;コプロセッサの有無と種類を表示する bsr ipl_message_dmac_clock ;DMACの動作周波数を表示する bsr ipl_message_rtc_dttm ;RTCの日時を表示する bsr ipl_message_hd_type ;内蔵ハードディスクインターフェイスの種類を表示する bsr ipl_message_boot_device ;起動デバイスを表示する ;テキストカーソルを下から7行目に移動させる movea.l a6,a0 move.b #27,(a0)+ move.b #'=',(a0)+ moveq.l #' '-6,d0 add.w BIOS_CONSOLE_BOTTOM.w,d0 move.b d0,(a0)+ ;行 move.b #' '+0,(a0)+ ;桁 bsr end_proportional movea.l a6,a1 bsr iocs_21_B_PRINT endif pop rts ;---------------------------------------------------------------- ;左の列を表示する ;<a1.l:文字列。コロンを含まない ;<a6.l:文字列バッファ print_left_column: push d0/a0-a1 movea.l a6,a0 ;文字列バッファ if <btst.b #1,message_style(pc)>,ne ;中央寄せ move.b #27,(a0)+ move.b #'[',(a0)+ moveq.l #1,d0 add.w BIOS_CONSOLE_RIGHT.w,d0 lsl.w #2,d0 ;コンソールの幅(px)/2 bsr utos move.b #'r',(a0)+ ;左の列を中央までの右寄せで表示する bsr strcpy lea.l 100f(pc),a1 ;' : ',1 bsr strcpy else ;左寄せ move.l a1,d0 if <btst.b #0,message_style(pc)>,ne ;プロポーショナルピッチ lea.l 101f(pc),a1 ;27,'[320l'。左寄せ40文字 else ;ノーマルピッチ lea.l 102f(pc),a1 ;27,'[304l'。左寄せ38文字 endif bsr strcpy movea.l d0,a1 bsr strcpy lea.l 103f(pc),a1 ;1,' : ' bsr strcpy endif movea.l a6,a1 ;文字列バッファ bsr iocs_21_B_PRINT pop rts 100: .dc.b ' : ',1,0 101: .dc.b 27,'[320l',0 102: .dc.b 27,'[304l',0 103: .dc.b 1,' : ',0 .even ;---------------------------------------------------------------- ;ROMのバージョンを表示する ;<a6.l:文字列バッファ ;?d0-d1/a0-a1 ipl_message_romver: lea.l 100f(pc),a1 ;'ROM version' bsr print_left_column IOCS _ROMVER ;BCD変換 move.l d0,d1 ;abcdefgh clr.w d0 ;abcd0000 sub.l d0,d1 ;0000efgh swap.w d0 ;0000abcd lsl.l #4,d0 ;000abcd0 lsl.l #4,d1 ;000efgh0 lsr.w #4,d0 ;000a0bcd lsr.w #4,d1 ;000e0fgh lsl.l #8,d0 ;0a0bcd00 lsl.l #8,d1 ;0e0fgh00 lsr.w #4,d0 ;0a0b0cd0 lsr.w #4,d1 ;0e0f0gh0 lsr.b #4,d0 ;0a0b0c0d lsr.b #4,d1 ;0e0f0g0h or.l #$30303030,d0 ;3a3b3c3d or.l #$30303030,d1 ;3e3f3g3h ;バージョン movea.l a6,a0 ;文字列バッファ rol.l #8,d0 move.b d0,(a0)+ move.b #'.',(a0)+ rol.l #8,d0 move.b d0,(a0)+ ;日付 move.b #' ',(a0)+ move.b #'(',(a0)+ rol.l #8,d0 if <cmp.b #'8',d0>,hs move.b #'1',(a0)+ move.b #'9',(a0)+ else move.b #'2',(a0)+ move.b #'0',(a0)+ endif move.b d0,(a0)+ rol.l #8,d0 move.b d0,(a0)+ move.b #'-',(a0)+ rol.l #8,d1 move.b d1,(a0)+ rol.l #8,d1 move.b d1,(a0)+ move.b #'-',(a0)+ rol.l #8,d1 move.b d1,(a0)+ rol.l #8,d1 move.b d1,(a0)+ move.b #')',(a0)+ bsr crlf movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'ROM Version',0 .even ;---------------------------------------------------------------- ;機種を表示する ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?a0-a1 ipl_message_model: if <cmpi.l #'NAME',$00FFFFE0>,ne ;機種名がない rts endif lea.l 100f(pc),a1 ;'Model' bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l $00FFFFE4,a1 bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Model',0 .even ;---------------------------------------------------------------- ;シリーズを表示する ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?a0-a1 ipl_message_series: lea.l 100f(pc),a1 ;'Series' bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l 101f(pc),a1 ;'X68000' if <isX68030>,eq lea.l 102f(pc),a1 ;'X68030' endif bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Series',0 101: .dc.b 'X68000',0 102: .dc.b 'X68030',0 .even ;---------------------------------------------------------------- ;MPUの種類と動作周波数を表示する ; XCとMC ; 000/010/020/030/040はMC ; 060はリビジョン5までXC、リビジョン6からMC ; http://www.ppa.pl/forum/amiga/29981/68060-pcr ; ? リビジョン0 ; F43G リビジョン1 ; G65V リビジョン5 ; G59Y ? ; E41J リビジョン6 ; 無印とECとLC ; 000/010/020は無印 ; 030はMMUがないときEC、MMUがあるとき無印 ; 040/060はMMUがないときEC、MMUがあってFPUがないときLC、MMUとFPUがあるとき無印 ; リビジョンナンバー ; 060のとき末尾に-dddでリビジョンナンバーを表示する ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?d0-d2/a0-a1 ipl_message_mpu: lea.l 100f(pc),a1 ;'Microprocessor' bsr print_left_column movea.l a6,a0 ;文字列バッファ ;型番 moveq.l #-1,d2 ;リビジョンナンバー。-1=リビジョンナンバーなし moveq.l #'M',d1 if <cmp.b #6,d7>,eq ;060 .cpu 68060 movec.l pcr,d0 .cpu 68000 lsr.l #8,d0 moveq.l #0,d2 move.b d0,d2 ;リビジョンナンバー if <cmp.b #6,d2>,lo moveq.l #'X',d1 ;060はリビジョン5までXC endif endif move.b d1,(a0)+ ;'M'または'X' lea.l 101f(pc),a1 ;'C68' bsr strcpy do break <cmp.b #3,d7>,lo ;000/010/020は無印 moveq.l #'E',d1 ;030/040/060でMMUがないときEC if <btst.l #14,d7>,ne ;030/040/060でMMUがあるとき break <cmp.b #3,d7>,eq ;030でMMUがあるとき無印 break <tst.w d7>,mi ;040/060でMMUとFPUがあるとき無印 moveq.l #'L',d1 ;040/060でMMUがあってFPUがないときLC endif move.b d1,(a0)+ ;'E'または'L' move.b #'C',(a0)+ ;'C' while f move.b #'0',(a0)+ ;'0' moveq.l #'0',d1 add.b d7,d1 move.b d1,(a0)+ ;'0'~'6' move.b #'0',(a0)+ ;'0' move.l d2,d0 ;リビジョンナンバー if pl move.b #'-',(a0)+ moveq.l #3,d1 bsr utosz endif ;動作周波数 move.b #' ',(a0)+ move.b #'(',(a0)+ move.l d7,d0 clr.w d0 swap.w d0 ;動作周波数(MHz)*10 bsr utos move.b -1(a0),(a0)+ ;小数点以下1桁目を後ろにずらす move.b #'.',-2(a0) ;小数点を押し込む lea.l 102f(pc),a1 ;'MHz)' bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Microprocessor',0 101: .dc.b 'C68',0 102: .dc.b 'MHz)',0 .even ;---------------------------------------------------------------- ;FPU/FPCPの有無と種類を表示する ; 030はfmovecr.x #1,fp0が0のときMC68881、さもなくばMC68882 ; 040/060はon-chip ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?d0/a0-a1 ipl_message_fpu: if <tst.w d7>,pl ;FPU/FPCPなし rts endif lea.l 100f(pc),a1 ;'Floating-Point Unit (FPU)' if <cmp.b #4,d7>,lo ;020/030 lea.l 101f(pc),a1 ;'Floating-Point Coprocessor (FPCP)' endif bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l 102f(pc),a1 ;'on-chip' if <cmp.b #4,d7>,lo ;020/030 lea.l 103f(pc),a1 ;'MC68881' .cpu 68030 fmovecr.x #1,fp0 ;0=MC68881,0以外=MC68882 fmove.x fp0,-(sp) .cpu 68000 move.l (sp)+,d0 or.l (sp)+,d0 or.l (sp)+,d0 if ne lea.l 104f(pc),a1 ;'MC68882' endif endif bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Floating-Point Unit (FPU)',0 101: .dc.b 'Floating-Point Coprocessor (FPCP)',0 102: .dc.b 'on-chip',0 103: .dc.b 'MC68881',0 104: .dc.b 'MC68882',0 .even ;---------------------------------------------------------------- ;MMUの有無を表示する ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?d0/a0-a1 ipl_message_mmu: if <btst.l #14,d7>,eq ;MMUなし rts endif lea.l 100f(pc),a1 ;'Memory Management Unit (MMU)' bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l 101f(pc),a1 ;'on-chip' if <cmp.b #3,d7>,lo ;020 lea.l 102f(pc),a1 ;'MC68851' endif bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Memory Management Unit (MMU)',0 101: .dc.b 'on-chip',0 102: .dc.b 'MC68851',0 .even ;---------------------------------------------------------------- ;メインメモリの範囲と容量を表示する ; $00100000-$00BFFFFFについて1MB単位でメインメモリの有無を確認し、メインメモリが存在する範囲を表示する ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?d0-d1/a0-a1 ipl_message_memory: lea.l 100f(pc),a1 ;'Main Memory' bsr print_left_column moveq.l #0,d0 ;開始アドレス move.l BIOS_MEMORY_SIZE.w,d1 ;終了アドレス(これを含まない) ;---------------------------------------------------------------- ;メモリの範囲と容量を表示する ;<d0.l:開始アドレス ;<d1.l:終了アドレス(これを含まない) ;<a6.l:文字列バッファ ;?d0/a0-a1 ipl_message_memory_sub: movea.l a6,a0 ;文字列バッファ move.b #'$',(a0)+ bsr h8tos ;開始アドレス move.b #'-',(a0)+ move.b #'$',(a0)+ move.l d0,-(sp) ;開始アドレス move.l d1,d0 ;終了アドレス(これを含まない) subq.l #1,d0 ;終了アドレス(これを含む) bsr h8tos move.b #' ',(a0)+ move.b #'(',(a0)+ move.l d1,d0 ;終了アドレス(これを含まない) sub.l (sp)+,d0 ;終了アドレス(これを含まない)-開始アドレス=容量 clr.w d0 swap.w d0 lsr.w #4,d0 ;容量(16MB単位) bsr utos lea.l 101f(pc),a1 ;'MB)' bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Main Memory',0 101: .dc.b 'MB)',0 .even ;---------------------------------------------------------------- ;拡張メモリの範囲と容量を表示する ; $01000000-$FFFFFFFFについて16MB単位で独立した拡張メモリの有無を確認し、拡張メモリが存在する範囲を表示する ; 手順 ; 各ページの同じオフセットに上位のページから順に異なるデータを書き込む ; 下位のページに書き込んだことで上位のページのデータが変化した場合は上位のページは存在しないと判断する ; $2000-$21FFをワークとして使用する ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?d0-d1/a0-a3/a5 ipl_message_exmemory: ; if <cmp.b #2,d7>,lo ;000/010 ; rts ; endif ;確認開始 di ;sr保存、割り込み禁止 move.l OFFSET_BUS_ERROR.w,-(sp) ;バスエラーベクタ保存 movea.l sp,a5 ;sp保存 ;読み出し、保存 move.l #@f,OFFSET_BUS_ERROR.w suba.l a2,a2 ;ページの先頭。a2=page<<24 lea.l $2200.w,a1 ;保存領域。a1=$2100+page lea.l $2100.w,a0 ;結果領域。a0=$2000+page move.w #$00FF,d1 ;ページ番号。d1=page for d1 suba.l #$01000000,a2 subq.l #1,a1 st.b -(a0) ;$FF=読み出し失敗 nop move.b (a2),(a1) ;読み出し、保存。-(a1)はバスエラーのときずれるので不可 nop sf.b (a0) ;$00=読み出し成功 @@: movea.l a5,sp ;sp復元 next ;書き込み move.l #@f,OFFSET_BUS_ERROR.w suba.l a2,a2 lea.l $2100.w,a0 move.w #$00FF,d1 for d1 suba.l #$01000000,a2 if <tst.b -(a0)>,eq ;$00=読み出し成功のとき st.b (a0) ;$FF=書き込み失敗 nop move.b d1,(a2) ;書き込み nop sf.b (a0) ;$00=読み出し成功かつ書き込み成功,$FF=読み出し失敗または書き込み失敗 @@: movea.l a5,sp ;sp復元 endif next ;比較 move.l #@f,OFFSET_BUS_ERROR.w suba.l a2,a2 lea.l $2100.w,a0 move.w #$00FF,d1 for d1 suba.l #$01000000,a2 if <tst.b -(a0)>,eq ;$00=読み出し成功かつ書き込み成功のとき nop cmp.b (a2),d1 ;比較 nop sne.b (a0) ;$00=一致,$FF=読み出し失敗または書き込み失敗または不一致 @@: movea.l a5,sp ;sp復元 endif next ;復元 move.l #@f,OFFSET_BUS_ERROR.w suba.l a2,a2 lea.l $2200.w,a1 move.w #$00FF,d1 for d1 suba.l #$01000000,a2 nop move.b -(a1),(a2) ;復元 nop @@: movea.l a5,sp ;sp復元 next ;確認終了 move.l (sp)+,OFFSET_BUS_ERROR.w ;バスエラーベクタ復元 ei ;sr復元 ;表示 suba.l a2,a2 ;開始位置。a2=$2000+page。0=page-1に拡張メモリはない lea.l $2000+1.w,a3 ;終了位置。a3=$2000+page do if <tst.b (a3)>,eq ;ある continue <move.l a2,d0>,ne ;ある→ある ;ない→ある movea.l a3,a2 ;開始位置 else ;ない continue <move.l a2,d0>,eq ;ない→ない ;ある→ない bsr ipl_message_exmemory_sub ;拡張メモリの範囲と容量を1つ表示する suba.l a2,a2 ;開始位置 endif while <addq.l #1,a3>,<cmpa.w #$20FF,a3>,ls if <move.l a2,d0>,ne ;ある→ない bsr ipl_message_exmemory_sub ;拡張メモリの範囲と容量を1つ表示する endif ;後始末 lea.l $2000.w,a0 moveq.l #($2200-$2000)/4-1,d0 for d0 clr.l (a0)+ next rts ;---------------------------------------------------------------- ;拡張メモリの範囲と容量を1つ表示する ;<a2.l:$2000+page。開始位置 ;<a3.l:$2000+page。終了位置(これを含まない) ;<a6.l:文字列バッファ ;?d0-d1/a0-a1 ipl_message_exmemory_sub: lea.l 100f(pc),a1 ;'Extension Memory' bsr print_left_column move.l a2,d0 swap.w d0 lsl.l #8,d0 ;開始アドレス move.l a3,d1 swap.w d1 lsl.l #8,d1 ;終了アドレス(これを含まない) goto ipl_message_memory_sub 100: .dc.b 'Extension Memory',0 .even ;---------------------------------------------------------------- ;コプロセッサの有無と種類を表示する ; マザーボードコプロセッサ ; 040/060でFC=7の$00022000にCIRがある ; 数値演算プロセッサボード1 ; $00E9E000にCIRがある ; 数値演算プロセッサボード2 ; $00E9E080にCIRがある ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ipl_message_coprocessor: ;マザーボードコプロセッサ if <cmp.b #4,d7>,hs ;040/060 bsr copro_check_1 if <tst.l d0>,pl ;マザーボードコプロセッサがある lea.l 105f(pc),a1 ;'Motherboard Coprocessor' bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l 103f(pc),a1 ;'MC68881' if <tst.l d0>,ne lea.l 104f(pc),a1 ;'MC68882' endif bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ bsr iocs_21_B_PRINT endif endif ;数値演算プロセッサボード1 moveq.l #0,d0 bsr copro_check_2 if <tst.l d0>,pl ;数値演算プロセッサボード1がある lea.l 106f(pc),a1 ;'Extension Coprocessor #1' bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l 103f(pc),a1 ;'MC68881' if <tst.l d0>,ne lea.l 104f(pc),a1 ;'MC68882' endif bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ bsr iocs_21_B_PRINT endif ;数値演算プロセッサボード2 moveq.l #1,d0 bsr copro_check_2 if <tst.l d0>,pl ;数値演算プロセッサボード2がある lea.l 107f(pc),a1 ;'Extension Coprocessor #2' bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l 103f(pc),a1 ;'MC68881',13,10 if <tst.l d0>,ne lea.l 104f(pc),a1 ;'MC68882',13,10 endif bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ bsr iocs_21_B_PRINT endif rts 105: .dc.b 'Motherboard Coprocessor',0 106: .dc.b 'Extension Coprocessor #1',0 107: .dc.b 'Extension Coprocessor #2',0 103: .dc.b 'MC68881',0 104: .dc.b 'MC68882',0 .even ;---------------------------------------------------------------- ;マザーボードコプロセッサの有無と種類を調べる ; 1ms以内に判別できなければ諦める。Timer-Cが動作していること ;>d0.l:-1=なし,0=MC68881,1=MC68882 .cpu 68060 copro_check_1: moveq.l #-1,d0 ;-1=なし if <cmpi.b #4,BIOS_MPU_TYPE.w>,lo ;000/010/020/030 rts endif push d1-d5/a0-a3 lea.l $00022000,a0 ;マザーボードコプロセッサのCIR ;<a0.l:FPCP_CIR lea.l MFP_TCDR,a3 ;<a3.l:MFP_TCDR move.w sr,d2 ;sr保存 ;<d2.w:srの元の値 ori.w #$0700,sr ;割り込み禁止 move.b (a3),d3 sub.b #20,d3 ;50us*20=1ms if ls add.b #200,d3 endif ;<d3.b:1ms後のMFP_TCDRの値 movec.l dfc,d4 ;dfc保存 ;<d4.l:dfcの元の値 movec.l sfc,d5 ;sfc保存 ;<d5.l:sfcの元の値 moveq.l #7,d1 ;CPU空間 movec.l d1,dfc movec.l d1,sfc movea.l OFFSET_BUS_ERROR.w,a2 ;バスエラー保存 ;<a2.l:バスエラーの元のベクタ lea.l copro_check_1_abort(pc),a1 move.l a1,OFFSET_BUS_ERROR.w movea.l sp,a1 ;sp保存 ;<a1.l:spの元の値 clr.w d1 ;null moves.w d1,$06(a0) ;restore moves.w $06(a0),d1 ;restore do goto <cmp.b (a3),d3>,eq,copro_check_1_abort ;タイムアウト moves.w (a0),d1 ;response ; and.w #$7FFF,d1 ;clear CA while <cmp.w #$0802,d1>,ne ;idle move.w #$5C01,d1 ;fmovecr.x #$01,fp0 moves.w d1,$0A(a0) ;command do goto <cmp.b (a3),d3>,eq,copro_check_1_abort ;タイムアウト moves.w (a0),d1 ;response ; and.w #$7FFF,d1 ;clear CA while <cmp.w #$0802,d1>,ne ;idle move.w #$6800,d1 ;fmove.x fp0,<mem> moves.w d1,$0A(a0) ;command do goto <cmp.b (a3),d3>,eq,copro_check_1_abort ;タイムアウト moves.w (a0),d1 ;response ; and.w #$7FFF,d1 ;clear CA ; while <cmp.w #$320C,d1>,ne ;extended to mem while <cmp.w #$8900,d1>,eq ;busy moves.l $10(a0),d0 ;operand moves.l $10(a0),d1 ;operand or.l d1,d0 moves.l $10(a0),d1 ;operand or.l d1,d0 ;0=MC68881 if ne moveq.l #1,d0 ;1=MC68882 endif copro_check_1_abort: movea.l a1,sp ;sp復元 move.l a2,OFFSET_BUS_ERROR.w ;バスエラー復元 movec.l d5,sfc ;sfc復元 movec.l d4,dfc ;dfc復元 move.w d2,sr ;sr復元 pop rts .cpu 68000 ;---------------------------------------------------------------- ;数値演算プロセッサボードの有無と種類を調べる ; 1ms以内に判別できなければ諦める。Timer-Cが動作していること ;<d0.l:0=数値演算プロセッサボード1,1=数値演算プロセッサボード2 ;>d0.l:-1=なし,0=MC68881,1=MC68882 copro_check_2: push d1-d3/a0-a3 lea.l $00E9E000,a0 ;数値演算プロセッサボード1のCIR if <tst.l d0>,ne lea.l $00E9E080-$00E9E000(a0),a0 ;数値演算プロセッサボード2のCIR endif ;<a0.l:FPCP_CIR lea.l MFP_TCDR,a3 ;<a3.l:MFP_TCDR moveq.l #-1,d0 ;-1=なし ;<d0.l:-1=なし,0=MC68881,1=MC68882 move.w sr,d2 ;sr保存 ;<d2.w:srの元の値 ori.w #$0700,sr ;割り込み禁止 move.b (a3),d3 sub.b #20,d3 ;50us*20=1ms if ls add.b #200,d3 endif ;<d3.b:1ms後のMFP_TCDRの値 movea.l OFFSET_BUS_ERROR.w,a2 ;バスエラー保存 ;<a2.l:バスエラーの元のベクタ lea.l copro_check_2_abort(pc),a1 move.l a1,OFFSET_BUS_ERROR.w movea.l sp,a1 ;sp保存 ;<a1.l:spの元の値 move.w #$0000,$06(a0) ;restore,null tst.w $06(a0) ;restore do goto <cmp.b (a3),d3>,eq,copro_check_2_abort ;タイムアウト move.w (a0),d1 ;response ; and.w #$7FFF,d1 ;clear CA while <cmp.w #$0802,d1>,ne ;idle move.w #$5C01,$0A(a0) ;command,fmovecr.x #$01,fp0 do goto <cmp.b (a3),d3>,eq,copro_check_2_abort ;タイムアウト move.w (a0),d1 ;response ; and.w #$7FFF,d1 ;clear CA while <cmp.w #$0802,d1>,ne ;idle move.w #$6800,$0A(a0) ;command,fmove.x fp0,<mem> do goto <cmp.b (a3),d3>,eq,copro_check_2_abort ;タイムアウト move.w (a0),d1 ;response ; and.w #$7FFF,d1 ;clear CA ; while <cmp.w #$320C,d1>,ne ;extended to mem while <cmp.w #$8900,d1>,eq ;busy move.l $10(a0),d0 ;operand move.l $10(a0),d1 ;operand or.l d1,d0 move.l $10(a0),d1 ;operand or.l d1,d0 ;0=MC68881 if ne moveq.l #1,d0 ;1=MC68882 endif copro_check_2_abort: movea.l a1,sp ;sp復元 move.l a2,OFFSET_BUS_ERROR.w ;バスエラー復元 move.w d2,sr ;sr復元。割り込み許可 pop rts ;---------------------------------------------------------------- ;DMACの動作周波数を表示する ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?d0-d2/a0-a1 ipl_message_dmac_clock: lea.l 100f(pc),a1 ;'Direct Memory Access Controller (DMAC)' bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l 101f(pc),a1 ;'HD63450 (Main Memory:' bsr strcpy lea.l $6800.w,a2 bsr measure_dmac_clock bsr utos lea.l 102f(pc),a1 ;'%, SRAM:' bsr strcpy lea.l $00ED0000,a2 bsr measure_dmac_clock bsr utos lea.l 103f(pc),a1 ;'%)',13,10 bsr strcpy movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Direct Memory Access Controller (DMAC)',0 101: .dc.b 'HD63450 (Main Memory:',0 102: .dc.b '%, SRAM:',0 103: .dc.b '%)',13,10,0 .even ;---------------------------------------------------------------- ;DMACの動作周波数を計測する ; DMACが(a2)から(a2)へ5000ワード転送するのにかかる時間をus単位で計る ; 10MHzの10サイクル/ワードを100%とする%値を返す ;<a2.l:アドレス ;>d0.l:DMACの動作速度。10MHzの10サイクル/ワードを100%とする%値 measure_dmac_clock: push d1-d2/a0-a1 aDMAC reg a0 lea.l DMAC_2_BASE,aDMAC aTCDCR reg a1 lea.l MFP_TCDCR,aTCDCR ;キャッシュ禁止 bsr cache_off move.l d0,d2 ;割り込み禁止 di ;SRAM書き込み許可 unlocksram ;DMAC保存 move.b DMAC_DCR(aDMAC),-(sp) move.b DMAC_OCR(aDMAC),-(sp) move.b DMAC_SCR(aDMAC),-(sp) move.b DMAC_MFC(aDMAC),-(sp) move.b DMAC_CPR(aDMAC),-(sp) move.b DMAC_DFC(aDMAC),-(sp) ;DMAC設定 st.b DMAC_CSR(aDMAC) ;CSRクリア move.b #DMAC_BURST_TRANSFER|DMAC_HD68000_COMPATIBLE|DMAC_16_BIT_PORT|DMAC_STATUS_INPUT,DMAC_DCR(aDMAC) move.b #DMAC_MEMORY_TO_DEVICE|DMAC_16_BIT_OPERAND|DMAC_NO_CHAINING|DMAC_AUTO_REQUEST_MAX,DMAC_OCR(aDMAC) move.b #DMAC_INCREMENT_MEMORY|DMAC_INCREMENT_DEVICE,DMAC_SCR(aDMAC) move.b #DMAC_HIGHEST_PRIORITY,DMAC_CPR(aDMAC) move.b #DMAC_SUPERVISOR_DATA,DMAC_MFC(aDMAC) move.b #DMAC_SUPERVISOR_DATA,DMAC_DFC(aDMAC) move.l a2,DMAC_MAR(aDMAC) ;転送元 move.l a2,DMAC_DAR(aDMAC) ;転送先 move.w #5000,DMAC_MTC(aDMAC) ;転送オペランド数 ;タイマ保存 move.b MFP_IERB-MFP_TCDCR(aTCDCR),-(sp) move.b MFP_IMRB-MFP_TCDCR(aTCDCR),-(sp) move.b (aTCDCR),-(sp) ;タイマ設定 andi.b #.notb.(MFP_B_TIMERC_MASK|MFP_B_TIMERD_MASK),MFP_IERB-MFP_TCDCR(aTCDCR) ;Timer-C/D割り込み停止 andi.b #.notb.(MFP_B_TIMERC_MASK|MFP_B_TIMERD_MASK),MFP_IMRB-MFP_TCDCR(aTCDCR) ;Timer-C/D割り込み禁止 move.b #0,(aTCDCR) ;Timer-C/Dカウント停止 do while <tst.b (aTCDCR)>,ne ;完全に停止するまで待つ move.b #0,MFP_TCDR-MFP_TCDCR(aTCDCR) ;Timer-Cカウンタクリア move.b #0,MFP_TDDR-MFP_TCDCR(aTCDCR) ;Timer-Dカウンタクリア ;カウント開始 move.b #MFP_50US<<4|MFP_1US,(aTCDCR) ;Timer-C/Dカウント開始 ;Timer-Cは1/200プリスケール(50us) ;Timer-Dは1/4プリスケール(1us) ;DMA転送実行 ; DMA転送中はMPUのバスアクセスが制限されることに注意 move.b #DMAC_CCR_STR,DMAC_CCR(aDMAC) ;DMA転送開始 .rept 8 nop ;12.5MHzで7サイクル(560ns)待つ .endm do while <tst.b DMAC_CSR(aDMAC)>,pl ;DMA転送終了を待つ ;カウント停止 move.b #0,(aTCDCR) ;Timer-C/Dカウント停止 do while <tst.b (aTCDCR)>,ne ;完全に停止するまで待つ ;タイマ取得 moveq.l #0,d0 sub.b MFP_TCDR-MFP_TCDCR(aTCDCR),d0 ;Timer-Cカウント数 moveq.l #0,d1 sub.b MFP_TDDR-MFP_TCDCR(aTCDCR),d1 ;Timer-Dカウント数(オーバーフローあり) ;タイマ復元 move.b #200,MFP_TCDR-MFP_TCDCR(aTCDCR) ;Timer-Cカウンタ復元 move.b #0,MFP_TDDR-MFP_TCDCR(aTCDCR) ;Timer-Dカウンタクリア move.b (sp)+,(aTCDCR) move.b (sp)+,MFP_IMRB-MFP_TCDCR(aTCDCR) move.b (sp)+,MFP_IERB-MFP_TCDCR(aTCDCR) ;DMAC復元 st.b DMAC_CSR(aDMAC) ;CSRクリア move.b (sp)+,DMAC_DFC(aDMAC) move.b (sp)+,DMAC_CPR(aDMAC) move.b (sp)+,DMAC_MFC(aDMAC) move.b (sp)+,DMAC_SCR(aDMAC) move.b (sp)+,DMAC_OCR(aDMAC) move.b (sp)+,DMAC_DCR(aDMAC) ;SRAM書き込み禁止 locksram ;割り込み許可 ei ;カウンタ合成 mulu.w #50,d0 if <cmp.b d1,d0>,hi add.w #256,d0 endif move.b d1,d0 subq.w #1,d0 ;<d0.l:SRAMからSRAMへ5000ワードDMA転送するのにかかった時間(us)。0~12799 ;10サイクル/ワードで10MHzを100%とする%値を求める ; 10(サイクル/ワード)/(d0/5000)(us/ワード)/10(MHz)*100 = 10*5000/d0*10 move.l #10*5000*10,d1 ;d1=被除数 divu.w d0,d1 ;d1=余り<<16|商 swap.w d1 ;d1=商<<16|余り lsr.w #1,d0 ;d0=除数/2 sub.w d1,d0 ;d0=除数/2-余り。x=除数/2<余り?1:0 swap.w d1 ;d1=余り<<16|商 moveq.l #0,d0 addx.w d1,d0 ;<d0.l:10MHzの10サイクル/ワードを100%とする%値 ;キャッシュ許可 move.l d0,d1 bsr cache_set move.l d1,d0 pop rts ;---------------------------------------------------------------- ;RTCの日時を表示する ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?d0-d2/a0-a1 ipl_message_rtc_dttm: lea.l 100f(pc),a1 ;'Real Time Clock (RTC)' bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l 101f(pc),a1 ;'RP5C15 (' bsr strcpy ;RTCから日時を読み出す bsr readrtc if pl bsr checkdttm endif ;<d0.l:0=正常,-1=異常 ;<d1.l:曜日<<28|西暦年<<16|月<<8|月通日 ;<d2.l:時<<16|分<<8|秒 ;異常のとき取り消し線開始 if <tst.l d0>,mi lea.l 102f(pc),a1 ;27,'[9m' bsr strcpy endif ;日時を文字列に変換する bsr dttmtos ;異常のとき取り消し線終了 if <tst.l d0>,mi lea.l 103f(pc),a1 ;27,'[29m' bsr strcpy endif lea.l 104f(pc),a1 ;')',13,10 bsr strcpy movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Real Time Clock (RTC)',0 101: .dc.b 'RP5C15 (',0 102: .dc.b 27,'[9m',0 103: .dc.b 27,'[29m',0 104: .dc.b ')',13,10,0 .even ;-------------------------------------------------------------------------------- ;日時を文字列に変換する ;<d1.l:曜日<<28|西暦年<<16|月<<8|月通日 ;<d2.l:時<<16|分<<8|秒 ;<a0.l:バッファ ;>a0.l:0の位置 dttmtos: push d0-d2 swap.w d1 ;d1.l:月<<24|月通日<<16|曜日<<12|西暦年 move.l #$00000FFF,d0 and.w d1,d0 ;d0.l:西暦年 bsr utos move.b #'-',(a0)+ rol.l #8,d1 ;d1.l:月通日<<24|曜日<<20|西暦年<<8|月 moveq.l #0,d0 move.b d1,d0 ;d0.l:月 bsr 50f move.b #'-',(a0)+ rol.l #8,d1 ;d1.l:曜日<<28|西暦年<<16|月<<8|月通日 moveq.l #0,d0 move.b d1,d0 ;d0.l:月通日 bsr 50f move.b #' ',(a0)+ move.b #'(',(a0)+ rol.l #4,d1 ;d1.l:西暦年<<20|月<<12|月通日<<4|曜日 moveq.l #$0F,d0 and.b d1,d0 ;d0.l:曜日 if <cmp.b #7,d0>,hi moveq.l #7,d0 endif lsl.b #2,d0 ;4*曜日 lea.l 100f(pc,d0.w),a1 bsr strcpy move.b #')',(a0)+ move.b #' ',(a0)+ swap.w d2 ;d2.l:分<<24|秒<<16|時 moveq.l #0,d0 move.b d2,d0 ;d0.l:時 bsr 50f move.b #':',(a0)+ rol.l #8,d2 ;d2.l:秒<<24|時<<8|分 moveq.l #0,d0 move.b d2,d0 ;d0.l:分 bsr 50f move.b #':',(a0)+ rol.l #8,d2 ;d2.l:|時<<16|分<<8|秒 moveq.l #0,d0 move.b d2,d0 ;d0.l:秒 bsr 50f pop rts 50: if <cmp.b #10,d0>,lo move.b #'0',(a0)+ endif goto utos 100: .dc.b 'Sun',0 .dc.b 'Mon',0 .dc.b 'Tue',0 .dc.b 'Wed',0 .dc.b 'Thu',0 .dc.b 'Fri',0 .dc.b 'Sat',0 .dc.b '???',0 .even ;-------------------------------------------------------------------------------- ;RTCから日時を読み出す ; スーパーバイザモードで呼び出すこと ;>d0.l:0=正常,-1=異常 ;>d1.l:曜日<<28|西暦年<<16|月<<8|月通日 ;>d2.l:時<<16|分<<8|秒 ; 曜日 正常のとき0~6。0=日曜日,…,6=土曜日 ; 西暦年 正常のとき1980~2079 ; 月 正常のとき1~12 ; 月通日 正常のとき1~月の日数 ; 時 正常のとき0~23 ; 分 正常のとき0~59 ; 秒 正常のとき0~59 ; 異常のとき範囲外の値が返ることがある ;>ccr:pl=正常,mi=異常 ; 異常の内容 ; ・BCDが異常 readrtc: push d3-d4/d7/a0-a2 moveq.l #0,d7 ;正常 aRTC reg a1 rtc reg -RTC_MODE(aRTC) lea.l RTC_MODE,aRTC aPPIA reg a2 lea.l PPI_PORT_A,aPPIA ;------------------------------------------------ ;RTCのレジスタを読み出す ; 複数のレジスタを読み出している間に時計が進みレジスタの内容が変化する場合がある ; 上位から読んで最下位が0のとき(繰り上がりにかかる時間待ってから)読み直す moveq.l #2-1,d4 for d4 moveq.l #RTC_MODE_BANK_MASK,d0 or.b (RTC_MODE)rtc,d0 tst.b (aPPIA) tst.b (aPPIA) move.b d0,(RTC_MODE)rtc ;バンク1 tst.b (aPPIA) tst.b (aPPIA) moveq.l #$01,d2 and.b (RTC_1_TWENTY_FOUR)rtc,d2 ;0=12時間計,1=24時間計 subq.b #1,d0 tst.b (aPPIA) tst.b (aPPIA) move.b d0,(RTC_MODE)rtc ;バンク0 tst.b (aPPIA) tst.b (aPPIA) moveq.l #$07,d1 and.b (RTC_0_DAY_OF_WEEK)rtc,d1 ;曜日カウンタ lea.l (RTC_0_TEN_YEARS+1)rtc,a0 ;10年カウンタの直後 moveq.l #6-1,d3 for d3 moveq.l #$0F,d0 and.w -(a0),d0 ;10年カウンタ→1日カウンタ lsl.l #4,d1 or.b d0,d1 next subq.l #2,a0 ;曜日カウンタを跨ぐ。10時カウンタの直後 moveq.l #6-1,d3 for d3 moveq.l #$0F,d0 and.w -(a0),d0 ;10時カウンタ→1秒カウンタ lsl.l #4,d2 or.b d0,d2 next moveq.l #$0F,d0 and.b d2,d0 ;最下位 next eq ;0でなければ終了 ;<d1.l:曜日<<24|(西暦年-1980)(BCD)<<16|月(BCD)<<8|月通日(BCD) ;<d2.l:時(BCD)<<16|分(BCD)<<8|秒(BCD) ;------------------------------------------------ ;日付をデコードする move.l d1,d0 bsr decode3bcd ;2桁*3組のBCDをデコードする ;<d0.l:曜日<<24|(西暦年-1980)<<16|月<<8|月通日 if mi ;異常 moveq.l #-1,d7 ;異常 endif ;曜日をずらして西暦年に1980を加える swap.w d0 ;mmdd0wyy ror.w #8,d0 ;mmddyy0w lsl.b #4,d0 ;mmddyyw0 rol.w #8,d0 ;mmddw0yy add.w #1980,d0 ;mmddwyyy swap.w d0 ;wyyymmdd move.l d0,d1 ;<d1.l:曜日<<28|西暦年<<16|月<<8|月通日 ;------------------------------------------------ ;時刻をデコードする move.l d2,d0 bsr decode3bcd ;2桁*3組のBCDをデコードする ;<d0.l:時<<16|分<<8|秒 if mi ;異常 moveq.l #-1,d7 ;異常 endif move.l d0,d2 ;<d2.l:時<<16|分<<8|秒 ;------------------------------------------------ ;終了 move.l d7,d0 pop rts ;-------------------------------------------------------------------------------- ;RTCから読み出した日時に異常がないか確認する ;<d1.l:曜日<<28|西暦年<<16|月<<8|月通日 ;<d2.l:時<<16|分<<8|秒 ;>d0.l:0=正常,-1=異常 ;>ccr:pl=正常,mi=異常 ; 異常の内容 ; ・2023月2日29日や31時などの存在しない日時 ; ・_ROMVERの日付より前の明らかに過去の日付 ; ・曜日が違う checkdttm: push d3-d5/a0 ;------------------------------------------------ ;日付を分解する move.l d1,d5 ;d5.l:曜日<<28|西暦年<<16|月<<8|月通日 moveq.l #0,d3 move.b d5,d3 ;d3.l:月通日。正常のとき1~月の日数 lsr.w #8,d5 ;d5.l:曜日<<28|西暦年<<16|月 moveq.l #0,d4 move.b d5,d4 ;d4.l:月。正常のとき1~12 swap.w d5 ;d5.l:月<<16|曜日<<12|西暦年 and.l #$00000FFF,d5 ;d5.l:西暦年。正常のとき1980~2079 ;<d3.l:月通日。正常のとき1~月の日数 ;<d4.l:月。正常のとき1~12 ;<d5.l:西暦年。正常のとき1980~2079 ;------------------------------------------------ ;西暦年の範囲を確認する gotoor <cmp.w #1980,d5>,lo,<cmp.w #2079,d5>,hi,90f ;西暦年が1980より小さいまたは2079より大きい ;------------------------------------------------ ;月の範囲を確認する gotoor <tst.w d4>,eq,<cmp.w #12,d4>,hi,90f ;月が0または12より大きい ;------------------------------------------------ ;月通日の範囲を確認する moveq.l #0,d0 if <cmp.b #2,d4>,eq ;2月 moveq.l #3,d0 and.b d5,d0 ;西暦年&3 seq.b d0 ;0=閏年ではない年の2月,-1=閏年の2月 neg.b d0 ;0=閏年ではない年の2月,1=閏年の2月 endif lea.l daysofmonth(pc),a0 add.b -1(a0,d4.w),d0 ;d0.l:月の日数 gotoor <tst.w d3>,eq,<cmp.w d0,d3>,hi,90f ;月通日が0または月の日数より大きい ;------------------------------------------------ ;_ROMVERの日付と比較する IOCS _ROMVER bsr decode3bcd ;2桁*3組のBCDをデコードする ;<d0.l:_ROMVERのバージョン<<24|_ROMVERの西暦年の下2桁<<16|_ROMVERの月<<8|_ROMVERの月通日 ;_ROMVERの西暦年と比較する swap.w d0 ;d0.w:_ROMVERのバージョン<<24|_ROMVERの西暦年の下2桁 and.w #$00FF,d0 ;d0.w:_ROMVERの西暦年の下2桁 add.w #1900,d0 if <cmp.w #1950,d0>,lo add.w #2000-1900,d0 ;d0.w:_ROMVERの西暦年 endif goto <cmp.w d0,d5>,lo,90f ;_ROMVERの西暦年より前 if eq ;_ROMVERの西暦年と同じ ;_ROMVERの月と比較する swap.w d0 ;d0.w:_ROMVERの月<<8|_ROMVERの月通日 ror.w #8,d0 ;d0.w:_ROMVERの月通日<<8|_ROMVERの月 goto <cmp.b d0,d4>,lo,90f ;_ROMVERの月より前 if eq ;_ROMVERの月と同じ ;_ROMVERの月通日と比較する rol.w #8,d0 ;d0.w:_ROMVERの月<<8|_ROMVERの月通日 goto <cmp.b d0,d3>,lo,90f ;_ROMVERの月通日より前 endif endif ;------------------------------------------------ ;曜日を確認する if <cmp.w #2,d4>,ls ;1月と2月を subq.w #1,d5 ;前年の add.w #12,d4 ;13月と14月にする endif move.l d5,d0 ;d0.l:西暦年 mulu.w #365,d0 ;d0.l:365*西暦年 lsr.w #2,d5 ;d5.l:floor(西暦年/4) add.l d5,d0 ;d0.l:365*西暦年+floor(西暦年/4) addq.w #1,d4 ;d4.l:月+1 mulu.w #306,d4 ;d4.l:306*(月+1) .if 1 divu.w #10,d4 ;d4.w:floor(306*(月+1))/10。被除数は306*4=1224~306*15=4590 ext.l d4 ;d4.l:floor(306*(月+1))/10 .else mulu.w #3277,d4 add.l d4,d4 clr.w d4 swap.w d4 ;d4.l:floor(306*(月+1))/10 .endif add.l d4,d0 ;d0.l:365*西暦年+floor(西暦年/4)+floor(306*(月+1))/10 add.l d3,d0 ;d0.l:365*西暦年+floor(西暦年/4)+floor(306*(月+1))/10+月通日 sub.l #723256,d0 ;d0.l:365*西暦年+floor(西暦年/4)+floor(306*(月+1))/10+月通日-723256。1980年1月1日は2、2079年12月31日は36526 divu.w #7,d0 swap.w d0 ;d0.w:日付の曜日。0~6 move.l d1,d3 ;d3.l:曜日<<28|西暦年<<16|月<<8|月通日 rol.l #4,d3 ;d3.l:西暦年<<20|月<<12|月通日<<4|曜日 and.w #$000F,d3 ;d3.w:RTCが返した曜日 goto <cmp.w d0,d3>,ne,90f ;曜日が違う ;------------------------------------------------ ;時刻の範囲を確認する move.l d2,d0 goto <cmp.b #59,d0>,hi,90f ;秒が範囲外 lsr.w #8,d0 goto <cmp.b #59,d0>,hi,90f ;分が範囲外 swap.w d0 goto <cmp.b #23,d0>,hi,90f ;時が範囲外 ;------------------------------------------------ ;正常終了 moveq.l #0,d0 80: pop rts ;------------------------------------------------ ;異常終了 90: moveq.l #-1,d0 goto 80b ;------------------------------------------------ ;閏年でない年の月の日数 daysofmonth: .dc.b 31,28,31,30,31,30,31,31,30,31,30,31 .even ;-------------------------------------------------------------------------------- ;2桁*3組のBCDをデコードする ;<d0.l:$WWXXYYZZ ;>d0.l:$WW<<24|x<<16|y<<8|z ; 上位8ビットは変化しない ; x,y,zの最大値は正常のとき9*10+9=99、異常のとき15*10+15=165 ;>ccr:pl=正常,mi=異常 decode3bcd: push d1-d4/d7 moveq.l #0,d7 ;d7.l:0=正常,-1=異常 moveq.l #10,d4 ;d4.l:10 moveq.l #3-1,d3 ;d3.w:2,1,0 for d3 moveq.l #$0F,d1 and.b d0,d1 ;d1.b:下位4bit lsr.b #4,d0 ;d0.b:上位4bit ifor <cmp.b d4,d1>,hs,<cmp.b d4,d0>,hs ;下位4bitが10以上または上位4bitが10以上 moveq.l #-1,d7 ;異常 endif move.b d0,d2 ;d2.b:上位4bit lsl.b #2,d0 ;d0.b:上位4bit*4 add.b d2,d0 ;d0.b:上位4bit*5 add.b d0,d0 ;d0.b:上位4bit*10 add.b d1,d0 ;d0.b:上位4bit*10+下位4bit ror.l #8,d0 ;$ZZ,$YY,$XXの順 next ror.l #8,d0 ;$WWはそのまま tst.l d7 pop rts ;---------------------------------------------------------------- ;内蔵ハードディスクインターフェイスの種類を表示する ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?d0/a0-a1 ipl_message_hd_type: lea.l 100f(pc),a1 ;'Built-in Hard Disk Interface' bsr print_left_column movea.l a6,a0 ;文字列バッファ lea.l 101f(pc),a1 ;'SASI' if <isSASI>,ne lea.l 102f(pc),a1 ;'SCSI' endif bsr strcpy bsr crlf movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Built-in Hard Disk Interface',0 101: .dc.b 'SASI',0 102: .dc.b 'SCSI',0 .even ;---------------------------------------------------------------- ;起動デバイスを表示する ; SRAM_ROM_BOOT_HANDLE ROM起動ハンドル ; SRAM_SRAM_BOOT_ADDRESS SRAM起動アドレス ; SRAM_BOOT_DEVICE 起動デバイス。$0000=STD,$8xxx=HD,$9xxx=FD,$Axxx=ROM,$Bxxx=SRAM ; $0000 STD ; $8xxx HD n ; $9xxx FD n ; $A000 ROM $xxxxxxxx ; $00E9F020 XEiJ HFS ; $00EA0020- Expansion SCSI n ; $00EA9000- PhantomX VDISK n ; $00FC0000- Built-in SCSI n ; $B000 SRAM $xxxxxxxx ;<d7.l:MPUステータス ;<a6.l:文字列バッファ ;?d0-d1/a0-a1 ipl_message_boot_device: lea.l 100f(pc),a1 ;'Boot Device' bsr print_left_column movea.l a6,a0 ;文字列バッファ move.w SRAM_BOOT_DEVICE,d0 ;起動デバイス if eq ;$0000 lea.l 101f(pc),a1 ;'STD' bsr strcpy elifor <cmp.w #$8000,d0>,lo,<cmp.w #$C000,d0>,hs lea.l 102f(pc),a1 ;'Unknown $' bsr h4tos elif <cmp.w #$9000,d0>,lo ;$8xxx lea.l 103f(pc),a1 ;'SASI HD ' bsr strcpy lsr.w #8,d0 moveq.l #$0F,d1 and.l d1,d0 bsr utos elif <cmp.w #$A000,d0>,lo ;$9xxx lea.l 104f(pc),a1 ;'FD ' bsr strcpy lsr.w #8,d0 moveq.l #$07,d1 and.l d1,d0 bsr utos elif <cmp.w #$B000,d0>,lo ;$Axxx move.l SRAM_ROM_BOOT_HANDLE,d0 ;ROM起動ハンドル moveq.l #3,d1 and.w d0,d1 if <cmp.l #$00E9F020,d0>,eq lea.l 105f(pc),a1 ;'XEiJ HFS' bsr strcpy elifand <cmp.l #$00EA0020,d0>,hs,<cmp.l #$00EA0020+4*8,d0>,lo,<tst.l d1>,eq lea.l 106f(pc),a1 ;'Expansion SCSI ' bsr strcpy lsr.w #2,d0 moveq.l #7,d1 and.l d1,d0 bsr utos elifand <cmp.l #$00EA9000,d0>,hs,<cmp.l #$00EA9000+4*8,d0>,lo,<tst.l d1>,eq lea.l 107f(pc),a1 ;'PhantomX VDISK ' bsr strcpy lsr.w #2,d0 moveq.l #7,d1 and.l d1,d0 bsr utos elifand <cmp.l #$00FC0000,d0>,hs,<cmp.l #$00FC0000+4*8,d0>,lo,<tst.l d1>,eq lea.l 108f(pc),a1 ;'Built-in SCSI ' bsr strcpy lsr.w #2,d0 moveq.l #7,d1 and.l d1,d0 bsr utos else lea.l 109f(pc),a1 ;'ROM $' bsr strcpy bsr h8tos endif else ;$Bxxx lea.l 110f(pc),a1 ;'SRAM $' bsr strcpy move.l SRAM_SRAM_BOOT_ADDRESS,d0 ;SRAM起動アドレス bsr h8tos endif bsr crlf movea.l a6,a1 ;文字列バッファ goto iocs_21_B_PRINT 100: .dc.b 'Boot Device',0 101: .dc.b 'STD',0 102: .dc.b 'Unknown $',0 103: .dc.b 'SASI HD ',0 104: .dc.b 'FD ',0 105: .dc.b 'XEiJ HFS',0 106: .dc.b 'Expansion SCSI ',0 107: .dc.b 'PhantomX VDISK ',0 108: .dc.b 'Built-in SCSI ',0 109: .dc.b 'ROM $',0 110: .dc.b 'SRAM $',0 .even ;---------------------------------------------------------------- ; SHARPロゴ ; 変更前 ; 00FF0EC0 43FA04CA lea.l $00FF138C(pc),a1 ;SHARPロゴ ; 00FF0EC4 343C0000 move.w #$0000,d2 ; 00FF0EC8 ;---------------------------------------------------------------- PATCH_DATA sharp_logo,$00FF0EC0,$00FF0EC7,$43FA04CA lea.l $00FFD680,a1 clr.w d2 ;---------------------------------------------------------------- ; 不具合 ; クロック表示ルーチンでA6レジスタの最上位バイトが破壊される ; https://stdkmd.net/bugsx68k/#rom_clocka6 ; 変更前 ; 00000F0C 4E56FFFC link.w a6,#-4 ; 00000F10 1D7C00000000 move.b #$00,$0000.w(a6) ;---------------------------------------------------------------- ;---------------------------------------------------------------- ; 不具合 ; メインメモリが9MBのとき起動時に19MBと表示される ; 変更前 ; 00000FD4 6A0A_00000FE0 bpl ~FF0FE0 ;9MB以上 ;---------------------------------------------------------------- ;---------------------------------------------------------------- ; 起動音 ; 起動音を鳴らすとFM音源ドライバが誤動作することがある不具合を修正する ; https://stdkmd.net/bugsx68k/#rom_chime ; 起動音のキーコードを変更できるようにする ;---------------------------------------------------------------- PATCH_DATA play_stupsnd,$00FF10D8,$00FF118F,$4A3900ED CH equ 0 KC equ 76 KF equ 5 TM equ 2500/100 FLCON equ (1<<3)|3 ;|FL###|CON###| SLOT equ %1101 ;|C2|M2|C1|M1| WAVE equ 0 SYNC equ 1 SPEED equ 0 PMD equ 0 AMD equ 0 PMS equ 0 AMS equ 0 PAN equ %11 ;|R|L| M1AR equ 6 M1D1R equ 11 M1D2R equ 4 M1RR equ 4 M1D1L equ 0 M1TL equ 29 M1KS equ 0 M1MUL equ 0 M1DT1 equ 0 M1DT2 equ 3 M1AMSEN equ 1 C1AR equ 31 C1D1R equ 6 C1D2R equ 0 C1RR equ 2 C1D1L equ 2 C1TL equ 40 C1KS equ 2 C1MUL equ 1 C1DT1 equ 0 C1DT2 equ 3 C1AMSEN equ 1 M2AR equ 3 M2D1R equ 2 M2D2R equ 7 M2RR equ 2 M2D1L equ 3 M2TL equ 28 M2KS equ 1 M2MUL equ 3 M2DT1 equ 0 M2DT2 equ 1 M2AMSEN equ 1 C2AR equ 31 C2D1R equ 21 C2D2R equ 6 C2RR equ 4 C2D1L equ 2 C2TL equ 2 C2KS equ 1 C2MUL equ 1 C2DT1 equ 0 C2DT2 equ 0 C2AMSEN equ 1 play_stupsnd: push d0-d4/a0 move.b SRAM_STARTUP_SOUND,d3 ;0=off,1..255=on,2..127=kc if ne ;on moveq.l #$08,d1 ;KeyOff moveq.l #(0<<3)|CH,d2 ;|-|C2|M2|C1|M1|CH###| bsr stupsnd_opmset lea.l stupsnd_data(pc),a0 ;レジスタデータの配列 moveq.l #$20+CH,d1 ;レジスタアドレス moveq.l #28-1,d4 ;0..27 for d4 move.b (a0)+,d2 ;レジスタデータ ifand <cmp.b #$28+CH,d1>,eq,<cmp.b #2,d3>,ge ;2..127=kc。キーコードが指定されている move.b d3,d2 endif bsr stupsnd_opmset addq.b #8,d1 ;次のレジスタアドレス next moveq.l #6-1,d4 ;28..39 for d4 move.b (a0)+,d1 ;レジスタアドレス move.b (a0)+,d2 ;レジスタデータ bsr stupsnd_opmset next moveq.l #$08,d1 ;KeyOn moveq.l #(SLOT<<3)|CH,d2 ;|-|C2|M2|C1|M1|CH###| bsr stupsnd_opmset moveq.l #0,d0 move.w (a0)+,d0 ;40..41。tm@100us add.l d0,d0 ;tm@50us jsr wait_50us ;50us単位のウェイト ; moveq.l #$08,d1 ;KeyOff moveq.l #(0<<3)|CH,d2 ;|-|C2|M2|C1|M1|CH###| bsr stupsnd_opmset endif pop rts stupsnd_opmset: IOCS _OPMSET rts ;レジスタデータ(42バイト)。偶数アドレスに配置すること .even stupsnd_data: .ifdef STUPSNDDAT .insert stupsnd.dat .else .dc.b (PAN<<6)|FLCON ;0 $20+CH |PAN##|FL###|CON###| .dc.b KC ;1 $28+CH |-|KC#######| .dc.b KF<<2 ;2 $30+CH |KF######|--| .dc.b (PMS<<4)|AMS ;3 $38+CH |-|PMS###|--|AMS##| .dc.b (M1DT1<<4)|M1MUL ;4 $40+CH M1 |-|DT1###|MUL####| .dc.b (M2DT1<<4)|M2MUL ;5 $48+CH M2 .dc.b (C1DT1<<4)|C1MUL ;6 $50+CH C1 .dc.b (C2DT1<<4)|C2MUL ;7 $58+CH C2 .dc.b M1TL ;8 $60+CH M1 |-|TL#######| .dc.b M2TL ;9 $68+CH M2 .dc.b C1TL ;10 $70+CH C1 .dc.b C2TL ;11 $78+CH C2 .dc.b (M1KS<<6)|M1AR ;12 $80+CH M1 |KS##|-|AR#####| .dc.b (M2KS<<6)|M2AR ;13 $88+CH M2 .dc.b (C1KS<<6)|C1AR ;14 $90+CH C1 .dc.b (C2KS<<6)|C2AR ;15 $98+CH C2 .dc.b (M1AMSEN<<7)|M1D1R ;16 $A0+CH M1 |AMSEN|--|D1R#####| .dc.b (M2AMSEN<<7)|M2D1R ;17 $A8+CH M2 .dc.b (C1AMSEN<<7)|C1D1R ;18 $B0+CH C1 .dc.b (C2AMSEN<<7)|C2D1R ;19 $B8+CH C2 .dc.b (M1DT2<<6)|M1D2R ;20 $C0+CH M1 |DT2##|-|D2R#####| .dc.b (M2DT2<<6)|M2D2R ;21 $C8+CH M2 .dc.b (C1DT2<<6)|C1D2R ;22 $D0+CH C1 .dc.b (C2DT2<<6)|C2D2R ;23 $D8+CH C2 .dc.b (M1D1L<<4)|M1RR ;24 $E0+CH M1 |D1L####|RR####| .dc.b (M2D1L<<4)|M2RR ;25 $E8+CH M2 .dc.b (C1D1L<<4)|C1RR ;26 $F0+CH C1 .dc.b (C2D1L<<4)|C2RR ;27 $F8+CH C2 .dc.b $18,SPEED ;28,29 $18 |LFRQ########| .dc.b $19,(0<<7)|AMD ;30,31 $19 |0|AMD#######| .dc.b $19,(1<<7)|PMD ;32,33 $19 |1|PMD#######| .dc.b $1B,WAVE ;34,35 $1B |CT1|CT2|----|WAVE##| .dc.b $01,SYNC<<1 ;36,37 $01 |------|LFORESET|-| .dc.b $01,0<<1 ;38,39 $01 |------|LFORESET|-| .dc.w TM ;40,41 tm@100us ;42 .even .endif ;---------------------------------------------------------------- ; 不具合 ; 起動メッセージのMemory Managiment Unitのスペルが間違っている ; https://stdkmd.net/bugsx68k/#rom_mmu ; 対策 ; Memory Management Unit ; 変更前 ; 00001254 4D656D6F7279204D .dc.b 'Memory Managiment Unit(MMU) : On-Chip MMU',$0D,$0A,$00 ; 616E6167696D656E ; 7420556E6974284D ; 4D5529203A204F6E ; 2D43686970204D4D ; 550D0A00 ;---------------------------------------------------------------- ;---------------------------------------------------------------- ; TRAP#14(エラー表示) ; 「エラーが発生しました。リセットしてください。」だけでは分からないエラーの内容を表示する ; 変更前 ; 00FF1458 41FAF364 lea.l $00FF07BE(pc),a0 ;TRAP#14(エラー表示) ; 00FF145C 21C800B8 move.l a0,OFFSET_TRAP_14.w ;---------------------------------------------------------------- PATCH_DATA trap14,$00FF1458,$00FF145F,$41FAF364 move.l #trap14,OFFSET_TRAP_14.w PATCH_TEXT ;<d7.w:エラー番号 ; $00xx 未定義例外 ; $01xx 未定義IOCSコール ; $301F NMI ; $7009 プリンタオフライン ;<a6.l:SRの位置。$7009のときセットされない trap14: ;文字列バッファを確保する lea.l -128(sp),sp ;文字列バッファ ;エラーメッセージを作る ; Bus error on writing to $XXXXXXXX at $XXXXXXXX ; Bus error on reading from $XXXXXXXX at $XXXXXXXX ; Address error on writing to $XXXXXXXX at $XXXXXXXX ; Address error on reading from $XXXXXXXX at $XXXXXXXX ; Error $XXXX at $XXXXXXXX movea.l sp,a0 ;文字列バッファ bsr start_proportional move.b #' ',(a0)+ move.b #' ',(a0)+ moveq.l #-2,d0 and.w d7,d0 subq.w #2,d0 if eq ;バスエラーとアドレスエラー move.b BIOS_MPU_TYPE.w,d0 if eq ;68000 ; MC68000UM 6-17 ; 0.w ; 15-5 4 3 2-0 ; X R/W I/N FC ; R/W 0=Write,1=Read ; I/N 0=Instruction,1=Not ; 2.l ACCESS ADDRESS ; 6.w INSTRUCTION REGISTER ; 8.w STATUS REGISTER ; 10.l PROGRAM COUNTER moveq.l #$10,d0 and.b 1-8(a6),d0 ;0=Write,その他=Read movea.l 2-8(a6),a2 ;Address elif <subq.b #1,d0>,eq ;68010 ; MC68000UM 6-18 ; 0.w STATUS REGISTER ; 2.l PROGRAM COUNTER ; 6.w FORMAT $A VECTOR OFFSET ; 8.w SPECIAL STATUS WORD ; 15 14 13 12 11 10 9 8 7-3 2-0 ; RR X IF DF RM HB BY RW X FC ; RW 0=Write,1=Read ; 10.l FAULT ADDRESS ; 14.w UNUSED, RESERVED ; 16.w DATA OUTPUT BUFFER ; 18.w UNUSED, RESERVED ; 20.w DATA INPUT BUFFER ; 22.w UNUSED, RESERVED ; 24.w INSTRUCTION INPUT BUFFER ; 26.w VERSION NUMBER INTERNAL INFORMATION, 16 WORDS ; 58バイト。実際に書き込まれるのは52バイト moveq.l #$01,d0 and.b 8(a6),d0 ;0=Write,その他=Read movea.l 10(a6),a2 ;Address elif <subq.b #4-1,d0>,lo ;68020/68030 ;68020/68030 ; MC68020UM 6-23/MC68030UM 8-28 ; 10.w SPECIAL STATUS WORD ; 15 14 13 12 11-9 8 7 6 5-4 3 2-0 ; FC FB RC RB X DF RM RW SIZE X FC ; RW 0=Write,1=Read ; 16.l DATA CYCLE FAULT ADDRESS moveq.l #$40,d0 and.b 11(a6),d0 ;0=Write,その他=Read movea.l 16(a6),a2 ;Address elif eq ;68040 ; MC68040UM 8-24 ; 12.w SPECIAL STATUS WORD ; 15 14 13 12 11 10 9 8 7 6-5 4-3 2-0 ; CP CU CT CM MA ATC LK RW X SIZE TT TM ; RW 0=Write,1=Read ; 20.l FAULT ADDRESS moveq.l #$01,d0 and.b 12(a6),d0 ;0=Write,その他=Read movea.l 20(a6),a2 ;Address elif <cmp.w #2,d7>,eq ;68060のバスエラー ; MC68060UM 8-21 ; 8.l FAULT ADDRESS ; 12.l FAULT STATUS LONG WORD ; 31-28 27 26 25 24-23 22-21 20-19 18-16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ; X MA X LK RW SIZE TT TM IO PBE SBE PTA PTB IL PF SP WP TWE RE WE TTR BPE X SEE ; RW 00=Undefined,Reserved,01=Write,10=Read,11=Read-Modify-Write ; SIZE 00=Byte,01=Word,10=Long,11=Double Precision or MOVE16 moveq.l #$01,d0 and.b 12(a6),d0 ;0=Write,その他=Read if ne ;Read or Read-Modify-Write ifand <tst.b 13(a6)>,mi,<btst.b #4,15(a6)>,ne ;Read-Modify-Write and Bus Error on Write moveq.l #0,d0 ;0=Write,その他=Read endif endif movea.l 8(a6),a2 ;Address else ;68060のアドレスエラー ; MC68060UM 8-7 ; 8.l FAULT ADDRESS moveq.l #1,d0 ;Read movea.l 8(a6),a2 ;Address addq.l #1,a2 ;bit0が0になっているので1に戻す endif lea.l 101f(pc),a1 ;'Bus' subq.w #2,d7 if ne lea.l 102f-101f(a1),a1 ;'Address' endif bsr strcpy lea.l 103f(pc),a1 ;' error on ' bsr strcpy lea.l 104f(pc),a1 ;'writing to $' if <tst.b d0>,ne lea.l 105f-104f(a1),a1 ;'reading from $' endif bsr strcpy move.l a2,d0 bsr h8tos ;XXXXXXXX elif <cmp.w #12,d7>,lo ;4~11 PATCH_lea sysstat,trap14_message,a1 move.w d7,d0 add.w d0,d0 adda.w -2*4(a1,d0.w),a1 bsr strcpy elif <cmp.w #$301F,d7>,eq ;NMI lea.l 106f(pc),a1 ;'NMI' bsr strcpy else ;その他未定義例外と未定義IOCSコール lea.l 107f(pc),a1 ;'Error $' bsr strcpy move.w d7,d0 bsr h4tos ;XXXX endif if <cmp.w #$7009,d7>,ne lea.l 108f(pc),a1 ;' at $' bsr strcpy move.l 2(a6),d0 ;PC bsr h8tos endif bsr end_proportional bsr crlf ;エラーメッセージを表示する movea.l sp,a1 bsr iocs_21_B_PRINT ;文字列バッファを開放する lea.l 128(sp),sp ;常に中止 ; キー入力を待たず直ちにリセット待ちにする 10: IOCS _ABORTJOB goto 10b ;無限ループ 101: .dc.b 'Bus',0 102: .dc.b 'Address',0 103: .dc.b ' error on ',0 104: .dc.b 'writing to $',0 105: .dc.b 'reading from $',0 106: .dc.b 'NMI',0 107: .dc.b 'Error $',0 108: .dc.b ' at $',0 .even ;---------------------------------------------------------------- ; IOI HDCINTベクタの設定 ; このまま。IPLROM 1.2とIPLROM 1.3で同じ。SPCINTとは関係ない ; 変更前 ; 000017FC 047E .dc.w ~FF1C76-~FF17F8 ;[$0188.w].l:[$0062]:HDCINT ハードディスクのステータス割り込み ; 00001C76 4E73 rte ;---------------------------------------------------------------- ;---------------------------------------------------------------- ; DMAC 1の初期化 ; このまま。IPLROM 1.2とIPLROM 1.3で同じ ; 変更前 ; 0000180A 4480 .dc.b $00E84044-$00E84000,$80 ;[$00E84044].b:DMA 1 DCR(XRM##|DTYP##|DPS|-|PCL##) ; 0000180C 4604 .dc.b $00E84046-$00E84000,$04 ;[$00E84046].b:DMA 1 SCR(----|MAC##|DAC##) ; 0000180E 6905 .dc.b $00E84069-$00E84000,$05 ;[$00E84069].b:DMA 1 MFC ; 00001810 6D02 .dc.b $00E8406D-$00E84000,$02 ;[$00E8406D].b:DMA 1 CPR ; 00001812 7105 .dc.b $00E84071-$00E84000,$05 ;[$00E84071].b:DMA 1 DFC ;---------------------------------------------------------------- ;---------------------------------------------------------------- ; DMAC 1 DARの初期化 ; SASI内蔵機のときHDC_DATAを設定する ; SCSI内蔵機のとき削除。IPLROM 1.3は無意味な値を設定している ; 変更前 ; 00001788 237A7BB2_0000933C move.l spc_base_handle(pc),DMAC_DAR+DMAC_1_BASE-DMAC_0_BASE(a1) ; 0054 ;---------------------------------------------------------------- PATCH_DATA p1788,$00FF1788,$00FF1788+5,$237A7BB2 jsr p1788 PATCH_TEXT p1788: if <tst.b BIOS_BUILTIN_SCSI.w>,eq ;SASI内蔵機 move.l #HDC_DATA,DMAC_DAR+DMAC_1_BASE-DMAC_0_BASE(a1) else ;SCSI内蔵機 clr.l DMAC_DAR+DMAC_1_BASE-DMAC_0_BASE(a1) endif rts ;---------------------------------------------------------------- ; SASIポートまたはSCSIポートの初期化 ; SASI内蔵機のときSASIポートを初期化する ; SCSI内蔵機で拡張SCSIがないときSCSIINROMのscsi_init_routineを呼び出す ; 変更前 ; 000017D6 70F5 moveq.l #_SCSIDRV,d0 ; 000017D8 7200 moveq.l #_S_RESET,d1 ; 000017DA 4E4F trap #15 ;---------------------------------------------------------------- PATCH_DATA p17D6,$00FF17D6,$00FF17D6+5,$70F57200 jsr p17d6 PATCH_TEXT p17d6: push d0-d1/a0-a1 if <tst.b BIOS_BUILTIN_SCSI.w>,eq ;SASI内蔵機 ;SASIポートを初期化する do break <tst.l BIOS_ALARM_MINUTE.l>,ne while <cmpi.w #6000-100*1,BIOS_TC_MINUTE_COUNTER.l>,cc ;起動後1秒まで待つ move.w #$8000,d1 do suba.l a1,a1 IOCS _B_DSKINI if <cmpi.w #100*30,BIOS_TC_MINUTE_COUNTER.l>,cc ;起動後30秒までは redo <cmp.b #$04,d0>,eq ;$04でリトライ endif break <tst.b d0>,ne add.w #$0100,d1 while <cmp.w #$9000,d1>,ne else ;SCSI内蔵機 lea.l $00EA0044,a0 ;'SCSIEX' bsr read_long if <cmp.l #'SCSI',d0>,eq bsr read_word goto <cmp.w #'EX',d0>,eq,@f ;拡張SCSIがある endif ;拡張SCSIがない ;SCSIINROMのscsi_init_routineを呼び出す movea.l $00FC0020,a1 ;scsi_init_handle jsr (a1) @@: endif pop rts ;---------------------------------------------------------------- ; 不具合 ; 電卓を使うと実行中のプログラムが誤動作することがある ; https://stdkmd.net/bugsx68k/#rom_dentakud3 ; 変更前 ; 00FF3BFC 48E76000 movem.l d1-d2,-(sp) ; 00FF3C00 ;---------------------------------------------------------------- PATCH_DATA dentaku_d3_1st,$00FF3BFC,$00FF3BFF,$48E76000 movem.l d1-d3,-(sp) ;---------------------------------------------------------------- ; 変更前 ; 00FF3C16 4CDF0006 movem.l (sp)+,d1-d2 ; 00FF3C1A ;---------------------------------------------------------------- PATCH_DATA dentaku_d3_2nd,$00FF3C16,$00FF3C19,$4CDF0006 movem.l (sp)+,d1-d3 ;---------------------------------------------------------------- ; 変更前 ; 00FF3C1C 4CDF0006 movem.l (sp)+,d1-d2 ; 00FF3C20 ;---------------------------------------------------------------- PATCH_DATA dentaku_d3_3rd,$00FF3C1C,$00FF3C1F,$4CDF0006 movem.l (sp)+,d1-d3 ;---------------------------------------------------------------- ; 変更前 ; 00FF3C5A 48E76000 movem.l d1-d2,-(sp) ; 00FF3C5E ;---------------------------------------------------------------- PATCH_DATA dentaku_d3_4th,$00FF3C5A,$00FF3C5D,$48E76000 movem.l d1-d3,-(sp) ;---------------------------------------------------------------- ; 変更前 ; 00FF3C76 4CDF0006 movem.l (sp)+,d1-d2 ; 00FF3C7A ;---------------------------------------------------------------- PATCH_DATA dentaku_d3_5th,$00FF3C76,$00FF3C79,$4CDF0006 movem.l (sp)+,d1-d3 ;---------------------------------------------------------------- ; 不具合 ; カーソルが画面の最下行にあると電卓が画面外に表示される ; https://stdkmd.net/bugsx68k/#rom_dentaku64 ; 対策 ; 電卓の表示位置を決める処理にY座標を調整するコードを追加する ; 直前にある電卓OFFルーチンを詰めてできた隙間にY座標を調整するコードを押し込んでそれを呼び出す ; 変更前 ; 00FF4444 3F00 move.w d0,-(sp) ; 00FF4446 3F3C0010 move.w #$0010,-(sp) ; 00FF444A 3F3C00B8 move.w #$00B8,-(sp) ; 00FF444E 3F380BFE move.w BIOS_DEN_Y.w,-(sp) ;電卓表示Y座標 ; 00FF4452 3F380BFC move.w BIOS_DEN_X.w,-(sp) ;電卓表示X座標 ; 00FF4456 3F3C0002 move.w #$0002,-(sp) ; 00FF445A 61002368 bsr.w $00FF67C4 ;_TXFILL実行 ; 00FF445E 4FEF000C lea.l $000C(sp),sp ; 00FF4462 4267 clr.w -(sp) ; 00FF4464 3F3C0010 move.w #$0010,-(sp) ; 00FF4468 3F3C00B8 move.w #$00B8,-(sp) ; 00FF446C 3F380BFE move.w BIOS_DEN_Y.w,-(sp) ;電卓表示Y座標 ; 00FF4470 3F380BFC move.w BIOS_DEN_X.w,-(sp) ;電卓表示X座標 ; 00FF4474 3F3C0003 move.w #$0003,-(sp) ; 00FF4478 6100234A bsr.w $00FF67C4 ;_TXFILL実行 ; 00FF447C 4FEF000C lea.l $000C(sp),sp ; 00FF4480 301F move.w (sp)+,d0 ; 00FF4482 6704 beq.s $00FF4488 ; 00FF4484 610065D6 bsr.w $00FFAA5C ;IOCS _MS_CURON ; 00FF4488 4CDF7FFE movem.l (sp)+,d1-d7/a0-a6 ; 00FF448C 4E75 rts ; 00FF448E ;---------------------------------------------------------------- PATCH_DATA dentaku64_1st,$00FF4444,$00FF448D,$3F003F3C ;電卓OFF move.w d0,-(sp) move.l #184<<16|16,-(sp) move.l BIOS_DEN_X.w,-(sp) ;電卓表示X座標。BIOS_DEN_Y 電卓表示Y座標 move.w #2,-(sp) bsr ($00FF67C4)PATCH_ZL ;_TXFILL実行 clr.w 10(sp) addq.w #1,(sp) ;3 bsr ($00FF67C4)PATCH_ZL ;_TXFILL実行 lea.l 12(sp),sp move.w (sp)+,d0 if ne bsr ($00FFAA5C)PATCH_ZL ;IOCS _MS_CURON endif movem.l (sp)+,d1-d7/a0-a6 rts dentaku64: addq.w #1,d1 ;カーソルの次の行 ifand <cmp.w #32,d1>,hs,<cmp.w BIOS_CONSOLE_BOTTOM.w,d1>,hi ;32以上かつコンソールの範囲外 move.w BIOS_CONSOLE_BOTTOM.w,d1 ;コンソールの最下行 if ne ;コンソールが2行以上ある subq.w #1,d1 ;コンソールの下から2番目の行 endif endif rts ;---------------------------------------------------------------- ; 変更前 ; 00FF44A6 5241 addq.w #1,d1 ;カーソルの次の行 ; 00FF44A8 E941 asl.w #4,d1 ;---------------------------------------------------------------- PATCH_DATA dentaku64_2nd,$00FF44A6,$00FF44A7,$5241E941 PATCH_bsr dentaku64_1st,dentaku64 ;---------------------------------------------------------------- ; 不具合 ; ソフトキーボードの↑キーの袋文字が閉じていない ; https://stdkmd.net/bugsx68k/#rom_softkeyboard ; 変更前 ; 00005AA8 2B80 .dc.b __M_M_MM,M_______ ;---------------------------------------------------------------- PATCH_DATA softkeyboard,$00FF5AA8,$00FF5AA9,$2B800A00 .dc.b __MMM_MM,M_______ ;---------------------------------------------------------------- ; 不具合 ; _DEFCHRでフォントサイズに0が指定されたとき8に読み替える処理が文字コードも0のときしか機能していない ; _DEFCHRでフォントサイズに6を指定できない ; _DEFCHRで_FNTADRがフォントパターンをBIOS_FNTADR_BUFFER.wに作成して返したときそこに上書きしても保存されないのにエラーにならない ; _DEFCHRでフォントアドレスがX68030のハイメモリや060turboのローカルメモリを指しているとROMと誤認してエラーになる ; 変更前 ; 00FF6ADA 70FF moveq.l #$FF,d0 ; 00FF6ADC 48E76040 movem.l d1-d2/a1,-(sp) ; 00FF6AE0 2401 move.l d1,d2 ; 00FF6AE2 4842 swap.w d2 ; 00FF6AE4 6604 bne.s $00FF6AEA ; 00FF6AE6 343C0008 move.w #$0008,d2 ; 00FF6AEA B47C0006 cmp.w #$0006,d2 ; 00FF6AEE 6722 beq.s $00FF6B12 ; 00FF6AF0 20780458 movea.l $0458.w,a0 ;[$0458.w].l:[$0116]_FNTADR ; 00FF6AF4 4E90 jsr (a0) ; 00FF6AF6 2040 movea.l d0,a0 ; 00FF6AF8 70FF moveq.l #$FF,d0 ; 00FF6AFA B1FC00F00000 cmpa.l #$00F00000,a0 ;ROMならキャンセル ; 00FF6B00 6410 bcc.s $00FF6B12 ; 00FF6B02 5242 addq.w #1,d2 ; 00FF6B04 5241 addq.w #1,d1 ; 00FF6B06 C4C1 mulu.w d1,d2 ; 00FF6B08 5342 subq.w #1,d2 ; 00FF6B0A 10D9 move.b (a1)+,(a0)+ ; 00FF6B0C 51CAFFFC dbra.w d2,$00FF6B0A ; 00FF6B10 4280 clr.l d0 ; 00FF6B12 4CDF0206 movem.l (sp)+,d1-d2/a1 ; 00FF6B16 4E75 rts ; 00FF6B18 ;---------------------------------------------------------------- PATCH_DATA defchr,$00FF6ADA,$00FF6B17,$70FF48E7 ;---------------------------------------------------------------- ;IOCSコール$0F _DEFCHR フォントパターン設定 ;<d1.l:フォントサイズ<<16|文字コード ; フォントサイズ ; 0,8 8x16,16x16 ; 12,24 12x24,24x24 ;<a1.l:フォントパターンの先頭アドレス ;>d0.l:0=正常終了,-1=エラー iocs_0F_DEFCHR: push d1/d2/a0/a1 move.l d1,d2 swap.w d2 movea.l 4*($100+_FNTADR).w,a0 ;IOCSコール$16 _FNTADR フォントアドレスの取得 jsr (a0) ;<d0.l:フォントアドレス ;<d1.w:横方向のバイト数-1 ;<d2.w:縦方向のドット数-1 movea.l d0,a0 ;フォントアドレス moveq.l #-1,d0 ;フォントアドレスがROMを指しているときは上書きできないので失敗 ifor <cmpa.l #$00F00000,a0>,lo,<cmpa.l #$01000000,a0>,hs ;フォントアドレスがBIOS_FNTADR_BUFFER.wを指しているときは上書きしても保存されないので失敗 if <cmpa.w #BIOS_FNTADR_BUFFER.w,a0>,ne ;フォントパターンをコピーする addq.w #1,d1 addq.w #1,d2 mulu.w d2,d1 subq.w #1,d1 for d1 move.b (a1)+,(a0)+ next moveq.l #0,d0 endif endif pop rts .if REMOVE_CRTMOD_G_CLR_ON=0 ;---------------------------------------------------------------- ; _CRTMOD ; 変更前 ; 00006B18 48E77060 movem.l d1-d3/a1-a2,-(sp) ; : ; 00006B8C iocs_10_CRTMOD: ; 00006B8C 41F900E80028 lea.l CRTC_MODE_RESOLUTION,a0 ;メモリモードと解像度 ; : ; 00007042 0400028001E00001 .dc.w 1024,640,480,1 ;---------------------------------------------------------------- PATCH_DATA crtmod,$00FF6B8C,$00FF6B91,$41F900E8 jmp iocs_10_CRTMOD PATCH_TEXT ;---------------------------------------------------------------- ;IOCSコール$10 _CRTMOD 画面モードの取得と設定 ;<d1.w:設定後の画面モード ; $16FF バージョンの確認。$16xxxxxx(CRT向け)または$96xxxxxx(LCD向け)を返す ; $56FF バージョンの確認。$16xxxxxxを返す ; $76FF 画面モードの最大値の確認。$160000xxを返す ; $43xx CRT向け。SRAMに保存する。$43FFはSRAMの変更のみ ; $4Cxx LCD向け。SRAMに保存する。$4CFFはSRAMの変更のみ ; $xxFF 取得のみ ; $01xx 初期化しない ;>d0.l:設定前の画面モード。-1=設定後の画面モードが範囲外,-2=拡張グラフィック画面がない ; バージョンの確認のとき$16xxxxxxまたは$96xxxxxx ; 画面モードの最大値の確認のとき$160000xx ;---------------------------------------------------------------- ; 画面モード ; ; 画面モード 解像度 画面サイズ 実画面サイズ 色数 ページ数 ; 0 高 512x512 1024x1024 16 1 ; 1 低 512x512 1024x1024 16 1 ; 2 高 256x256 1024x1024 16 1 ; 3 低 256x256 1024x1024 16 1 ; 4 高 512x512 512x512 16 4 ; 5 低 512x512 512x512 16 4 ; 6 高 256x256 512x512 16 4 ; 7 低 256x256 512x512 16 4 ; 8 高 512x512 512x512 256 2 ; 9 低 512x512 512x512 256 2 ; 10 高 256x256 512x512 256 2 ; 11 低 256x256 512x512 256 2 ; 12 高 512x512 512x512 65536 1 ; 13 低 512x512 512x512 65536 1 ; 14 高 256x256 512x512 65536 1 ; 15 低 256x256 512x512 65536 1 ; 16 高 768x512 1024x1024 16 1 ; 17 中 1024x424 1024x1024 16 1 ; 18 中 1024x848 1024x1024 16 1 ; 19 VGA 640x480 1024x1024 16 1 ; 20 高 768x512 512x512 256 2 ; 21 中 1024x424 512x512 256 2 ; 22 中 1024x848 512x512 256 2 ; 23 VGA 640x480 512x512 256 2 ; 24 高 768x512 512x512 65536 1 ; 25 中 1024x424 512x512 65536 1 ; 26 中 1024x848 512x512 65536 1 ; 27 VGA 640x480 512x512 65536 1 ; $100+(0~27) 初期化しない ; -1 取得のみ ; ; 以下は拡張 ; 28 高 384x256 1024x1024 16 1 ; 29 高 384x256 512x512 16 4 ; 30 高 384x256 512x512 256 2 ; 31 高 384x256 512x512 65536 1 ; 32 高 512x512(正方形) 1024x1024 16 1 ; 33 高 512x512(正方形) 512x512 16 4 ; 34 高 512x512(正方形) 512x512 256 2 ; 35 高 512x512(正方形) 512x512 65536 1 ; 36 高 256x256(正方形) 1024x1024 16 1 ; 37 高 256x256(正方形) 512x512 16 4 ; 38 高 256x256(正方形) 512x512 256 2 ; 39 高 256x256(正方形) 512x512 65536 1 ; 40 高 512x256 1024x1024 16 1 ; 41 高 512x256 512x512 16 4 ; 42 高 512x256 512x512 256 2 ; 43 高 512x256 512x512 65536 1 ; 44 高 512x256(※) 1024x1024 16 1 ; 45 高 512x256(※) 512x512 16 4 ; 46 高 512x256(※) 512x512 256 2 ; 47 高 512x256(※) 512x512 65536 1 ; ※スプライトは512x512 ; ; 以下は拡張グラフィック画面が必要 ; 0,1,2,3,16,17,18,19,28,32,36,40,44を256色にしたもの ; 48 高 512x512 1024x1024 256 1 ; 49 低 512x512 1024x1024 256 1 ; 50 高 256x256 1024x1024 256 1 ; 51 低 256x256 1024x1024 256 1 ; 52 高 768x512 1024x1024 256 1 ; 53 中 1024x424 1024x1024 256 1 ; 54 中 1024x848 1024x1024 256 1 ; 55 VGA 640x480 1024x1024 256 1 ; 56 高 384x256 1024x1024 256 1 ; 57 高 512x512(正方形) 1024x1024 256 1 ; 58 高 256x256(正方形) 1024x1024 256 1 ; 59 高 512x256 1024x1024 256 1 ; 60 高 512x256(※) 1024x1024 256 1 ; 0,1,2,3,16,17,18,19,28,32,36,40,44を65536色にしたもの ; 61 高 512x512 1024x1024 65536 1 ; 62 低 512x512 1024x1024 65536 1 ; 63 高 256x256 1024x1024 65536 1 ; 64 低 256x256 1024x1024 65536 1 ; 65 高 768x512 1024x1024 65536 1 ; 66 中 1024x424 1024x1024 65536 1 ; 67 中 1024x848 1024x1024 65536 1 ; 68 VGA 640x480 1024x1024 65536 1 ; 69 高 384x256 1024x1024 65536 1 ; 70 高 512x512(正方形) 1024x1024 65536 1 ; 71 高 256x256(正方形) 1024x1024 65536 1 ; 72 高 512x256 1024x1024 65536 1 ; 73 高 512x256(※) 1024x1024 65536 1 ; ;---------------------------------------------------------------- ; いろいろ ; ; CRT向けとLCD向け ; 各画面モードの同期周波数をそれぞれCRT向けとLCD向けに分ける ; SRAM_XEIJのSRAM_XEIJ_LCD_BITが0のときCRT向け、1のときLCD向けの同期周波数で出力する ; ; 画面モード17 ; 水平24.699kHz、垂直53.116Hz、1024x424、実画面1024x1024、16色 ; X68000初代からあるが未公開 ; LCD向けのときは画面モード16の上下を削る ; ; 画面モード18 ; 水平24.699kHz、垂直53.116Hz、1024x848(インターレース)、実画面1024x1024、16色 ; X68000初代からあるが未公開 ; LCD向けのときは画面モード16の上下を削ってインターレースにする ; ; 画面モード19(VGAモード) ; 水平31.469kHz、垂直59.940Hz、640x480、実画面1024x1024、16色 ; X68000 Compactで追加された ; CRT向けのときは画面モード16の周囲を削る ; LCD向けのときはそのまま ; ; 画面モード20~23 ; 画面モード16~19を実画面512x512、256色に変更したもの ; X68030で追加された。未公開 ; ; 画面モード24~27 ; 画面モード16~19を実画面512x512、65536色に変更したもの ; X68030で追加された。未公開 ; ; グラフィックパレットのバグ(IPLROM 1.0~1.3) ; _CRTMODが指定された画面モードと異なる色数でグラフィックパレットを初期化する ; https://stdkmd.net/bugsx68k/#rom_crtmod_gpalet ; 256x256は16色、512x512は256色、それ以外は65536色になる ; ; 画面モード20~27のバグ(IPLROM 1.3) ; 画面モードに20~27が指定されたとき画面モードを16~19にしてから256色または65536色に変更しているが、 ; このときBIOSワークエリアの画面モードを16~19のまま放置している ; 続けて_G_CLR_ONを呼び出すと画面モードが16~19なので16色に戻ってしまう ; ; クリッピングエリアのバグ(IPLROM 1.3) ; _CRTMODで画面モードを22または26にするとクリッピングエリアが512x848になる ; ; VGAオシレータの問題 ; 初代~XVIにはVGAオシレータがないのでVGAモードが正しい同期周波数で出力されない ; VGAオシレータがある場合 ; (50.350MHz/2)/(8*100)=31.469kHz ; (50.350MHz/2)/(8*100*525)=59.940Hz ; VGAオシレータがない場合 ; (69.552MHz/3)/(8*100)=28.980kHz ; (69.552MHz/3)/(8*100*525)=55.200Hz ; 大きく外れるわけではないのでマルチスキャンモニタは追従できるが気持ち悪い ; ; VGAオシレータの有無の判別 ; VGAモードの垂直周期はVGAオシレータがあるとき16.683ms、ないとき18.116ms ; 垂直同期割り込みの間にTimer-Cが1周10msと7.5ms進んだかどうかでVGAオシレータの有無を判別できるはず ; 後で試す? ; ;---------------------------------------------------------------- ; 同期信号とCRTC設定値の関係 ; ; HT 水平周期カラム数 ; HS 水平同期パルスカラム数 ; HB 水平バックポーチカラム数 ; HD 水平映像期間カラム数 ; HF 水平フロントポーチカラム数 ; VT 垂直周期ラスタ数 ; VS 垂直同期パルスラスタ数 ; VB 垂直バックポーチラスタ数 ; VD 垂直映像期間ラスタ数 ; VF 垂直フロントポーチラスタ数 ; ; R00 HT-1=HS+HB+HD+HF-1 水平フロントポーチ終了カラム ; R01 HS-1 水平同期パルス終了カラム ; R02 HS+HB-5 水平バックポーチ終了カラム-4 ; R03 HS+HB+HD-5 水平映像期間終了カラム-4 ; R04 VT-1=VS+VB+VD+VF-1 垂直フロントポーチ終了ラスタ ; R05 VS-1 垂直同期パルス終了ラスタ ; R06 VS+VB-1 垂直バックポーチ終了ラスタ ; R07 VS+VB+VD-1 垂直映像期間終了ラスタ ; ;---------------------------------------------------------------- ; オシレータと分周比とR20LとHRLの関係 ; ; OSC/DIV R20L HRL ; 38/8 %0**00 * ; 38/4 %0**01 * ; 38/8 %0**1* * ; 69/6 %1**00 0 ; 69/8 %1**00 1 ; 69/3 %1**01 0 ; 69/4 %1**01 1 ; 69/2 %1**10 * スプライト不可 ; 50/2 %1**11 * スプライト不可。Compactから ; ;---------------------------------------------------------------- ; CRTC設定値(CRT向け) ; ; CRT 0/4/8/12/48/61: 512x512 31.500kHz 55.458Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10101 0 91 9 17 81 567 5 40 552 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 3 92 10 12 64 6 568 6 35 512 15 | ; +------------------------------------------------------+ ; (69.552MHz/3)/(8*92)=31.500kHz (69.552MHz/3)/(8*92*568)=55.458Hz ; 64/92=0.696 512/568=0.901 (0.696/0.901)/(512/512)=0.772 ; 31k ; ; CRT 1/5/9/13/49/62: 512x512 15.980kHz 61.463Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %00101 0 75 3 5 69 259 2 16 256 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 38.864 4 76 4 6 64 2 260 3 14 240 3 | ; +------------------------------------------------------+ ; (38.864MHz/4)/(8*76)=15.980kHz (38.864MHz/4)/(8*76*260)=61.463Hz ; 64/76=0.842 240/260=0.923 (0.842/0.923)/(512/512)=0.912 ; 15k インターレース ; ; CRT 2/6/10/14/50/63: 256x256 31.500kHz 55.458Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10000 0 45 4 6 38 567 5 40 552 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 6 46 5 6 32 3 568 6 35 512 15 | ; +------------------------------------------------------+ ; (69.552MHz/6)/(8*46)=31.500kHz (69.552MHz/6)/(8*46*568)=55.458Hz ; 32/46=0.696 512/568=0.901 (0.696/0.901)/(256/256)=0.772 ; 31k ラスタ2度読み ; ; CRT 3/7/11/15/51/64: 256x256 15.980kHz 61.463Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %00000 0 37 1 0 32 259 2 16 256 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 38.864 8 38 2 3 32 1 260 3 14 240 3 | ; +------------------------------------------------------+ ; (38.864MHz/8)/(8*38)=15.980kHz (38.864MHz/8)/(8*38*260)=61.463Hz ; 32/38=0.842 240/260=0.923 (0.842/0.923)/(256/256)=0.912 ; 15k ; ; CRT 16/20/24/52/65: 768x512 31.500kHz 55.458Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10110 0 137 14 28 124 567 5 40 552 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 2 138 15 18 96 9 568 6 35 512 15 | ; +------------------------------------------------------+ ; (69.552MHz/2)/(8*138)=31.500kHz (69.552MHz/2)/(8*138*568)=55.458Hz ; 96/138=0.696 512/568=0.901 (0.696/0.901)/(768/512)=0.514 ; 31k ; ; CRT 17/21/25/53/66: 1024x424 24.699kHz 53.116Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10110 0 175 15 31 159 464 7 32 456 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 2 176 16 20 128 12 465 8 25 424 8 | ; +------------------------------------------------------+ ; (69.552MHz/2)/(8*176)=24.699kHz (69.552MHz/2)/(8*176*465)=53.116Hz ; 128/176=0.727 424/465=0.912 (0.727/0.912)/(1024/424)=0.330 ; 24k ; ; CRT 18/22/26/54/67: 1024x848 24.699kHz 53.116Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %11010 0 175 15 31 159 464 7 32 456 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 2 176 16 20 128 12 465 8 25 424 8 | ; +------------------------------------------------------+ ; (69.552MHz/2)/(8*176)=24.699kHz (69.552MHz/2)/(8*176*465)=53.116Hz ; 128/176=0.727 424/465=0.912 (0.727/0.912)/(1024/848)=0.661 ; 24k インターレース ; ; CRT 19/23/27/55/68: 640x480 31.500kHz 55.458Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10110 0 137 14 36 116 567 5 56 536 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 2 138 15 26 80 17 568 6 51 480 31 | ; +------------------------------------------------------+ ; (69.552MHz/2)/(8*138)=31.500kHz (69.552MHz/2)/(8*138*568)=55.458Hz ; 80/138=0.580 480/568=0.845 (0.580/0.845)/(640/480)=0.514 ; 31k ; ; CRT 28/29/30/31/56/69: 384x256 31.963kHz 56.273Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10001 1 67 6 11 59 567 5 40 552 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 4 68 7 9 48 4 568 6 35 512 15 | ; +------------------------------------------------------+ ; (69.552MHz/4)/(8*68)=31.963kHz (69.552MHz/4)/(8*68*568)=56.273Hz ; 48/68=0.706 512/568=0.901 (0.706/0.901)/(384/256)=0.522 ; 31k ラスタ2度読み ; ; CRT 32/33/34/35/57/70: 512x512 31.500kHz 55.458Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10110 0 137 14 44 108 567 5 40 552 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 2 138 15 34 64 25 568 6 35 512 15 | ; +------------------------------------------------------+ ; (69.552MHz/2)/(8*138)=31.500kHz (69.552MHz/2)/(8*138*568)=55.458Hz ; 64/138=0.464 512/568=0.901 (0.464/0.901)/(512/512)=0.514 ; 31k ; ; CRT 36/37/38/39/58/71: 256x256 31.963kHz 56.273Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10001 1 67 6 19 51 567 5 40 552 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 4 68 7 17 32 12 568 6 35 512 15 | ; +------------------------------------------------------+ ; (69.552MHz/4)/(8*68)=31.963kHz (69.552MHz/4)/(8*68*568)=56.273Hz ; 32/68=0.471 512/568=0.901 (0.471/0.901)/(256/256)=0.522 ; 31k ラスタ2度読み ; ; CRT 40/41/42/43/44/45/46/47/59/60/72/73: 512x256 31.500kHz 55.458Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10001 0 91 9 17 81 567 5 40 552 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 3 92 10 12 64 6 568 6 35 512 15 | ; +------------------------------------------------------+ ; (69.552MHz/3)/(8*92)=31.500kHz (69.552MHz/3)/(8*92*568)=55.458Hz ; 64/92=0.696 512/568=0.901 (0.696/0.901)/(512/256)=0.386 ; 31k ; ;---------------------------------------------------------------- ; CRTC設定値(LCD向け) ; ; LCD 0/4/8/12/48/61: 512x512 35.341kHz 56.546Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10101 0 81 5 11 75 624 1 67 579 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 3 82 6 10 64 2 625 2 66 512 45 | ; +------------------------------------------------------+ ; (69.552MHz/3)/(8*82)=35.341kHz (69.552MHz/3)/(8*82*625)=56.546Hz ; 64/82=0.780 512/625=0.819 (0.780/0.819)/(512/512)=0.953 ; SVGA ; ; LCD 1/5/9/13/49/62: 512x512 35.341kHz 56.546Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10101 0 81 5 11 75 624 1 83 563 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 3 82 6 10 64 2 625 2 82 480 61 | ; +------------------------------------------------------+ ; (69.552MHz/3)/(8*82)=35.341kHz (69.552MHz/3)/(8*82*625)=56.546Hz ; 64/82=0.780 480/625=0.768 (0.780/0.768)/(512/512)=1.016 ; SVGA ; ; LCD 2/6/10/14/50/63: 256x256 34.500kHz 55.200Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10000 0 41 2 3 35 624 1 67 579 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 6 42 3 5 32 2 625 2 66 512 45 | ; +------------------------------------------------------+ ; (69.552MHz/6)/(8*42)=34.500kHz (69.552MHz/6)/(8*42*625)=55.200Hz ; 32/42=0.762 512/625=0.819 (0.762/0.819)/(256/256)=0.930 ; SVGA ラスタ2度読み ; ; LCD 3/7/11/15/51/64: 256x256 34.500kHz 55.200Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10000 0 41 2 3 35 624 1 83 563 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 6 42 3 5 32 2 625 2 82 480 61 | ; +------------------------------------------------------+ ; (69.552MHz/6)/(8*42)=34.500kHz (69.552MHz/6)/(8*42*625)=55.200Hz ; 32/42=0.762 480/625=0.768 (0.762/0.768)/(256/256)=0.992 ; SVGA ラスタ2度読み ; ; LCD 16/20/24/52/65: 768x512 35.056kHz 56.090Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10110 0 123 8 19 115 624 1 67 579 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 2 124 9 15 96 4 625 2 66 512 45 | ; +------------------------------------------------------+ ; (69.552MHz/2)/(8*124)=35.056kHz (69.552MHz/2)/(8*124*625)=56.090Hz ; 96/124=0.774 512/625=0.819 (0.774/0.819)/(768/512)=0.630 ; SVGA ; ; LCD 17/21/25/53/66: 768x600 35.056kHz 56.090Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10110 0 123 8 19 115 624 1 23 623 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 2 124 9 15 96 4 625 2 22 600 1 | ; +------------------------------------------------------+ ; (69.552MHz/2)/(8*124)=35.056kHz (69.552MHz/2)/(8*124*625)=56.090Hz ; 96/124=0.774 600/625=0.960 (0.774/0.960)/(768/600)=0.630 ; SVGA ; ; LCD 18/22/26/54/67: 768x1024 35.056kHz 56.090Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %11010 0 123 8 19 115 624 1 67 579 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 2 124 9 15 96 4 625 2 66 512 45 | ; +------------------------------------------------------+ ; (69.552MHz/2)/(8*124)=35.056kHz (69.552MHz/2)/(8*124*625)=56.090Hz ; 96/124=0.774 512/625=0.819 (0.774/0.819)/(768/1024)=1.260 ; SVGA インターレース ; ; LCD 19/23/27/55/68: 640x480 31.469kHz 59.940Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10111 0 99 11 13 93 524 1 34 514 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 50.350 2 100 12 6 80 2 525 2 33 480 10 | ; +------------------------------------------------------+ ; (50.350MHz/2)/(8*100)=31.469kHz (50.350MHz/2)/(8*100*525)=59.940Hz ; 80/100=0.800 480/525=0.914 (0.800/0.914)/(640/480)=0.656 ; VGA ; ; LCD 28/29/30/31/56/69: 384x256 31.963kHz 51.141Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10001 1 67 6 11 59 624 1 67 579 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 4 68 7 9 48 4 625 2 66 512 45 | ; +------------------------------------------------------+ ; (69.552MHz/4)/(8*68)=31.963kHz (69.552MHz/4)/(8*68*625)=51.141Hz ; 48/68=0.706 512/625=0.819 (0.706/0.819)/(384/256)=0.574 ; ラスタ2度読み ; ; LCD 32/33/34/35/57/70: 512x512 35.056kHz 56.090Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10110 0 123 8 35 99 624 1 67 579 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 2 124 9 31 64 20 625 2 66 512 45 | ; +------------------------------------------------------+ ; (69.552MHz/2)/(8*124)=35.056kHz (69.552MHz/2)/(8*124*625)=56.090Hz ; 64/124=0.516 512/625=0.819 (0.516/0.819)/(512/512)=0.630 ; SVGA ; ; LCD 36/37/38/39/58/71: 256x256 31.963kHz 51.141Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10001 1 67 6 19 51 624 1 67 579 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 4 68 7 17 32 12 625 2 66 512 45 | ; +------------------------------------------------------+ ; (69.552MHz/4)/(8*68)=31.963kHz (69.552MHz/4)/(8*68*625)=51.141Hz ; 32/68=0.471 512/625=0.819 (0.471/0.819)/(256/256)=0.574 ; ラスタ2度読み ; ; LCD 40/41/42/43/44/45/46/47/59/60/72/73: 512x256 35.341kHz 56.546Hz ; +------------------------------------------------------+ ; | R20L HRL R00 R01 R02 R03 R04 R05 R06 R07 | ; | %10001 0 81 5 11 75 624 1 67 579 | ; +------------------------------------------------------+ ; | OSC DIV HT HS HB HD HF VT VS VB VD VF | ; | 69.552 3 82 6 10 64 2 625 2 66 512 45 | ; +------------------------------------------------------+ ; (69.552MHz/3)/(8*82)=35.341kHz (69.552MHz/3)/(8*82*625)=56.546Hz ; 64/82=0.780 512/625=0.819 (0.780/0.819)/(512/256)=0.476 ; SVGA ; ; 【参考】VGA: 640x480 31.469kHz 59.940Hz ; +------------------------------------------------------+ ; | OSC HT HS HB HD HF VT VS VB VD VF | ; | 25.175 100 12 6 80 2 525 2 33 480 10 | ; +------------------------------------------------------+ ; 25.175MHz/(8*100)=31.469kHz (25.175MHz/1)/(8*100*525)=59.940Hz ; 80/100=0.800 480/525=0.914 (0.800/0.914)/(640/480)=0.656 ; ; 【参考】SVGA: 800x600 35.156kHz 56.250Hz ; +------------------------------------------------------+ ; | OSC HT HS HB HD HF VT VS VB VD VF | ; | 36.000 128 9 16 100 3 625 2 22 600 1 | ; +------------------------------------------------------+ ; 36.000MHz/(8*128)=35.156kHz (36.000MHz/1)/(8*128*625)=56.250Hz ; 100/128=0.781 600/625=0.960 (0.781/0.960)/(800/600)=0.610 ; ; 【参考】SVGA: 800x600 37.879kHz 60.317Hz ; +------------------------------------------------------+ ; | OSC HT HS HB HD HF VT VS VB VD VF | ; | 40.000 132 16 11 100 5 628 4 23 600 1 | ; +------------------------------------------------------+ ; 40.000MHz/(8*132)=37.879kHz (40.000MHz/1)/(8*132*628)=60.317Hz ; 100/132=0.758 600/628=0.955 (0.758/0.955)/(800/600)=0.595 ; ; 【参考】SVGA: 800x600 46.875kHz 75.000Hz ; +------------------------------------------------------+ ; | OSC HT HS HB HD HF VT VS VB VD VF | ; | 49.500 132 10 20 100 2 625 3 21 600 1 | ; +------------------------------------------------------+ ; 49.500MHz/(8*132)=46.875kHz (49.500MHz/1)/(8*132*625)=75.000Hz ; 100/132=0.758 600/625=0.960 (0.758/0.960)/(800/600)=0.592 ; ;---------------------------------------------------------------- ;パラメータ1 .offset 0 crtmod_param_1_width: .ds.w 1 crtmod_param_1_height: .ds.w 1 crtmod_param_1_r20h: .ds.b 1 .ds.b 1 crtmod_param_1_2nd: .ds.w 1 crtmod_param_1_size: .text ;パラメータ2 .offset 0 crtmod_param_2_r20l: .ds.b 1 crtmod_param_2_hrl: .ds.b 1 crtmod_param_2_r00: .ds.w 1 crtmod_param_2_r01: .ds.w 1 crtmod_param_2_r02: .ds.w 1 crtmod_param_2_r03: .ds.w 1 crtmod_param_2_r04: .ds.w 1 crtmod_param_2_r05: .ds.w 1 crtmod_param_2_r06: .ds.w 1 crtmod_param_2_r07: .ds.w 1 crtmod_param_2_r08: .ds.w 1 crtmod_param_2_size: .text crtmod_param_1 .macro width,height,r20h,offset2nd .dc.w width .dc.w height .dc.b r20h ;R20H .dc.b 0 .dc.w crtmod_param_2_size*offset2nd .endm crtmod_param_2 .macro r20l,hrl,ht,hs,hb,hd,hf,vt,vs,vb,vd,vf,r08 .fail (ht.and.1)!=0 .fail ht!=hs+hb+hd+hf .fail vt!=vs+vb+vd+vf .dc.b r20l ;R20L .dc.b hrl ;HRL .dc.w hs+hb+hd+hf-1 ;R00 .dc.w hs-1 ;R01 .dc.w hs+hb-5 ;R02 .dc.w hs+hb+hd-5 ;R03 .dc.w vs+vb+vd+vf-1 ;R04 .dc.w vs-1 ;R05 .dc.w vs+vb-1 ;R06 .dc.w vs+vb+vd-1 ;R07 .dc.w r08 ;R08 .endm crtmod_modes equ (crtmod_table_1_crt_end-crtmod_table_1_crt)/crtmod_param_1_size ;画面モードの数 iocs_10_CRTMOD: dMM reg d3 ;メモリモード dPM reg d4 ;設定前の画面モード dGVRAM reg d5 ;$00C00000 aE8 reg a2 ;(~)E8のベースアドレス aEB reg a3 ;(~)EBのベースアドレス aED reg a4 ;(~)EDのベースアドレス aP1 reg a5 ;パラメータ1のアドレス aP2 reg a6 ;パラメータ2のアドレス push d1-d2/dMM/dPM/dGVRAM/a0-a1/aE8/aEB/aED/aP1/aP2 move.l #$00C00000,dGVRAM ;(~)E8でアクセスする ; $00E80000 CRTC ; $00E82000 VICON ; $00E84000 DMAC ; $00E86000 SUPERAREA ; $00E88000 MFP ; $00E8A000 RTC ; $00E8C000 PRNPORT ; $00E8E000 SYSPORT lea.l $00E88000,aE8 E8 reg -$00E88000(aE8) ;(~)EBでアクセスする ; $00EB0000 SPRC lea.l $00EB8000,aEB EB reg -$00EB8000(aEB) ;(~)EDでアクセスする ; $00ED0000 SRAM lea.l $00ED8000,aED ED reg -$00ED8000(aED) ;SRAMを初期化する moveq.l #$60,d0 moveq.l #$F0,d2 and.b (SRAM_XEIJ)ED,d2 if <cmp.b d0,d2>,ne ;初期化されていない move.b #$31,(SYSPORT_SRAM)E8 ;unlocksram move.b d0,(SRAM_XEIJ)ED ;初期化する clr.b (SYSPORT_SRAM)E8 ;locksram endif ;バージョンの確認 move.l #CRTMOD_VERSION,d0 goto <cmp.w #$56FF,d1>,eq,@f if <cmp.w #$16FF,d1>,eq if <btst.b #SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED>,ne bset.l #31,d0 endif @@: goto crtmod_pop endif ;画面モードの最大値の確認 if <cmp.w #$76FF,d1>,eq move.l #$16000000+crtmod_modes-1,d0 ; goto crtmod_pop goto @b endif ;設定前の画面モードを確認する moveq.l #0,dPM move.b BIOS_CRTMOD.w,dPM ;設定前の画面モード swap.w dPM ;<dPM.l:設定前の画面モード<<16 ;初期化するか move.w d1,dPM clr.b dPM sub.w dPM,d1 ;<d1.w:画面モード ;<dPM.w:$0000=初期化する,$0100=初期化しない,$4300=CRT向け,$4C00=LCD向け ;CRT向けとLCD向けのスイッチの切り替え if <cmp.w #$4300,dPM>,eq ;CRT向け move.b #$31,(SYSPORT_SRAM)E8 ;unlocksram bclr.b #SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED clr.b (SYSPORT_SRAM)E8 ;locksram clr.w dPM ;初期化する elif <cmp.w #$4C00,dPM>,eq ;LCD向け move.b #$31,(SYSPORT_SRAM)E8 ;unlocksram bset.b #SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED clr.b (SYSPORT_SRAM)E8 ;locksram clr.w dPM ;初期化する endif ;<dPM.w:$0000=初期化する,$0100=初期化しない ;取得のみか ; IPLROM 1.0~1.3は$FFFFが取得のみ ; ここでは$xxFFを取得のみとする ; ただし$43FFと$4CFFはCRT向けとLCD向けのスイッチの切り替えだけ行う goto <cmp.w #$00FF,d1>,eq,crtmod_end ;取得のみ ;設定後の画面モードが範囲外か ; IPLROM 1.0~1.3は$FFFFを除いて設定後の画面モードが範囲外のとき何も返さない ; ここでは$xxFFを除いて設定後の画面モードが範囲外のとき-1を返す if <cmp.w #crtmod_modes,d1>,hs moveq.l #-1,d0 ;設定後の画面モードが範囲外 goto crtmod_pop endif ;設定する ;パラメータ1のアドレスを求める lea.l crtmod_table_1_crt(pc),aP1 if <btst.b #SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED>,ne ;LCD向け lea.l crtmod_table_1_lcd(pc),aP1 endif move.w d1,d0 .if crtmod_param_1_size=8 lsl.w #3,d0 .else mulu.w #crtmod_param_1_size,d0 .endif adda.w d0,aP1 ;<aP1.l:パラメータ1のアドレス ;パラメータ2のアドレスを求める lea.l crtmod_table_2(pc),aP2 adda.w crtmod_param_1_2nd(aP1),aP2 ;<aP2.l:パラメータ2のアドレス ;メモリモードを確認する moveq.l #7,dMM and.b crtmod_param_1_r20h(aP1),dMM ;メモリモード。0~7 ;<dMM.w:メモリモード。0~7 ;拡張グラフィック画面を確認する ; 拡張グラフィック画面がないのに拡張グラフィック画面が必要な画面モードが指定されたとき-2を返す ; 76543210 if <btst.b dMM,#%10100000>,ne ;メモリモード5,7。拡張グラフィック画面が必要 move.b (CRTC_MODE_BYTE)E8,-(sp) ;メモリモードを保存 move.b #7,(CRTC_MODE_BYTE)E8 ;メモリモードを7に変更 movea.l dGVRAM,a0 move.w (a0),d2 ;保存 not.w (a0) ;反転 move.w (a0),d0 ;d0=反転してから読み出したもの move.w d2,(a0) ;復元 move.b (sp)+,(CRTC_MODE_BYTE)E8 ;メモリモードを復元 not.w d2 ;d2=読み出してから反転したもの if <cmp.w d2,d0>,ne ;反転できていない moveq.l #-2,d0 ;拡張グラフィック画面がない goto crtmod_pop endif endif ;初期化するか if <tst.w dPM>,eq ;初期化する ;設定後の画面モードを保存する move.b d1,BIOS_CRTMOD.w ;設定後の画面モード ;グラフィック画面OFF、テキスト画面OFF、スプライト画面OFF clr.w (VICON_VISIBLE)E8 ;テキストカーソルOFF IOCS _B_CUROFF ;テキストプレーン0~1をクリアする ; ラスタコピーを使うと速いがコードが長くなる ; 初回はCRTCが動いていないのでラスタコピーが終わらない move.w #$0133,(CRTC_ACCESS)E8 ;同時アクセス開始 moveq.l #0,d0 lea.l $00E00000,a0 ;テキストVRAM move.w #($00E20000-$00E00000)/(4*2)-1,d1 ;16384回 for d1 move.l d0,(a0)+ move.l d0,(a0)+ next move.w #$0033,(CRTC_ACCESS)E8 ;同時アクセス終了 ;グラフィック画面使用不可 clr.w BIOS_GRAPHIC_PALETS.w ;グラフィック画面の色数-1。0=グラフィック画面使用不可 ;初期化する/しない共通 bsr crtmod_common ;CRTCコマンド停止 clr.w (CRTC_ACTION)E8 ;グラフィックパレットを初期化する .ifdef CRTMOD_REPRODUCE_BUG ;バグを再現させる moveq.l #3,d0 and.b crtmod_param_2_r20l(aP2),d0 ;水平解像度。256x256=256色,512x512=512色,768x512=65536色 .else move.w dMM,d0 ;メモリモード。0~7 .endif PATCH_jsr g_clr_on,initialize_gpalet ;グラフィックパレットを初期化する ;グラフィックストレージON ; IPLROM 1.0~1.3の_CRTMODはグラフィックストレージONの状態で復帰する bset.b #CRTC_GRAPHIC_STORAGE_BIT,(CRTC_MODE_BYTE)E8 ;グラフィックストレージON ;テキストカーソルON IOCS _B_CURON ;テキストパレットを初期化する lea.l (SRAM_TEXT_PALET_0)ED,a0 lea.l (VICON_TSPALET)E8,a1 move.l (a0)+,(a1)+ ;0,1 move.l (a0)+,(a1)+ ;2,3 move.l (a0),d0 ;d0=4|8 move.l d0,d1 ;d1=4|8 swap.w d0 ;d0=8|4 move.w d0,(a1)+ ;4 move.w d0,(a1)+ ;5 move.w d0,(a1)+ ;6 move.w d0,(a1)+ ;7 move.w d1,d0 ;d0=8|8 move.l d0,(a1)+ ;8,9 move.l d0,(a1)+ ;10,11 move.l d0,(a1)+ ;12,13 move.l d0,(a1)+ ;14,15 ;コントラストを初期化する move.b (SRAM_CONTRAST)ED,(SYSPORT_CONTRAST)E8 ;スプライトコントローラを設定する ~i = SPRC_SPRITE_OFF|SPRC_BG_1_TEXT_1|SPRC_BG_1_OFF|SPRC_BG_0_TEXT_0|SPRC_BG_0_OFF move.w #~i,(SPRC_CONTROL)EB ;テキスト画面ON move.w #VICON_TXON_MASK,(VICON_VISIBLE)E8 ;優先順位を設定する ~i = 0<<VICON_SPPR_BIT|1<<VICON_TXPR_BIT|2<<VICON_GRPR_BIT ;SP>TX>GR ~j = 3<<VICON_G4TH_BIT|2<<VICON_G3RD_BIT|1<<VICON_G2ND_BIT|0<<VICON_G1ST_BIT ;G1>G2>G3>G4 move.w #~i|~j,(VICON_PRIORITY)E8 else ;初期化しない ;設定後の画面モードを保存する move.b d1,BIOS_CRTMOD.w ;設定後の画面モード ;グラフィック画面使用不可 clr.w BIOS_GRAPHIC_PALETS.w ;グラフィック画面の色数-1。0=グラフィック画面使用不可 ;初期化する/しない共通 bsr crtmod_common ;グラフィック画面が表示されているか moveq.l #VICON_GXON_MASK|VICON_G4ON_MASK|VICON_G3ON_MASK|VICON_G2ON_MASK|VICON_G1ON_MASK,d0 and.w (VICON_VISIBLE)E8,d0 if ne ;グラフィック画面が表示されているとき ;メモリモードを設定する ; ストレージは変化しない moveq.l #.not.7,d0 and.b (CRTC_MODE_BYTE)E8,d0 or.b dMM,d0 move.b d0,(CRTC_MODE_BYTE)E8 move.w dMM,(VICON_MEMORY_MODE)E8 ;BIOSワークエリアを初期化する lea.l BIOS_GRAPHIC_PAGE.w,a0 ;BIOS_GRAPHIC_Y_OFFSET,BIOS_GRAPHIC_PALETS move.l dGVRAM,(a0)+ ;描画ページ先頭アドレス move.l #2*512,d0 if <cmp.w #4,dMM>,hs ;4~7 add.w d0,d0 ;2*1024 endif move.l d0,(a0)+ ;Y方向オフセット moveq.l #16-1,d0 ; 76543210 if <btst.b dMM,#%00100010>,ne ;1,5 st.b d0 ;256-1 ; 76543210 elif <btst.b dMM,#%10001100>,ne ;2,3,7 moveq.l #-1,d0 ;65536-1 endif move.w d0,(a0) ;色数-1 endif endif ;終了 ;<dPM.l:設定前の画面モード<<16 crtmod_end: clr.w dPM swap.w dPM ;設定前の画面モード move.l dPM,d0 crtmod_pop: pop rts ;初期化する/しない共通 crtmod_common: ;CRTCとシステムポートのR20,HRL,R00~R07を設定する ; すべての画面モードがメモリモード3になる ; ストレージはOFFになる move.w #3<<8,d2 ;R20H(新) move.b crtmod_param_2_r20l(aP2),d2 ;R20L(新) ;<d2.w:R20(新) lea.l dot_clock_rank(pc),a0 moveq.l #%00011111,d0 and.b (CRTC_RESOLUTION_BYTE)E8,d0 ;R20L(古) moveq.l #SYSPORT_HRL,d1 and.b (SYSPORT_MISC)E8,d1 neg.b d1 addx.b d0,d0 ;R20L<<1|HRL(古) move.b (a0,d0.w),d0 ;古いドットクロックのランク moveq.l #%00011111,d1 and.b d2,d1 ;R20L(新) add.b d1,d1 add.b crtmod_param_2_hrl(aP2),d1 ;R20L<<1|HRL(新) move.b (a0,d1.w),d1 ;新しいドットクロックのランク if <cmp.b d0,d1>,lo ;ドットクロックが下がる move.w d2,(CRTC_MODE_RESOLUTION)E8 ;R20 tst.b crtmod_param_2_hrl(aP2) bsne.b #SYSPORT_HRL_BIT,(SYSPORT_MISC)E8 ;HRL lea.l (CRTC_H_SYNC_END)E8,a0 ;R01 lea.l crtmod_param_2_r01(aP2),a1 move.w (a1)+,(a0)+ ;R01 move.l (a1)+,(a0)+ ;R02,R03 move.l (a1)+,(a0)+ ;R04,R05 move.l (a1)+,(a0)+ ;R06,R07 move.w crtmod_param_2_r00(aP2),(CRTC_H_FRONT_END)E8 ;R00 else ;ドットクロックが同じか上がる lea.l (CRTC_H_FRONT_END)E8,a0 ;R00 lea.l crtmod_param_2_r00(aP2),a1 move.l (a1)+,(a0)+ ;R00,R01 move.l (a1)+,(a0)+ ;R02,R03 move.l (a1)+,(a0)+ ;R04,R05 move.l (a1)+,(a0)+ ;R06,R07 move.w d2,(CRTC_MODE_RESOLUTION)E8 ;R20 tst.b crtmod_param_2_hrl(aP2) bsne.b #SYSPORT_HRL_BIT,(SYSPORT_MISC)E8 ;HRL endif ;CRTCのR08を設定する ; 外部同期水平アジャスト ; スーパーインポーズするときビデオの映像とX68000の映像を重ねるために、 ; ビデオとX68000の水平同期パルスの先頭の時間差を38.863632MHzのサイクル数で指定する ; 低解像度512x512のとき ; 水平同期パルス幅は4キャラクタ。R01=4-1=3 ; 水平バックポーチは6キャラクタ。R02=4+6-5=5 ; 外部同期水平アジャストは44 ; perl -e "print((4.7+4.7)*38.863632-(4*8*(4+6))-1)" ; 44.3181408 ; 低解像度256x256のとき。1ドット追加する ; 水平同期パルス幅は2キャラクタ。R01=2-1=1 ; 水平バックポーチは3キャラクタ。R02=2+3-5=0 ; 外部同期水平アジャストは36 ; perl -e "print((4.7+4.7)*38.863632-(8*(8*(2+3)+1))-1)" ; 36.3181408 move.w crtmod_param_2_r08(aP2),(CRTC_ADJUST)E8 ;R08 ;CRTCのR09~R19,R21~R24を初期化する moveq.l #0,d0 lea.l (CRTC_RASTER)E8,a0 ;R09 move.w d0,(a0)+ ;R09 move.l d0,(a0)+ ;R10,R11 move.l d0,(a0)+ ;R12,R13 move.l d0,(a0)+ ;R14,R15 move.l d0,(a0)+ ;R16,R17 move.l d0,(a0)+ ;R18,R19 addq.l #2,a0 move.w #$0033,(a0)+ ;R21 move.l d0,(a0)+ ;R22,R23 move.w d0,(a0)+ ;R24 ;ビデオコントローラのメモリモードを設定する ; すべての画面モードがメモリモード3になる move.w #3,(VICON_MEMORY_MODE)E8 ;スプライトコントローラを初期化する ;解像度 moveq.l #%1_11_11,d1 and.b crtmod_param_2_r20l(aP2),d1 ;R20L ;<d1.w:解像度 ;水平バックポーチ終了カラム moveq.l #4,d0 add.w crtmod_param_2_r02(aP2),d0 move.w d0,(SPRC_H_BACK_END)EB ;スプライト水平バックポーチ終了カラム。R02+4 ;水平フロントポーチ終了カラム ; 水平バックポーチ終了カラムを設定後130us待ってから水平フロントポーチ終了カラムを設定する ; 水平フロントポーチ終了カラムは水平256ドットのときはR00と同じ値、それ以外は255 ; Inside X68000に低解像度256x256のときだけR00と同じ値を、それ以外は255を設定すると書かれているが、 ; 高解像度256x256のときも255にするとスプライトが崩れる場合がある ; 水平512ドットのときは255にしないと水平256ドットから水平512ドットに切り替えたときスプライトの水平方向の位置がずれることがある ; IPLROM 1.3はdbraでX68030 25MHzのとき500us待っている。060turboのときウエイトが不足する moveq.l #500/50,d0 ;500us bsr wait_50us ;50us単位のウェイト moveq.l #%0_00_11,d0 and.b d1,d0 if eq ;水平256ドット move.w crtmod_param_2_r00(aP2),(SPRC_H_FRONT_END)EB ;スプライト水平フロントポーチ終了カラム。R00 else ;水平256ドット以外 move.w #255,(SPRC_H_FRONT_END)EB ;スプライト水平フロントポーチ終了カラム。255 endif ;垂直バックポーチ終了ラスタ move.w crtmod_param_2_r06(aP2),(SPRC_V_BACK_END)EB ;スプライト垂直バックポーチ終了ラスタ。R06 ;解像度 move.b BIOS_CRTMOD.w,d0 if <cmp.b #36,d0>,hs ;36~ if <cmp.b #40,d0>,lo ;36/37/38/39 256x256(正方形) moveq.l #%10000,d1 ;スプライトは256x256 elif <cmp.b #44,d0>,hs ;44~ ifor <cmp.b #48,d0>,lo,<cmp.b #60,d0>,eq,<cmp.b #73,d0>,eq ;44/45/46/47/60/73 512x256(※) moveq.l #%10101,d1 ;スプライトは512x512 endif endif endif move.w d1,(SPRC_RESOLUTION)EB ;スプライト解像度。--------|---|高解像度|垂直サイズ##|水平サイズ## ;グラフィック画面のクリッピングエリア ; 画面モード20~27は表示画面が実画面より大きいことに注意する move.w crtmod_param_1_width(aP1),d0 ;幅 move.w crtmod_param_1_height(aP1),d1 ;高さ if <cmp.w #4,dMM>,lo ;メモリモード0~3。512x512まで move.w #512,d2 if <cmp.w d2,d0>,hi move.w d2,d0 endif if <cmp.w d2,d1>,hi move.w d2,d1 endif endif subq.w #1,d0 ;X最大 subq.w #1,d1 ;Y最大 clr.l BIOS_GRAPHIC_LEFT.w ;BIOS_GRAPHIC_TOP move.w d0,BIOS_GRAPHIC_RIGHT.w move.w d1,BIOS_GRAPHIC_BOTTOM.w ;グラフィックVRAMのY方向のオフセット ;dMM= 0 1 2 3 4 5 6 7 moveq.l #4,d0 ; d0= 4 4 4 4 4 4 4 4 and.w dMM,d0 ; d0= 0 0 0 0 4 4 4 4 addq.w #4,d0 ; d0= 4 4 4 4 8 8 8 8 lsl.w #8,d0 ; d0=1024 1024 1024 1024 2048 2048 2048 2048 move.l d0,BIOS_GRAPHIC_Y_OFFSET.w ;グラフィック画面のページ数 ;dMM=0 1 2 3 4 5 6 7 moveq.l #4,d0 ; d0=4 4 4 4 4 4 4 4 lsr.b dMM,d0 ; d0=4 2 1 0 0 0 0 0 seq.b d1 ; d1=0 0 0 -1 -1 -1 -1 -1 sub.b d1,d0 ; d0=4 2 1 1 1 1 1 1 move.b d0,BIOS_GRAPHIC_PAGES.w ;テキスト画面の位置 move.l #$00E00000,BIOS_TEXT_PLANE.w clr.l BIOS_CONSOLE_OFFSET.w ;テキスト画面の大きさ move.w crtmod_param_1_width(aP1),d0 ;幅 move.w crtmod_param_1_height(aP1),d1 ;高さ lsr.w #3,d0 ;幅/8 lsr.w #4,d1 ;高さ/16。424は16で割り切れないことに注意 subq.w #1,d0 ;幅/8-1 subq.w #1,d1 ;高さ/16-1 move.w d0,BIOS_CONSOLE_RIGHT.w move.w d1,BIOS_CONSOLE_BOTTOM.w ;テキストカーソルの位置 clr.l BIOS_CURSOR_COLUMN.w ;BIOS_CURSOR_ROW ;マウスカーソルの移動範囲 clr.l d1 move.l BIOS_GRAPHIC_RIGHT,d2 ;BIOS_GRAPHIC_BOTTOM IOCS _MS_LIMIT ;IOCSコール$77 _MS_LIMIT マウスカーソルの移動範囲を設定する rts ;パラメータ1(CRT向け) crtmod_table_1_crt: ; WIDTH HEIGHT R20H 2ND 1ST crtmod_param_1 512, 512, 4, 0 ; CRT 0 crtmod_param_1 512, 512, 4, 1 ; CRT 1 crtmod_param_1 256, 256, 4, 2 ; CRT 2 crtmod_param_1 256, 256, 4, 3 ; CRT 3 crtmod_param_1 512, 512, 0, 0 ; CRT 4 crtmod_param_1 512, 512, 0, 1 ; CRT 5 crtmod_param_1 256, 256, 0, 2 ; CRT 6 crtmod_param_1 256, 256, 0, 3 ; CRT 7 crtmod_param_1 512, 512, 1, 0 ; CRT 8 crtmod_param_1 512, 512, 1, 1 ; CRT 9 crtmod_param_1 256, 256, 1, 2 ; CRT 10 crtmod_param_1 256, 256, 1, 3 ; CRT 11 crtmod_param_1 512, 512, 3, 0 ; CRT 12 crtmod_param_1 512, 512, 3, 1 ; CRT 13 crtmod_param_1 256, 256, 3, 2 ; CRT 14 crtmod_param_1 256, 256, 3, 3 ; CRT 15 crtmod_param_1 768, 512, 4, 4 ; CRT 16 crtmod_param_1 1024, 424, 4, 5 ; CRT 17 crtmod_param_1 1024, 848, 4, 6 ; CRT 18 crtmod_param_1 640, 480, 4, 7 ; CRT 19 crtmod_param_1 768, 512, 1, 4 ; CRT 20 crtmod_param_1 1024, 424, 1, 5 ; CRT 21 crtmod_param_1 1024, 848, 1, 6 ; CRT 22 crtmod_param_1 640, 480, 1, 7 ; CRT 23 crtmod_param_1 768, 512, 3, 4 ; CRT 24 crtmod_param_1 1024, 424, 3, 5 ; CRT 25 crtmod_param_1 1024, 848, 3, 6 ; CRT 26 crtmod_param_1 640, 480, 3, 7 ; CRT 27 crtmod_param_1 384, 256, 4, 8 ; CRT 28 crtmod_param_1 384, 256, 0, 8 ; CRT 29 crtmod_param_1 384, 256, 1, 8 ; CRT 30 crtmod_param_1 384, 256, 3, 8 ; CRT 31 crtmod_param_1 512, 512, 4, 9 ; CRT 32 crtmod_param_1 512, 512, 0, 9 ; CRT 33 crtmod_param_1 512, 512, 1, 9 ; CRT 34 crtmod_param_1 512, 512, 3, 9 ; CRT 35 crtmod_param_1 256, 256, 4, 10 ; CRT 36 crtmod_param_1 256, 256, 0, 10 ; CRT 37 crtmod_param_1 256, 256, 1, 10 ; CRT 38 crtmod_param_1 256, 256, 3, 10 ; CRT 39 crtmod_param_1 512, 256, 4, 22 ; CRT 40 crtmod_param_1 512, 256, 0, 22 ; CRT 41 crtmod_param_1 512, 256, 1, 22 ; CRT 42 crtmod_param_1 512, 256, 3, 22 ; CRT 43 crtmod_param_1 512, 256, 4, 22 ; CRT 44 crtmod_param_1 512, 256, 0, 22 ; CRT 45 crtmod_param_1 512, 256, 1, 22 ; CRT 46 crtmod_param_1 512, 256, 3, 22 ; CRT 47 crtmod_param_1 512, 512, 5, 0 ; CRT 48 crtmod_param_1 512, 512, 5, 1 ; CRT 49 crtmod_param_1 256, 256, 5, 2 ; CRT 50 crtmod_param_1 256, 256, 5, 3 ; CRT 51 crtmod_param_1 768, 512, 5, 4 ; CRT 52 crtmod_param_1 1024, 424, 5, 5 ; CRT 53 crtmod_param_1 1024, 848, 5, 6 ; CRT 54 crtmod_param_1 640, 480, 5, 7 ; CRT 55 crtmod_param_1 384, 256, 5, 8 ; CRT 56 crtmod_param_1 512, 512, 5, 9 ; CRT 57 crtmod_param_1 256, 256, 5, 10 ; CRT 58 crtmod_param_1 512, 256, 5, 22 ; CRT 59 crtmod_param_1 512, 256, 5, 22 ; CRT 60 crtmod_param_1 512, 512, 7, 0 ; CRT 61 crtmod_param_1 512, 512, 7, 1 ; CRT 62 crtmod_param_1 256, 256, 7, 2 ; CRT 63 crtmod_param_1 256, 256, 7, 3 ; CRT 64 crtmod_param_1 768, 512, 7, 4 ; CRT 65 crtmod_param_1 1024, 424, 7, 5 ; CRT 66 crtmod_param_1 1024, 848, 7, 6 ; CRT 67 crtmod_param_1 640, 480, 7, 7 ; CRT 68 crtmod_param_1 384, 256, 7, 8 ; CRT 69 crtmod_param_1 512, 512, 7, 9 ; CRT 70 crtmod_param_1 256, 256, 7, 10 ; CRT 71 crtmod_param_1 512, 256, 7, 22 ; CRT 72 crtmod_param_1 512, 256, 7, 22 ; CRT 73 crtmod_table_1_crt_end: ;パラメータ1(LCD向け) crtmod_table_1_lcd: ; WIDTH HEIGHT R20H 2ND 1ST crtmod_param_1 512, 512, 4, 11 ; LCD 0 crtmod_param_1 512, 512, 4, 12 ; LCD 1 crtmod_param_1 256, 256, 4, 13 ; LCD 2 crtmod_param_1 256, 256, 4, 14 ; LCD 3 crtmod_param_1 512, 512, 0, 11 ; LCD 4 crtmod_param_1 512, 512, 0, 12 ; LCD 5 crtmod_param_1 256, 256, 0, 13 ; LCD 6 crtmod_param_1 256, 256, 0, 14 ; LCD 7 crtmod_param_1 512, 512, 1, 11 ; LCD 8 crtmod_param_1 512, 512, 1, 12 ; LCD 9 crtmod_param_1 256, 256, 1, 13 ; LCD 10 crtmod_param_1 256, 256, 1, 14 ; LCD 11 crtmod_param_1 512, 512, 3, 11 ; LCD 12 crtmod_param_1 512, 512, 3, 12 ; LCD 13 crtmod_param_1 256, 256, 3, 13 ; LCD 14 crtmod_param_1 256, 256, 3, 14 ; LCD 15 crtmod_param_1 768, 512, 4, 15 ; LCD 16 crtmod_param_1 768, 600, 4, 16 ; LCD 17 crtmod_param_1 768, 1024, 4, 17 ; LCD 18 crtmod_param_1 640, 480, 4, 18 ; LCD 19 crtmod_param_1 768, 512, 1, 15 ; LCD 20 crtmod_param_1 768, 600, 1, 16 ; LCD 21 crtmod_param_1 768, 1024, 1, 17 ; LCD 22 crtmod_param_1 640, 480, 1, 18 ; LCD 23 crtmod_param_1 768, 512, 3, 15 ; LCD 24 crtmod_param_1 768, 600, 3, 16 ; LCD 25 crtmod_param_1 768, 1024, 3, 17 ; LCD 26 crtmod_param_1 640, 480, 3, 18 ; LCD 27 crtmod_param_1 384, 256, 4, 19 ; LCD 28 crtmod_param_1 384, 256, 0, 19 ; LCD 29 crtmod_param_1 384, 256, 1, 19 ; LCD 30 crtmod_param_1 384, 256, 3, 19 ; LCD 31 crtmod_param_1 512, 512, 4, 20 ; LCD 32 crtmod_param_1 512, 512, 0, 20 ; LCD 33 crtmod_param_1 512, 512, 1, 20 ; LCD 34 crtmod_param_1 512, 512, 3, 20 ; LCD 35 crtmod_param_1 256, 256, 4, 21 ; LCD 36 crtmod_param_1 256, 256, 0, 21 ; LCD 37 crtmod_param_1 256, 256, 1, 21 ; LCD 38 crtmod_param_1 256, 256, 3, 21 ; LCD 39 crtmod_param_1 512, 256, 4, 23 ; LCD 40 crtmod_param_1 512, 256, 0, 23 ; LCD 41 crtmod_param_1 512, 256, 1, 23 ; LCD 42 crtmod_param_1 512, 256, 3, 23 ; LCD 43 crtmod_param_1 512, 256, 4, 23 ; LCD 44 crtmod_param_1 512, 256, 0, 23 ; LCD 45 crtmod_param_1 512, 256, 1, 23 ; LCD 46 crtmod_param_1 512, 256, 3, 23 ; LCD 47 crtmod_param_1 512, 512, 5, 11 ; LCD 48 crtmod_param_1 512, 512, 5, 12 ; LCD 49 crtmod_param_1 256, 256, 5, 13 ; LCD 50 crtmod_param_1 256, 256, 5, 14 ; LCD 51 crtmod_param_1 768, 512, 5, 15 ; LCD 52 crtmod_param_1 768, 600, 5, 16 ; LCD 53 crtmod_param_1 768, 1024, 5, 17 ; LCD 54 crtmod_param_1 640, 480, 5, 18 ; LCD 55 crtmod_param_1 384, 256, 5, 19 ; LCD 56 crtmod_param_1 512, 512, 5, 20 ; LCD 57 crtmod_param_1 256, 256, 5, 21 ; LCD 58 crtmod_param_1 512, 256, 5, 23 ; LCD 59 crtmod_param_1 512, 256, 5, 23 ; LCD 60 crtmod_param_1 512, 512, 7, 11 ; LCD 61 crtmod_param_1 512, 512, 7, 12 ; LCD 62 crtmod_param_1 256, 256, 7, 13 ; LCD 63 crtmod_param_1 256, 256, 7, 14 ; LCD 64 crtmod_param_1 768, 512, 7, 15 ; LCD 65 crtmod_param_1 768, 600, 7, 16 ; LCD 66 crtmod_param_1 768, 1024, 7, 17 ; LCD 67 crtmod_param_1 640, 480, 7, 18 ; LCD 68 crtmod_param_1 384, 256, 7, 19 ; LCD 69 crtmod_param_1 512, 512, 7, 20 ; LCD 70 crtmod_param_1 256, 256, 7, 21 ; LCD 71 crtmod_param_1 512, 256, 7, 23 ; LCD 72 crtmod_param_1 512, 256, 7, 23 ; LCD 73 ;パラメータ2 crtmod_table_2: ; R20L HRL HT HS HB HD HF VT VS VB VD VF R08 2ND 1ST crtmod_param_2 %10101, 0, 92, 10, 12, 64, 6, 568, 6, 35, 512, 15, 27 ; 0 CRT 0/4/8/12/48/61 crtmod_param_2 %00101, 0, 76, 4, 6, 64, 2, 260, 3, 14, 240, 3, 44 ; 1 CRT 1/5/9/13/49/62 crtmod_param_2 %10000, 0, 46, 5, 6, 32, 3, 568, 6, 35, 512, 15, 27 ; 2 CRT 2/6/10/14/50/63 crtmod_param_2 %00000, 0, 38, 2, 3, 32, 1, 260, 3, 14, 240, 3, 36 ; 3 CRT 3/7/11/15/51/64 crtmod_param_2 %10110, 0, 138, 15, 18, 96, 9, 568, 6, 35, 512, 15, 27 ; 4 CRT 16/20/24/52/65 crtmod_param_2 %10110, 0, 176, 16, 20, 128, 12, 465, 8, 25, 424, 8, 27 ; 5 CRT 17/21/25/53/66 crtmod_param_2 %11010, 0, 176, 16, 20, 128, 12, 465, 8, 25, 424, 8, 27 ; 6 CRT 18/22/26/54/67 crtmod_param_2 %10110, 0, 138, 15, 26, 80, 17, 568, 6, 51, 480, 31, 27 ; 7 CRT 19/23/27/55/68 crtmod_param_2 %10001, 1, 68, 7, 9, 48, 4, 568, 6, 35, 512, 15, 27 ; 8 CRT 28/29/30/31/56/69 crtmod_param_2 %10110, 0, 138, 15, 34, 64, 25, 568, 6, 35, 512, 15, 27 ; 9 CRT 32/33/34/35/57/70 crtmod_param_2 %10001, 1, 68, 7, 17, 32, 12, 568, 6, 35, 512, 15, 27 ; 10 CRT 36/37/38/39/58/71 crtmod_param_2 %10101, 0, 82, 6, 10, 64, 2, 625, 2, 66, 512, 45, 27 ; 11 LCD 0/4/8/12/48/61 crtmod_param_2 %10101, 0, 82, 6, 10, 64, 2, 625, 2, 82, 480, 61, 27 ; 12 LCD 1/5/9/13/49/62 crtmod_param_2 %10000, 0, 42, 3, 5, 32, 2, 625, 2, 66, 512, 45, 27 ; 13 LCD 2/6/10/14/50/63 crtmod_param_2 %10000, 0, 42, 3, 5, 32, 2, 625, 2, 82, 480, 61, 27 ; 14 LCD 3/7/11/15/51/64 crtmod_param_2 %10110, 0, 124, 9, 15, 96, 4, 625, 2, 66, 512, 45, 27 ; 15 LCD 16/20/24/52/65 crtmod_param_2 %10110, 0, 124, 9, 15, 96, 4, 625, 2, 22, 600, 1, 27 ; 16 LCD 17/21/25/53/66 crtmod_param_2 %11010, 0, 124, 9, 15, 96, 4, 625, 2, 66, 512, 45, 27 ; 17 LCD 18/22/26/54/67 crtmod_param_2 %10111, 0, 100, 12, 6, 80, 2, 525, 2, 33, 480, 10, 27 ; 18 LCD 19/23/27/55/68 crtmod_param_2 %10001, 1, 68, 7, 9, 48, 4, 625, 2, 66, 512, 45, 27 ; 19 LCD 28/29/30/31/56/69 crtmod_param_2 %10110, 0, 124, 9, 31, 64, 20, 625, 2, 66, 512, 45, 27 ; 20 LCD 32/33/34/35/57/70 crtmod_param_2 %10001, 1, 68, 7, 17, 32, 12, 625, 2, 66, 512, 45, 27 ; 21 LCD 36/37/38/39/58/71 crtmod_param_2 %10001, 0, 92, 10, 12, 64, 6, 568, 6, 35, 512, 15, 27 ; 22 CRT 40/41/42/43/44/45/46/47/59/60/72/73 crtmod_param_2 %10001, 0, 82, 6, 10, 64, 2, 625, 2, 66, 512, 45, 27 ; 23 LCD 40/41/42/43/44/45/46/47/59/60/72/73 ;R20L<<1|HRL→ドットクロックのランク ; rank R20L HRL osc div dotclk mode ; 7 1**10 * 69.552 2 34.776 768x512(高) ; 6 1**11 * 50.350 2 25.175 640x480 ; 5 1**01 0 69.552 3 23.184 512x512(高) ; 4 1**01 1 69.552 4 17.388 384x256 ; 3 1**00 0 69.552 6 11.592 256x256(高) ; 2 0**01 * 38.864 4 9.716 512x512(低) ; 1 1**00 1 69.552 8 8.694 ; 0 0**00 * 38.864 8 4.858 256x256(低) ; 0 0**1* * 38.864 8 4.858 dot_clock_rank: .rept 4 .dc.b 0 ;0**00 0 .dc.b 0 ;0**00 1 .dc.b 2 ;0**01 0 .dc.b 2 ;0**01 1 .dc.b 0 ;0**10 0 .dc.b 0 ;0**10 1 .dc.b 0 ;0**11 0 .dc.b 0 ;0**11 1 .endm .rept 4 .dc.b 3 ;1**00 0 .dc.b 1 ;1**00 1 .dc.b 5 ;1**01 0 .dc.b 4 ;1**01 1 .dc.b 7 ;1**10 0 .dc.b 7 ;1**10 1 .dc.b 6 ;1**11 0 .dc.b 6 ;1**11 1 .endm .endif ;REMOVE_CRTMOD_G_CLR_ON ;---------------------------------------------------------------- ; 6x12 ANKフォント ; X68000のCGROMとIPLROM 1.3を組み合わせると6x12 ANKフォントを表示できない ; IPLROM 1.6は6x12 ANKフォントを$00FEF400~$00FEFFFF(3072バイト)に置く ; 変更前 ; 000073F6 203C00FBF400 move.l #$00FBF400,d0 ;---------------------------------------------------------------- PATCH_DATA p73F6,$00FF73F6,$00FF73F6+5,$203C00FB move.l #$00FEF400,d0 ;---------------------------------------------------------------- ; IOCS _SET232C ; ボーレート8=19200bpsを使えるようにする ; IPLROM 1.3のIOCS _SET232Cはボーレート8=19200bpsを選択できるが、SCC WR13:WR12の値が間違っており、 ; スタートビットで同期してもストップビットまでにおよそ1ビットずれてしまうので使えなかった ; (5000000/2/16)/19200-2=6.138 ; (5000000/2/16)/(7+2)=17361.111=19200*0.904 誤 ; (5000000/2/16)/(6+2)=19531.250=19200*1.017 正 ; ボーレート9=38400bpsと10=76800bpsを選択できるようにする ; 使えるとは限らない ; RTS/CTSに対応していないので実用性は不明 ; SCCの動作周波数が7.5MHzのとき9=57600bpsと10=115200bpsになる ; RTS/CTSの選択を確実に無視する ; RTS/CTSには対応していないが選択されているだけでボーレート4=1200bpsになってしまう問題があった ; ; 変更前 変更後 ; 00FF7A1A 4240 clr.w d0 = ; 00FF7A1C 1001 move.b d1,d0 = ; A 00FF7A1E B03C cmp.b #$09,d0 movea.l d1,a0 ; 00FF7A20 0009 and.b #$7F,d1 ; 00FF7A22 6504 bcs $00FF7A28 ; 00FF7A24 303C move.w #$0004,d0 cmp.b #11,d1 ; 00FF7A26 0004 ; 00FF7A28 D040 add.w d0,d0 blo $00FF7A2C ; 00FF7A2A 41FA lea.l $00FF7AE2(pc),a0 moveq.l #4,d1 ; 00FF7A2C 00B6 bsr.w $00FF7AE2 ; 00FF7A2E 3030 move.w $00(a0,d0.w),d0 ; 00FF7A30 0000 move.l a0,d1 ; 00FF7A32 ; B 00FF7AE2 0821 .dc.w $0821 move.w #2083,d0 ; 00FF7AE4 0410 .dc.w $0410 ; 00FF7AE6 0207 .dc.w $0207 lsr.w d1,d0 ; 00FF7AE8 0102 .dc.w $0102 moveq.l #-2,d1 ; 00FF7AEA 0080 .dc.w $0080 addx.w d1,d0 ; 00FF7AEC 003F .dc.w $003F rts ; 00FF7AEE 001F .dc.w $001F = ; 00FF7AF0 000E .dc.w $000E = ; 00FF7AF2 0007 .dc.w $0007 ;6が正しい = ; 00FF7AF4 ;---------------------------------------------------------------- PATCH_DATA p7a1e,$00FF7A1E,$00FF7A31,$B03C0009 ;A ;<d1.b:ボーレートの番号 ; 0=75bps,1=150bps,2=300bps,3=600bps,4=1200bps,5=2400bps,6=4800bps,7=9600bps,8=19200bps,9=38400bps,10=76800bps movea.l d1,a0 ;d1を保存する and.b #$7F,d1 ;RTS/CTSの選択を確実に無視する if <cmp.b #11,d1>,hs ;ボーレートの番号が0~10の範囲外のとき moveq.l #4,d1 ;ボーレート4=1200bpsにする endif bsr.w ($00FF7AE2)PATCH_ZL ;Bを呼び出す move.l a0,d1 ;d1を復元する ;<d0.w:SCC WR13:WR12の値 PATCH_DATA p7ae2,$00FF7AE2,$00FF7AED,$08210410 ;B move.w #2083,d0 ;(5000000Hz/2/16)/75bps=2083.333を lsr.w d1,d0 ;ボーレートの番号の分だけ右にシフトして moveq.l #-2,d1 ;2を引いて addx.w d1,d0 ;四捨五入する rts ;0→2081,1→1040,2→519,3→258,4→128,5→63,6→31,7→14,8→6,9→2,10→0 ;---------------------------------------------------------------- ; DMA転送開始直前のキャッシュフラッシュ ; 変更前 ; 00FF8284 2F00 move.l d0,-(sp) ; 00FF8286 0C3800010CBC cmpi.b #$01,BIOS_MPU_TYPE.w ; 00FF828C 6314 bls.s $00FF82A2 ; 00FF828E 4E7A0002 movec.l cacr,d0 ; 00FF8292 807C0808 or.w #$0808,d0 ; 00FF8296 4E7B0002 movec.l d0,cacr ; 00FF829A C07CF7F7 and.w #$F7F7,d0 ; 00FF829E 4E7B0002 movec.l d0,cacr ; 00FF82A2 201F move.l (sp)+,d0 ; 00FF82A4 4E75 rts ; 00FF82A6 ;---------------------------------------------------------------- PATCH_DATA dma_cache_flush,$00FF8284,$00FF82A5,$2F000C38 jmp cache_flush ;---------------------------------------------------------------- ; 割り込み関係のIOCSコールのハイメモリ対策 ; 割り込み関係のIOCSコールは割り込みが未使用かどうかをベクタが$01000000以上かどうかで判断している ; ベクタがハイメモリを指していると未使用と誤認する ; ベクタの上位8bitがベクタ番号と一致しているかどうかに変更する ; 以下のIOCSコールが該当する ; $43 iocs_6A_OPMINTST ; $44 iocs_6B_TIMERDST ; $4D iocs_6C_VDISPST ; $4E iocs_6D_CRTCRAS ; $4F iocs_6E_HSYNCST ; $63 iocs_6F_PRNINTST ; 変更前 ; 00FF85D4 007C0700 ori.w #$0700,sr ;割り込み禁止 ; 00FF85D8 E548 lsl.w #2,d0 ;ベクタオフセット ; 00FF85DA 3040 movea.w d0,a0 ;a0.l:ベクタオフセット ; 00FF85DC 2009 move.l a1,d0 ;変更後のベクタ ; 00FF85DE 670C_000085EC beq.s $00FF85EC ;解除 ; 00FF85E0 2010 move.l (a0),d0 ;d0.l:変更前のベクタ ; >>>>> 00FF85E2 0C8001000000 cmpi.l #$01000000,d0 ;変更前のベクタにベクタ番号が付いているか ; 00FF85E8 6504_000085EE bcs.s $00FF85EE ;変更前のベクタにベクタ番号が付いていないので使用中 ; 00FF85EA ;変更前のベクタにベクタ番号が付いているので未使用 ; 00FF85EA 2089 move.l a1,(a0) ;ベクタを変更する ; 00FF85EC 4E75 rts ;個々のIOCSコールへ戻る ; 00FF85EE ;変更前のベクタにベクタ番号が付いていないので使用中 ; 00FF85EE 4A9F tst.l (sp)+ ;個々のIOCSコールへ戻らない ; 00FF85F0 ;使用中のときTRAP#15のrteまで割り込み禁止のままになる ; 00FF85F0 4E75 rts ;IOCSコールから復帰する ; 00FF85F2 ; ;---------------------------------------------------------------- PATCH_DATA p85E2,$00FF85E2,$00FF85E7,$0C800100 jsr p85E2 PATCH_TEXT ;<d0.l:変更前のベクタ ;<a0.l:ベクタオフセット ;>c:cc=未使用,cs=使用中 p85E2: push d0-d1 move.w a0,d1 ;d1.w:ベクタオフセット lsr.w #2,d1 ;d1.b:ベクタ番号 rol.l #8,d0 ;d0.b:変更前のベクタの上位8bit cmp.b d1,d0 ;eq=未使用,ne=使用中 sne.b d0 ;d1.b:$00=未使用,$FF=使用中 add.b d0,d0 ;cc=未使用,cs=使用中 pop rts ;---------------------------------------------------------------- ; 不具合 ; _MS_LIMITでY方向の範囲を1007までしか設定できない ; https://stdkmd.net/bugsx68k/#rom_mslimit ; 変更前 ; 00FFABA4 B27C03F0 cmp.w #$03F0,d1 ; 00FFABA8 ;---------------------------------------------------------------- PATCH_DATA mslimit_1st,$00FFABA4,$00FFABA7,$B27C03F0 cmp.w #$0400,d1 ;---------------------------------------------------------------- ; 変更前 ; 00FFABB4 B47C03F0 cmp.w #$03F0,d2 ; 00FFABB8 ;---------------------------------------------------------------- PATCH_DATA mslimit_2nd,$00FFABB4,$00FFABB7,$B47C03F0 cmp.w #$0400,d2 ;---------------------------------------------------------------- ; _MS_ONTMのキャッシュ制御 ; 変更前 ; 00FFAC72 0C3800010CBC cmpi.b #$01,BIOS_MPU_TYPE.w ; 00FFAC78 630C bls.s $00FFAC86 ; 00FFAC7A 4E7A0002 movec.l cacr,d0 ; 00FFAC7E 2F00 move.l d0,-(sp) ; 00FFAC80 7001 moveq.l #$01,d0 ;EI=1,ED=0 ; 00FFAC82 4E7B0002 movec.l d0,cacr ; 00FFAC86 ;---------------------------------------------------------------- PATCH_DATA ms_ontm_cache_1st,$00FFAC72,$00FFAC85,$0C380001 jsr cache_on_i ;データキャッシュOFF,命令キャッシュON move.l d0,-(sp) bra ($00FFAC86)PATCH_ZL ;---------------------------------------------------------------- ; 変更前 ; 00FFACE8 0C3800010CBC cmpi.b #$01,BIOS_MPU_TYPE.w ; 00FFACEE 6306 bls.s $00FFACF6 ; 00FFACF0 201F move.l (sp)+,d0 ; 00FFACF2 4E7B0002 movec.l d0,cacr ; 00FFACF6 ;---------------------------------------------------------------- PATCH_DATA ms_ontm_cache_2nd,$00FFACE8,$00FFACF5,$0C380001 move.l (sp)+,d2 jsr cache_set ;キャッシュ設定 bra ($00FFACF6)PATCH_ZL .if REMOVE_CRTMOD_G_CLR_ON=0 ;---------------------------------------------------------------- ; _G_CLR_ON ; 変更前 ; 0000B326*48E76040 movem.l ~pushrl,-(sp) ; : ; 0000B660*FFFE .dc.w (31<<11)|(31<<6)|(31<<1) ;---------------------------------------------------------------- PATCH_DATA g_clr_on,$00FFB326,$00FFB661,$48E76040 ;---------------------------------------------------------------- ;IOCSコール$90 _G_CLR_ON グラフィック画面の消去とパレット初期化と表示ON ;>d0.l:0 ;---------------------------------------------------------------- iocs_90_G_CLR_ON: dMM reg d3 ;メモリモード dGVRAM reg d5 ;$00C00000 aE8 reg a2 ;(~)E8のベースアドレス aED reg a4 ;(~)EDのベースアドレス aP1 reg a5 ;パラメータ1のアドレス push d0-d2/dMM/dGVRAM/a0/aE8/aED/aP1 move.l #$00C00000,dGVRAM ;(~)E8でアクセスする ; $00E80000 CRTC ; $00E82000 VICON ; $00E84000 DMAC ; $00E86000 SUPERAREA ; $00E88000 MFP ; $00E8A000 RTC ; $00E8C000 PRNPORT ; $00E8E000 SYSPORT lea.l $00E88000,aE8 E8 reg -$00E88000(aE8) ;(~)EDでアクセスする ; $00ED0000 SRAM lea.l $00ED8000,aED ED reg -$00ED8000(aED) ;現在の画面モードを確認する moveq.l #0,d1 move.b BIOS_CRTMOD.w,d1 ;現在の画面モード if <cmp.w #crtmod_modes,d1>,hs ;現在の画面モードが範囲外のとき move.b (SRAM_CRTMOD)ED,d1 ;起動時の画面モードを使う if <cmp.w #crtmod_modes,d1>,hs ;起動時の画面モードも範囲外のとき moveq.l #16,d1 ;16を使う .if 0 move.b #$31,(SYSPORT_SRAM)E8 ;unlocksram move.b d1,(SRAM_CRTMOD)ED clr.b (SYSPORT_SRAM)E8 ;locksram .endif endif endif ;<d1.l:画面モード ;パラメータ1のアドレスを求める lea.l crtmod_table_1_crt,aP1 if <btst.b #SRAM_XEIJ_LCD_BIT,(SRAM_XEIJ)ED>,ne ;LCD向け lea.l crtmod_table_1_lcd,aP1 endif move.w d1,d0 .if crtmod_param_1_size=8 lsl.w #3,d0 .else mulu.w #crtmod_param_1_size,d0 .endif adda.w d0,aP1 ;<aP1.l:パラメータ1のアドレス ;メモリモードを確認する moveq.l #7,dMM and.b crtmod_param_1_r20h(aP1),dMM ;メモリモード。0~7 ;<dMM.w:メモリモード。0~7 ;テキスト画面のみON move.w #VICON_TXON_MASK,(VICON_VISIBLE)E8 ;メモリモードを設定する move.b dMM,(CRTC_MODE_BYTE)E8 move.w dMM,(VICON_MEMORY_MODE)E8 ;グラフィックVRAMをクリアする bset.b #CRTC_GRAPHIC_STORAGE_BIT,(CRTC_MODE_BYTE)E8 ;グラフィックストレージON movea.l dGVRAM,a0 moveq.l #0,d0 moveq.l #1-1,d2 ; 76543210 if <btst.b dMM,#%10100000>,ne ;5,7 ;メモリモードだけでクリアする範囲を決めている ;拡張グラフィック画面がないとき拡張グラフィック画面が必要な画面モードはCRTMODが弾くのでここを通ることはないはず moveq.l #4-1,d2 endif for d2 moveq.l #-1,d1 ;2*512*512/8=65536 for d1 move.l d0,(a0)+ move.l d0,(a0)+ next next bclr.b #CRTC_GRAPHIC_STORAGE_BIT,(CRTC_MODE_BYTE)E8 ;グラフィックストレージOFF ;BIOSワークエリアを初期化する lea.l BIOS_GRAPHIC_PAGE.w,a0 ;BIOS_GRAPHIC_Y_OFFSET,BIOS_GRAPHIC_PALETS move.l dGVRAM,(a0)+ ;描画ページ先頭アドレス move.l #2*512,d0 if <cmp.w #4,dMM>,hs ;4~7 add.w d0,d0 ;2*1024 endif move.l d0,(a0)+ ;Y方向オフセット moveq.l #16-1,d0 ; 76543210 if <btst.b dMM,#%00100010>,ne ;1,5 st.b d0 ;256-1 ; 76543210 elif <btst.b dMM,#%10001100>,ne ;2,3,7 moveq.l #-1,d0 ;65536-1 endif move.w d0,(a0) ;色数-1 ;グラフィックパレットを初期化する move.w dMM,d0 bsr initialize_gpalet ;テキスト画面ON、グラフィック画面ON ; if <cmp.w #4,dMM>,lo ;メモリモード0~3。512x512ドット ; move.w #VICON_TXON_MASK|VICON_G4ON_MASK|VICON_G3ON_MASK|VICON_G2ON_MASK|VICON_G1ON_MASK,(VICON_VISIBLE)E8 ; else ;メモリモード4~7。1024x1024ドット ; move.w #VICON_TXON_MASK|VICON_GXON_MASK,(VICON_VISIBLE)E8 ; endif ; IPLROM 1.0~1.3は1024x1024ドットと512x512ドットを両方ONにしている move.w #VICON_TXON_MASK|VICON_GXON_MASK|VICON_G4ON_MASK|VICON_G3ON_MASK|VICON_G2ON_MASK|VICON_G1ON_MASK,(VICON_VISIBLE)E8 moveq.l #0,d0 pop rts ;---------------------------------------------------------------- ;グラフィックパレットを初期化する ;<d0.w:メモリモード。0~7 initialize_gpalet: push d0-d4/a0-a1 lea.l VICON_GPALET,a0 ifor <tst.w d0>,eq,<cmp.w #4,d0>,eq,<cmp.w #6,d0>,eq ;メモリモード0,4,6。16色 lea.l gpalet_16_array(pc),a1 moveq.l #16/2-1,d0 for d0 move.l (a1)+,(a0)+ next elifor <cmp.w #1,d0>,eq,<cmp.w #5,d0>,eq ;メモリモード1,5。256色 ;greenは増分10.5で4階調(10.5*3=31.5)、redとblueは増分4.5で8階調(4.5*7=31.5)、端数は切り捨て move.l #((9<<1)<<16)|(9<<1),d1 ;blueの増分4.5+4.5 moveq.l #0,d3 ;green=0 do moveq.l #(4<<1),d2 ;red=0,blue=(0,4.5) moveq.l #8-1,d4 for d4 move.l d3,d0 ;green and.l #.not.(((1<<10)<<16)|(1<<10)),d0 ;greenの端数を切り捨てる add.l d2,d0 ;red,blue=(0,4.5) and.l #.not.(((1<<5)<<16)|(1<<5)),d0 ;redの端数を切り捨てる move.l d0,(a0)+ add.l d1,d0 ;blue+=4.5+4.5 move.l d0,(a0)+ add.l d1,d0 ;blue+=4.5+4.5 move.l d0,(a0)+ add.l d1,d0 ;blue+=4.5+4.5 move.l d0,(a0)+ add.l #((9<<5)<<16)|(9<<5),d2 ;red+=4.5 next add.l #((21<<10)<<16)|(21<<10),d3 ;green+=10.5 while cc else ;メモリモード2,3,7。65536色 move.l #$00_01_00_01,d0 ;(L00,L01,H00,H01),(L02,L03,H02,H03),…,(LFE,LFF,HFE,HFF) move.l #$02_02_02_02,d2 moveq.l #256/2-1,d1 for d1 move.l d0,(a0)+ add.l d2,d0 next endif pop rts ;グラフィック16色パレット gpalet_16_array: dcrgb 0,0,0 dcrgb 10,10,10 dcrgb 0,0,16 dcrgb 0,0,31 dcrgb 16,0,0 dcrgb 31,0,0 dcrgb 16,0,16 dcrgb 31,0,31 dcrgb 0,16,0 dcrgb 0,31,0 dcrgb 0,16,16 dcrgb 0,31,31 dcrgb 16,16,0 dcrgb 31,31,0 dcrgb 21,21,21 dcrgb 31,31,31 PATCH_TEXT ;---------------------------------------------------------------- ;50us単位のウェイト ;<d0.l:時間(50us単位) .text .even wait_50us: .if 0 ;Timer-Cを使う ; Timer-Cが1/200プリスケール(50us)で動作していなければならない aTCDR reg a0 push d0-d2/aTCDR lea.l MFP_TCDR,aTCDR moveq.l #0,d1 move.b (aTCDR),d1 move.b (aTCDR),d1 do moveq.l #0,d2 move.b (aTCDR),d2 redo <cmp.b (aTCDR),d2>,cs sub.w d2,d1 if cs add.w #200,d1 endif exg.l d1,d2 sub.l d2,d0 while hi pop rts .else ;dbra空ループを使う ; BIOS_MPU_SPEED_ROM.wとBIOS_MPU_TYPE.wが設定されていなければならない push d0-d3 subq.l #1,d0 if cc move.l BIOS_MPU_SPEED_ROM_LONG.w,d1 if eq move.w BIOS_MPU_SPEED_ROM.w,d1 endif ; 上限を20bitとして50usあたりのdbraの回数を求める if <cmpi.b #4,BIOS_MPU_TYPE.w>,lo ;000/010/020/030 move.w #205,d2 ;2**12*50/1000=204.8 elif eq ;040 move.w #307,d2 ;2**12*50/1000*6/4=307.2 else ;060 move.w #1229,d2 ;2**12*50/1000*6/1=1228.8 endif move.l d1,d3 ;d3=H|L swap.w d3 ;d3=L|H mulu.w d2,d3 ;d3=c*H mulu.w d2,d1 ;d1=c*L swap.w d3 clr.w d3 ;d3=c*H|0 add.l d3,d1 ;d1=c*(H|L) and.w #$F000,d1 ;43210___ rol.l #4,d1 ;3210___4 swap.w d1 ;___43210 50usあたりのdbraの回数 subq.l #1,d1 move.l d1,d2 forlong d0 move.l d2,d1 .align 16,$2048 forlong d1 next next endif pop rts .endif .endif ;REMOVE_CRTMOD_G_CLR_ON ;---------------------------------------------------------------- ; 不具合 ; _GPALETで65536色モードのパレットを正しく取得できない ; https://stdkmd.net/bugsx68k/#rom_gpalet ; 変更前 ; 00FFB740 16300000 move.b $00(a0,d0.w),d3 ; 00FFB744 ;---------------------------------------------------------------- PATCH_DATA gpalet,$00FFB740,$00FFB743,$16300000 move.b 2(a0,d0.w),d3 ;---------------------------------------------------------------- ; 不具合 ; _SYS_STATのコードが間違っている ; https://stdkmd.net/bugsx68k/#rom_sysstat ; 変更前 ; 00FFC75A 48E76000 movem.l d1-d2,-(sp) ; : ; 00FFC818 ;---------------------------------------------------------------- PATCH_DATA sysstat,$00FFC75A,$00FFC817,$48E76000 jmp iocs_AC_SYS_STAT ;余った領域をtrap#14で使う trap14_message: 200: .dc.w 204f-200b .dc.w 205f-200b .dc.w 206f-200b .dc.w 207f-200b .dc.w 208f-200b .dc.w 209f-200b .dc.w 210f-200b .dc.w 211f-200b 204: .dc.b 'Illegal instruction',0 205: .dc.b 'Zero divide',0 206: .dc.b 'CHK instruction',0 207: .dc.b 'TRAPV instruction',0 208: .dc.b 'Privilege violation',0 209: .dc.b 'Trace',0 210: .dc.b 'Line 1010 emulator',0 211: .dc.b 'Line 1111 emulator',0 .even PATCH_TEXT ;---------------------------------------------------------------- ;IOCSコール$AC _SYS_STAT システム環境の取得と設定 ;<d1.w:モード ; 0 MPUステータス取得 ; >d0.l:MPUステータス ; bit31-16 MPUの動作周波数。MHz値*10 ; bit15 FPU/FPCPの有無。0=なし,1=あり ; bit14 MMUの有無。0=なし,1=あり ; bit7-0 MPUの種類。0=68000,1=68010,2=68020,3=68030,4=68040,6=68060 ; 1 キャッシュ取得 ; >d0.l:現在のキャッシュの状態 ; bit1 データキャッシュは0=OFF,1=ON ; bit0 命令キャッシュは0=OFF,1=ON ; 2 キャッシュ設定(SRAM設定値) ; >d0.l:設定後のキャッシュの状態 ; bit1 データキャッシュを0=OFF,1=ONにした ; bit0 命令キャッシュを0=OFF,1=ONにした ; 3 キャッシュフラッシュ ; 4 キャッシュ設定 ; <d2.l:設定後のキャッシュの状態 ; bit1 データキャッシュを0=OFF,1=ONにする ; bit0 命令キャッシュを0=OFF,1=ONにする ; >d0.l:設定前のキャッシュの状態 ; bit1 データキャッシュは0=OFF,1=ONだった ; bit0 命令キャッシュは0=OFF,1=ONだった iocs_AC_SYS_STAT: moveq.l #-1,d0 ifor <cmpi.b #2,BIOS_MPU_TYPE.w>,hs,<tst.w d1>,eq ;000/010はモード0以外はエラー if <cmp.w #5,d1>,lo ;モード5以上はエラー push d1 add.w d1,d1 move.w 100f(pc,d1.w),d1 jsr 100f(pc,d1.w) pop endif endif rts 100: .dc.w mpu_status-100b ;0 MPUステータス取得 .dc.w cache_get-100b ;1 キャッシュ取得 .dc.w cache_default-100b ;2 キャッシュ設定(SRAM設定値) .dc.w cache_flush-100b ;3 キャッシュフラッシュ .dc.w cache_set-100b ;4 キャッシュ設定 ;---------------------------------------------------------------- ;MPUステータス取得 ;>d0.l:MPUステータス ; bit31-16 MPUの動作周波数。MHz値*10 ; bit15 FPU/FPCPの有無。0=なし,1=あり ; bit14 MMUの有無。0=なし,1=あり ; bit7-0 MPUの種類。0=68000,1=68010,2=68020,3=68030,4=68040,6=68060 mpu_status: move.l BIOS_MPU_SPEED_ROM_LONG.w,d0 ; if eq ;IPLROM 1.6以外で使うとき必要 ; move.w BIOS_MPU_SPEED_ROM.w,d0 ; endif move.l d0,-(sp) ;x1 add.l d0,d0 ;x2 add.l (sp)+,d0 ;x3 add.l d0,d0 ;x6 if <cmpi.b #2,BIOS_MPU_TYPE.w>,lo ;68000/68010 add.l d0,d0 ;x12 endif add.l #50,d0 divu.w #100,d0 ;MHz値*10 ; if vs ;6553.6MHz以上 ; moveq.l #-1,d0 ; endif swap.w d0 ;ssssssss ssssssss ........ ........ clr.w d0 ;ssssssss ssssssss 00000000 00000000 tst.b BIOS_MMU_TYPE.w sne.b d0 ;ssssssss ssssssss 00000000 mmmmmmmm ror.w #1,d0 ;ssssssss ssssssss m0000000 0mmmmmmm tst.b BIOS_FPU_TYPE.w sne.b d0 ;ssssssss ssssssss m0000000 ffffffff ror.w #1,d0 ;ssssssss ssssssss fm000000 0fffffff move.b BIOS_MPU_TYPE.w,d0 ;ssssssss ssssssss fm000000 pppppppp rts ;---------------------------------------------------------------- ;キャッシュ取得 ;>d0.l:現在のキャッシュの状態 ; bit1 データキャッシュは0=OFF,1=ON ; bit0 命令キャッシュは0=OFF,1=ON ; 000/010のときは0を返す cache_get: moveq.l #0,d0 if <cmpi.b #2,BIOS_MPU_TYPE.w>,hs ;020/030/040/060 .cpu 68030 movec.l cacr,d0 if <cmpi.b #4,BIOS_MPU_TYPE.w>,lo ;020/030 ;........ ........ .......d .......i ror.l #1,d0 ;i....... ........ ........ d....... rol.b #1,d0 ;i....... ........ ........ .......d else ;040/060 ;d....... ........ i....... ........ swap.w d0 ;i....... ........ d....... ........ rol.w #1,d0 ;i....... ........ ........ .......d endif rol.l #1,d0 ;........ ........ ........ ......di and.l #3,d0 ;00000000 00000000 00000000 000000di .cpu 68000 endif rts ;---------------------------------------------------------------- ;キャッシュ設定(SRAM設定値) ;>d0.l:設定後のキャッシュの状態 ; bit1 データキャッシュを0=OFF,1=ONにした ; bit0 命令キャッシュを0=OFF,1=ONにした ; 000/010のときは0を返す cache_default: push d2 moveq.l #0,d2 move.b SRAM_CACHE,d2 ;キャッシュ設定。------|データ|命令 bsr cache_set ;キャッシュ設定 pop rts ;---------------------------------------------------------------- ;キャッシュフラッシュ cache_flush: if <cmpi.b #2,BIOS_MPU_TYPE.w>,hs ;020/030/040/060 .cpu 68030 if <cmpi.b #4,BIOS_MPU_TYPE.w>,lo ;020/030 push d0 movec.l cacr,d0 or.w #$0808,d0 movec.l d0,cacr ; and.w #$F7F7,d0 ; movec.l d0,cacr pop else ;040/060 .cpu 68040 cpusha bc endif .cpu 68000 endif rts ;---------------------------------------------------------------- ;キャッシュ設定 ;<d2.l:設定後のキャッシュの状態 ; bit1 データキャッシュを0=OFF,1=ONにする ; bit0 命令キャッシュを0=OFF,1=ONにする ; 000/010のときは何もしない ;>d0.l:設定前のキャッシュの状態 ; bit1 データキャッシュは0=OFF,1=ONだった ; bit0 命令キャッシュは0=OFF,1=ONだった ; 000/010のときは0を返す cache_set: moveq.l #0,d0 if <cmpi.b #2,BIOS_MPU_TYPE.w>,hs ;020/030/040/060 .cpu 68030 push d1-d3 moveq.l #3,d3 ;d3 00000000 00000000 00000000 00000011 and.l d3,d2 ;d2 00000000 00000000 00000000 000000di ror.l #1,d2 ; i0000000 00000000 00000000 0000000d movec.l cacr,d0 if <cmpi.b #4,BIOS_MPU_TYPE.w>,lo ;020/030 ;d0 ........ ........ .......d .......i neg.w d2 ;d2 i0000000 00000000 dddddddd dddddddd and.w #$2101.shr.1,d2 ; i0000000 00000000 000d0000 d0000000 rol.l #1,d2 ; 00000000 00000000 00d0000d 0000000i move.l d0,d1 ;d1 ........ ........ .......d .......i and.w #.notw.$2101,d1 ; ........ ........ ..0....0 .......0 or.w d2,d1 ; ........ ........ ..d....d .......i movec.l d1,cacr ror.l #1,d0 ;d0 i....... ........ ........ d....... rol.b #1,d0 ; i....... ........ ........ .......d else ;040/060 ;d0 d....... ........ i....... ........ .cpu 68040 ror.w #1,d2 ;d2 i0000000 00000000 d0000000 00000000 swap.w d2 ; d0000000 00000000 i0000000 00000000 move.l d0,d1 ;d1 d....... ........ i....... ........ and.l #.not.$80008000,d1 ; 0....... ........ 0....... ........ or.l d2,d1 ; d....... ........ i....... ........ movec.l d1,cacr not.l d2 and.l d0,d2 ;設定前&~設定後 if mi ;データキャッシュがON→OFF cpusha dc ;データキャッシュをプッシュして無効化 endif if <tst.w d2>,mi ;命令キャッシュがON→OFF cinva ic ;命令キャッシュと分岐キャッシュを無効化 endif swap.w d0 ;d0 i....... ........ d....... ........ rol.w #1,d0 ; i....... ........ ........ .......d endif rol.l #1,d0 ; ........ ........ ........ ......di and.l d3,d0 ; 00000000 00000000 00000000 000000di pop .cpu 68000 endif rts ;---------------------------------------------------------------- ;キャッシュOFF ;>d0.l:設定前のキャッシュの状態 ; bit1 データキャッシュは0=OFF,1=ONだった ; bit0 命令キャッシュは0=OFF,1=ONだった ; 000/010のときは0を返す cache_off: push d2 moveq.l #0,d2 bsr cache_set ;キャッシュ設定 pop rts ;---------------------------------------------------------------- ;データキャッシュOFF,命令キャッシュON ;>d0.l:設定前のキャッシュの状態 ; bit1 データキャッシュは0=OFF,1=ONだった ; bit0 命令キャッシュは0=OFF,1=ONだった ; 000/010のときは0を返す cache_on_i: push d2 moveq.l #1,d2 ;データキャッシュOFF,命令キャッシュON bsr cache_set ;キャッシュ設定 pop rts ;---------------------------------------------------------------- ; ; _SP_INIT でバスエラーが発生する (IPLROM 1.0/1.1/1.2/1.3) ; https://stdkmd.net/bugsx68k/#rom_spinit ; ; 症状 ; スプライトを表示できないとき _SP_INIT が -1 を返さずバスエラーで止まることがある。 ; ; 発生条件 ; 画面モード 18 (1024x848) または画面モード 19 (640x480; VGA モード) で _SP_INIT を呼び出したとき。 ; ; 原因 ; ハードウェアの制約で、CRTC の R20 ($00E80028) の下位 5 ビットが %1??1? のとき、スプライトを表示できない。 ; スプライトを表示できないとき、スプライトスクロールレジスタ ($00EB0000~$00EB07FF) または ; スプライト PCG・テキストエリア ($00EB8000~$00EBFFFF) にアクセスすると、バスエラーが発生する。 ; スプライト関連の IOCS コールは、画面モード 16 (768x512) と画面モード 17 (1024x424) の %10110 のときだけ、スプライトを表示できないと判断する。 ; 画面モード 18 の %11010 と画面モード 19 の %10111 を含む %1001? と %10111 と %11?1? はスプライトを表示できると誤って判断され、 ; _SP_INIT がアクセスできないスプライトスクロールレジスタを初期化しようとしてバスエラーが発生する。 ; ; 補足 ; 画面モード 17 (1024x424) と画面モード 18 (1024x848) は IPLROM 1.0 からあるが未公開。 ; 画面モード 19 (640x480; VGA モード) は X68000 Compact の IPLROM 1.2 で追加された。 ; ; メモ ; このバスエラーはエミュレータでは再現されないことがある。 ; ;---------------------------------------------------------------- ;---------------------------------------------------------------- ; 変更前 ; 00FFCC9E 303900E80028 move.w $00E80028,d0 ;[$00E80028].w:CRTC R20 メモリモード/解像度(高解像度|垂直解像度|水平解像度) ; 00FFCCA4 024000FF andi.w #$00FF,d0 ; 00FFCCA8 0C400016 cmpi.w #$0016,d0 ; 00FFCCAC 6606 bne.s $00FFCCB4 ; 00FFCCAE 70FF moveq.l #$FF,d0 ; 00FFCCB0 588F addq.l #4,sp ; 00FFCCB2 4E75 rts ; ; 00FFCCB4 7000 moveq.l #$00,d0 ; 00FFCCB6 4E75 rts ; ; 00FFCCB8 ;---------------------------------------------------------------- PATCH_DATA spinit,$00FFCC9E,$00FFCCB7,$303900E8 ;スプライトを表示できるか ; スプライト関連のIOCSコールの先頭で呼び出される ; 表示できないときは-1を返してIOCSコールから復帰する ;>d0.l:0=スプライトを表示できる,-1=スプライトを表示できない moveq.l #%10010,d0 and.w $00E80028,d0 ;CRTC R20 if <cmp.w #%10010,d0>,eq ;%1??1?。スプライトを表示できない moveq.l #-1,d0 ;スプライトを表示できない addq.l #4,sp ;IOCSコールから復帰する else ;その他。スプライトを表示できる moveq.l #0,d0 ;スプライトを表示できる endif rts ;---------------------------------------------------------------- ; ; グラフィック関係のIOCSコールがリバースモードになったままになる ; https://stdkmd.net/bugsx68k/#rom_drawmode ; ;---------------------------------------------------------------- ;---------------------------------------------------------------- ; 変更前 ; 00FFDCEA B07CFFFF cmp.w #$FFFF,d0 ; 00FFDCEE ;---------------------------------------------------------------- PATCH_DATA drawmode,$00FFDCEA,$00FFDCED,$B07CFFFF cmp.w #-1,d1 ;---------------------------------------------------------------- ; ; プロポーショナルピッチコンソール ; 改良というより魔改造 ; 動作は遅く、編集は困難になる ; ;---------------------------------------------------------------- .if USE_PROPORTIONAL_IOCS PATCH_DATA timer_c_cursor,$00FF1D8C,$00FF1D91,$4A380992 jmp timer_c_cursor PATCH_DATA iocs_1E_B_CURON,$00FF79CE,$00FF79D3,$4A380993 jmp iocs_1E_B_CURON PATCH_DATA iocs_1F_B_CUROFF,$00FF79EA,$00FF79EF,$4A380993 jmp iocs_1F_B_CUROFF PATCH_DATA iocs_20_B_PUTC,$00FF96AE,$00FF96B3,$2F016100 jmp iocs_20_B_PUTC PATCH_DATA iocs_21_B_PRINT,$00FF96BC,$00FF96C3,$48E74020 jmp iocs_21_B_PRINT PATCH_DATA iocs_22_B_COLOR,$00FF96D8,$00FF96DD,$700041F8 jmp iocs_22_B_COLOR PATCH_DATA iocs_23_B_LOCATE,$00FF96F4,$00FF96FB,$20380974 jmp iocs_23_B_LOCATE PATCH_DATA iocs_24_B_DOWN_S,$00FF9724,$00FF972B,$6100E2C4 jmp iocs_24_B_DOWN_S PATCH_DATA iocs_25_B_UP_S,$00FF9730,$00FF9737,$6100E2B8 jmp iocs_25_B_UP_S PATCH_DATA iocs_26_B_UP,$00FF973C,$00FF9741,$2F016100 jmp iocs_26_B_UP PATCH_DATA iocs_27_B_DOWN,$00FF9748,$00FF974D,$2F016100 jmp iocs_27_B_DOWN PATCH_DATA iocs_28_B_RIGHT,$00FF9754,$00FF9759,$2F016100 jmp iocs_28_B_RIGHT PATCH_DATA iocs_29_B_LEFT,$00FF9760,$00FF9765,$2F016100 jmp iocs_29_B_LEFT PATCH_DATA iocs_2A_B_CLR_ST,$00FF9772,$00FF9779,$48E77848 jmp iocs_2A_B_CLR_ST PATCH_DATA iocs_2B_B_ERA_ST,$00FF9780,$00FF9787,$48E77848 jmp iocs_2B_B_ERA_ST PATCH_DATA iocs_2C_B_INS,$00FF9796,$00FF979D,$48E77F78 jmp iocs_2C_B_INS PATCH_DATA iocs_2D_B_DEL,$00FF97A4,$00FF97AB,$48E77F78 jmp iocs_2D_B_DEL PATCH_DATA iocs_2E_B_CONSOL,$00FF97BA,$00FF97C1,$6100E22E jmp iocs_2E_B_CONSOL PATCH_DATA iocs_AE_OS_CURON,$00FFC87E,$00FFC883,$31F809BA jmp iocs_AE_OS_CURON PATCH_DATA iocs_AF_OS_CUROF,$00FFC8AC,$00FFC8B1,$4EB900FF jmp iocs_AF_OS_CUROF .endif PATCH_TEXT ;コンソール拡張 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