TINY野郎のブログ -6ページ目

TINY野郎のブログ

PC-6001、MSX、ぴゅう太など、昔のPCが大好きな人のブログ。

今回は、P6イース2オープニングデモ本編のメモリ管理と、データ圧縮について書いてみたいと思います。

まず、本編再生中のメモリマップはこのようになっています。

イメージ 1

「サブプログラム2」が、本編のシーンを制御するプログラムで、その後にシーン1からシーン8のデータが入っています。

ここで、「圧縮データ」というのがありますが、それについて説明します。

このデモを再現するにあたって、とにかくテンポというものを大切にしたかったので、できる限りロードはなくしたいと思っていました。
シーン7(天空へのスクロール)のパターンネーム(PN)データについてはさすがにメモリに載せるのは無理でしたが、それ以外のシーンはすべてオンメモリにしたかったのです。

しかし、全てのデータを詰め込んでみたところ、どうしても1KBほどメモリが足りませんでした。

前回のブログに書いたような細かいセルの削減を繰り返したり、デバッグ用のコードなども削ったのですが、それでも7~800バイト足りません。

この時点で、オフ会まであと3日くらいでした。

もう設計を変更している時間はありません。
かといって、アニメーションを削ってクオリティーを下げるのもやりたくありません。できるだけ「TINY」ではないものを作りたかったのです。

3秒くらい考えた挙句、データを圧縮してみることにしました。

・20KB近いデータのうち、800バイト減らせれば良い。
・時間がないので、簡単に実装できること。
・展開ルーチンが、処理的にも、メモリ的にも、軽くてすむこと。
・そもそも、圧縮アルゴリズムなんてほとんど知らない!

ということで、とりあえず、ランレングス圧縮をしてみることにしました。
同じデータが連続する場合に、データと個数を並べる、という方式です。

0FFHというデータを展開用のフラグにして、それ以外のデータはそのまま並べるようにします。

同じデータが続いている場合は、
 

FF (個数) (データ)

 


と、フラグの後に、繰り返し個数とデータを並べるようにしました。
個数が「0」の場合はデータ終端とします。

例えば、

 

 

 

11 22 33 33 33 33 33 33 44 55 66

 


というデータがあった場合、

 

 

 

 

 

11 22 FF 06 33 44 55 66 FF 00

 


となります。

同じデータが3個以上並ばないと意味がありませんし、フラグと同じ「FF」というデータを含む場合は、1個だけでもこのフォーマットで書かなければならないので、むしろ元データよりサイズが大きくなってしまいます。
効率は決して良くないですが、たった800バイト減ってくれれば良いので、とりあえず実装することにしました。

展開ルーチンはこうなりました。

イメージ 2

単純な処理なので、24バイトで済みました。
(※追記:twitterで、“最初の「LD A,(HL)」の後に「INC HL」すれば1バイト減らせる”とのご指摘を受けました。その通りです!)
複雑な演算等も一切行っていないので、速度的にも全く問題ありません。
「処理的にも、メモリ的にも、軽い」を満たしてくれました。

というわけで、圧縮したほうが良いデータについては、この方式でどんどん圧縮し、結果的に、なんとかオンメモリに収めることができました。
ちなみに、一番減ったのは、シーン3(高速アニメーションシーン)で、ここだけで350バイトほど減りました。

また、メモリマップを見ると、シーン1(ダームの塔の夜明け)が非圧縮になっていますが、これは展開したデータを置くメモリがないからです。
シーン2以降は、シーン1のデータがあった場所を展開用エリアとして使っていて、例えば、シーン2再生時のメモリマップはこうなります。

イメージ 3

このように、圧縮データのシーンの場合は、再生前に先程の展開ルーチンを呼び出し、展開後のデータのアドレスをプログラムに渡すようにしました。
非圧縮データの場合はそのままのアドレスをプログラム側に渡しているので、プログラム的には何の変更もせずに済みました。

そんなわけで、本当にギリギリになって、メモリ上に(スクロールシーン以外の)すべてのデータを載せることができたのでした。