ctr_Repair/branches/CardCupForNBD/CardSaveData/Mover/body/source/main.cpp
N2614 b6024ff808 セルフCUPツール NBDリリース向けブランチ
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@337 385bec56-5757-e545-9c3a-d8741f4650f1
2011-06-14 00:36:31 +00:00

1452 lines
45 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*---------------------------------------------------------------------------*
Project: Horizon
File: main.cpp
Copyright (C)2010 Nintendo Co., Ltd. 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.
*---------------------------------------------------------------------------*/
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <nn.h>
//#include <nn/os.h>
#include <nn/applet.h>
#include <nn/ndm.h>
#include <nn/ndm/ndm_DebugControl.h>
#include <nn/fs/ctr/mpcore/fs_FileSystemBasePrivate.h>
#include <nn/fs/fs_Parameters.h>
//#include <nn/fs/fs_ApiProcessInfo.h>
#include "../../../common/savefile/savefile.h"
#include "../../../common/savefile/savedata.h"
#ifdef BKUP_NOTMEM
#include "./savefile/exsave.h"
#else
#include "../../../common/savefile/membak.h"
#endif
#include "./screen/screen.h"
#include "../../../common/common.h"
nn::fnd::ExpHeap appHeap;
uptr heapForGx;
//Gui gui;
myResult errRes;
#ifdef BKUP_NOTMEM
const u32 IconBuffSize = 1024*20;
uptr IconBuffer;
size_t IconSize;
#endif
#ifdef DEBUG_ENABLE
cStrLst memo;
#endif
bool isDebugMode = false;//デバッグモード
//char strBuff[128];
//bool exist;
SaveData savedata;
nn::os::LightEvent ejectEvnt(false);
nn::os::LightEvent insEvnt(false);
#ifdef BKUP_NOTMEM
ExSave exsave;
nn::os::LightEvent ejectEvntSd(false);
nn::os::LightEvent insEvntSd(false);
#else
MemBak exsave;
#endif
//バックアップの状態
bool Active,Formatted;
bool exActive,exFormatted;
tArcInfo arcInfo,arcInfo_ex;//アーカイブ情報
//プロダクトコードの一致
bool isAgreePCode;
//ベリファイ結果
//bool failveri;
//Top画面エラー表示
int tmerr;
#ifdef ENABLE_CRUSH
int CrashForDebug= 0;
#endif
//結果
typedef enum {
SUCCESS
,ERROR
,CANCEL
,INSEXIT
}RetCode;
//挿抜イベント時に設定
typedef enum {
InEx_None
,InEx_InsCard
,InEx_EjcCard
#ifdef BKUP_NOTMEM
,InEx_InsSd
,InEx_EjcSd
#endif
}tIsInsEject;
tIsInsEject isInsEject;
extern u8 scr_evnt;
void WaitUI();
void PutError(ErcDev dev,int cd=0);
//終了処理
void endfunc()
{
nn::fs::UnregisterCardEjectedEvent();
nn::fs::UnregisterCardInsertedEvent();
ejectEvnt.Finalize();
insEvnt.Finalize();
#ifdef BKUP_NOTMEM
nn::fs::UnregisterSdmcEjectedEvent();
nn::fs::UnregisterSdmcInsertedEvent();
ejectEvntSd.Finalize();
insEvntSd.Finalize();
#endif
savedata.Finalize();
exsave.Finalize();
ScrFinalize();
#ifdef BKUP_NOTMEM
appHeap.Free(reinterpret_cast<void*>(IconBuffer));
#endif
}
//エラー停止
void failstop()
{
NN_LOG("fail %d,stop\n",errRes);
finish();
}
#ifdef DEBUG_ENABLE
//ログ追加&表示
void LogAdd(char *s)
{
memo.add(s);
if(isDebugMode){
scr_DgbLog(&memo);
while(ScrGetDrawFlag()){
nn::os::Thread::Yield();//表示
}
}
}
char dst[128],work[64];
void LogAdd_Int(char *s,int i)
{
sprintf(dst,s,i);
LogAdd(dst);
}
void LogAdd_cat(char *s,char *s2)
{
strcpy(dst,s);
strcat(dst,s2);
LogAdd(dst);
}
void LogAdd_bytes(char *s,u8 *b,int n)
{
int i;
for (i=0;i<n;i++){
work[i] = b[i];
}
work[i]=0;
strcpy(dst,s);
strcat(dst,work);
LogAdd(dst);
}
void LogAdd_Res(nn::Result res)
{
LogAdd_Int("> desc = %d",res.GetDescription());
}
void LogAdd_Fparam(tArcInfo *p)
{
LogAdd_Int("FileCount %d",p->FileCount);
LogAdd_Int("DirCount %d",p->DirCount);
LogAdd_Int("FileEntry %d",p->FileEntry);
LogAdd_Int("DirEntry %d",p->DirEntry);
}
void LogAdd_InfoParam(tArcInfo *p)
{
LogAdd_Int("Version %d",p->Ver);
LogAdd_cat("> pcode = ",p->Pcode);
LogAdd_Fparam(p);
}
#else
void LogAdd(char *s)
{
NN_UNUSED_VAR(s);
}
void LogAdd_Int(char *s,int i)
{
NN_UNUSED_VAR(s);
NN_UNUSED_VAR(i);
}
void LogAdd_cat(char *s,char *s2)
{
NN_UNUSED_VAR(s);
NN_UNUSED_VAR(s2);
}
void LogAdd_bytes(char *s,u8 *b,int n)
{
NN_UNUSED_VAR(s);
NN_UNUSED_VAR(b);
NN_UNUSED_VAR(n);
}
void LogAdd_Res(nn::Result res)
{
NN_UNUSED_VAR(res);
}
void LogAdd_Fparam(tArcInfo *p)
{
NN_UNUSED_VAR(p);
}
void LogAdd_InfoParam(tArcInfo *p)
{
NN_UNUSED_VAR(p);
}
#endif
char sts[64];
void PutError(ErcDev dev,int cd)
{
nn::Result res;
switch (dev)
{
case ERC_DEV_CARD: res = savedata.LastNnResult;break;
case ERC_DEV_OUT: res = exsave.LastNnResult;break;
}
GetErrorStr(dev,res,cd,sts);
scr_Status(sts,COLOR_RED);
}
//-------------------------------------------------- Verifi
wchar_t file_pathw[MAX_PATH_LENGTH];
char file_path[MAX_PATH_LENGTH];
//ドライバの仕様で速度的に4バイトアラインした方がいい(SDK 0.14.23 時点)
char fileBuffer[512] NN_ATTRIBUTE_ALIGN(4);//検証が512単位なので
char fileBuffer_ex[512] NN_ATTRIBUTE_ALIGN(4);
#define FILEBUFF_SIZE sizeof(fileBuffer)
bool Verifi()
{
myResult res;
int ct,i,msize,rsize;
s64 total=0;
LogAdd("Verifi");
//セーブデータのマウント
LogAdd("Mount savedata");
res = savedata.Mount();
if(res != RESULT_OK){
PutError(ERC_DEV_CARD);
return false;
}
/*
if(isDebugMode==false) scr_Status("Ready to Verifi",COLOR_YELLO);
//情報ファイル
LogAdd("Directry Info");
if(savedata.GetInfo(&arcInfo)==false)
{
LogAdd("> get fail");//有効な情報ファイルがない
savedata.Unmount();
PutError(ERC_DEV_CARD);
return ERROR;
}
LogAdd_Fparam(&arcInfo);
*/
//出力デバイスのマウント
#ifdef BKUP_NOMEM //フラグ間違えチェック用に表示分け
LogAdd("Mount Device");//不揮発メディア
#else
LogAdd("memory setup");//メモリ保存
#endif
res = exsave.Mount();
if(res != RESULT_OK){
PutError(ERC_DEV_OUT);
return false;
}
//情報ファイル
LogAdd("Directry Info(out)");
if (exsave.GetInfo(&arcInfo_ex))
{
//todo:フォーマット変更時はバージョンチェック入れる
LogAdd_InfoParam(&arcInfo_ex);
}else {
LogAdd("> get fail");//有効な情報ファイルがない
savedata.Unmount();
exsave.Unmount();
return false;
}
//フォーマット情報の比較
if ((arcInfo.DirEntry != arcInfo_ex.DirEntry) ||
(arcInfo.FileEntry != arcInfo_ex.FileEntry) ||
(arcInfo.Dup != arcInfo_ex.Dup))
{
LogAdd("> verifi fail");//有効な情報ファイルがない
PutError(ERC_DEV_OUT,ERC_VERIFI);
savedata.Unmount();
exsave.Unmount();
return false;
}
ct =0;
if (arcInfo.FileCount == 0)//ファイルが無い
{
LogAdd("> no files");
savedata.Unmount();
exsave.Unmount();
return true;//フォーマット一致のみ
}else{
LogAdd("-- file compair --");
if(isDebugMode==false) scr_Status("file compairing",COLOR_YELLO);
savedata.ResetPath();
exsave.ResetPath();
s64 fsize;
res = RESULT_OK;
while(res==RESULT_OK){
res = savedata.GetPath(file_pathw);
if (res != RESULT_OK)
{
LogAdd("failed to get path");
if (res == RESULT_DIR_LEVEL_OVER){
LogAdd("Dir Level Over");
break;
}
if (res == RESULT_PATH_LENGTH_OVER){
LogAdd("path name too long");
break;
}
res = RESULT_FAIL_OPEN;
break;
}
if (file_pathw[0] == 0){LogAdd("end");break;}//root then end
if (ct>=arcInfo.FileCount)
{//カウンタ壊れ、メモリフローの可能性
LogAdd("memory error");
res = RESULT_FAIL;
break;
}
#ifdef DEBUG_ENABLE
wcstombs(file_path,file_pathw,510);
LogAdd(file_path);
#endif
if(isDebugMode==false) scr_CountPerMax(ct,arcInfo.FileCount);
if (savedata.Open(file_pathw)==false)
{
LogAdd("Open Error(card)");
res = RESULT_FAIL_OPEN;
break;
}
fsize = savedata.FileSize;
total += fsize;
if (exsave.Open(file_pathw)==false)
{
LogAdd("Open Error(out)");
res = RESULT_FAIL_OPENW;
//savedata.Close();
break;
}
if (fsize != exsave.FileSize)//file size
{
res = RESULT_FAIL;
break;
}
msize=fsize;
if(msize <= FILEBUFF_SIZE ){//一回で読めるサイズならゲージは出さない
if(isDebugMode==false) scr_CountPerMax2(0,0,-1);
}
while(fsize)
{
if(msize > FILEBUFF_SIZE ){
if(isDebugMode==false) scr_CountPerMax2(msize-fsize,msize,0);
}
if (fsize > FILEBUFF_SIZE)
{
rsize = FILEBUFF_SIZE;
fsize -= FILEBUFF_SIZE;
}else{
rsize = fsize;
fsize = 0;
}
if(savedata.Read(fileBuffer,rsize) != rsize )
{
//中身のデータが作成サイズに満たない場合に検証エラーとなる対策
//読めないブロックは置き換える
//検証は512単位でされるので読めてるとこまで置き換えないよう
//リードサイズは512にしておく
if(nn::fs::ResultVerificationFailed::Includes(savedata.LastNnResult))
{
for (i = 0; i < rsize; i++)
{
fileBuffer[i] = 0;//0埋め
}
}else{
LogAdd("Read Error(card)");
res = RESULT_FAIL_READ;
break;
}
}
if(exsave.Read(fileBuffer_ex,rsize) != rsize )
{
LogAdd("Read Error(out)");
res = RESULT_FAIL;
break;
}
}
savedata.Close();
exsave.Close();
if (res != RESULT_OK)break;
//verifi
for (i = 0;i<rsize;i++)if (fileBuffer[i] != fileBuffer_ex[i])
{
LogAdd("verifi error");
res = RESULT_FAIL;
break;
}
ct++;
}
savedata.Close();
exsave.Close();
}
savedata.Unmount();
exsave.Unmount();
if(isDebugMode==false)
{
scr_CountPerMax(ct,arcInfo.FileCount);
scr_CountPerMax2(0,0,total);
}
if (res != RESULT_OK){
PutError(ERC_DEV_OUT,ERC_VERIFI);
return false;
}
return true;
}
//---------------------------------------------------------------------- from CARD
RetCode Card2Sd()
{
myResult res;
int ct=0,msize,rsize;
s64 total=0;
LogAdd("-- read savedata --");
if(isDebugMode == false){
scr_BackupYesNo();//実行確認
WaitUI();//入力待ち
if(isInsEject != InEx_None )
{//挿抜?
//isInsEject = InEx_None;
return INSEXIT;//挿抜による中断
}
if (scr_evnt != EVNT_YES)return CANCEL;//キャンセル
}
if(isDebugMode==false){
scr_Backup();//画面表示
scr_Status("Check CARD",COLOR_YELLO);
}
//セーブデータのマウント
LogAdd("Mount savedata");
res = savedata.Mount();
if(res != RESULT_OK){
PutError(ERC_DEV_CARD);
return ERROR;
}
LogAdd("Get Directry Infomation");
if(savedata.GetInfo(&arcInfo)==false)
{
savedata.Unmount();
PutError(ERC_DEV_CARD);
return ERROR;
}
LogAdd_Fparam(&arcInfo);
if(isDebugMode==false) scr_Status("BackUp Check",COLOR_YELLO);
LogAdd("check bkup Existance");
if(exsave.IsExist()){
LogAdd("> detect");
if(exsave.Delete()) LogAdd("> deleted");
else{
savedata.Unmount();
LogAdd("delete failed");
PutError(ERC_DEV_OUT);
return ERROR;
}
}else{
LogAdd("not found");
}
if(isDebugMode==false)scr_Status("Create Backup",COLOR_YELLO);
LogAdd("Create bkup");
#ifdef BKUP_NOTMEM
res = exsave.Create((void*)IconBuffer,IconSize
,arcInfo.DirEntry+1,arcInfo.FileEntry+1);//管理情報
#else
res = exsave.Create(0,0,arcInfo.DirEntry+1,arcInfo.FileEntry+1);//管理情報
#endif
if (res != RESULT_OK){
savedata.Unmount();
PutError(ERC_DEV_OUT);
return ERROR;
}
if (arcInfo.FileCount == 0)//ファイルが無い
{
LogAdd("> no files");
if(isDebugMode==false)scr_Status("no files",COLOR_YELLO);
savedata.Unmount();
exsave.Unmount();
return SUCCESS;//フォーマットのみ
}else{
LogAdd("-- file copy --");
if(isDebugMode==false)scr_Status("file copying",COLOR_SKY);
savedata.ResetPath();
s64 fsize;
res = RESULT_OK;
while(res==RESULT_OK){
res = savedata.GetPath(file_pathw);
if (res != RESULT_OK)
{
LogAdd("failed to get path");
if (res == RESULT_DIR_LEVEL_OVER){
LogAdd("Dir Level Over");
PutError(ERC_DEV_CARD,ERC_DIRDEPTH);
break;
}
if (res == RESULT_PATH_LENGTH_OVER){
LogAdd("path name too long");
PutError(ERC_DEV_CARD,ERC_PATH);
break;
}
res = RESULT_FAIL_OPEN;
break;
}
if (file_pathw[0] == 0){LogAdd("end");break;}//root then end
if (ct>=arcInfo.FileCount)
{//カウンタ壊れ、メモリフローの可能性
LogAdd("memory error");
res = RESULT_FAIL;
break;
}
#ifdef DEBUG_ENABLE
wcstombs(file_path,file_pathw,510);
LogAdd(file_path);
#endif
if(isDebugMode==false) scr_CountPerMax(ct,arcInfo.FileCount);
if (savedata.Open(file_pathw)==false)
{
LogAdd("Open Error(card)");
res = RESULT_FAIL_OPEN;
break;
}
fsize = savedata.FileSize;
total += fsize;
if (exsave.OpenW(file_pathw,fsize)==false)
{
LogAdd("Open Error(sd)");
res = RESULT_FAIL_OPENW;
//savedata.Close();
break;
}
msize=fsize;
while(fsize)
{
if(msize > FILEBUFF_SIZE * 2){
if(isDebugMode==false) scr_CountPerMax2(msize-fsize,msize,0);
}
if (fsize>FILEBUFF_SIZE)
{
rsize = FILEBUFF_SIZE;
fsize -= FILEBUFF_SIZE;
}else{
rsize = fsize;
fsize = 0;
}
if(savedata.Read(fileBuffer,rsize) != rsize )
{
//中身のデータが作成サイズに満たない場合に検証エラーとなる対策
//読めないブロックは置き換える
//検証は512単位でされるので読めてるとこまで置き換えないよう
//リードサイズは512にしておく
if(nn::fs::ResultVerificationFailed::Includes(savedata.LastNnResult))
{
for (int i = 0; i < rsize; i++)
{
fileBuffer[i] = 0;//0埋め
}
}else{
LogAdd("Read Error(card)");
res = RESULT_FAIL_READ;
break;
}
}
if(exsave.Write(fileBuffer,rsize) != rsize )
{
LogAdd("Write Error(bkup)");
res = RESULT_FAIL_WRITE;
break;
}
}
savedata.Close();
exsave.CloseW();
//todo: ゲージ表示
ct++;
}
savedata.Close();
exsave.CloseW();
}
if (res == RESULT_OK){
if (ct != arcInfo.FileCount)//ファイル数に満たないパス検索終了
{//ディレクトリ情報かパス取得で失敗してると思われる
PutError(ERC_DEV_OTHER,ERC_EXEC);
return ERROR;
}
//フォーマット情報を記録
//Exsaveに2重化が無いので情報取得APIでは不足 - 2011.1 現在
//プロダクトコードを追加(2011.1.26)
//バージョンを追加(2011.1.27)
LogAdd("save systemfile");
if (exsave.OpenSysW())
{
strcpy(arcInfo.Pcode,savedata.PrdCode);
if(exsave.WriteSys(&arcInfo)){
LogAdd("> done");
}else{
LogAdd("> write fail");
res = RESULT_FAIL_WRITE;
}
}else{
LogAdd("> open fail");
res = RESULT_FAIL_OPENW;
}
exsave.CloseSysW();
}
savedata.Unmount();
//exsave.Commit(); Nandはコミット入れる(NAND未実装->MEM変更、今後も不要)
exsave.Unmount();
LogAdd_Int("> %d files",ct);
if(isDebugMode==false){
scr_CountPerMax(ct,arcInfo.FileCount);
if(total>0)scr_CountPerMax2(0,0,total);
}
//結果
switch(res)
{
case RESULT_OK:
if (Verifi()==false)return ERROR;
if(isDebugMode==false) scr_Status("Complate",COLOR_WHITE);
return SUCCESS;
case RESULT_FAIL_WRITE:
case RESULT_FAIL_OPENW:
PutError(ERC_DEV_OUT);
exsave.Delete();//バックアップを削除
return ERROR;
case RESULT_FAIL_READ:
case RESULT_FAIL_OPEN:
PutError(ERC_DEV_CARD);
exsave.Delete();//バックアップを削除
return ERROR;
}
//その他、実行時エラー
PutError(ERC_DEV_OTHER);
return ERROR;
}
bool mkdir;
//---------------------------------------------------------------- SD->CARD
RetCode Sd2Card()
{
myResult res;
int ct=0,msize,rsize;
s64 total = 0;
LogAdd("-- write savedata --");
if(isDebugMode == false){
scr_RestoreYesNo();//実行確認
WaitUI();//入力待ち
if(isInsEject != InEx_None ){//挿抜?
//isInsEject = InEx_None;
return INSEXIT;//挿抜による中断
}
if (scr_evnt != EVNT_YES)return CANCEL;//キャンセル
}
if(isDebugMode==false){
scr_Restore();//画面表示
scr_Status("Check Backup",COLOR_YELLO);
}
//保存先のマウント
LogAdd("Mount bkup");
res = exsave.Mount();
if(res != RESULT_OK){
PutError(ERC_DEV_OUT);
return ERROR;
}
//セーブデータのフォーマット&マウント
if(isDebugMode==false)scr_Status("Card savedata Create",COLOR_YELLO);
LogAdd("Format savedata");
res = savedata.Format(&arcInfo);//_exの方がいいかも
if(res != RESULT_OK){
exsave.Unmount();
PutError(ERC_DEV_CARD);
return ERROR;
}
//パラメータはバックアップ時
//Top画面開始時、挿入イベントで取得
if (arcInfo.FileCount == 0)//ファイルが無い
{
LogAdd("> no files");
savedata.Unmount();
exsave.Unmount();
return SUCCESS;//フォーマットのみ
}else{
LogAdd("-- file restore --");
if(isDebugMode==false)scr_Status("file copying",COLOR_PARPL);
exsave.ResetPath();
s64 fsize;
res = RESULT_OK;
while(res==RESULT_OK){
res = exsave.GetPath(file_pathw);
if (res != RESULT_OK)
{
LogAdd("failed to get path");
if (res == RESULT_DIR_LEVEL_OVER){
LogAdd("Dir Level Over");
break;
}
if (res == RESULT_PATH_LENGTH_OVER){
LogAdd("path name too long");
break;
}
res = RESULT_FAIL_OPEN;
break;
}
if (file_pathw[0] == 0){LogAdd("end");break;}//root then end
if (ct>=arcInfo.FileCount)
{//カウンタ壊れ、メモリフローの可能性
LogAdd("memory error");
res = RESULT_FAIL;
break;
}
#ifdef DEBUG_ENABLE
wcstombs(file_path,file_pathw,510);
LogAdd(file_path);//todo:デバグ表示オーバ対策
#endif
if(isDebugMode==false) scr_CountPerMax(ct,arcInfo.FileCount);
if (exsave.Open(file_pathw)==false)
{
LogAdd("Open Error(bkup)");
res = RESULT_FAIL_OPEN;
break;
}
fsize = exsave.FileSize;
total += fsize;
#ifdef ENABLE_CRUSH
//デバグ用に違うファイル名にする
if (CrashForDebug & 2)wcscat(file_pathw,L"D");
#endif
int rev = 0;
while(1){
if (savedata.OpenC(file_pathw,fsize,&mkdir)==false)
{
if(mkdir)//ディレクトリのみ作成
{//深い場合に作成が多いと画面が止まるので
LogAdd("Dir create");
rev++;
if (rev & 1)scr_MessOnCount2("Create Directry -");
else scr_MessOnCount2("Create Directry |");
}else{
LogAdd("Open Error(card)");
res = RESULT_FAIL_OPENW;
//exsave.Close();
break;
}
}else break;
}
if (res != RESULT_OK)break;
msize = fsize;
int itvl = 0;
while(fsize)
{
if(isDebugMode==false)
if(msize > FILEBUFF_SIZE * 2){
scr_CountPerMax2(msize-fsize,msize,0);
if (++itvl & 1)scr_Status("file copying |",COLOR_PARPL);
else scr_Status("file copying -",COLOR_PARPL);
}else scr_MessOnCount2("");
if (fsize>FILEBUFF_SIZE)
{
rsize = FILEBUFF_SIZE;
fsize -= FILEBUFF_SIZE;
}else{
rsize = fsize;
fsize = 0;
}
if(exsave.Read(fileBuffer,rsize) != rsize )
{
LogAdd("Read Error(bkup)");
res = RESULT_FAIL_READ;
break;
}
#ifdef ENABLE_CRUSH
//デバグ用にデータを壊す
if (CrashForDebug & 1)//中身
{
int i;
for (i = 0;i<rsize;i++)fileBuffer[i] ^=0xff;
}
#endif
if(savedata.Write(fileBuffer,rsize) != rsize )
{
LogAdd("Write Error(CARD)");
res = RESULT_FAIL_WRITE;
break;
}
}
savedata.CloseW();
exsave.Close();
ct++;
}
savedata.Close();
exsave.CloseW();
}
savedata.Commit();
savedata.Unmount();
exsave.Unmount();
LogAdd_Int("> %d files",ct);
if(isDebugMode==false){
scr_CountPerMax(ct,arcInfo.FileCount);
scr_CountPerMax2(0,0,total);
}
//結果
switch(res){
case RESULT_OK:
if (Verifi()==false)return ERROR;
#ifdef SUCCESS_DELETE
if(exsave.Delete()){//バックアップを削除
LogAdd("> deleted");
#endif
if(isDebugMode==false) scr_Status("Complate",COLOR_WHITE);
return SUCCESS;
#ifdef SUCCESS_DELETE
}else{
LogAdd("> delete fail");
PutError(ERC_DEV_OUT);
return ERROR;
}
#endif
case RESULT_FAIL_WRITE:
case RESULT_FAIL_OPENW:
PutError(ERC_DEV_CARD);
return ERROR;
case RESULT_FAIL_READ:
case RESULT_FAIL_OPEN:
PutError(ERC_DEV_OUT);
return ERROR;
}
//その他、実行時エラー
PutError(ERC_DEV_OTHER);
return ERROR;
}
//メモリ保存では不要
#ifdef BKUP_NOTMEM
//------------------------------------------------------------------ アイコンデータ
//NAND起動で失敗は無いはず
void ReadIcon()
{
const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
static char buffer[ROMFS_BUFFER_SIZE];
nn::Result res;
Active = false;
Formatted = false;
//Iconデータ
//NN_LOG("ICON Data Read\n");
LogAdd("Mount Rom");
nn::fs::FileReader RomFsFile;
res = nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE);
if (res.IsFailure())
{
//NN_LOG("failed :res.desc = %d\n",res.GetDescription());
//failstop();
LogAdd("> failed");
LogAdd_Res(res);
return;
}
LogAdd("Read Icon data");
res = RomFsFile.TryInitialize(L"rom:/def.icn");
if (res.IsFailure())
{
//NN_LOG("failed :res.desc = %d\n",res.GetDescription());
nn::fs::Unmount("rom:");
//failstop();
LogAdd("> open failed");
LogAdd_Res(res);
return;
}
//s32 gs = RomFsFile.GetSize();
//NN_LOG("Icon Size = %d\n",gs);
res = RomFsFile.TryRead((s32*)&IconSize,(void*)IconBuffer,IconBuffSize);
if (res.IsFailure())
{
//NN_LOG("failed :res.desc = %d\n",res.GetDescription());
//RomFsFile.Finalize();
nn::fs::Unmount("rom:");
//failstop();
LogAdd("> read failed");
LogAdd_Res(res);
return;
}
//NN_LOG("Read Size = %d\n",IconSize);
RomFsFile.Finalize();
nn::fs::Unmount("rom:");
}
#endif
//--------------------------------------------------------------- セーブデータの情報取得
//呼ぶ前に tmerr のクリアを忘れない事
void CheckSaveDataState()
{
myResult myres;
Formatted = false;//フォーマット
Active = false;
//failveri = false;
LogAdd("get pcode");
if (savedata.GetPrdCode())
{
LogAdd_cat("> pcode = ",savedata.PrdCode);
LogAdd("check savedata");
myres = savedata.IsExist();
NN_LOG("%d",savedata.LastNnResult.GetDescription());
if (myres != RESULT_FAIL)
{
Active = true;//アクセス可能
switch(myres){
case RESULT_OK:
LogAdd("> exist");
Formatted=true;
break;
case RESULT_NO_MEDIA:
LogAdd("> Media not found");
tmerr |= SDATA_ERRPUT_MEDIA;
break;
case RESULT_NOT_FAUND:
LogAdd("> not Found");
break;
case RESULT_SDK_VERIFI:
LogAdd("> sdk verifi err");
//failveri = true;
tmerr |= SDATA_ERRPUT_VERIFI;
break;
default:
LogAdd("> Not/Bad Format");
break;
}
}else{
LogAdd("> Invalid state");
LogAdd_Res(savedata.LastNnResult);
}
}else
{
LogAdd("> fail");
}
scr_PrdCode(savedata.PrdCode);
//プロダクトコードのチェック
isAgreePCode = strcmp(savedata.PrdCode,arcInfo.Pcode)==0;
}
void CheckExSaveState()
{
LogAdd("check exsave");
#ifdef BKUP_NOTMEM
exActive = nn::fs::IsSdmcInserted();
#else
exActive = true;
#endif
if (exActive){
exFormatted = exsave.IsExist();
if (exFormatted){
LogAdd("> exist");
if (exsave.GetInfo(&arcInfo))
{
LogAdd_InfoParam(&arcInfo);
//todo:フォーマット変更時はバージョンチェック入れる
}else {
LogAdd("> sysdata none");//有効な情報ファイルがない
//arcInfo.Pcode[0] = 0;
exFormatted = false;
}
exsave.Unmount();
}else{
LogAdd("> not found");
//arcInfo.Pcode[0] = 0;
}
}else{
LogAdd("> not inserted");
//arcInfo.Pcode[0] = 0;
exFormatted = false;
}
if (exFormatted==false) arcInfo.Pcode[0] = 0;
scr_PrdCodeEx(arcInfo.Pcode);
//プロダクトコードのチェック
isAgreePCode = strcmp(savedata.PrdCode,arcInfo.Pcode)==0;
}
//---------------------------------------------------------------- 入力待ち
void WaitUI()
{
tmerr = 0;
scr_Draw();//画面更新
scr_evnt = EVNT_NONE;
while(scr_evnt == EVNT_NONE)
{
nn::os::Thread::Yield();//スレッド実行
//scr_GetEvnt();//入力イベント
CheckSysBreak();//中断処理
int i = nn::ndm::GetDaemonStatus( nn::ndm::DN_CEC );
if (i !=3 )NN_LOG("DN_CEC %d\n",i);
i = nn::ndm::GetDaemonStatus( nn::ndm::DN_BOSS );
if (i !=3 )NN_LOG("DN_BOSS %d\n",i);
i = nn::ndm::GetDaemonStatus( nn::ndm::DN_NIM );
if (i !=3 )NN_LOG("DN_NIM %d\n",i);
i = nn::ndm::GetDaemonStatus( nn::ndm::DN_FRIENDS );
if (i !=3 )NN_LOG("DN_FRIENDS %d\n",i);
//挿抜を検知したら中断して抜ける
//トップ以外ではトップメニューへ戻るようする
if (ejectEvnt.TryWait()){
LogAdd("Card Ejected");//状態表示:抜け
CheckSaveDataState();
isInsEject = InEx_EjcCard;
return;
}
if (insEvnt.TryWait()){
LogAdd("Card Inserted");//状態表示:挿入
CheckSaveDataState();
isInsEject = InEx_InsCard;
return;
}
#ifdef BKUP_NOTMEM
if (ejectEvntSd.TryWait()){
LogAdd("SD Ejected");//状態表示:抜け
CheckExSaveState();
isInsEject = InEx_EjcSd;
return;
}
if (insEvntSd.TryWait()){
LogAdd("SD Inserted");//状態表示:挿入
CheckExSaveState();
isInsEject = InEx_InsSd;
return;
}
#endif
}
ScrClr();//画面消去
nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(500));//チャタ対策
}
tColStr mess_ReadError = {"[Read] is failed",COLOR_RED};
tColStr mess_WriteError = {"[Write] is failed",COLOR_RED};
tColStr mess_ReadOk = {"[Read] is Success",COLOR_GREEN};
tColStr mess_WriteOk = {"[Write] is Success",COLOR_GREEN};
tColStr mess_PullOut = {"Pull Out",COLOR_RED};
tColStr mess_ChkDev = {"check device",COLOR_RED};
tColStr mess_Insexit = {"Detect Insert or pull out",COLOR_RED};
tColStr mess_WhenExc = {"When you exchange device",COLOR_WHITE};
tColStr mess_PoffSys = {"PowerOff or return Top Menu",COLOR_WHITE};
//---------------------- main loop --------------------------
void nnMain()
{
int i;
myResult mres;
RetCode retc;
tColStr *colstr[4];
colstr[2] = &mess_WhenExc;
colstr[3] = &mess_PoffSys;
isDebugMode = false;
isInsEject = InEx_None;
//NN_LOG("Start\n");
nn::os::Initialize();
nn::fs::Initialize();
//DEA-SUPにて推奨のフリーズ暫定対策無線デーモンを停止 (2011.3.1 現在)
//ただし、スリープ時は止まらない
//心配なら本体スイッチで切っとく
nn::ndm::Initialize();
nn::ndm::SuspendScheduler();
//中断処理の準備
InitSysBreak((uptr)endfunc);
// グラフィックスライブラリの初期化は、以降で行わなければならない
// 他、アプリケーションの初期化処理
nn::applet::DisableSleep();//スリープ非対応
//Heap
appHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR);
const u32 GxHeapSize = 0x800000;
heapForGx = reinterpret_cast<uptr>(appHeap.Allocate(GxHeapSize));
#ifdef BKUP_NOTMEM
IconBuffer = reinterpret_cast<uptr>(appHeap.Allocate(IconBuffSize));
#endif
//画面初期化
if (ScrInitialize(heapForGx,GxHeapSize) == false)failstop();
#ifdef DEBUG_ENABLE
memo.clr();
memo.setbuttom(ScrDbgLogGetMax()-1);//表示行数でリスト数を制限
#endif
ejectEvnt.ClearSignal();
insEvnt.ClearSignal();
nn::fs::RegisterCardEjectedEvent(&ejectEvnt);
nn::fs::RegisterCardInsertedEvent(&insEvnt);
#ifdef BKUP_NOTMEM
ejectEvntSd.ClearSignal();
insEvntSd.ClearSignal();
nn::fs::RegisterSdmcEjectedEvent(&ejectEvntSd);
nn::fs::RegisterSdmcInsertedEvent(&insEvntSd);
ReadIcon(); //アイコンデータの読込
#endif
// スリープ要求に対する返答を有効にする
// また、蓋の状態チェックを行い蓋が閉じられているならスリープ要求が発生する
//nn::applet::EnableSleep(true);
LogAdd("-- start --");
extern u8 scr_evnt;
while(1)
{
tmerr = 0;
CheckSaveDataState(); //セーブデータの状態取得
CheckExSaveState(); //同バックアップ
#ifdef DEBUG_ENABLE
//トップメニュー
if (isDebugMode){
scr_TopMenuDbg(Formatted,Active);
scr_DgbLog(&memo);
while(ScrGetDrawFlag()){
nn::os::Thread::Yield();//表示
}
}else
#endif
if (isAgreePCode==false) tmerr |= SDATA_ERRPUT_PCODE;
// scr_TopMenu(Formatted,Active,exFormatted,exActive,isAgreePCode,failveri);
scr_TopMenu(Formatted,Active,exFormatted,exActive,tmerr);
WaitUI();//入力待ち
if (isInsEject != InEx_None){
ScrClr();//画面消去
isInsEject= InEx_None;
}else
switch(scr_evnt)
{
case EVNT_PUSH_B:
case EVNT_NONE:
break;
case EVNT_PUSH_Y:
#ifdef ENABLE_CRUSH
CrashForDebug++;
CrashForDebug &= 3;
#endif
break;
case EVNT_SEL_READ://リード
NN_LOG("select read\n");
retc = Card2Sd();
switch (retc){
case SUCCESS:
//CheckExSaveState(); //状態の更新
if (isDebugMode){
colstr[1] = &mess_ReadOk;
scr_SuccessQuitDbg(&colstr[1]);//成功とQuitボタン
}else scr_ResultQuit("Success",COLOR_GREEN);//成功とQuitボタン
break;
case INSEXIT:
//scr_InsExitQuit();//挿抜検知表示 & Quit
ScrClr();//画面消去
scr_Backup();
#ifdef DEBUG_ENABLE
if (isDebugMode){
colstr[1] = &mess_PullOut;
scr_ErrorQuitDbg(&colstr[1]);//エラーとQuitボタン
}else
#endif
{
if (isInsEject == InEx_EjcCard)PutError(ERC_DEV_CARD,ERC_DEVICE);
#ifdef BKUP_NOTMEM
else if (isInsEject == InEx_EjcSd)PutError(ERC_DEV_OUT,ERC_DEVICE);
#endif
else PutError(ERC_DEV_OTHER);
scr_ResultQuit("Break",COLOR_RED);//エラーとQuitボタン
}
break;
case CANCEL:
//scr_ResultQuit("Canseled",COLOR_YELLO);//キャンセル
break;
default://errors
#ifdef DEBUG_ENABLE
if (isDebugMode){
colstr[0] = &mess_ReadError;
colstr[1] = &mess_ChkDev;
scr_ErrorQuitDbg(colstr);//エラーとQuitボタン
}else
#endif
scr_ResultQuit("Failed",COLOR_RED);//エラーとQuitボタン
break;
}
if (retc == CANCEL)break;
//isInsEject = InEx_None;
while(1){
WaitUI();
if (isInsEject != InEx_None){
isInsEject = InEx_None;
}
if(scr_evnt==EVNT_QUIT)break;
if(scr_evnt==EVNT_PUSH_B)break;
}
break;
case EVNT_SEL_WRITE://リストア
NN_LOG("select write\n");
retc = Sd2Card();
switch (retc){
case SUCCESS:
//CheckSaveDataState(); //状態の更新
//CheckExSaveState();
if (isDebugMode){
colstr[1] = &mess_WriteOk;
scr_SuccessQuitDbg(&colstr[1]);//成功とQuitボタン
}else scr_ResultQuit("Success",COLOR_GREEN);//成功とQuitボタン
break;
case INSEXIT:
//scr_InsExitQuit();//挿抜検知表示 & Quit
ScrClr();//画面消去
scr_Backup();
#ifdef DEBUG_ENABLE
if (isDebugMode){
colstr[1] = &mess_PullOut;
scr_ErrorQuitDbg(&colstr[1]);//エラーとQuitボタン
}else
#endif
{
if (isInsEject == InEx_EjcCard)PutError(ERC_DEV_CARD,ERC_DEVICE);
#ifdef BKUP_NOTMEM
else if (isInsEject == InEx_EjcSd)PutError(ERC_DEV_OUT,ERC_DEVICE);
#endif
else PutError(ERC_DEV_OTHER);
scr_ResultQuit("Break",COLOR_RED);//エラーとQuitボタン
}
break;
case CANCEL:
//scr_ResultQuit("Canseled",COLOR_YELLO);//キャンセル
break;
default://errors
#ifdef DEBUG_ENABLE
if (isDebugMode){
colstr[0] = &mess_WriteError;
colstr[1] = &mess_ChkDev;
scr_ErrorQuitDbg(colstr);//エラーとQuitボタン
}else
#endif
scr_ResultQuit("Failed",COLOR_RED);//エラーとQuitボタン
break;
}
if (retc == CANCEL)break;
while(1){
WaitUI();
if (isInsEject != InEx_None){
isInsEject= InEx_None;
}
if(scr_evnt==EVNT_QUIT)break;
if(scr_evnt==EVNT_PUSH_B)break;
}
break;
/* case EVNT_SEL_END:
NN_LOG("select end\n");
finish();
break;
case EVNT_NO:
NN_LOG("select NO\n");
break;
case EVNT_YES:
NN_LOG("select NO\n");
break;
*/
case EVNT_PUSH_L:// ----------------------------------------- 表示の切り替え
case EVNT_PUSH_DOWN_Y:// ----------------------------------------- 表示の切り替え
#ifdef DEBUG_ENABLE
isDebugMode = (isDebugMode == false);
#endif
break;
case EVNT_PUSH_LEFT_X:// ------------------------------------- LEFT + X
//バックアップ削除
scr_DelConf();//実行確認
WaitUI();
if (scr_evnt != EVNT_YES)break;
exsave.Delete();
//CheckExSaveState(); //状態更新
break;
case EVNT_PUSH_R:// ------------------------------------------- R
//CARD(NAND)へテストファイル書き込み
//デバグモード時のみ
bool flg;
scr_ConfirmDbg("dummy savedata write OK?");//実行確認
WaitUI();
if (scr_evnt != EVNT_YES)break;
for ( i =0;i<FILEBUFF_SIZE;i++)fileBuffer[i] = (char)i;
//セーブデータのフォーマット&マウント
LogAdd("Format savedata");
arcInfo.FileEntry = 10;
arcInfo.DirEntry = 10;
arcInfo.Dup = false;
mres = savedata.Format(&arcInfo);
if(mres != RESULT_OK)
{
LogAdd("> failed");
LogAdd_Res(savedata.LastNnResult);
LogAdd_Int("%d",mres);
break;
}
i= 2;
LogAdd("create");
while(i){
sprintf(file_path,"dir%d/file%d",i,i);
LogAdd(file_path);
mbstowcs(file_pathw,file_path,510);
if (savedata.OpenC(file_pathw,FILEBUFF_SIZE,&flg)==false)
{
LogAdd("> Open Error");
break;
}
if(savedata.Write(fileBuffer,FILEBUFF_SIZE)!=FILEBUFF_SIZE)
{
LogAdd("> Write failed");
break;
}
savedata.CloseW();
i--;
}
i=2;
while(i){
sprintf(file_path,"dir%d/dir%d/file%d",i,i,i);
LogAdd(file_path);
mbstowcs(file_pathw,file_path,510);
if (savedata.OpenC(file_pathw,FILEBUFF_SIZE,&flg)==false)
{
LogAdd("> Open Error");
break;
}
if(savedata.Write(fileBuffer,FILEBUFF_SIZE)!=FILEBUFF_SIZE)
{
LogAdd("> Write failed");
break;
}
savedata.CloseW();
sprintf(file_path,"dir%d/dir%d/file%d",i,i,i+2);
LogAdd(file_path);
mbstowcs(file_pathw,file_path,510);
if (savedata.OpenC(file_pathw,FILEBUFF_SIZE,&flg)==false)
{
LogAdd("> Open Error");
break;
}
if(savedata.Write(fileBuffer,FILEBUFF_SIZE)!=FILEBUFF_SIZE)
{
LogAdd("> Write failed");
break;
}
savedata.CloseW();
i--;
}
savedata.CloseW();
savedata.Commit();
savedata.Unmount();
//CheckSaveDataState(); //カード状態更新
break;
default:
NN_LOG("menu error\n");
failstop();
break;
}
}//while()
}
/*---------------------------------------------------------------------------*
End of file
*---------------------------------------------------------------------------*/