#include #include #include #include <../fs/fs_ResultPrivate.h> #include "exsave.h" #define OWN_UID 0xf8014 const char *exsaveName = "exsave:"; const wchar_t *exsaveRoot_w = L"exsave:/save/"; const char *exsaveRoot = "exsave:/save/"; #define ROOTLENGTH_EX 8 const wchar_t *exsaveSys_w = L"exsave:/ncl_sysdata.ncl";//暫定 wchar_t expath_w[PATHLENGTH_MAX];//パス名 wchar_t expathu_w[100][PATHLENGTH_MAX];//上層パス名 wchar_t expathw_w[PATHLENGTH_MAX];//パス名ワーク static nn::fs::DirectoryEntry exdcEntry[MAX_LEVEL]; static nn::fs::Directory exdc[MAX_LEVEL]; //拡張セーブデータ //存在確認 bool ExSave::IsExist() { LastNnResult = nn::fs::MountExtSaveData(exsaveName,OWN_UID); nn::fs::Unmount(exsaveName); return LastNnResult.IsSuccess(); } //パス検索位置のリセット void ExSave::ResetPath() { s_lv=0; s_serch = false; wcscpy(expath_w,exsaveRoot_w); //wcscpy(expathu_w,expath_w); } myResult ExSave::GetPath(wchar_t *path) { int n; while(1){ if (s_serch==false){ LastNnResult = exdc[s_lv].TryInitialize(expath_w);//Open if (LastNnResult.IsFailure()){ return RESULT_FAIL; } } while(1){ n = (exdc[s_lv].Read(&exdcEntry[s_lv],1)); if ( n==0 )//終端 { exdc[s_lv].Finalize(); if (s_lv == 0){path[0]=0;return RESULT_OK;}// ---- rootなら終了 s_lv--;//上の層に戻る wcscpy(expath_w,expathu_w[s_lv]);//パス戻す }else{ if(exdcEntry[s_lv].attributes.isDirectory){//ディレクトリ //m_info.DirCount++; wcscpy(expathu_w[s_lv],expath_w);//パス保存 wcscat(expath_w,exdcEntry[s_lv].entryName);//次のディレクトリパス wcscat(expath_w,L"/"); if (++s_lv == MAX_LEVEL)return RESULT_DIR_LEVEL_OVER; s_serch = false; break; }else{//ファイル //m_info.FileCount++; s_serch = true; wcscpy(path,pPathTop); wcscat(path,exdcEntry[s_lv].entryName); return RESULT_OK; } } } } } //削除 bool ExSave::Delete() { LastNnResult = nn::fs::DeleteExtSaveData(OWN_UID); //if (nn::fs::ResultNotFound().Includes(LastNnResult))return RESULT_NOT_FOUND; return LastNnResult.IsSuccess(); } //セーブ作成、成功時はマウント状態 myResult ExSave::Create(const void* icon,size_t iconSize,u32 entryDir,u32 entryFile) { if ( IsMounted )return RESULT_ALREADY_MOUNT; LastNnResult = nn::fs::CreateExtSaveData(OWN_UID,icon,iconSize,entryDir,entryFile); if (LastNnResult.IsFailure())return RESULT_FAIL_CREATE; LastNnResult = nn::fs::MountExtSaveData(exsaveName,OWN_UID); if (LastNnResult.IsFailure())return RESULT_FAIL_MOUNT; LastNnResult = nn::fs::TryCreateDirectory(exsaveRoot_w); if (LastNnResult.IsFailure()){ nn::fs::Unmount(exsaveName); return RESULT_FAIL_MOUNT; } IsMounted = true; return RESULT_OK; } //マウント myResult ExSave::Mount() { if ( IsMounted )return RESULT_ALREADY_MOUNT; LastNnResult = nn::fs::MountExtSaveData(exsaveName,OWN_UID); if (LastNnResult.IsFailure()){ return RESULT_FAIL_MOUNT; } IsMounted = true; return RESULT_OK; } void ExSave::Unmount() { IsMounted = false; nn::fs::Unmount(exsaveName); } //ライト属性ファイルを閉じる void ExSave::CloseW() { writer.Finalize(); } //ファイルライト s32 ExSave::Write(char *buffer,size_t size) { s32 ct; LastNnResult = writer.TryWrite(&ct,(void*)buffer,size); if(LastNnResult.IsFailure())ct=0; return ct; } //管理用ファイル //ライト属性で開く bool ExSave::OpenSysW() { LastNnResult = nn::fs::TryCreateFile(exsaveSys_w,sizeof(tArcInfo)); LastNnResult = writerSys.TryInitialize(exsaveSys_w,false); return LastNnResult.IsSuccess(); } //ライト属性ファイルを閉じる void ExSave::CloseSysW() { writerSys.Finalize(); } //システムファイルライト bool ExSave::WriteSys(tArcInfo *pinfo) { s32 ct; pinfo->Ver = INFO_VERSION; LastNnResult = writerSys.TryWrite(&ct,(void*)pinfo,sizeof(tArcInfo)); return LastNnResult.IsSuccess(); } //リード属性で開く bool ExSave::OpenSysR() { LastNnResult = readerSys.TryInitialize(exsaveSys_w); return LastNnResult.IsSuccess(); } //ライト属性ファイルを閉じる void ExSave::CloseSysR() { readerSys.Finalize(); } //ファイルリード bool ExSave::ReadSys(tArcInfo *pinfo) { s32 ct; LastNnResult = readerSys.TryRead(&ct,(void*)pinfo,sizeof(tArcInfo)); return LastNnResult.IsSuccess(); } //ライト属性ファイルを開く bool ExSave::OpenW(wchar_t *path,s64 size) { int pos,pos2; wcscpy(expath_w,exsaveRoot_w); wcscat(expath_w,path); while(1){ LastNnResult = nn::fs::TryCreateFile(expath_w,size); if(LastNnResult.IsSuccess())break; //ディレクトリがなければディレクトリを作成 pos = GetPosDelmLast(expath_w,ROOTLENGTH_EX);//ファイルが存在するディレクトリ if (pos <= 0)return false;//rootかパスが不正 //while (1){ wcscpy(expathw_w,expath_w);//ワークにコピー while (LastNnResult.IsFailure()){//ディレクトリ作成できるまで遡る if(LastNnResult.GetDescription()!=nn::fs::DESCRIPTION_DBM_DIRECTORY_NOT_FOUND)return false; pos2 = GetPosDelmLast(expathw_w,ROOTLENGTH_EX);//境界位置を探す if (pos2 == 0)return false;//root到達 expathw_w[pos2] = 0;//境界まで削除 (例) dir1/dir2/file -> dir1/dir2 -> dir1 LastNnResult = nn::fs::TryCreateDirectory(expathw_w); } //if (pos2 == pos)break;//配置ディレクトリなら抜ける //todo:ディレクトリが深いとき時間がかかるなら、無駄なTryCreateを省く //案)直上から最初の成功までのデリミタ位置を記録 //先に全ディレクトリ作っておくのがよさげ //} } LastNnResult = writer.TryInitialize(expath_w,false); return LastNnResult.IsSuccess(); } //ファイルリード s32 ExSave::Read(char *buffer,size_t size) { // if (IsMounted==false)return 0; s32 ct; LastNnResult = reader.TryRead(&ct,(void*)buffer,size); if(LastNnResult.IsFailure())ct=0; return ct; } void ExSave::Close() { reader.Finalize(); } //ファイルを開く //パス指定はルート以降 //(ex)data:/dir/file -> dir/file bool ExSave::Open(wchar_t *path) { wcscpy(expathw_w,exsaveRoot_w); wcscat(expathw_w,path); LastNnResult = reader.TryInitialize(expathw_w); if (LastNnResult.IsSuccess()) { LastNnResult = reader.TryGetSize(&FileSize); if (LastNnResult.IsSuccess())return true; else Close(); } return false; } //アーカイブ情報の取得 bool ExSave::GetInfo(tArcInfo *pinfo) { if(Mount()==RESULT_FAIL_MOUNT)return false; //システムデータからフォーマット情報 if (OpenSysR()) { if(ReadSys(pinfo) == false){ pinfo->Pcode[0]=0; CloseSysR();//クローズ Unmount(); return false; } }else{ Unmount(); return false; } CloseSysR();//クローズ // Unmount(); //#ifdef INFO_API_USE //API情報と比較 // LastNnResult = nn::fs::GetExtSaveDataFormatInfo(OWN_UID,&m_info.FileEntry,&m_info.DirEntry); // if (m_info.FileEntry != pinfo->FileEntry)return false; // if (m_info.DirEntry != pinfo->DirEntry)return false; // //if (m_info.Dup != pinfo->Dup)return false; //ExSaveには無い //#endif return true; } //コンストラクタ ExSave::ExSave() { IsMounted = false; s_lv=0; m_info.DirCount = 0; m_info.FileCount = 0; m_info.DirEntry = 0; m_info.FileEntry = 0; wcscpy(expath_w,exsaveRoot_w); //wcscpy(expathu_w,expath_w); pPathTop = (wchar_t*)((u32)&expath_w+strlen(exsaveRoot)*2); } void ExSave::Finalize() { Close(); Unmount(); } //デストラクタ ExSave::~ExSave() { Finalize(); }