ET解析記事 その3 増補版 『 おきて破りのET−BIOS内部解析(3) 』   著作:E.Kako ######## # はじめに # ########  ETのBIOS−ROMの内部を探って分かったことを毎回少しずつ書いて いきたいと思います。この記事により、BIOSを使わないで直接ハードにア クセスする方法も紹介されますが、ハードのバージョンの違いによってソフト が動かないというリスクもありますので、あまりお勧めできません。注意して この記事をご利用ください。この記事に関して不利益が発生しても、著者は免 責とします。 ################ # 表示関係のBIOSの解析 # ################  表示関係のBIOSは非常にたくさんのファンクションがあるので、まだ全部を 解析していません。解析した分の結果についてそれを全部説明しても、あたりまえ の処理の解説を書き連ねるだけになるので、BIOSの内容についてはあえて触れ ません。 そのかわり、直接ハードウェアにアクセスする方法について特に詳しく 解説します。 ############# # ハードウェアの説明 # #############  ETの表示装置は160×64ドットのLCD(液晶)表示ディスプレイです。 98などのパソコンの場合にはV−RAMと呼ばれるRAMがメインメモリ上に存 在していて、そこに値を書き込むことでディスプレイに文字や絵を表示することが できます。 しかしETの場合にはメインメモリ上にV−RAMが存在しません。 V−RAMは、LCDコントローラである『HD61202』の内部に存在してい るので、LCDコントローラにコマンドを出力してV−RAMへの入出力等の制御 を行います。  まず、ETに搭載されているLCDコントローラ『HD61202』の仕様を説 明します。このコントローラは1つが64×64ドットのV−RAMを持っていて、 そのV−RAMのそれぞれのドットに対応するLCDのドットを点灯/消灯します。 ETの画面は3つの別々のLCDCを合わせて192×64ドットになりますが、 160×64ドットしか表示はされません。 【VRAMの構成】 0 63 64 127 128 191 +--------------------+--------------------+--------------------+ 0| | | | | | | | | LCDC1 | LCDC2 | LCDC3 | | のVRAM | のVRAM | のVRAM | | | | | 63| | | | +--------------------+--------------------+--------------------+ 【表示される範囲】 16 63 64 127 128 175 +-+------------------+--------------------+------------------+-+ 0| | | | | | | | | | | | | | LCDC1 | LCDC2 | LCDC3 | | | | の表示範囲 | の表示範囲 | の表示範囲 | | | | (48×64) | (64×64) | (48×64) | | 63| | | | | | +-+------------------+--------------------+------------------+-+  ※左右の16ドット分づつは、一部がインジケータの表示に使われますがあとの   部分には値を書き込んでも何も表示されません。  次に、LCDCの持つVRAMの構成を説明します。1つのLCDCは前述のと おり64×64ドットのVRAMを持っています。VRAMにアクセスするために は、そのアドレスをXとYというパラメータで指定します。1組の(X,Y)でア クセスされるVRAMは1バイトで、縦の方向に8ドット分のビットイメージです。 LSBが上で、MSBが下です。ビットは0がドット消灯で、1がドット点灯です。 【LCDCのアドレス】 X=0 X=63 +--------------------+ Y=0| | Y=1| | : | LCDC | : | のVRAM | Y=6| (64×64) | Y=7| | +--------------------+ 【一番上(Y=0)の部分】 X=0 1 2 3 60 61 62 63 bit0 → ■ □ □ □ 〜 □ □ □ □ bit1 → ■ □ □ □ 〜 □ □ □ □ bit2 → ■ □ □ □ 〜 □ □ □ □ Y=0 bit3 → ■ □ □ □ 〜 □ □ □ □ bit4 → ■ □ □ □ 〜 □ □ □ □ bit5 → ■ □ □ □ 〜 □ □ □ □ bit6 → ■ □ □ □ 〜 □ □ □ □ bit7 → ■ □ □ □ 〜 □ □ □ □       ↑ つまり、X=0,Y=0を指定するとこの縦8ドットがアクセスされる  また、特にYのアドレスで指定された横方向1行全部(X=0〜63)のことを レーンと呼ぶことがあります。(例.Y=0をレーン0,Y=1をレーン1..) レーンは0から7まであり、文字の大きさを8×8や6×8にした場合に1行目か ら8行目に対応します。 +---------------------------+ レーン0| 0〜63 | +---------------------------+ レーン1| 0〜63 | : +---------------------------+ : : 〜 : : +---------------------------+ レーン6| 0〜63 | +---------------------------+ レーン7| 0〜63 | +---------------------------+ ################## # LCDコントローラの制御方法 # ##################  LCDCにアクセスするためのI/Oポート、I/Oポートから読み出された ステータス、I/Oポートに書き込むコマンドの値と意味は次のとおりです。 【LCDCのI/Oポート】   I/Oポート(30H) : LCDC1のステータス読み出し/コマンド出力   I/Oポート(31H) : LCDC1のデータREAD/WRITE   I/Oポート(32H) : LCDC2のステータス読み出し/コマンド出力   I/Oポート(33H) : LCDC2のデータREAD/WRITE   I/Oポート(34H) : LCDC3のステータス読み出し/コマンド出力   I/Oポート(35H) : LCDC3のデータREAD/WRITE 【LCDCのステータス】   1バイトのデータが読み出されます。各ビットは次のような意味を持ちます。    bit7 : BUSY .... 0:READY状態/1:内部動作中    bit5 : ON/OFF .. 0:表示ON   /1:表示OFF    bit4 : RESET? .. 0:ノーマル?  /1:リセット?   ※あとのbitは0です 【LCDCのコマンド】  コマンドの値    コマンドの意味   3EH     : LDCの表示をOFFにする   3FH     : LDCの表示をONにする   40H〜7FH : Xアドレスの値を(40H+X)で指定する   B8H〜BFH : Yアドレスの値を(B8H+Y)で指定する   C0H〜FFH : 表示開始位置を(C0H+n)で指定する                 ※表示開始位置については後に説明します。  具体的な使い方の例を以下に説明します。 【LCDのステータスを調べる】 IN (30H),A : AレジスタにLCDC1のステータスを読み出す  LCDCにコマンドを書き込んだ直後にごく短い時間だけBUSY状態となり、  BUSY状態ではLCDCはコマンドを受け付けてくれません。 本来ならば、  ステータスを読み出してチェックするべきですが、一定時間のWAITを入れて  やることで代用できます。NOPを1つだけ入れればREADY状態に戻るので  わざわざポートを読み出して調べたりしなくてもいいでしょう。 【LCDのON/OFF】 LD A,3EH OUT (30H),A : LCDC1をOFFにする LD A,3FH OUT (30H),A : LCDC1をONにする 例えば、モニタで ]O 30 3E と入力すると、画面の左側の3分の1のLCDが消灯します。 ]O 30 3F と入力すると、またLCDが点灯します。 (画面が見えないので注意深く入力してください。) 【VRAMへの書き込み】  例として、LCDC1のVRAMのレーン0全体にFFHを書き込むプログラム を示します。 LD A,0B8H ;Yアドレス=0を指定する LD B,40H ;Xアドレス=0を指定する LD C,30H ;LCDC1にコマンド出力する OUT (C),A NOP ;WAITを入れなければならない! OUT (C),B LD A,0FFH ;VRAMに書き込むデータ LD B,64 ;64回書き込みをくり返す LD C,31H ;LCDC1にデータを書き込む LBL1: OUT (C),A DJNZ LBL1  ここで注意しなければならないのは、データR/Wのポート(31H)にアクセ スすると、自動的にXアドレスがインクリメントされることです。ですから、1回 の書き込みごとにわざわざアドレスを指定する必要はなく、1つのレーンに対して は連続してデータを書き込むことができます。  また、コマンドを連続して出力するときにはBUSY状態を避けるために適当な WAITを入れてやる必要があります。クロックが2MHzのときにはNOPが1 つ(4クロックサイクル)の時間で十分です。データの連続書き込みにはWAIT は必要ありません。 【VRAMの読み出し】  例として、LCDC1のVRAMのレーン0全体をHLレジスタの指すバッファ に読み出すプログラムを示します。 LEA HL,VRAM_BUFFER ;VRAMを読み出すバッファの先頭アドレス LD A,0B8H ;Yアドレス=0を指定する LD B,40H ;Xアドレス=0を指定する LD C,30H ;LCDC1にコマンド出力する OUT (C),A NOP ;WAITを入れなければならない! OUT (C),B LD B,64 ;64回読み出しをくり返す LD C,31H ;LCDC1からデータを読み出す IN A,(C) ;ダミーの読み出しを1回しなければならない! NOP ;WAITを入れなければならない! LBL1: IN A,(C) LD (HL),A INC HL DJNZ LBL1  読み出しの場合に注意することは、書き込みの場合とほとんど同じですが、1つ だけ特に注意しなければならないのは、ダミーの読み出しを1回だけ入れておかな ければならないことです。ダミーの読み出しにより、LCDコントローラは読み出 しの準備をするからです。また、このときにもWAITが必要です。 ############################# # 直接LCDCを制御するメリット/表示開始位置とは? # #############################  ここまでに書いてきた内容によって、LCDCを直接制御してVRAMを読み書 きする方法を示しました。少し難しいですが、直接LCDCを制御すればBIOS を使うよりもかなり速く表示ができます。高速な画面処理が要求されるようなゲー ムを作る場合には、直接制御したほうがいいでしょう。  LCDCのコマンドには表示開始位置を指定するコマンドがあります。LCDC のこの機能はETのBIOSでは全く扱われていません。この機能を利用するため にはLCDCを直接制御する以外には方法はありません。 【LCDCのコマンド】  コマンドの値    コマンドの意味   C0H〜FFH : 表示開始位置を(C0H+n)で指定する  ※ここで、nというのは0〜63の値を取り、VRAMの上からn番目のドット   を実際に表示されるLCDの一番上に割り付けます。 例えば、モニタで ]O 30 C1 ]O 30 C2 ]O 30 C3 ]O 30 C4 ]O 30 C5 ]O 30 C6 と順番に入力してみて下さい。画面の左側の3分の1のLCDが上方向に1ドット づつだけスクロールアップしていくように見えます。 ]O 30 C0 で元に戻ります。  つまり、表示開始位置を0〜63まで変化させれば上方向に1ドットづつ画面が スクロールアップします。また、63〜0まで変化させれば下方向に1ドットづつ 画面がスクロールダウンします。VRAMの内容を書き換えずに、表示する位置を ずらしているだけなので、高速な1ドットごとのスクロールができます。これも、 ゲームを作る場合などに応用できるでしょう。 ###### # 付録 # ###### begin 644 lcd1.lzh M'@$M;&@Q+1`%``#W$P``<3'<&"``"$Q#1#$N05--+H3CYG+8N5['/Z&L[G>[] M?3O.;V;[Y?O_6;WJ[GH^#>VJ0+XV?_^MM^J:[=;R1%^T]^UF<6@HSV%1U_;][ MY-L'F)AX5W)NH-/+`#J0X3S"N;^-*XTEOSF-F])5B&A!Y8%M.F0VW$\;M+7OK M[+!L;:):&]AEHAC-0,4/(F]>#)]?`Q4`^D*)8C!WT^XX'"O12.@:8VF<,H%%^ M."8F_:@H81F!P;:$]\C3"8A&"242)0]HD9V"06;D0A('.^*)0E!B=ASG$D1P[ M0AD4(/PD$Q5ND:*T`2C%$"SQ<6875(^%,%6JY]%C9L&_;=F_#%G8J\R)Q%'D( MNYO<"3ET]FE.&';L?%+^H6>IG<,H2A^_$BNSH#3@1[_&YV\PE_; MBZR*3,FO'P;SR/(5[];K+X$/:%$ MMSLQNL[/$-09Q24K[3E:]:ARZ12,V`A$*+E<]M$>CZG'5 MX=;P2>IN?O>0`I5Z.<@H(V8>!AT]T@/P?.\60_\^4"1TD"7!TFJ1PPGB9%`3T MV19MP);N"8M6@QW8(#J>VC&TQJ!,@!DF7\C&!V#M>$R"`)T194U=9C;:A;F@S/K MUZ-_?GTWAHC>)*L_99I1NX8I41Z_G69E&*Z2";AJOM:B/WDGG00U8ZG=2MBUC ME<$(B1(+@G%48PJ2E\%DJL++U(UV?^2?IJC0,%U*92?:C>&"8UC0'(:"@0=*I&F?,M`>$XY8A` MBF0N,4=HZOYJ:1GG=09!T),LH-H',GPE1L,%"PHNK];(6T,6UZ.Q2,,\`1\+% M$4TQ'62MG#VZ[#ZF(".Q>4"B$W8?5<3QW)PU+6KN@#`2`%USKR2@LKL=I>;7$ M/#085-+D8=?H$>O*Z,$PIZ8/LT[HLPO(/V6;HG_77R-J57VG=]7U'SSV(OTYB M_)QC+;O4O^:PG(/\O*582AYV%GS:*9C&H;3@3;AOM`\ M/'@$FQ6@<["LF>*4/\O7!!@!VH"YMWW\E;IPL5ZE6`=V\CZ<#FT4`C=)OH@0B M(/&"<;65YGNA7)Z!#3<0)\J9-NFY3X`GD3R#CD"2'8]QC`II8SHEF^8\[ZB5"MJ^3D;_9XDSV(J"ER4Q2! M,4=."9/$SYYG1[CHM#+O>L!@#]O8OP`>9BUL:#$M%@(``%8#``"/,=P8(``(! M3$-$,2Y$3T.N!`W\QP!YD>`=8'?>_]U[WWNYB]"T%C0I8)6#=H]&`?]T^E4(` MI\*?^N#I81^&L:`MNVR<38:HD9F#NR1U(RD(6TN\U?ZK%?PM^%70VUS:&*A6Y6A,TN+%S@KG5S&"!\3YRPWWM>B-Z"#[M-3H%%T061@^>?8A MU]$F_OM=^V6<93PP,M;SM*;OU@$@UD[JYMZ-4"GLF^]WZK+)P_N0BF6-O5=(N^) M@"PCR\>+N3SM2-V8-RC/\AX$)[M[\B$17X%E./0G%F-AXMVQ"\&DG9[O;>RL/ MO:)8\C9R(>A1E66MB':23-XP8!,LY7Z,IXILZG&8C=*9?!E:7!985]:NV[.ERLG!J-GN7/BUMMK7DLI`V2DB5/LS5O3O(+71.R&D?6:A">3)-C%S<@3RUSE'ZY>9=L;QR1;2'*/X@`JS8< M=%;AM"=)PPM9:E!30[\N,'4T7+)4RW/TI#%IJN(E$`P!$)BK6A;FO3CWA-!`5 M/T6H'L@I(2LZ$LP/-!PB%SL-M!J%=FCXK_.OZ*"#?MKK;R:V_*-?RHRG62U@S M^ET-1R*3-QVH(Z,)/87'LX)ZM/+F9#"?^,&B#0./J,Q>:++349BI,CX_YT]&8 MEFFQ?[^.,UZ\K_PV4^=#I=RDLF'N5#,.?,H237*,][_"R?8[MR$YK!9U>4N3AIII]KV]AX\QM?V"U97G0\O M08>R:6&GVGI>M>"QT5`L+)O+7C=F">D_ZHN,?9EV>VS,8A165U",+" MJ0C``.8.P9MTD8-:_2`&BLAM(*VAV2(Y9_VN8Q/>.A%H_Z.VG`Z =472+KN"5E=*+V);4P\G'#AI=@[]EX@`#