
昨今「バイブコーディング」が話題になっているので、乗り遅れないようにチャレンジしてみた成果物です。
今回作っているのは、PC-98で動作するADV(ノベル)ゲームエンジンです。
この記事では、現在実装しているスクリプト仕様を整理してまとめます。
このエンジンでは、script.txt を用意することで、背景表示・立ち絵・会話・選択肢・分岐などを制御できます。
なお本プロジェクトは、ChatGPTやCodexを活用しながら開発しています。
コード生成の大部分(99%以上)はAIに支援してもらっています。
実機での動作確認や仕様の調整だけは自分で行っています。
PC-98という制約のある環境でどこまで作れるか、試行錯誤しながら開発しています。
本記事はネット上からいつでも見れるようにするための管理人のメモ書きです!
バイナリの配布(githubの公開)はそのうち公開予定ですが直近ところはありません。
ちなみに本記事は非常に説明的になっていますが、これはソースコードをChatGPT先生に読んでもらって、「現在の仕様と今後の課題を出して」と頼んだ結果をほぼ未修正でコピペしたためです。
チャレンジしてみた結果
チャレンジしてみた結果です。 こういうの出来ました。
開発環境
AIツール
本プロジェクトでは以下のAIツールを活用しています。
- ChatGPT
- Codex(CLI)
コード生成や仕様検討の大部分はこれらのAIに支援してもらっています。
開発環境
- Windows 11(25H2)
- WSL(Ubuntu)
- ia16-elf-gcc(MS-DOS 向けクロスコンパイラ)
- VS Code
主にWSL上で開発し、C言語 (イン アセンブラ) でエンジンを実装しています。
環境構築方法は以下リンクです。
Codexに丸投げでPC-98のHello Worldを実機で動かすまで(WSL+ia16環境構築) - PokuG stdio.h
実行・確認環境
- エミュレータ:T98-NEXT
- 実機:PC-9821Ra43、PC-9821V13
- OS:MS-DOS6.2、MS-DOS5.0A-H
開発中はエミュレータで確認しつつ、最終的な動作は実機で確認しています。
PC-98 ADVエンジン script.txt 命令メモ
自作PC-98 ADVゲームエンジン用の script.txt の書き方メモです。
自分が忘れないための説明書として、現在の仕様をまとめています。
基本ルール
スクリプトは script.txt に書きます。
大きく分けると、行には2種類あります。
#で始まる行 → 命令 [名前] → 話者名 普通の文章 → メッセージ本文
例:
#bg bg01 #right character01 normal [美緒] こんにちは、健一。 [健一] えっと……呼び出したのは美緒だよね?
こんな感じになります。 www.youtube.com
表示仕様
現在のメッセージ表示は以下の仕様です。
1行:25文字 表示:3行
文章が長い場合は、エンジン側でページ送りされます。
基本操作は Enter キーで進行します。

