/*---------------------------------------------------------------------------* Project: Sample demo program for NAND library File: check.c Programmer: HIRATSU Daisuke Copyright (C) 2006 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: check.c,v $ Revision 1.4 2006/12/20 02:53:17 hiratsu Refactoring. Added comments. Revision 1.3 2006/12/14 09:00:52 hiratsu Almost completely revised. Revision 1.2 2006/09/06 09:42:48 hiratsu Fixed wrong message. Revision 1.1 2006/09/05 12:49:28 hiratsu Sample demo program for NANDCheck(). *---------------------------------------------------------------------------*/ #include #include #include #include "util.h" #define PERM (NAND_PERM_OWNER_READ | NAND_PERM_OWNER_WRITE) /* Owner can read/write */ #define ATTR 0x00 /* No attributes. */ #define BUF_SIZE (128*1024) /* 128KB */ /* Please note 1 FS block is 16 KB. */ #define FILE_A_SIZE ( 1*1024) /* 1KB occupies 1 FS block. */ #define FILE_B_SIZE ( 130*1024) /* 130KB occupies 9 FS blocks. 130KB = 16KB * 8 + 2KB) */ #define FILE_C_SIZE (2*1024*1024) /* 2MB occupies 128 FS blocks. 2MB = 16KB * 128 */ /* Below files are placed under ~/profile[n] */ #define FILE_A_NAME "a.dat" #define FILE_B_NAME "b.dat" #define FILE_C_NAME "c.dat" static BOOL init(void); static BOOL generateFile(const char *path, u32 size); /* Creates dummy file. */ static BOOL createDir(const char *path); static BOOL generateSaveFile(const char *path); static BOOL verifySaveFile(const char *path); /* Does save data already exist? */ static BOOL nandCheck(u32 fsBlock, u32 inode); /* Wrapper function for NANDCheck(). */ static BOOL moveToHome(const char *src); /* /tmp/profile[n] -> ~/profile[n] */ static char s_homePath[NAND_MAX_PATH] = ""; int main(void) { u16 prev_button = 0x0000; init(); OSReport("This is NANDCheck() demo program.\n"); OSReport("Press A to create save data.\n"); OSReport("Press START to halt this demo.\n"); while(1) { PADStatus pad[PAD_MAX_CONTROLLERS]; PADRead(pad); if((pad[PAD_CHAN0].button & PAD_BUTTON_A) && !(prev_button & PAD_BUTTON_A)) { /* Try to create save files and directory. */ if(nandCheck(1+9+128, 1+3)) { char saveFilePath[NAND_MAX_PATH]; char tmpFilePath[NAND_MAX_PATH]; int i = 0; for(;; ++i) { sprintf(saveFilePath, "profile%d", i); if(!verifySaveFile(saveFilePath)) { break; } } OSReport("NANDCheck() passed. Creating files/directories...\n"); sprintf(tmpFilePath, "/tmp/%s", saveFilePath); if(!generateSaveFile(tmpFilePath)) { OSReport("generateSaveFile() failed.\n"); } else{ if(!moveToHome(tmpFilePath)) { OSReport("moveToHome() failed.\n"); } else{ OSReport("Done. Save files are created under ~/%s .\n", saveFilePath); } } } } if(pad[PAD_CHAN0].button & PAD_BUTTON_START) { OSHalt("START buttun was pressed. Halt."); } prev_button = pad[PAD_CHAN0].button; VIWaitForRetrace(); } return 0; // Never reach here. } static BOOL init(void) { s32 ret = NAND_RESULT_FATAL_ERROR; VIInit(); PADInit(); ret = NANDGetHomeDir(s_homePath); if(ret!=NAND_RESULT_OK) { OSReport("NANDGetHomeDir() failed. (Result code: %d)\n", ret); return FALSE; } return TRUE; } static BOOL generateSaveFile(const char *path) { const char *FILENAME[] = {FILE_A_NAME, FILE_B_NAME, FILE_C_NAME}; const u32 FILESIZE[] = {FILE_A_SIZE, FILE_B_SIZE, FILE_C_SIZE}; char filePath[NAND_MAX_PATH] = ""; int i = 0; if(!createDir(path)) { OSReport("createDir() failed.\n"); return FALSE; } for(i = 0; i<3; ++i) { sprintf(filePath, "%s/%s", path, FILENAME[i]); if(!generateFile(filePath, FILESIZE[i])) { OSReport("generateFile() failed.\n"); return FALSE; } } return TRUE; } static BOOL generateFile(const char *path, u32 size) { static u8 s_buffer[BUF_SIZE] ATTRIBUTE_ALIGN(32); NANDFileInfo info; u32 i = 0; s32 ret = NAND_RESULT_FATAL_ERROR; ret = NANDCreate(path, PERM, ATTR); if(ret != NAND_RESULT_OK) { printErrMsg(ret); OSReport("NANDCreate() failed. Result code: %d\n", ret); return FALSE; } ret = NANDOpen(path, &info, NAND_ACCESS_WRITE); if(ret != NAND_RESULT_OK) { printErrMsg(ret); OSReport("NANDOpen() failed. Result code: %d\n", ret); return FALSE; } for(i = 0; i size) { sz = size - i; } else { sz = BUF_SIZE; } ret = NANDWrite(&info, s_buffer, sz); if(ret != sz) { printErrMsg(ret); OSReport("NANDWrite() failed. Result code: %d\n", ret); NANDClose(&info); return FALSE; } } ret = NANDClose(&info); if(ret != NAND_RESULT_OK) { printErrMsg(ret); OSReport("NANDClose() failed. Result code: %d\n", ret); return FALSE; } return TRUE; } static BOOL createDir(const char *path) { s32 ret = NAND_RESULT_FATAL_ERROR; ret = NANDCreateDir(path, PERM, ATTR); if(ret != NAND_RESULT_OK) { printErrMsg(ret); OSReport("NANDCreateDir() failed. Result code: %d\n", ret); return FALSE; } return TRUE; } static BOOL nandCheck(const u32 fsBlock, const u32 inode) { u32 answer = 0xffffffff; s32 ret = NANDCheck(fsBlock, inode, &answer); if(ret==NAND_RESULT_OK) { if(answer==0) { return TRUE; } else { if(answer & NAND_CHECK_HOME_INSSPACE) { OSReport("Your request will exceed limit of home directory (16MB).\n"); } if(answer & NAND_CHECK_HOME_INSINODE) { OSReport("Your request will exceed limit of home directory (32 i-nodes).\n"); } if(answer & NAND_CHECK_SYS_INSSPACE) { OSReport("Your request will invade space of system area.\n"); } if(answer & NAND_CHECK_SYS_INSINODE) { OSReport("Your request will invade i-nodes of system area.\n"); } return FALSE; } } else { OSReport("NANDCheck() failed. Result code: %d\n", ret); return FALSE; } } static BOOL moveToHome(const char *src) { s32 ret = NAND_RESULT_FATAL_ERROR; ret = NANDMove(src, s_homePath); if(ret != NAND_RESULT_OK){ printErrMsg(ret); OSReport("NANDMove() failed. Result code: %d\n", ret); return FALSE; } return TRUE; } // This function just checks specified directory exists or not. // Of course, more decent checking mechanism is required in your // application program. static BOOL verifySaveFile(const char *path) { s32 ret = NAND_RESULT_FATAL_ERROR; u8 type = 0x00; ret = NANDGetType(path, &type); if(ret == NAND_RESULT_OK && type == NAND_TYPE_DIR) { return TRUE; } else { return FALSE; } }