ホーム   »  スポンサー広告  »  スポンサーサイト   »  PSPプログラミング  »  第6弾 : ファイル入出力

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

第6弾 : ファイル入出力

前回でボタン入力が出来る様になりました。
押されたボタンが何であるか、画面に出力していました。

そして、現段階の目的はキーロガーの作成です。
キーロガーは入力されたキー(ボタン)を(ファイルに)記録するものです。

という訳で、PSPで行うファイル入出力を今回解説します。
サンプルで用意したアプリケーションは若干ながら複雑ですが、がんばって下さい。
まず、標準のC言語であれば fopen / fclose / fwrite / fread 関数等を使用しますね。
実はPSPにもそれら入出力用の関数が用意されています。
使う場合stdio.h ヘッダーファイルをインクルードしましょう。
しかし、速度が出ないようなので、殆どの場合PSPのAPIが使われます。

PSPのファイル入出力APIの一部を以下に記述します。

sceIoOpen
sceIoClose
sceIoWrite
sceIoRead
sceIoSeek
sceIoLseek


もう一つ紹介、ファイル・ディレクトリ情報の取得に sceIoGetstat 関数があります。
作成日時・属性・ファイルサイズが取得できます。
ほかに、ファイルが存在するかチェックする目的で使われたりもします。

上記のそれらAPIはカーネルに近く、動作が高速です。
この他、関数名にAsyncと付く、非同期関数などもあります。
非同期は扱いが難しいので、機会があれば解説しようと思います。

今回のサンプルではOpen/Close/Write/Read それと sceIoGetstat を使用しました。
sceIoSeek 関数は標準の物と扱いは変わりません。
sceIoLseek 関数はラージ・ファイルに対応した関数です。シークサイズに64bit変数が使われます。

これらの関数は pspkernel.h ヘッダーファイル内でインクルードされる pspiofilemgr.h ヘッダーファイルで定義されています。
pspiofilemgr.h 内部でさらに、pspiofilemgr_fcntl.h や pspiofilemgr_stat.h や pspiofilemgr_dirent.h ヘッダーファイルがインクルードされます。
それらヘッダーファイルには、入出力関数で使用する定数が定義されています。

それから、今回のサンプルアプリケーションでは、ファイルパスを扱います。
ファイルパスの形式は
デバイス名 / ディレクトリ(フォルダ) / ファイル
となります。
例) ms0:/PSP/GAME/UPDATE/EBOOT.PBP
デバイス名はPSPの型により、使用不可能な物があります。
下記に記します。

ms0: メモリースティックアダプタ 全て共通
ef0: PSP-goのみの内臓メモリー
eh0: PSP-goのみの内臓隠しメモリー
disc0: UMDドライブ(モチのロン読み取りのみ) PSP-go以外共通
flash0: ファームウェア領域
flash1: 設定・壁紙・カスタムテーマ・レジストリ領域
flash2: PSN認証データ領域
flash3: 使用用途不明
※flashはNANDと呼ばれる物です。不用意に書き換えるとブリックします。全て共通。

通常であれば、ms0: / ef0: / disc0: のみ使用でしょうね。
そのほかは、書き込み権限が必要だったりします。
今回のサンプルアプリでは一工夫して、PSP-goの内臓メモリにアプリが置かれても、正常動作するようにしてあります(PSP-goでのテストはしていないw)。

前置きはこのぐらいにして、ソースコード見てみましょうか。
意味は無いのですが、関数ポインタを使用したmain関数とそうでないmain関数が記述してあります。
動作の違いはないです。いろんな書き方がある程度に考えておいてください。

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <pspctrl.h>

#include <string.h>


#define printf pspDebugScreenPrintf


PSP_MODULE_INFO( "HelloWorld", 0, 0, 1 );
PSP_MAIN_THREAD_ATTR( THREAD_ATTR_USER | THREAD_ATTR_VFPU );


char FILE_PATH[256] = "ms0:/test.txt"; // ファイルパス
int end_flag = 0;


int exit_callback( int arg1, int arg2, void *common )
{
end_flag = 1;
return 0;
}

int CallbackThread( SceSize args, void *argp )
{
int cbid = sceKernelCreateCallback( "Exit Callback", exit_callback, NULL );
sceKernelRegisterExitCallback( cbid );
sceKernelSleepThreadCB();
return 0;
}

int setupCallbacks( void )
{
int thid = sceKernelCreateThread( "update_thread", CallbackThread, 0x11, 0xFA0, 0, 0 );
if( thid >= 0 ) {
sceKernelStartThread( thid, 0, 0 );
}
return thid;
}

void init_screen( void )
{
pspDebugScreenInit();
pspDebugScreenSetXY( 0, 0 );

printf( "Sample application of file I/O.\n" );

printf( "Press Circle to write file.\n" );
printf( "Press Triangle to read file and display it.\n" );
printf( "Press Square to display file information.\n" );
printf( "Press X to exit.\n" );

printf( "\n" );
}

int write_file( void )
{
char data[] = "Hello,World!"; // ファイルに書き込む内容

SceUID fd = sceIoOpen( FILE_PATH, PSP_O_WRONLY | PSP_O_CREAT | PSP_O_TRUNC, 0777 );
if( fd < 0 ) {
return -1;
}

int nWrite = sceIoWrite( fd, data, sizeof(data) );
if( nWrite != sizeof(data) ) {
printf( "Error, write_file function.\n" );
sceIoClose( fd );
return -1;
} else {
printf( "Write file successful.\n" );
}

sceIoClose( fd );
return 0;
}

