diff --git a/trunk/CardSaveData/ToSD/body/OMakefile b/trunk/CardSaveData/ToSD/body/OMakefile index dfe1e96..e219081 100644 --- a/trunk/CardSaveData/ToSD/body/OMakefile +++ b/trunk/CardSaveData/ToSD/body/OMakefile @@ -29,7 +29,7 @@ SOURCES[] = ./source/main.cpp ./source/screen/screen.cpp ../../common/savefile/savedata.cpp - ../../common/savefile/sdmc.cpp + ../../common/savefile/sdmcwo.cpp ../../common/savefile/savefile.cpp ../../common/gui/gui.cpp ../../common/shfnt.cpp diff --git a/trunk/CardSaveData/ToSD/body/source/main.cpp b/trunk/CardSaveData/ToSD/body/source/main.cpp index 3395e80..70923f7 100644 --- a/trunk/CardSaveData/ToSD/body/source/main.cpp +++ b/trunk/CardSaveData/ToSD/body/source/main.cpp @@ -25,7 +25,7 @@ #include #include "../../../common/savefile/savefile.h" #include "../../../common/savefile/savedata.h" -#include "../../../common/savefile/sdmc.h" +#include "../../../common/savefile/sdmcwo.h" #include "../../../common/common.h" #include "./screen/screen.h" @@ -38,7 +38,7 @@ myResult errRes; SaveData savedata; nn::os::LightEvent ejectEvnt(false); nn::os::LightEvent insEvnt(false); -Sdmc exsave; +Sdmcwo exsave; nn::os::LightEvent ejectEvntSd(false); nn::os::LightEvent insEvntSd(false); @@ -178,113 +178,6 @@ bool TryDeleteDir() return true; } -//------------------------------------------------------------- Verifi -bool Verifi() -{ - myResult res; - int ct=0,msize,rsize,i; - s64 total=0; - - - if (arcInfo.FileCount == 0)return true;//ファイル無し - - //セーブデータのマウント - scr_Status("Mount SaveData",COLOR_YELLO); - res = savedata.Mount(); - if(res != RESULT_OK)return false; - scr_Status("Mount SD",COLOR_YELLO); - res = exsave.Mount(); - if(res != RESULT_OK)return false; - - scr_Status("file compairing",COLOR_YELLO); - savedata.ResetPath(); - s64 fsize; - res = RESULT_OK; - while(res==RESULT_OK){ - if(CheckInsExit())break;//挿抜による中断 - res = savedata.GetPath(file_pathw);//パス取得 - if (res != RESULT_OK)break; - if (file_pathw[0] == 0)break;//root then end - if (ct>=arcInfo.FileCount) - { - res = RESULT_FAIL; - break; - } - if(CheckInsExit())break;//挿抜による中断 - scr_CountPerMax(ct,arcInfo.FileCount);//カウンタ表示 - if (savedata.Open(file_pathw)==false)//カード上のファイル - { - res = RESULT_FAIL_OPEN; - break; - } - fsize = savedata.FileSize; - total += fsize; - if(CheckInsExit())break;//挿抜による中断 - if (exsave.Open(file_pathw)==false)//SDのファイル - { - if (exsave.OpenVnf(file_pathw)==false)//退避ファイルを探す - { - res = RESULT_FAIL_OPEN; - break; - } - } - msize=fsize; - while(fsize) - { - if(msize > FILEBUFF_SIZE * 2){//サイズが大きい場合にゲージ表示 - scr_CountPerMax2(msize-fsize,msize,0); - } - if (fsize>FILEBUFF_SIZE) - { - rsize = FILEBUFF_SIZE; - fsize -= FILEBUFF_SIZE; - }else{ - rsize = fsize; - fsize = 0; - } - if(CheckInsExit())break;//挿抜による中断 - if(savedata.Read(fileBuffer,rsize) != rsize )//カード - { //中身のデータが作成サイズに満たない場合 - //不明部分の処置は書出し時と合わせる - if(nn::fs::ResultVerificationFailed::Includes(savedata.LastNnResult)) - { - for ( i = 0; i < rsize; i++) - { - fileBuffer[i] = 0;//0埋め - } - }else{ - res = RESULT_FAIL_READ; - break; - } - } - if(CheckInsExit())break;//挿抜による中断 - if(exsave.Read(fileBuffer_ex,rsize) != rsize )//SD - { - res = RESULT_FAIL_READ; - break; - } - } - savedata.Close(); - exsave.Close(); - if (res != RESULT_OK)break; - if(isInsEject != InEx_None )break;//挿抜による中断 - //比較 - for (i=0;i=arcInfo.FileCount) { res = RESULT_FAIL; @@ -384,8 +277,8 @@ RetCode Card2Sd() while(1){ if (exsave.OpenW(file_pathw,fsize,&mkdir)==false) { - if(mkdir)//ディレクトリのみ作成 - {//深い場合に作成が多いと画面が止まるので + if(mkdir)//ディレクトリ作成のみ + {//深いと作成に時間かかるので画面に変化つける rev++; if (rev & 1)scr_MessOnCount2("Create Directry -"); else scr_MessOnCount2("Create Directry |"); @@ -396,8 +289,8 @@ RetCode Card2Sd() if (exsave.OpenVnfW(file_pathw,fsize)==false)//退避ファイル { res = RESULT_FAIL_OPENW; - break; } + break; }else{ res = RESULT_FAIL_OPENW; break; @@ -423,7 +316,7 @@ RetCode Card2Sd() fsize = 0; } if(CheckInsExit())break;//挿抜による中断 - if(savedata.Read(fileBuffer,rsize) != rsize ) + if(savedata.Read(fileBuffer,rsize) != rsize )//リード { //中身のデータが作成サイズに満たない場合に検証エラーとなる対策 //読めないブロックは置き換える @@ -441,7 +334,7 @@ RetCode Card2Sd() } } if(CheckInsExit())break;//挿抜による中断 - if(exsave.Write(fileBuffer,rsize) != rsize ) + if(exsave.Write(fileBuffer,rsize) != rsize )//ライト { res = RESULT_FAIL_WRITE; break; @@ -455,7 +348,6 @@ RetCode Card2Sd() savedata.Close(); exsave.CloseW(); } - savedata.Unmount(); exsave.Unmount(); @@ -467,57 +359,39 @@ RetCode Card2Sd() }else{ if (res == RESULT_OK) { - if (ct != arcInfo.FileCount)//ファイル数に満たないパス検索終了 - {//ディレクトリ情報かパス取得で失敗してると思われる - PutError(ERC_DEV_OTHER,ERC_EXEC); - return ERROR; - } + if (ct == arcInfo.FileCount)//ファイル数一致? + { + if(exsave.WriteSys(&arcInfo))//フォーマット情報 + { + //成功 + strcpy(sts,"output folder [ "); + strcat(sts,exsave.DirName);//保存先 + strcat(sts," ]"); + scr_Status(sts,COLOR_WHITE); - if(Verifi())//ベリファイ - { - if (exsave.WriteSys(&arcInfo)) - {//最後に書き戻しに必要なパラメータファイルを記録 - if(CheckInsExit()==false) - { - if (exsave.GetInfo(&arcInfo_ex)) - { //リードチェック - if ((arcInfo.DirEntry != arcInfo_ex.DirEntry) || - (arcInfo.FileEntry != arcInfo_ex.FileEntry) || - (arcInfo.DirCount != arcInfo_ex.DirCount) || - (arcInfo.FileCount != arcInfo_ex.FileCount) || - (arcInfo.Dup != arcInfo_ex.Dup))res = RESULT_FAIL_WRITE; - } - }else res = RESULT_FAIL; - }else res = RESULT_FAIL_WRITE; - }else res = RESULT_FAIL_VERIFI; - } - if (res != RESULT_OK) - { - if (TryDeleteDir()) - { - if ((res == RESULT_FAIL_WRITE) || (res== RESULT_FAIL_OPENW)) PutError(ERC_DEV_OUT); - else if ((res == RESULT_FAIL_READ) || (res== RESULT_FAIL_OPEN)) PutError(ERC_DEV_CARD); - else if (res == RESULT_FAIL_VERIFI) PutError(ERC_DEV_OUT,ERC_VERIFI); - else PutError(ERC_DEV_OTHER); + scr_CountPerMax(ct,arcInfo.FileCount);//ファイル数 + scr_CountPerMax2(0,0,total);//総サイズ + return SUCCESS; + } + }else{ + NN_LOG("file count error\n"); + res = RESULT_FAIL; } - }else - { - strcpy(sts,"output folder [ "); - strcat(sts,exsave.DirName);//保存先 - strcat(sts," ]"); - scr_Status(sts,COLOR_WHITE); - - scr_CountPerMax(ct,arcInfo.FileCount);//ファイル数 - scr_CountPerMax2(0,0,total);//総サイズ - return SUCCESS; - } + //失敗 + if (TryDeleteDir())//ディレクトリごと削除 + { + if ((res == RESULT_FAIL_WRITE) || (res== RESULT_FAIL_OPENW)) PutError(ERC_DEV_OUT); + else if ((res == RESULT_FAIL_READ) || (res== RESULT_FAIL_OPEN)) PutError(ERC_DEV_CARD); + else if (res == RESULT_FAIL_VERIFI) PutError(ERC_DEV_OUT,ERC_VERIFI); + else PutError(ERC_DEV_OTHER); + } + } return ERROR; } -bool mkdir; //--------------------------------------------------------------- セーブデータの情報取得 //呼ぶ前に tmerr のクリアを忘れない事 diff --git a/trunk/CardSaveData/common/savefile/savefile.h b/trunk/CardSaveData/common/savefile/savefile.h index 4548eab..4fc0a80 100644 --- a/trunk/CardSaveData/common/savefile/savefile.h +++ b/trunk/CardSaveData/common/savefile/savefile.h @@ -19,7 +19,8 @@ int GetPosDelmLast(wchar_t *s,int top); //t@C̃o[W #define INFO_VERSION 1 -//SDobNAbvɓ +//tH[}bg +//SDobNAbv̏ꍇ͓ //ύX̍ۂ͌݊Ƃ悤lĵ݂Ƃ struct tArcInfo{ u32 DirEntry,FileEntry; diff --git a/trunk/CardSaveData/common/savefile/sdmcwo.cpp b/trunk/CardSaveData/common/savefile/sdmcwo.cpp new file mode 100644 index 0000000..d7698e5 --- /dev/null +++ b/trunk/CardSaveData/common/savefile/sdmcwo.cpp @@ -0,0 +1,307 @@ +/* + + Horizon/tools/SaveDataFiler で読めるファイルを作成 + + ライトのみアーカイブ使用 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sdmcwo.h" + +const char *devName = "sdmcwo:"; +const wchar_t *devName_w = L"sdmcwo:"; +#define PATHLENGTH_MAX_SD 512 + +wchar_t sdmcRoot_w[MAX_PATH_LENGTH];//filer/UserSaveData/YearMtDtHrMtSc/00000000 +#define ROOTLENGTH_SD 51 +wchar_t expath_w[MAX_PATH_LENGTH];//パス名 +wchar_t expathw_w[MAX_PATH_LENGTH];//パス名ワーク +wchar_t latestPath_w[MAX_PATH_LENGTH];//filer/UserSaveData/YearMtDtHrMtSc +bool created; +bool IsMounted; + +//SDKツールのSaveFilerのフォーマットに合わせる +//------------ sources\tools\NandFiler\nandf_Dialog.h 参照 +const wchar_t *SDMC_ROOT_DIR_NAME = L"/filer"; + +struct FormatParameters +{ + size_t m_LimitSize; + size_t m_MaxDir; + size_t m_MaxFile; + s32 m_IconSize; + bit8 *m_pIconData; + bool m_Duplicate; + + FormatParameters() + : m_LimitSize(0),m_IconSize(0), m_pIconData(0) {} + //オリジナルはLinitSize不定 +}; + +struct AdditionalInfo +{ + bit64 m_Version; + bit64 m_Id; + bit64 m_Reserved[128];//オリジナルは乱数埋 + AdditionalInfo() + : m_Version(0), m_Id(0) {} +}; +//--------------------------- nandf_util.cpp 参照 +std::wstring Sdmcwo::GetDateName() +{ + nn::fnd::DateTime tm = nn::fnd::DateTime::GetNow(); + + std::wostringstream name; + name << std::setw(4) << std::setfill(L'0') << tm.GetYear() + << std::setw(2) << std::setfill(L'0') << tm.GetMonth() + << std::setw(2) << std::setfill(L'0') << tm.GetDay() + << std::setw(2) << std::setfill(L'0') << tm.GetHour() + << std::setw(2) << std::setfill(L'0') << tm.GetMinute() + << std::setw(2) << std::setfill(L'0') << tm.GetSecond(); + + + //char型 :表示で使う + wcstombs(DirName, name.str().c_str(), 14); + DirName[14] = 0; + return name.str(); +} + + +bit64 ChangeId(bit64 id, bit64 key) +{ + return id ^ key ^ 0xce8a4d52f7105339; +} + +//----------------------------- + +//ディレクトリ作成 +//ディレクトリオープンも出来ないので、ライト試行 +bool CreateDir(const wchar_t *dirName) +{ + nn::Result result = nn::fs::TryCreateDirectory(dirName); + if(result.IsSuccess())return true; + return nn::fs::ResultAlreadyExists::Includes(result); +} + + +//SDMCにライト専用アーカイブ +//ディレクトリもファイルも読めない + +//直前のCreateで作成したDateTimeフォルダ削除 +bool Sdmcwo::Delete() +{ + if (created==false)return true; + if (Mount() == RESULT_FAIL_MOUNT)return false; + LastNnResult = nn::fs::TryDeleteDirectoryRecursively(latestPath_w); + Unmount(); + return LastNnResult.IsSuccess(); +} + +//全削除 +bool Sdmcwo::DeleteAll() +{ + if (Mount() == RESULT_FAIL_MOUNT)return false; + std::wostringstream woss; + woss << devName << SDMC_ROOT_DIR_NAME;//sdmc:/filer + LastNnResult = nn::fs::TryDeleteDirectoryRecursively(woss.str().c_str()); + Unmount(); + return LastNnResult.IsSuccess(); +} + + +//保存先のディレクトリ作成 +//成功時はマウント状態 +bool Sdmcwo::Create() +{ + std::wostringstream woss; + created = false; + if (Mount() == RESULT_FAIL_MOUNT)return false; + + woss << devName << SDMC_ROOT_DIR_NAME;//sdmc:/filer + if (CreateDir(woss.str().c_str())) + { + woss << L"/" << L"UserSaveData";//sdmc:/filer/UserSaveData + if ( CreateDir(woss.str().c_str()) ) + { + DateDirName = GetDateName(); + woss << L"/" << DateDirName;//sdmc:/filer/UserSaveData/YearMtDtHrMtSc + if ( CreateDir(woss.str().c_str()) ) + { + wcscpy(latestPath_w,woss.str().c_str()); + created = true;//日時ディレクトリ作成フラグ + //コピー先ルート + woss << L"/" << "00000000";//sdmc:/filer/UserSaveData/YearMtDtHrMtSc/00000000 + if ( CreateDir(woss.str().c_str()) ) + { + woss << L"/";//sdmc:/filer/UserSaveData/YearMtDtHrMtSc/00000000/ + wcscpy(sdmcRoot_w,woss.str().c_str());//格納先パス保存 + return true; + } + } + } + } + Unmount(); + return false; +} + +//格納先パスの取得 +//先にCreateしとくこと +void Sdmcwo::GetRootPath(wchar_t *path) +{ + wcscpy(path,sdmcRoot_w); +} + + +//マウント +myResult Sdmcwo::Mount() +{ + if ( IsMounted )return RESULT_ALREADY_MOUNT; + LastNnResult = nn::fs::MountSdmcWriteOnly(devName); + if (LastNnResult.IsFailure()){ + return RESULT_FAIL_MOUNT; + } + IsMounted = true; + return RESULT_OK; +} +void Sdmcwo::Unmount() +{ + IsMounted = false; + nn::fs::Unmount(devName); +} +//ライト属性ファイルを閉じる +void Sdmcwo::CloseW() +{ + writer.Finalize(); +} + +//ファイルライト +s32 Sdmcwo::Write(char *buffer,size_t size) +{ + s32 ct; + LastNnResult = writer.TryWrite(&ct,(void*)buffer,size); + if(LastNnResult.IsFailure())ct=0; + return ct; +} + +//ライトでオープン +bool Sdmcwo::OpenW(wchar_t *path,s64 size,bool *mkdir) +{ + int pos,pos2; + + wcscpy(expath_w,sdmcRoot_w); + wcscat(expath_w,path); + *mkdir = false; + LastNnResult = nn::fs::TryCreateFile(expath_w,size); + if(LastNnResult.IsSuccess()) + { + LastNnResult = writer.TryInitialize(expath_w,false); + return LastNnResult.IsSuccess(); + } + //ディレクトリがなければディレクトリを作成 + pos = GetPosDelmLast(expath_w,ROOTLENGTH_SD);//ファイルが存在するディレクトリ + if (pos <= 0)return false;//rootかパスが不正 + wcscpy(expathw_w,expath_w);//ワークにコピー + while (LastNnResult.IsFailure()){//ディレクトリ作成できるまで遡る + //if(LastNnResult.GetDescription()!=nn::fs::DESCRIPTION_DBM_DIRECTORY_NOT_FOUND)return false; + if(nn::fs::ResultNotFound::Includes(LastNnResult)==false)return false; + pos2 = GetPosDelmLast(expathw_w,ROOTLENGTH_SD);//境界位置を探す + if (pos2 == 0)return false;//root到達 + expathw_w[pos2] = 0;//境界まで削除 (例) dir1/dir2/file -> dir1/dir2 -> dir1 + LastNnResult = nn::fs::TryCreateDirectory(expathw_w); + } + //作成ディレクトリ多いと画面止まるので、作成ごとに抜ける + *mkdir = true; // 帰値:false で mkdir=true ならディレクトリ作成のみ + return false; +} + + +//パス名エラーで作成できない場合の退避先 +//例:FAT規約違反、"/ test"->"/test"、SD格納先ディレクトリでパス長オーバー +bool Sdmcwo::OpenVnfW(wchar_t *path,s64 size) +{ + s32 sz; + tVnf vnf; + //パス名&オフセット用ファイル + wcscpy(expath_w,latestPath_w); + wcscat(expath_w,L"/00000000.vnf"); + LastNnResult = writer.TryInitialize(expath_w,false); + if (LastNnResult.IsSuccess()){ + LastNnResult = writer.TrySeek(0,nn::fs::POSITION_BASE_END);//追記 + }else LastNnResult = writer.TryInitialize(expath_w,true);//新規 + if (LastNnResult.IsSuccess()) + { + wcscpy(vnf.path,path); + vnf.size = size; + LastNnResult = writer.TryWrite(&sz,&vnf,sizeof(tVnf));//ヘッダ格納 + } + if (LastNnResult.IsFailure()) + { + writer.Finalize(); + return false; + } + return true; + +} + + + +//情報ファイル +// +bool Sdmcwo::WriteSys(tArcInfo *ifo) +{//SaveFilerで読むためのファイル + std::wostringstream woss; + if (Mount() == RESULT_FAIL_MOUNT)return false; + woss << latestPath_w << L"/00000000"; + // FormatParameter を保存 + LastNnResult = writer.TryInitialize( (woss.str() + L".dat").c_str(), true); + if (LastNnResult.IsFailure()){Unmount();return false;} + s32 size; + FormatParameters Fparam; + Fparam.m_MaxDir = ifo->DirEntry; + Fparam.m_MaxFile = ifo->FileEntry; + Fparam.m_Duplicate = ifo->Dup; + LastNnResult = writer.TryWrite(&size, &Fparam, sizeof(FormatParameters)); + if (LastNnResult.IsFailure()){Unmount();return false;} + LastNnResult = writer.TryFlush(); + if (LastNnResult.IsFailure()){Unmount();return false;} + writer.Finalize(); + //AdditionalInfoを保存 + AdditionalInfo Ainfo; + LastNnResult = writer.TryInitialize((woss.str() + L"_.dat").c_str(), true); + if (LastNnResult.IsFailure()){ Unmount();return false;} + Ainfo.m_Version = 0; + Ainfo.m_Id = ChangeId(Ainfo.m_Id, static_cast(std::wcstoll(DateDirName.c_str(), NULL, 10))); + LastNnResult = writer.TryWrite(&size, &Ainfo, sizeof(AdditionalInfo)); + if (LastNnResult.IsFailure()){ Unmount();return false;} + LastNnResult = writer.TryFlush(); + if (LastNnResult.IsFailure()){ Unmount();return false;} + writer.Finalize(); + + + return true; +} + +//コンストラクタ +Sdmcwo::Sdmcwo() +{ + IsMounted = false; +} + +void Sdmcwo::Finalize() +{ + CloseW(); + Unmount(); +} +//デストラクタ +Sdmcwo::~Sdmcwo() +{ + Finalize(); +} + diff --git a/trunk/CardSaveData/common/savefile/sdmcwo.h b/trunk/CardSaveData/common/savefile/sdmcwo.h new file mode 100644 index 0000000..a6fe321 --- /dev/null +++ b/trunk/CardSaveData/common/savefile/sdmcwo.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + + Copyright (C)2009 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. + + *---------------------------------------------------------------------------*/ + +//ライトのみアーカイブ使用 + +#ifndef sdmcwo_H_ +#define sdmcwo_H_ + +#include +#include +#include +#include "../my_defs.h" +#include "savefile.h" + +class Sdmcwo +{ +public: + s64 FileSize; + nn::Result LastNnResult; + char DirName[16]; +private: + tArcInfo m_info; + std::wstring GetDateName(); + std::wstring DateDirName; + nn::fs::FileWriter writer; +public: + Sdmcwo(); + ~Sdmcwo(); + void Finalize(); + bool Create(); + myResult Mount(); + void Unmount(); + bool Delete(); + bool DeleteAll(); + void CloseW(); + bool OpenW(wchar_t *path,s64 size,bool *mkdir); + bool OpenVnfW(wchar_t *path,s64 size); + void GetRootPath(wchar_t *path); + s32 Write(char *buffer,size_t size); + bool WriteSys(tArcInfo *ifo); +}; + +//Fat違反パス格納データのヘッダ +//直後にデータ配置 +//Header+Data,、Header+Data ... と連続して追記してゆく +typedef struct{ + wchar_t path[MAX_PATH_LENGTH]; + s64 size; +}tVnf; + +#endif diff --git a/trunk/CardSaveData/common/test_data.cpp b/trunk/CardSaveData/common/test_data.cpp index 270c3d9..fd73e36 100644 --- a/trunk/CardSaveData/common/test_data.cpp +++ b/trunk/CardSaveData/common/test_data.cpp @@ -971,7 +971,7 @@ bool Test6_V() strcat(fname,"_.bin");//data:/base_/base_.bin i =0; - while(kinsi[i] != '/')//末尾スラッシュは名無しでエラー + while(kinsi[i] != 0)//末尾スラッシュは名無しでエラー { c = kinsi[i]; fname[pos] = c;