2018年12月02日

画面切り替えと垂直同期検出の件(画面がちらつく問題)

 P6でキャラ描画時にちらつく問題の続きです。

 ロジアナで確認しました。
 結論ですが、いろいろと間違いが発見されました。

○mk2
★ページ切り替え(ポート0xb0)に設定した値は、垂直同期がH→Lのタイミングで反映される。
★PSGのIOA7には、垂直同期が出力されている。
 1フレーム262ラインの内、3ラインが"L"、259ラインが"H"が出力されている。

○mk2SR
★ページ切り替え(ポート0xb0)に設定した値は、即時に反映される。
★OPNのIOA7には、帰線期間が出力されている(帰線期間は"H"、描画期間は"L")。
 1フレーム262ラインの内、192ラインが"L"、70ラインが"H"(MODE2)
 1フレーム262ラインの内、200ラインが"L"、62ラインが"H"(MODE5)


 調査していませんが、66/66SRも、mk2/mk2SRと同等だと思います。
 (カスタムLSIなどが同じなので)

 特に、SRのOPNから読み出せるのが、垂直同期ではなく、帰線期間だったというのは、ちょっとびっくりです。
 (確かにちゃんと調査してませんでしたが...)


以下、調査内容の詳細です。

こんなプログラムで調査してみました。


10 REM mode2/5,page4
20 FOR J=2 TO 4
30 SCREEN3,J,J:CLS:LINE(0,0)-(319,199),J,BF
40 NEXT
1000 GOSUB 9000
1010 EXEC &HDF00
9000 AD=&HDF00
9010 READA$:IF A$="**" THEN RETURN
9020 POKEAD,VAL("&H"+A$):AD=AD+1:GOTO 9010
10100 DATAf3,31,00,df,21,e8,03,cd,2a,df,3e,00,d3,91,3e,f0
10110 DATAd3,b0,3e,ff,d3,91,21,e8,03,cd,2a,df,3e,00,d3,91
10120 DATA3e,f6,d3,b0,3e,ff,d3,91,18,da,3e,78,3d,20,fd,2b
10130 DATA7c,b5,20,f6,c9
10140 DATA**


マシン語の内容は以下の通りです。


org $df00

di
ld sp,$df00
MAINLOOP;
ld hl,1000
call W_TIME

ld a,$00
out ($91),a ; プリンタポートへ出力(デバッグ用)

ld a,$f0 ; $c000〜を表示(MODE 1-4時)SCREEN,3
; $8000〜を表示(MODE 5時)SCREEN,2
out ($b0),a

ld a,$ff
out ($91),a ; プリンタポートへ出力(デバッグ用)

ld hl,1000
call W_TIME

ld a,$00
out ($91),a ; プリンタポートへ出力(デバッグ用)

ld a,$f6 ; $a000〜を表示(MODE 1-4時)SCREEN,4
; $4000〜を表示(MODE 5時)SCREEN,3
out ($b0),a

ld a,$ff
out ($91),a ; プリンタポートへ出力(デバッグ用)

jr MAINLOOP

;
; 時間待ち(大体 2ms × HL)
;
W_TIME:
.lp1: ld a,$78
.lp2: dec a
jr nz,.lp2

dec hl
ld a,h
or l
jr nz,.lp1
ret



 プログラムは単純に違うページに違う色を付けて、ページを切り替えているだけのものです。

 ロジアナで確認したものが以下の通りです。
 信号は上から、
 トリガ(プリンタポート)
 PSG/OPNのIOA7(PSG/OPNから読み出せる値)
 VSYNC(バッファ後、外部に出力されているもの)
 HSYNC(バッファ後、外部に出力されているもの)
 R(バッファ後、外部に出力されているもの)
 G(バッファ後、外部に出力されているもの)
 B(バッファ後、外部に出力されているもの)
 H(バッファ後、外部に出力されているもの)
 です。

181202_01_mk2_mode2_1.png
 mk2 MODE2

181202_01_mk2_mode5_1.png
 mk2 MODE5


 mk2の場合、描画範囲では、MODE2/MODE5とも、すぐには画面が切り替えられずに、次のフレームで切り替わっています。

181202_01_mk2sr_mode2_1.png
 mk2SR MODE2

181202_01_mk2sr_mode5_1.png
 mk2SR MODE5


 mk2SRの場合、描画範囲では、MODE2/MODE5とも、すぐに画面が切り替わっています。
 さらに、IOA7が描画範囲では"L"になっているのが分かると思います。


 さらに、VSYNCの前後で、画面を切り替えた時に、どこで反映されるかを確認しました。

181202_01_mk2_mode2_2.png
 mk2 MODE2 VSYNC後

181202_01_mk2_mode5_2.png
 mk2 MODE5 VSYNC後

 VSYNCの後に画面切り替えを指示した場合、その次のフレームで画面が切り替わっています。


181202_01_mk2_mode2_3.png
 mk2 MODE2 VSYNC前

181202_01_mk2_mode2_3.png
 mk2 MODE5 VSYNC前


 VSYNCの前に画面切り替えを指示した場合、VSYNCを跨いだ次のフレームで画面が切り替わっています。
posted by えすび at 22:56| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年12月01日

ROMアニメ再生

  唐突ですが、戦士カートリッジmk2を使ったアニメ再生ソフトを作成しました。


○何が出来るか?
128x120ドットの画像を 1/ 5 秒おきに再生します。50枚 (10秒分)再生可能です。
64x 60ドットの画像を 1/15 秒おきに再生します。200枚(13.3秒分)再生可能です。
音声は再生しません。


○動作環境
実機
 本体:PC-6001mk2、PC-6601、PC-6001mk2SR、PC-6601SR のいずれか
 拡張RAM:戦士のカートリッジmk2(新ベルーガカートリッジ)

エミュレータ
 PC-6001V ver 1.25
 PC-6001VW ver4.00 (2018/10/27)


 詳しい事は同梱のドキュメントを参照して下さい。


128x120ドットの画像を 1/ 5 秒おきに再生
181201_02_romanime_128x120_f5.zip

64x 60ドットの画像を 1/15 秒おきに再生
181201_02_romanime_64x60_f15.zip


 1/15秒おきは、動画再生カートリッジと同じ再生速度です。画面小さいですが(^^;)

posted by えすび at 20:04| Comment(1) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

画面がちらつく問題

  P6でキャラ描画時にちらつく問題ですが、何となく理由がわかりました。
 (うちのプログラムの問題ではないので、同じ理由かどうかわかりませんが)


  ちらつきを避けるために2画面を使って以下のようなプログラムをしたとします。
  mk2以降は、垂直同期が検出できるために、それも使った場合です。


VSYNC=H→Lになるまで待つ
 ↓
画面1を表示する
画面2内で、キャラを消し、新しいキャラクタを描く
 ↓
VSYNC=H→Lになるまで待つ
 ↓
画面2を表示する
画面1内で、キャラを消し、新しいキャラクタを描く
 ↓
最初に戻る



 実際にプログラムに落とすと以下のような感じです(実際に作ったものを修正しています)。



di
; レジスタ0x07(ミキサ)の上位2ビットを設定する(B:出力、A:入力)
ld a,$07
out ($a0),a
ld a,$bf
out ($a1),a

; レジスタ0x0eから読み出す設定にする
ld a,$0e
out ($a0),a

call WAIT_VSYNC ; 垂直同期がH→Lになるまで待つ
call WAIT_VSYNC ; 垂直同期がH→Lになるまで待つ
call WAIT_VSYNC ; 垂直同期がH→Lになるまで待つ(*1)

MAINLOOP:

ld a,$f6 ; $4000〜を表示(画面2を表示)
out ($b0),a

ld de,$0000 ; $0000に描画する(画面1に描画)
call DRAWPAGE

call WAIT_VSYNC ; 垂直同期がH→Lになるまで待つ
call WAIT_VSYNC ; 垂直同期がH→Lになるまで待つ
call WAIT_VSYNC ; 垂直同期がH→Lになるまで待つ(*1)

ld a,$f4 ; $0000〜を表示(画面1を表示)
out ($b0),a ;

ld de,$4000 ; $4000に描画する(画面2に描画)
call DRAWPAGE

call WAIT_VSYNC ; 垂直同期がH→Lになるまで待つ
call WAIT_VSYNC ; 垂直同期がH→Lになるまで待つ
call WAIT_VSYNC ; 垂直同期がH→Lになるまで待つ(*1)

jp MAINLOOP


;
; 垂直同期がH→Lになるまで待つ
;
WAITVSYNC:
.lp1:
in a,($a2)
rlca
jr nc,.lp1 ; 垂直同期がHになるまで待つ
.lp2:
in a,($a2)
rlca
jr c,.lp2 ; 垂直同期がLになるまで待つ
ret




 DRAWPAGE は、データのブロック転送で、数フレーム分の時間が掛かります。

 これを実際に動かしてみると、描画画面上部の方がちらついて表示されます。
 よーく見てみると、画面が切り換わっていない感じでした。

 エミュレータではちらつきが出ません。また、SR以降でも問題なく表示されます。


 予想なのですが、理由は以下のようです。

 ポート0xb0に出力して表示ページを変更しています。
 これが即時に変更されるのではなく、垂直同期がH→Lになった時に変更されているようです。

 プログラムでは、垂直同期がH→Lを検出して表示ページを変更しているので、結局1フレーム後に表示ページが変更されてしまっているようです。

 ロジアナを使ってちゃんと確認しないといけないんですが...そのうちに(^^;)


 上記プログラムの(*1)の部分を、下記のように、『垂直同期がH→Lのちょっと前』のタイミングを検出する事で、ちらつきがなくなりました。

 他のプログラムで同様の事をする場合、どのようにするのがベストかは考える必要があります。


 (*1)の call WAIT_VSYNC を、call WAIT_flrame として、以下のように変更。



;
; 描画範囲分待つ
; VSYNC が H→L から、大体描画範囲が終わるぐらいまで待つ
;
; VSYNC:H→L(ライン#0)
; 描画範囲:ライン#33〜#232
;
; ライン# 0〜# 32:912clk@14.32MHz
; ライン#33〜#232:176clk@14.32MHz
;
; 合計:33x912+200x176 = 65296clk@14.32MHz = 18239clk@4MHz
;
WAIT_flame:
push af
push bc

ld bc,345
.lp1:
push bc ; 11+1 / 12
pop bc ; 10+1 / 23
dec bc ; 6+1 / 30
ld a,b ; 4+1 / 35
or c ; 4+1 / 40
jr nz,.lp1 ; 12+1 / 53

pop bc
pop af
ret





posted by えすび at 14:35| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年11月10日

画面がちらつく事について

  P6でキャラ描画時にちらつく問題ですが...

  普通はキャラ描画時には、

 キャラを消す(背景を描く)
 ↓
 新しいキャラクタを描く

  を1画面内で行うため、描画タイミングによっては、キャラが消えている瞬間と、キャラが描画されている瞬間の両方が表示されるために、キャラがちらつくという現象が発生すると思います。

  P6の場合、この現象を抑えるために2画面を使用している事が多いです。

 画面1を表示する
 ↓
 画面2内で、キャラを消し、新しいキャラクタを描く
 ↓
 画面2を表示する
 ↓
 画面1内で、キャラを消し、新しいキャラクタを描く
 ↓
 画面1を表示する(最初に戻る)


  この時、画面1→画面2に表示を切り替えるのを、垂直帰線期間で切り替えるのがベストですが、描画中でもそこまで画面がちらつく事はありません。

  と思うのですが、どうでしょうか?


posted by えすび at 14:32| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年11月09日

同期信号検出について

  P6の垂直同期信号検出についてまとめました。
  いろいろ飛び交っているようなので(^^;)

1.初代機

  垂直同期は普通では検出不可です。
  ブログの前の記事では、サブCPUを使って無理やり検出してますが、実際にプログラムで使用するのにはちょっと難しいです。


2.mk2/66

  垂直同期、水平同期は、PSGのジョイスティックポートから読み出す事が出来ます。
  MODE1〜5のどのモードでも読み出せます。


; ジョイスティックポートにアクセスする
;

: レジスタ0x07(ミキサ)の上位2ビットを設定する(B:出力、A:入力)
; BASICではA、Bとも入力になっているため変更が必要
ld a,$07
out ($a0),a
ld a,$bf
out ($a1),a

; レジスタ0x0fに0xc0を出力(ジョイスティック1、8ピンに"L"を出力)
ld a,$0f
out ($a0),a
ld a,$c0
out ($a1),a

; レジスタ0x0eからジョイスティックポートを読み出す
ld a,$0e
out ($a0),a
in a,($a2)


  この状態で、Aregには、

  Areg[7-0]:垂直同期 水平同期 TRG2 TRG1 右 左 下 上

  が返ってきます。


  ただし...

  検出できる垂直同期は、垂直帰線期間の始まりとかではなく、どちらかというと単なるタイミング信号です。

  具体的には、画面走査線のカウンタ値で示すと以下の通りです。


  画面走査線カウンタ(0〜261)

   0〜 2:垂直同期="L"
   3〜261:垂直同期="H"
  37〜228:画面描画範囲


  帰線期間のちょうど真ん中辺りのタイミングのため、ちょっと使いづらいです。

  また、水平同期に関してはパルス幅が14MHzで64クロックしかなく、CPUからまともに検出する事が難しいです。


3.mk2SR/66SR

  mk2/66と同じ手順で垂直同期、水平同期は、PSGのジョイスティックポートから読み出す事が出来ます。
  MODE1〜6のどのモードでも読み出せます。

  さらに垂直同期をトリガにした割り込みが使用できます。

  ただし、あくまでも垂直同期で、垂直帰線期間の始まりとかではありません。


posted by えすび at 23:38| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年06月17日

SR画面周り(8)

  P6月間企画(その17)

  SRモードでの画面周りについて、の続きです。

  今回は、横640ドットのグラフィックモードについて、その2です。


○グラフィックモード640×200/640x204ドット

4)ビットマップモード

 『Y座標をポート0xCE、X座標をアドレスで指定』する事で、指定のXY座標の位置にドットを描く』のは、横320ドットの場合ですが、この回路をそのまま横640ドットの場合にも使っているために、分かりにくい動作になっています。

 VRAMアドレスを示す時に4バイト単位で見ましたが、その4バイト単位で同じ回路を使って、横320ドットと横640ドットの表示がされているようです。


