85DATA HOMEへ
MYCAR情報掲示板BLOGプロフィール

■レトロプログラミング  疑似スプライトルーチンの作成

  〜ポケコンPC-G850によるVRAMへの描画処理〜

今回は、ポケコン(PC-G850)によるプログラム内容なのですが、”共通の技法”として多くの8ビットパソコンが同様のプログラムにて画像(グラフィック)を表示させていたのではないでしょうか?

20数年前振りに、このような機械語プログラミングをしてみました。

・・・いや、ホント懐かしいものです。
   (しかし、Z80プログラミングにおいてはリハビリ中のようなものです。かなり忘れてしまっています)


さて、私が所有しているポケコン(PC-G850)はVRAMがどうなっているのか、そして、どうやってVRAMにアクセスさせるのか(マニュアルも無く、私には)何も分かりませんでした。

色々と調べてみたところ、「秋日和」さんの製作の「ぽけこんのほん 2」が非常に参考になったのです。

http://ha9.seikyou.ne.jp/home/akihi/
(P4のリスト1 「G850の仮想VRAMから実VRAM転送ルーチン」です)

これをサブルーチンとして利用させてもらえれば、かなり楽にポケコン(PC-G850)のグラフィック描画が可能となります。

こうやってマニュアルが無くとも調べる事ができるのは、ありがたい事です。

※まだ、このポケコン(PC-G850)の機械語プログラミングを始めて1ヶ月足らずですから、もっと(このポケコンにとって)良い作り方があるのかもしれませんが、私にはこれ以降に書いた技法でしか(現時点では)作る事が出来ませんでした。

 

仮想VRAMについて

下表の +数値は仮想VRAMの開始アドレスからのオフセット値です。
  (1Byteで8ドットのOn/Off)

もちろん、”仮想”VRAMですから、描画する範囲によってVRAMの容量は自由に決定できます。
「秋日和」さんのサンプルルーチンをそのまま使用する場合は以下の通りになります。

 

 

しかし上表で説明を続けると、実画面と仮想VRAMが8ビット(=8ドット)を縦に描画させる為、少し説明しづらいのです。
 (2進数と実描画のイメージがつきにくい)

よって、x軸(横)とy軸(縦)を逆にした仮想VRAMの表を作ってみました。
つまり、ポケコン(PC-G850)を時計回りに90度回転させた状態です。
※と云う訳で以降の説明では、x軸(横)とy軸(縦)が逆になっています。ご注意下さい。

仮想VRAMへ値をセットした後に、”G850の仮想VRAMから実VRAM転送ルーチン”を実行すれば良いだけなのです。

まずは、描画をしてみます。 
(サンプルプログラムは文末に掲載しました)

 

仮想VRAM開始アドレス(の+オフセット)に以下の値を書き込む事で上記の画像が表示される。   
   (値を仮想VRAMにセットした後に「G850の仮想VRAMから実VRAM転送ルーチン」を実行)   
     
   +0 に0E   
   +1 に11   
   +2 に11   
   +3 に11   
   +4 に0E   
     
   +144 に0E   
   +145 に1F   
   +146 に1F   
   +147 に1F   
   +148 に0E

「うーん。実に簡単だ!」 

 

ここからが本題!
画像の重ね合わせ処理について


描画自体は(「秋日和」さん作サンプルルーチンを使用すれば)簡単なのですが、”画像の重ね合わせ”については考慮しないとなりません。

「仮想VRAM値とマスク画像との値をANDし、それに対し画像データ値とをORすれば良い」    
・・・要するに、「これだけ」の事です。   

そして「そんなの、基本だ!」と思われる方も多い事でしょう。

現在(2014年)でも、この様な技法が使われているのかどうかは分かりませんが、    
ビットシフトをして対応する事は現在では少ないのではないか・・・と思っています。
(不明です)    
かなり、基本的な(古典的な?)技法ではありますが、懐かしついでに纏めてみました。

 

マスク画像による重ね合わせ処理 その1

