見出し画像

MSXの画面まわりの基礎知識

前回にひきつづいて、目的(なにかしらのゲームを作る)ことに向けて少しずつ学習していきましょう。私も勉強中みたいなものですからあまり詳しくは語れませんが。

VDP(Video Display Processor)

ゲームといえば画面ですよね!画面表示まわりを取り仕切っているチップのことをVDPと呼びます。現代におけるウインドウアクセラレータとかGPUとかはこの系譜です。MSXのVDPはテキサスインスツルメンツ社のTMS9918というチップになっています。TMS9918の仕様は以下のとおりとなります。

TMS9918の主な仕様
・解像度: 256ドット×192ライン
・画面モード
横6ドット×縦8ドット単色キャラクター40文字×24行
横8ドット×縦8ドット単色キャラクター32文字×24行
横8ドット×縦8ドットカラー32文字×24行
 キャラクターグラフィック(PCG): 横8ドット中に16色中2色
 キャラクターパターン: 画面の上段・中段・下段ごとに別々に設定可能
・横4ドット×縦4ドット相当のブロックキャラクタモード64ピクセル×48ライン
・スプライト機能: 8×8ドットまたは16×16ドット、16色中単色、一画面中に32枚・横1ラインに4枚まで同時表示可能。全スプライトパターンを縦横2倍に拡大表示するモードも選択可能。スプライト同士の衝突検出機能あり。スプライトの一つを画面外の特定ラインに配置することで一斉消去する機能あり。
・カラーパレット機能: なし
・ハードウェアスクロール機能: なし
・ビデオメモリ: 最大16KiB。CPUからはVDPを通じてVRAMにアクセス可能。DRAMリフレッシュ機能があり、DRAMを直接接続可能。
・映像出力: NTSC(コンポジット映像信号)。RGBは無し。

https://ja.wikipedia.org/wiki/TMS9918

MSXには3つのスクリーンモードがあります。ゲームといえば"画面”なので基礎を学習してみましょう。

SCREEN0
 上記仕様の横6ドット×縦8ドット単色キャラクター40文字×24行に該当
 このスクリーンモードではスプライトは表示できない。
 あまりゲームでは使われない画面モードだと思います。
SCREEN1
 上記仕様の横8ドット×縦8ドット単色キャラクター32文字×24行に該当
 これはMSX-BASICのゲームとかでは使われる画面モードかも(?)
SCREEN2
 上記仕様の横8ドット×縦8ドットカラー32文字×24行に該当
 キャラクターグラフィック(PCG): 横8ドット中に16色中2色
 キャラクターパターン: 画面の上段・中段・下段ごとに別々に設定可能
 この画面モードこそがMSXの至高!

どのスクリーンモードであっても、パターンジェネレータというものがあって、例えばAという文字(フォント)の形をブロックの形に自由に変更することが出来たりします。

SCREEN2モードでは8ドットあたり16色中から2色を選べます。
MSXで使える色は以下のとおりです。(GreenOwl様のサイトより引用)
色のバーの下に表示されている数字とアルファベット(16進表記)がカラーコードになります。2進表記、10進表記、16進表記については後述します。

https://www.greenowl5.com/gprogram/msx/basic_010.html

上記のうち、カラーコード0は「透明」と定義されていてスプライト以外では使えません。文字の色として使うと背景色と同じ色になります。スプライトを消したり表示したりという場合の「消したい」場合などでカラーコード0は使います(私はあまり使いませんが)

スプライト
8×8ドットまたは16×16ドット、16色中単色、一画面中に32枚・横1ラインに4枚まで同時表示可能。全スプライトパターンを縦横2倍に拡大表示するモードも選択可能。スプライト同士の衝突検出機能あり。

"スプライトはゲームキャラなんだなあ"とイメージしてください。当記事のヘッダ画像に人形のキャラが表示されていますが、それがスプライトです。パッと目には何がスプライトで何がスプライトではないか判別しづらいですが、作っていくうちに「あー、これはスプライトだなー」と判別できるようになっていきます。
スプライトには8x8ドットのスプライトと16x16 ドットのスプライトの2つが選べますが、双方を同時に使用することはできません。また32枚しか同時に表示できません。スプライトの特性として1つのスプライトを定義しようとするとそのスプライトには1色のカラーコードしか割り当てられません。
当記事のヘッダ画像にある人形のスプライトは白色のスプライトとピンク色のスプライトを2枚重ねているため2色で表示されているように見えるだけです。スプライトは横に5枚以上並ぶと5枚目以降が画面表示から消える仕様になっています。とても制約が激しいため、私は自キャラ以外はあまり使う気はしません。"スプライトっていうものがあるんだね"という程度の理解でけっこうです。

MSXの画面制約について商用ゲームでのサンプルがあります。どちらが面白そうだな?と思いますか?(ナムコさんをDisってるわけではありません)
スプライトに頼ると単色になりがちになってしまうので、スプライトとキャラクタ(文字)をうまく使い分けることでMSXでも美麗な表示を行えるようになります。繰り返しますがナムコさん、ディグダグは最高のゲームです!

ディグダグは動くキャラが全部スプライト
グラディウス2はスプライトだけにこだわらない

VDPとVRAM