背景表示:#bg
背景を変更する命令です。
#bg bg01
現在使える背景ID:
| スクリプト | 読み込むファイル |
|---|---|
#bg bg01 |
bg001.g98 |
#bg bg02 |
bg002.g98 |
#bg bg03 |
bg003.g98 |
例:
#bg bg01 [] 教室は静かだった。 #bg bg02 [] 廊下に出ると、夕方の光が差し込んでいた。
背景ファイルは PC-98 / DOS で扱いやすいように、8.3形式のファイル名にしています。
bg001.g98 bg002.g98 bg003.g98
立ち絵表示:#left / #right
左側または右側にキャラクターを表示します。
#left character01 normal #right character02 happy
書式:
#left キャラID 表情 #right キャラID 表情
現在使う想定のキャラID:
| キャラID |
|---|
character01 |
character02 |
character03 |
現在使える表情:
| 表情 | 意味 | ファイル名の記号 |
|---|---|---|
normal |
通常 | n |
happy |
笑顔 | h |
angry |
怒り | a |
surprised |
驚き | s |
実際に読み込むファイル名は以下のようになります。
| スクリプト | 読み込むファイル |
|---|---|
#right character01 normal |
c01_n.spr |
#right character01 happy |
c01_h.spr |
#right character01 angry |
c01_a.spr |
#right character01 surprised |
c01_s.spr |
#left character02 normal |
c02_n.spr |
#left character03 happy |
c03_h.spr |
例:
#bg bg01 #right character01 normal [美緒] ちょっと聞きたいことがあるんだけど。 #right character01 angry [美緒] 冷蔵庫のタルト、知らない?
立ち絵を消す:none
立ち絵を消したい場合は、キャラIDに none を指定します。
#left none #right none
例:
#right character01 normal [美緒] またあとでね。 #right none [] 美緒は教室を出ていった。
話者名:[]
話者名は [] で指定します。
[美緒] こんにちは。
名前なしの地の文にしたい場合は、空の [] を使います。
[] 誰もいない教室は、妙に静かだった。
選択肢:#choice
2択の選択肢を表示します。
書式:
#choice ラベル1 ラベル2 選択肢1の文章 選択肢2の文章
例:
#choice ask help 素直に手伝う 少しだけ断ってみる
選択肢1を選ぶと #label ask へ移動します。
選択肢2を選ぶと #label help へ移動します。
操作:
↑ / ↓ キー W / S キー 8 / 2 キー Enterで決定
ラベル:#label
ジャンプ先の目印です。
#label start
#label 自体は画面には表示されません。
例:
#label ask [健一] わかった。僕でよければ手伝うよ。
ジャンプ:#jump
指定したラベルへ移動します。
#jump ラベル名
例:
#jump common_route
選択肢のあとに共通ルートへ戻すときに使います。
#choice route_a route_b 手伝う 断る #label route_a [健一] わかった。手伝うよ。 #jump common #label route_b [健一] ごめん、今は少し難しいかも。 #jump common #label common [] こうして、放課後の調査が始まった。
フラグを立てる:#set
フラグをONにします。
#set flag_name
例:
#set helped_mio
フラグを消す:#reset
フラグをOFFにします。
#reset flag_name
例:
#reset helped_mio
条件分岐:#if
フラグがONのときだけ、指定したラベルへジャンプします。
#if フラグ名 ラベル名
例:
#if helped_mio good_route
helped_mio がONなら #label good_route へ移動します。
OFFなら、そのまま次の行へ進みます。
条件分岐:#ifnot
フラグがOFFのときだけ、指定したラベルへジャンプします。
#ifnot フラグ名 ラベル名
例:
#ifnot helped_mio normal_route
helped_mio がOFFなら #label normal_route へ移動します。
パレット変更:#pal
外部パレットファイルを読み込みます。
#pal adv.pal
基本的にはゲーム開始時に adv.pal を読む想定です。
演出用に途中でパレットを変えることもできます。
例:
#pal adv.pal #bg bg01
ファイル名ルール
PC-98 / DOSでは、基本的にファイル名は8.3形式です。
ファイル名:8文字まで 拡張子:3文字まで
そのため、以下のような長い名前は避けます。
stand_character01_normal.spr ← 長すぎるのでNG
現在の推奨ルール:
背景
bg001.g98 bg002.g98 bg003.g98
立ち絵
c01_n.spr c01_h.spr c01_a.spr c01_s.spr c02_n.spr c02_h.spr c02_a.spr c02_s.spr c03_n.spr c03_h.spr c03_a.spr c03_s.spr
画像サイズの現在仕様
背景
640 x 400
背景は .g98 形式です。
立ち絵
最大 256 x 290
現在の立ち絵読み込み処理では、横幅256pxまでが安全です。
横幅280pxなどにすると読み込みエラーになります。
スクリプト例:基本
#pal adv.pal #bg bg01 #right character01 normal [美緒] 健一、ちょっといい? [健一] どうしたんだ? #right character01 angry [美緒] 冷蔵庫のタルト、知らない? [健一] えっ、僕は知らないよ。
スクリプト例:選択肢と分岐
#bg bg01 #right character01 normal [美緒] 犯人探し、手伝ってくれる? #choice help refuse 手伝う 断る #label help #set helped_mio [健一] わかった。僕でよければ手伝うよ。 #jump after_choice #label refuse #reset helped_mio [健一] ごめん、今はちょっと難しいかも。 #jump after_choice #label after_choice #if helped_mio good #ifnot helped_mio normal #label good [美緒] ありがとう。助かるよ。 #jump end #label normal [美緒] そっか……わかった。 #jump end #label end [] こうして放課後の時間が過ぎていった。
選択肢「YES」の場合
www.youtube.com
選択肢「NO」の場合
www.youtube.com
現在の命令一覧
| 命令 | 用途 |
|---|---|
#bg |
背景変更 |
#left |
左立ち絵変更 |
#right |
右立ち絵変更 |
#choice |
2択選択肢 |
#label |
ジャンプ先ラベル |
#jump |
ラベルへ移動 |
#set |
フラグON |
#reset |
フラグOFF |
#if |
フラグONならジャンプ |
#ifnot |
フラグOFFならジャンプ |
#pal |
パレット読み込み |
注意点
- ファイル名は8.3形式にする。
- 背景は
bg001.g98のような短い名前にする。 - 立ち絵は
c01_n.sprのような短い名前にする。 - 立ち絵の幅は最大256pxまで。
#choiceは2択専用。#choiceの直後2行が選択肢文になる。#labelは画面には表示されない。#jumpや#ifのラベル名には#labelは付けず、名前だけを書く。
追記 -BGM関連
PMD.COM 常駐環境での BGM 再生に対応しています。
対応コマンド
| コマンド | 内容 |
|---|---|
#bgm opening.m |
BGMファイルを読み込み再生 |
#bgmstart |
現在ロード済みBGMを再生 |
#bgmstop |
BGMを即停止 |
#bgmfade |
BGMをフェードアウト停止 |
使用例
#bg classroom #bgm school.m [美緒] 「おはよう」
■ 画像変換ツール
本エンジンでは、PNG画像をそのまま読み込むことはできないため、専用フォーマット(.g98 / .spr)に変換する必要があります。
なお、PNG画像は aseprite などドットの編集ソフトで作成します。
このとき16色で画像を作成し、キャラ / 背景 / UI を "1画面にに表示する" ので同じ16色で統一する必要があります

