2011年04月05日


広告


SNES9X最新版をPSPに移植してみる(4)

■psp/unix.cpp psp/x11.cpp をPSP用に修正する

まだ、pspディレクトリ配下のソースは、元にしたunix/X11用のコードのままなので、これをPSP用に置き換えていく必要がある。項目としては、
グラフィック関連
サウンド関連
ジョイスティック関連
といったところか。

unix.cpp、x11.cppというファイル名もPSP用としてはいまいちですね。そのうち直しましょう。

ここからは、機種依存部分で大きな変更が伴うので、main()関数から順をおって修正していく。

●default_dirの設定

unix版では、genenv()で環境変数$HOMEを取得し、~/.snes9xというディレクトリを変数default_dirに入れている。default_dirで示されるディレクトリにコンフィグファイル等を置くようである。

snprintf(default_dir, PATH_MAX + 1, "%s%s%s", getenv("HOME"), SLASH_STR, ".snes9x");

PSPでは、main()関数のargv[0]にms0:/psp/game/snes9x/eboot.pbpの様な起動プログラムのフルパスが入っているので、これを利用する様に変更する。

●コンフィグファイル読み込み、ロムファイル名、作業ディレクトリ作成

コンフィグ読み込み関数S9xLoadConfigFiles(argv, argc);についてはとりあえずコメントアウトして後回し。後で実装する場合もargv, argcの中身がunixとPSPで違うので注意。
ロムファイルについては、unix版はsnes9xプログラムのコマンド起動時に引数として渡されるが、PSPではGUI等の実装が必要になるのでrom_filename = "hoge.smc";としてとりあえず決め打ち。
作業ディレクトリ作成は、PSPでは不要なので、make_snes9x_dir()は削除。

●グラフィック関連

main()関数を読み進めていくと、S9xInitDisplay(argc, argv);という関数の呼び出しがある。この中身を覗いていくとX11関連のグラフィック周りの設定となっている。ここにPSPのグラフィック設定ロジックを組み込んでいく。
unix版の構造体GUIをいじっている箇所を含め、X Window関連の処理はすべて削除する。
ざっくりと以下の様に変更した。GU関連はよく分からない(オイ)ので適当に。必要があれば後で修正。

ここで重要なのは、GFX.PitchとGFX.Screen。詳細はオリジナルソースアーカイブのdocs/porting.htmlを参照していただくとして、この二つがsnes9xコア側とPSP側のグラフィックを結びつける架け橋になります。
snes9xコア側はGFX.Screenをフレームバッファとして画面出力を行っていきますので、これにPSPのvram上のバッファポインタを渡しています。

もう一つのsnes9xコア/PSP間インタフェースとして、S9xDeinitUpdate()があります。これはsnes9xコア側がGFX.Screenへの書き込みを完了した時点で呼ばれるので、ここでPSP側のキャッシュ上のデータのvramへの書き出しと、書き込みバッファと表示バッファのスワップを行います。S9xDeinitUpdate()からcallされる、以下のS9xPutImage()がそれです。チラつきが目立つ様であれば、このスワップ処理はVsync時のcallback関数の延長で行う方がよいかもしれません。

static unsigned int __attribute__((aligned(16))) list[262144];

#define BUF_WIDTH (512)
#define SCR_WIDTH (480)
#define SCR_HEIGHT (272)

void *fbp0, *fbp1, *zbp;

void S9xInitDisplay (int argc, char **argv)
{
fbp0 = 0; // offset 0
fbp1 = (void *)((unsigned int)fbp0 + BUF_WIDTH * SCR_HEIGHT * 2); // fbp0 + (buf0 size)
zbp = (void *)((unsigned int)fbp1 + BUF_WIDTH * SCR_HEIGHT * 2); // fpb1 + (buf1 size)

sceGuInit();

sceGuStart(GU_DIRECT,list);
sceGuDrawBuffer(GU_PSM_5650,fbp0,BUF_WIDTH);
sceGuDispBuffer(SCR_WIDTH,SCR_HEIGHT,fbp1,BUF_WIDTH);
sceGuDepthBuffer(zbp,BUF_WIDTH);
sceGuOffset(2048 - (SCR_WIDTH/2),2048 - (SCR_HEIGHT/2));
sceGuViewport(2048,2048,SCR_WIDTH,SCR_HEIGHT);
sceGuDepthRange(65535,0);
sceGuScissor(0,0,SCR_WIDTH,SCR_HEIGHT);
sceGuEnable(GU_SCISSOR_TEST);
sceGuFrontFace(GU_CW);
sceGuEnable(GU_TEXTURE_2D);
sceGuDepthMask(0xffff);
sceGuDisable(GU_DEPTH_TEST);
sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT);
sceGuFinish();
sceGuSync(0,0);

sceDisplayWaitVblankStart();
sceGuDisplay(1);

S9xSetRenderPixelFormat(RGB565);
S9xBlitFilterInit();
S9xBlit2xSaIFilterInit();
S9xBlitHQ2xFilterInit();

SetupImage();
}

static void SetupImage (void)
{
TakedownImage();

GFX.Pitch = BUF_WIDTH * 2;
GFX.Screen = (uint16 *)0x04000000; // vram top addr (buf0)

S9xGraphicsInit();
}

void S9xPutImage (int width, int height)
{
/* xxxxx */
sceKernelDcacheWritebackAll();
fbp0 = sceGuSwapBuffers();
}


それなりに適当ではありますが実装が完了したので、この後はmakeが完了するところまで追いこんでいきます。




タグ:SNES9X PSP
posted by ひっそりぃ at 2011/04/05 15:35 | Comment(0) | TrackBack(0) | SNES9X for PSP | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:


この記事へのトラックバック
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。