既に、描画済の画像(濃い色)があった場合に、グレー箇所の画像を描画してみる。 
     

上図の例では仮想VRAMの内容(+数値は仮想VRAM開始アドレスからのオフセット)は以下の値になっている。
 (グレー箇所は、これから描画予定なので、以下の値として反映されていません)

 +0に80
 +1にC0
 +2にC0
 +3にC0
 +4に80

+145に07
+146に07
+147に07
+148に03
+149に00

 

そして、描画したい画像(グレー箇所)を、”普通に”描画(仮想VRAMに書き込む)した場合

以下の様にy座標5〜7までが消えてしまう。

「これでは、都合が悪い!」
(これでは、穴だらけになってしまう)

 

よって、以下のパターンのマスクデータ(値)を準備する。

 

 

そのマスクデータと仮想VRAM値とのANDをした値を仮想VRAMに書き込む。
(この時点で仮想VRAMに書き込まなくても良いが、どこかに保存しておく)

以下はANDをした仮想VRAM値
なお、以下のグレー部分は描画位置に影響しないので考慮しない。
(今回は、y座標8以上は考慮しない)

 

 

仮想VRAM開始アドレス(の+オフセット)に画像データとのOR値を書き込む事で以下の画像が表示される。

なお、仮想VRAMに書き込む値は以下の通り。
 +0に8E
 +1にD1
 +2にD1
 +3にD1
 +4に8E

※上記の例ではAND処理をする必要は無い・・・・と思われがちだが、その通り!
上記例では必要は無いが、描画したい位置に何かが”既に”描画済の場合にはAND処理が必要になる。

 

マスク画像による重ね合わせ処理 その2

「その1」の例では、描画したい画像のy座標位置が8の倍数(0を含む)であれば問題が無い。
では、描画開始位置のy座標が”8の倍数”以外では、どうしたら良いのかを考える。

既に、描画済の画像(濃い色)があり、グレー部のように描画させたい場合を説明する。
 (描画開始のy座標は6)

 

 

@マスクデータは上図の(y座標0〜7)の通り、これを左ビットシフトをさせる。
Aさらに描画開始y座標に隣接する仮想VRAMアドレス(座標8〜15)のマスク画像はFFとする。

@とAを(この例では) 6回、左ビットシフトすれば良い。
描画したいy座標の開始位置は6なので、6÷8の余りがシフト回数となる。

なお、@の値は左ビットシフト後のビット0は1とする。
@の左シフトシフト処理前の7ビット目(溢れる7ビット目)は、Aを左ビットシフトした後にビット0にセットさせる。

6回、左ビットシフトした内容は以下の通り。

 

 

同様に描画データも6回シフトさせる。

@描画データは上図の(y座標0〜7)の通り、これを左ビットシフトをさせる。
Aさらに描画開始y座標の隣(座標8〜15→開始位置は8の倍数)の値は00とする。

なお、@の値は左ビットシフト後のビット0には0とさせる。
@の左シフトシフト処理前の7ビット目(溢れた7ビット目)は、Aを左ビットシフトした後にビット0にセットさせる。

6回、左ビットシフトした内容は以下の通り。

 

 

生成されたマスクデータと仮想VRAMの値とでANDとした値を仮想VRAMに書き込む。
以下はANDをした仮想VRAM値

 

 

仮想VRAM開始アドレス(の+オフセット)に画像データとのOR値を書き込む事で以下の画像となる。

なお、仮想VRAMに書き込む値は以下の通り。
 +0に8E
 +1に51
 +2に51
 +3に51
 +4に8E

+144にE3
+145にF4
+146にF4
+147にF4
+148にE3

 

もう一度、その2の技法を使って、確かめてみる。

上図で状態から、y座標4、x座標2の位置に、同じ画像を表示させてみたい場合はどうなるのか?
(描画する画像はグレー箇所)

 

 

マスク画像は4回、左ビットシフトをすると以下の通りとなる。

 

 

仮想VRAMとマスク画像のAND値は以下の通り
なお、グレー部分は描画位置に影響しないので、考慮しない。

 

 