180617_01_ビットマップアクセス320.png

 横320ドットの場合、上図の1ドット単位でアクセスが出来るように、ビットマップモード用変換回路が動作します。
 X座標とY座標を個別に指定し、図内の太線四角枠が一度に指定するドットになります。横320ドットの場合は、一度に指定するドットは1ドットです。


 同じ回路を使うため、横640ドットのビットマップモードで、一度に指定するドットは下図のようになります。

180617_01_ビットマップアクセス640.png


 図内の太線四角枠が一度に指定するドットになります。横640ドットの場合は、一度に指定するドットは、B/Rプレーンのいずれかの4ドットです。
 つまり、2回指定しないと4ドットの色を全部決める事はできませんし、1ドット単位で設定する事はできません。

 さらに、枠内の(0,0)などは指定する時のXY座標です。Y座標は実際のY座標と一致するのですが、X座標は一致しません。

 実際の座標(x,y)、指定座標(X,Y) とすると、以下の通りになります。

 X,Y = 0,0 の時、x = 4〜 7, y = 0 のプレーンB
 X,Y = 1,0 の時、x = 0〜 3, y = 0 のプレーンB
 X,Y = 2,0 の時、x = 4〜 7, y = 0 のプレーンR
 X,Y = 3,0 の時、x = 0〜 3, y = 0 のプレーンR
 X,Y = 0,1 の時、x = 4〜 7, y = 1 のプレーンB
 X,Y = 1,1 の時、x = 0〜 3, y = 1 のプレーンB
 X,Y = 2,1 の時、x = 4〜 7, y = 1 のプレーンR
 X,Y = 3,1 の時、x = 0〜 3, y = 1 のプレーンR

 X,Y = 4,0 の時、x = 12〜15, y = 0 のプレーンB
 X,Y = 5,0 の時、x = 8〜11, y = 0 のプレーンB
 X,Y = 6,0 の時、x = 12〜15, y = 0 のプレーンR
 X,Y = 7,0 の時、x = 8〜11, y = 0 のプレーンR
 X,Y = 4,1 の時、x = 12〜15, y = 1 のプレーンB
 X,Y = 5,1 の時、x = 8〜11, y = 1 のプレーンB
 X,Y = 6,1 の時、x = 12〜15, y = 1 のプレーンR
 X,Y = 7,1 の時、x = 8〜11, y = 1 のプレーンR
  :
 以下同様です。

 一般化すると、

 指定座標(X,Y) (ただし、X=4*n n=0,1,2,…,159)の時

 X+0,Y の時、x = X*2+4 〜X*2+7, y = Y のプレーンB
 X+1,Y の時、x = X*2+0 〜X*2+3, y = Y のプレーンB
 X+2,Y の時、x = X*2+4 〜X*2+7, y = Y のプレーンR
 X+3,Y の時、x = X*2+0 〜X*2+3, y = Y のプレーンR

 となります。

 横640ドットなのですが、実際にX座標に指定する値は、0〜319という事になります。


5)ビットマップモードで
・Y座標の設定を204以上にした場合はどうなる?
・X座標の設定を320以上にした場合はどうなる?

 横320ドットと同じです。


6)ビットマップモードで
・ポート0xC8のビット3でイネーブル/ディセーブルの切換だけど、ビット4のビットマップページ指定との関係は?
・メモリ割り当てと同時に使うとどうなる?
・そもそもビットマップモードとは?

 横320ドットと同じです。


7)それぞれのモードの利点

 基本的に横320ドットと同じなのですが、ビットマップモードの利点である『ドット単位で扱える』事がなくなっており、さらに、直接アクセスモードの方が分かりやすくなっています。

 あくまでも横320ドットが基本で、横640ドットは付け足しのような印象です。


posted by えすび at 21:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年06月16日

SR画面周り(7)

  P6月間企画(その16)

  SRモードでの画面周りについて、の続きです。

  今回は、横640ドットのグラフィックモードについて、その1です。


○グラフィックモード640×200/640x204ドット

1)縦ドット数について
2)ビットマップモード、直接アクセスモードについて

 横320ドットと同じです。


3)VRAMアドレス(直接アクセスモード)

 横640ドットの場合、1ドット=2ビットで、1バイトに4ドット収容されます。

 ビット順は、
 1バイト目:b7-0 = B7 B6 B5 B4 B3 B2 B1 B0
 2バイト目:b7-0 = R7 R6 R5 R4 R3 R2 R1 R0
 です。

 HとRは、ポート0xC0で指定され、bit1:CSS2 =H、bit0:CSS1 =G、になります(CSS3=0時)。

 ですが...CSS3=0、CSS2=1、CSS1=1、で使うべきです。

 この組み合わせの場合、HGRB=1100、1101、1110、1111、の4色が出力されますが、これは全てパレットで変換できる色に当たります。そのため、16色中任意の4色を出力できる設定になります。


 VRAMアドレスは、横320ドットと同じ、ページ#0が0x0000〜0x7FFF、ページ#1が0x8000〜0xFFFFです(割り当ての変更がない場合)。
 以下、ページ#0についてで、X座標0〜639、Y座標0〜203とします。


 X,Y = 0,0 は、0x1A00、0x1A01 のbit7
 X,Y = 1,0 は、0x1A00、0x1A01 のbit6
 X,Y = 2,0 は、0x1A00、0x1A01 のbit5
 X,Y = 3,0 は、0x1A00、0x1A01 のbit4
 X,Y = 4,0 は、0x1A00、0x1A01 のbit3
 X,Y = 5,0 は、0x1A00、0x1A01 のbit2
 X,Y = 6,0 は、0x1A00、0x1A01 のbit1
 X,Y = 7,0 は、0x1A00、0x1A01 のbit0
 X,Y = 0,1 は、0x1A02、0x1A03 のbit7
 X,Y = 1,1 は、0x1A02、0x1A03 のbit6
 X,Y = 2,1 は、0x1A02、0x1A03 のbit5
 X,Y = 3,1 は、0x1A02、0x1A03 のbit4
 X,Y = 4,1 は、0x1A02、0x1A03 のbit3
 X,Y = 5,1 は、0x1A02、0x1A03 のbit2
 X,Y = 6,1 は、0x1A02、0x1A03 のbit1
 X,Y = 7,1 は、0x1A02、0x1A03 のbit0

 X,Y = 0,2 は、0x1A04、0x1A05 のbit7
 X,Y = 1,2 は、0x1A04、0x1A05 のbit6
 X,Y = 2,2 は、0x1A04、0x1A05 のbit5
 X,Y = 3,2 は、0x1A04、0x1A05 のbit4
 X,Y = 4,2 は、0x1A04、0x1A05 のbit3
 X,Y = 5,2 は、0x1A04、0x1A05 のbit2
 X,Y = 6,2 は、0x1A04、0x1A05 のbit1
 X,Y = 7,2 は、0x1A04、0x1A05 のbit0
 X,Y = 0,3 は、0x1A06、0x1A07 のbit7
 X,Y = 1,3 は、0x1A06、0x1A07 のbit6
 X,Y = 2,3 は、0x1A06、0x1A07 のbit5
 X,Y = 3,3 は、0x1A06、0x1A07 のbit4
 X,Y = 4,3 は、0x1A06、0x1A07 のbit3
 X,Y = 5,3 は、0x1A06、0x1A07 のbit2
 X,Y = 6,3 は、0x1A06、0x1A07 のbit1
 X,Y = 7,3 は、0x1A06、0x1A07 のbit0
  :

 以下省略しますが、4バイト単位(横320ドット時8ドット単位、横640ドット時16ドット単位)で見ると、アドレシングは横320ドットと同じになります。


 つまり

 横640ドット:X = 8*m, Y = 2*n
 横320ドット:x = 4*m, Y = 2*n

 が同じアドレスになります。


 例えば、

 横640ドット X,Y = 0,0
 横320ドット x,y = 0,0

 横640ドット X,Y = 0,202
 横320ドット x,y = 0,202

 横640ドット X,Y = 624,0
 横320ドット x,y = 312,0

 横640ドット X,Y = 624,202
 横320ドット x,y = 312,202

 などです。


 4バイト単位に関して、それぞれのモードを図示すると、以下のようになります。


180616_01_VRAM640.png

 横640ドットの場合は、VRAMメモリの状態がそのままXY座標になるので理解しやすいのですが...


180616_01_VRAM320.png

 横320ドットの場合は、VRAMメモリの状態とXY座標が入れ替わったりするので、直感的に理解しにくいです。

posted by えすび at 21:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年06月15日

SR画面周り(6)

  P6月間企画(その15)

  SRモードでの画面周りについて、の続きです。

  今回は、横320ドットのグラフィックモードについて、その4です。


○グラフィックモード320×200/320x204ドット

7)それぞれのモードの利点

○一度にアクセスするビット数が多い(直接アクセスモード)
 画面の描画をする際に、1命令で1ドット描く(ビットマップモード)か、2ドット描く(直接アクセスモード)の違いです。単純に2倍の速さが可能になります。

○ドット単位で扱える(ビットマップモード)
 背景絵+キャラクタなどの重ね合わせ処理などが容易に出来るのがビットマップモードです。
 (多分、これがビットマップモードの本来の目的だと思われます)
 直接アクセスモードの場合は、一度VRAMの内容を読み出して、ANDを取ってORを取る、という処理が必要になります。

○アドレス計算がし易い(ビットマップモード)
 XY座標で指定できるビットマップモードに比べて、アドレスが不連続かつ難解な直接アクセスモードでは、目的の場所を算出するのも大変だったりします。

○アドレス空間が狭い(ビットマップモード)
 X座標は、通常0〜319の範囲で指定します。

 そのため、CPUから見たアドレス空間としては、せいぜい0〜511(0x0000〜0x01FF)だけをVRAMアドレスとして割り当てればいい事になります。
 一方、直接アクセスモードでは、0x0000〜0x7FFFのアドレス空間を消費してします。

 さらに、リード/ライト割り当て設定を使えば、もっと便利なものになります。


 例えば、通常のSR-BASICの状態は

リード:
 0x0000〜0x7FFF:BASIC-ROM
 0x8000〜0x9FFF:RAM(0x8000〜0x9FFF)
 0xA000〜0xBFFF:RAM(0xA000〜0xBFFF)
 0xC000〜0xDFFF:RAM(0xC000〜0xDFFF)
 0xE000〜0xFFFF:RAM(0xE000〜0xFFFF)

ライト:
 0x0000〜0x7FFF:RAM(0x0000〜0x7FFF)
 0x8000〜0x9FFF:RAM(0x8000〜0x9FFF)
 0xA000〜0xBFFF:RAM(0xA000〜0xBFFF)
 0xC000〜0xDFFF:RAM(0xC000〜0xDFFF)
 0xE000〜0xFFFF:RAM(0xE000〜0xFFFF)

 ですが、


リード:
 0xC000〜0xDFFF:RAM(0x0000〜0x1FFFを割り当てる)

ライト:
 0xC000〜0xDFFF:RAM(0x0000〜0x1FFFを割り当てる)


 とすると、BASIC-ROMは見えた状態で、VRAMにアクセスする事が出来ます。これにより、割り込み禁止をせずに、画面描画が可能になります。
 あ、当然、0xC000〜0xDFFFに本来あるRAMには、このままではアクセスできませんよ。


 利点が多いビットマップモードですが、速度を上げるために直接アクセスモードを使う事も多々あります。88版のソフトからの移植では、片方だけでなく両方のモードを使う事がほとんどです。


posted by えすび at 21:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年06月14日

SR画面周り(5)

  P6月間企画(その14)

  SRモードでの画面周りについて、の続きです。

  今回は、横320ドットのグラフィックモードについて、その3です。


○グラフィックモード320×200/320x204ドット

5)ビットマップモードで
・Y座標の設定を204以上にした場合はどうなる?
・X座標の設定を320以上にした場合はどうなる?

 実機でプログラムを組んでみて、調査しました。
 VRAMを全面0x00クリアした後に、XY座標を指定して描画し、VRAMのどこにセットされるかを見ています。

bitmap.zip


 結果をまとめると以下の通りです。

 X座標:
  下位10ビットのみ演算対象
  0x0000〜0x013F(=319)の時は、そのまま
  0x0140〜0x027F(=639)の時は、0x0140(=320)を引いた値で算出
  0x0280〜0x03FF の時は、演算結果が信用できない

  下位10ビットのみ演算対象のため、0x0400〜0x7FFFは上記0x0000〜0x03FFのイメージが出力されます。


 Y座標:
  下位9ビットのみ演算対象
  0x0000〜0x00CB(=203)の時は、そのまま
  0x00CC〜0x0197(=407) の時は、0x00CC(=204)を引いた値で算出
  0x0198〜0x01FF の時は、演算結果が信用できない

  下位9ビットのみ演算対象のため、0x0200〜0x7FFFは上記0x0000〜0x01FFのイメージが出力されます。


  通常は、範囲外を超えた設定を行わないと思います。しかし、この範囲外を超えた設定の時に、X座標は320、Y座標は204を引かれる処理は、プログラムで有効に使う事ができます。


  例えば、8x8のキャラクタ描画ルーチンを作る場合...