int read_file( void )
{
char buffer[32] = "";

SceUID fd = sceIoOpen( FILE_PATH, PSP_O_RDONLY, 0777 );
if( fd < 0 ) {
printf( "Can't open \"%s\"\n", FILE_PATH );
return -1;
}

int nRead = sceIoRead( fd, buffer, 31 ); // 31文字まで読み込む
if( nRead < 0 ) {
printf( "Error, read_file function.\n" );
sceIoClose( fd );
return -1;
}
buffer[nRead] = '\0'; // NULL文字を追加

printf( "Print file contents.\n\n" );
printf( buffer );
printf( "\n\n" );

sceIoClose( fd );
return 0;
}

char *GetDate( ScePspDateTime *time )
{
/* yyyy/mm/dd hh:mm:ss */
static char str[32];
sprintf( str, "%04u/%02u/%02u %02u:%02u:%02u",
time->year, time->month, time->day, time->hour, time->minute, time->second );
return str;
}

int print_file_info( void )
{
SceIoStat stat;
if( sceIoGetstat( FILE_PATH, &stat ) < 0 ) {
printf( "Can't open \"%s\"\n", FILE_PATH );
return -1;
}

printf( "File infomation.\n" );
printf( "Attribute : %s\n", (stat.st_attr & FIO_SO_IFREG)? "Regular" : "Unknown" );
printf( "Size : %lld byte\n", stat.st_size );
printf( "Created date : %s\n", GetDate( &stat.st_ctime ) );
printf( "Accessed date : %s\n", GetDate( &stat.st_atime ) );
printf( "Modified date : %s\n", GetDate( &stat.st_mtime ) );

return 0;
}

int exit_app( void )
{
printf( "Wait 3 seconds...\n" );
sceKernelDelayThread( 3000000 ); // Delay 3 seconds
sceKernelExitGame();
return 0;
}

void wait_anykey( void )
{
SceCtrlData pad;
printf( "\nPress any key...\n" );

sceKernelDelayThread( 1000000 ); // Delay 1 seconds

do {
sceKernelDelayThread( 10000 ); // Delay 0.01 seconds
sceCtrlReadBufferPositive( &pad, 1 );
} while( pad.Buttons == 0 );

do {
sceKernelDelayThread( 10000 );
sceCtrlReadBufferPositive( &pad, 1 );
} while( pad.Buttons != 0 );
sceKernelDelayThread( 1000000 ); // Delay 1 seconds
}

// PSP-Go support.
void get_root_path( char *path )
{
FILE_PATH[0] = path[0];
FILE_PATH[1] = path[1];
}

// 関数ポインタを使用したmain関数
int main( int argc, char *argv[] )
{
int n;
int keys[4] = { PSP_CTRL_CIRCLE, PSP_CTRL_TRIANGLE, PSP_CTRL_SQUARE, PSP_CTRL_CROSS };
int (*func[4])(void);
SceCtrlData pad;

func[0] = write_file;
func[1] = read_file;
func[2] = print_file_info;
func[3] = exit_app;

setupCallbacks();
init_screen();
get_root_path( argv[0] );

sceCtrlSetSamplingCycle( 0 );
sceCtrlSetSamplingMode( PSP_CTRL_MODE_DIGITAL );

while( end_flag != 1 )
{
sceCtrlReadBufferPositive( &pad, 1 );

for( n = 0; n < 4; n++ ) {
if( pad.Buttons & keys[n] ) {
func[n]();
wait_anykey();
init_screen();
break;
}
}
sceKernelDelayThread( 10000 ); // Delay 0.01 seconds
}

sceKernelExitGame();
return 0;
}

/*
// 関数ポインタを使用していないmain関数
int main( int argc, char *argv[] )
{
SceCtrlData pad;

setupCallbacks();
init_screen();
get_root_path( argv[0] );

sceCtrlSetSamplingCycle( 0 );
sceCtrlSetSamplingMode( PSP_CTRL_MODE_DIGITAL );

while( end_flag != 1 )
{
sceCtrlReadBufferPositive( &pad, 1 );

if( pad.Buttons & (PSP_CTRL_CIRCLE | PSP_CTRL_TRIANGLE | PSP_CTRL_SQUARE | PSP_CTRL_CROSS) ) {
if( pad.Buttons & PSP_CTRL_CIRCLE ) {
write_file();
}
else if( pad.Buttons & PSP_CTRL_TRIANGLE ) {
read_file();
}
else if( pad.Buttons & PSP_CTRL_SQUARE ) {
print_file_info();
}
else if( pad.Buttons & PSP_CTRL_CROSS ) {
exit_app();
}

wait_anykey();
init_screen();
}
sceKernelDelayThread( 10000 );
}

sceKernelExitGame();
return 0;
}
*/



Makefile

TARGET = FileIO
OBJS = main.o

INCDIR =
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

LIBDIR =
LDFLAGS =
LIBS =

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = FileIO

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak



そうしたら、ほかのとこから!_mk.batを持ってきて、ビルドして実行してみましょう。
動作を確かめたら、ソースコードをみて、どの様になっているのか、処理を追ってみて下さい。

今回のサンプルアプリはCFWなどのインストーラーを意識して作ってみました。
前々からやってみたかったw

さて、次回はこのソースコードの詳細説明です。
ではでは~ ノシ
スポンサーサイト
Comment
長文乙です。
今回自分もアプリ作ってました。できない所をこのサンプル見ながらやって完成しました。ありがとうございましたorz
Flash3は限定版PSPとかで使われるオリジナルctfデータ入れですお
ここに.ctfファイルを入れると設定のときにオリジナルとして読み込まれるはずです
Trackback
Trackback URL
Comment Form
管理者にだけ表示を許可する
Twitter...A

estuibal=Y.K < > Reload

検索フォーム
RSSリンクの表示
リンク
QRコード
QR
ブロとも申請フォーム
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。