git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_Repair@254 385bec56-5757-e545-9c3a-d8741f4650f1

This commit is contained in:
mizu 2011-05-12 07:57:37 +00:00
parent 5adc064478
commit da83077290
6 changed files with 406 additions and 163 deletions

View File

@ -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

View File

@ -25,7 +25,7 @@
#include <nn/fs/fs_Parameters.h>
#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<rsize;i++)if (fileBuffer[i]!=fileBuffer_ex[i]){
res = RESULT_FAIL;
break;
}
ct++;
}
savedata.Close();
exsave.Close();
savedata.Unmount();
exsave.Unmount();
return res == RESULT_OK;
}
//---------------------------------------------------------------------- CARD to SD
RetCode Card2Sd()
{
@ -336,7 +229,7 @@ RetCode Card2Sd()
res = RESULT_OK;
while(res==RESULT_OK){
if(CheckInsExit())break;//挿抜による中断
res = savedata.GetPath(file_pathw);
res = savedata.GetPath(file_pathw);//パス取得
if (res != RESULT_OK)
{
if (res == RESULT_DIR_LEVEL_OVER){
@ -350,7 +243,7 @@ RetCode Card2Sd()
res = RESULT_FAIL_OPEN;
break;
}
if (file_pathw[0] == 0)break;//root then end
if (file_pathw[0] == 0)break;//ルートなら終了
if (ct>=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 のクリアを忘れない事

View File

@ -19,7 +19,8 @@ int GetPosDelmLast(wchar_t *s,int top);
//情報ファイルのバージョン
#define INFO_VERSION 1
//SDバックアップに同梱する情報
//フォーマット情報
//SDバックアップの場合は同梱する
//変更の際は後方互換とれるよう追加のみとする
struct tArcInfo{
u32 DirEntry,FileEntry;

View File

@ -0,0 +1,307 @@
/*
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のフォーマットに合わせる
//------------ 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<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();
}

View File

@ -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 <sstream>
#include <nn/types.h>
#include <nn/Result.h>
#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

View File

@ -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;