================================

ld hl,PATTERN ; パターン先頭
ld de,XADD ; X座標先頭
ld (.xpt+1),XADD

ld c,YADD ; Y座標先頭
ld b,8
.lp1:
push bc
ld a,c
out (0xCE),a

.xpt: ld de,0x0000
ldi
ldi
ldi
ldi
ldi
ldi
ldi
ldi

pop bc
inc c
djnz .lp1

================================

  こんな感じだと思います。

  通常の320x204で表示する場合は、X=0〜311、Y=0〜195 を指定すれば、画面全体にキャラクタを表示する事ができます。しかし、スクロールなどをしている場合は、X=311→X=0や、Y=203→Y=0のラインをまたぐようなキャラクタを描画する必要がありますよね?

  この場合に、上のようなプログラムで、X=0〜319、Y=0〜203を指定するだけで、場合分けをせずに描画が可能になります。これは、上のプログラム実行の途中に、X座標が320以上、Y座標が204以上になっても、X座標は320、Y座標は204を引かれる処理が行われているからです。


 注意)X座標が320以上、Y座標が204以上 は、エミュレータでは同じ動作をするかどうかはわかりません。



6)ビットマップモードで
・ポート0xC8のビット3でイネーブル/ディセーブルの切換だけど、ビット4のビットマップページ指定との関係は?
・メモリ割り当てと同時に使うとどうなる?
・そもそもビットマップモードとは?


 まず、VRAMとは、から。

 SRモードでのVRAMとは、0x0000〜0x7FFF(ページ0)、0x8000〜0xFFFF(ページ1)のアドレスを持っており、設定されているメモリの内容を画面に描くものです。

 ここで挙げている、0x0000〜0x7FFF、0x8000〜0xFFFF、というアドレスですが、SRの場合は直接CPUアドレスと繋がっていません。初代/mk2/66の場合は、直接CPUアドレスと繋がっているので、ややこしくないんですが...

 ビットマップモードの正体は、『ポート0xCE、0xCFの値(=Y座標)と、与えられたアドレス(=X座標)から、VRAMアドレスを算出する変換回路』です。

 直接アクセスモードの時は、この変換回路を使わずに、与えられたアドレス=VRAMアドレスになります。


 さらに、CPUから与えられるアドレスは、ポート0x60〜0x6Fのリード/ライト割り当て設定により変換されます。

 図に描くとこんな感じです。

180614_01_ビットマップモード.png


 CPUから与えられたアドレスは、まずリード/ライト割り当て設定で変換され、その後にビットマップモードで変換されます。直接アクセスモードの時は、リード/ライト割り当て設定のみで変換されます。


 また、ポート0xC8は、

 bit4:ビットマップページ指定(0:ページ0(0x0000〜0x7FFF)/1:ページ1(0x8000〜0xFFFF))
 bit3:ビットマップモード(0:イネーブル/1:ディセーブル(直接アクセスモード))

 なのですが、

 bit4=0、bit3=0 の時、ページ0(0x0000〜0x7FFF)にアクセスする時に、ビットマップモードで変換される
 bit4=1、bit3=0 の時、ページ1(0x8000〜0xFFFF)にアクセスする時に、ビットマップモードで変換される
 bit4=0、bit3=1 の時、直接アクセスモードなので、変換されない
 bit4=1、bit3=1 の時、直接アクセスモードなので、変換されない

 です。

 このビットマップモードの変換回路は1つしかないため、bit4を変更すると変換の対象も変更されます。

 bit4=0、bit3=0 を設定した後に、bit4=1、bit3=0 を設定すると、ページ0、ページ1ともビットマップモードになりそうなんですが、変換回路が一つしかないため、後に設定したページ1のみがビットマップモードになります。


posted by えすび at 21:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年06月13日

SR画面周り(4)

  P6月間企画(その13)

  SRモードでの画面周りについて、の続きです。

  今回は、横320ドットのグラフィックモードについて、その2です。


○グラフィックモード320×200/320x204ドット

4)ビットマップモード
 前にも書きましたが、『Y座標をポート0xCE、X座標をアドレスで指定』する事で、指定のXY座標の位置にドットを描きます。
 指定したアドレスに対してデータを書き込めばドットを描き、読み出せばそのドットの色が分かるというものです。

 1ドット=4ビットなので、以下のようになります。

 書き込み時:
  bit7-4:何でもよい
  bit3-0:HGRB

 読み出し時:
  bit7-4:不定
  bit3-0:HGRB


 例1:X,Y = 0,0 に、赤のドットを描く

ld a,0x00 ; Y座標
out (0xCE),a
ld a,0x02 ; 赤
ld (0x0000),a ; X座標


 例2:X,Y = 1,1 と X,Y = 2,1 のドットの色が同じかどうかを調べる

ld a,0x01 ; Y座標
out (0xce),a
ld a,(0x0001) ; X,Y = 1,1 を読み出す
and $0f ; 不定部分を削除
ld b,a
ld a,(0x0002) ; X,Y = 2,1 を読み出す
and $0f ; 不定部分を削除
cp b ; 比較


 例2のように、読み出した値を比較するなどをする場合は、不定部分をマスクする必要があります。


 この説明だけだと、直接アドレスモードよりもビットマップモードの方が単純だと考えそうなのですが...いろいろと疑問点が出てきますよね?

・Y座標の設定を204以上にした場合はどうなる?
・X座標の設定を320以上にした場合はどうなる?
・ポート0xC8のビット3でイネーブル/ディセーブルの切換だけど、ビット4のビットマップページ指定との関係は?
・メモリ割り当てと同時に使うとどうなる?
・そもそもビットマップモードとは?

 などなど。

 この答えは次回に(^^;)/
 
posted by えすび at 21:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年06月12日

SR画面周り(3)

  P6月間企画(その12)

  SRモードでの画面周りについて、続きです。

  今回は、横320ドットのグラフィックモードについて、その1です。


○グラフィックモード320×200/320x204ドット

1)縦ドット数について
 横320ドットの場合、縦は200ドットか204ドットになります。ポート0xC1のbit0で切り替えます。

 縦200ドットの場合は、『下4ドットが表示されない状態』です。

 スクロールした場合は、
  スクロールY座標が 0の場合:Y座標が0-203の内、0-199が表示される
  スクロールY座標が10の場合:Y座標が0-203の内、10-203,0-5が表示される
 となります。

2)ビットマップモード、直接アクセスモードについて
 ポート0xC8のbit3を0にすると、ビットマップモードがイネーブル(有効)になります。
 ポート0xC8のbit3を1にすると、ビットマップモードがディセーブル(無効)になります。

 呼び名が長いので、私は『ビットマップモード』『直接アクセスモード』と呼んでいます。
 (ビットアクセスモード、と言っているかも...)


 大雑把に言うと...

・ビットマップモード:
 Y座標をポート0xCE、X座標をアドレスで指定する。
 4ビット単位でVRAMに読み書きする。

・直接アクセスモード:
 VRAMのアドレスを直接指定する。
 8ビット単位でVRAMに読み書きする。


 直接アクセスモードは、VRAMアドレスが変な事以外は、ビットマップモードより理解しやすいと思います。


3)VRAMアドレス(直接アクセスモード)
 アドレシングがヘン&バグのために、すごくわかりにくいです...

 横320ドットの場合、1ドット=4ビットで、1バイトに2ドット収容されます。
 ビット順は、b7-4=HGRB / b3-0=HGRB です。

 VRAMアドレスは、ページ#0が0x0000〜0x7FFF、ページ#1が0x8000〜0xFFFFです(割り当ての変更がない場合)。
 以下、ページ#0についてで、X座標0〜319、Y座標0〜203とします。

○Xが256未満の場合
 X,Y = 0,0 は、0x1A00 の下位4ビット
 X,Y = 1,0 は、0x1A00 の上位4ビット
 X,Y = 2,0 は、0x1A01 の下位4ビット
 X,Y = 3,0 は、0x1A01 の上位4ビット
 X,Y = 0,1 は、0x1A02 の下位4ビット
 X,Y = 1,1 は、0x1A02 の上位4ビット
 X,Y = 2,1 は、0x1A03 の下位4ビット
 X,Y = 3,1 は、0x1A03 の上位4ビット

 X,Y = 4,0 は、0x1A000x1A04 の下位4ビット
 X,Y = 5,0 は、0x1A000x1A04 の上位4ビット
 X,Y = 6,0 は、0x1A010x1A05 の下位4ビット
 X,Y = 7,0 は、0x1A010x1A05 の上位4ビット
 X,Y = 4,1 は、0x1A020x1A06 の下位4ビット
 X,Y = 5,1 は、0x1A020x1A06 の上位4ビット
 X,Y = 6,1 は、0x1A030x1A07 の下位4ビット
 X,Y = 7,1 は、0x1A030x1A07 の上位4ビット
  :
 X,Y = 252,0 は、0x1AFC の下位4ビット
 X,Y = 253,0 は、0x1AFC の上位4ビット
 X,Y = 254,0 は、0x1AFD の下位4ビット
 X,Y = 255,0 は、0x1AFD の上位4ビット
 X,Y = 252,1 は、0x1AFE の下位4ビット
 X,Y = 253,1 は、0x1AFE の上位4ビット
 X,Y = 254,1 は、0x1AFF の下位4ビット
 X,Y = 255,1 は、0x1AFF の上位4ビット


 X,Y = 0,2 は、0x1B00 の下位4ビット
 X,Y = 1,2 は、0x1B00 の上位4ビット
 X,Y = 2,2 は、0x1B01 の下位4ビット
 X,Y = 3,2 は、0x1B01 の上位4ビット
 X,Y = 0,3 は、0x1B02 の下位4ビット
 X,Y = 1,3 は、0x1B02 の上位4ビット
 X,Y = 2,3 は、0x1B03 の下位4ビット
 X,Y = 3,3 は、0x1B03 の上位4ビット
  :
 X,Y = 252,2 は、0x1BFC の下位4ビット
 X,Y = 253,2 は、0x1BFC の上位4ビット
 X,Y = 254,2 は、0x1BFD の下位4ビット
 X,Y = 255,2 は、0x1BFD の上位4ビット
 X,Y = 252,3 は、0x1BFE の下位4ビット
 X,Y = 253,3 は、0x1BFE の上位4ビット
 X,Y = 254,3 は、0x1BFF の下位4ビット
 X,Y = 255,3 は、0x1BFF の上位4ビット

 以下同様で
  :
  :
 X,Y = 252,202 は、0x7FFC の下位4ビット
 X,Y = 253,202 は、0x7FFC の上位4ビット
 X,Y = 254,202 は、0x7FFD の下位4ビット
 X,Y = 255,202 は、0x7FFD の上位4ビット
 X,Y = 252,203 は、0x7FFE の下位4ビット
 X,Y = 253,203 は、0x7FFE の上位4ビット
 X,Y = 254,203 は、0x7FFF の下位4ビット
 X,Y = 255,203 は、0x7FFF の上位4ビット

 つまり、8ドット単位で
 X,Y = x+0,y+0 は、0x1A00 + 0x0100*(y/2) + x の下位4ビット
 X,Y = x+1,y+0 は、0x1A00 + 0x0100*(y/2) + x の上位4ビット
 X,Y = x+2,y+0 は、0x1A01 + 0x0100*(y/2) + x の下位4ビット
 X,Y = x+3,y+0 は、0x1A01 + 0x0100*(y/2) + x の上位4ビット
 X,Y = x+0,y+1 は、0x1A02 + 0x0100*(y/2) + x の下位4ビット
 X,Y = x+1,y+1 は、0x1A02 + 0x0100*(y/2) + x の上位4ビット
 X,Y = x+2,y+1 は、0x1A03 + 0x0100*(y/2) + x の下位4ビット
 X,Y = x+3,y+1 は、0x1A03 + 0x0100*(y/2) + x の上位4ビット
  (x は4の倍数。y は2の倍数)

 となります。