■ 背景画像:PNG → G98
背景画像は 001_png_to_g98.py を使用して .g98 に変換します。
● 使い方
python3 tools/001_png_to_g98.py input.png bg001.g98
● 出力ファイル
bg001.g98 bg001_preview.bmp
bg001.g98→ ゲームで使用する背景ファイルbg001_preview.bmp→ 変換結果の確認用BMP
● 処理内容
- 画像を 640×400 にリサイズ
- 固定16色パレットへ減色
- パレット番号 0〜15 をそのまま使用
- パレット0は予約色(透過扱い)
● 注意点
・サイズは必ず 640×400 に変換される ・色は16色に減色される ・見える黒は自動で別色に逃がされる
■ キャラ画像:PNG → SPR
立ち絵は 010_png_to_spr.py を使用して .spr に変換します。
● 使い方
python3 tools/010_png_to_spr.py input.png c01_n.spr
● 出力ファイル
c01_n.spr c01_n_preview.bmp c01_n_checker.bmp
c01_n.spr→ ゲームで使用する立ち絵*_preview.bmp→ 通常確認用*_checker.bmp→ 透明部分確認用(市松模様)
● 処理内容
- RGBA画像を読み込み
- 透明部分 → パレット0へ変換
- RGB → 固定16色パレットへ変換
- 最近傍色で色を割り当て
● 透明処理の仕様
透明(alpha) → index 0
ただし、
黒 (0,0,0) は透過と衝突するため、 見える黒は index 2 に変換される
● 注意点
・パレット0は必ず透明になる ・黒をそのまま使うと消えるので注意 ・画像サイズは自由(ただし描画側に制限あり)
■ ファイル命名ルール(重要)
PC-98のDOS制約により、8.3形式を守る必要があります。
● 背景
bg001.g98 bg002.g98 bg003.g98
● キャラ
c01_n.spr c01_h.spr c01_a.spr c01_s.spr
■ サイズ制限
| 種類 | サイズ |
|---|---|
| 背景 | 640×400 |
| 立ち絵 | 最大 256×290 |
※ 立ち絵は横256pxを超えると読み込みエラーになります
■ メモ(重要)
・PNGから直接変換できる ・確認用BMPを必ずチェックする ・色ズレはここで発見できる ・透明処理はindex 0固定
■変換 まとめ
- 背景 → PNG → G98(640×400固定)
- キャラ → PNG → SPR(透過対応)
- どちらも確認用BMPが出力される
この変換ツールを使うことで、PC-98用の画像素材を簡単に作成できます。
未実装・今後の課題
現在のエンジンは基本的な動作はできていますが、 まだ未実装・改善予定の機能があります。
描画の高速化
現状は背景や立ち絵を毎回描画しているため、 シーンによっては描画が遅くなる場合があります。
今後は以下の対応を予定しています。
・同じ背景の場合は再描画しない ・立ち絵の差分再描画(変更部分のみ描画) ・画面更新の最適化
VRAMバッファ未実装
現在はVRAMへ直接描画しているため、 描画の途中経過がそのまま画面に表示されてしまいます。
・背景 → 立ち絵 → テキスト
のように順番に描画されるため、 場合によっては描画のチラつき(フリッカー)が発生します。
今後は以下の対応を予定しています。
・オフスクリーンバッファの導入 ・一度メモリ上に描画してからVRAMへ転送 ・画面更新の一括処理
これにより、
・描画のチラつき軽減 ・見た目の安定化 ・高速化
が期待できます。
メモ
現在は「直接VRAM書き込み」方式 将来的には「ダブルバッファ」的な構造にする予定
PC-98のVRAM構造上、実装方法には制約がありますが、 可能な範囲で改善を検討しています。
FM音源未対応
現在は音声機能は未実装です。
・BGM再生(FM音源) ・効果音
PC-98らしさを出すため、将来的には FM音源(OPN系)の対応を検討しています。
セーブ/ロード機能
現状はセーブ機能がありません。
・スクリプト位置の保存 ・フラグ状態の保存
テキスト表示機能の拡張
・自動送り(オートモード) ・スキップ機能 ・表示速度調整
UI改善
・メッセージウィンドウの強化 ・選択肢UIの改善 ・名前表示の専用枠
スクリプト機能の拡張
・変数対応 ・複雑な条件分岐 ・マクロ的な機能
今後について
まずは描画の最適化を優先し、 その後に音やUIなどを順次追加していく予定です。
PC-98という制約のある環境で、 どこまで快適なゲーム体験を作れるかを目標に開発を続けていきます。