ファミリーコンピュータ
PPU2C02へ
ファミリーコンピュータ ディスクシステムへ
ファミリー ベーシックへ
ファミコン ステーション(仮)へ
シャープ C1(仮)へ
マッパー0(HVC−NROM)へ
マッパー1(MMC1xx)へ
マッパー2、94(HVC−UNROM−xx)へ
マッパー3、66、185(HVC−CNROM−256K)へ
マッパー87へ
マッパー206(namcot 34xx)へ
ファミリーコンピュータのスペック
CPU | 2A03 1.789772MHz |
PPU | 2C02 |
ROM | 無し |
RAM | 2KB |
V-RAM | 2KB |
CPUは6502の機能を一部削り、
サウンドジェネレータ、OBJ DMA、I/Oポート等を追加かなりの機能を誇る。
ただし、コストダウンの為、本体はフルデコードされなかったり一部のポートが固定
色々と機能が削られているのが不満といえば不満
割り込み
2A03は6502と同様な割り込みができます
$FFFA−$FFFB:NMI (PPUから割り込み要求がきます)
$FFFC−$FFFD:RST (電源オン時またはリセットボタン)
$FFFE−$FFFF:BRK/IRQ
優先順位
RST>NMI>BRK/IRQ
NMIとBRK/IRQは割り込みが掛かると
PC上位、PC下位、PSRがスタックに退避されます
RTI命令はPSR、PC下位、PC上位をスタックから取り出す事になります
もし割り込みでRTSで戻る場合はスタックの操作が必要になります
I/Oポート
PPU RP2C02ポート
インターフェイスモード
/OBJBLK=0、/BGBLK=0
またはVBLANK中にインターフェイスモード(ポートのアクセス可)になる
CTLR0、CTLR1、SRは無関係
$2000 CTRL0:PPUコントロール0(出力のみ)
d7:INT 割り込み発生 1=オン 、0=オフ
d6:SLAVE モード指定 1=スレーブ 、0=マスタ
d5:8×16 CHRサイズ 1=8×16ドット、0=8×8ドット
d4:BGSEG BGキャラクタ領域 1=$1000 、0=$0000
d3:OBJSEG OBJキャラクタ領域 1=$1000 、0=$0000
d2:INCM INCモード 1=+32 、0=+1
d1:MSBV Vスクロールオフセット最上位bit
d0:MSBH Hスクロールオフセット最上位bit
*EXT0〜EXT3のカラーパレットインデックス
8×16=1の時OBJSEGは無効かつ
OBJnnが偶数$0000〜$0FFF
奇数$1000〜$1FFFを使用
$2001 CTRL1:PPUコントロール1(出力のみ)
d7:GREEN 全面着色 緑 1=オン、0=オフ
d6:BLUE 〃 青 1=オン、0=オフ
d5:RED 〃 赤 1=オン、0=オフ
d4:/OBJBLK OBJブランキング 1=オフ、0=オン
d3:/BGBLK BG 〃 1=オフ、0=オン
d2:/OBJLBLK OBJ左端ブランキング 1=オフ、0=オン
d1:/BGLBLK BG 〃 1=オフ、0=オン
d0:M&C モノトーン/カラー 1=M 、0=C
*d7〜d5は全画面のフィルタカラー
M&C 1=モノトーン、0=カラー
ブランキング 1=オフで表示、0=オンで表示しない
$2002 SR:ステータスレジスタ(入力)
d7:INT 割り込み(VBLANK) 1=オン 、0=オフ
d6:STRIKE 一致衝突判定フラグ 1=オン 、0=オフ
d5:9’OVER OBJ9オーバー 1=9個以上、0=8個以下
d4: 垂直ライン224オーバーd4 ポート$2005(垂直)で$E0より上の数値を書き込んだ値
d3: 垂直ライン224オーバーd3 $00〜$E0の場合 $00
d2: 垂直ライン224オーバーd2 $E1の場合 $01
d1: 垂直ライン224オーバーd1 :
d0: 垂直ライン224オーバーd0 $FFの場合 $1F
*読み込みすることによってd7 INT=0になる
$2005、$2006の内容がリセットされる
$2003 OAM.AR:OAMアドレスレジスタ(出力)
OBJ属性メモリのアドレスを指定します(オートインクリメント)
$2004 OAM :OBJ属性メモリ データ (入力/出力)
OBJ属性メモリにデータを入出力を行います(入力は古いロットによっては不可)
$2005 SCC H、V:スクロールレジスタ(出力)
スクロールのオフセットを書き込む
HオフセットはCTRL0 d0+SCCHの9ビット
VオフセットはCTRL1 d1+SCCVの9ビット
$2002を読むとリセットされ
VRAMAR($2006)と内部ラッチ共有のため
VRAMARアクセスすると新たにSCCを再設定しなければならない
$2006 VRAM.AR H、L:VRAMアドレスレジスタ(出力)
PPUのメモリアドレスをセットします
$2002を読み(リセット)、上位アドレス、下位アドレスでセットします
カラーパレット以外はVBLANK期間にセットしないとアドレスが変化します
$2007 VRAM READ/WRITE:PPUデータ (入力/出力)
$2006でセットしたPPUアドレスのデータを書きます(入力)
$2006でセットしたPPUアドレスのデータを読みます(出力)
ただし最初のデータは無効なので最初は2回読む事が必要
VRAMを読み書きした後、INCMによって
VRAM.ARは+1(右方向)または+32(下方向)にセットされる
APUポート周り
$4000 WRA0:SoundA 方形波(出力)
d7:デュティー指定 d1 11=75.0%、10=50.0%
d6: 〃 d0 01=25.0%、00=12.5%
d5:連続音/長さカウンタ 1=連続音 、0=長さカウンタ
d4:Direct/エンベローブ 0=Direct、0=エンベローブ
d3:エンベローブ減衰率/音量 d3
d2: 〃 d2
d1: 〃 d1
d0: 〃 d0
$4001 WRA1:SoundA 方形波(出力)
d7:Sweep機能 1=オン、0=オフ
d6:時間間隔 d2 Sweep演算の時間間隔
d5: 〃 d1 nフレーム/2 (n=0〜7)
d4: 〃 d0
d3:減算/加算 1=減算、0=加算 tn=t(n-1)±t(n-1)/2^n
d2:シフト数 d2 Sweepクロックジェネレータ
d1: 〃 d1 シフト数(n=0〜7)
d0: 〃 d0
$4002 WRA2:SoundA 方形波(出力)
d7:周波数下位 d7
d6: 〃 d6
d5: 〃 d5
d4: 〃 d4
d3: 〃 d3
d2: 〃 d2
d1: 〃 d1
d0: 〃 d0
$4003 WRA3:SoundA 方形波(出力)
d7:長さデータ d4
d6: 〃 d3
d5: 〃 d2
d4: 〃 d1
d3: 〃 d0
d2:周波数上位 d10
d1: 〃 d9
d0: 〃 d8
$4004 WRB0:SoundB 方形波(出力)
d7:デュティー指定 d1 11=75.0%、10=50.0%
d6: 〃 d0 01=25.0%、00=12.5%
d5:連続音/長さカウンタ 1=連続音 、0=長さカウンタ
d4:Direct/エンベローブ 0=Direct、0=エンベローブ
d3:エンベローブ減衰率/音量 d3
d2: 〃 d2
d1: 〃 d1
d0: 〃 d0
$4005 WRB1:SoundB 方形波(出力)
d7:Sweep機能 1=オン、0=オフ
d6:時間間隔 d2 Sweep演算の時間間隔
d5: 〃 d1 nフレーム/2 (n=0〜7)
d4: 〃 d0
d3:減算/加算 1=減算、0=加算 tn=t(n-1)±t(n-1)/2^n
d2:シフト数 d2 Sweepクロックジェネレータ
d1: 〃 d1 シフト数(n=0〜7)
d0: 〃 d0
$4006 WRB2:SoundB 方形波(出力)
d7:周波数下位 d7
d6: 〃 d6
d5: 〃 d5
d4: 〃 d4
d3: 〃 d3
d2: 〃 d2
d1: 〃 d1
d0: 〃 d0
$4007 WRB3:SoundB 方形波(出力)
d7:長さデータ d4
d6: 〃 d3
d5: 〃 d2
d4: 〃 d1
d3: 〃 d0
d2:周波数上位 d10
d1: 〃 d9
d0: 〃 d8
$4008 WRC0:SoundC 三角波(出力)
d7:連続音/長さカウンタ 1=有効、0=無効
d6:長さ d6
d5: 〃 d5
d4: 〃 d4
d3: 〃 d3
d2: 〃 d2
d1: 〃 d1
d0: 〃 d0
$4009 WRC1:SoundC 三角波(未使用)
$400A WRC2:SoundC 三角波(出力)
d7:周波数下位 d7
d6: 〃 d6
d5: 〃 d5
d4: 〃 d4
d3: 〃 d3
d2: 〃 d2
d1: 〃 d1
d0: 〃 d0
$400B WRC3:SoundC 三角波(出力)
d7:長さデータ d4
d6: 〃 d3
d5: 〃 d2
d4: 〃 d1
d3: 〃 d0
d2:周波数上位 d10
d1: 〃 d9
d0: 〃 d8
$400C WRD0:SoundD ノイズ(出力)
d7: −
d6: −
d5:連続音/長さカウンタ
d4:エンベローブ音響/Direct
d3:エンベローブ減衰率/音量 d3
d2: 〃 d2
d1: 〃 d1
d0: 〃 d0
$400D WRD1:SoundD ノイズ(未使用)
$400E WRD2:SoundD ノイズ(出力)
d7:モード 1=93Bit、0=32KBit
d6: −
d5: −
d4: −
d3:長さ
d2: 〃
d1: 〃
d0: 〃
$400F WRD3:SoundD ノイズ(出力)
d7:長さデータ
d6: 〃
d5: 〃
d4: 〃
d3: 〃
d2: −
d1: −
d0: −
$4010 WRE0:SoundE ΔMOD(出力)
d7:INT 1=オン、0=オフ
d6:繰り返し 1=オン、0=オフ
d5:
d4:
d3:サンプルクロック周波数
d2: 〃
d1: 〃
d0: 〃
$4011 WRE1:SoundE ΔMODロードカウンタ(出力)
d7: −
d6:ΔMOD出力DA 直接データ
d5: 〃
d4: 〃
d3: 〃
d2: 〃
d1: 〃
d0: 〃
$4012 WRE2:SoundE ΔMODアドレスカウンタ(出力)
d7:A13 アドレスは$C000〜$FFFFの範囲
d6:A12
d5:A11
d4:A10
d3:A9
d2:A8
d1:A7
d0:A6
$4013 WRE3:SoundE ΔMODターミナルカウンタ(出力)
d7:長さ d15 サンプリングレングスは+1にしてセットされる
d6: 〃 d14
d5: 〃 d13
d4: 〃 d12
d3: 〃 d11
d2: 〃 d10
d1: 〃 d9
d0: 〃 d8
$4014 WRF0:OBJ DMA セグメント指定(出力)
d7:CPU A15
d6:CPU A14
d5:CPU A13
d4:CPU A12
d3:CPU A11
d2:CPU A10
d1:CPU A9
d0:CPU A8
CPUA7〜A0は全て0になり
CPUメモリからOBJ属性メモリへ 256バイトDMA転送を行います
このポートにデータ書き込みが行われると転送開始されますので
VBLANK期間中に書き込む様にします
また転送中はCPUが止まります
$4015 RDST:ステータス(入力)
d7:IRQΔMODステータス 1=DMC、0=IRQ
d6:IRQフレームステータス
d5: −
d4:APU ChE ΔMODステータス 1=出力 、0=停止
d3:APU ChD ノイズステータス 1=出力 、0=停止
d2:APU ChC 三角波ステータス 1=出力 、0=停止
d1:APU ChB 方形波ステータス 1=出力 、0=停止
d0:APU ChA 方形波ステータス 1=出力 、0=停止
APU Chn ステータス、チャンネルはエンベロープ等で
音が出なくなると0になる
WRST:チャンネル(出力)
d7: −
d6: −
d5: −
d4:ChE ΔMODチャンネル 1=オン、0=オフ
d3:ChD ノイズチャンネル 1=オン、0=オフ
d2:ChC 三角波チャンネル 1=オン、0=オフ
d1:ChB 矩形波チャンネル 1=オン、0=オフ
d0:ChA 矩形波チャンネル 1=オン、0=オフ
I/Oポート周り
$4016 RDP0:INP0(入力)
d7: −
d6: −
d5: −
d4: −
d3: −
d2:MIC IN
d1:4016 D1
d0:4016 D0
WRP0:(出力)
d7: −
d6: −
d5: −
d4: −
d3: −
d2:OUT2
d1:OUT1
d0:OUT0 コントローラー入力トリガ
$4017 RDP1:INP1(入力)
d7: −
d6: −
d5: −
d4:4017 D4
d3:4017 D3
d2:4017 D2
d1:4017 D1
d0:4017 D0
SOFT CLK:フレームカウンタ(出力)
d7:EXTモード 1=5ステップ、0=4ステップ
d6:IRQ 1=禁止 、0=許可
d5: −
d4: −
d3: −
d2: −
d1: −
d0: −
*IRQの禁止・許可はCPU内部・外部の切り替えか?
ただし内部IRQカウンタは未使用
その他(未使用)
$4018 ChB、A(入力) CPU30ピンがHで使用可
$4019 ChC、D(入力) CPU30ピンがHで使用可
$401A ChE (入力) CPU30ピンがHで使用可
Chロック(出力) CPU30ピンがHで使用可
$401B
$401C CPUタイマカウンタ下位 未使用
$401D CPUタイマカウンタ中位 未使用
$401E CPUタイマカウンタ上位 未使用
$401F CPUタイマコントロール 未使用
CPU周り
*CPUの30ピンはX OUTとしています(C1のゲーム基本配線図等)
またPC10では入力端子/SPECIALとなりタイムが0になると
強制ストップする為に使用しています
36、35ピンは/RDP0、/RDP1となっているのもありますが
INP0、INP0、としています
LS139でメモリ、I/Oのデーコードをいます。
CPUが$8000−$FFFFをアクセスすると/ROMSELが0になりROM空間のアクセス
CPUが$2000−$3FFFをアクセスすると/DBE が0になりPPUのI/Oアクセス
CPUが$0000−$1FFFをアクセスすると/RAMSELが0になりワークRAMのI/Oアクセス
ワークRAM
RAM領域は$0000−$1FFFなのですが2KBのRAM$0000−$07FFを載せています
デコードされていないので$0800−$1FFFがミラーイメージになります。
ファミリーコンピュータ以外の機種ではデコードされているのもあります
尚アクセスタイムは150nsのSRAMを使用
I/Oポート周り
40H368を使用しているためポートは1方向(入力)、出力はOUTnになります
PPU周り
2C02の39ピンALEで下位アドレスバスとデータバスを切り換えて使用しているのがわかります
また/VRAM CSとPA13はカセットでショートされていることがほとんどで
PPUアドレス$2000−$3FFFのアクセスをすると本体内のVRAMをセレクトする様になっています。
VA10はカセットのスクロールのジャンパでVA10とPA10で水平、VA10とPA11で垂直の選択になります。
EXT0〜EXT3はPPUマスタとPPUスレーブ制御用
カートリッジコネクタ
コントローラ、その他
コントローラは4021を使用してパラレルからシリアルにして転送します。
Iコンの場合OUT0を1−>0にして4021をシリアルモードに設定します。
読み込むデータ(ボタン)は8つなので読み込むシリアルデータはQ8になります。
4016 D0を1回読むと4016 CUPが1クロック動作するので1つのボタンを読む事になります。
8回読む事で全てのボタンを読む事になります。
IIコンの場合OUT0を1−>0にして4021をシリアルモードに設定します。
4017 D0を8回読みます
外付けIコンの場合OUT0を1−>0にして4021をシリアルモードに設定します。
4016 D1を8回読みます
外付けIIコンの場合OUT0を1−>0にして4021をシリアルモードに設定します。
4017 D1を8回読みます
Iコンの場合"A","B","SELECT","START ","下","上","左","右"の順
IIコンの場合"A","B",0,0,"下","上","左","右"の順
外付けIコン、IIコンの場合"A","B","SELECT","START ","下","上","左","右"の順
1=ボタンが押されている
0=ボタンが押されていない
本体のコントローラと外付けコントローラは別々に判断出来ますが外付けのコントローラも使用できるように
D0とD1を同時に読み込んでデータを合成しています。
ホリカード HJ−12
コントローラは本体のコントローラー同様4021を使用してパラレルからシリアルにして転送します。
OUT0を1−>0にして4021をシリアルモードに設定します。
読み込むデータ(ボタン)は8つなので読み込むシリアルデータはQ8になります。
4016 D1を1回読むと4016 CUPが1クロック動作するので1つのボタンを読む事になります。
8回読む事で全てのボタンを読む事になります。(IIコンの場合は4016が4017になります)
”A”,”B”,”SELECT”,”START”,”下”,”上”,”左”,”右”の順
1=ボタンが押されている
0=ボタンが押されていない
ハイパーショット JE−506
カラオケスタジオの回路図
メインの回路図です。
尚BANK3は実際には使われていないので違う場合があります。
当然マッパの端子名は不明なので勝手につけています。
$6000:入力ポート?
Bit2:???IN0 マイク
Bit1:IN1 START (Bボタン)
Bit0:IN2 SELECT (Aボタン)
$C000:バンク切り換え用 ポート
Bit4:1=M ROM(本体ROM)、0=E ROM(専用カセット)
Bit3:BANK3
Bit2:BANK2
Bit1:BANK1
Bit0:BANK0
*回路図を見て分ると思いますが、画面のミラーリングはポートによって切り換えることが出来ます。
恐らく$C000のBit5か6ぐらいに当てはまると思いますが不明です。
後ろにさすオプションの回路図です。(ただし手持ちは試作品のボードなので市販品と若干違うと思われます。)
BB−10 バトルボックスの回路図
シリアルEEROMを2つ使用で16ビットモードなので128*16Bit*2つの容量(256ワード)です。
左のJKフリップ・フロップはOUT0が入力で2つあるシリアルEEROMのどちらかを選択します。
右のJKフリップ・フロップはP1 CLKが0から1になるたびにQと/Qの値が反転されます。
またOUT0は各シリアルEEROMの/CLKにも繋がっています。
シリアルEEROMにデータを書き込む
左のQはシリアルEEROMにデータを出力します。
左の/Qは$4017のd4に繋がっており、データの出力した反対のデータを読むことが出来ます。
シリアルEEROMにデータ入力はP1 CLKで”1”と”0”が常にセットされることになります、
右のQと/Qは各EEROMの/CSなのでROMの選択。
OUT0がROMの選択、兼ROMの/CLKに使われます。
OUT0のデータをそのままにしておくとP1 CLKで動作する4027の出力データは反転されます。
したがってデータ入力はタイミングを見計らって($4017のd4)、
シリアルEEROMの/CLK($4017のd0)を制御する事になります。
シリアルEEROMのデータを読み込む
シリアルEEROMの/CLK($4017のd0)を制御して、
P1 D3($4017のd3)を読みます。
使用ポート
$4017
d7:−
d6:−
d5:−
d4:P1 D4 =DIの反転の状態で切り替わりのタイミングはP1 CLK(入力)
d3:P1 D3 =シリアルEEROMのDO(入力)
d2:−
d1:−
d0:P1 OUT0=シリアルEEROMの/CLK(出力)
シリアルEEROMなので/CLKとDIでコマンドを送ります。
Command1 Read
A0,A1,A2,A3,A4,A5,A6,0,1,0,0,0,0,0,0,0
Command2 Program
A0,A1,A2,A3,A4,A5,A6,0,0,1,1,0,0,0,0,0,D0,D1,D2,D3,D4,D5,..D14,D15
Command3 Chip Erase
/CLK*9,0,0,1,1,0,0,0,0
Command4 Busy Monitor
/CLK*9,1,0,1,1,0,0,0,0
Command5 E/W Enable
/CLK*9,1,0,0,1,0,0,0,0
Command6 Busy Monitor
/CLK*9,1,1,0,1,0,0,0,0
ターボファイル
74HC368がコントロール、74HC573でシリアル転送、
4024と4040でアドレスのカウンタを行います。
つまり、アドレスの指定してのアクセスは出来ませんので
アドレスカウンタをリセットして
最初のアドレスからアクセスしてアドレスをカウントしていくしかありません。
アドレスカウンタリセット
LDA #$002
STA $4016
NOP*6
LDA #$000
STA $4016
NOP*6
データリード
LDY #$08
LOOP:LDA $4017
AND #$04
LSR A
LSR A
ORA #$06
STA $4016
AND #$03
STA $4016
LSR A
ROR WRITE_DATA
DEY
BNE LOOP
データライト
LDY #$08
LOOP:LDA READ_DATA
AND #$01
ORA #$06
STA $4016
AND #$03
STA $4016
LSR READ_DATA
DEY
BNE LOOP
Home へ戻る