○X座標が256以上の場合
 256未満の場合と同じ8ドット単位ですが...

 X,Y = 256,0 は、0x0000 の下位4ビット
 X,Y = 257,0 は、0x0000 の上位4ビット
 X,Y = 258,0 は、0x0001 の下位4ビット
 X,Y = 259,0 は、0x0001 の上位4ビット
 X,Y = 256,1 は、0x0002 の下位4ビット
 X,Y = 257,1 は、0x0002 の上位4ビット
 X,Y = 258,1 は、0x0003 の下位4ビット
 X,Y = 259,1 は、0x0003 の上位4ビット
  :
 X,Y = 316,0 は、0x003C の下位4ビット
 X,Y = 317,0 は、0x003C の上位4ビット
 X,Y = 318,0 は、0x003D の下位4ビット
 X,Y = 319,0 は、0x003D の上位4ビット
 X,Y = 316,1 は、0x003E の下位4ビット
 X,Y = 317,1 は、0x003E の上位4ビット
 X,Y = 318,1 は、0x003F の下位4ビット
 X,Y = 319,1 は、0x003F の上位4ビット

 X,Y = 256,2 は、0x0100 の下位4ビット
 X,Y = 257,2 は、0x0100 の上位4ビット
 X,Y = 258,2 は、0x0101 の下位4ビット
 X,Y = 259,2 は、0x0101 の上位4ビット
 X,Y = 256,3 は、0x0102 の下位4ビット
 X,Y = 257,3 は、0x0102 の上位4ビット
 X,Y = 258,3 は、0x0103 の下位4ビット
 X,Y = 259,3 は、0x0103 の上位4ビット
  :
 X,Y = 316,2 は、0x013C の下位4ビット
 X,Y = 317,2 は、0x013C の上位4ビット
 X,Y = 318,2 は、0x013D の下位4ビット
 X,Y = 319,2 は、0x013D の上位4ビット
 X,Y = 316,3 は、0x013E の下位4ビット
 X,Y = 317,3 は、0x013E の上位4ビット
 X,Y = 318,3 は、0x013F の下位4ビット
 X,Y = 319,3 は、0x013F の上位4ビット

 X,Y = 256,4 は、0x0040 の下位4ビット
 X,Y = 257,4 は、0x0040 の上位4ビット
 X,Y = 258,4 は、0x0041 の下位4ビット
 X,Y = 259,4 は、0x0041 の上位4ビット
 X,Y = 256,5 は、0x0042 の下位4ビット
 X,Y = 257,5 は、0x0042 の上位4ビット
 X,Y = 258,5 は、0x0043 の下位4ビット
 X,Y = 259,5 は、0x0043 の上位4ビット
  :
 X,Y = 316,4 は、0x007C の下位4ビット
 X,Y = 317,4 は、0x007C の上位4ビット
 X,Y = 318,4 は、0x007D の下位4ビット
 X,Y = 319,4 は、0x007D の上位4ビット
 X,Y = 316,5 は、0x007E の下位4ビット
 X,Y = 317,5 は、0x007E の上位4ビット
 X,Y = 318,5 は、0x007F の下位4ビット
 X,Y = 319,5 は、0x007F の上位4ビット

 とわかりにくくなっています。

 長くなりますが8ビット単位の先頭だけを書き出すと、

 X,Y = 256, 0 は、0x0000 の下位4ビット
 X,Y = 256, 2 は、0x0100 の下位4ビット
 X,Y = 256, 4 は、0x0040 の下位4ビット
 X,Y = 256, 6 は、0x0140 の下位4ビット
 X,Y = 256, 8 は、0x0080 の下位4ビット
 X,Y = 256, 10 は、0x0180 の下位4ビット
 X,Y = 256, 12 は、0x00C0 の下位4ビット
 X,Y = 256, 14 は、0x01C0 の下位4ビット

 X,Y = 256, 16 は、0x0200 の下位4ビット
 X,Y = 256, 18 は、0x0300 の下位4ビット
 X,Y = 256, 20 は、0x0240 の下位4ビット
 X,Y = 256, 22 は、0x0340 の下位4ビット
 X,Y = 256, 24 は、0x0280 の下位4ビット
 X,Y = 256, 26 は、0x0380 の下位4ビット
 X,Y = 256, 28 は、0x02C0 の下位4ビット
 X,Y = 256, 30 は、0x03C0 の下位4ビット

 X,Y = 256, 32 は、0x0400 の下位4ビット
 X,Y = 256, 34 は、0x0500 の下位4ビット
 X,Y = 256, 36 は、0x0440 の下位4ビット
 X,Y = 256, 38 は、0x0540 の下位4ビット
 X,Y = 256, 40 は、0x0480 の下位4ビット
 X,Y = 256, 42 は、0x0580 の下位4ビット
 X,Y = 256, 44 は、0x04C0 の下位4ビット
 X,Y = 256, 46 は、0x05C0 の下位4ビット

 X,Y = 256, 48 は、0x0600 の下位4ビット
 X,Y = 256, 50 は、0x0700 の下位4ビット
 X,Y = 256, 52 は、0x0640 の下位4ビット
 X,Y = 256, 54 は、0x0740 の下位4ビット
 X,Y = 256, 56 は、0x0680 の下位4ビット
 X,Y = 256, 58 は、0x0780 の下位4ビット
 X,Y = 256, 60 は、0x06C0 の下位4ビット
 X,Y = 256, 62 は、0x07C0 の下位4ビット

 X,Y = 256, 64 は、0x0800 の下位4ビット
 X,Y = 256, 66 は、0x0900 の下位4ビット
 X,Y = 256, 68 は、0x0840 の下位4ビット
 X,Y = 256, 70 は、0x0940 の下位4ビット
 X,Y = 256, 72 は、0x0880 の下位4ビット
 X,Y = 256, 74 は、0x0980 の下位4ビット
 X,Y = 256, 76 は、0x08C0 の下位4ビット
 X,Y = 256, 78 は、0x09C0 の下位4ビット

 X,Y = 256, 80 は、0x0A00 の下位4ビット
 X,Y = 256, 82 は、0x0B00 の下位4ビット
 X,Y = 256, 84 は、0x0A40 の下位4ビット
 X,Y = 256, 86 は、0x0B40 の下位4ビット
 X,Y = 256, 88 は、0x0A80 の下位4ビット
 X,Y = 256, 90 は、0x0B80 の下位4ビット
 X,Y = 256, 92 は、0x0AC0 の下位4ビット
 X,Y = 256, 94 は、0x0BC0 の下位4ビット

 X,Y = 256, 96 は、0x0C00 の下位4ビット
 X,Y = 256, 98 は、0x0D00 の下位4ビット
 X,Y = 256,100 は、0x0C40 の下位4ビット
 X,Y = 256,102 は、0x0D40 の下位4ビット
 X,Y = 256,104 は、0x0C80 の下位4ビット
 X,Y = 256,106 は、0x0D80 の下位4ビット
 X,Y = 256,108 は、0x0CC0 の下位4ビット
 X,Y = 256,110 は、0x0DC0 の下位4ビット

 X,Y = 256,112 は、0x0E00 の下位4ビット
 X,Y = 256,114 は、0x0F00 の下位4ビット
 X,Y = 256,116 は、0x0E40 の下位4ビット
 X,Y = 256,118 は、0x0F40 の下位4ビット
 X,Y = 256,120 は、0x0E80 の下位4ビット
 X,Y = 256,122 は、0x0F80 の下位4ビット
 X,Y = 256,124 は、0x0EC0 の下位4ビット
 X,Y = 256,126 は、0x0FC0 の下位4ビット

 X,Y = 256,128 は、0x1000 の下位4ビット
 X,Y = 256,130 は、0x1100 の下位4ビット
 X,Y = 256,132 は、0x1040 の下位4ビット
 X,Y = 256,133 は、0x1140 の下位4ビット
 X,Y = 256,136 は、0x1080 の下位4ビット
 X,Y = 256,138 は、0x1180 の下位4ビット
 X,Y = 256,140 は、0x10C0 の下位4ビット
 X,Y = 256,142 は、0x11C0 の下位4ビット

 X,Y = 256,144 は、0x1200 の下位4ビット
 X,Y = 256,146 は、0x1300 の下位4ビット
 X,Y = 256,148 は、0x1240 の下位4ビット
 X,Y = 256,150 は、0x1340 の下位4ビット
 X,Y = 256,152 は、0x1280 の下位4ビット
 X,Y = 256,154 は、0x1380 の下位4ビット
 X,Y = 256,156 は、0x12C0 の下位4ビット
 X,Y = 256,158 は、0x13C0 の下位4ビット

 X,Y = 256,160 は、0x1400 の下位4ビット
 X,Y = 256,162 は、0x1500 の下位4ビット
 X,Y = 256,164 は、0x1440 の下位4ビット
 X,Y = 256,166 は、0x1540 の下位4ビット
 X,Y = 256,168 は、0x1480 の下位4ビット
 X,Y = 256,170 は、0x1580 の下位4ビット
 X,Y = 256,172 は、0x14C0 の下位4ビット
 X,Y = 256,174 は、0x15C0 の下位4ビット

 X,Y = 256,176 は、0x1600 の下位4ビット
 X,Y = 256,178 は、0x1700 の下位4ビット
 X,Y = 256,180 は、0x1640 の下位4ビット
 X,Y = 256,182 は、0x1740 の下位4ビット
 X,Y = 256,184 は、0x1680 の下位4ビット
 X,Y = 256,186 は、0x1780 の下位4ビット
 X,Y = 256,188 は、0x16C0 の下位4ビット
 X,Y = 256,190 は、0x17C0 の下位4ビット

 X,Y = 256,192 は、0x1800 の下位4ビット
 X,Y = 256,194 は、0x1900 の下位4ビット
 X,Y = 256,196 は、0x1840 の下位4ビット
 X,Y = 256,198 は、0x1940 の下位4ビット
 X,Y = 256,200 は、0x1880 の下位4ビット
 X,Y = 256,202 は、0x1980 の下位4ビット

 0x18C0〜0x18FF、0x19C0〜0x19FFは未使用です。


 ややこしくなりますが、8ドット単位で
 X,Y = x+0,y+0 は、0x0000 + 0x0040*(y/2) + x の下位4ビット
 X,Y = x+1,y+0 は、0x0000 + 0x0040*(y/2) + x の上位4ビット
 X,Y = x+2,y+0 は、0x0001 + 0x0040*(y/2) + x の下位4ビット
 X,Y = x+3,y+0 は、0x0001 + 0x0040*(y/2) + x の上位4ビット
 X,Y = x+0,y+1 は、0x0002 + 0x0040*(y/2) + x の下位4ビット
 X,Y = x+1,y+1 は、0x0002 + 0x0040*(y/2) + x の上位4ビット
 X,Y = x+2,y+1 は、0x0003 + 0x0040*(y/2) + x の下位4ビット
 X,Y = x+3,y+1 は、0x0003 + 0x0040*(y/2) + x の上位4ビット
  (x は4の倍数。y は2の倍数)

 ここで、y と Y の関係が以下のようになります(括弧内は、ビット番号)。

 Y(0)=y(0) (=0)
 Y(1)=y(2) Y(1)=y(3)
 Y(2)=y(3) Y(2)=y(1)
 Y(3)=y(1) Y(3)=y(2)
 Y(4)=y(4)
 Y(5)=y(5)
 Y(6)=y(6)
 Y(7)=y(7)


 本来だと、0x0000、0x0040、0x0080、…、となるはずの所が、ビットが入れ替わっているんですね。
 多分バグだと思いますが...

 これのせいで、直接アクセスモードでのプログラムが煩雑になってしまいます。


posted by えすび at 21:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年06月11日

SR画面周り(2)

  P6月間企画(その11)

  SRモードでの画面周りについて、記載します。

  SRモードですので、ポート0xC8のbit0=0の時のみの記述になります。
  非SRモード(ポート0xC8のbit0=1)や、初代/mk2/66の画面周りに関しては、また別の機会に。

 注)SRモードの画面周りのI/Oポートは、SR-BASICを使う際にはBASIC側で管理されています。具体的には、VSYNC割り込みで、ワークエリアに設定した値でI/Oポートの内容を設定され直されます。
  そのため、直接I/Oポートを叩いて画面モードの変更などをする場合は、割り込み禁止にするか、ワークエリアの方に値を設定するなどが必要になります。
  テスト的に試すのであれば、割り込み禁止→設定変更→無限ループ、などの方法を採るのがいいかと思います。


  SRモードの画面種類は、大きく3つに分かれます。BASICのSCREENコマンドの第一パラメータと同じです。

 ・キャラクタモード
 ・横320ドットのグラフィックモード
 ・横640ドットのグラフィックモード

  それぞれのモードを個別に記載していきます。



○キャラクタモード
 ポート0xC1のbit2を1にするとキャラクタモードになります。
 画面は、横80列x縦25行、80x20、40x25、40x20 が設定できます。

 ポート0xC1:bit1:横文字数(0:80文字/1:40文字)
 ポート0xC8:bit2:縦行数設定(0:25行/1:20行)

 ポート0xC1、0xC8は、他のデータも設定するので、誤って設定しないように注意が必要です。

 どのページを表示させるかは、ポート0xC9で設定します。
 例えば、0xf000〜を表示させる場合は、0x0fを設定します。

 また、ポート0xC1、0xC8で画面制御を変更した場合は、関係がなくてもポート0xC9〜0xCCを設定する必要があります(関係のないポートは、0x00で構わない)。
 設定しない場合、正常動作しない場合があります。


 キャラクタ画面に文字を表示するには、VRAMにデータを書き込むだけです。
 1文字で2バイト使用します。1バイト目がキャラクタデータ、2バイト目がアトリビュートデータです。

 例えば、ポート0xC9に0x0Fを設定している場合、0xF000〜が表示されるVRAMになります。
 横方向0〜39/0〜79桁、縦方向0〜19/0〜24行とすると、

40x20
 F000/F001 F002/F003 ... F04C/F04D F04E/F04F
 F050/F051 F052/F053 ... F09C/F09D F09E/F09F
  :                  :
  :                  :
 F5A0/F5A1 F5A2/F5A3 ... F5EC/F5ED F5EE/F5EF
 F5F0/F5F1 F5F2/F5F3 ... F63C/F63D F63E/F63F

40x25
 F000/F001 F002/F003 ... F04C/F04D F04E/F04F
 F050/F051 F052/F053 ... F09C/F09D F09E/F09F
  :                  :
  :                  :
 F730/F731 F732/F733 ... F77C/F77D F77E/F77F
 F780/F781 F782/F783 ... F7CC/F7CD F7CE/F7CF

80x20
 F000/F001 F002/F003 ... F09C/F09D F09E/F09F
 F0A0/F0A1 F0A2/F0A3 ... F13C/F13D F13E/F13F
  :                  :
  :                  :
 FB40/FB41 FB42/FB43 ... FBDC/FBDD FBDE/FBDF
 FBE0/FBE1 FBE2/FBE3 ... FC7C/FC7D FC7E/FC7F

