g800とbm2をSDLを1.2から2.0に変えたとき気づいたことをメモします. 「やってみたらこうだった」レベルなので正確ではないかもしれません.
「SDL 1.2から2.0への移行」も参考にしてください.
SDL 2.0では複数のウィンドウを扱えるようになった. それに伴いウィンドウの表示方法も変わっている. なお, 2.0にはSDL_GetVideoInfo関数はない.
SDL_VideoInfo *v;
SDL_Surface *s;
v = SDL_GetVideoInfo();
s = SDL_SetVideoMode(W, H, v->vfmt->BitsPerPixel, SDL_HWSURFACE);
SDL_Window *w;
SDL_Surface *s;
w = SDL_CreateWindow("Title", X, Y, W, H, 0);
s = SDL_GetWindowSurface(w);
SDL 1.2ではSDL_UpdateRect関数またはSDL_UpdateRects関数を使用したが, 2.0ではSDL_UpdateWindowSurface関数またはSDL_UpdateWindowSurfaceRects関数を使用する.
1.2では, ウィンドウを最小化したときや画面外に移動したときも表示を維持したが, 2.0では表示が消えてしまう. この場合SDL_UpdateWindowSurface関数で更新しなければならない.
なお, SDL_Surfaceはハードウェアアクセラレーションを使用しない. SDL_Textureを使えば有効になり, こちらが推奨されている.
SDL_UpdateRect(s, X, Y, W, H); /* X = Y = W = H = 0 ならウィンドウ全体 */
または
SDL_Rect r[256];
int n;
/*
.
.
.
*/
SDL_UpdateRects(s, n, r);
SDL_UpdateWindowSurface(w); /* ウィンドウ全体 */
または
SDL_UpdateWindowSurfaceRects(w, r, n);
タイトルバーの文字を変更する関数が変更された.
SDL_WM_SetCaption("Title", NULL);
SDL_SetWindowTitle(w, "Title")
タイトルバーのアイコンを変更する関数も変更されている. アイコンの透過部分の指定がなくなり, アルファチャンネルで透過を表すようになっている.
SDL_Surface icon;
Uint8 mask[32 * 32 / 8];
/*
.
.
.
*/
SDL_WM_SetIcon(icon, mask);
SDL_SetWindowIcon(w, icon);
256色時のパレットも以下のように変わったようだが, 実際には試していない.
SDL_Color c[256];
/*
.
.
.
*/
SDL_SetPalette(s, SDL_PHYSPAL, c, 0, 256);
SDL_SetPaletteColors(s->format->palette, c, 0, 256);
SDL 1.2のSDL_Keysym構造体のsymフィールドはSDLK_FIRSTからSDLK_LASTまでの連番になっていたが, 2.0ではそうではない. SDL 2.0ではsymフィールドは押されたキーの文字コード(UNICODE)となっている. キーを配列の添え字にするような場合はscancodeフィールドを使用する.
symフィールドの値はキーコード(SDLK_*), scancodeフィールドの値はスキャンコード(SDL_SCANCODE_*)と呼ばれている. キーコードはキーの文字を表し, スキャンコードはキーの位置を表している.
またキーコードの定義(#define)も, なくなったり追加されたものや, 名前が変わったものがある.
SDLK_RMETA SDLK_LMETA SDLK_COMPOSE SDLK_EURO
SDLK_KP0 → SDLK_KP_0 SDLK_KP1 → SDLK_KP_1 SDLK_KP2 → SDLK_KP_2 SDLK_KP3 → SDLK_KP_3 SDLK_KP4 → SDLK_KP_4 SDLK_KP5 → SDLK_KP_5 SDLK_KP6 → SDLK_KP_6 SDLK_KP7 → SDLK_KP_7 SDLK_KP8 → SDLK_KP_8 SDLK_KP9 → SDLK_KP_9 SDLK_NUMLOCK → SDLK_NUMLOCKCLEAR SDLK_SCROLLOCK → SDLK_SCROLLLOCK SDLK_PRINT → SDLK_PRINTSCREEN SDLK_BREAK → SDLK_STOP SDLK_RSUPER → SDLK_RGUI SDLK_LSUPER → SDLK_LGUI
SDL 1.2にはキーリピートの有無と速さを設定するSDL_EnableKeyRepeat関数があったが, 2.0ではなくなっている. SDL 2.0では何も指定しなくてもキーリピートする. キーリピート時にはSDL_KeyboardEvent構造体のrepeatフィールドの値が真になっているので, 必要ならばこれを見ればよい.
SDL_OpenAudio関数で初期化するとき, フォーマットをAUDIO_U8(8bit符号なし)とすると音が出力されなかった.
AUDIO_S8(8bit符号あり)とすると正常に出力された. 原因は不明である.
(このあたりはよくわからない...)
SDL_OpenAudioは旧バージョンとの互換性のためにある関数で, 新しくSDL_OpenAudioDevice関数が追加されているが試していない.
SDL 2.0では音声出力のコールバック関数でミックスされる元のバッファ(第2引数)を0で初期化しないとエコーがかかったようになった.
Uint8 *soundBuffer;
/*
.
.
.
*/
static void SDLCALL audioCallbackFunc(void *unused, Uint8 *stream, int len)
{
SDL_MixAudio(stream, soundBuffer, len, SDL_MIX_MAXVOLUME);
}
static void SDLCALL audioCallbackFunc(void *unused, Uint8 *stream, int len)
{
memset(stream, 0, len);
SDL_MixAudio(stream, soundBuffer, len, SDL_MIX_MAXVOLUME);
}
1つのバッファの音声を出力中に別のバッファに音声を書き込み, 出力し終えたらバッファを交換するようにした場合, SDL 1.2ではポインタを交換すればよかったが, SDL 2.0ではできない.
バッファの値を出力側に書き込まなければならないようである.
(このあたりはよくわからない...)
int soundBufferSize;
Uint8 *soundWriteBuffer;
void flipSoundBuffer()
{
Uint8 *p;
p = soundBuffer;
soundBuffer = soundWriteBuffer;
soundWriteBuffer = p;
memset(soundWriteBuffer, 0, soundBufferSize);
}
void flipSoundBuffer()
{
memcpy(soundBuffer, soundWriteBuffer, soundBufferSize);
memset(soundWriteBuffer, 0, soundBufferSize);
}
SDL 1.2はLGPLなので静的リンクすると場合によってはライセンス違反となる. SDL 2.0はzlibライセンスに変更されたため静的リンクできる.
しかし筆者の環境ではリンクのオプションを sdl2-config --static-libs としても静的リンクできなかった. (win32ではリンクエラー, Linuxでは動的リンクとなった.) /usr/local/bin/sdl2-config の --static-libs の下の echo を編集することで静的リンクできた.
-lSDL2main -lSDL2
の部分を
-Wl,-Bstatic -lSDL2main -lSDL2 -Wl,-Bdynamic
として
-XCClinker -static-libgcc
を削除する.
SDL 1.2では文字コードはその環境のロケール(例えば日本語WindowsならばShift-JIS)だったが, SDL 2.0ではUTF-8になっている.
日本語Windowsの場合, int main(int argc, char *argv[])のargvはShift-JISなので注意すること.
SDL 2.0はSDL 1.2と同様に文字コードはUTF-8である. 日本語Windowsの場合, SDL 1.2ではint main(int argc, char *argv[])のargvはSHIFT-JISだったが, SDL 2.0ではUTF-8になっている.