Windows95版ぷよぷよSUN 解析
もしかしたら、バージョンによってフォーマットやパレットの位置が違うかもしれません。
私が解析した各ファイルの更新日時はこのようになっていました。
puyo3.exe 1998年3月12日、3:51:36
grp.dat 1998年3月11日、16:40:14
comic.scr 1998年3月10日、22:43:12
BはByteの略です。
◇基本
◆DATファイル
◆BGファイル
◆SPRファイル
◆パレット位置一覧
画像データは「grp.dat」に格納されています。ほとんどが無圧縮のベタ画像です。ただ「grp.dat」には画像とそのサイズに関する情報のみで、パレットデータは一切含まれていません。
アトリエの画像以外、すべて色深度8bitです。
たとえ16色しか使用していない場合でも1ピクセルあたり1Bです。
■パレット■
パレットデータは「puyo3.exe」と「comic.scr」に格納されています。
16bitカラー(つまり1色あたり2B)で、下位ビットからR5G5B5A1です。
■キャラクター順■
パレットデータはこのように並ぶことが多いです。
SKEL スケルトンT
HAPY ハーピー
CHOP ちょっぷん
DRAC ドラコケンタウロス
INCU インキュバス
TARA すけとうだら
KIKI キキーモラ
NOHO のほほ
KODO コドモドラゴン
WICH ウィッチ
ZOH ぞう大魔王
HONY ハニービー
LUGN 勇者ラグナス・ビシャシ
RULU ルルー
SHEZ シェゾ・ウィグィィ
SATN サタンさま
ARLE アルル・ナジャ
CARB カーバンクル
複数のファイルを格納したアーカイブファイルです。ファイル先頭に、各ファイルへの位置やサイズの情報があります。
DATファイルのヘッダ構造
size | 内容 |
4B | 格納ファイル数 |
4B | DATファイルのサイズ |
格納ファイル数分、以下の8Bが続く |
4B | ファイル位置 |
4B | ファイルサイズ |
ファイルサイズが0の場合、ファイル位置は0xffffffffになっています。
grp.datに格納されているファイルの名前は、
puyo3.exeのオフセット0xD3764から、grp.dat内での格納順に並んでいます。
以降に出てくるBGファイルやSPRファイルやDATファイルは、grp.datから抽出したものです。
■end_dr.dat open.dat result.dat の圧縮について■
grp.dat内には、end_dr.dat、open.dat、result.datというDATファイルがあります。
ヘッダ部分は無圧縮ですが、格納ファイルはそれぞれ先頭からLZSS圧縮されています。
C言語で復号ルーチンを書いてみたので参考にして下さい。
(2009/8/12 constの位置を修正)
int decode_puyo3lz(unsigned char *const src /*圧縮データの開始位置*/
,unsigned char *const dest /*展開先の位置*/
,unsigned char *const s_end /*圧縮データの終了位置*/
){
unsigned char flags,*sp,*dp;
unsigned long i,j,len,offset;
sp=src;
dp=dest;
while(1){
flags=*(sp++);
for(i=0;i<8;i++){
if(flags & 1){
*(dp++)=*(sp++);
}else{
if(*sp & 0x80){
if(*sp & 0x40){
len =((sp[0]>>2) & 0xf) +4;
offset=((sp[0]<<8) | sp[1]) & 0x3ff;
sp+=2;
}else{
len =((sp[0]>>5) & 1) +2;
offset=sp[0] & 0x1f;
if(offset){
sp++;
}else{
offset=((sp[0]<<8) | sp[1]) & 0x3ff;
sp+=2;
}
}
}else{
if(*sp == 0x7f){
len =((sp[2]<<8) | sp[1]) +2;
offset=(sp[4]<<8) | sp[3];
sp+=5;
}else{
len = sp[0] +4;
offset=(sp[2]<<8) | sp[1];
sp+=3;
}
}
for(j=0;j<len;j++,dp++) *dp=*(dp-offset);
}
if(sp == s_end) return (int)(dp-dest);
if(sp > s_end){
printf("ERROR!\n");
return -1;
}
flags>>=1;
}
}
}
このコードをそのまま使う場合は、不正メモリアクセスに注意して下さい。(特に展開先)
まあopen.datとresult.datは既存のファイルを圧縮してあるだけなので、特に復号する必要ありませんけどね(^_^;
BG(背景)を格納したファイルです。
ひとつの画像が複数に分割されていて、ファイル先頭に各画像への位置、横幅、縦幅などの情報があります。
分割画像は大抵タイル状に並びます。画像が配置されなかった部分は0で埋めます。
ファイル構造は、先頭から「索引1」、「索引2」、「画像」の順です。
索引1
size | 内容 |
4B | 総画像数 (常に1) |
4B | 不明 |
総画像数分、以下の8Bが続く |
2B | 完成画像の横幅 |
2B | 完成画像の縦幅 |
2B | 不明 (常に0) |
2B | 不明 |
索引2
size | 内容 |
4B | 格納画像数 |
格納画像数分、以下の16Bが続く |
2B | 画像の横幅 |
2B | 画像の縦幅 |
2B | 位置X(左方向のパディング数) |
2B | 位置Y(上方向のパディング数) |
4B | 不明 |
4B | 「画像」開始位置からのオフセット |
「画像」は色深度8bitのベタです。
以下に、いくつか例を紹介します。
■com_*.bg■
漫才デモの背景です。索引データどおりに画像を並べると、このようなタイル状になります
【例:com_chop.bg】

パレットは「puyo3.exe」のオフセット0xD0320から512Bずつ格納されています。
com_chop.bgからアルファベット順です。
■bak_*.bg■
各キャラの対戦フィールドです。索引データどおりに画像を並べると、このようなタイル状になります。
【例:bak_arle.bg】

パレットは「puyo3.exe」のオフセット0xCDB10から256Bずつ格納されています。bak_skel.bgからキャラクター順です。
これらは128色しか使用していないので、パレットのサイズも256Bずつになっています。
スプライトを格納したファイルです。ファイル構造はBGファイルとほぼ同じです。
BGファイルとの違いは、索引1の「総画像数」と索引2の「格納画像数」が同数で、
索引1が画像全体のサイズ、索引2が実際に格納されている画像サイズをそれぞれ示していることです。図で表すと、

赤枠が索引1で示される、全体のサイズ、
青枠が索引2で示される、格納されている画像サイズになります。
BGファイル同様、余白は0で埋めます。
索引1
size | 内容 |
4B | 総画像数 |
4B | 不明 |
総画像数分、以下の8Bが続く |
2B | 画像の横幅 |
2B | 画像の縦幅 |
2B | 不明 (画像の番号?) |
2B | 不明 |
索引2
size | 内容 |
4B | 格納画像数 |
格納画像数分、以下の16Bが続く |
2B | 画像の横幅 |
2B | 画像の縦幅 |
2B | 位置X(左方向のパディング数) |
2B | 位置Y(上方向のパディング数) |
4B | 不明 |
4B | 「画像」開始位置からのオフセット |
以下に、いくつか例を紹介します。
■at_*.spr■
オプションのアトリエで使用されている画像です。これらの画像のみ色深度16bitです。
色の構成はパレットと同じで、最下位ビットからR5G5B5A1です。
■chr_sel.spr■
「ふたりでぷよぷよ」のキャラ選択で使用されているスプライトです。
パレットは「puyo3.exe」のオフセット0xCF520に、32Bずつ格納されています。

■comi??es.spr、comic??s.spr■
漫才デモで使用されているスプライトです。
comic??s.sprがプレイキャラクター用、comi??es.sprが敵キャラクター用です。
【例:comic19s.spr パレット適用済】

パレットは「chr_sel.spr」と同じく、
「puyo3.exe」のオフセット0xCF520に、32Bずつキャラクター順に格納されています。
各キャラクターに合わせて使用パレットを決定します。
ミノタウロスは「puyo3.exe」のオフセット0xCF7E0から32B、
対ちょっぷんでの波のパレットは場所が分かりませんでした。(特に調べていません)
■cut_*.spr■
連鎖カットインなどのスプライトです。
これらの画像に関しては、キャラ毎にパレットの位置がバラバラで規則性は分かりませんでした。
【例:cut_arle.spr パレット適用済】
私が調べた分しかありませんが、以下がpuyo3.exeにあるパレットの場所です。
「バイナリエディタで見て、パレットっぽいデータを見つけては片っ端から試す」という方法で調べていったので間違いがあるかもしれません。
puyo3.exe内のパレット位置
offset | size | file | 備考 |
0xCA9C8 | 64B | cut_wich.spr | 32Bx2 |
0xCAAB0 | 256B | entr01s.spr | 32Bx8 |
0xCABD0 | 512B | entr01b.bg | |
0xCC650 | 128B | cut_incu.spr | 32Bx4 |
0xCDB10 | 4608B | bak_*.bg | 256Bx18 キャラクター順 |
0xCF520 | 704B | chr_sel.spr | 32Bx22 |
0xCF7E0 | 32B | ミノタウロス | |
0xCFB80 | 416B | menu_1.spr | 32Bx13 |
0xD0240 | 224B | cont_*.spr | 32Bx7 |
0xD0320 | 8192B | com_*.bg | 512Bx16 ABC順 |
0xD3320 | 64B | cut_huny.spr | 32Bx2 |
0xEED20 | 352B | cut_skel.spr | 32Bx11 |
0xEEEA0 | 32B | cut_zoh.spr | |
0xF0110 | 512B | aaa_comp.bg aaabks.bg | |
0xF0310 | 32B | cut_kiki.spr | |
0xF0718 | 512B | snd_bak.bg | |
0xF09B8 | 480B | st_*_*.spr | 32Bx15 ABC順 |
0xF3768 | 64B | cut_cabn.spr | 32Bx2 |
0xF37A8 | 32B | cut_lagn.spr | |
0xF3808 | 160B | open.spr | 32Bx5 |
0xF38A8 | 32B | opsat.spr | |
0xF3A88 | 512B | opbg1.bg | |
0xF3C88 | 512B | opsora.bg | |
0xF4068 | 1536B | opbgsat.bg | 512Bx3 |
0xF4868 | 3072B | op02.bg | 512Bx6 |
0xF5468 | 512B | opdrac.bg | |
0xF5668 | 512B | opdora3.bg | |
0xF5868 | 512B | doukutu.bg | |
0xF5CC8 | 512B | op_dra1.spr | |
0xF5EC8 | 32B | cut_shez.spr | |
0xF76D0 | 512B | trav01b.bg | |
0xF78D0 | 32B | cut_noho.spr | |
0xF8738 | 384B | cut_kodo.spr | 32Bx12 |
0xF8EB8 | 96B | cut_chop.spr | 32Bx3 |
0xFA340 | 608B | rk_face.spr | 32Bx19 |
0xFA5A0 | 96B | rk_????.spr | 32Bx3 ABC順 |
0xFA600 | 512B | rank01b.bg | |
0xFAB18 | 64B | cut_arle.spr | 32Bx2 |
0xFB240 | 480B | cut_tara.spr | 32Bx15 |
0xFB420 | 32B | cut_satn.spr | |
0xFB440 | 128B | cut_rulu.spr | 32Bx4 |
0xFCAB0 | 128B | staff.spr | 32Bx4 |
0xFCC78 | 32B | cut_drac.spr | |
0xFD2A0 | 160B | end_dr.dat 03,08 | 32Bx5 |
0xFD340 | 512B | end_dr.dat 05,06,07 | |
0xFD540 | 512B | end_dr.dat 10 | |
0xFD740 | 512B | end_dr.dat 11 | |
0xFDB40 | 1216B | end_shez.spr | 32Bx38 |
0xFE000 | 1024B | ed_shiro.bg | 512Bx2 |
0xFE400 | 576B | end_arle.spr | 32Bx18 |
0xFE800 | 512B | moon.bg | |
0xFEA00 | 512B | shiro.bg | |
0xFEC00 | 1024B | shiro2.bg | 512Bx2 |
0xFF000 | 512B | yozora.bg | |
0xFF220 | 128B | cut_hapy.spr | 32Bx4 |