当初、マップはそのままの配置データを RLE圧縮(ランレングス)で保持していました。無圧縮だと 2.8KBですが、この圧縮で 1.7KBには縮んでいたので、これで良いと思っていました。
これがすぐにぶっちぎりに甘い見積りだったとすぐに思い知らされる事になります。今回はサイズ的にもかなりのウェイトを占める、マップデータを如何にメモリに収めたかの顛末についてお話しします。
そこで次に検討したのが BPE圧縮です。これは読んで字が如く Byte の Pair で Encode する技術です。ファミコンの頃から存在している手法だったりします。マップをよく見ると、2バイトで一つのオブジェクトを形成しているような形状が多い事が分かります。これは期待が出来るかもと、C# で圧縮プログラムを書いてテストしてみました。
縮みはしましたが、正直微妙な結果に…。そんな中、ネットで Exomizer という圧縮を知りました。Z80 展開ルーチンが付いていて高圧縮そこそこ高速。これは試してみるしかない!
さらに微妙な結果に…。
そう!データ構造そのものが抜本的に拙いのだ!!
そこで私は仕様の見直しを始めました。まず、画面全体をそのまま保持する考え方そのものを止める事にしました。よくよく考えたら、そんな贅沢なデータの持ち方ってないよなあと。仮配置されたマップをよく見ると、マップ内にはオブジェクト毎にパーツ化できる塊がありました。この塊をエディタで事前に作成して、そのパーツをどこに配置するかだけをデータ化すれば軽いんじゃないのか?
また、複数ステージで流用するパーツも当然あるはずです。それも使い回す事にして、さらにマップに使用する PCGはステージ毎に要る要らないがあるので、まとめて全種類を定義しておくのは勿体ない事にも気がつきました。PCGは同時に最大37個までだけど、全10面で 370個の PCGデータは要らないですよね。例えば樹木パターンはどのステージにも使うわけだから、使う分だけトータルで管理すればデータ量は減るはずです。
【広告】
この前回のマップを下地として、次のマップに必要なオブジェクトを継ぎ足していきます。
これならかなりの省メモリに貢献するのでは無いかと期待が膨らみます。そして、マップに連続性が出来た事から、思わぬ副産物が。意図せず10面全てのマップに、ゼビウスのマップのようなストーリー性が生まれたのです!
右側から左側に進んでいく事で、最初に山間部に現れた怪獣が、最終的には都市部の地球防衛隊本部まで到達するという流れが、勝手に出来てしまったのです。いやー、これは本当に棚ぼたでした。このゲームにストーリー性が加わって、ますます完成度が上がった気がした瞬間でした。
その展開したデータを元にマップを再構築するのは、VRAMそのものです。このゲームでステージ切り替え時に、ペンゴのマップ生成のように、マップが作られていく過程が見えるのは、そのような理由からです。ただ、展開が見えるおかげで、1秒ちょっとの待ち時間が全く苦にならなくなりました。寧ろ速いと感じられるぐらいです。作られていく過程が見えるのは楽しいですからね。
実は最初はDMAを止めて裏方で高速展開にしていたのですが、1秒がコンマ数秒になったところであまり速くなった気がしないのと、例の cocopar のモニタがやっぱり画面復帰時に荒ぶってくれたので、この方法は採用できませんでした。もし、cocopar が荒ぶらなければ、このゲームはもう少し違ったテイストになっていたかもしれないですね…。
圧縮展開は Exomizer をおいて他の選択肢は考えられません。早速試してみます。
LGPL の何が問題かというと、このライセンスのプログラムを組み込んだ製品は、同じく LGPL ライセンスとしなければならないという事です。自由に使って良いソフトを売り物にする事は出来ません。さりとて、この高い圧縮率でかろうじてメモリ内に収まっているデータを、今更外す事が出来ず。
悩んだ挙げ句、私は一度は Exomizer の使用を諦めて、LZSA2 で組み込む決意をしました。圧縮すると、120バイト程度溢れてしまいました。そこでプログラム書き換えなどを駆使して、涙ながらの努力でようやくメモリ内に収めた直後ぐらいのタイミングで、なんと有志による Exomizer の Z80 デコードプログラムが zlibライセンスで公開されたのです。まるで、私が困っているのを見計らって、わざわざ作って頂いたかの如きタイミング💦
また Exomizer に戻して、浮いた 120バイト強で、ボーナスステージを追加する事にしました。そこでまたまたメモリとの戦いになってしまったのですが、なんとかなってしまうモノですね。それで、Newシティヒーロー v1.2 には、ボーナスステージが付いているというワケなんです。
いやー、奇跡って続くモノなんですね😁
これがすぐにぶっちぎりに甘い見積りだったとすぐに思い知らされる事になります。今回はサイズ的にもかなりのウェイトを占める、マップデータを如何にメモリに収めたかの顛末についてお話しします。
- データ圧縮をいろいろ試す
そこで次に検討したのが 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
さらに微妙な結果に…。
- 根本的にデータ形式を見直す
そう!データ構造そのものが抜本的に拙いのだ!!
そこで私は仕様の見直しを始めました。まず、画面全体をそのまま保持する考え方そのものを止める事にしました。よくよく考えたら、そんな贅沢なデータの持ち方ってないよなあと。仮配置されたマップをよく見ると、マップ内にはオブジェクト毎にパーツ化できる塊がありました。この塊をエディタで事前に作成して、そのパーツをどこに配置するかだけをデータ化すれば軽いんじゃないのか?
また、複数ステージで流用するパーツも当然あるはずです。それも使い回す事にして、さらにマップに使用する PCGはステージ毎に要る要らないがあるので、まとめて全種類を定義しておくのは勿体ない事にも気がつきました。PCGは同時に最大37個までだけど、全10面で 370個の PCGデータは要らないですよね。例えば樹木パターンはどのステージにも使うわけだから、使う分だけトータルで管理すればデータ量は減るはずです。
【広告】
[umbar net] 圧縮バッグ 衣類圧縮 旅行 トラベルバッグ 防水 YKK コーデュラ トラベルポーチ
umbar net
※ 圧縮と言えば、お出掛け荷物の圧縮も手軽にしたいですよね。
オブジェクトの塊を事前に編集するダイアログを別途用意して、データを吐き出す際は使用済みだけとする事にしました。
そして、上記で編集済みのPCGとオブジェクトをステージ毎に、配置座標データを作成する事にしました。このような数段階の分離形式にはなりましたが、思惑通りのデータ形式で実際に落とし込む事が出来ました。
そして、マップの作成中にふと気がついた事が。マップの配置データの半分を次のステージの配置データに活用すれば、少なくとも配置データは半減するし、マップの連続性もよくなるし、データ作成もラクだし!このアイディアは使えないかと!
具体的には、このマップデータから…
次のステージに繋がる左半分だけを取り出して、右側に単純移動させます。
※ 圧縮と言えば、お出掛け荷物の圧縮も手軽にしたいですよね。
- 新マップデータ構造の構築
オブジェクトの塊を事前に編集するダイアログを別途用意して、データを吐き出す際は使用済みだけとする事にしました。
そして、上記で編集済みのPCGとオブジェクトをステージ毎に、配置座標データを作成する事にしました。このような数段階の分離形式にはなりましたが、思惑通りのデータ形式で実際に落とし込む事が出来ました。
そして、マップの作成中にふと気がついた事が。マップの配置データの半分を次のステージの配置データに活用すれば、少なくとも配置データは半減するし、マップの連続性もよくなるし、データ作成もラクだし!このアイディアは使えないかと!
具体的には、このマップデータから…
次のステージに繋がる左半分だけを取り出して、右側に単純移動させます。
この前回のマップを下地として、次のマップに必要なオブジェクトを継ぎ足していきます。
これならかなりの省メモリに貢献するのでは無いかと期待が膨らみます。そして、マップに連続性が出来た事から、思わぬ副産物が。意図せず10面全てのマップに、ゼビウスのマップのようなストーリー性が生まれたのです!
右側から左側に進んでいく事で、最初に山間部に現れた怪獣が、最終的には都市部の地球防衛隊本部まで到達するという流れが、勝手に出来てしまったのです。いやー、これは本当に棚ぼたでした。このゲームにストーリー性が加わって、ますます完成度が上がった気がした瞬間でした。
- 再度データ圧縮を行う
その展開したデータを元にマップを再構築するのは、VRAMそのものです。このゲームでステージ切り替え時に、ペンゴのマップ生成のように、マップが作られていく過程が見えるのは、そのような理由からです。ただ、展開が見えるおかげで、1秒ちょっとの待ち時間が全く苦にならなくなりました。寧ろ速いと感じられるぐらいです。作られていく過程が見えるのは楽しいですからね。
実は最初はDMAを止めて裏方で高速展開にしていたのですが、1秒がコンマ数秒になったところであまり速くなった気がしないのと、例の cocopar のモニタがやっぱり画面復帰時に荒ぶってくれたので、この方法は採用できませんでした。もし、cocopar が荒ぶらなければ、このゲームはもう少し違ったテイストになっていたかもしれないですね…。
圧縮展開は Exomizer をおいて他の選択肢は考えられません。早速試してみます。
- 無圧縮 2.8KB
- RLE圧縮 1.7KB
- BPE圧縮 1.4KB
- BPE + Exomizer 1.2KB
- 新構造 + Exomizer 0.3KB
- ライセンス問題発生
LGPL の何が問題かというと、このライセンスのプログラムを組み込んだ製品は、同じく LGPL ライセンスとしなければならないという事です。自由に使って良いソフトを売り物にする事は出来ません。さりとて、この高い圧縮率でかろうじてメモリ内に収まっているデータを、今更外す事が出来ず。
悩んだ挙げ句、私は一度は Exomizer の使用を諦めて、LZSA2 で組み込む決意をしました。圧縮すると、120バイト程度溢れてしまいました。そこでプログラム書き換えなどを駆使して、涙ながらの努力でようやくメモリ内に収めた直後ぐらいのタイミングで、なんと有志による Exomizer の Z80 デコードプログラムが zlibライセンスで公開されたのです。まるで、私が困っているのを見計らって、わざわざ作って頂いたかの如きタイミング💦
また Exomizer に戻して、浮いた 120バイト強で、ボーナスステージを追加する事にしました。そこでまたまたメモリとの戦いになってしまったのですが、なんとかなってしまうモノですね。それで、Newシティヒーロー v1.2 には、ボーナスステージが付いているというワケなんです。
いやー、奇跡って続くモノなんですね😁
コメント