ctr_Repair/trunk/CardSaveData/common/savefile/savedata.cpp

312 lines
9.3 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.

#include <wchar.h>
#include <string.h>
#include <nn/fs.h>
#include "savedata.h"
#include <nn/fs/fs_ResultPrivate.h>
#include <nn/fs/CTR/MPCore/fs_ApiForHwCheck.h>
#include <nn/am/am_ApiSystemMenu.h>
#include <nn/am/am_ApiLocalImporter.h>
int dc_readed[MAX_LEVEL];//リード済みエントリ数
const wchar_t *sdataRoot_w = L"data:/";
#define ROOTLENGTH 6
const char *sdataName = "data:";
static bool IsMounted;
wchar_t path_w[MAX_PATH_LENGTH];//パス名
wchar_t pathu_w[MAX_LEVEL][MAX_PATH_LENGTH];//パス名履歴
wchar_t pathw_w[MAX_PATH_LENGTH];//パス名ワーク
//セーブ作成、成功時はマウント状態
myResult SaveData::Format(tArcInfo *pinfo)
{
if ( IsMounted )return RESULT_ALREADY_MOUNT;
LastNnResult = nn::fs::FormatCtrCardSaveData(pinfo->FileEntry,pinfo->DirEntry,pinfo->Dup);
if (LastNnResult.IsFailure())return RESULT_FAIL_FORMAT;
if ( Mount() != RESULT_OK )return RESULT_FAIL_MOUNT;
IsMounted = true;
return RESULT_OK;
}
void SaveData::ResetPath()
{
s_lv=0;
s_serch = false;
wcscpy(path_w,sdataRoot_w);
for (int n = 0;n<MAX_LEVEL;n++)dc_readed[n] = 0;
}
myResult SaveData::GetPath(wchar_t *path)
{
static nn::fs::DirectoryEntry dcEntryl;
static nn::fs::Directory dcl;
int n,ct;
while(1){
LastNnResult = dcl.TryInitialize(path_w);//Open
if (LastNnResult.IsFailure()){
return RESULT_FAIL;
}
if (dc_readed[s_lv] != 0)for(n=0;n<dc_readed[s_lv];n++)dcl.Read(&dcEntryl,1);
n = (dcl.Read(&dcEntryl,1));
dc_readed[s_lv]++;
dcl.Finalize();
if ( n==0 )//終端
{
if (s_lv == 0){path[0]=0;return RESULT_OK;}// ---- rootなら終了
dc_readed[s_lv]=0;
s_lv--;//上の層に戻る
wcscpy(path_w,pathu_w[s_lv]);//パス戻す
}else{
if(dcEntryl.attributes.isDirectory){//ディレクトリ
wcscpy(pathu_w[s_lv],path_w);//パス保存
wcscat(path_w,dcEntryl.entryName);//次のディレクトリパス
wcscat(path_w,L"/");
if (++s_lv == MAX_LEVEL)return RESULT_DIR_LEVEL_OVER;
}else{//ファイル
wcscpy(path,pPathTop);
ct =wcslen(path) + wcslen(dcEntryl.entryName);
if (ct>MAX_PATH_LENGTH - 1)return RESULT_PATH_LENGTH_OVER;
wcscat(path,dcEntryl.entryName);
return RESULT_OK;
}
}
}
}
//アンマウント
void SaveData::Unmount()
{
if(IsMounted){
IsMounted = false;
nn::fs::Unmount(sdataName);
}
}
//バックアップの存在チェック
myResult SaveData::IsExist(){
myResult res;
res = Mount();
Unmount();
return res;
}
//アーカイブ情報の取得
bool SaveData::GetInfo(tArcInfo *pinfo)
{
static nn::fs::DirectoryEntry dcEntryl;
static nn::fs::Directory dcl;
if(IsMounted==false){NN_LOG("GetInfo: Not Mounted\n");return false;};
s_lv=0;
m_info.DirCount = 0;
m_info.FileCount = 0;
m_info.DirEntry = 0;
m_info.FileEntry = 0;
m_info.Dup = false;
wcscpy(path_w,sdataRoot_w);
int n;
int lv = 0;
for (n = 0;n<MAX_LEVEL;n++)dc_readed[n] = 0;
bool cont = true;
while(cont){
LastNnResult = dcl.TryInitialize(path_w);//Open
if (LastNnResult.IsFailure())return false;
if (dc_readed[lv] != 0)for(n=0;n<dc_readed[lv];n++)dcl.Read(&dcEntryl,1);
while(1){
n = (dcl.Read(&dcEntryl,1));
dc_readed[lv]++;
if ( n==0 )//終端
{
if (lv == 0){cont=false;break;}// ---- 終了
dc_readed[lv]=0;
lv--;//上の層に戻る
wcscpy(path_w,pathu_w[lv]);//パス戻す
break;
}else{
if(dcEntryl.attributes.isDirectory){//ディレクトリ
m_info.DirCount++;
wcscpy(pathu_w[lv],path_w);//パス保存
wcscat(path_w,dcEntryl.entryName);//次のディレクトリパス
wcscat(path_w,L"/");
if (++lv == MAX_LEVEL)return false;
break;
}else{//ファイル
m_info.FileCount++;
}
}
}
dcl.Finalize();
}
for (n = 0;n<MAX_LEVEL;n++)dc_readed[n] = 0;
Unmount();//GetCtrCardSaveDataFormatInfo内でマウントするので一旦アンマウント(SDK2.13のみエラー)
LastNnResult = nn::fs::GetCtrCardSaveDataFormatInfo(&m_info.FileEntry,&m_info.DirEntry,&m_info.Dup);
Mount();
*pinfo = m_info;
return true;
}
//プロダクトコード
//結果は PrdCord に格納
bool SaveData::GetPrdCode()
{
PrdCode[0] = 0;//clear
s32 numPrograms;
nn::ProgramId programId;
LastNnResult = nn::am::InitializeForLocalImporter();
if (LastNnResult.IsFailure()){
nn::am::FinalizeForLocalImporter();
return false;
}
LastNnResult = nn::am::GetProgramList(&numPrograms, &programId, 1, nn::fs::MEDIA_TYPE_CTRCARD);
if (LastNnResult.IsFailure()){
nn::am::FinalizeForLocalImporter();
return false;
}
LastNnResult = nn::am::GetProductCode( (nn::ProductCode*)&PrdCode,nn::fs::MEDIA_TYPE_CTRCARD,programId);
nn::am::FinalizeForLocalImporter();
PrdCode[sizeof(nn::ProductCode)] = 0;//表示時のオーバラン対策
return LastNnResult.IsSuccess();
}
//マウント&アーカイブ情報の取得
myResult SaveData::Mount()
{
if (IsMounted)return RESULT_ALREADY_MOUNT;
LastNnResult = nn::fs::MountCtrCardSaveDataForCheck(sdataName);//ApiForHwCheck
IsMounted = LastNnResult.IsSuccess();
if (IsMounted)return RESULT_OK;
if (nn::fs::ResultMediaNotFound().Includes(LastNnResult))return RESULT_NO_MEDIA;
if (nn::fs::ResultFatNotFound().Includes(LastNnResult))return RESULT_NOT_FAUND;//書けるのか?
if (nn::fs::ResultNotFormatted().Includes(LastNnResult))return RESULT_NOT_FORMAT;
if (nn::fs::ResultBadFormat().Includes(LastNnResult))return RESULT_BAD_FORMAT;
if (nn::fs::ResultVerificationFailed().Includes(LastNnResult))return RESULT_SDK_VERIFI;//SDK2.3以前
return RESULT_FAIL;
}
//ファイルリード
s32 SaveData::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 SaveData::Close()
{
reader.Finalize();
}
void SaveData::CloseW()
{
writer.Finalize();
}
//ファイルを開く
//パス指定はルート以降
//(ex)data:/dir/file -> dir/file
bool SaveData::Open(wchar_t *path)
{
wcscpy(pathw_w,sdataRoot_w);
wcscat(pathw_w,path);
LastNnResult = reader.TryInitialize(pathw_w);
if (LastNnResult.IsSuccess())
{
LastNnResult = reader.TryGetSize(&FileSize);
if (LastNnResult.IsSuccess())return true;
else Close();
}
return false;
}
bool SaveData::OpenW(wchar_t *path,s64 size,bool *mkdir)
{
int pos,pos2;
wcscpy(path_w,sdataRoot_w);
wcscat(path_w,path);
*mkdir = false;
LastNnResult = nn::fs::TryCreateFile(path_w,size);
if(LastNnResult.IsSuccess())
{
LastNnResult = writer.TryInitialize(path_w,false);
return LastNnResult.IsSuccess();
}
//ディレクトリがなければディレクトリを作成
pos = GetPosDelmLast(path_w,ROOTLENGTH);//ファイルが存在するディレクトリ
if (pos <= 0)return false;//rootかパスが不正
wcscpy(pathw_w,path_w);//ワークにコピー
while (LastNnResult.IsFailure()){//ディレクトリ作成できるまで遡る
if(LastNnResult.GetDescription()!=nn::fs::DESCRIPTION_DBM_DIRECTORY_NOT_FOUND)return false;
pos2 = GetPosDelmLast(pathw_w,ROOTLENGTH);//境界位置を探す
if (pos2 == 0)return false;//root到達
pathw_w[pos2] = 0;//境界まで削除 (例) dir1/dir2/file -> dir1/dir2 -> dir1
LastNnResult = nn::fs::TryCreateDirectory(pathw_w);
}
//作成ディレクトリ多いと画面止まるので、作成ごとに抜ける
*mkdir = true; // 帰値false で mkdir=true ならディレクトリ作成のみ
return false;
}
//ファイルライト
s32 SaveData::Write(char *buffer,size_t size)
{
s32 ct;
LastNnResult = writer.TryWrite(&ct,(void*)buffer,size);
if(LastNnResult.IsFailure())ct=0;
return ct;
}
//コミット
bool SaveData::Commit()
{
LastNnResult=nn::fs::CommitSaveData(sdataName);
return LastNnResult.IsSuccess();
}
//コンストラクタ
SaveData::SaveData()
{
IsMounted = false;
s_lv=0;
PrdCode[0] = 0;
m_info.DirCount = 0;
m_info.FileCount = 0;
m_info.DirEntry = 0;
m_info.FileEntry = 0;
wcscpy(path_w,sdataRoot_w);
pPathTop = (wchar_t*)((u32)&path_w+strlen(sdataName)*2+2);
}
void SaveData::Finalize()
{
Close();
Unmount();
}
//デストラクタ
SaveData::~SaveData()
{
Finalize();
}