画像データも同様に4回、左ビットシフトを行う。

 

 

仮想VRAM開始アドレス(の+オフセット)に画像データとのOR値を書き込む事で以下の画像が表示される。

なお、仮想VRAMに書き込む値は以下の通り。
 +2にF1
 +3に11
 +4に1E
 +5に10
 +6にE0

+146にF4
+147にF5
+148にE3
+149に01
+150に00

 

サンプルプログラム

上記の考え方により、サンプルプログラムを作ってみました。
一応、機械語とBASICのソースもダウンロード出来るようにしておきます。

機械語アセンブルリストのダウンロード

BASICリストのダウンロード

手っ取り早く インテルHEX形式もダウンロード

※動作はオール機械語なのですが、BASICにてキャラの座標位置、増減数をセットして機械語をコールしています。

きっと、無駄が多いのだろうな。

 

最後に実行動画です。

ポケコンPC-G850 擬似スプライト&スクロール サンプル

 

 


2014/10/12 追記

実機で動かしてみました。
【実機】ポケコンpc-g850で擬似スプライト&スクロール

 

キャプチャした動画を確認したら、60FPSで動作しているようです。
キャラの移動が速過ぎて、液晶の反応が間に合っていない感じ。

うまく、作れば3階調で表現させる事も出来るかもしれません。
(現段階では、静止画ならば3階調も出来ています)

 

 


BASICソース


10 AD=&H33B 'CHRDT
20 BG=&H77B 'BGVRAM
30 PRINT "ハイケイ ";:INPUT A
40 '
50 IF A=0 THEN
60  POKE &H101,&HB1:POKE &H102,&H02
70 ELSE
80  POKE &H101,&H97:POKE &H102,&H01
90 ENDIF
100 '
110 FOR I=0 TO 19:J=I*16
120  A=RND(2)   :POKE (AD+J+0),A 'CHRNO
130  A=RND(48)+8:POKE (AD+J+2),A 'X
140  A=RND(48)+8:POKE (AD+J+4),A 'Y
150  B=RND(1)
160  A=RND(256)-1
170  IF B=1 THEN
180   POKE(AD+J+5),0:POKE(AD+J+6),1
190   POKE(AD+J+7),A:POKE(AD+J+8),0
200  ELSE
210   POKE(AD+J+5),A:POKE(AD+J+6),0
220   POKE(AD+J+7),0:POKE(AD+J+8),1
230  ENDIF
240 NEXT
250 '
260 CALL &H100 'SAMPLE


機械語ソース


          ORG 0100H     
SAMPLE:   CALL BGCOPY    ;   BGVRAMからVRAMへ転送 ※背景使うなら、こちらをコール
;         CALL VRAMCLS   ;   VRAMクリア           ※背景使わないなら、こちらをコール
          LD A,(COUNT)  
          INC A         
          LD (COUNT),A  
                        
          LD IX,CHRDT   
          LD B,0        
          LD C,16       
          LD D,20       
                        
SAM_L1:   PUSH DE       
          PUSH BC       
          LD A,(IX+0)   
          LD (CHRNO),A  
          LD L,(IX+1)    ;   L=X下位     (小数部)
          LD H,(IX+2)    ;   H=X上位   (整数部)
          LD E,(IX+5)    ;   E=X増加下位 (小数部)
          LD D,(IX+6)    ;   D=X増加上位 (整数部)
          LD A,87       
          LD B,A        
          CALL SA_SB1    ;   HL=HL+DE:IF H<8 OR H>MAX THEN DE=-DE
                        
          LD (IX+1),L   
          LD (IX+2),H   
          LD (IX+5),E   
          LD (IX+6),D   
          LD A,H        
          LD (XG),A     
                        
          LD L,(IX+3)    ;   L=Y下位     (小数部)
          LD H,(IX+4)    ;   H=Y上位     (整数部)
          LD E,(IX+7)    ;   E=Y増加下位 (小数部)
          LD D,(IX+8)    ;   D=Y増加上位 (整数部)
          LD A,50       
          LD B,A        
          CALL SA_SB1    ;   HL=HL+DE:IF H<8 OR H>MAX THEN DE=-DE
          LD (IX+3),L   
          LD (IX+4),H   
          LD (IX+7),E   
          LD (IX+8),D   
          LD A,H        
          LD (YG),A     
                        
          CALL SPRITE    ;スプライトルーチン (IN:CHRNO,XG,YG)
                        
          POP BC        
          POP DE        
          ADD IX,BC     
          DEC D         
          JP NZ,SAM_L1  
                        
          CALL VRAMWRT   ;仮想VRAMから実VRAMへ転送
          CALL BE53h     ;BIOS リアルタイムキー入力
          RET C         
          JP SAMPLE     
          RET           
                        