80x25
 F000/F001 F002/F003 ... F09C/F09D F09E/F09F
 F0A0/F0A1 F0A2/F0A3 ... F13C/F13D F13E/F13F
  :                  :
  :                  :
 FE60/FE61 FE62/FE63 ... FEFC/FEFD FEFE/FEFF
 FF00/FF01 FF02/FF03 ... FF9C/FF9D FF9E/FF9F

 となります。


 データ1バイト目は、キャラクタコード(いわゆるアスキーコード)、2バイト目がアトリビュートです。

 アトリビュートは、

 bit7 :グラフィックフラグ(0:ノーマル、1:セミグラフィック)
 bit6-4:背景色BGR
 bit3-0:文字色HBGR

 背景色のHは、ポート0xC0のbit1(CSS2)で与えられます。
 ポート0xC0の他のビット(CSS1、CSS3)は、キャラクタモードでは無効です。


○注意点:
1)セミグラフィックは、縦行数によって違います。
  40x20、80x20の場合、別のキャラセット(mk2/66で使用されている人間とかがあるキャラセット)が選ばれます。
  40x25の場合、80x100のセミグラフィックになります。
  80x25の場合、160x100のセミグラフィックになります(PC-8001相当)。

  セミグラフィックと言っても、単にそういうキャラセットを読み出すだけですが...

  PC-8001相当の160x100のセミグラフィックですが、ビットアサインが違います。

P6SR:
  b7 b6
  b5 b4
  b3 b2
  b1 b0

80:
  b0 b4
  b1 b5
  b2 b6
  b3 b7

  また、ハードウエアのバグがあります
  セミグラフィック使用時(40x25/80x25表示で、グラフィックフラグ=1時)に、画面右の方のキャラクタが、なぜかずれて表示されます。
  同じ場所でグラフィックフラグ=0 にしても、通常キャラクタはずれないのが不思議...


2)背景色、文字色の並びがグラフィックと違います。
  キャラクタモード :HBGR
  グラフィックモード:HGRB

  理由は不明...バグかな?

  ちなみに、H はハーフトーン、の意味だったと思います。


posted by えすび at 21:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年06月10日

SR画面周り(1)

  P6月間企画...そろそろつらい(その10)

  SRの画面周りについて、まとめてみました。
  参考文献などが入手困難のために、情報が少ない部分でもあると思います。

  とりあえず、I/Oポートを列挙しています。それぞれの詳細は後ほど。
  また、今回はSRの画面周りの紹介をしたいので、それ以外は省略しています。

  参考文献
  Mr.PCテクニカルコレクション 秀和システムトレーディング
  PC-6001mkII 解析マニュアルI 秀和システムトレーディング

  参考文献の内容を参考に、間違っている部分などは修正したつもりです。


ポート0x40〜0x4F:パレット設定
色番号13〜16に任意の色を割り当てる。

○ポート0x40:色番号16(HGRB=1111)のパレット色設定
○ポート0x41:色番号15(HGRB=1110)のパレット色設定
○ポート0x42:色番号14(HGRB=1101)のパレット色設定
○ポート0x43:色番号13(HGRB=1100)のパレット色設定

・SR以降のみに存在。
・SRモード以外でも動作可。
・書き込みのみ。

・書き込むデータは次の通り。
 bit7-4:don't care
 bit3:Hの反転
 bit2:Gの反転
 bit1:Rの反転
 bit0:Bの反転

 例えば、白色(HGRB=1111)を設定する場合は、0x00を書き込みます。


ポート0x60〜0x6F:リード/ライト割り当て設定(SRモード用)
CPUから読み出す/CPUから書き込むメモリを8K単位で任意に割り当てる。

○ポート0x60:CPUアドレス:0x0000〜0x1FFFの読み出し設定
○ポート0x61:CPUアドレス:0x2000〜0x3FFFの読み出し設定
○ポート0x62:CPUアドレス:0x4000〜0x5FFFの読み出し設定
○ポート0x63:CPUアドレス:0x6000〜0x7FFFの読み出し設定
○ポート0x64:CPUアドレス:0x8000〜0x9FFFの読み出し設定
○ポート0x65:CPUアドレス:0xA000〜0xBFFFの読み出し設定
○ポート0x66:CPUアドレス:0xC000〜0xDFFFの読み出し設定
○ポート0x67:CPUアドレス:0xE000〜0xFFFFの読み出し設定

○ポート0x68:CPUアドレス:0x0000〜0x1FFFの書き込み設定
○ポート0x69:CPUアドレス:0x2000〜0x3FFFの書き込み設定
○ポート0x6A:CPUアドレス:0x4000〜0x5FFFの書き込み設定
○ポート0x6B:CPUアドレス:0x6000〜0x7FFFの書き込み設定
○ポート0x6C:CPUアドレス:0x8000〜0x9FFFの書き込み設定
○ポート0x6D:CPUアドレス:0xA000〜0xBFFFの書き込み設定
○ポート0x6E:CPUアドレス:0xC000〜0xDFFFの書き込み設定
○ポート0x6F:CPUアドレス:0xE000〜0xFFFFの書き込み設定

・SR以降のみに存在。
・SRモードのみ動作可(非SRモード時は、ポート0xF0〜0xF2を使用する)。
・書き込みのみ。

・書き込むデータは次の通り。

 bit7-4:割り当てるメモリの種別
 bit7-4=0000:内部RAM(VRAM)
 bit7-4=0010:外部RAM(拡張RAM)
 bit7-4=1011:外部ROM1(拡張ROM(nCS2):通常、0x6000〜0x7FFFに割り当てる)
 bit7-4=1100:外部ROM2(拡張ROM(nCS3):通常、0x4000〜0x5FFFに割り当てる)
 bit7-4=1101:CGROM
 bit7-4=1110:SYSTEMROM2(音声合成/漢字)
 bit7-4=1111:SYSTEMROM1(BASIC-ROM)
 それ以外は未使用

 bit3-1:割り当てるメモリの先頭アドレス(アドレスバスA15-13に出力する値)
 bit0:常に"0"

注)通常は8K毎に割り当てが出来ますが、内部RAM(VRAM)とCGROMには、制限があります。
  (基板接続間違いのようです)

  内部RAM(VRAM)、CGROMの0x0000〜0x1FFFは、0x0000〜0x1FFF、0x4000〜0x5FFF、0x8000〜0x9FFF、0xC000〜0xDFFFにしか割り当てられない。
  内部RAM(VRAM)、CGROMの0x2000〜0x3FFFは、0x2000〜0x3FFF、0x6000〜0x7FFF、0xA000〜0xBFFF、0xE000〜0xEFFFにしか割り当てられない。

  同様に、
  内部RAM(VRAM)の0x4000〜0x5FFF、0x8000〜0x9FFF、0xC000〜0xDFFFは、0x0000〜0x1FFF、0x4000〜0x5FFF、0x8000〜0x9FFF、0xC000〜0xDFFFにしか割り当てられない。
  内部RAM(VRAM)の0x6000〜0x7FFF、0xA000〜0xBFFF、0xE000〜0xEFFFは、0x2000〜0x3FFF、0x6000〜0x7FFF、0xA000〜0xBFFF、0xE000〜0xEFFFにしか割り当てられない。



ポート0x80〜0x8F:RS-232C(8251)アクセス
●今回は省略

ポート0x90〜0x9F:8255/サブCPUアクセス
●今回は省略

 画面関連は以下の通り。
 ポート0x93に0x02を書き込み→画面OFF(画面モードによっては砂嵐)
 ポート0x93に0x03を書き込み→画面ON

ポート0xA0〜0xAF:YM-2203(SRのみ)/AY-3-8910(非SRのみ)アクセス
●今回は省略

 画面関連は以下の通り(mk2以降のみ存在)。
 ジョイスティックポートに、垂直同期、水平同期の信号が接続されています。
 OPN(PSG)のアドレス0x0eを読み出すと、垂直同期(bit7)、水平同期(bit6)が読み出せます。
 ただし、水平同期はパルス幅が短すぎるため、まともに読み取れません。

ポート0xB0〜0xBF:割り込み、CMT、FDD制御、表示VRAM(非SRモード)
●今回は省略

ポート0xC0:プリンタ、RS-232Cチェック、色の組み合わせ設定
○ポート0xC0(読み出し)
 bit1:プリンタBUSY(0:BUSY/1:READY)
 bit0:RS-232Cキャリア検出
○ポート0xC0(書き込み)
 bit7-3:don't care
 bit2:CSS3
 bit1:CSS2
 bit0:CSS1

・読み出しは全機種に存在。
・書き込みはmk2以降に存在。


ポート0xC1〜0xCF:CRTモードなど(SRモード用)

○ポート0xC1(CRTモード設定)
 bit7-4:don't care
 bit3:横ドット数(0:640ドット/1:320ドット)
 bit2:グラフィックモード(0:グラフィック/1:キャラクタ)
 bit1:横文字数(0:80文字/1:40文字)
 bit0:縦ドット数(0:204ドット/1:200ドット)

・SRモードのみ動作可。
・書き込みのみ。


○ポート0xC8(CRTコントローラ設定)
 bit7-5:don't care
 bit4:グラフィック表示ページ ビットマップページ指定(0:ページ0(0x0000〜0x7FFF)/1:ページ1(0x8000〜0xFFFF))
 bit3:ビットマップモード(0:イネーブル/1:ディセーブル(直接アクセスモード))
 bit2:縦行数設定(0:25行/1:20行)
 bit1:バスリクエスト(0:ON/1:OFF)
 bit0:CRTコントローラモード設定(0:SRモード/1:非SRモード)

・bit0、1は、全モードで動作可。bit2〜4は、SRモードのみ動作可。
・書き込みのみ。


○ポート0xC9(CRTコントローラ設定)
 bit7-4:don't care
 bit3-0:表示ページ(グラフィックモードの時は、bit3のみ有効)

・SRモードのみ動作可。
・書き込みのみ。

 テキスト表示の場合、開始アドレスの上位4ビットをbit3-0に設定する。
 例えば、0xF000〜を表示する場合は、0x0Fを書き込む。
 グラフィック表示の場合は、ページ0を表示する場合は、0x00、ページ1を表示する場合は0x08を書き込む。

注)ポート0xC1、0xC8で画面制御を変更した場合は、関係がなくてもポート0xC9〜0xCCを設定する(0x00でよい)。
  設定しない場合、正常動作しない場合がある(詳細不明)。


ポート0xCA、0xCB(スクロール設定)
○ポート0xCA
 bit7-0:X座標下位8ビット

○ポート0xCB
 bit7-1:'0'を設定する
 bit0:X座標上位1ビット

○ポート0xCC
 bit7-0:Y座標

・SRモードのみ動作可。
・書き込みのみ。

 ポート0xCA、0xCBにX、Y座標を設定すると、画面左上に(X,Y)が来るように画面がスクロールする。
 (移動距離を設定するわけではない)

注)ポート0xC1、0xC8で画面制御を変更した場合は、関係がなくてもポート0xC9〜0xCCを設定する(0x00でよい)。
  設定しない場合、正常動作しない場合がある(詳細不明)。


ポート0xCE、0xCF(ビットマップアクセスY座標指定)
ビットマップがイネーブル時のY座標を指定する
○ポート0xCE
 bit7-0:Y座標

○ポート0xCF
 bit7-0:'0'を設定する

・SRモードのみ動作可。
・書き込みのみ。

 アクセスした時のメモリアドレスがX座標になる。そのため普通は、アドレス0x0000〜0x013Fに読み書きする事で、VRAMにアクセスする事になる(詳細は別途)。
 ポート0xCFは、画面モードを変更した後に、0x00を書けば問題なく、アクセスの度に設定する必要はない。



ポート0xC1〜0xCF:CRTモードなど(非SRモード用)
●今回は省略

ポート0xD0〜0xDF:内蔵FDD/外付けFDDアクセス
●今回は省略

ポート0xE0〜0xEF:音声合成LSIアクセス
●今回は省略

ポート0xF0〜0xF2:メモリ割り当て(非SRモード用)
●今回は省略

ポート0xF3〜0xFB:割り込み制御
●今回は省略

ポート0xFC〜0xFF:拡張漢字ROMパックアクセス
●今回は省略

posted by えすび at 21:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年04月08日

P6SRの2画面切換(3)

  P6SRのグラフィック2画面切換について。

  参考プログラムを作りました。

  拡張RAMなしで動作します。エミュレータでは動作がちょっとヘンです。


sc2demo2.zip


  拡張RAMありで、ビットマップモードのものを作ろうかとも思ったのですが、面倒だったので止めました(^^;)


  内容は、画面の一部分を1/2/3/4ビット、ローテートするだけのものです。

  一応、動作説明です。

1)初期設定
2)表示ページ#0にする
3)表示ページ#0のデータをページ#1にコピーする
4)ページ#1のデータをローテートする
5)表示ページ#1にする
6)表示ページ#1のデータをページ#0にコピーする
7)ページ#0のデータをローテートする
8)2)に戻る

  表示ページと違う側に書き込みをしているので、ちらつきなどが抑えられています。

posted by えすび at 17:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年04月06日

P6SRの2画面切換(2)

  P6SRのグラフィック2画面切換について。

  調査した所、以下の通りでした(以下、グラフィック画面のみの話です)。


  表示切替は、ポート0xC9に、0x00/0x08 を出力します。
  0x00を出力した場合は、0x0000〜0x7FFFのVRAMの内容が表示されます。
  0x08を出力した場合は、0x0000〜0x7FFF0x8000-0xFFFFのVRAMの内容が表示されます。
  (グラフィックの場合は、bit3のみ意味を持ちます) 


  ポート0xC8のbit4-3は、以下の通りですが、画面表示には関係ありません。
  bit4:グラフィック表示ページ(0:ページ0(0x0000〜0x7FFF)/1:ページ1(0x8000〜0xFFFF))
  bit3:ビットマップモード(0:イネーブル/1:ディセーブル(直接アクセスモード))


  ポート0xC8のbit4-3は、CPUからVRAMにアクセスする際に有効となるビットで、画面表示には関係がないんですね。この辺りが、今のエミュレータでは正確に対応できていません。



  上記のことですが、画面周りのポートはBASICで管理されているので、BASICから確認するのはちょっと面倒です。例えば、以下のようにします。

 1)コマンドラインから、SCREEN 2,2,2:LINE(0,0)-(319,199),16 とします。BASICでいうページ2に斜め線が1本引かれます。

 2)MON で、マシン語モニタに入って、0xA000〜から以下の設定をします(SA000 space で入力できます)。

