当初、マップはそのままの配置データを RLE圧縮(ランレングス)で保持していました。無圧縮だと 2.8KBですが、この圧縮で 1.7KBには縮んでいたので、これで良いと思っていました。

これがすぐにぶっちぎりに甘い見積りだったとすぐに思い知らされる事になります。今回はサイズ的にもかなりのウェイトを占める、マップデータを如何にメモリに収めたかの顛末についてお話しします。


  • データ圧縮をいろいろ試す
メモリの枯渇が見えてきたのでさらなる圧縮を考えました。当初は先に書いたとおりRLE圧縮でした。連続したデータがあれば圧縮されます。でも、そんな都合の良いデータでは無かったのです。空白部分ですら、アトリビュートエリアがデータの連続性を阻害しました。
マップ
そこで次に検討したのが BPE圧縮です。これは読んで字が如く Byte の Pair で Encode する技術です。ファミコンの頃から存在している手法だったりします。マップをよく見ると、2バイトで一つのオブジェクトを形成しているような形状が多い事が分かります。これは期待が出来るかもと、C# で圧縮プログラムを書いてテストしてみました。

  • 無圧縮       2.8KB
  • RLE圧縮    1.7KB
  • BPE圧縮    1.4KB

縮みはしましたが、正直微妙な結果に…。そんな中、ネットで Exomizer という圧縮を知りました。Z80 展開ルーチンが付いていて高圧縮そこそこ高速。これは試してみるしかない!

  • 無圧縮                2.8KB
  • RLE圧縮               1.7KB
  • BPE圧縮               1.4KB
  • BPE + Exomizer   1.2KB

さらに微妙な結果に…。


  • 根本的にデータ形式を見直す
高圧縮を求めて対応し続けたが現段階で最高 1.2KB。最終的には全10面を入れたいので、単純計算で12KB必要となります。この時の残りメモリは、8KBを切っていました…。まだサウンドデータが入ってないし、あれもこれも作ってない。そもそも圧縮率42.8%って凄い事なんです。凄い事やって足りないのなら、そのデータ構造ダメやんね…。

そう!データ構造そのものが抜本的に拙いのだ!!

そこで私は仕様の見直しを始めました。まず、画面全体をそのまま保持する考え方そのものを止める事にしました。よくよく考えたら、そんな贅沢なデータの持ち方ってないよなあと。仮配置されたマップをよく見ると、マップ内にはオブジェクト毎にパーツ化できる塊がありました。この塊をエディタで事前に作成して、そのパーツをどこに配置するかだけをデータ化すれば軽いんじゃないのか?

また、複数ステージで流用するパーツも当然あるはずです。それも使い回す事にして、さらにマップに使用する PCGはステージ毎に要る要らないがあるので、まとめて全種類を定義しておくのは勿体ない事にも気がつきました。PCGは同時に最大37個までだけど、全10面で 370個の PCGデータは要らないですよね。例えば樹木パターンはどのステージにも使うわけだから、使う分だけトータルで管理すればデータ量は減るはずです。
[umbar net] 圧縮バッグ 衣類圧縮 旅行 トラベルバッグ 防水 YKK コーデュラ トラベルポーチ
【広告】
[umbar net] 圧縮バッグ 衣類圧縮 旅行 トラベルバッグ 防水 YKK コーデュラ トラベルポーチ
umbar net
※ 圧縮と言えば、お出掛け荷物の圧縮も手軽にしたいですよね。


  • 新マップデータ構造の構築
PCGは全てのステージで使用済みだけを分解して保持する事にしました。そのため、マップエディタには PCG管理専用のダイアログを準備する事にしました。
PCGリスト
オブジェクトの塊を事前に編集するダイアログを別途用意して、データを吐き出す際は使用済みだけとする事にしました。
パーツリスト
そして、上記で編集済みのPCGとオブジェクトをステージ毎に、配置座標データを作成する事にしました。このような数段階の分離形式にはなりましたが、思惑通りのデータ形式で実際に落とし込む事が出来ました。
マップ
そして、マップの作成中にふと気がついた事が。マップの配置データの半分を次のステージの配置データに活用すれば、少なくとも配置データは半減するし、マップの連続性もよくなるし、データ作成もラクだし!このアイディアは使えないかと!

具体的には、このマップデータから…
このマップデータから

次のステージに繋がる左半分だけを取り出して、右側に単純移動させます。
左半分を右に移動