;         ------------- 
;         IN B(判定値)     
;         HL=HL+DE:IF H<8 OR H>MAX THEN DE=-DE
                        
SA_SB1:   ADD HL,DE     
          LD A,H        
          CP 08         
          JP NC,SA_J     ;IF A>=8 THEN SA_J
          LD HL,0800H   
          CALL SA_SB2    ;DE=-DE
          RET           
SA_J:     CP B          
          RET C         
          LD H,B        
          LD L,0        
          CALL SA_SB2    ;DE=-DE
          RET           
;         ------------- 
          ;DEの正負反転      
SA_SB2:   PUSH AF       
          LD A,D        
          CPL           
          LD D,A        
          LD A,E        
          CPL           
          LD E,A        
          INC DE        
          POP AF        
          RET           
;---------------------------------------------               
;背景用RAMから仮想VRAMへ転送               
BGCOPY:   LD HL,BGVRAM  
          LD DE,VRAMS   
          LD BC,576      ;   576=96*6   ※横描画範囲により値は変動する
          LDIR          
                        
          ;背景スクロール(2行目〜4行目)
          LD B,7        
          LD HL,BGVRAM1+1
          LD DE,BGVRAM1 
                        
BGC_J0:   PUSH BC       
          LD A,(COUNT)  
          AND B         
          CP B          
          JP NZ,BGC_J1   ;   IF A<>B THEN 転送しない(行によってスクロールする頻度が異なる)
          CALL BGC_SB    ;転送する
          JP BGC_J2     
                        
          ;転送しない(スクロールしない)
BGC_J1:   LD BC,96      
          ADD HL,BC     
          LD D,H        
          LD E,L        
          DEC DE        
                        
BGC_J2:   POP BC        
          SRL B         
          JP NZ,BGC_J0  
                        
          ;背景スクロール(5行目〜6行目)
          CALL BGC_SB    ;5行目のスクロール
          CALL BGC_SB    ;6行目のスクロール
          RET           
                        
          ;転送する(スクロールする)
BGC_SB:   LD BC,95       ;   96-1 ※横描画範囲により値は変動する
          LD A,(DE)      ;左端の値をバックアップ
          LDIR          
          LD (DE),A      ;左端を右端にセット
          INC DE        
          INC HL        
          RET           
                        
;---------------------------------------------               
;疑似スプライト                
;入力 アドレス(XG,YG,CHRNO)に値を代入しておく               
;結果は仮想VRAMへ出力               
                        