A000:F3 3E FB D3 C3 3E 08 D3 C9 18 FE

 3)B でBASICで戻った後、EXEC &HA000 でさっきと違うグラフィックページが表示されるはずです。

  ちなみに表示されているのは、0x8000〜0xFFFFのページです。
  実行後は、BASICに戻ってこないので、リセットして下さい(0xA000〜の内容は残っています)。

  0xA007 の 08 を 00 にすると、0x0000〜0x7FFFのページが表示されます。



続きを読む
posted by えすび at 22:58| Comment(8) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2018年03月27日

P6SRの2画面切換

  現在着手中の移植の、オープニング、エンディングを作成している事で気付いたこと。


  画面スクロールなどもあるので、2画面切換を使って滑らかに表示しようとしたら...
  エミュレータが対応していませんでした(^^;)...

  まあ、P6SRでグラフィック2画面を使う場合拡張RAMが必須になるので、そこまで調査できていないんだろうなぁ、という感じです(使っているソフトもないですし)。


  この辺りは、詳細を調べてまとめるつもりです。



  個人的にはマウスも対応して欲しいけど...これも使っているソフトがないですね(^^;)...

posted by えすび at 00:30| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2015年11月08日

パレット機能

  テクノウを作るに当たり機能ごとに書くのもいいんですが、画面周りが非常に大変そうなので...
  とりあえずI/Oポート順に攻めてみたいと思います。


  参考文献:Mr.PCテクニカルコレクション 秀和システムトレーディング


○ポート0x40:色番号16(HGRB=1111)のパレット色設定
○ポート0x41:色番号15(HGRB=1110)のパレット色設定
○ポート0x42:色番号14(HGRB=1101)のパレット色設定
○ポート0x43:色番号13(HGRB=1100)のパレット色設定

(ポート0x44〜0x4F:ポート0x40〜0x43のイメージ)


 ・SR以降のみに存在するI/Oポートです。
 ・SRモード(ポート0xC8:bit0=0)以外でも動作します。
 ・書き込みのみ。読み出しはできません(読み出すと0xFFになる)。

  書き込むデータは次の通り。

  bit7-4:don't care
  bit3:Hの反転
  bit2:Gの反転
  bit1:Rの反転
  bit0:Bの反転


◎解説
 いろいろとユーザには理解しがたい仕様のパレット設定です。

 なぜ、4色だけなのか?せめて8色なら88からの移植がラクなのに。
 なぜ、色番号13〜16なのか?せめて色番号1〜8なら、88で出せる色はそのまま使えるのに。

 と、88からの移植にすごく不向きなパレットです。

 設定する値は出したい色の反転を設定します。これもなぜ反転か不明ですが...

 例えば、色番号13に白(HGRB=1111)の設定する場合は、ポート0x43 に 0x00を出力します。


 また、SR-BASICのグラフィック全般に言える事ですが、SR-BASICではVSYNC割り込みを使って、常に画面設定をしています。

 そのため、SR-BASICのコマンドラインから、

 SCREEN 2,2,2:LINE (0,0)-(319,199),16,BF

 の後に

 OUT &H40,&H05

 としても、色番号16の白(HGRB=1111)が、赤(HGRB=1010)になりません。

 SR-BASICではなく、N66-BASIC(MODE5)で同じ事を実行した場合、ちゃんと所望の動作をします。
 (ただし、SCREEN 2,2,2 → SCREEN 3,2,2 とする)


 SR-BASICでは、ポート0x40〜0x43に出力した値をワークエリアに持っています。

 ポート0x40:0xED1F
 ポート0x41:0xED20
 ポート0x42:0xED21
 ポート0x43:0xED22

 これを使って、

 10 SCREEN 2,2,2:LINE (0,0)-(319,199),16,BF
 20 POKE &HED1F,&H05
 30 GOTO 30

 とすると、色番号16の白(HGRB=1111)が、赤(HGRB=1010)になります。



 このパレットが性能を発揮するのは、MODE5の320x200ドット表示の色を変える時ぐらいかも知れません。

posted by えすび at 12:25| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2014年06月03日

SRのグラフィックのバグ

  SRの簡易グラフィックモードでのハードウエアのバグの話です。
  バグは有名かどうか分かりませんが...


  SRでは、screen 1 で、width 80,25 をした場合に、簡易グラフィックが使えます。丁度、PC-8001の160x100のグラフィックと同じようになります。

  マニュアルにも記載があり、単純にグラフィックビットを1にするだけです。width 80,25 以外では、ガイコツや体のパーツみたいな、他のキャラクタが表示されますが、width 80,25 では、コードによって256パターンのグラフィックデータが表示されます。


  で、実際に使ってみると...バグがあります。

  一番右側(79文字目)のキャラクタの表示がおかしくなります。
  もうちょっと正確に言うと、160x100のドットで数えて、0.5ドット下にずれます(下にローテートしている)。



  試したプログラムはこれです。

グラフィック表示リスト.JPG



  実際の写真がこれ。一番右の所だけずれているのがわかると思います。

140603_01_160x100グラフィック.JPG



  さすがにエミュレータでは再現されていません(その必要もありませんが...)。
posted by えすび at 19:50| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2014年05月21日

SRのVRAMについて(4)

  SRのVRAM関連を調べていて(というか違うプログラムを作っていて)、どうもハードウエアのバグらしきものを見つけました。


  発生条件が確定していないんですが、今の所

  ・MODE6でグラフィックを2画面使う。
  ・ポート0xC9 で画面を頻繁に切り替える。

  画面を切り替えた時に、たまーに書き込んでいない部分のVRAMに、データが書き込まれます。

  どうも、ページ切り替えと、画面表示で、NGなタイミングがあるようなんですが、詳細を調査中です。
 

  MODE6 のテキスト2画面や、テキストとグラフィック、さらには、MODE1〜5に関して同じ問題が発生するかどうかは不明です。
 (多分、MODE1〜5は大丈夫だと思うんですが...)

posted by えすび at 20:37| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2014年05月12日

SRのVRAMについて(3)

  SRのVRAMのアクセス関連の調査中です。


  先日挙げた、


 ○グラフィックモードの場合


 ☆ポート0xC8 bit3=0 にすると、ポート0xCE、ポート0xCFで座標アクセスが出来る。逆に直接アクセスができない。
 ☆座標アクセスの際は、ページ番号によりポート0xC8 bit4を変更する。通常は、下位32K(ページ0)。
 ☆ポート0xC8 bit3=1 、bit4=0 にした場合、通常環境では暴走する。これは、BASICのワークエリアにアクセスができないため。

  ☆の1つ目の項目はこれで正解のようです。

  ただやっかいなのは、X座標0〜319、Y座標0〜203 の範囲なのですが、I/Oとしては両方とも16ビットあるため、範囲外にアクセスした時にどうなるかを調べる必要があります(調査中ですが、多少ヘンな動きをします)。

  また、上位32Kに座標アクセス(ビットマップアクセス)するためには、プログラムを二段階に組む必要があるので、まだ調べきれていません。



  ちなみに、画面を表示させながら、ディスクからロードするには、以下の方法で実現できます。

  SCREEN 2,2,2:POKE &HED1D,&HEE:BLOAD "ファイル名"


  0xED1D は、ポート0xC8の値を保存しているワークエリアで、VSYNC割り込みで読み出してポート0xC8に設定しています。

posted by えすび at 20:29| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2014年05月10日

SRのVRAMについて(2)

  SRのVRAMのアクセス関連がよく分からないので調べてみました。まだ途中ですが。


  Mr.PC Technical Collection を参考にしているのですが、間違っている所もあるようです。

  どうやったら、思っているモードの画面が表示されるのかがかなり分かり難いです。

  I/Oポートの0xC0〜0xCFをアクセスすればよさそうなのですが、いまいちすっきりしません。また、BASICからI/Oポートにアクセスしても、VSYNC割り込みの時に変更されるので、挙動が分かりにくくなっています。

  そこでプログラムを作ってみました。


srgraph.zip



  サブCPU以外の割り込みを禁止して、0xC1〜0xCF にアクセスできるようにしています。

  走らせると、0xC0〜0xCF に出力する値を入力すると、その値を出力します。
  任意のキー(スペースキーがベスト)を元に戻ります。

  事前に、0x0000〜0x7FFFにグラフィックデータをロードさせると、挙動が分かりやすいです。



Mr.PC Technical Collection でのI/Oポートの説明は以下の通りです。

 ポート0xC1
  bit7-4:1固定
  bit3:1=横320ドット。0=横640ドット。
  bit2:1=キャラクタモード。0=グラフィックモード。
  bit1:1=40文字。0=80文字。
  bit0:1=縦200ライン。0=縦204ライン。

 ポート0xC8
  bit7-5:1固定
  bit4:ビットマップのページ指定。1=上位32K。0=下位32K。
  bit3:1=ビットマップDisable。0=ビットマップEnable。
  bit2:1=20行。0=25行。
  bit1:1=バスリクエストOFF。0=バスリクエストON。
  bit0:1=旧BASIC。0=SR-BASIC

 ポート0xC9
  bit7-4:0固定
  bit3-0:VRAMアドレス指定(ページ1〜16)



  これを動作ごとにまとめた結果が以下の通りです。


 ○キャラクタモードの場合

  ポート0xC1 bit2=1にする。
  画面サイズは、ポート0xC1 bit1 と、ポート0xC8 bit2 で決定する。
  表示ページは、ポート0xC9 で決定する。

  ポート0xC1 bit3、bit0 は、グラフィックモード用の設定のため、無関係になる。

  ポート0xC8 bit0=0 に設定しておく必要あり(SR-BASICのため)
  ポート0xC8 bit3=1 に設定しておく。


 ○グラフィックモードの場合

  ポート0xC1 bit2=0にする。
  画面サイズは、ポート0xC1 bit3 bit0 で決定する。
  表示ページは、ポート0xC9 で決定する。ただし、bit2-0 は無視される。bit3=ページ番号となる。

  ポート0xC1 bit1 と、ポート0xC8 bit2 は、キャラクタモード用の設定のため、無関係になる。

  ポート0xC8 bit0=0 に設定しておく必要あり(SR-BASICのため)


 ☆ポート0xC8 bit3=0 にすると、ポート0xCE、ポート0xCFで座標アクセスが出来る。逆に直接アクセスができない。
 ☆座標アクセスの際は、ページ番号によりポート0xC8 bit4を変更する。通常は、下位32K(ページ0)。
 ☆ポート0xC8 bit3=1 、bit4=0 にした場合、通常環境では暴走する。これは、BASICのワークエリアにアクセスができないため。

  最後の☆の行に関しては、まだ調査中です。

posted by えすび at 20:44| Comment(9) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2014年05月07日

SRのVRAMについて

  SRのVRAMは、構成が結構ヘンなんですが...


  気になるツイッターの発言を見つけました。

 『SRのグラフィックをBSAVEしたデータをロードする際、SCREENを表示させずに裏側でBLOADさせるとちゃんと画面が表示されるが、SCREENを表示させた状態でBLOADさせると画面がちゃんと表示されない』

  実際にやってみました。


  SR上でグラフィックデータを作るのが面倒だったので、P6VW上で、以下の手順でデータを作りました。

 1)適当なソフトを走らせて、0x0000〜0x7FFFをgetbinコマンドで一度ファイルに落とす。
 2)フォーマット済みの.d88を挿入して、モード6で立ち上げて、setbinコマンドでVRAMにデータを戻す。
 3)BSAVE "ファイル名",0,&H8000 で、ディスクにセーブする。


  上記の.d88を使って、P6VW上で

 ・SCREEN 2,2,2:BLOAD "ファイル名"

  をすると、確かに変なロード状態になります。


  で、問題はここからで、

 ○P6VW
 ○P6V
 ○iP6plus
 ○実機

  で、この変なロード状態に差異があります。

  実機では、最下行だけにロードデータが表示されるのですが、エミュレータでは、X座標が0〜255の分だけは表示されてしまいます。


  何となく予想はついているんですが、まだちゃんと調査できていません。


  また、上記の.d88ファイルを使って、

 ・SCREEN 2,2,2 を実行した後、SCREEN 1 で、BLOAD "ファイル名"

  を実行した場合、

 ○P6VW
 ○iP6plus

  では、正常な画像が表示されるんですが、

 ○P6V
 ○実機

  では、正常な画像が表示されません。X座標が256〜319のデータがナゼか1行置きに表示されます。

  多分、P6VWで作成したデータ自体がおかしいんだと思いますが、これも調査中です。


posted by えすび at 20:00| Comment(3) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2013年04月03日

CRTCのバスリクエストOFF(3)

  前言撤回です。


>> ・CRTKILL の解除は、水平同期(横の行)単位で行われている。
>> ・CRTKILL の最中に表示されるデータは、画面右下(データとアトリビュートの両方)が表示される。


  画面の右下のデータが表示されるのではなく、最後に描画したデータを表示するようです。

  ↓サンプルプログラムです。

