Skip to content

Latest commit

 

History

History
161 lines (81 loc) · 17.7 KB

DESIGN.md

File metadata and controls

161 lines (81 loc) · 17.7 KB

Design Concept

後々、「これはどういう意図で作ったものなのか」をついつい忘れがちなので、設計思想を備忘録として記しておきます。

Qiita でこの文章を元に執筆したより詳細な記事を投稿しています。

Kernel Design Concept

ラズパイ全般(※Picoを除く)は Linux で動かすのが一般的ですが、VGS-Zero は OS 無しのベアメタル環境 で動作するので、レインボースクリーン(VideoCoreIVの初期化処理)の後、わずか2〜3秒でゲームが起動します。

GPi Case や Rockchip や AllWinner などの Linux を用いたよくあるエミュレータゲーム機とは異なり、永い OS のブート待ちに暇を持て余したり、SD カード破損のリスクに怯えることなくサクッとゲームをプレイできます。

些細なことかもしれませんが、どうやら私にとってそれはかなり重要な事のようです。

3秒間で仕度しな!(超絶アスペ?)

これは、私が超絶アスペという訳ではなく、ポケットから取り出して瞬時にスリープモードから復帰してプレイアブルな状態になるデバイス(スマートフォン)に慣れきってしまった現代人にとって死活問題なのかもしれません。

私は GPi Case や中華ゲーム機(RG350など)といったガジェットが結構好きなので何台か持っているのですが、結局のところ Linux + SD カードという組み合わせの悪さ に起因する諸問題がダルくなって遊ばなくなる傾向が見受けられます。

起動速度だけが問題であれば気にならないという、私と違って人間ができた方も多くいらっしゃると思われますが「媒体の耐久性の低さ」は問題だと思う方も多いのではないでしょうか。

一般的な Linux カーネルは OS を起動するだけでも無数のファイル入出力を行うため、入出力(特に出力)の耐久性が極めて低い SD カードで Linux を動かすと、電源断によるデータ破損やファイルシステム不整合などに陥りやすく、メディア交換や OS 再インストールなどの面倒な作業がカジュアルに発生します。

そもそも、Linux カーネルは SD カードにインストールして動かすことを想定した設計ではないと思われます。(参考までにリーナス・トーバルズが Linux の開発を始めたのは 1991 年で、SD カードの規格が制定されたのは 1999 年です)

一方、VGS-Zero は Linux とは異なる Circle ベースの独自カーネルです。

Linux カーネルはサーバ用途、デスクトップ用途、プログラミング用途、ゲーム用途など「何にでも使える汎用性」がありますが、VGS-Zero カーネルは ゲーム(game.pkg)しか 動かすことができません。

VGS-Zero カーネルが SD カードへの I/O を行うのは、ブート時の game.pkg の読み込み(read only)と、save.dat(セーブデータ)のロードとセーブに限られています。

game.pkg のサイズは最大 16 MB (128メガビット) です。

「100メガショック」で有名なあの NEO-GEO を上回る巨大なサイズですが、RaspberryPi Zero 2W には無限に等しいサイズの RAM(512MB)が搭載されているので、ブート時に全て読み込んで記憶することが可能です。

また、VGS-Zero のセーブデータは最大でも 16KB と極めて小さく、更にデータの中身に更新が無いセーブデータの保存リクエストはカーネルが write skip することで、書き込み耐久性が極めて弱い SD カード媒体の寿命を最大限に延ばす「SD カードに優しいデザイン」になっています。

VGS-Zero 独自カーネルは RaspberryPi Zero 2W のクアッドコア(4 コア)の CPU リソースのほぼ全てを余すこと無く使用して Z80、VDP、VGS(音声システム)のエミュレーションによりゲームを動かします。

ゲームを動かすのにエミュレーション技術を採用する目的は、VGS-Zero カーネルとゲームのコードバイナリの分離 です。

Windowsなら.exe、Linux なら elf に相当するものが VGS-Zero の game.pkg です。

VGS-Zero カーネルは、GPL の OSS などもゴリゴリ使っているため、実行形式ファイルをカーネルから分離しなければゲーム側のライセンスを自由に設定できない不自由が生じます。

そのような不自由は避けたかったため、game.pkg をカーネルから分離しました。

なお、それだけの理由なら .exe や elf などと同じようにネイティブコード(ARMv8)の実行形式ファイルにした方が性能面でのメリットが大きいです。

しかし、ゲームのコードが ARMv8 に依存すると将来的に互換性の問題が発生することになるので、VGS-Zero では LLVM の代用として Z80 を採用しました。

幅広いプログラミングを行う上で Z80 では不便なところも多いかもしれませんが、ゲームのプログラミングであれば Z80 で必要十分だと私は考えています。

これは、若干暴論かもしれません。

ただし、少なくとも私が創りたいゲームに関しては Z80 で必要十分だという点については断言できるので、色々な意味で都合の良い Z80 エミュレータ も自作した形です。

Hardware Design Concept