SPRITE:   PUSH IX       
          PUSH BC       
          PUSH DE       
          PUSH HL       
                        
          LD A,(YG)     
          SRL A         
          SRL A         
          SRL A         
          LD (YAD),A     ;YAD=Int(YG/8)
          SLA A         
          SLA A         
          SLA A         
          LD E,A        
          LD A,(YG)     
          SUB E         
          LD (YOFF),A    ;YOFF=YG-Int(YG/8)*8 (余りを求める)
                        
          LD A,(YAD)    
          LD H,A        
          LD L,96       
          CALL CAL_X     ;戻りIX=H*L
          PUSH IX       
          POP DE        
                        
          LD HL,VRAM    
          ADD HL,DE      ;    HL=アドレスVRAM+YG*96
                        
          LD D,0        
          LD A,(XG)     
          LD E,A        
          ADD HL,DE      ;    HL=HL+XG
          LD (V_AD),HL   ;V_AD=HL
                        
          LD A,(CHRNO)  
          SLA A         
          SLA A         
          SLA A         
          LD D,0        
          LD E,A        
          LD HL,CHR     
          ADD HL,DE     
          LD (CHRAD),HL  ;CHRAD==アドレスCHR+CHRNO*8
          LD HL,MSK     
          ADD HL,DE     
          LD (MSKAD),HL  ;MASAD=アドレスMSK+CHRNO*8
                        
          LD HL,(V_AD)  
          LD IX,(CHRAD) 
          LD IY,(MSKAD) 
                        
          LD A,0        
          LD (CHRCT),A  
                        
SP_J1:    LD A,(IY+0)    ;マスク
          LD C,A        
          LD B,FFH      
          CALL SP_SB1   
                        
          LD A,(IX+0)   
          LD E,A        
          LD D,00H      
          CALL SP_SB2   
                        
          LD A,(HL)      ;VRAM内容
          AND C         
          OR E          
          LD (HL),A     
                        
          PUSH HL       
          PUSH BC       
          LD B,0        
          LD C,96       
          ADD HL,BC     
          POP BC        
          LD A,(HL)     
          AND B         
          OR D          
          LD (HL),A     
          POP HL        
                        
          INC HL        
          INC IX        
          INC IY        
                        
          LD A,(CHRCT)  
          INC A         
          LD (CHRCT),A  
          LD B,A        
          LD A,(CHRWD)  
          CP B          
          JP NZ,SP_J1   
                        
          POP HL        
          POP DE        
          POP BC        
          POP IX        
          RET           
                        
          ;------------------------
          ;YOFF分シフトさせる  
                        
          ;マスク用         
          ;入力 Cレジスタ (シフトする)下位8ビット/Bレジスタ 上位8ビット側
SP_SB1:   LD A,(YOFF)   
SB1_J     CP 00         
          RET Z         
          SLA C         
          RL B          
          SET 0,C       
          DEC A         
          JP SB1_J      
                        
          ;キャラ用         
          ;入力 Cレジスタ (シフトする)下位8ビット/Bレジスタ 上位8ビット側
SP_SB2:   LD A,(YOFF)   
SB2_J     CP 00         
          RET Z         
          SLA E         
          RL D          
          DEC A         
          JP SB2_J      
                        
;---------------------------------------------               
;乗算                     
;         入力   HL       
;         戻りは IX = H×L の計算結果
                        
CAL_X:    PUSH HL       
          PUSH DE       
          LD   IX,0      ;IX 計算結果を代入
          LD   E,L      
          LD   D,0       ;DE=L
C_J1:     BIT  0,H       ;ビット0を確認
          JP   Z,C_J2    ;ビットが立っていなければスキップ
          ADD  IX,DE     ;IX=IX+DE
C_J2:     SLA  E        
          RL   D        
          SRL  H        
          JP   NZ,C_J1   ;IF H<>0 THEN C_J1
          POP DE        
          POP HL        
          RET           
;*************************************************************               
;秋日和さんの「G850の仮想VRAMから実VRAM転送ルーチン」です。               
                        
; ※一部 変更しています。(コメントR2部分)               
;*************************************************************               
                        
VRAMCLS:LD A,00H               
          LD HL,VRAM    
          LD DE,VRAM+1  
          LD BC,767      ;   767=96*8-1 ※横描画範囲により値は変動する
          LD (HL),A     
          LDIR          
          RET           
                        
VRAMWRT:LD A,(790DH) ;実行時縦アドレスを取得  
          LD D,A        
          LD E,6        
          LD C,41H       ;出力ポート 41H
;         LD HL,VRAM    
          LD HL,VRAMS-8  ;   R2(追加・↑から変更)
                        
