ctr_Repair/trunk/CardSaveData/Mover/body/source/main.cpp

1923 lines
59 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.

/*---------------------------------------------------------------------------*
Project: Horizon
File: main.cpp
Copyright (C)2010 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.
*---------------------------------------------------------------------------*/
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <nn.h>
//#include <nn/os.h>
#include <nn/applet.h>
#include <nn/ndm.h>
#include <nn/cfg.h>
//#include <nn/ndm/ndm_DebugControl.h>
#include <nn/ndm/ndm_UserControl.h>
#include <nn/fs/ctr/mpcore/fs_FileSystemBasePrivate.h>
#include <nn/fs/fs_Parameters.h>
//#include <nn/fs/fs_ApiProcessInfo.h>
#include "../../../common/savefile/savefile.h"
#include "../../../common/savefile/savedata.h"
#include "../../../common/savefile/membak.h"
#include "./screen/screen.h"
#include "../../../common/common.h"
//ヘッダにフラグのみ、コメントアウトで旧版相当(SD非対応)
#include "main.h"
#ifdef CSM_FLAG_USE_SD
#include "../../../common/savefile/exsave.h"
#endif
nn::fnd::ExpHeap appHeap;
uptr heapForGx;
//Gui gui;
myResult errRes;
//char strBuff[128];
//bool exist;
SaveData savedata;
nn::os::LightEvent ejectEvnt(false);
nn::os::LightEvent insEvnt(false);
#ifdef CSM_FLAG_USE_SD
ExSave exsave;
nn::os::LightEvent ejectEvntSd(false);
nn::os::LightEvent insEvntSd(false);
bool BkupSd = false;//バックアップ先がSDか(ファイルサイズ合計で選択)
#endif
MemBak memsave;
//バックアップの状態
bool Active,Formatted;
bool exActive,exFormatted;
tArcInfo arcInfo,arcInfo2;//アーカイブ情報
tDcList dcList,dcList2;//ディレクトリ格納
//プロダクトコードの一致
bool isAgreePCode;
//SDあり起動
bool alive_Sd;
//Top画面エラー表示
int tmerr;
//結果
typedef enum {
SUCCESS
,ERROR
,CANCEL
,INSEXIT
}RetCode;
//挿抜イベント時に設定
typedef enum {
InEx_None
,InEx_InsCard
,InEx_EjcCard
,InEx_InsSd
,InEx_EjcSd
}tIsInsEject;
//メッセージ用タグ
enum eMesTag{
MT_Compair,//コンペア時
MT_ChkCard,//ユーザセーブの存在チェック時
MT_ChkBkup,//バックアップ先の存在チェック時
MT_CrtBkup,//保存先の作成
MT_FileNot,//ユーザセーブのマウント成功したがファイルが無い
MT_Reading,//リード中
MT_Complate,//終了
MT_CardFormat,//ユーザセーブのフォーマット時
MT_FormatOnly,//フォーマットのみ行ったとき(ファイルなし時)
MT_Writing,//ライト中
MT_CrtDir1,//ディレクトリ作成中その1
MT_CrtDir2,//その2(1,2を交互表示)
MT_Copy1,// ファイルコピー
MT_Copy2,//ファイルコピー
MT_Failed,//失敗
MT_Break,//中断
MT_Success,//成功
MT_END
};
tChar* MES_NULL = L"";
//文字数(終端込)
#define MESS_SIZE 32
//メッセージ格納
wchar_t Mess[MT_END*MESS_SIZE];
//メッセージ位置
int MessPos[MT_END];
#define MessTxt(i) (wchar_t*)&Mess[MessPos[i]]
tIsInsEject isInsEject;
extern u8 scr_evnt;
s64 sSize;
wchar_t wk_dir[20];//拡張セーブ上のリネームファイル用ディレクトリ
int rename_n =0;//リネーム番号
wchar_t file_pathw[MAX_PATH_LENGTH];
wchar_t file_pathw2[MAX_PATH_LENGTH];
char file_path[MAX_PATH_LENGTH];
//ドライバの仕様で速度的に4バイトアラインした方がいい(SDK 0.14.23 時点)
char fileBuffer[512] NN_ATTRIBUTE_ALIGN(4);//検証が512単位なので
char fileBuffer_ex[512] NN_ATTRIBUTE_ALIGN(4);
#define FILEBUFF_SIZE sizeof(fileBuffer)
void WaitUI();
void PutError(TgtDev dev,int cd=0);
RetCode Card2Sd();
RetCode Sd2Card();
void CheckSaveDataState();
void CheckExSaveState();
//------------------------------------------------------------ 挿抜チェック
bool CheckInsExit()
{
if (ejectEvnt.TryWait()){
//CARD抜け
CheckSaveDataState();
isInsEject = InEx_EjcCard;
return true;
}
if (insEvnt.TryWait()){
//CARD挿入
CheckSaveDataState();
isInsEject = InEx_InsCard;
return true;
}
#ifdef CSM_FLAG_USE_SD
if(alive_Sd){
if (ejectEvntSd.TryWait()){
//SD抜け
CheckExSaveState();
isInsEject = InEx_EjcSd;
return true;
}
if (insEvntSd.TryWait()){
//SD挿入
CheckExSaveState();
isInsEject = InEx_InsSd;
return true;
}
}
#endif
return false;
}
//---------------------------------------------------------------- 終了処理
void endfunc()
{
nn::fs::UnregisterCardEjectedEvent();
nn::fs::UnregisterCardInsertedEvent();
ejectEvnt.Finalize();
insEvnt.Finalize();
#ifdef CSM_FLAG_USE_SD
if (alive_Sd){
nn::fs::UnregisterSdmcEjectedEvent();
nn::fs::UnregisterSdmcInsertedEvent();
ejectEvntSd.Finalize();
insEvntSd.Finalize();
}
#endif
savedata.Finalize();
memsave.Finalize();
ScrFinalize();
}
//エラー停止
void failstop()
{
NN_LOG("fail %d,stop\n",errRes);
while(1){
CheckSysBreak();
}
}
//エラー表示
tChar sts[64];
void PutError(TgtDev dev,int cd)
{
nn::Result res;
switch (dev)
{
case TGT_CARD: res = savedata.LastNnResult;break;
case TGT_MEM: res = memsave.LastNnResult;break;
#ifdef CSM_FLAG_USE_SD
case TGT_SD: res = exsave.LastNnResult;break;
#endif
default: dev = TGT_NONE;//GetDescriptエラー対策
}
GetErrorStr(dev,res,cd,sts);
scr_Status(sts,COLOR_RED);
}
//表示テキストの読込(eMessTagの順)
//テキストはSJISやASCII不可、U-16で保存し文字列は改行(0a0d)で終える
//BOM(先頭2バイトのゴミ ^^; )は付けない事
void LoadMessText(wchar_t* path)
{
const size_t ROMFS_BUFFER_SIZE = 1024*8;
static char buffer[ROMFS_BUFFER_SIZE];
NN_LOG("reqsize = %d",nn::fs::GetRomRequiredMemorySize(8,8));
nn::fs::MountRom(4, 4, buffer, ROMFS_BUFFER_SIZE);
nn::fs::FileReader Reader;
if(Reader.TryInitialize(path).IsFailure())
{
NN_LOG("fail to read file $s\n",path);
endfunc();
}
const u32 size = (u32)Reader.GetSize();
if (size > (MT_END*MESS_SIZE*2))
{
NN_LOG("textfile:size over\n");
endfunc();
}
Reader.Read(Mess,size);
int i,n;
for (i=0;i<MT_END;i++)MessPos[i]=0;
//for (i=0;i<(MT_END*MESS_SIZE);i++)Mess[i]=0;
//Mess[0] = 0;MessPos[0]=0;//先頭(FEFF)をNULLに差替..BOMありのとき
//i=1;n=1;
i=0;n=0;
bool b=true;//最初の改行以外から開始
while( n < (size/2))
{
if ((Mess[n] == 0x0a)||(Mess[n] == 0x0d)){//改行?
Mess[n]=0;//終端に置換
b =true;
} else{
if(b){//改行直後の文字を先頭とみなす
MessPos[i]=n;
i++;
if (i == MT_END)break;
b=false;
}
}
n++;
}
if (i < MT_END){
NN_LOG("textfile: few strings\n");
endfunc();
}
//最後の文字列に終端付ける
n = MessPos[i-1]+1;
while( n < (size/2))
{
if ((Mess[n] == 0x000d) || (Mess[n] == 0x000a)){//改行?
Mess[n]=0;//終端に置換
//break;
}
n++;
}
Mess[size/2] = 0;//念の為、最後に終端
Reader.Finalize();
nn::fs::Unmount("rom:");
}
//ユーザセーブのブロックリード
//中身のデータが作成サイズに満たない場合に
//未書込み領域で検証エラー(desc=329)となる場合がある
//読めないブロックは0で置き換える(SDKツールのSaveFilerと同じ方法..ロンチ当時)
//size = サイズ
// 検証は512単位、読めてるとこまで置き換えないよう512以下で指定
// 尚、ユーザセーブ以外の検証は4096ごと
//pos = 位置指定
// SDK3.1(より?)エラー時にファイルポインタ更新しないので2.0より
bool ReadBlock(s64 pos,int size)
{
if ((size > 512) || (size < 0))return false;
savedata.SetPos(pos);
if(savedata.Read(fileBuffer,size) != size )
{
NN_LOG("%d\n",savedata.LastNnResult.GetDescription());
if(nn::fs::ResultVerificationFailed::Includes(savedata.LastNnResult))
{//検証エラー
for (int i = 0; i < size; i++) fileBuffer[i] = 0;//0埋め
}else return false;
}
return true;
}
//-------------------------------------------------- Verifi
bool Verifi(bool flg)
{
myResult res;
int ct,i,msize,rsize;
s64 total=0,pos;
//セーブデータのマウント
res = savedata.Mount();
if(res != RESULT_OK){
//PutError(TGT_CARD);
return false;
}
//バッファデバイスのマウント
res = memsave.Mount();
if(res != RESULT_OK){
//PutError(TGT_MEM);
return false;
}
//ディレクトリの確認
//空ディレクトリチェックするアプリあり(マリカ7)
//ファイルなし状態ありえるので先に確認
if( dcList.num >0 )
{
nn::fs::Directory dc;
for(i=0;i<dcList.num;i++)
{
if(dc.TryInitialize(dcList.name[i]).IsFailure())
{
dc.Finalize();
return false;
}
dc.Finalize();
}
}
ct =0;
if (arcInfo.FileCount == 0)//ファイルが無い
{
savedata.Unmount();
memsave.Unmount();
return true;//フォーマット一致のみ
}else{
scr_Status(MessTxt(MT_Compair),COLOR_YELLO);
savedata.ResetPath();
memsave.ResetPath();
s64 fsize;
res = RESULT_OK;
while(res==RESULT_OK){
res = savedata.GetPath(file_pathw);
if (res != RESULT_OK)
{
if (res == RESULT_DIR_LEVEL_OVER){
break;
}
if (res == RESULT_PATH_LENGTH_OVER){
break;
}
res = RESULT_FAIL_OPEN;
break;
}
if (file_pathw[0] == 0)break;//root then end
if (ct>=arcInfo.FileCount)
{//カウンタ壊れ、メモリフローの可能性
res = RESULT_FAIL;
break;
}
scr_CountPerMax(ct,arcInfo.FileCount);
if (savedata.Open(file_pathw)==false)
{
res = RESULT_FAIL_OPEN;
break;
}
fsize = savedata.FileSize;
total += fsize;
if (memsave.Open(file_pathw)==false)
{
res = RESULT_FAIL_OPENW;
//savedata.Close();
break;
}
if (fsize != memsave.FileSize)//file size
{
res = RESULT_FAIL;
break;
}
msize=fsize;
if(msize <= FILEBUFF_SIZE ){//一回で読めるサイズならゲージは出さない
scr_CountPerMax2(0,0,-1);
}
pos = 0;
while(fsize)
{
if(msize > FILEBUFF_SIZE ){
scr_CountPerMax2(msize-fsize,msize,0);
}
if (fsize > FILEBUFF_SIZE)
{
rsize = FILEBUFF_SIZE;
fsize -= FILEBUFF_SIZE;
}else{
rsize = fsize;
fsize = 0;
}
if (ReadBlock(pos,rsize)==false)
{
res = RESULT_FAIL_READ;
break;
}
pos += rsize;
if(memsave.Read(fileBuffer_ex,rsize) != rsize )
{//メモリなので実行時バグ
res = RESULT_FAIL;
break;
}
//verifi
for (i = 0;i<rsize;i++)if (fileBuffer[i] != fileBuffer_ex[i])
{
res = RESULT_FAIL_VERIFI;
break;
}
}
savedata.Close();
memsave.Close();
if (res != RESULT_OK)break;
ct++;
}
savedata.Close();
memsave.Close();
}
//セーブ前後で構成が一致するか
if(flg){//読み込み時は無駄なのでフラグでキャンセル
if(savedata.GetInfo(&arcInfo2,&dcList2)==false)res = RESULT_FAIL_VERIFI;
else if (arcInfo.total != arcInfo2.total)res = RESULT_FAIL_VERIFI;
else if (arcInfo.DirEntry != arcInfo2.DirEntry)res = RESULT_FAIL_VERIFI;
else if (arcInfo.DirCount != arcInfo2.DirCount)res = RESULT_FAIL_VERIFI;
else if (arcInfo.FileEntry != arcInfo2.FileEntry)res = RESULT_FAIL_VERIFI;
else if (arcInfo.FileCount != arcInfo2.FileCount)res = RESULT_FAIL_VERIFI;
else if (arcInfo.Dup != arcInfo2.Dup)res = RESULT_FAIL_VERIFI;
if (res == RESULT_OK)
{
int j,k=0;
if(dcList.num != dcList2.num)res=RESULT_FAIL_VERIFI;
else {
for(i=0;i<dcList.num;i++){//いずれかに一致するか
for(j=0;j<dcList.num;j++){
if (CmpPathW(dcList.name[i],dcList2.name[j])){k++;break;}
}
}
if (k != dcList.num)res=RESULT_FAIL_VERIFI;//全一致?
}
}
}
savedata.Unmount();
memsave.Unmount();
scr_CountPerMax(ct,arcInfo.FileCount);
scr_CountPerMax2(0,0,total);
if (res != RESULT_OK){
//PutError(TGT_CARD,ERC_VERIFI);
return false;
}
return true;
}
//---------------------------------------------------------------------- from CARD
RetCode Card2Ctr()
{
myResult res;
int ct=0,msize,rsize;
s64 total=0,pos;
scr_BackupYesNo();//実行確認
WaitUI();//入力待ち
if(isInsEject != InEx_None )
{//挿抜?
//isInsEject = InEx_None;
return INSEXIT;//挿抜による中断
}
if (scr_evnt != EVNT_YES)return CANCEL;//キャンセル
scr_Backup();//画面表示
scr_Status(MessTxt(MT_ChkCard),COLOR_YELLO);
//セーブデータのマウント
res = savedata.Mount();
if(res != RESULT_OK){
PutError(TGT_CARD);
return ERROR;
}
//セーブデータの情報
//arcInfo <- フォーマット情報、ファイル、ディレクトリ数
//scList <- ディレクトリパス
if(savedata.GetInfo(&arcInfo,&dcList)==false)
{
savedata.Unmount();
PutError(TGT_CARD);
return ERROR;
}
//strcpy(arcInfo.Pcode,savedata.PrdCode);
//カウント異常なら実行エラー
if (arcInfo.FileCount > arcInfo.FileEntry)
{
savedata.Unmount();
PutError(TGT_NONE,ERC_EXEC);
return ERROR;
}
if (arcInfo.DirCount > arcInfo.DirEntry)
{
savedata.Unmount();
PutError(TGT_NONE,ERC_EXEC);
return ERROR;
}
if(arcInfo.DirCount >= MAX_DCLIST)
{//ディレクトリ数が多すぎ
savedata.Unmount();
PutError(TGT_MEM,ERC_EXEC);
return ERROR;
}
//メモリFSの予想占有サイズ
sSize = arcInfo.total+arcInfo.FileCount*512;
#ifdef CSM_FLAG_FORCE_SD
return Card2Sd();//デバグ用、強制でSDへ
//警告抑制 unreachable
#pragma diag_suppress 111
#endif
//簡易サイズチェック
if (sSize > MEM_BKUP_SIZE)
{
#ifdef CSM_FLAG_USE_SD
if (alive_Sd)return Card2Sd();//SD使用
#endif
savedata.Unmount();
PutError(TGT_MEM,ERC_NOSPACE);//容量オーバ
return ERROR;
}
#ifdef CSM_FLAG_USE_SD
//本体メモリ使用
BkupSd = false;
#endif
//一時保存が存在したら消す
scr_Status(MessTxt(MT_ChkBkup),COLOR_YELLO);
if(memsave.IsExist()){
if(memsave.Delete()==false)
{
savedata.Unmount();
PutError(TGT_MEM);
return ERROR;
}
}
//一時保存先の作成
scr_Status(MessTxt(MT_CrtBkup),COLOR_YELLO);
res = memsave.Create(arcInfo.DirEntry+1,arcInfo.FileEntry+1);
if (res != RESULT_OK){
savedata.Unmount();
PutError(TGT_MEM);
return ERROR;
}
if (arcInfo.FileCount == 0)//ファイルが無い
{
scr_Status(MessTxt(MT_FileNot),COLOR_YELLO);
savedata.Unmount();
memsave.Unmount();
strcpy(arcInfo.Pcode,savedata.PrdCode);
return SUCCESS;//フォーマットのみ
}else{
scr_Status(MessTxt(MT_Reading),COLOR_SKY);
savedata.ResetPath();
s64 fsize;
res = RESULT_OK;
while(res==RESULT_OK){
res = savedata.GetPath(file_pathw);
if (res != RESULT_OK)
{
if (res == RESULT_DIR_LEVEL_OVER){
//PutError(ERC_DEV_CARD,ERC_DIRDEPTH);
PutError(TGT_NONE,ERC_WORK);
break;
}
if (res == RESULT_PATH_LENGTH_OVER){
//PutError(ERC_DEV_CARD,ERC_PATH);
PutError(TGT_NONE,ERC_WORK);
break;
}
res = RESULT_FAIL_OPEN;
break;
}
if (file_pathw[0] == 0)break;//root then end
if (ct>=arcInfo.FileCount)
{//カウンタ壊れ、メモリフローの可能性
res = RESULT_FAIL;
break;
}
scr_CountPerMax(ct,arcInfo.FileCount);
if (savedata.Open(file_pathw)==false)
{
res = RESULT_FAIL_OPEN;
break;
}
fsize = savedata.FileSize;
total += fsize;
if (memsave.OpenW(file_pathw,fsize)==false)
{
res = RESULT_FAIL_OPENW;
//savedata.Close();
break;
}
//検証単位の512ずつ
msize=fsize;
pos = 0;
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 (ReadBlock(pos,rsize)==false)
{
res = RESULT_FAIL_READ;
break;
}
pos += rsize;
if(memsave.Write(fileBuffer,rsize) != rsize )
{
res = RESULT_FAIL_WRITE;
break;
}
}
savedata.Close();
memsave.CloseW();
//todo: ゲージ表示
ct++;
}
savedata.Close();
memsave.CloseW();
}
if (res == RESULT_OK){
if (ct != arcInfo.FileCount)//ファイル数に満たないパス検索終了
{//ディレクトリ情報かパス取得で失敗してると思われる
PutError(TGT_NONE,ERC_EXEC);
return ERROR;
}
}
savedata.Unmount();
//memsave.Commit(); Nand,SDはコミット入れる
memsave.Unmount();
scr_CountPerMax(ct,arcInfo.FileCount);
if(total>0)scr_CountPerMax2(0,0,total);
//結果
switch(res)
{
case RESULT_OK:
if (Verifi(false))
{
scr_Status(MessTxt(MT_Complate),COLOR_WHITE);
strcpy(arcInfo.Pcode,savedata.PrdCode);
return SUCCESS;
}
PutError(TGT_CARD,ERC_VERIFI);
break;
case RESULT_FAIL_WRITE:
case RESULT_FAIL_OPENW:
PutError(TGT_MEM,ERC_WRITE);
break;
case RESULT_FAIL_READ:
case RESULT_FAIL_OPEN:
PutError(TGT_CARD,ERC_READ);
break;
default:
PutError(TGT_NONE,ERC_EXEC);
break;
}
memsave.Delete();//バックアップを削除
return ERROR;
}
bool mkdir;
//---------------------------------------------------------------- to CARD
RetCode Ctr2Card()
{
myResult res;
int ct=0;
int msize,rsize;
s64 total = 0;
scr_RestoreYesNo();//実行確認
WaitUI();//入力待ち
if(isInsEject != InEx_None ){//挿抜?
//isInsEject = InEx_None;
return INSEXIT;//挿抜による中断
}
if (scr_evnt != EVNT_YES)return CANCEL;//キャンセル
scr_Restore();//画面表示
scr_Status(MessTxt(MT_ChkBkup),COLOR_YELLO);
#ifdef CSM_FLAG_USE_SD
if (BkupSd)return Sd2Card();//SD使用
#endif
//一時保存のマウント
res = memsave.Mount();
if(res != RESULT_OK){
PutError(TGT_MEM);
return ERROR;
}
//セーブデータのフォーマット&マウント
scr_Status(MessTxt(MT_CardFormat),COLOR_YELLO);
res = savedata.Format(&arcInfo);
if(res != RESULT_OK){
memsave.Unmount();
PutError(TGT_CARD);
return ERROR;
}
//ディレクトリ作成
//空ディレクトリもチェックするゲームあるので(マリカ7)
//ファイルの存在と関係なく作成
if(dcList.num >0)
{
int i,rev=0;
for (i=0;i<dcList.num;i++)
{
while(1){
if (savedata.MakeDir(dcList.name[i],&mkdir)==false)
{
if(mkdir==false)
{
res = RESULT_FAIL_OPENW;
break;
}
}else break;
}
if (res != RESULT_OK)break;
rev^=1;
if (rev & 1)scr_Status(MessTxt(MT_CrtDir1),COLOR_YELLO);
else scr_Status(MessTxt(MT_CrtDir2),COLOR_YELLO);
}
if (res != RESULT_OK)
{
memsave.Unmount();
savedata.Unmount();
PutError(TGT_CARD);
return ERROR;
}
}
//パラメータはバックアップ時
//Top画面開始時、挿入イベントなどで取得済み
if (arcInfo.FileCount == 0)
{ //ファイルが無い場合抜ける
scr_Status(MessTxt(MT_FormatOnly),COLOR_YELLO);
savedata.Unmount();
memsave.Unmount();
memsave.Delete();
return SUCCESS;
}else{
scr_Status(MessTxt(MT_Writing),COLOR_PARPL);
memsave.ResetPath();
s64 fsize;
res = RESULT_OK;
while(res==RESULT_OK){
res = memsave.GetPath(file_pathw);
if (res != RESULT_OK)
{
if (res == RESULT_DIR_LEVEL_OVER)break;
if (res == RESULT_PATH_LENGTH_OVER)break;
res = RESULT_FAIL_OPEN;
break;
}
if (file_pathw[0] == 0)break;//root then end
if (ct>=arcInfo.FileCount)
{//カウンタ壊れ、メモリフローの可能性
res = RESULT_FAIL;
break;
}
scr_CountPerMax(ct,arcInfo.FileCount);
if (memsave.Open(file_pathw)==false)
{
res = RESULT_FAIL_OPEN;
break;
}
fsize = memsave.FileSize;
total += fsize;
if (savedata.OpenC(file_pathw,fsize,&mkdir)==false)
{
//ディレクトリは作成済みなので作成されたらエラー
res = RESULT_FAIL_OPENW;
break;
}
/*
int rev = 0;
while(1){
if (savedata.OpenC(file_pathw,fsize,&mkdir)==false)
{
if(mkdir)//ディレクトリのみ作成
{//深い場合に作成が多いと画面が止まるので
rev++;
if (rev & 1)scr_MessOnCount2(MessTxt(MT_CrtDir1));
else scr_MessOnCount2(MessTxt(MT_CrtDir2));
}else{
res = RESULT_FAIL_OPENW;
//memsave.Close();
break;
}
}else break;
}
if (res != RESULT_OK)break;
*/
//メモリファイルで検証エラーはないので512ごとである必要は無いが
//メモリ節約のため同じ方法をとる
msize = fsize;
int itvl = 0;
while(fsize)
{
if(msize > FILEBUFF_SIZE * 2){
scr_CountPerMax2(msize-fsize,msize,0);
if (++itvl & 1)scr_Status(MessTxt(MT_Copy1),COLOR_PARPL);
else scr_Status(MessTxt(MT_Copy2),COLOR_PARPL);
}else scr_MessOnCount2(MES_NULL);
if (fsize>FILEBUFF_SIZE)
{
rsize = FILEBUFF_SIZE;
fsize -= FILEBUFF_SIZE;
}else{
rsize = fsize;
fsize = 0;
}
if(memsave.Read(fileBuffer,rsize) != rsize )
{
res = RESULT_FAIL_READ;
break;
}
if(savedata.Write(fileBuffer,rsize) != rsize )
{
res = RESULT_FAIL_WRITE;
break;
}
}
savedata.CloseW();
memsave.Close();
ct++;
}
savedata.Close();
memsave.CloseW();
}
savedata.Commit();
savedata.Unmount();
memsave.Unmount();
scr_CountPerMax(ct,arcInfo.FileCount);
scr_CountPerMax2(0,0,total);
//結果
switch(res){
case RESULT_OK:
if (Verifi(true)){
if(memsave.Delete()){//バックアップを削除
scr_Status(MessTxt(MT_Complate),COLOR_WHITE);
return SUCCESS;
}
}
PutError(TGT_CARD,ERC_VERIFI);
break;
case RESULT_FAIL_WRITE:
case RESULT_FAIL_OPENW:
PutError(TGT_CARD,ERC_WRITE);
break;
case RESULT_FAIL_READ:
case RESULT_FAIL_OPEN:
PutError(TGT_MEM,ERC_READ);
break;
default:
PutError(TGT_NONE,ERC_EXEC);
break;
}
return ERROR;
}
//******************************************** for SD
//パス長オーバのファイルはメモリ上に記録
//mem:/元ネーム <- リネーム名格納
//sd:/ワーク/リネーム名 <-データ格納
//20000ファイル程度まで
#ifdef CSM_FLAG_USE_SD
bool VerifiSd()
{
myResult res;
int ct,i,msize,rsize;
s64 total=0,pos;
wchar_t ws[20];//"/"+16文字+"\0"
//セーブデータのマウント
res = savedata.Mount();
if(res != RESULT_OK){
//PutError(TGT_CARD);
return false;
}
//出力デバイスのマウント
res = exsave.Mount();
if(res != RESULT_OK){
//PutError(TGT_SD);
return false;
}
memsave.Mount();
ct =0;
if (arcInfo.FileCount == 0)//ファイルが無い
{
savedata.Unmount();
exsave.Unmount();
return true;//フォーマット一致のみ
}else{
scr_Status(MessTxt(MT_Compair),COLOR_YELLO);
savedata.ResetPath();
exsave.ResetPath();
s64 fsize;
res = RESULT_OK;
while(res==RESULT_OK){
if(CheckInsExit())break;//挿抜による中断
res = savedata.GetPath(file_pathw);
if (res != RESULT_OK)
{
if (res == RESULT_DIR_LEVEL_OVER){
break;
}
if (res == RESULT_PATH_LENGTH_OVER){
break;
}
res = RESULT_FAIL_OPEN;
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 (memsave.Open(file_pathw))
{//リネーム対象
memsave.Read((char*)ws,18);//リネーム名
ws[9]=0;ws[10]=0;
wcscpy(file_pathw,wk_dir);//格納先ディレクトリ
wcscat(file_pathw,ws);//パス変換
memsave.Close();
}
if(CheckInsExit())break;//挿抜による中断
if (exsave.Open(file_pathw)==false)
{
res = RESULT_FAIL_OPENW;
//savedata.Close();
break;
}
if (fsize != exsave.FileSize)//file size
{
res = RESULT_FAIL;
break;
}
msize=fsize;
if(msize <= FILEBUFF_SIZE ){//一回で読めるサイズならゲージは出さない
scr_CountPerMax2(0,0,-1);
}
pos = 0;
while(fsize)
{
if(msize > FILEBUFF_SIZE ){
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 (ReadBlock(pos,rsize)==false)
{
res = RESULT_FAIL_READ;
break;
}
pos += rsize;
if(CheckInsExit())break;//挿抜による中断
if(exsave.Read(fileBuffer_ex,rsize) != rsize )
{
res = RESULT_FAIL;
break;
}
for (i = 0;i<rsize;i++)if (fileBuffer[i] != fileBuffer_ex[i])
{
res = RESULT_FAIL;
break;
}
}
savedata.Close();
exsave.Close();
memsave.Close();
if(isInsEject != InEx_None )break;//挿抜による中断
if (res != RESULT_OK)break;
//verifi
ct++;
}
savedata.Close();
exsave.Close();
memsave.Close();
}
savedata.Unmount();
exsave.Unmount();
memsave.Unmount();
scr_CountPerMax(ct,arcInfo.FileCount);
scr_CountPerMax2(0,0,total);
if (res != RESULT_OK){
// PutError(ERC_DEV_OTHER,ERC_VERIFI);
return false;
}
return true;
}
//エラー表示&リターン選択(抜け or ERROR)
RetCode PutErrRetCode(TgtDev dev,int erc = 0)
{
savedata.Unmount();
exsave.Unmount();
memsave.Unmount();
if(CheckInsExit())return INSEXIT;
PutError(dev,erc);
return ERROR;
}
//Ctr2Cardより呼ばれる
RetCode Sd2Card()
{
myResult res;
int ct=0,msize,rsize;
s64 total = 0;
wchar_t ws[20];//"/"+16文字+"\0"
//カードのフォーマット&マウント
scr_Status(MessTxt(MT_CardFormat),COLOR_YELLO);
res = savedata.Format(&arcInfo);
if(res != RESULT_OK) return PutErrRetCode(TGT_CARD,ERC_FORMAT);
//パラメータはバックアップ時
//Top画面開始時、挿入イベントで取得
if (arcInfo.FileCount == 0)//ファイルが無い
{
savedata.Unmount();
if(exsave.Delete()){//バックアップを削除
scr_Status(MessTxt(MT_FormatOnly),COLOR_YELLO);
return SUCCESS;
}
return PutErrRetCode(TGT_SD,ERC_ACCESS);
}
//拡張セーブのマウント
res = exsave.Mount();
if(res != RESULT_OK) return PutErrRetCode(TGT_SD);
memsave.Mount();
scr_Status(MessTxt(MT_Writing),COLOR_PARPL);
exsave.ResetPath();
s64 fsize;
res = RESULT_OK;
while(res==RESULT_OK){
res = exsave.GetPath(file_pathw);
if (res != RESULT_OK)
{
if ((res != RESULT_DIR_LEVEL_OVER)
&& (res != RESULT_PATH_LENGTH_OVER))res = RESULT_FAIL_OPEN;
break;
}
if (file_pathw[0] == 0)break;//root then end
if (ct>=arcInfo.FileCount)
{//カウンタ壊れ、メモリフローの可能性
res = RESULT_FAIL;
break;
}
scr_CountPerMax(ct,arcInfo.FileCount);//カウンタ表示
if (exsave.Open(file_pathw)==false)
{
res = RESULT_FAIL_OPEN;
break;
}
fsize = exsave.FileSize;
total += fsize;
if (savedata.CheckPathBit & cpb_ex )
{//違反パス名あり?
if (CmpDirW(file_pathw,wk_dir)==1)
{//リネームファイルなら元のパス名を探す
memsave.ResetPath();
int i=0;bool b=false;
ws[9]=0;ws[10]=0;
while(i<rename_n){
memsave.GetPath(file_pathw2);
if(file_pathw2[0]==0)break;
memsave.Open(file_pathw2);
memsave.Read((char*)ws,18);
if(CmpNameW(file_pathw,ws)){
wcscpy(file_pathw,file_pathw2);
b = true;
break;
}
i++;
}//while
if (b==false){//見つからない->差替?? or メモリ破壊??
res = RESULT_FAIL;
break;
}
}
}
int rev = 0;
while(1){
if (savedata.OpenC(file_pathw,fsize,&mkdir)==false)
{
if(mkdir)//ディレクトリのみ作成
{//深い場合に作成が多いと画面が止まるので
rev++;
if (rev & 1)scr_MessOnCount2(MessTxt(MT_CrtDir1));
else scr_MessOnCount2(MessTxt(MT_CrtDir2));
}else{
res = RESULT_FAIL_OPENW;
//exsave.Close();
break;
}
}else break;
}//while
if (res != RESULT_OK)break;
msize = fsize;
int itvl = 0;
while(fsize)
{
if(msize > FILEBUFF_SIZE * 2){
scr_CountPerMax2(msize-fsize,msize,0);
if (++itvl & 1)scr_Status(MessTxt(MT_Copy1),COLOR_PARPL);
else scr_Status(MessTxt(MT_Copy2),COLOR_PARPL);
}else scr_MessOnCount2(MES_NULL);
if (fsize>FILEBUFF_SIZE)
{
rsize = FILEBUFF_SIZE;
fsize -= FILEBUFF_SIZE;
}else{
rsize = fsize;
fsize = 0;
}
if(exsave.Read(fileBuffer,rsize) != rsize )
{
res = RESULT_FAIL_READ;
break;
}
if(savedata.Write(fileBuffer,rsize) != rsize )
{
res = RESULT_FAIL_WRITE;
break;
}
}//while
savedata.CloseW();
exsave.Close();
ct++;
}//while
savedata.Close();
exsave.CloseW();
if(res == RESULT_OK)savedata.Commit();
savedata.Unmount();
exsave.Unmount();
memsave.Unmount();
scr_CountPerMax(ct,arcInfo.FileCount);
scr_CountPerMax2(0,0,total);
//結果
TgtDev ercd;
int ercc;
switch(res){
case RESULT_OK:
if (VerifiSd()){
memsave.Delete();
if(exsave.Delete()){//バックアップを削除
scr_Status(MessTxt(MT_Complate),COLOR_WHITE);
return SUCCESS;
}
}
ercd =TGT_CARD;ercc = ERC_VERIFI;//ベリファイエラー
break;
case RESULT_FAIL_WRITE:
case RESULT_FAIL_OPENW:
ercd = TGT_CARD;ercc = ERC_WRITE;
break;
case RESULT_FAIL_READ:
case RESULT_FAIL_OPEN:
ercd = TGT_SD;ercc = ERC_READ;
break;
default:
ercd = TGT_NONE;ercc = ERC_EXEC;
break;
}
return PutErrRetCode(ercd,ercc);
}
//Crad2Ctrより呼ばれる
RetCode Card2Sd()
{
myResult res;
int ct=0,msize,rsize;
s64 total=0,fsize,pos;
int i;
wchar_t ws[20];//"/"+16文字+"\0"
BkupSd = true;
//拡張セーブが存在したら消す
scr_Status(MessTxt(MT_ChkBkup),COLOR_YELLO);
if(exsave.IsExist()){
if(exsave.Delete()==false) return PutErrRetCode(TGT_SD);
}
if(CheckInsExit())return INSEXIT;//抜けで"なし"判定の場合
//一時保存先の作成
scr_Status(MessTxt(MT_CrtBkup),COLOR_YELLO);
//拡張セーブで違反になるパス名あり?
if (savedata.CheckPathBit & cpb_ex )
{
//該当ファイルを変名保存するディレクトリ追加
res = exsave.Create(arcInfo.DirEntry+1,arcInfo.FileEntry);
}else res = exsave.Create(arcInfo.DirEntry,arcInfo.FileEntry);
if (res != RESULT_OK) return PutErrRetCode(TGT_SD);
if(CheckInsExit())return INSEXIT;//抜け
//パラメータはバックアップ時
//Top画面開始時、挿入イベントで取得
if (arcInfo.FileCount == 0)//ファイルが無い
{
scr_Status(MessTxt(MT_FileNot),COLOR_YELLO);
strcpy(arcInfo.Pcode,savedata.PrdCode);
savedata.Unmount();
return SUCCESS;//フォーマットのみ
}
//簡易サイズチェック
//SDのクラスタサイズやヘッダでメモリFSより多く占有する
//セクタサイズ4:2GB、32K:4GB 余裕を見ておく(ファイル数上限での最悪)
//4GBデバイスの移行なら、8G以上のSDを使う
fsize = exsave.GetFreeSize();//取得APIがマウント必須なのでCreate後でないとダメ
//ヘッダ16k+4K(ファイル名+アライメント) ..セクタサイズ4Kの前提
sSize = arcInfo.total + arcInfo.FileCount*20480;
if ((sSize > fsize) || (fsize ==0)) return PutErrRetCode(TGT_SD,ERC_NOSPACE);
//メモリFS上に作成..ファイル名保存のため、中身はSD上のファイル名
//拡張セーブは最大パス長がユーザセーブより短いため超えるものは変名
//オリジナルファイル名で作成したファイルに変更後のファイル名を格納
//ワークの10MByteで1万ファイルくらい
memsave.Delete();
memsave.Create(1,arcInfo.FileCount);
memsave.Mount();
//read
scr_Status(MessTxt(MT_Reading),COLOR_PARPL);
savedata.ResetPath();
total=0;ct=0;rename_n=0;
res = RESULT_OK;
while(res==RESULT_OK){
res = savedata.GetPath(file_pathw);
if (res != RESULT_OK)
{
if ((res != RESULT_DIR_LEVEL_OVER)
&& (res != RESULT_PATH_LENGTH_OVER)) res = RESULT_FAIL_OPEN;
break;
}
if (file_pathw[0] == 0)break;//root then end
if (ct>=arcInfo.FileCount)
{//カウンタ壊れ、メモリフローの可能性
res = RESULT_FAIL;
break;
}
scr_CountPerMax(ct,arcInfo.FileCount);
if (savedata.Open(file_pathw)==false)
{
res = RESULT_FAIL_OPEN;
break;
}
fsize = savedata.FileSize;
total += fsize;
//パス名チェック
if (CheckPathEx(file_pathw) == false)
{//メモリFS上にファイル作成(パス名記録のみ目的)
savedata.Close();
if (memsave.OpenW(file_pathw,512)==false)
{
res = RESULT_FAIL_OPENW;
break;
}
//リネーム名の格納
swprintf(ws,16,L"/%8x",rename_n);//リネーム
for (i=1;i<8;i++)if(ws[i]==L' ')ws[i]=L'0';
rename_n++;
if(memsave.Write( (char*)ws,18) != 18)//wchar 9文字
{
res = RESULT_WORK_OVER;//ワーク不足
break;
}
memsave.CloseW();
}else
{
int rev = 0;
while(1){
if (exsave.OpenC(file_pathw,fsize,&mkdir)==false)
{
if(mkdir)//ディレクトリのみ作成
{//深い場合に作成が多いと画面が止まるので
rev++;
if (rev & 1)scr_MessOnCount2(MessTxt(MT_CrtDir1));
else scr_MessOnCount2(MessTxt(MT_CrtDir2));
}else{
res = RESULT_FAIL_OPENW;
//exsave.Close();
break;
}
}else break;
}
if (res != RESULT_OK)break;
msize = fsize;
int itvl = 0;
pos =0;
while(fsize)
{
if(msize > FILEBUFF_SIZE * 2)
{
scr_CountPerMax2(msize-fsize,msize,0);
if (++itvl & 1)scr_Status(MessTxt(MT_Copy1),COLOR_PARPL);
else scr_Status(MessTxt(MT_Copy2),COLOR_PARPL);
}else scr_MessOnCount2(MES_NULL);
if (fsize>FILEBUFF_SIZE)
{
rsize = FILEBUFF_SIZE;
fsize -= FILEBUFF_SIZE;
}else{
rsize = fsize;
fsize = 0;
}
if (ReadBlock(pos,rsize)==false)
{
res = RESULT_FAIL_READ;
break;
}
pos += rsize;
if(exsave.Write(fileBuffer,rsize) != rsize )
{
NN_LOG("desc = %d\n",savedata.LastNnResult.GetDescription());
res = RESULT_FAIL_WRITE;
break;
}
}//fsize
ct++;
savedata.Close();
exsave.CloseW();
}//else
}//while
if ((res == RESULT_OK) && (savedata.CheckPathBit & cpb_ex))
{//違反パスありなら、リネームして保存
nn::Result result;
nn::fnd::DateTime tm;
//ディレクトリ作成..既存名を避けるため作成後に行う
i = 0;
while(i++ < 10 ){//試行回数(無駄?)
tm = nn::fnd::DateTime::GetNow();
//退避先ディレクトリ名作成:SDK制限で16文字まで
swprintf(file_pathw,3,L"%3d",tm.GetMilliSecond());
if (file_pathw[0]==L' ')file_pathw[0] = L'0';
if (file_pathw[1]==L' ')file_pathw[1] = L'0';
wcscpy(wk_dir,L"/cSm_");//通常、使われないであろう名前にする
wcscat(wk_dir,file_pathw);
wcscat(wk_dir,L"_zzz");
exsave.GetRootPath(file_pathw);
wcscat(file_pathw,wk_dir);
result = nn::fs::TryCreateDirectory(file_pathw);
if (result.IsSuccess())break;
if(CheckInsExit())break;
}
if (result.IsFailure()){
exsave.Unmount();
memsave.Unmount();
savedata.Unmount();
exsave.Delete();//バックアップを削除
memsave.Delete();
if(isInsEject != InEx_None )return INSEXIT;
PutError(TGT_SD,ERC_WORK);//退避先が確保できない
return ERROR;
}
memsave.ResetPath();
while(res==RESULT_OK){
res = memsave.GetPath(file_pathw);//リネーム対象ファイル名
if (file_pathw[0] == 0)break;//root then end
if (ct>=arcInfo.FileCount)
{
res = RESULT_FAIL;
break;
}
scr_CountPerMax(ct,arcInfo.FileCount);
if (savedata.Open(file_pathw)==false)//ユーザセーブ開く
{
res = RESULT_FAIL_OPEN;
break;
}
fsize = savedata.FileSize;
//リネーム名取得
if (memsave.Open(file_pathw)==false)
{
res = RESULT_FAIL;//メモリからなので通常ありえない
break;
}
if(memsave.Read((char*)ws,18)!=18)//wchar 9文字
{
res = RESULT_FAIL;//メモリからなので通常ありえない
break;
}
memsave.Close();
ws[9]=0;//終端
ws[10]=0;
wcscpy(file_pathw2,wk_dir);
wcscat(file_pathw2,ws);
if (exsave.OpenC(file_pathw2,fsize,&mkdir)==false)
{//エラーもしくは、退避先ディレクトリが無い
res = RESULT_FAIL_OPENW;
break;
}
msize = fsize;
pos =0;
while(fsize)
{
if (fsize>FILEBUFF_SIZE)
{
rsize = FILEBUFF_SIZE;
fsize -= FILEBUFF_SIZE;
}else{
rsize = fsize;
fsize = 0;
}
if (ReadBlock(pos,rsize)==false)
{
res = RESULT_FAIL_READ;
break;
}
pos += rsize;
if(exsave.Write(fileBuffer,rsize) != rsize )
{
res = RESULT_FAIL_WRITE;
break;
}
}//while(fsize)
ct++;
savedata.Close();
exsave.CloseW();
memsave.Close();
}//while
}//if
savedata.Unmount();
exsave.Unmount();
memsave.Unmount();
scr_CountPerMax(ct,arcInfo.FileCount);
scr_CountPerMax2(0,0,total);
//結果
TgtDev ercd;
int ercc;
switch(res)
{
case RESULT_OK:
if (VerifiSd())
{
scr_Status(MessTxt(MT_Complate),COLOR_WHITE);
strcpy(arcInfo.Pcode,savedata.PrdCode);
return SUCCESS;
}
ercd = TGT_CARD;ercc = ERC_VERIFI;
break;
case RESULT_FAIL_WRITE:
case RESULT_FAIL_OPENW:
ercd = TGT_SD;ercc = ERC_WRITE;//ライト失敗
break;
case RESULT_FAIL_READ:
case RESULT_FAIL_OPEN:
ercd = TGT_CARD;ercc = ERC_READ;//リード
break;
case RESULT_WORK_OVER:
ercd = TGT_NONE;ercc = ERC_NOSPACE;//ワーク不足..違反フアイル多すぎ
break;
default:
ercd = TGT_NONE;ercc = ERC_EXEC;
break;
}
exsave.Delete();//バックアップを削除
memsave.Delete();
return PutErrRetCode(ercd,ercc);
}
#endif
//--------------------------------------------------------------- セーブデータの情報取得
//呼ぶ前に tmerr のクリアを忘れない事
void CheckSaveDataState()
{
Formatted = false;
Active = false;
if (savedata.GetPrdCode())
{
//NN_LOG("%d",savedata.LastNnResult.GetDescription());
Active = true;//カード
if (savedata.IsExist())//マウントで確認
{
Formatted=true;
}else{
tmerr |= SDATA_ERRPUT_MEDIA;
}
}
scr_PrdCode(savedata.PrdCode);
//プロダクトコードのチェック
isAgreePCode = strcmp(savedata.PrdCode,arcInfo.Pcode)==0;
}
void CheckExSaveState()
{
#ifdef CSM_FLAG_USE_SD
if (alive_Sd)exActive = nn::fs::IsSdmcWritable();
else exActive = true;
#else
exActive = true;
#endif
if (exActive){
#ifdef CSM_FLAG_USE_SD
if (BkupSd){
exFormatted = exsave.IsExist();
exsave.Unmount();
}else{
#endif
exFormatted = memsave.IsExist();
memsave.Unmount();
#ifdef CSM_FLAG_USE_SD
}
#endif
}else{
exFormatted = false;
}
//デバグ時は抜けてもクリアしない
#ifndef CSM_FLAG_DEBUG
if (exFormatted==false) arcInfo.Pcode[0] = 0;
#endif
scr_PrdCodeEx(arcInfo.Pcode);
//プロダクトコードのチェック
isAgreePCode = strcmp(savedata.PrdCode,arcInfo.Pcode)==0;
}
//SD挿抜
void Evt_SdInEx()
{
#ifndef CSM_FLAG_DEBUG
ScrClr();
scr_TopMenu(Formatted,Active,exFormatted,exActive,tmerr);
scr_Draw();
failstop();//停止
#else
CheckExSaveState();//状態更新
scr_evnt = EVNT_INEX;
#endif
}
//---------------------------------------------------------------- 入力待ち
void WaitUI()
{
tmerr = 0;
scr_Draw();//画面更新
scr_evnt = EVNT_NONE;
while(scr_evnt == EVNT_NONE)
{
//nn::os::Thread::Yield();//スレッド実行
//scr_GetEvnt();//入力イベント
CheckSysBreak();//中断処理
#ifdef CSM_FLAG_USE_SD
//挿抜を検知したらアプリ終了待ちするようする
if (ejectEvntSd.TryWait()){
isInsEject = InEx_EjcSd;
Evt_SdInEx();
return;
}
if (insEvntSd.TryWait()){
isInsEject = InEx_InsSd;
Evt_SdInEx();
return;
}
#endif
//挿抜を検知したら中断して抜ける
//トップ以外ではトップメニューへ戻るようする
if (ejectEvnt.TryWait()){
isInsEject = InEx_EjcCard;
CheckSaveDataState();
scr_evnt = EVNT_INEX;
return;
}
if (insEvnt.TryWait()){
isInsEject = InEx_InsCard;
CheckSaveDataState();
scr_evnt = EVNT_INEX;
return;
}
nn::os::Thread::Yield();//スレッド実行..タッチ&ボタン取得
}
ScrClr();//画面消去
nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(500));//チャタ対策
}
void InsExtErrPut(tIsInsEject n)
{
switch (n)
{
case InEx_EjcSd:
case InEx_InsSd://SD insert or exit
PutError(TGT_SD,ERC_PULLOUT);
#ifndef CSM_FLAG_DEBUG
failstop();//stop running
#endif
break;
case InEx_EjcCard:
PutError(TGT_CARD,ERC_DEVICE);
break;
case InEx_InsCard://素早い抜き差しでEjectイベント消える?
PutError(TGT_CARD,ERC_PULLOUT);
break;
default://通常ありえない .. 実行時エラー
PutError(TGT_NONE,ERC_EXEC);
failstop();//stop running
break;
}
}
//---------------------- main loop --------------------------
void nnMain()
{
RetCode retc;
//tColStr *colstr[4];
//colstr[2] = &mess_WhenExc;
//colstr[3] = &mess_PoffSys;
isInsEject = InEx_None;
//NN_LOG("Start\n");
nn::os::Initialize();
nn::fs::Initialize();
//DEA-SUPにて推奨のフリーズ暫定対策無線デーモンを停止 (2011.3.1 現在)
//ただし、スリープ時は止まらない
//心配なら本体スイッチで切っとく
nn::ndm::Initialize();
nn::ndm::SuspendScheduler();
//中断処理の準備
InitSysBreak((uptr)endfunc);
// グラフィックスライブラリの初期化は、以降で行わなければならない
// 他、アプリケーションの初期化処理
nn::applet::DisableSleep();//スリープ非対応
#ifdef CSM_FLAG_USE_SD
//起動時にSD確認
alive_Sd = nn::fs::IsSdmcWritable();
#else
alive_Sd = false;
#endif
//Heap
appHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR);
const u32 GxHeapSize = 0x800000;
heapForGx = reinterpret_cast<uptr>(appHeap.Allocate(GxHeapSize));
//画面初期化
//メッセージ用テキストの読み込み
bool jp;
// nn::cfg::CTR::Initialize();
// if (nn::cfg::GetLanguage() == nn::cfg::CFG_LANGUAGE_JAPANESE)
// {
// jp = true;
// LoadMessText(L"rom:/lang_jp.mes");
//}
//else{
jp = false;
LoadMessText(L"rom:/lang_en.mes");
// }
// nn::cfg::Finalize();
#ifdef CSM_FLAG_DEBUG
//リリース品と区別するためタイトルに[debug]を付ける(非セキュア品の流出予防)
if (ScrInitialize(heapForGx,GxHeapSize,jp,true) == false)finish();
#else
if (ScrInitialize(heapForGx,GxHeapSize,jp,false) == false)finish();
#endif
//挿抜イベント
ejectEvnt.ClearSignal();
insEvnt.ClearSignal();
nn::fs::RegisterCardEjectedEvent(&ejectEvnt);
nn::fs::RegisterCardInsertedEvent(&insEvnt);
#ifdef CSM_FLAG_USE_SD
if (alive_Sd){
ejectEvntSd.ClearSignal();
insEvntSd.ClearSignal();
nn::fs::RegisterSdmcEjectedEvent(&ejectEvntSd);
nn::fs::RegisterSdmcInsertedEvent(&insEvntSd);
//拡張セーブが存在したら消す
if(exsave.IsExist())exsave.Delete();
}
#endif
// スリープ要求に対する返答を有効にする
// また、蓋の状態チェックを行い蓋が閉じられているならスリープ要求が発生する
//nn::applet::EnableSleep(true);
extern u8 scr_evnt;
u8 scr_evntbk;
while(1)
{
tmerr = 0;
CheckSaveDataState(); //セーブデータの状態取得
CheckExSaveState(); //同バックアップ
if (isAgreePCode==false) tmerr |= SDATA_ERRPUT_PCODE;
scr_TopMenu(Formatted,Active,exFormatted,exActive,tmerr);
WaitUI();//入力待ち
scr_evntbk = scr_evnt;
switch(scr_evnt)
{
case EVNT_INEX:
isInsEject= InEx_None;
break;
case EVNT_PUSH_B:
case EVNT_PUSH_R:
case EVNT_PUSH_Y:
case EVNT_NONE:
break;
case EVNT_SEL_READ://**************************** リード
NN_LOG("select read\n");
retc = Card2Ctr();
switch (retc){
case SUCCESS:
//CheckExSaveState(); //状態の更新
scr_ResultQuit(MessTxt(MT_Success),COLOR_GREEN);//成功とQuitボタン
break;
case INSEXIT:
//scr_InsExitQuit();//挿抜検知表示 & Quit
ScrClr();//画面消去
scr_Backup();
InsExtErrPut(isInsEject);
scr_ResultQuit(MessTxt(MT_Break),COLOR_RED);//エラーとQuitボタン
break;
case CANCEL:
break;
default://errors
if (CheckInsExit())InsExtErrPut(isInsEject);//抜差イベント?
scr_ResultQuit(MessTxt(MT_Failed),COLOR_RED);//エラーとQuitボタン
break;
}
break;
case EVNT_SEL_WRITE:// **************************** リストア
NN_LOG("select write\n");
retc = Ctr2Card();
switch (retc){
case SUCCESS:
//CheckSaveDataState(); //状態の更新
//CheckExSaveState();
scr_ResultQuit(MessTxt(MT_Success),COLOR_GREEN);//成功とQuitボタン
break;
case INSEXIT:
//scr_InsExitQuit();//挿抜検知表示 & Quit
ScrClr();//画面消去
scr_Restore();
InsExtErrPut(isInsEject);
scr_ResultQuit(MessTxt(MT_Break),COLOR_RED);//エラーとQuitボタン
case CANCEL:
break;
default://errors
if (CheckInsExit())InsExtErrPut(isInsEject);//抜差イベント?
scr_ResultQuit(MessTxt(MT_Failed),COLOR_RED);//エラーとQuitボタン
break;
}
break;
case EVNT_PUSH_LEFT_X:// ------------------------------------- LEFT + X
//バックアップ削除
scr_DelConf();//実行確認
WaitUI();
if (scr_evnt != EVNT_YES)break;
memsave.Delete();
#ifdef CSM_FLAG_USE_SD
if(alive_Sd)exsave.Delete();
#endif
break;
default:
failstop();
break;
}
if (((scr_evntbk == EVNT_SEL_WRITE)||(scr_evntbk == EVNT_SEL_READ)) && (retc != CANCEL))
{
while(1){
WaitUI();
if (scr_evnt == EVNT_INEX)isInsEject = InEx_None;
if ((scr_evnt==EVNT_QUIT) || (scr_evnt==EVNT_PUSH_B))break;
}
}
}//while()
}
/*---------------------------------------------------------------------------*
End of file
*---------------------------------------------------------------------------*/