この前回のマップを下地として、次のマップに必要なオブジェクトを継ぎ足していきます。
不足分は新しくオブジェクトを継ぎ足す
これならかなりの省メモリに貢献するのでは無いかと期待が膨らみます。そして、マップに連続性が出来た事から、思わぬ副産物が。意図せず10面全てのマップに、ゼビウスのマップのようなストーリー性が生まれたのです!
マップの連続性
右側から左側に進んでいく事で、最初に山間部に現れた怪獣が、最終的には都市部の地球防衛隊本部まで到達するという流れが、勝手に出来てしまったのです。いやー、これは本当に棚ぼたでした。このゲームにストーリー性が加わって、ますます完成度が上がった気がした瞬間でした。


  • 再度データ圧縮を行う
全10面ではありますが、マップはそのとき使用するステージだけを展開して、それ以外はメモリ上に圧縮して待避させておくのがベストです。展開バッファが必要になりますが、PCG定義データ、オブジェクトパーツ、配置データという3種類をメモリに展開しなくてはいけません。そのため、ゲーム中に使用しているバックバッファをその裏方データの展開に使用しました。

その展開したデータを元にマップを再構築するのは、VRAMそのものです。このゲームでステージ切り替え時に、ペンゴのマップ生成のように、マップが作られていく過程が見えるのは、そのような理由からです。ただ、展開が見えるおかげで、1秒ちょっとの待ち時間が全く苦にならなくなりました。寧ろ速いと感じられるぐらいです。作られていく過程が見えるのは楽しいですからね。

実は最初はDMAを止めて裏方で高速展開にしていたのですが、1秒がコンマ数秒になったところであまり速くなった気がしないのと、例の cocopar のモニタがやっぱり画面復帰時に荒ぶってくれたので、この方法は採用できませんでした。もし、cocopar が荒ぶらなければ、このゲームはもう少し違ったテイストになっていたかもしれないですね…。

圧縮展開は Exomizer をおいて他の選択肢は考えられません。早速試してみます。
  • 無圧縮                    2.8KB
  • RLE圧縮                   1.7KB
  • BPE圧縮                   1.4KB
  • BPE + Exomizer       1.2KB
  • 新構造 + Exomizer   0.3KB
うわははは!やった、やったぞ!めっちゃくちゃ小さくなったぞ!!


  • ライセンス問題発生
Newシティヒーロー完成後暫くして、BEEPさんからパッケージ販売のオファーがありました。そこで、使用しているソフトなどの権利に問題が出ていないか確認をしていたのですが、ひとつかなり致命的な問題が発覚しました。それがよりによって Exomizer だったのです。Exomizer そのものは使用に関して特に問題になる事は無かったのですが、そこに同梱されている Z80 プログラムは別の人が使ったモノで、ライセンス形式は残念な事に LGPL だったのです。

LGPL の何が問題かというと、このライセンスのプログラムを組み込んだ製品は、同じく LGPL ライセンスとしなければならないという事です。自由に使って良いソフトを売り物にする事は出来ません。さりとて、この高い圧縮率でかろうじてメモリ内に収まっているデータを、今更外す事が出来ず。

悩んだ挙げ句、私は一度は Exomizer の使用を諦めて、LZSA2 で組み込む決意をしました。圧縮すると、120バイト程度溢れてしまいました。そこでプログラム書き換えなどを駆使して、涙ながらの努力でようやくメモリ内に収めた直後ぐらいのタイミングで、なんと有志による Exomizer の Z80 デコードプログラムが zlibライセンスで公開されたのです。まるで、私が困っているのを見計らって、わざわざ作って頂いたかの如きタイミング💦

また Exomizer に戻して、浮いた 120バイト強で、ボーナスステージを追加する事にしました。そこでまたまたメモリとの戦いになってしまったのですが、なんとかなってしまうモノですね。それで、Newシティヒーロー v1.2 には、ボーナスステージが付いているというワケなんです。

いやー、奇跡って続くモノなんですね😁


Newシティヒーローメイキング・インデックス
  1. Newシティヒーローメイキング
  2. スタッフアサイン
  3. PCG再定義
  4. アトリビュート制御
  5. メモリ省力化
  6. マップデータの圧縮
  7. 動作の安定化
  8. 人間100人を動かすために

サーモス 水筒 真空断熱スポーツボトル ブラックカモフラージュ 1.0L FHT-1000F BK-C
【広告】
サーモス 水筒 真空断熱スポーツボトル ブラックカモフラージュ 1.0L FHT-1000F BK-C
サーモス(THERMOS)
2019-03-01
※ 外を出歩く際は水分持ち歩きたいですよね。