- FPGA:
ModRetro/oss-chromatic-console-fpgav18.8、commit210176f - MCU:
ModRetro/oss-chromatic-console-mcu、commit6c94613
以下は公開ソースを静的に追跡した結果である。回路図や実機波形を使った電気的検証ではない。
Game Boy / Game Boy Color core
├─ LCD pixel stream ─→ color correction / frame blend / OSD
│ ├─→ ST7785 LCD interface
│ └─→ USB UVC 160x144/60fps
├─ stereo PCM ───────→ IIR + DC blocker
│ ├─→ TLV320 audio codec / speaker / headphones
│ └─→ USB UAC 2.0, 16-bit stereo, 44.1kHz
├─ joy P14/P15 ←────── physical buttons + ESP32 virtual buttons
├─ serial port ───────→ physical Game Boy link connector
├─ IR port ───────────→ IR receiver / LED
└─ cartridge bus ─────→ physical 5V cartridge interface
ESP32 ←──115200bps UART──→ FPGA system monitor
├─ OSD/settings, brightness, palette, status
├─ physical button state readback
└─ virtual button injection (command/address 0x09)
ChromaticはGBC対応である。FPGA統合層ではGame Boyコアの isGBC を常に 1 にしている。ブート処理後はCGB対応カートリッジならCGBモード、DMGソフトなら互換モードとして動作する構成である。
実装上確認できるCGB機能には次がある。
- CPU倍速切替(KEY1、4 MHz / 8 MHz相当)
- VRAM bank 0/1
- WRAM bank
- CGBカラー・パレット
- HDMA
- CGBのIRレジスタ
- CGBシリアル高速モード
統合箇所: emu_system_top.v
コアは次のLCDストリームを出す。
gb_lcd_data[14:0]: 15-bit RGBgb_lcd_clkena: 有効画素gb_lcd_mode: LCDモード。水平タイミングにも使用gb_lcd_vsync: フレーム同期gb_lcd_on: LCDオン/オフ状態
vid_system_top は160画素×144ラインのGame Boy映像を受け、15-bit RGBを各色6-bitへ展開する。
- 外部PSRAMを映像・OSD用メモリとして使用する。
- 前フレームを読み、設定に応じてフレームブレンドを行う。
- LCD向けとUSB UVC向けに別々のカラー補正を持つ。
- ESP32が生成するOSD、バッテリー警告、タイマー、デバッグ表示を合成できる。
- ST7785出力とのクロック差をラインバッファで吸収する。
映像処理: vid_system_top.sv
メモリ接続: top.v
起動時は LCD_SPI_CSX/SCLK/SDA と LCD_RESET を使ってST7785を初期化する。表示開始後は次の同期インターフェースを使う。
LCD_DOTCLKLCD_HSYNCLCD_VSYNCLCD_ENABLE(DE)LCD_DB[5:0]LCD_PWM(バックライト)LCD_TE入力
LCD_DB は18本のパラレルRGBではなく、6本へBlue / Green / Redを3位相で時分割している。ラインバッファは各Game Boyラインの160画素を取り込み、パネルタイミングへ合わせて読み出す。
パネル出力: ST7785_panel_master.v
初期化: ST7785_init.v
LCDへ送るのと同系統の映像をUSB UVCへ分岐する。USBディスクリプタ上の映像形式は160×144、16-bit/pixel、60 fpsである。
定義: uvc_defs.v
注意: v18.8の HDMI_* ポートはGame Boy内部信号のデバッグ出力に割り当てられており、HDMI映像送信器ではない。
A、B、上下左右、Start、Select、MenuはFPGAの専用GPIOへ直接入る。通常のゲーム入力はESP32を経由しない。
physical button
→ FPGA GPIO
→ button_debouncer
→ OSD/menu gating
→ opposite-direction filtering
→ Game Boy P14/P15 multiplex
→ joy_din[3:0]
Game BoyのJOYPは4本入力をP14/P15で多重化するため、FPGA側も joy_p54 に応じて次を返す。
01: Start / Select / B / A10: Down / Up / Left / Right00: 両グループの論理積11: 全解放
実装: emu_system_top.v
ChromaticにはESP32からFPGAへボタンを注入する経路もある。FPGAの物理ボタンと MCU_buttons はORされる。
| bit | 入力 |
|---|---|
| 0 | Start |
| 1 | Select |
| 2 | B |
| 3 | A |
| 4 | Up |
| 5 | Right |
| 6 | Left |
| 7 | Down |
| 8 | Menu |
ESP32はUARTコマンドID 0x09 (kTxCmd_PokeButton) でビットマップを送る。FPGAではsystem-monitor address 9 を受信すると MCU_buttons <= rx_data[8:0] とする。
FPGA受信: system_monitor.sv
物理+仮想入力の合成: top.v
ESP32送信: fpga_tx.c
MCUには poke <hex bitmap> というコンソールコマンドもあり、「Chromaticがボタンを押した」状態を擬似生成できる。OSD表示中は物理ボタン状態がFPGAからESP32へ戻され、ESP32側のメニュー操作に使われる。
仮想入力実装: button.c
システム管理用通信は専用UARTで、設定は115200 bps、8 data bits、parityなし、1 stop bit、ハードウェアフロー制御なしである。
FPGA ESP32_MCU_D11 (TX) → ESP32 GPIO10 (RX)
FPGA ESP32_MCU_D12 (RX) ← ESP32 GPIO9 (TX)
V2パケットは概ね次の構造である。
0x8F | command/address | payload length | payload | CRC-8 SAE J1850
ESP32→FPGAには仮想ボタン、システム設定、明るさ、カラーパレット、バージョン要求などがある。FPGA→ESP32には物理ボタン、電池電圧、音量・ヘッドホン状態、PMIC状態、FPGAバージョン、ゲームパレット情報などがある。
FPGA UART: top.v
MCU UART設定: main.c
Game Boyコアのシリアルエンジンは物理 LINK_CLK, LINK_IN, LINK_OUT へ接続されている。内部クロック動作時だけ LINK_CLK を駆動し、外部クロック時はHi-Zにして相手側を受ける。したがってマスター/スレーブ双方のリンク動作を想定した回路である。
実装: emu_system_top.v
IR_RX と IR_LED はGame Boyコアへ直接接続されている。CGBのRPレジスタ(FF56)を通じた赤外線通信を実装できる構成である。
FPGAはUSB側で次の機能をまとめた複合デバイスを実装する。
- UVC: 160×144映像
- UAC 2.0: 16-bit stereo、44.1 kHz
- CDC/UART: ESP32コンソールへのブリッジ
USB CDCのDTR/RTSはESP32のEN/IO0にも接続され、ESP32ブートローダー制御に使われる。これはUSBゲームパッドを読むUSB Hostではなく、Chromatic自身がPCから見えるUSB Device実装である。
実装: usbuvcuart_top.v
物理カートリッジへ次の信号を出している。
- 16-bit address
CART_A[15:0] - 8-bit bidirectional data
CART_D[7:0] CART_RD,CART_WR,CART_CS,CART_CLK,CART_RST- データバス方向制御
CART_DATA_DIR_E - 挿入検出
CART_DET
MBCは実カートリッジ側に存在するため、Chromatic FPGAはカートリッジバスサイクルを生成する。CGBのHDMAやDMA時もこの外部バスへアクセスする。
CART_AUDIN はトップポートには存在するが、調査対象のv18.8 RTL内では音声ミキサーへ接続されていない。
GB/GBC APU 16-bit L/R
→ audio_filter
├─ IIR filter
└─ DC blocker
→ aud_system_top
→ serial audio (AUD_MCLK/BCLK/WCLK/DIN)
→ TLV320 codec
→ speaker / headphones
audio_filter はコア出力の安定化、IIR処理、DC除去を行う。aud_system_top はI2CでTLV320を初期化し、音量、ヘッドホン検出、PMIC状態をポーリングする。
ヘッドホン接続時はステレオ、非接続時は左右を加算したモノラルスピーカー用データへ切り替える。ソフトウェアmute、または音量閾値によるmuteもある。
フィルタ: audio_filter.v
コーデック出力: aud_system_top.v
同じフィルタ済みL/RはUSB UACにも入力される。USB定義は16-bit、2-channel、44.1 kHzである。
UAC定義: uac_defs.v
操作の最短移植は、Chromaticの MCU_buttons とP14/P15多重化をTang版へ移す方法である。
USB gamepad on Mac
→ host utility
→ Dock UART
→ 9-bit virtual button bitmap
→ Chromatic-compatible joy multiplexer
→ Game Boy core
この方式ならUSB HostコアをFPGAへ追加せず、現在のROMローダーUARTをROM転送後の操作チャネルとして再利用できる。将来スタンドアロン化する場合も、ESP32をBLE/USBゲームパッドからUARTへのブリッジとして置けば、Chromaticとほぼ同じ仮想入力経路を維持できる。
- Chromaticの通常操作は物理ボタン→FPGA直結である。
- ESP32とは115200 bps UARTで双方向通信し、OSD管理に加えて仮想ボタン注入も可能である。
- GBC対応は有効で、倍速、メモリバンク、HDMA、カラー、IR、シリアルを含む。
- LCDはST7785をSPI初期化後、6-bit時分割RGB+同期信号で駆動する。
- USBはUVC映像、UAC音声、CDC/UARTを持つDeviceであり、USB Hostゲームパッド入力ではない。
- 音声はAPU→IIR/DC filter→TLV320とUSB UACへ分岐する。
- Tang Primer 20KではESP32仮想入力方式を模倣するのが最短である。