crtkill.zip


  先のプログラムとほとんど変わりませんが、WAIT値を2つ設定できるようにしました。
  垂直同期からどれくらい待つか(WAIT1)と、その後どれくらいCRTKILLするか(WAIT2)です。


  画面の縞模様(もしくは真っ黒)の部分が、CRTKILLしている期間になります。

  WAIT1 に、0x0118〜0x011Eを入れると右下のデータが繰り返されるのではなく、水色の線が表示されます。
  (WAIT2は、CRTKILLの幅なので、0x0200ぐらいでいいでしょう)

  WAIT1 に、0x0110〜0x01C0 ぐらいの値なら、画面右下のデータが表示され、0x120より大きいと、真っ黒な横帯になります。


  何となく使えそうな使えなさそうな機能です...

posted by えすび at 22:37| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2013年04月02日

CRTCのバスリクエストOFF(2)

  mk2、66で、バスリクエストOFF(OUT &H93,2)をした場合の挙動を調べて面白い事が分かりました。


  ↓がCRTC周りの回路図です(以前にアップしたものから一部を修正しています)。

pc6001mk2_crtcnt


  CRTKILLの信号を、一度H-SYNCで叩いてから、LSIに入力しています。

  これはもしかして1行単位でCRTKILL(バスリクエストOFF)が出来るのでは?
  という事で調べてみました。

  ↓が作成したプログラムです。

crtkill.zip


  Mode5,Page3 で動かして下さい。

  RUN すると、WAIT値を聞いてくるので、とりあえず 200 を入力してみて下さい。
  上の方に縞模様が出ると思います(時間が経つと変化します)。
  スペースキーを押すと、ループから抜けます。

  プログラムの内容は、以下の通りです。

 1)垂直同期が来るまで待つ
 2)CRTKILL (バスリクエストOFF)にする
 3)一定時間待つ
 4)CRTKILL を解除する(バスリクエストONにする)
 5)1)に戻る


  です。5)で戻る前に、画面左上と右下に適当な値を書き込んでいます。


  実行してもらうとわかりますが、CRTKILL (バスリクエストOFF)は以下のように動作しているようです。

 ・CRTKILL の解除は、水平同期(横の行)単位で行われている。
 ・CRTKILL の最中に表示されるデータは、画面右下(データとアトリビュートの両方)が表示される。



  ただ、CRTKILL の設定は、水平同期(横の行)単位で行われているかどうか不明です。

  今回のプログラムでは、1フレーム間に、
    CRTKILL設定→CRTKILL解除
  ですが、これを1フレーム間に、
    CRTKILL設定→CRTKILL解除→CRTKILL設定→CRTKILL解除
  とやっても、縞模様が2つ出来るような期待通りの動作をしてくれません。


  やっぱり動きがナゾです...

posted by えすび at 18:36| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2013年01月16日

色ずれの話(1)

  ふと思いついたので、色ずれを制御する回路を組んでみました。


  以下が実施した結果です。
  実行はmk2上で行い、電源などは切らずに色を変えています。


色ずれ緑・桃

  mk2では、普通の色ずれです。


色ずれ桃・緑

  色が入れ替わっています。電源を切ると入れ替わる事はありますが、通常は入れ替わりません。


色ずれ青・赤

  初代機での色ずれの色です。


色ずれ赤・青

  上の色の入れ替わり。


色ずれ紫・黄緑

  紫と黄緑の組み合わせ。全体的に青っぽい印象です。


色ずれ黄緑・紫

  上の色の入れ替わり。


色ずれ赤紫・緑

  赤紫と緑の組み合わせ。この緑と、通常の色ずれの緑は、違う色です。


色ずれ緑・赤紫

  上の色の入れ替わり。



  原理を詳細に説明すると大変なので、すごく端折ると、『カラーバースト信号のみ、タイミングをずらす』事をしています。

  回路は簡単で、mk2のRFモジュールに入力されている、3.58MHzのクロックをずらしているだけです。



CLOCKSFT回路

  これが回路図です。74LS00 で組んでいるのは、単なるセレクタです。
  元の3.58MHz、14MHz は、mk2本体から取って、ずらしたクロックをRFモジュールに入力しています。

  スイッチの組み合わせで、3.58MHzを、14MHzの半分の単位でずらしています(8通りの組み合わせになる)。


色ずれ変換回路実装1

  実際に実装した所です。緑の線が、mk2のIC47につながっています(見づらいですが)。


