*以下SGDKは記述時点で最新版のSGDK 1.80 (september 2022) を使用しています
*2024/05/18追記 ここを改めて読むとあやふやな内容が含まれており、また実装時のサンプルコードが不足していると感じます。 例えばunpackTileSet()は原文(rescomp.txt)に存在しているから書いているだけで ・どのようなときに使うのか ・実装の仕方は? などがわかっていませんでした。 今より知識がないときに書いた、初心者にありがちな「分かっていないことが分かっていない」故の浅い内容であることを踏まえて読んでいただけるとありがたいです。 現在SGDKを最初から勉強し直している最中なのですが、ある程度理解が進んだらリライトするかもしれません。
SGDK学習の際のメモです。 今回調べながら+翻訳しながら、かつ文章量が多いです。そのため理解不足等から間違いが含まれている可能性が高いです。もし間違いありましたらコメントでご指摘頂けると嬉しいです。 また自分で間違いに気づいたときは該当箇所を書き直すつもりです。その際は基本修正履歴を残さない予定です。
今回は任意スクロールを学習していきます。
参考にするのはSGDK. Move around the map. - Under-Prog.ru
です。
今回の任意スクロールの処理概要
1.背景全体が入っている背景グラフィックデータをresources.resにMAP型リソースとして記述する 2.MAP_scrollTo関数で背景グラフィックデータの任意の位置を表示できる
つまり背景グラフィックが完成している場合、resources.resへの記述とMAP_scrollTo関数を呼び出すことで背景をスクロールできる、となります。 なおMAP_scrollTo関数はSGDK 1.60 (december 2020) で実装されたそうです。
今回使用する背景グラフィックデータはSGDK. Move around the map.で配布されているbg.png を使用します。これは1408 x 1344ドットと大きめのデータになっています。以下の画像はAseprite で縮小表示した状態です。
縮小されて見えづらいですが上部中央にエッグマンがいます コンパイルしてみる SGDK. Move around the map.に記載されているコードをそのままコンパイルして動作確認してみます。細かい補足、調査は今回の内容を踏まえ、次回以降に行います。 SGDKのバージョン違いが原因と思われるコンパイルエラーが発生します。そのためmain.cを以下のように書き換えます。 TILE_USERINDEX → TILE_USER_INDEX VDP_setPaletteColors() → PAL_setPalette()
res/resources.res (*同じフォルダにbg.pngも設置する) (因みに.res中//でコメントアウト可能、sample\sonic\res\res_gfx.res等を参照)
PALETTE palette_all "bg.png"
TILESET bga_tileset "bg.png" BEST ALL
MAP bga_map "bg.png" bga_tileset BEST 0
src/main.c (コンパイルエラー対応及びインデント修正済み、resources.hはresources.res記述後コンパイルで(rescompも実行されることで)生成される)
#include <genesis.h>
#include "resources.h"
Map *bga;
s16 camPosX = -1 ;
s16 camPosY = -1 ;
fix32 posX = 0 ;
fix32 posY = 0 ;
bool paused = FALSE;
void setCameraPosition (s16 x, s16 y )
{
if ((x != camPosX) || (y != camPosY))
{
camPosX = x;
camPosY = y;
MAP_scrollTo(bga, x, y);
}
}
void handleInput ( )
{
u16 value = JOY_readJoypad(JOY_1);
if (!paused)
{
if (value & BUTTON_RIGHT)
{
posX += FIX32(5 );
setCameraPosition(fix32ToInt(posX),fix32ToInt(posY)-140 );
}
else if (value & BUTTON_LEFT)
{
posX -= FIX32(5 );
setCameraPosition(fix32ToInt(posX),fix32ToInt(posY)-140 );
}
if (value & BUTTON_UP)
{
posY -= FIX32(5 );
setCameraPosition(fix32ToInt(posX),fix32ToInt(posY)-140 );
}
else if (value & BUTTON_DOWN)
{
posY += FIX32(5 );
setCameraPosition(fix32ToInt(posX),fix32ToInt(posY)-140 );
}
}
}
int main ( )
{
u16 ind;
ind = TILE_USER_INDEX;
VDP_loadTileSet(&bga_tileset, ind, DMA);
bga = MAP_create(&bga_map, BG_A, TILE_ATTR_FULL(0 , FALSE, FALSE, FALSE, TILE_USER_INDEX));
setCameraPosition(fix32ToInt(posX),fix32ToInt(posY)-140 );
SYS_doVBlankProcess();
PAL_setPalette(0 , palette_all.data, 16 *2 );
while (1 )
{
handleInput();
SYS_doVBlankProcess();
}
return (0 );
}
とりあえず実行して動作確認する コンパイルして作成されたout/rom.bin をKega Fusionで起動し、動画を撮影してみます。 *何度トライしてもgifアニメのアップロードに失敗するので、動画から切り出したスクショを貼っておきます、gifアニメはimgurにアップロードしておきました。
最初は背景の一部が表示されています、 bg.pngの一部のようですが上下左右が欠損しているようです 少し右下に行くとエッグマンが現れます、この辺りはbg.pngに存在する画像と一致します ずっと下に移動し続けるとと再度エッグマンが現れます、 背景は上下はつながっているようです、 gifアニメには含まれていませんが左右も同様につながっているようです、 bg.pngに存在しない部分の背景は欠損したり破損したような表示になります Debug Message表示 今後の動作確認や調査をしやすくするため、Gens KModを使用したDebug Message表示を確認しておきます。これはTuto Introduction · Stephane-D/SGDK Wiki · GitHub
に説明が記載されています。
1.Gens KModを起動、メニュー→Option→Debug選択
2.Debug Configuration→Active Development Featuresにチェック
3.Klogで始まるメソッドを使用することでGens KModのDebug Messageにメッセージが表示される
SGDKに含まれるsgdk Documentation(doc\html\index.html)の KLog関連の関数(一部)のスクリーンショット、 全45関数が用意されておりそれぞれに引数が異なります 4.実際にメッセージを表示してみる 今回はmain.cのwhile(1)の直前に
KLog("String only" );
KLog_U1("TestAbc->" , 567 );
と記述後コンパイル、Gens KModのDebug Messageでメッセージの表示が確認できました。
メガドライブにおける画像の優先順位について 以下の説明で画像の優先順位フラグ(プライオリティフラグ)の話が出てきますが、これは以下の動画を見ると理解しやすいと思います。
BGとかスプライトとか色分けしてみた【続・メガドライブ編】
動画冒頭の説明文を引用させてもらうと
各スプライト、BGの各セル(8x8)ドットには優先度を変更するフラグがあり、フラグをONにした部分は、より手前に表示されます。
https://www.nicovideo.jp/watch/sm18832549 『ランドストーカー』はこのフラグを動的に書き換えることでスプライトと背景の重ね合わせ処理を実装 していることがわかります。
rescomp.txtの確認+resources.resを読み解く (*以下長文です) SGDKのフォルダ内にResComp (bin/rescomp.jar ) の説明が記述されている bin/rescomp.txt というテキストファイル が存在します。
グラフィックや音楽のなどのリソースファイルを指定する res/resources.res (厳密にはres/*.res のようです) はResCompによって処理されます。
以下ではrescomp.txt内の今回の学習に関わるグラフィック関連部分を抽出、翻訳してみます。可読性を上げるためのインデントや改行の変更、Bold 装飾、私の英語力、原文中の誤字と思われる部分などの理由で、一部内容が原文とは異なる場合があります。
ResComp 3.60 (July 2022) (中略) ResComp is part of SGDK (aka Sega Genesis Dev Kit) so refer to SGDK licence for licensing. It allows to compile different type of resource and output them in assembly source form (GAS format). ResCompはSGDKの一部です、そのため使用許諾についてはSGDKライセンスを参照してください。 ResCompは様々なタイプのリソースをコンパイルしアセンブリソース形式(GASフォーマット)として出力できます。
rescomp.txt、翻訳を追記 GASフォーマットは"GNUアセンブラフォーマット "のことです(多分)。 今のところアセンブリソースは使用しません。コンパイル時にResCompも実行される→オブジェクト(.o)(とヘッダー(.h))が生成される→オブジェクトがrom.outに組み込まれる(リンクされる)、という挙動になっています。
コンパイル時ターミナルに出力されるログにも
java -jar C:/games/ dev/sgdk180/bin/rescomp.jar res/resources.res res/resources.rs -dep out/res/resources.o
ResComp 3.60 - SGDK Resource Compiler - Copyright 2022 (Stephane Dallongeville)
Resource: PALETTE palette_all "bg.png"
--> executing plugin PALETTE... 'palette_all' raw size: 38 bytes
Resource: TILESET bga_tileset "bg.png" BEST ALL
--> executing plugin TILESET... 'bga_tileset' raw size: 6824 bytes
Resource: MAP bga_map "bg.png" bga_tileset BEST 0
--> executing plugin MAP... 'bga_map' raw size: 11391 bytes
MAP 'bga_map' details: 1 tilesets, 282 metatiles, 70 blocks, block grid size = 11 x 11 - optimized = 11 x 11
'bga_tileset_data' packed with APLIB, size = 3412 (50 % - origin size = 6816 )
'bga_map_metatiles' packed with APLIB, size = 1212 (54 % - origin size = 2256 )
'bga_map_mapBlockIndexes' not packed (size = 121 )
'bga_map_mapBlocks' packed with APLIB, size = 2234 (25 % - origin size = 8960 )
res/resources.res summary:
-------------
Binary data: 7034 bytes
Unpacked: 176 bytes
Packed: 6858 bytes (38 % - origin size: 18032 bytes)
Misc metadata (map, bitmap, image, tilemap, tileset, palette..): 46 bytes
Total: 7080 bytes (7 KB)
とResCompの実行結果が出力されています。 *ログにResComp関連の情報が出力されない場合、out/resフォルダを削除後にコンパイルを再実行してみてください
ResCompは7種類の画像リソースタイプをサポートします(+3種類の音楽関連リソースもサポート)。
Supported resource type ----------------------- - BITMAP bitmapped image type resource, used for the Bitmap SGDK engine (do not use it as tile resource). - PALETTE palette type resource, used as color input for Bitmap, Image or Sprite resource. - TILESET tileset type resource, contains tiles data which can be used / shared for TILEMAP and MAP resources. - TILEMAP tilemap type resource, contains raw tilemap data. It can be used to draw an image or complete (but small) plane background. - MAP map type resource, optimized to draw large map / level. - IMAGE image type resource, internally contains Palette, Tileset and Tilemap data. It can be used to draw an image or complete (but small) plane background. - SPRITE sprite type resource, used to handle sprites with the SGDK Sprite engine. サポートされるリソースタイプ ----------------------- - ビットマップ(BITMAP) ビットマップ型リソース、ビットマップSGDKエンジンで処理される(タイルリソースとして使用しないこと)。 - パレット(PALETTE) パレット型リソース、ビットマップ、イメージ、またはスプライトのリソースの色として使用される。 - タイルセット(TILESET) タイルセット型リソース、タイルマップとマップリソースで使用/共用できるタイルデータを保持する。 - タイルマップ(TILEMAP) タイルマップ型リソース、未加工のタイルマップデータを保持する。画像または完璧な(しかし小さな)面の背景に使用できる。 - マップ(MAP) マップ型リソース、大きな図、面を描くのに最適化されている。 - イメージ(IMAGE) イメージ型リソース、内部的にパレット型リソース、タイルセット型リソース、タイルマップ型リソースを保持する。画像または完璧な(しかし小さな)面の背景に使用できる。 - スプライト(SPRITE) スプライト型リソース、 SGDKスプライトエンジンで処理するスプライトとして使用される。
rescomp.txt、翻訳を追記 上記一覧には出てきませんがOBJECTS型リソース も存在し、Tiled(というアプリ、後述)のTMXファイルを指定できます。今回これは省略します。詳細はrescomp.txtを参照ください。
以下それぞれの画像リソースタイプを確認していきます。
ビットマップ(BITMAP) これはよくわかりません。最初Windows bitmap (.bmp拡張子)ファイルを処理するためのリソースタイプかと思ったのですが、rescomp.txtには
img_file path of the input image file (BMP or PNG image)
rescomp.txt と記載がありPNGにも対応していました。ここでのビットマップはビットマップ画像 を意味している? SGDK内のサンプルソースディレクトリ以下でもベンチマーク用のプログラム(sample\bench\res\gfx.res )でしか使用されていません。 ビットマップ(BITMAP)はマップ(MAP)またはイメージ(IMAGE)で代替できるようなので、今回これ以上追わないことにします。
パレット(PALETTE) パレットはインデックスカラー (indexed color)形式の画像で色の定義が行われる表 のことです。以下はGens KModのデバッガでVDP (Video Display Processor)情報を表示した状態です。
未定義のパレットにはSGDKがデフォルトの値を設定するようです メガドライブはパレット0~パレット3の全4パレット(各パレットは16色指定可能)が存在し、これが画面上に表示される色となります。 パレットは背景、スプライトで共用されます(因みにファミコンは背景、スプライトでパレットは別です )。 メガドライブは基本的に同時発色数が61色です。発色については過去の学習メモ:No.1 で詳しめに書きました。
rescomp.txtにImportant note about image formatというセクションがあり、ここにパレットについての注釈があります。
Important note about image format --------------------------------- Many resource types use image file as input and Rescomp now supports both RGB images and indexed color images :) Here're some important informations to know about how to use properly these 2 image formats: * RGB images (中略) * Indexed color images rescomp supports 8bpp, 4bpp, 2bpp and even 1bpp indexed color image and will always directly use the palette data from the image it's *very* important to properly setup the palette in the image (color at position #0 is the transparent color). Some software as Asesprite let you to setup your palette as you require. An advantage of using indexed colors is that you can use color >= 128 with 8bpp image to define the priority information (more detail about it in resource description). 画像フォーマットにおける重要な注記 --------------------------------- 様々なリソースタイプの入力データとして画像ファイルを取り扱いますが、現在ResCompはRGB画像とインデックスカラー画像をサポートします。 ここではこれら2つの画像ファイルフォーマットを適切に扱うためのいくつかの重要な情報を記載します。 * RGB画像(RGB images) (中略) * インデックスカラー画像 (Indexed color images) ResComp は8bpp(bits per pixel/ビット毎ピクセル )、4bpp、2bppそして1bppインデックスカラー画像でさえもサポートします、そして常に画像中のパレットデータを直接使用します、画像ファイル中のパレットを適切に設定するのは*非常に*大切です(先頭の0番の色は背景色/透過色となります)。Asepriteのようないくつかのソフトウェアはあなたが望むようにパレットをセットアップできます。 インデックスカラーを使用する利点は、8bpp画像で128色以上の色を使用して優先順位フラグを定義できることです(これについてのもっと詳細な情報はリソースの説明を参照)。
rescomp.txt、翻訳を追記 現時点ではメガドライブ開発時の画像にはインデックスカラー画像を使用 、画像ファイルに指定する各パレットの先頭は背景色/透過色とすること 、と理解しておきます。
パレットの説明についてはよくわからない点があります。 まずRGB画像(RGB images)。 そもそもRGB画像の定義がよくわからないのですが、CMYK形式ではない画像という認識で合っているのでしょうか。 rescomp.txtでRGB画像ファイルは「画像ファイルの左上に4つの全パレットが存在することを期待する」(意訳)という記載があります。SGDKに同梱されているRGB画像のサンプルファイル sample/sonic/res/gfx/rgb_example.png を開いてみると、確かに画像ファイルの左上に16色のパレットが4つが存在します。
rgb_example.pngはEDGEで開けません(EDGE2は未確認)、Asespriteでは開けます 試しにこの画像を.resに組み込んでコンパイル→ResCompを実行してみましたがエラーになりました。また本ファイルを使用したサンプルも存在しません。そのため今回RGB画像についてはこれ以上調査しません。
またインデックスカラー画像を使用する利点の説明もちゃんと理解できていませんです。8bppだと128色以上の色が使用できる上に優先順位フラグが定義できる、ということのようです。
PALETTE ------- Take a .pal file or an image as input and transform it into SGDK Palette structure. See the note above about how palette is retrieved from RGB or indexed color images. Palette is used as color input for Bitmap, Image and Sprite resources. Syntax: PALETTE name file name name of the output Bitmap structure file path of the input image file (BMP or PNG image) or PAL file (Paint Shop Pro palette) See the note about image format at the beginning of the file パレット(PALETTE) ------- .palファイルまたは画像ファイルをインプットとして取り込みSGDKパレット構造へと変換します。 どの様にRGB画像またはインデックスカラー画像からパレットが読み出されるかは上記注釈を参照してください。 パレットはビットマップ型リソース、イメージ型リソース、スプライト型リソースの色として使用されます。 構文: PALETTE 名前 ファイル(ファイルパス) 名前 出力されるパレットの名前 (*rescomp.txtだとpaletteではなくBitmapとなっているが誤字?) ファイル(ファイルパス) 入力ファイルのパス(BMP or PNG画像)または PALファイル(Paint Shop Pro パレット) ファイル(rescomp.txt)先頭のイメージフォーマットについての 注釈を参照すること
rescomp.txt、翻訳を追記 BMP、PNG、PALを読み込んでSGDKにパレットとして取り込めるということになります。私はPaint Shop Proは触ったことがないのでPALについてはわかりません。 *2024/05/25追記Aseprite でPALファイルの作成、及びSGDKでの取り込みができました。
Asepriteのパレット用メニューから「Save Palette」を選択、 palファイルを保存 palファイルの中身はRGB値が指定された テキストファイル SGDKの*.resファイルに palファイルを指定 palファイルの内容(黒赤緑青)をパレット1に 反映させてみた状態 タイルセット(TILESET) タイルセットはメガドライブ内部で取り扱われる画像ファイルフォーマットで、8ドット*8ドットが最小単位です。この最小単位はCELL(セル)と呼ばれる そうです。
Regen Debug version(Tuto Introduction 内にバイナリへのリンクがあります)を使用するとタイルセットをビットマップファイルとして出力できるので、今回のbg.pngを使用したout.romを読み込んでビットマップファイルとして出力してみます。 * Gens KMod、Regen Debug versionともに画面上でタイルセットは確認できます、以下はRegenの機能紹介/確認を兼ねています(No.1 でも紹介はしていますけれど)。RegenのVDPデバッガの方がスプライトなどの情報も表示されて高機能ですが、負荷が高いようでFPSが一気に落ち込みます。
ビットマップファイルとして出力したタイルセットの一部を拡大表示した状態、 先頭にはインデックスカラーとして指定した色情報も タイルセットとして格納されています(という考え方で合ってるかな?) 今回resources.resでタイルセットは
TILESET bga_tileset "bg.png" BEST ALL
という記述になっています。後述しますが第4引数の最適化レベル(opt) が"ALL "となっています。そのためbg.png内で重複したとみなされるタイルセットは省略されます 。
ResCompはタイルセットとして「TSXファイル 」も受け付けます。これはTiled
というマップエディターアプリの入出力フォーマットTMX Map Format
TMX and TSX are Tiled ’s own formats for storing tile maps and tilesets, based on XML.
https://doc.mapeditor.org/en/stable/reference/tmx-map-format/ ですが、私はTiledを使用したことがないため上記リンクを貼るにとどめておきます。Tiledは慣れると効率的にマップが作成できそうです。
本記事作成中に見つけたのですが、ズバリSGDK向けの「16Tile 」というタイルエディタも存在しました。テスト的に触ってみたのですがabortが発生して落ちたこともあったで、まだ未完成な部分があるのかもしれません。 16Tileは優先順位フラグを指定できるようなので、後日動作確認する予定です。16Tile
TILESET ------- Take an image or TSX file as input and transform it into SGDK TileSet structure. TileSet is used as tiles source for Image, Tilemap, Map and Sprite resources. If you use a real 'tileset format' image as input (as a font) then you should set 'opt' parameter to 'NONE' to avoid removing duplicated tiles (which may exist). Syntax: TILESET name file [compression [opt]] name name of the output TileSet structure file path of the input file (BMP, PNG image file or TSX Tiled file) See the note about image format at the beginning of the file compression compression type (use unpackTileSet(..) to unpack), accepted values: -1 / BEST / AUTO = use best compression 0 / NONE = no compression (default) 1 / APLIB = aplib library (good compression ratio but slow) 2 / FAST / LZ4W = custom lz4 compression (average compression ratio but fast) opt define the optimisation level, accepted values: 0 / NONE = no optimisation, each tile is unique 1 / ALL = ignore duplicated and flipped tile (default) 2 / DUPLICATE = ignore duplicated tile only Tips: When using a 8bpp indexed image as input you can use the extra bits of palette to provide extra information for the TILEMAP data but you have to ensure that all pixels from a same tile (block of 8x8 pixels) use the same value otherwise rescomp will generate an error. bit 4-5: palette index (0-3) so it allows to use the 4 available palettes to draw the tilemap / MAP. bit 6: not used (ignored) bit 7: priority information (0=LOW 1=HIGH) タイルセット(TILESET) ------- 画像ファイルまたはTSXファイルを入力ファイルとして取り込みSGDKタイルセット構造へと変換します。 タイルセットはイメージ型リソース、タイルマップ型リソース、マップ型リソース、そして スプライト型リソースのタイルソースとして使用されます。 もし入力リソースを実際の'タイルセットフォーマット'として使用する場合(例えばフォントとして)、重複したタイルの消失を防ぐため最適化レベル('opt')のパラメーターとして'NONE'を選択するべきです (そうすれば存在するでしょう)。 構文: TILESET 名前 ファイル(ファイルパス) [圧縮 [最適化レベル]] 名前 プログラム中または.resファイル中で使用するタイルセットの名前 ファイル(ファイルパス) 入力ファイルのパス(BMP or PNG画像またはTSX Tiledファイル) ファイル(rescomp.txt)先頭のイメージフォーマットについての 注釈を参照すること 圧縮 解凍のためにunpackTileSet()時に使用する、受け付ける値: -1 / BEST / AUTO = 最適な圧縮を使用する 0 / NONE =圧縮しない(デフォルト) 1 / APLIB = aplibライブラリ (良い圧縮率だが遅い) 2 / FAST / LZ4W = カスタムlz4圧縮(平均的な圧縮率だが早い) 最適化レベル 最適化レベルの規定、受け付ける値: 0 / NONE = 最適化しない、それぞれのタイルはそれぞれに異なる (重複したタイルも受け付ける) 1 / ALL = 重複、反転したタイルは受け付けない(デフォルト) 2 / DUPLICATE =重複タイルのみ受け付けない 秘訣: 入力リソースとして8bppインデックスカラー画像を使用する場合、パレットの余分なビットをタイルマップの追加情報として使用できます、しかし同じタイル(8x8ピクセルのブロック)による全てのピクセルは同じ値である必要があります、そうでなければrescompはエラーとなります。 bit 4-5:パレットインデックス(0-3)、つまりタイルマップ、マップを 描くために4つのパレットが使用できます bit 6: 未使用(無視される) bit 7: 優先順位情報 (0=LOW 1=HIGH)
rescomp.txt、翻訳を追記 圧縮はサンプルソースを確認する限りBESTまたはFASTが使用されています。今のところ「基本はBEST、処理速度が必要な場合は圧縮率を犠牲にしてFAST選択するのだろう」としておきます。 最適化レベルは省メモリ化のために基本ALL(重複、反転したタイルは受け付けない)を指定するのが定石だろう、としておきます。重複させたい場合はNONEを選択しますが、大きい画像ファイルだとメモリに格納できなくなるでしょう。
タイルマップ(TILEMAP) タイルマップは 前述のタイルセット(8*8ピクセルのタイル)を背景レイヤーのどこに置くか (その名の通りTILEのMAP) の情報です。
今回タイルマップについては調査しないことにしました。 ・サンプルソース中の.resファイルで使用されていないこと ・後述するイメージ(IMAGE)またはマップ(MAP)で代替できるだろう がその理由です。 rescomp.txt中に「大きい背景画像にはMAPを使用すること」(意訳)という記述があります。
Megatiler 1 - Tiles
ではコード中2次元配列でタイルの配置を行っています。
マップ(MAP) タイルマップの進化系のようです。イメージ型リソース(後述)より少ない容量で大きな背景を扱えるというメリットがあるとされています。
MAP --- Take an image or TMX file as input and transform it into SGDK Map structure. Map is used to define a large background/plane data, it's different from the IMAGE resource as MAP uses an advanced encoding so it can encode large background while taking much less ROM space than IMAGE resource so use it to handle large level. Syntax: MAP name img_file tileset_id [compression [map_base]] name name of the output Map structure img_file path of the input image file (BMP or PNG image file) See the note about image format at the beginning of the file tileset_id base tileset resource to use (allow to share tileset along several tilemaps) compression compression type, accepted values: -1 / BEST / AUTO = use best compression 0 / NONE = no compression (default) 1 / APLIB = aplib library (good compression ratio but slow) 2 / FAST / LZ4W = custom lz4 compression (average compression ratio but fast) map_base define the base tilemap value, useful to set a default priority, palette and base tile index offset. Using a base tile index offset (static tile allocation) allow to use faster MAP decoding function internally. (TMXの構文については省略) マップ(MAP) ----- 画像ファイルまたはTMXファイルを入力ファイルとして取り込みSGDKマップ構造へと変換します。 マップは大きな背景/面を定義するために使用されます、イメージ型リソースと異なりマップは進歩したエンコードを使用します。そのためイメージ型リソースより少ないロム容量で大きな背景をエンコード(変換)できます、ですので大きな背景を取り扱えます。 構文: MAP 名前 ファイル(ファイルパス) タイルセットID [圧縮 [マップベース]] 名前 プログラム中または.resファイル中で使用するマップの名前 ファイル(ファイルパス) 入力ファイルのパス(BMP or PNG画像) ファイル(rescomp.txt)先頭のイメージフォーマットについての 注釈を参照すること タイルセットID 使用する土台となるタイルセット (タイルセットは様々なタイルマップとともに共用できる) 圧縮 圧縮タイプ 、受け付ける値: -1 / BEST / AUTO = 最適な圧縮を使用する 0 / NONE =圧縮しない(デフォルト) 1 / APLIB = aplibライブラリ (良い圧縮率だが遅い) 2 / FAST / LZ4W = カスタムlz4圧縮(平均的な圧縮率だが早い) マップベース 基底値となるタイルマップの値を定義する、 デフォルトのプライオリティフラグ、パレット、 基礎となるタイルのインデックスのオフセット値。 内部的にこのオフセット値を使用すること(静的なタイルの分量)は Mapの解読機能(MAP decoding function)より早いです。
rescomp.txt、翻訳を追記 イメージ(IMAGE) イメージは直接的に背景面に画像を描く際に使用され(used to directly draw image in background plane)、パレット、タイルセット、タイルマップを含みます(contains a Palette, TileSet and TileMap structure)。 タイルマップと同様に「大きい背景にはマップを使用すること」となっています。
構文は上記マップからタイルセットIDを除いたもの(img_fileの後のtileset_id がない)になっています。
Syntax: IMAGE name img_file [compression [map_opt [map_base]]]
rescomp.txt
サンプルソースにBad Apple (sample\demo\bad-apple)が含まれていますが、動画の各フレームはイメージとして扱われています。 以下sample\demo\bad-apple\res\movie_res.resの先頭2行です。
IMAGE frame_0000 "movie/img_T0000.png" FAST ALL 16
IMAGE frame_0001 "movie/img_T0001.png" FAST ALL 16
余談ですがSGDK 1.80のsample\demo\bad-apple\out\rom.bin + BlastEmは起動すると下記ワーニングが出て動画のテンポもおかしいです。
KDEBUG MESSAGE: Warning: frame missed detection on frame #7 - V-Counter = 144
SGDK 1.70のBad AppleはBlastEmで正常に動きます。 私の確認した範囲だとBad AppleはBlastEmでしか起動できませんでした。
スプライト(SPRITE) 今回の学習にスプライトは含んでいませんが、後に備えて翻訳だけしておきます。
SPRITE ------ Take an image as input and transform it into SGDK SpriteDefinition structure. SpriteDefinition is used to draw, animate and manage sprites, it internally contains severals TileSet, Palette and Animation structures. Syntax: SPRITE name img_file width heigth [compression [time [collision [opt [iteration]]]]] name name of the output SpriteDefinition structure img_file path of the input image file (BMP or PNG image) See the note about image format at the beginning of the file width width of a single sprite frame in tile (should be < 32) heigth heigth of a single sprite frame in tile (should be < 32) compression compression type, accepted values: -1 / BEST / AUTO = use best compression 0 / NONE = no compression (default) 1 / APLIB = aplib library (good compression ratio but slow, don't use it for streamed sprite) 2 / FAST / LZ4W = custom lz4 compression (average compression ratio but fast, recommended for streamed sprite) time display frame time in 1/60 of second (time between each animation frame) If this value is set to 0 (default) then auto animation is disabled collision collision type: CIRCLE, BOX or NONE (NONE by default) opt sprite cutting optimization strategy, accepted values: 0 / BALANCED = balance between used tiles and hardware sprites (default) 1 / SPRITE = reduce the number of hardware sprite (using bigger sprite) at the expense of more used tiles 2 / TILE = reduce the number of tiles at the expense of more hardware sprite (using smaller sprite) 3 / NONE = no optimization (cover the whole sprite frame) iteration number of iteration for sprite cutting optimization (default = 500000) Some informations about how SpriteDefinition is generated from the input image: - input image dimension should be aligned on tile (multiple of 8). - input image is a grid where each cell represents a single animation frame and where each row define a complete sprite animation. - an animation cannot contains more than 255 frames. - cell size (frame size) = width * height (in tile) where width and height should be < 32 (maximum = 248 pixels for both width and height). - a frame can be composed of several internal VDP (hardware) sprites but it stricly limited to a maximum of 16 hardware sprites. If the sprite is too large to fit in 16 hardware sprites (rescomp will complain about it), then you may reduce its size or split it in 2 parts. - rescomp detects flipped frame to avoid redundant sprite tiles. - rescomp detects empty frame at end of animation row to not store empty frame data. - rescomp try to optimize hardware sprites and vRAM usage by detecting empty areas in sprite frames. - rescomp detects frame copy inside an animation to generate the according animation sequence. - by default collision bounds are calculated by using 75% of the original sprite frame. スプライト(SPRITE) ------ 画像ファイルを入力ファイルとして取り込みSGDKスプライト定義構造へと変換します。 スプライト定義構造は描画、アニメ、スプライトの取り扱いに使用されます、内部的にそれぞれのタイルセット、パレットとアニメーション構造を保持します。 構文: SPRITE 名前 ファイル(ファイルパス) 幅 高さ [圧縮 [時間 [当たり判定 [最適化 [反復]]]]] 名前 出力するスプライト定義構造の名前 ファイル(ファイルパス) 入力ファイルのパス(BMP or PNG画像) ファイル(rescomp.txt)先頭のイメージフォーマットについての 注釈を参照すること 幅 タイル中の各スプライトフレームの幅(32より小さいこと) 高さ タイル中の各スプライトフレームの高さ(32より小さいこと) 圧縮 圧縮タイプ 、受け付ける値: -1 / BEST / AUTO = 最適な圧縮を使用する 0 / NONE =圧縮しない(デフォルト) 1 / APLIB = aplibライブラリ (良い圧縮率だが遅い、連続したスプライトには使用しないこと) 2 / FAST / LZ4W = カスタムlz4圧縮 (平均的な圧縮率だが早い、連続したスプライトに推奨) (*streamedを"連続した"と訳したが、適切な訳/意味か自信がない) 時間 1/60秒での表示時間(各アニメーションのフレーム間の時間) 0(デフォルト)だとオートアニメーションは無効化される 当たり判定 当たり判定のタイプ:丸(CIRCLE)、四角(BOX )、 なし(NONE)(なしがデフォルト) (*以下「最適化」と「反復」は翻訳に自信がありません≒理解できていません) 最適化 スプライト切断の最適化の方針、受け付ける値: 0 / BALANCED = タイルとハードウェアスプライトの間の平均 (デフォルト) 1 / SPRITE = ハードウェアスプライトの数を減らし (より大きなスプライトの使用) より多くの使用するタイルを消費する 2 / TILE = タイルの数を減らしより多くのハードウェアスプライトを 消費する(より小さなスプライトを使用する) 3 / NONE = 最適化しない(全てスプライトフレームとする) 反復 スプライト切断最適化反復回数(デフォルト= 500000) 画像ファイルから生成されたスプライト定義についてのいくつかの情報: - 入力画像の側面はタイルにそわせるべきです(8(ピクセル)の倍数) - 入力画像は各セルのグリッドが1つのアニメーションフレームを表し 各行が完全なスプライトアニメーションを定義します - アニメーションは255フレーム以上格納できません - セルサイズ(フレームサイズ) = (パラメーターの)幅と高さは (タイルにおいての)幅*高さとなり、 32以下を推奨(幅、高さ共に最大248ピクセル) - 1フレームはいくつかの内部的なVDP(ハードウェア)スプライトで 構成できますが、厳密に最大16個のハードウェアスプライトが限界 となっています。 もしスプライトが16個のハードウェアスプライトより大きい場合 (ResCompがエラー(*警告かも)を出します)、2つの部品にサイズを分割して サイズを小さくするべきです - ResCompは冗長なスプライトのタイルを排除するために反転したフレームを検出します - ResCompは空のフレームデータの格納を行わないために アニメーション行の最後の空のフレームを検出します - ResCompはスプライトフレームの空のエリアを検知することでハードウェアスプライトとvRAMの使用量の最適化を試みます - ResCompはアニメーション内の重複したフレームを検出し、それに応じた アニメーションシーケンスを生成します - デフォルトで当たり判定は元の75%のスプライトフレームを使用して 境界線が計算されます
rescomp.txt、翻訳を追記 理解できていない部分が多いです。 例えば最適化。 SPRITEとTILEを指定した際の実際の挙動の違いは?それをどうやって確認する?デバッガでわかる or ソース解析必要? 例えば反復。 そもそも反復という翻訳は正しい?スプライト用のリソースを複数回"反復"調査して最適化するという意味は?500000という数の単位、意味は?
とりあえず今回は翻訳だけしておき、実際のスプライト学習時に調べ直します。
というわけで今回の冒頭の res/resources.res を確認してみます。
PALETTE palette_all "bg.png"
パレットにはインデックスカラー画像の"bg.png"を指定、名前はpalette_all
TILESET bga_tileset "bg.png" BEST ALL
タイルセットには(パレットと同様に)インデックスカラー画像の"bg.png"を指定、名前はbga_tileset、圧縮タイプはBEST(AUTO = 最適な圧縮)、最適化レベルはALL(重複、反転したタイルは受け付けない(デフォルト))
MAP bga_map "bg.png" bga_tileset BEST 0
マップには(パレット、タイルセットと同様に)インデックスカラー画像の"bg.png"を指定、使用するタイルセットは上記bga_tileset、圧縮タイプはBEST(AUTO = 最適な圧縮)、マップベース(プライオリティ、パレット、タイルのオフセット値)は指定なしとして0
【了】