VGS-Zero には 16MHz の高速な Z80 CPU(エミュレータ)が搭載されていて、更に 16KB の巨大な RAM 領域の全てを ゲームプログラムで専有 することができます。

実際に Z80 CPU のコンピュータでプログラミングした経験があれば、16KB は必ずしも「巨大なサイズ」ではないと感じるかもしれません。

例えば MSX2 なら最低でも 64KB の RAM が搭載されていますし、PC-8801 のメイン RAM も 64KB です。

VGS-Zero は 16KB の RAM でも必要十分になるようにハードウェア全体での最適化設計がされているため、実際にプログラムを組んでみると大きすぎて持て余す筈です。

参考までに、Battle Marine が使用している RAM サイズは(スタック領域と合算しても)2KB 以下です。これは、メモリ削減に苦労した結果ではなく、むしろ(何も考えずに)かなり冗長に作った結果が 2KB でした。つまり、その 8 倍の 16KB もあれば、プログラマが「メモリが足りない!!」と嘆くことはほぼ無いと想定しています。

(Split Sound System from game core)

Z80 時代の一般的なゲームコンソールでは、AY-3-8910 (PSG 音源) や FM 音源などのチップチューン音源で音楽や効果音を再生するため、チップチューン音源の制御プログラム(音源ドライバ)に一定量の CPU リソースを割り当てる必要があり、また音楽や効果音のシーケンスデータやシーケンス制御処理用に一定量の RAM リソースを割り当てる必要があります。

VGS-Zero には VGS (Video Game Sound) という SUZUKIPLAN が開発した独自のチップチューン音源を搭載していますが、この音源ドライバ・プログラムは RaspberryPi Zero 2W のネイティブ・コード (ARMv8) で動作し、音楽(MML)と効果音(.wav)のデータもネイティブ RAM (512MB) 側で管理しているため、ゲーム側(Z80)の CPU と RAM を一切専有する必要がありません。

また、開発難度が高い音源ドライバの開発リソース(予算)をゼロに出来る点も大きいかもしれません。

音源ドライバを開発するのはそこそこ大変なので、PC-9801 版の東方 Project(旧作)でも PMD という音源ドライバが使われています。PMD は商用のゲームソフトでも使われているものが多くあります。PC-9801 では PMD 以外にも FMP やツクールシリーズの MUSIC.COM なども有名だったかもしれません。

(VDP specialized for Z80)

VGS-Zero は、VDP(Video Display Processor)を用いてグラフィック出力をする古典的なテクノロジーを採用したゲーム機です。

そのため、MSX、ファミコン、SG-1000、セガ・マスターシステム、ゲームギア、メガドライブ、スーパーファミコン、X68000 あたりの VDP (PPU) を搭載したコンピュータでゲーム開発経験があるプログラマであれば、ほぼ学習無し(VRAM メモリマップを参照するだけ)でプログラミングできるものと思われます。

フルアセンブリ言語で記述する必要が無い分、それらのコンピュータよりも更に難度が低い筈です。

また、一般的な VDP では 2 回の OUT ポート出力で VRAM アドレスをセットしてから I/O で VRAM の入出力をする必要がありますが、VGS-Zero の VDP(VGS-Video)は VRAM が Z80 から見えるメモリ上(0x8000〜0xBFFF)にマッピング(mmap)されているので、I/O 命令無しで VRAM へのアクセスができます。

そのため、仮にフルアセンブリ言語で組むにしても MSX やセガ・マスターシステムよりも簡単にプログラミングができます。

VGS-Video では、BG(背景)、FG(前景)、スプライトの3レイヤーを扱うことができ、BG/FGを独立してハードウェアスクロールすることができ、スプライトは256個を同時に表示でき、水平上限がありません。(これは Z80 全盛期の時代のハードウェアでは実現が難しかった)

スキャンライン位置は、セガ・マスターシステム、ゲームギア、メガドライブなどと同様にVカウンタで取得できるため、ラスタースクロールの為に IRQ を実装する必要がありません。

一応 IRQ を使うこともできるようになっていますが、IRQ 一切無しでプログラミング可能なハード仕様にしました。

VGS-Video の弱点としては、スーパーファミコンやメガ CD の VDP のような回転、拡大・縮小、半透明には対応していない点かと思われます。

また、ポリゴンは使えません。

メガドライブや X68000 相当の VDP をシンプルに強化したイメージ でハードウェア仕様を設計しています。

(Hardware Accumulator for Z80)

Z80 でゲームプログラミングをすると、2のn乗を除く乗算、除算、剰余算やアークタンジェント(角度を求めるために必要な三角関数)の計算処理がボトルネックになりがちですが、それらの計算処理を高速に実行できる HAGe; High-speed Accumulator for Game と呼ばれるゲーム向けの演算用途に特化したハードウェアを搭載しています。

これらの演算はゲームで必要になるシーンが多いので、ゲームを高速に動かす上では非常に有用です。

また、C言語の memset, memcpy に相当する DMA ハードウェアも搭載しているので、メモリ間のブロック転送が(LDIRよりも)かなり高速に実行できます。