VR_1:     PUSH BC       
          LD BC,0010H    ;   R2(追加) 16=見えないエリア分をVRAMに足す
          ADD HL,BC      ;   R2(追加)
          POP BC        
                        
TATEAD:   LD A,0B0H      ;縦アドレス(基本値)※ココが書き換わる
          ADD A,D       
          AND 0B7H       ;下位3ビットが縦アドレス B7H=10110111
          OUT (40H),A    ;縦アドレス指定・出力
          LD A,010H      ;横アドレス上位4ビットを0 10H=00010000
          OUT (40H),A    ;横アドレス上位指定・出力
          XOR A         
          OUT (40H),A    ;横アドレス下位指定・出力
          LD B,80       
          OTIR          
          LD A,(TATEAD+1)
          INC A         
          LD (TATEAD+1),A;縦アドレス+1
          DEC E         
;         JR NZ,TATEAD   ;IF E<>0 THEN TATEAD
          JR NZ,VR_1     ;   R2(追加・↑から変更)
          LD A,0B0H     
          LD (TATEAD+1),A
          RET           
                        
STPKEN:   IN A,(1FH)    
          RLC A         
          RET C         
          JP VRAMWRT    
                        
;*************************************************************               
VAL1:     DB 00H,00H     ;汎用
COUNT:    DB 00H        
                        
CHRNO:    DB 02H        
XG:       DB 08H        
YG:       DB 08H        
YAD:      DB 00H        
YOFF:     DB 00H        
V_AD:     DB 00H,00H     ;VRAM書込み開始アドレス
CHRAD:    DB 00H,00H    
MSKAD:    DB 00H,00H    
                        
CHRCT:    DB 00         
CHRWD:    DB 05         
                        
;描画するグラフィックデータ               
CHR:      DB 00H,00H,00H,00H,00H,00H,00H,00H
          DB 0EH,11H,11H,11H,0EH,00H,00H,00H
          DB 0EH,1FH,1FH,1FH,0EH,00H,00H,00H
                        
;上記のマスクデータ              
MSK:      DB E0H,E0H,E0H,E0H,E0H,FFH,FFH,FFH
          DB F1H,E0H,E0H,E0H,F1H,FFH,FFH,FFH
          DB F1H,E0H,E0H,E0H,F1H,FFH,FFH,FFH
                        
                        
;描画キャラクタの情報               
;以下 上位を整数部、下位を小数部として取り扱う。               
                        
          ; CHRNO|----X----|----Y----|--X増加--|--Y増加--|→以降予備
          ;      |下位,上位|下位,上位|下位,上位|下位,上位|
          ;   0    1    2    3    4    5    6    7    8
CHRDT:    DB 00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ,00H ;1
          ;以降 2〜20      
          DS 16*19      
                        
;仮想VRAM     X座標:0〜95 Y座標:0〜63               
;うち描画範囲 X座標:8〜87 Y座標:8〜55               
                        
VRAM:     DS 96          ; 見えない範囲
VRAMS:    DS 96*6        ; 見えない範囲8  +描画範囲80  +見えない範囲8
          DS 96          ; 見えない範囲
                        
;背景用RAM                 
;         ; 見えない範囲8  +描画範囲80  +見えない範囲8
BGVRAM:   DB 00H,00H,00H,00H,00H,04H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H
          DB 00H,00H,00H,80H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H
          DB 00H,02H,00H,00H,00H,00H,00H,00H,40H,00H,00H,00H,00H,80H,00H,00H
          DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,04H,00H,00H
          DB 00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,00H,20H,00H,00H,00H
          DB 00H,00H,00H,00H,00H,00H,40H,00H,00H,00H,00H,00H,00H,00H,00H,00H
                        
