mirror of
https://github.com/rvtr/ctr_Repair.git
synced 2025-10-31 13:51:08 -04:00
300 lines
8.6 KiB
C++
300 lines
8.6 KiB
C++
#include <wchar.h>
|
|
#include <string.h>
|
|
#include <nn/fs.h>
|
|
#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();
|
|
}
|
|
|