色ずれ変換回路実装2

  RFモジュールに戻している所です。
  RFモジュールへのケーブルを切ったり、パターンカットをするのがイヤだったので、入力の初段のコイル(L1)を外して、そこに入力しています。



  実は、色ずれ以外の、普通の色にも影響がありそうなんですが、あまり確認をしていません。
  色ずれした色が結構キレイだったので(^^;

posted by えすび at 21:29| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2013年01月15日

CRTCのバスリクエストOFF(1)

  mk2、66で、バスリクエストOFF(OUT &H93,2)をした場合の挙動が不思議です。

  MODE5、PAGE4にして、起動直後(SCREEN1)で、OUT &H93,2 をすると砂嵐になります。

  OUT &H93,3 で元に戻した後、
  SCREEN 3,2,2:OUT &H93,2
  とすると、画面が真っ黒になったまま、砂嵐にはなりません。

  その後、OUT &H93,3 で元に戻した後、同じように
  SCREEN 3,2,2:OUT &H93,2
  とすると、今度は砂嵐になります(たまに真っ黒になる)。

  上のコマンドの代わりに、
  SCREEN 4,2,2:SCREEN 3,2,2:OUT &H93,2
  とすると、100%、真っ黒です。


  SCREEN 3,2,2:OUT &H93,2
  だけだと、砂嵐になったり、真っ黒になったりと、結果が変わります。


  この辺りのタイミングは、CRTC のLSI に CRT-KILL のコマンドを入力する時に、H-SYNC の立ち上がりで叩いているので、H-SYNC が関係しているようなんですが、よくわかりません(以前にアップした回路図は、一部間違えていました)。


  画面が真っ黒ではなく縞模様になる事もあるので、どこかのタイミングでデータをラッチしているようなんですが、どーもよくわかりません...


  もうちょっと解析をしてみて、FPGA版にも反映させたいと思います(今のバージョンは中途半端)。


posted by えすび at 21:23| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2012年12月02日

画面描画期間検出(7)

  昨日アップした画面描画期間の検出プログラムは、やはり間違っていたようです。

  改定版をアップします。

vsync2_2.zip

  拡張RAMが必要で、ページ4です。
  前と同じですが、画面切り換えを使っている関係で、mk2、66では動作しません。



  方法ですが、基本は同じです。

・画面描画期間の検出の方法(基本)

  画面描画期間の時だけ止まっているCPU で、その止まっている期間を検出するためには、CPU の外部に基準の時計が必要になります。
  SUB-CPU がつながっている8255 のポートを使用します。

  特定ポートにデータを書き込むと、4MHz で60〜80クロックぐらいかかる処理があります。


  これを使い、画面描画期間を判定します。

  データ書き込み
  ↓
  4MHz で50クロックぐらい待つ
  ↓
  処理が完了しているかを判断する


  画面描画期間以外:処理が完了しない。
  画面描画期間:CPU が途中で止まっているため、実際には50クロック以上の時間が経っており、処理が完了する。

  で判断します。


・画面描画期間の検出の方法

  上記の基本の検出を4度行います。その際、一定期間(具体的には155クロック)空けます。
  こうすると、画面描画をしている時は、4度の検出のどこかで検出できるようになります。

  ただし、検出には大体8走査線分(描画期間中)、3走査線分(描画期間中)の時間がかかります。


  初代P6では、1走査線は 910クロック@14M(253クロック@4M)分の時間で、CPU が動作できる期間はその内の、296クロック@14M(83クロック@4M)ぐらいです。
  また、mk2、66では、1走査線は 912クロック@14M(255クロック@4M)分の時間で、CPU が動作できる期間はその内の、304クロック@14M(85クロック@4M)です。

  この走査線とCPUが動作できる/動作できない期間はほぼ一定間隔なので、検出期間をいい感じにすると、4度の検出の間のどこかで引っ掛けることが出来ます。


vsyncdet.xls


  ↑が説明の図です。

  ピンクの長方形が、検出方法の基本で書いている、サブCPU の処理完了待ちです。ピンクの最後で処理が完了しているかどうかを判断します。
  ピンクの最後が水色になっているのは、そのタイミングで画面描画期間(CPUが止まった期間)を検出できることを示します。


  サブCPUにアクセスする間隔をもっと短くすればよさそうなんですが、短くすると応答の時間が極端に長くなったり短くなったりと、変になります。
  なので、実測から今の155クロック間隔にしています。


 サンプルプログラムでは描画期間判断ルーチンを2度呼んでいますが、これは

 1)描画期間が開始されるまで待つ。その後に
 2)描画期間が終了するまで待つ。

 として、描画期間が終了した直後を探しています。

 2)描画期間が終了するまで待つ。だけでよさそうなんですが、これだと描画期間直後ではなく、中間の時も検出される場合があるからです。

 マウスのプログラムを作った時にハマりました(^^;



  ちなみに、PC-6001F の方でも、サブCPU からの応答値を合わせましたので、同じように動作すると思います。


posted by えすび at 23:26| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2012年12月01日

画面描画期間検出(6)について

  プログラムを見て、書いている事が矛盾しているのを発見。

  「2回検出」と書いていますが、「2回検出」のサブルーチンを2回コールしていました。


  だいぶ前に作ったので忘れてますが...1回コールに直すと全然ダメなので、とりあえず動いているバージョンが正しいという事で...



  「2回検出×2回コール」で、ちゃんと動いているようなんですが、もう一度見直す必要がありそうです。




posted by えすび at 16:33| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

画面描画期間検出(6)

  以前に作成した画面描画期間の検出プログラムを改定しました。

vsync2_2.zip


  拡張RAMが必要で、ページ4です。

  前と同じですが、画面切り換えを使っている関係で、mk2、66では動作しません。


  方法ですが、基本は同じです。

・画面描画期間の検出の方法(基本)

 画面描画期間の時だけ止まっているCPU で、その止まっている期間を検出するためには、CPU の外部に基準の時計が必要になります。
 SUB-CPU がつながっている8255 のポートを使用します。

 特定ポートにデータを書き込むと、4MHz で60〜80クロックぐらいかかる処理があります。


 これを使い、画面描画期間を判定します。

 データ書き込み
 ↓
 4MHz で45クロックぐらい待つ
 ↓
 処理が完了しているかを判断する


 画面描画期間以外:処理が完了しない。
 画面描画期間:CPU が途中で止まっているため、実際には45クロック以上の時間が経っており、処理が完了する。

 で判断します。


・画面描画期間の検出の方法(改定)

 上記の基本の検出を2度行います。その際、一定期間(具体的には96クロック)空けます。
 こうすると、画面描画をしている時は、1度目か2度目の検出で検出できるようになります。

 ただし、検出には3走査線分の時間がかかります。

 初代P6では、1走査線は 910クロック@14M(253クロック@4M)分の時間で、CPU が動作できる期間はその内の、296クロック@14M(83クロック@4M)ぐらいです。
 また、mk2、66では、1走査線は 912クロック@14M(255クロック@4M)分の時間で、CPU が動作できる期間はその内の、304クロック@14M(85クロック@4M)です。

 この走査線とCPUが動作できる/動作できない期間はほぼ一定間隔なので、検出期間をいい具合にすると、1度目の検出では引っ掛からなかったものを2度目の検出で引っ掛けられます。

 図を描いて、タイミングを計算しないと、すごく分かりにくいですが...



 ロジアナで、プログラムを動作中のものを見ましたが、多分ちゃんと動いているんじゃなかと思います。







posted by えすび at 14:58| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2012年08月08日

画面描画期間検出(5)

 画面描画期間検出(1) で使っていた手法ですが、8255 のモード2のレスポンス時間(正確には、sub-CPU の割り込みから読み出しまでのレスポンス時間)を使っていました。

 ただ、これだとちょっと短すぎるようで、画面描画期間を検出し損なうことがあります。


 他に使えそうなのが、sub-CPU のゲームキー検索です。
 これは、sub-CPU にコマンド(0x06)を出力して、sub-CPU からのデータ(0x16+キーデータ)が返ってくるレスポンス時間を計るものです。


 で、調べてみましたが...

 レスポンス時間が、HSYNC で数えて15〜40行分ぐらいと、えらく幅がありました。
 HSYNC 1行分が、912clk@14Mですので、大体 977μs 〜 2605μs と余り使え無そうです。

 sub-CPU のプログラムを読んだわけではないので何とも言えないですが、キーマトリックスにアクセスするタイミングが一定になっているために、レスポンス時間が一定にならないんじゃないかと思います。


posted by えすび at 17:10| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

画面描画期間検出(4)

  先に書いた追加ハードウエアを実際に組んでみました。
  その4の回路では問題がありましたので修正しています。


・その4改

  MREQ がネゲート(つまり CPU から読み書きされない)、CAS がアサートされた時にそのアドレスをラッチする。
  この条件の時は、画面描画範囲からデータを読み出しているタイミングなので、どのアドレスにアクセスしているかが読み出せます。

  実際の回路は、それ以外にラッチしたアドレスをクリアする機能が必要になります。


  組んでみた回路がこれです。

VSYNC検出回路例改

  I/O ポートは、0x40(アドレス下位)、0x41(アドレス上位)で、0x41 アクセス時は同時にクリアします。
  手抜き仕様なので、クリアというよりアクセスした時のアドレスが入ります。

  MREQ を1クロック引き伸ばしているのは、MREQ に対して CAS がちょっと遅れて出力されるための処置です。



  動かしてみたテストプログラムがこれです。

vsynccir.zip



  実際に動かした所です。





  うちの P6 の調子があまりよくないせいか色がヘンになったりしますが、水平2分割が出来ています。


posted by えすび at 14:59| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2012年08月05日

画面描画期間検出(3)

 Hashiさんトコの掲示板に書いたものの追加、変更です。

 画面描画期間ですが、拡張コネクタに外付け回路を使う事により、確実に検出が可能になると思います。
 拡張コネクタには、アドレスバス、ライト、リードなどの信号が出ているので、これらを使用します。


・その1
 通常のCPUからアクセス時は、4MHz。
 VDG からのアクセス時は、14MHz。

 アドレスバスの変化タイミングを見る方法です。
 タイミング的にちょっと厳しいかも。


・その2
 VDG からのアクセスは、アドレスが決まった変化をします。
 (スクリーンモードによりますが)
 その変化のパターンを調べて、学習する回路を作ります。

 例えば、スクリーン3ページ2の場合、

 E000 E200 E001 E201 E002 E202 ・・・ となるので、このパターンを
 探して、1フレーム後にも同じパターンが来るかを見るような回路です。


・その3
 初代P6 のみの方法です(mk2以降は不可)。

 通常のCPUからのアクセス時は、RAS をアサート、CAS をアサート、ですが、
 VDG からのアクセスは、RAS をアサート、CAS をアサート、CAS をアサートと
 RAS1回に対して、CASを2回出力します。

 このパターンを見つけてフレームレベルで周期監視するのが、割と簡単そうな回路です。


・その4
 これも初代P6 のみの方法(mk2以降は、不可)で、多分回路が一番簡単で、使いやすそう。

 M1 がネゲート、CAS がアサートされた時、つまりCPU のM1サイクル以外でRAMからリードされた時のアドレスをラッチする。
 これを適当なI/Oポートに割り当てて、CPUから読み出すというものです。

 CPU がメモリからの読み出しを行った後で、画面描画期間になれば、VRAM のアドレスが読める事になります。
 また、VRAM のアドレスで、何行目を描画しているかが判別できます。

 判別前にメモリからの読み出しを数命令分止める必要がありますが、判別の長さを調整できたり、何行目かが判別できるというメリットがあります。



 その4をディスクリートで組むと、こんな感じでしょうか。

VSYNC検出回路例


 M1 の信号を1クロック遅らせているのは、M1の変化点とCASの変化点が同じために、ハザードが誤動作する可能性があるためです。

 実際に試していないので、動くかどうかはわかりません...


posted by えすび at 21:15| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2012年08月04日

画面描画期間検出(2)

 画面描画期間検出(1) でアップしたプログラムですが、mk2以降では期待通りに分割されません。

 これは、初代機とmk2以降で、表示画面の取り込みが違うためのようです。

 初代機:ポート0xB0 の値で、逐次変更される →画面描画途中でも表示ページが変更される
 mk2以降:1画面描画する直前で、ポート0xB0 の値を記憶する →画面描画途中では、表示ページが変更されない



 ちなみに、画面描画期間検出(1) でアップしたプログラムの ウエイト時間を変更すると、違う画面になります。

 vsync.p6 の 2120行の最後の 01,00,03 を 01,80,05 にすると、SCREEN3 とSCREEN4 の重ね合わせになります(かなりちらつきますが)。


 実際の動画がこちら。




 ビデオ出力したものですが、よくみるとSCREEN3 が1行置きに表示されています。

 これは、SCREEN3 描画 → SCREEN4 描画 → SCREEN3 描画、と1フレーム毎に交互に描画されているためのようです。


 画面がちらつくのは、画面描画期間検出のタイミングが多少ずれたり、検出ルーチンを通らなかったりするためで、mk2以降の機能にあるAY-3-8910のポ

ート経由でVSYNC を検出すると、ちらつきがなくなります。


 実際の動画がこちら。




 プログラムはこちらです。

vsyncmk2.zip


posted by えすび at 14:49| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

画面描画期間検出(1)

 まず、以下の画像をご覧下さい。DSi で撮ってるので、画像が悪いですが...




 これは、PC-6001 初代機で動かしたものです。外部に余計はハードウエアは付けていません(RAMは32Kにしていますが)。


 境界がちらちらと動くのがイマイチなんですが、一応画面の上半分はSCREEN4、下半分はSCREEN3 になっています。

 これは、ソフトウエアで画面描画期間を検出して、そこから一定時間後に画面の切り替えを行ってます。
 (事前にページ3とページ4を、SCREEN3 とSCREEN 4 に設定しています)



 プログラムがこれです。

vsync.zip



 ・画面描画期間の検出の方法

 画面描画期間の時だけ止まっているCPU で、その止まっている期間を検出するためには、CPU の外部に基準の時計が必要になります。
 今回は、SUB-CPU がつながっている8255 のポートを使用しました(詳細は後述)。

 特定ポートにデータを書き込むと、4MHz で64クロックぐらいかかる処理があります。


 これを使い、画面描画期間を判定します。

 データ書き込み
 ↓
 4MHz で40クロックぐらい待つ
 ↓
 処理が完了しているかを判断する


 画面描画期間以外:処理が完了しない。
 画面描画期間:CPU が途中で止まっているため、実際には40クロック以上の時間が経っており、処理が完了する。

 で判断します。


 ・8255のポートの話

 かなりハード寄りの話です。

 SUB-CPU とメインCPU との通信のために、8255 のモード2を使っている、という話は周知だと思います。
 このモード2ですがもっと細かく見ると、以下のようになります(SUB-CPU に出力時)。

 OUT 0x93,0x08 :INTE2 をリセットして、リード側のポートを無効にする(→ライト側のポートのみ有効になる)。
 ↓
 IN (0x92)  :bit3 とbit7 が 1 になるまで待つ(8255が受信可能になるまで待つ)
 ↓
 OUT 0x93,0x09 :INTE2 をセットする(後のためにINTE2を戻しておく?)。
 ↓
 OUT 0x90,DATA :SUB-CPU へ出力するデータを書き込む。


 最後のデータを出力すると、8255 の port-C の bit7(OBF)が、H→L になります。この信号が、SUB-CPU の割り込み信号になっています。
 ↓
 SUB-CPU は、割り込みが発生すると、データを読み出すためにリードイネーブルをLにします。この信号が、8255 の port-C の bit6 (ACK) になっています。
 ↓
 8255 は、8255 の port-C の bit6 (ACK) がLになると、読み出しが完了したと判断して、port-C の bit7(OBF)をL→Hとして、処理が終了します。



 一連の動きを実機のPC-6601 で測定したものがこれになります。動きとしては、初代機PC-6001 でも同じです。

SUBCPUアクセス


 画面描画期間はちゃんと検出出来ているようですが、毎フレーム検出できるというわけではありません。
 それは、(当然ですが)画面描画期間中に検出ルーチンを通らないと検出できないため、プログラムのループが長い時には、検出できないことがあるようです。






posted by えすび at 14:06| Comment(6) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2012年06月04日

スクリーン3と4の混在のバグ(2)

 スクリーン3と4の混在のバグに関して、原因がわかりました。

 ゆみたろさんにもコメントをもらっていましたが、原因はVDG周辺の回路ではなくVDG本体でした。


 これは、MC6847 のブロック図の一部です(MC6847のマニュアルより。16ページ)


MC6847のブロック図


 A/G、GM2-0 にはFFが入っておらず、それ以外の信号にはFFが入っています。

 この信号は、アトリビュートを読み出した結果がそのまま入力されるため、A/G、GM2-0 と他の信号は1クロックずれて変化する事になります。
 これにより、アトリビュートが1つずれているようです。

 CSSには FFが3つ入っていますが、これで他の信号(A/S、INT/EXT、INV)と段数が合っているようです。


 この結果、アトリビュートのアドレスがずれてしまうのは、GM2-0 のみです。
 (A/G は、実際には混在して使う事が出来ないので、考慮しなくてもいいでしょう)


 mk2以降は、このずれを回路に入れていないようなので、アトリビュートがずれずに表示されます。



posted by えすび at 18:18| Comment(2) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2012年03月27日

実機との比較の結果


  色が明るすぎるのは、とりあえずMORIYAさんトコの写真の色に合わせるようにしました。
  http://p6ers.net/mm/pc-6001/dev/p6color_chk/

  写真の色から、RGBを抽出するツールを使って、データを作成しました。



  ボーダーの縞模様(ジャン狂の方)は、原因は判りましたが、修正が大変です...

  SCREEN1とSCREEN4のアトリビュートの混在をどうするか、という問題になります。



  AX-7 デモの背景の縞模様に関しても、原因はわかりました。

  あの縞模様は、単純に色を連続で変えているだけのようです。

  で、画面を書き換えるタイミングと、画面を表示するタイミングが、微妙にずれた時に、あのようなキレイな縞模様が出るようです。


  FPGA版では、VGA出力のタイミングが関わってくるので、映り方が変わっているようです。


  また、エミュレータでは、走査線1ラインずつ書いているわけではないため、画面全体の色が変わるんだと思います、多分。


posted by えすび at 21:39| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2012年03月26日

PC6001の色について

 今更ながらに気付いたんですが...

 PC-6001 の画面の色(例えば起動直後の緑色)が全然違う!!!


 全体的に何だか明るすぎますよね?


 色の変換の時に間違えたのかも。これも修正する方向で検討します。


posted by えすび at 19:02| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

P6のVDGのボーダーの色

 拡張RAM が使えるようになったので、気になっていたソフト(ジャン狂)をテスト。

 このソフトでは、左右のボーダーに縞模様が入ります。

 これは、アトリビュートを操作しているだけです。
(MORIYAさんトコに詳しく書いています → http://p6ers.net/mm/pc-6001/dev/p6color_chk/mode3_attr.html


 FPGA版の実行結果がこちら。

ジャン狂FPGA右上

ジャン狂FPGA左上



 右端のボーダーのすぐ左の1バイト分が色が変わるのは分かるんですが、左端のボーダーのすぐ右の1バイトも色が変わっています。しかもちらちらと点いたり消えたりしています。


 で、実機。

ジャン狂実機右上

ジャン狂実機左上



 FPGA版と明らかに違います(左右の緑色が違うのは、カメラの補正が入っちゃったためです)。

 ・上下のボーダーの色が緑色
 ・左右のボーダー(縞模様)の色が緑色
 ・右端のボーダーのすぐ左の1バイトは、ベタ緑。
 ・左端のボーダーのすぐ右の1バイトはちらちらしない。


 うーん、これも修正する方向で考えるとしましょう。

posted by えすび at 19:00| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2012年01月15日

mk2のバスリクエストについて

  mk2 になってから、加速モードでのCMT のロードを待たせる時間が長くなっています。


  具体的には、1バイトのデータを読み出すのに、

  P6 :3.93ms
  mk2:2.62ms

  と、1.5倍の時間待たせています。


  mk2 のBASIC のプログラムの方がドンくさいんだと思っていたら、どうもそうではなかったようです。


  mk2 のCRTC のBUSRQ を調べた結果、MODE2 とMODE5 でかなり違います。

  CRTC は水平ライン262本分で1周しますが、その内、MODE2 では192回BUSRQがLになり、MODE5 では200回BUSRQがLになります。
  これは縦192ドット/200ドットに相当する数字です(当然ですが)。

  また、その1ライン中(456クロック)にLになる区間が、MODE2 では304クロック、MODE5 では368クロックです。
  これは、横の256ドット/320ドットに少しだけ大きい数字です(Z80がすぐに止まらないので余裕を持たせています)。


  で、BUSRQ がLの期間はCPUが止まっているとして計算すると...

  MODE2:48.85%
  MODE5:61.60%

  の期間、BUSRQ で止まっている計算になります。


  mk2 止まりすぎですね(−−;


  で、CMT のロードの話ですが、CPUが速く動けば待たせる時間が少なく済むので、ロード時間も短くなります。

  CMT ロードの時には、CRTKILL をすれば取りあえず速くなります。


  が、画面を全く消さなくても間引けばいいのでした。


  通常の6001だと間引いても画面が乱れますが、FPGA版はVGAモニタへの画面表示のために、2P-RAMで乗せ換えをしているために間引いても問題ないんですね。


  修正が完了したら、またアップします。

posted by えすび at 21:28| Comment(2) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2011年12月30日

mk2設計(3)

  PC-6001 のVDG である MC6847 と、mk2 のCRTコントローラですが、未サポートの画面以外に微妙に違う所があります。

  一つはセミグラフィックの表示の仕方で、mk2 ではキャラクタROMからデータを読み出しています(つまりセミグラフィック表示ではなく、グラフィックのキャラクタを表示させている)。

  もう一つは、水平同期のクロック数で、PC-6001 は 14.31818MHz で 910クロックに対して、mk2 は 912クロックです。



  他にも違いがありそうなので、FPGA化の際は、両方のコントローラを載せる事にします。

  幸い、回路規模はそんなに大きくありません(カウンタの固まりのイメージです)。



posted by えすび at 19:10| Comment(6) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする

2011年12月22日

VSYNC読み出し

  AY-3-8910 のポートから、VSYNC、HSYNC が読み出せる事は、前に書いていますが、実際にテストプログラムを組んで見ました。

VSYNC読み出しテスト


  ページは2ページ以上を指定して、mk2以降の実機で実行してみて下さい。
  BASICには戻らないので、リセットで終了して下さい。


  プログラムの内容は、単純にSCREEN3で色を次々に変えているだけです。

  実行すると、画面がちらつきますが、その境界線がほぼ一定になります。
  VSYNCを検出しているため、同じタイミングで書き込みをしているため、境界線が一定になります。


  180行〜200行の書き込み値を&H00 にすると、VSYNCを無視します。この場合、同じように画面がちらつきますが、境界線が一定になりません。


posted by えすび at 21:54| Comment(0) | P6解析:画面周り | このブログの読者になる | 更新情報をチェックする