BGVRAM1:DB 00H,80H,00H,80H,80H,80H,80H,80H,80H,80H,80H,80H,80H,C0H,C0H,E0H               
          DB E0H,C0H,40H,C0H,C0H,C0H,40H,C0H,00H,80H,00H,80H,80H,C0H,E0H,E0H
          DB C0H,C0H,60H,E0H,60H,C0H,00H,C0H,00H,80H,00H,80H,00H,80H,00H,80H
          DB 00H,80H,00H,80H,00H,80H,80H,80H,C0H,C0H,C0H,C0H,E0H,E0H,F0H,F0H
          DB 70H,E0H,60H,E0H,40H,80H,40H,80H,40H,80H,00H,80H,00H,80H,80H,80H
          DB 80H,80H,C0H,C0H,C0H,C0H,40H,C0H,C0H,40H,C0H,00H,C0H,00H,C0H,80H
                        
          DB 06H,89H,20H,57H,00H,8BH,00H,57H,08H,A3H,15H,49H,02H,B5H,0AH,61H
          DB 36H,89H,20H,77H,30H,ABH,10H,77H,38H,BBH,3CH,D5H,3EH,1FH,3CH,57H
          DB 1CH,2FH,1EH,0DH,12H,2DH,16H,0FH,36H,4FH,02H,15H,20H,4DH,90H,01H
          DB ABH,11H,81H,47H,11H,03H,21H,47H,09H,83H,35H,49H,03H,94H,0BH,40H
          DB 17H,A8H,01H,56H,01H,ABH,00H,57H,09H,A3H,15H,49H,03H,B5H,0BH,61H
          DB 37H,89H,21H,76H,31H,AAH,11H,77H,39H,BAH,3DH,55H,3FH,9FH,3CH,57H
                        
          DB 38H,46H,62H,C1H,A3H,D5H,EBH,F5H,7EH,FEH,38H,0DH,40H,1AH,0CH,A5H
          DB 0CH,0EH,4CH,1DH,06H,AEH,0CH,4FH,1FH,87H,2FH,0CH,4FH,1FH,06H,ACH
          DB 0EH,02H,4EH,16H,00H,AAH,04H,42H,1CH,82H,20H,0EH,43H,14H,01H,ADH
          DB 3AH,44H,63H,C1H,A3H,D5H,EBH,F5H,7EH,FCH,38H,01H,44H,1AH,00H,A1H
          DB 00H,0AH,40H,15H,00H,AAH,00H,45H,10H,82H,20H,05H,40H,1AH,00H,A5H
          DB 00H,0AH,40H,15H,00H,A2H,00H,4DH,10H,82H,20H,05H,40H,1AH,00H,A5H
                        
          DB 20H,0AH,01H,40H,10H,84H,28H,00H,C1H,52H,A0H,58H,A9H,54H,AAH,55H
          DB FFH,FEH,FDH,F8H,F0H,E4H,E8H,80H,41H,12H,80H,08H,41H,04H,90H,00H
          DB 20H,0AH,01H,40H,10H,84H,28H,00H,41H,12H,80H,08H,41H,04H,90H,00H
          DB 20H,0AH,01H,40H,10H,84H,28H,00H,41H,12H,80H,08H,41H,04H,90H,00H
          DB 20H,0AH,01H,40H,10H,84H,28H,00H,41H,12H,80H,08H,41H,04H,90H,00H
          DB 20H,0AH,01H,40H,10H,84H,28H,00H,41H,12H,80H,08H,41H,04H,90H,00H
                        
          DB 90H,00H,01H,00H,20H,08H,06H,05H,4AH,0DH,1AH,15H,2AH,35H,6AH,55H
          DB FFH,7FH,3FH,3FH,3FH,1FH,0FH,0FH,47H,06H,00H,00H,21H,08H,02H,00H
          DB 90H,00H,01H,00H,20H,08H,02H,01H,40H,04H,00H,00H,21H,08H,02H,00H
          DB 90H,00H,01H,00H,20H,08H,02H,01H,40H,04H,00H,00H,21H,08H,02H,00H
          DB 90H,00H,01H,00H,20H,08H,02H,01H,40H,04H,00H,00H,21H,08H,02H,00H
          DB 90H,00H,01H,00H,20H,08H,02H,01H,40H,04H,00H,00H,21H,08H,02H,00H
                        
EOF:      DB 00H