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

310 lines
9.0 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.

/*
Horizon/tools/SaveDataFiler で読めるファイルを作成
ライトのみアーカイブ使用
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <cstdio>
#include <iomanip>
#include <wchar.h>
#include <string.h>
#include <nn/fs.h>
#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用の情報ファイル
//-------ources\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) {}
//オリジナルはLimitSize不定
};
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(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;
}
//パス名エラーで作成できない場合の格納先
bool Sdmcwo::OpenVnfW(wchar_t *path,s64 size)
{
s32 sz;
tVnf vnf;
//パス名&オフセット用ファイル
wcscpy(expath_w,latestPath_w);
wcscat(expath_w,L"/00000000.vnf");// 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<bit64>(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();
}