これらの特徴により 「C言語のみ」でもメガドライブの商用ゲーム相当のゲームが開発可能 にすることがゲームハードウェアとしての VGS-Zero の基本コンセプトです。

Programming Language Concept

一般的な Z80 を搭載しているゲーム機(セガ・マスターシステム、ゲームギアなど)やパソコン(MSX、PC-88など)でクオリティの高い商用ゲーム開発をするにはフルアセンブリ言語でのプログラミングがほぼ必須です。

もちろん、性能がそれほど要求されないタイプのゲーム(ADVやSLGなど)であれば、商用ゲームでもC言語やBASICで作られたものもあったかもしれませんが、Z80全盛期(1980年代〜1990年代前半ごろ)のゲームの花形はアクションゲームで、大量のキャラクタを滑らかに動かす必要があります。

大量のキャラクタを滑らかに動かそうとすると、BASICはもちろんC言語でも結構厳しくなります。

私は VGS-Zero 以外にも、Z80A 相当(約4MHz)の CPU を搭載した FCS80 というゲーム機も別途開発しましたが、実際に FCS80 で 256 個のスプライトを滑らかに動かす example を実装してみたところ、アセンブリ言語のみで書けば滑らかに動きましたが、C言語ではスプライト数を64個まで減らす必要がありました。(Cコンパイラの最適化がイマイチという説もあります)

ですが、VGS-ZeroならC言語で256個のスプライトを滑らかに動かせます!!

商用ゲームでもC言語が使われ始めたのは16ビットCPU以降(パソコンならPC-9801やX68000など)かと思われます。

私はその時代の商用ゲームを作ったことが無いので実際のところは分かりませんが、16ビットの時代はフルアセンブリ言語で作られたプログラムが神格化されつつあり、32ビット時代になると完全なオーパーツ(幻想入り)になったという印象です。

ですが、VGS-Zeroのスペック(16MHz)なら 8 ビット CPU でもC言語で十分商用クオリティのゲーム開発が可能だと考えています。

ちなみに Z80 を 16MHz にした理由は、ターゲットデバイス(RaspberryPi Zero 2W)のベアメタル環境(OSを用いずCPUとRAMを完全専有できる環境)のシングルコアで Z80 エミュレータ(自作)を動かす限界性能が 16MHz だったためです。

https://note.com/suzukiplan/n/nfc0106624c1f

ターゲットデバイスを RaspberryPi 4 にすれば、Zero2 の 1.5 倍ぐらいの速度なので 24MHz ぐらいでもイケたのですが、4は結構高い(1万円ぐらいする)ので、約 3,000 円ぐらいでお手軽に購入できる Zero2 を採用しました。

本当はもう少しだけ速くしたかったですが...

(具体的には 80486 ぐらいの性能が欲しかった)

実現できるかは分かりませんが、VGS-Zero の SDK を 任天堂Switch に移植する計画があり、任天堂Switch なら RaspberryPi Zero 2W よりも確実に性能が良い筈なので、任天堂Switch 版 VGS-Zero SDK では Z80 のクロックレートをもっと引き上げるかもしれません。

Marketing Concept

VGS-Zero は一応「ゲーム機」と名乗ってますが、既存のゲーム機に競合するつもりは全く無くて、仮に何らかのマーケットを狙うとすれば 新しいゲームを開発する上でのテストプラットフォーム のようなポジションです。

もちろん、Unreal Engine などのガチのゲームエンジンと競合するつもりはなくて、ハイクオリティな(AAAタイトル等の)ゲーム開発なら VGS-Zero よりも Unreal Engine 等の方が優れているのは明白です。

ですが、開発予算はかなり抑える事ができます。

具体的には、ゲーム開発を専門とする企業が本気で開発しても スーパーファミコンやメガドライブの頃のソフト(1タイトル1,000〜5,000万円ぐらい)ぐらいの予算感でゲーム開発&販売が可能です。

BGM(VGS)の仕様のクセが強めですが、サウンド系のプログラミングが不要というメリットがあるので、サウンドドライバのプログラミングが必要だったスーファミやメガドラの開発費よりも安く抑えられるかもしれません。(BGM のクオリティ面ではVGSの「BGMだけ」でもヒットアプリを創ることができたので問題無いかなと)

先ずは 3,000 万円前後のお手頃な予算で VGS-Zero 向けにゲームをサクッと作って販売し、そこでヒットしたタイトル(ドラクエなりFFなりのようなタイトル)が創れたら Switch や PlayStation 向けにしっかりとした予算(うん億円?)を組み、Unreal Engine なりを使ってゲームを開発すれば、投資効率良くハイクオリティな面白いゲームを世に出せるのではないか?...と、思ったり思わなかったりしています。

実のところ私は AAA タイトルのようなものには全然興味が無くて、ゲームはPCエンジンやメガドライブぐらいの頃のものが混沌としていて面白かったと思っている節もあります。

私が VGS; Video Game System で創りたいものは 「私にとって最もビデオゲームが創作しやすいプラットフォームの創出」 の一点のみで、この点に限れば VGS の初期設計をした 10 年以上前からずっと揺らいでいません。