VRAMって何?という点ですが画面表示を行うためにはVRAM(Video RAM)と呼ばれるRAMに対してデータを書き込むことで画面表示が行われる仕組みになっています。RAMはRandom Access Memoryのことでプログラマが書き換え可能なメモリ空間のことです。書き換え不可能なメモリ空間のことはROM(Read Only Memory)と呼びます。MSXでのROMはBIOSやBASICインタプリタなどが該当します。ちょっと用語がとびかってきだしたのでVRAMに話を戻します。まずはVRAMについてWikiPediaではこう書かれていますね。

VRAM (ブイラム, Video RAM)は、コンピュータなどにおける、ディスプレイに対するビデオ(動画像)表示部分のメモリ(記憶装置)として使われるRAM。グラフィックスメモリまたはビデオメモリ[1]とも呼ばれる。専用のデュアルポートのものもあれば、メインメモリと同じDRAMやSRAMを利用したものもある。かつて、グラフィックス用フレームバッファの為に用意したメモリをG-RAMと表記していた時期もあるが、意味としては等価である。GPU上で汎用計算を行なうGPGPUが普及してからは、グラフィックス用途に限らないデータの処理用途にも転用されている。

https://ja.wikipedia.org/wiki/VRAM

これまたややこしい説明ですが、CPUからの命令で画面に表示したいデータをVDPを経由してVRAMに書き込むことで、結果として画面表示が行われる。という流れになります。逆もまた然りで、画面の情報を取得したい場合はVRAMの情報をVDPを経由してCPUに渡す。ということもします。RAMにはアドレスというものがあってそのアドレスを基準にデータの読み書きをして画面表示を行う。というのがMSXでの画面表示のキホンです。
少年時代はこのVRAMやらVDPやらがさっぱりわかりませんでした。
だいたいのイメージ図は以下のような感じです。

CPU、VDP、VRAMの関連図

これがMSXの"画面表示のすべて"です。この認識を誤るとへんなところでつまずきます。少年時代の私に言いたい。いやテクハンやマシン語入門書に言いたい。「VRAMを先に学べ。先に学ぶように書籍にしてくれ」と、そう伝えたい。そのくらい重要です。

単に画面に表示されている文字もスプライトも色もなにもかもがVDPとVRAMによって制御されます。

前の記事からいきなり難しい話になってしまった感もありますが、これを先に伝えないといけないと思ったのでご容赦ください。。。
どのようにしてVRAMを操作するのか、どのように操作したらどのような結果になるのかについてはまた後続の記事で説明します。

ただ、z88dkとWebMSXについて先に説明しないとその先の説明に進めないので次回はそのへんを説明しますね。

では、また!

マシン語講座:マシン語はかく語りき(2進、10進、16進を覚える)

マシン語プログラムにおいて数字の数えかたを覚える必要があります。
コンピュータは電気で動く機械のため、電源のON/OFFの繰り返しでしかものごとを判別できません。0か1か。ということです。この0か1かという数字は1に1を足すと2になりますが2になると桁が繰り上がります。これを2進数と呼びます。アセンブラの表記としては 0110B などと表記します。BはBinary(2進)の略です。0110B は 10進に変換すると6です。

例)
0B + 1B = 1B
1B + 1B = 10B
1B + 1B + 1B = 10B + 1B = 11B
1B + 1B + 1B + 1B = 11B + 1B = 100B

2進数は右端から1が連続していたら10進数では、1, 2, 4, 8, 16, 32, 64…となります。こんな感じです。???と思うかもしれませんが”慣れ”てくださいとしか言えません・・。マシン語プログラムでは頻繁に出てきます。いやがおうにも慣れるしかありません。

0000001B = 1
0000010B = 2
0000100B = 4
0001000B = 8
0010000B = 16
0100000B = 32
1000000B = 64

10進数の3は 01B(1) + 10B(2) なので 11B です。奇数は全部一番右端が1になります。5は0101B、7は0111B、15は1111B です。

10進数は一般社会でお馴染みの10になったら桁が繰り上がる表記ですね。

例)
1 + 8 = 9
9 + 1 = 10 ← 10なので桁あがり
10 + 8 = 18
18 + 2 = 20 ← 20はまだ桁あがりしない
98 + 2 = 100 ← 100なので桁あがり

16進数はというと・・16になったら桁が繰り上がるのです。これ、わかりづらいかもしれませんが。10以上になったらA(10)から始まりF(15)まで続きます。16になったら桁上がりです。アセンブラの表記としては 1FH などと表記します。HはHexa(16進)の略です。1FHは 10進に変換すると31です。
0AH=10, 0BH=11, 0CH=12, 0DH=13, 0EH=14, 0FH=15,10H=16と覚えておきましょう。

例)
0H + 1H = 1H
1H + 8H = 9H
1H + 9H = AH(10)
AH + 3H= DH(13)
DH + 2H = FH(15)
FH + 1H = 10H ← 10進数での16は16進数では10H(わかりにくいですねえ・・)

VDPの説明で出てきたカラーコードのAとかFとかは10とか15とかを意味します。マシン語では2進数や16進数の単語が頻繁に出てきます。慣れていきましょう。またBとかHとかをつけないとプログラミングで混乱します。
10
と書かれていた場合にそれが2進数なら10進での2だけど、16進数なら10進での16になります。表記にはじゅうぶん注意しましょう。

セーラー服が似合うおじさんです。猫好き、酒好き、ガジェット好き、楽しいことならなんでも好き。そんな「好き」をつらつらと書き留めていきます。