diff --git a/branches/0thNUP_No_NUP/CardCup/CardCup.bsf b/branches/0thNUP_No_NUP/CardCup/CardCup.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/branches/0thNUP_No_NUP/CardCup/CardCup.bsf differ diff --git a/branches/0thNUP_No_NUP/CardCup/CardCup.rsf b/branches/0thNUP_No_NUP/CardCup/CardCup.rsf new file mode 100644 index 0000000..88792b8 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardCup/CardCup.rsf @@ -0,0 +1,22 @@ +BasicInfo: + Title : CupCardDemo + BackupMemoryType : None + Logo: Nintendo + +TitleInfo: + Use: Evaluation + UniqueId: 0xf802a + Version: 0 + +SystemControlInfo: + AppType : System + Dependency: + - codec + - hid + - gsp + - dsp + +AccessControlInfo: + Priority: 48 + FileSystemAccess: + - CategorySystemApplication diff --git a/branches/0thNUP_No_NUP/CardCup/OMakefile b/branches/0thNUP_No_NUP/CardCup/OMakefile new file mode 100644 index 0000000..bb62ff4 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardCup/OMakefile @@ -0,0 +1,46 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakefile +# +# 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. +# +# $Rev$ +#---------------------------------------------------------------------------- +CTR_APPTYPE=BOTH +CTR_MAKE_DEVELOPMENT_IMAGE = true + +SUPPORTED_TARGETS = CTR-T*.Process.MPCore.* + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) + +SOURCES[] = + main.cpp + scrollBuffer.cpp + +LIBS += lib_demo \ + libnn_am \ + libnn_cup \ + libnn_ns \ + libnn_ps + + +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/HomeMenuTest.desc + +TARGET_PROGRAM = CardCup + +TITLE = CardCup +ROM_SPEC_FILE = CardCup.rsf + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +include $(ROOT_OMAKE)/modulerules + +build: $(DEFAULT_TARGETS) diff --git a/branches/0thNUP_No_NUP/CardCup/OMakeroot b/branches/0thNUP_No_NUP/CardCup/OMakeroot new file mode 100644 index 0000000..7ee1cb5 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardCup/OMakeroot @@ -0,0 +1,73 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakeroot +# +# 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. +# +# $Rev:$ +#---------------------------------------------------------------------------- + +# ディレクトリレイアウトについての説明 +# +# a) ソースコードがルートディレクトリ直下に配置される場合 +# 例: +# /OMakeroot +# /foo/bar/OMakefile +# +# 結果: +# OMakefile と同じディレクトリ以下に objects や images が生成されます。 +# +# /foo/bar/objects/... +# /foo/bar/images/.. +# +# +# b) ソースコードが sources 以下に配置される場合 +# 例: +# /OMakeroot +# /sources/foo/bar/OMakefile +# +# 結果: +# ルートディレクトリ以下に objects や images が生成されます。 +# +# /objects/foo/bar/... +# /images/foo/bar/... +# +# + +# ルート環境変数の取得 +public.HORIZON_ROOT = +if $(defined-env HORIZON_ROOT) + HORIZON_ROOT = $(absname $(getenv HORIZON_ROOT)) + export + +if $(defined-env CTRSDK_ROOT) + CTRSDK_ROOT = $(absname $(getenv CTRSDK_ROOT)) + if $(and $(defined-env HORIZON_ROOT), $(not $(equal $(HORIZON_ROOT), $(CTRSDK_ROOT)))) + eprintln(HORIZON_ROOT と CTRSDK_ROOT が一致しません。同じパスを設定するか、どちらか一方だけを定義して下さい。) + exit(1) + HORIZON_ROOT = $(CTRSDK_ROOT) + export + +if $(not $(HORIZON_ROOT)) + eprintln($"$$CTRSDK_ROOT が定義されていません") + exit(1) + +include $(HORIZON_ROOT)/build/omake/commondefs + +DefineCommandVars() + +.PHONY: all build clean clobber +.PHONY: run run-scripts run-emumem + +# +# OMakefile の読み込み +# +.SUBDIRS: . + diff --git a/branches/0thNUP_No_NUP/CardCup/banner/model.cbmd b/branches/0thNUP_No_NUP/CardCup/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardCup/banner/model.cbmd differ diff --git a/branches/0thNUP_No_NUP/CardCup/banner/sound.cbsd b/branches/0thNUP_No_NUP/CardCup/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardCup/banner/sound.cbsd differ diff --git a/branches/0thNUP_No_NUP/CardCup/banner/unknown24x24.ctpk b/branches/0thNUP_No_NUP/CardCup/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardCup/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +スススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススニススススススススススススススススススススススススススススススススススススススニ8ニ8ニ゙銷スス8ニススススス釡゙ニ鍄踟ススススススススススススススススススススススススススススススススススススススススススニススススススススススススススススススススススススススススススススススススススススススyホスyホスススススYホスススススススススススススススススススススススススススススススススス鍄゙yホYホスロ゙ロ゙ススニススロ゙yボスyホ轌ホ釡゙ススススYホ轌ホ銷スススススyホニロ゙鍄躡ホyホスススyホスコヨスススススyホスyホスススススYホスススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススyホ躡ホ銷スススススニスス轌ホ8ニススススニススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススス \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/CardCup/banner/unknown48x48.ctpk b/branches/0thNUP_No_NUP/CardCup/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardCup/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +スススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススYホススススススススススススススススススススススススススス8ニスス8ニ8ニスススコヨ8ニコヨ釡゙銷スススススススススス8ニ8ニススニススススススススススススススススス鍄逧ヨニ銷スス墮ス逧ヨ銷スススススススススススススススススススススススススススススススススススススススススス8ニススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススロ゙スロ゙ススススス銷ズスススススススススススススススススススススコヨスススススススススス鍄8ニ゙ロ゙スス墮スYホススススス躡ホyホ轌ホニススススススススニススススススススススススロ゙ロ゙釡゙踟スス躡ホ銷スススススロ゙スロ゙銷ススYボ墮釡゙コヨス墮スロ゙ススススス踟ス踟スススススススススススススススススススススロ゙スyホススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススYホス墮銷スロ゙スロ゙銷ススススススススススススススススス8ニススコヨロ゙スススススYホニyホ逧ヨ郤ヨスYホス觝ホススススススススススススススロ゙墮ススススススyホス鍄踟ススニスススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススス踟ス銷ズスYホ鍄銷ススススススススススススススススススススス8ニスススススススススス逧ヨスロ゙ス釡゙墮ススススススススススススススススススス8ニススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススス \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/CardCup/main.cpp b/branches/0thNUP_No_NUP/CardCup/main.cpp new file mode 100644 index 0000000..e0cb634 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardCup/main.cpp @@ -0,0 +1,269 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: main.cpp + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "demo.h" +#include "scrollBuffer.h" + +namespace +{ + const int s_GxHeapSize=0x800000; + nn::fnd::ExpHeap s_appHeap; + uptr s_GxHeap; + + demo::RenderSystemDrawing s_RenderSystem; + ScrollBuffer s_scrollBufferInstance; + ScrollBuffer *s_scrollBuffer; + + char s_updaterBuffer[1<<20] NN_ATTRIBUTE_ALIGN(4096); + + // 繝繝「縺ョ蛻晄悄蛹 + void Initialize() + { + // os 縺ョ蛻晄悄蛹 + nn::os::Initialize(); + + // NuiShell縺ョ蛻晄悄蛹 (CUP縺ォ蠢鬆) + NN_UTIL_PANIC_IF_FAILED(nn::ns::CTR::InitializeForShell()); + + // fs縺ョ蛻晄悄蛹 (繧ォ繝シ繝臥「コ隱咲畑) + nn::fs::Initialize(); + + // applet縺ョ蛻晄悄蛹 + //nn::applet::InitializeForSystem( nn::applet::PHOME_MENU_APPLET_ID, nn::applet::TYPE_SYS ); + //nn::applet::Initialize( nn::applet::TEST2_APPLET_ID); + //nn::applet::SetAppletMode(); + nn::applet::Enable(); + + // 繝繝舌う繧ケ繝。繝「繝ェ縺ョ險ュ螳 + const int DEVICE_MEMORY_SIZE = 12*1024 * 1024; + NN_UTIL_PANIC_IF_FAILED(nn::os::SetDeviceMemorySize(DEVICE_MEMORY_SIZE)); + + // 繝偵シ繝励ョ蛻晄悄蛹 + s_appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + // 謠冗判繧、繝ウ繧ケ繧ソ繝ウ繧ケ縺ョ蛻晄悄蛹 + s_GxHeap = reinterpret_cast(s_appHeap.Allocate(s_GxHeapSize)); + s_RenderSystem.Initialize(s_GxHeap, s_GxHeapSize); + + // hid縺ョ蛻晄悄蛹 + NN_UTIL_PANIC_IF_FAILED(nn::hid::Initialize()); + + // 謠冗判繧、繝ウ繧ケ繧ソ繝ウ繧ケ縺ョ蛻晄悄蛹 + s_scrollBufferInstance.Initialize(&s_RenderSystem); + s_scrollBuffer=&s_scrollBufferInstance; + + // GPU蛻ゥ逕ィ螳」險 + nn::applet::AssignGpuRight(); + } + + // 豸郁イサ譎る俣蜿門セ礼畑髢「謨ー鄒、 + s64 s_StartTick; + void SetTick() + { + s_StartTick=nn::os::Tick::GetSystemCurrent(); + } + s64 GetConsumedMillisec() + { + s64 endTick=nn::os::Tick::GetSystemCurrent(); + nn::os::Tick consumed(endTick-s_StartTick); + return ((nn::fnd::TimeSpan)consumed).GetMilliSeconds(); + } + + // 蜍輔>縺ヲ縺繧九%縺ィ繧堤衍繧峨○繧九◆繧√ョ縲√¥繧九¥繧狗判髱「陦ィ遉コ蜿門セ礼畑繝。繧ス繝繝 + const char s_progress[]="-\\|/"; + int s_progressIndex=0; + char GetProgressChar() + { + s_progressIndex=(s_progressIndex+1)%(sizeof(s_progress)-1); + return s_progress[s_progressIndex]; + } + + nn::Result UpdateCore() + { + nn::Result result; + nn::cup::ProgressInfo info; + + /********************** 繧「繝繝励ョ繝シ繝*******************/ + SetTick(); + s_scrollBuffer->AppendText("Start Card Update")->Render(); + NN_UTIL_RETURN_IF_FAILED(nn::cup::CTR::DoUpdate()); + + // 繧ケ繝繝シ繧ソ繧ケ縺郡tarted縺ォ縺ェ繧九∪縺ァ縲√励Ο繧ー繝ャ繧ケ縺ッ蜿門セ励〒縺阪↑縺 + s_scrollBuffer->AppendText(""); + do{ + s_scrollBuffer->ReplaceText(" %c Initializing", GetProgressChar())->Render(); + result = nn::cup::CTR::GetProgressInfo(&info); + NN_UTIL_RETURN_IF_FAILED(result); + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(40)); + }while(info.state==nn::cup::CTR::UPDATE_STATE_INITIALIZING); + + // 謚懊¢縺滄圀縺ョstate縺熊AILED縺九←縺縺狗「コ隱 + if(info.state==nn::cup::CTR::UPDATE_STATE_FAILED){ + NN_UTIL_RETURN_IF_FAILED(info.lastResult); + } + s_scrollBuffer->ReplaceText(" - Initialized (%lldmsec)", GetConsumedMillisec()); + + /********************* 繧「繝繝励ョ繝シ繝井クュ ******************/ + SetTick(); + s_scrollBuffer->AppendText("")->Render(); + do{ + result = nn::cup::CTR::GetProgressInfo(&info); + NN_UTIL_RETURN_IF_FAILED(result); + s_scrollBuffer->ReplaceText(" %c Title %d/%d, size %lld/%lld", + GetProgressChar(), + info.numImportedTitles, info.numTotalTitles, + info.importedSize, info.totalSize)->Render(); + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(40)); + + }while(info.state==nn::cup::CTR::UPDATE_STATE_STARTED); + // 謚懊¢縺滄圀縺ョstate縺熊AILED縺九←縺縺狗「コ隱 + if(info.state==nn::cup::CTR::UPDATE_STATE_FAILED){ + NN_UTIL_RETURN_IF_FAILED(info.lastResult); + } + s_scrollBuffer->AppendText(" - Imported (%lldmsec)", GetConsumedMillisec())->Render(); + + /***************** 繧「繝繝励ョ繝シ繝育オゆコ荳ュ ******************/ + SetTick(); + s_scrollBuffer->AppendText("")->Render(); + do{ + result = nn::cup::CTR::GetProgressInfo(&info); + NN_UTIL_RETURN_IF_FAILED(result); + s_scrollBuffer->ReplaceText(" %c Update Finalizing", GetProgressChar())->Render(); + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(40)); + }while(info.state==nn::cup::CTR::UPDATE_STATE_FINALIZING); + // 謚懊¢縺滄圀縺ョstate縺熊AILED縺九←縺縺狗「コ隱 + if(info.state==nn::cup::CTR::UPDATE_STATE_FAILED){ + NN_UTIL_RETURN_IF_FAILED(info.lastResult); + } + + /******************* 繧「繝繝励ョ繝シ繝育オゆコ *******************/ + s_scrollBuffer->AppendText(" - Finalized (%lldmsec)", GetConsumedMillisec())->Render(); + s_scrollBuffer->AppendText(""); + + return nn::ResultSuccess(); + } + + nn::Result UpdateSequence(bool *isHandledError) + { + nn::Result result; + nn::Result lastResult=nn::ResultSuccess(); + nn::hid::PadReader padReader; + + /********************* CUP縺ョ蛻晄悄蛹 *******************/ + s_scrollBuffer->AppendText("Initializing Cup Library")->Render(); + SetTick(); // 蛻晄悄蛹夜幕蟋句燕縺ョ譎る俣繧偵そ繝繝 + result=nn::cup::CTR::Initialize(s_updaterBuffer,sizeof(s_updaterBuffer)); + if(result==nn::cup::CTR::ResultUpdatePartitionNotFound()){ + s_scrollBuffer->AppendText(" - Update Partition Not Found (%lldmsec)", GetConsumedMillisec())->Render(); + s_scrollBuffer->AppendText("")->Render(); + *isHandledError=true; + return result; + } + if(result==nn::cup::CTR::ResultUpdateNotRequired()){ + s_scrollBuffer->AppendText(" - Already Updated (%lldmsec)", GetConsumedMillisec())->Render(); + s_scrollBuffer->AppendText("")->Render(); + *isHandledError=true; + return result; + } + if(result==nn::cup::CTR::ResultInvalidUpdatePartitionFormat()){ + s_scrollBuffer->AppendText(" - Invalid Update Partition (%lldmsec)", GetConsumedMillisec())->Render(); + s_scrollBuffer->AppendText("")->Render(); + *isHandledError=true; + return result; + } + NN_UTIL_RETURN_IF_FAILED(result); + + s_scrollBuffer->AppendText(" - Need Update (%lldmsec)", GetConsumedMillisec())->Render(); + s_scrollBuffer->AppendText("")->Render(); + + lastResult=UpdateCore(); + + // Initialize縺ォ謌仙粥縺励◆蝣エ蜷医ョ縺ソ縲∝阪ウInitialize縺吶k縺溘a縺ォFinalize縺悟ソ隕 + SetTick(); + s_scrollBuffer->AppendText("Finalizing Cup Library")->Render(); + NN_UTIL_RETURN_IF_FAILED(nn::cup::CTR::Finalize()); + s_scrollBuffer->AppendText(" - Complete (%lldmsec)", GetConsumedMillisec())->Render(); + s_scrollBuffer->AppendText("")->Render(); + + return lastResult; + } +} + +extern "C" void nnMain() +{ + NN_LOG("Start cup demo\n"); + nn::Result result; + Initialize(); + + /******************** CUP縺ョ螳溯。 *******************/ + bool isHandledError = false; + result = UpdateSequence(&isHandledError); + if (isHandledError == false && result.IsFailure()) + { + { + // 縺昴l莉・螟悶ョ蝣エ蜷医ッ縲ヽesult繧定。ィ遉コ + s_scrollBuffer->AppendText(" - Unhandled Error: 0x%08x", result.GetPrintableBits()); + s_scrollBuffer->AppendText("")->Render(); + } + } + + s_scrollBuffer->AppendText("")->Render(); + + for(;;) + { + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); + if(result.IsSuccess() || result == nn::cup::CTR::ResultUpdateNotRequired()) + { + s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 0, 1, 0, 1); + } + else + { + s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 1, 0, 0, 1); + } + s_RenderSystem.Clear(); + s_RenderSystem.SwapBuffers(); + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); + if(result.IsSuccess() || result == nn::cup::CTR::ResultUpdateNotRequired()) + { + s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 0, 1, 0, 1); + } + else + { + s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 1, 0, 0, 1); + } + s_scrollBuffer->ReplaceText("%c Finished", GetProgressChar())->Render(); + + if ( nn::applet::IsExpectedToCloseApplication() ) + { + nn::applet::PrepareToCloseApplication(); + nn::applet::CloseApplication(); + } + + } +} diff --git a/branches/0thNUP_No_NUP/CardCup/scrollBuffer.cpp b/branches/0thNUP_No_NUP/CardCup/scrollBuffer.cpp new file mode 100644 index 0000000..54de11e --- /dev/null +++ b/branches/0thNUP_No_NUP/CardCup/scrollBuffer.cpp @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: scrollBuffer.cpp + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include "scrollBuffer.h" + +using namespace std; + +char ScrollBuffer::s_buffers[MAX_BUFFER_LINE][MAX_BUFFER_CHARS]; + +char *ScrollBuffer::GetFormattedString(const char *fmt, va_list arg) +{ + static char formattedBuffer[MAX_BUFFER_CHARS]; + vsnprintf(formattedBuffer, MAX_BUFFER_CHARS, fmt, arg); + return formattedBuffer; +} + +ScrollBuffer *ScrollBuffer::Update() +{ + return this; +} + +ScrollBuffer *ScrollBuffer::AppendText(const char *fmt, ...) +{ + va_list vlist; + va_start(vlist, fmt); + + int nextPosition=(m_tail+1)%MAX_BUFFER_LINE; + if(nextPosition==m_head){ + // 繝倥ャ繝峨→繝薙Η繝シ縺ョ遘サ蜍 + if(m_head==m_currentView){ + m_currentView=(m_head+1)%MAX_BUFFER_LINE; + } + m_head=(m_head+1)%MAX_BUFFER_LINE; + + } + strlcpy(s_buffers[m_tail], GetFormattedString(fmt, vlist), MAX_BUFFER_CHARS); + m_tail=nextPosition; + NN_LOG("cup: %s\n", GetFormattedString(fmt, vlist)); + + // 繝薙Η繝シ縺ョ遘サ蜍 + if((m_currentView+MAX_DISPLAY_LINES)%MAX_BUFFER_LINE==m_tail){ + m_currentView=(m_currentView+1)%MAX_BUFFER_LINE; + } + + return this; +} +ScrollBuffer *ScrollBuffer::ReplaceText(const char *fmt, ...) +{ + va_list vlist; + va_start(vlist, fmt); + + NN_ASSERT(m_tail!=m_head); + strlcpy(s_buffers[(m_tail-1)%MAX_BUFFER_LINE], GetFormattedString(fmt, vlist), MAX_BUFFER_CHARS); + + return this; +} + +void ScrollBuffer::Render() +{ + // 謠冗判蜑榊ヲ逅 + m_render->SetRenderTarget(NN_GX_DISPLAY1); + m_render->Clear(); + m_render->SetColor(1.0f, 1.0f, 1.0f, 1.0f); + + // 繝ェ繝ウ繧ー繝舌ャ繝輔ぃ縺ェ縺ョ縺ァ縲∫オらォッ譚。莉カ繧定ェソ謨エ + int tail=(m_tailDrawText(0, (i-m_currentView)*FONT_SIZE, s_buffers[i%MAX_BUFFER_LINE]); + } + } + + // 謠冗判霆「騾 + m_render->SwapBuffers(); +} diff --git a/branches/0thNUP_No_NUP/CardCup/scrollBuffer.h b/branches/0thNUP_No_NUP/CardCup/scrollBuffer.h new file mode 100644 index 0000000..1d3563a --- /dev/null +++ b/branches/0thNUP_No_NUP/CardCup/scrollBuffer.h @@ -0,0 +1,55 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: scrollBuffer.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef SCROLL_BUFFER_H_ +#define SCROLL_BUFFER_H_ + +#include "demo.h" +class ScrollBuffer +{ +private: + enum + { + MAX_BUFFER_LINE=128, + MAX_BUFFER_CHARS=80, + MAX_DISPLAY_LINES=20, + FONT_SIZE=12 + }; + // 陦ィ遉コ譁蟄励ョ繝舌ャ繝輔ぃ (繝ェ繝ウ繧ー繝舌ャ繝輔ぃ) + static char s_buffers[MAX_BUFFER_LINE][MAX_BUFFER_CHARS]; + int m_head; + int m_tail; + int m_currentView; + + demo::RenderSystemDrawing *m_render; + + char *GetFormattedString(const char *fmt, va_list arg); + +public: + ScrollBuffer() : + m_head(0), m_tail(0), m_currentView(0) + {} + void Initialize(demo::RenderSystemDrawing *render) + { + m_render=render; + } + + ScrollBuffer *Update(); // 繧ュ繝シ蜈・蜉帙r蜿らァ縺励※縲√せ繧ッ繝ュ繝シ繝ォ縺吶k + ScrollBuffer *AppendText(const char *fmt, ...); // 譁蟄怜励r霑ス蜉縺吶k + ScrollBuffer *ReplaceText(const char *fmt, ...); // 譛譁ー縺ョ譁蟄怜励r鄂ョ謠帙☆繧 + void Render(); // 繝ャ繝ウ繝繝ェ繝ウ繧ー +}; + +#endif // SCROLL_BUFFER_H diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/Imp.rsf b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/Imp.rsf new file mode 100644 index 0000000..d16189f --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/Imp.rsf @@ -0,0 +1,16 @@ +BasicInfo: + Title : $(TITLE) + BackupMemoryType: None + Logo : Nintendo +# Companycode: "00" + ProductCode : "CTR-N-22MA" +# MediaSize: 2GB + +Rom: + HostRoot : $(ROMFS_ROOT) + + +TitleInfo: +# UniqueId: 0xffff6 + UniqueId: 0xf8015 + Version: 0 diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/OMakefile b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/OMakefile new file mode 100644 index 0000000..b794b2d --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/OMakefile @@ -0,0 +1,65 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakefile +# +# 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. +# +# $Rev: 31765 $ +#---------------------------------------------------------------------------- +SUPPORTED_TARGETS = CTR-*.Process.MPCore.* + +#demo繝ゥ繧、繝悶Λ繝ェ菴咲スョ謖螳 +#SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir ../common/include) +#SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir ../CTR_SDK/sampledemos/common/include) +#INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) + + +SOURCES[] = + ./source/main.cpp + ./source/test_data.cpp + ../common/sleep.cpp + ../common/common.cpp + ../common/shfnt.cpp + +TARGET_PROGRAM = CtrSaveDataMover_imp + +TITLE = CSM_imp + +#LIBS += libnn_am + +IMPORTEE_CIA = importee.cia + +#SRC_IMPORTEE_PATH = ../body/images/$(BUILD_TARGET_DIR)/$(BUILD_TYPE_DIR)/CtrSaveDataMover.cia +#縺ィ繧翫≠縺医★縲√槭せ繧ソ繝ェ繝ウ繧ー譎ゅッ逶エ縺翫″縲驟咲スョ譎ゅ↓謾ケ蜷 +SRC_IMPORTEE_PATH = CtrSaveDataMover_master.cia + +# 繝薙Ν繝峨ち繧、繝怜挨縺ォ romfs 繧剃ス懊k +#ROMFS_ROOT = $`(TARGET.getObjectDirectory)/romfsroot +ROMFS_ROOT = ./romfiles +DEST_IMPORTEE_PATH = $(ROMFS_ROOT)/$(IMPORTEE_CIA) +foreach(TARGET, $(BUILDER.getTargets $(SUPPORTED_TARGETS))) + $(DEST_IMPORTEE_PATH): $(SRC_IMPORTEE_PATH) $(makeDirectory $(ROMFS_ROOT)) + cp $< $@ +ROMFS_DEPENDENCIES = $(DEST_IMPORTEE_PATH) + +# 繝励Ο繧ー繝ゥ繝縺九i蜿らァ縺吶k縺溘a縺ョROMFS縺ョ繝代せ縺ィ繝励Ο繧ー繝ゥ繝ID繧貞ョ夂セゥ縺吶k +ROMFS_IMPORTEE_PATH = L\"rom:/$(IMPORTEE_CIA)\" +CCFLAGS += -DROMFS_IMPORTEE_PATH=$(ROMFS_IMPORTEE_PATH) + +ROM_SPEC_FILE = Imp.rsf +DESCRIPTOR = $(CTRSDK_ROOT)/resources/specfiles/repairtool.desc + +# 繝舌リ繝シ縲√い繧、繧ウ繝ウ +CTR_BANNER_SPEC = banner.bsf + +include $(ROOT_OMAKE)/modulerules + +build: $(DEFAULT_TARGETS) + \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner.bsf b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner.bsf new file mode 100644 index 0000000..a18d99e Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner.bsf differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/BannerModel_imp/COMMON/COMMON.cmdl b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/BannerModel_imp/COMMON/COMMON.cmdl new file mode 100644 index 0000000..3e85377 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/BannerModel_imp/COMMON/COMMON.cmdl @@ -0,0 +1,274 @@ +サソ + + + + + MetaData + + + + + + + + + ContentSummaries + + + + + + + + + + + + + + + + + + + + + + + + + + + + ModelDccToolInfo + + + OptimizationLogs + + + + + + + + + + + + Skeleton.Bones["*"].AnimatedTransform + + + + + + + IsVisible + + + Meshes["*"].IsVisible + + + IsBranchVisible + + + + + + + Materials["*"].MaterialColor.Emission + + + Materials["*"].MaterialColor.Ambient + + + Materials["*"].MaterialColor.Diffuse + + + Materials["*"].MaterialColor.Specular0 + + + Materials["*"].MaterialColor.Specular1 + + + Materials["*"].MaterialColor.Constant0 + + + Materials["*"].MaterialColor.Constant1 + + + Materials["*"].MaterialColor.Constant2 + + + Materials["*"].MaterialColor.Constant3 + + + Materials["*"].MaterialColor.Constant4 + + + Materials["*"].MaterialColor.Constant5 + + + Materials["*"].TextureMappers["*"].Sampler.BorderColor + + + Materials["*"].TextureMappers["*"].Texture + + + Materials["*"].FragmentOperation.BlendOperation.BlendColor + + + Materials["*"].TextureCoordinators["*"].Scale + + + Materials["*"].TextureCoordinators["*"].Rotate + + + Materials["*"].TextureCoordinators["*"].Translate + + + + + + + + + + + + + + + + + + + + 0 + + + + 0 1 2 1 3 2 + + + + + + + +-12 -6 6.5 +12 -6 6.5 +-12 6 6.5 +12 6 6.5 + + 0 0 1 + +0 0 +1 0 +0 1 +1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + Textures["banner_imp"]@file:Textures/banner_imp.ctex + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DccToolSourceNode + + BONE_00 + + + + Shapes[0] + Materials["MT_00"] + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/BannerModel_imp/COMMON/Textures/banner_imp.ctex b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/BannerModel_imp/COMMON/Textures/banner_imp.ctex new file mode 100644 index 0000000..83e936f --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/BannerModel_imp/COMMON/Textures/banner_imp.ctex @@ -0,0 +1,17 @@ +サソ + + + + + + + + + + + F5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QnlBeUJ5QXlBeUF5QXlBeUJ5QnlCeUF5QnlBeUJ5QnlCeUJ5QnlCeUJ5QnlCeUJ5UnlSeVJ5UnlCeVJ5QnlSeVJ6UnlSelJ5QnlCeUJ5QnlCeUJ5QnlCeUJ5QnlCeUJ5QnlSeUJ5UnlCeVJ5UnlSeVJ6UnpSelJ5UnpSeVJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelN6UnpTelJ6U3pTelN6U3pTelN6U3pTelN6U3pTelN6U3pjelN6YnpSelJ6UnpSelN6U3pTelJ6U3pSelN6U3pTelN6U3pTelN6U3pTelN6Y3pjemN6Y3pTemN6U3pjemN6Y3pjemN6Y3pjemN6Y3pjemN6ZHpjemN6Y3pjemN6ZHpjemR7ZHpke2R7ZHtke2R7ZHtke2R7ZHtke2R7ZHtke3R7ZHtzemN6Y3pjemR6ZHtkemR7Y3pkemN6ZHpke2R7ZHtke2R7ZHtke2R7ZHtke3R7dHt0e2R7ZHtke3R7dHt0e3R7dHt0e3R7dHt0e3V7dXt1e3R7dHt0e3R7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V8hXx1fIR7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1fIZ8hXyGfIV7dXyFe3V8hXyGfIZ8hnyFfIZ8hXyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfJZ8h3yWfIZ8hnyGfIZ8l3yXfJd8lnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyHfJd8l3yXfJd8lnyHfJd8l3yXfJd8l3yXfZd8l3yXfJd8l3yXfZd9l32XfJd9l3yXfZd9l32XfZd9l32XfZd9l32YfZh9qH2ofad9mH2XfZh9qH2ofah9qH2nfJd9l32XfZd9l32XfZd9l32XfZd9l32XfZh9l32Yfah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2pfah9qX6ofal+qX2pfql+uX65frl+uX6pfrl+qX65frl+uX65frh9qH2ofah9qX2pfql9qX6ofah9qH2pfal+qX65fql+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frp+uX65frl+uX65frp+un66frp+un66frp+un66fsp+yn7Kfrp+un66frp+yn7Kfsp+yX66frl+un66frp+un66frl+un66frp+un66frp+un7Kfrp+yn66fsp+yn7Kfsp+yn7Kfsp+yn7Kfsp/yn7Kf8p+yn7Kfsp+yn/Kf8p/y3/Kfsp/yn/Kf8p/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Kf8p/yn/Lf8t/y3/Lf8t/yn/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/23/Lf8t/y3/bf9t/23/bf9t/y3/bf8t/23/bf9t/23/bf9t/23/bf9t/3H/bf9x/23/bf9t/23/cf9x/3H/cf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/cf9t/3H/cf9x/3H/cf9t/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/23/cf9x/3H/cf9x/3H/cf9t/3H/cf9x/3H/bf9t/23/bf9t/23/bf9t/23/bf8t/y3/Lf9t/23/bf8t/y3/Lf8t/zH/bf9x/23/bf9t/23/bf9t/23/bf9t/23/bf8t/23/Lf9t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y37Lf8t/y3/Lf8t+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lf8t/y3/Lfst+y37Lfst+y37Lfst/y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Kfsp+yn7Kfsp+u37Kfsp+yn7Kfsp+un7Kfrt+y37Lfst+y37Lfst+yn7Lfst+y37Lfst+yn7Kfsp+yn7Kfsp+yn7Kfrp+un66frp+yn66fsp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp9un26fbp9un26frp9un26fbp9un26fbp9un66frp+un66frp9un66fbp+un66frp+un66fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un25fbp9un26fbp9un25fbp9uX26fbp9un26fbl9uX25fbl9uX25fal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2qfbl9uX25fbl9uX2pfbl9qX25fbl9uX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfKl9qX2pfal9qX2pfKl9qXypfKl8qXypfKh8qHyofKh8qXyofKh8qHyofKh8mHyofJl9qX2pfal9qXypfKl8qHypfal8qX2pfKl8qHypfKh8qHyofKh8qHyofKh8mHyYfJh8qHyYfKh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8l3yYfJd8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8l3yXfJd7mHyYfJh8l3yXfJd7l3uXe4d8l3uXfJd7l3uXe4d7l3uHe5d7l3uXe5d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe5d7h3uXe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4Z7h3uHe4d7h3uGe4Z7hnuGe4d7hnuHe4Z7hnuGe4Z7hnuGe4Z7hnuGe3Z6dnp2enZ6dnt2enZ7dnp2enZ6dnp2end7hnuGe4Z7hnuGe3Z7hnp2e4Z7hnuGe4Z7dnp2e3Z6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp1enZ6dXp1enV6dXp1enV6dXplenV6dXp1enV6dXplenV6Znp2enZ6dnp2enV6dXp1enZ6dnp2enV6dXp1enV6dXp1enV6dXp1emV6ZXplemV6ZXp1emV6ZXplemV6ZXplemV6ZXplemV6ZXpleWV5ZXllemV5ZXplemV5ZXlleWV5ZXlleWV5ZXlleWR5ZHlkeWV5ZXlleWV5ZHlkeWR5ZHllemV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5VHlkeWR5ZHlkeWR5VHlUeVR5ZHlkeWR5ZHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR4VHlUeVR5VHlUeVR5VHlUeFR5ZHlUeWR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR4VHhTeFR5VHhUeVR4VHhTeFR4U3hUeFR4VHhTeFN4U3hTeFN4VHhTeFR4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeEN4Q3hDeFN4U3hTeEN4Q3hDeEN4Q3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hDeFN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hCeEJ4QnhCeEN4QnhDeEJ4QnhCd0J4QndDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEJ4Q3hCeEJ4QnhCeEJ3QndCd0J3QndCeEJ3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3Qncyd0J3MndCdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3QndCd0J3QndCdzJ3Qncyd0J3QndCdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MXcxdzF3MXcydzJ3MncxdzF3MXcxdzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncxdzJ3MXcydzF3MncxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF2MXcxdjF3MXcxdzF2MXcxdjF2MXYxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF2MXYxdjF2MXYxdjF2MXcxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdiF2MXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYxdjF2IXYhdiF2IXYhdjF2IXYxdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYheUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlCeUJ5QnlBeUJ5QXlCeUJ5QnlCeUJ5QXlBeUF5QXlBeUF5QXlBeUF5QXlBeUF5QXlCeUF5QnlBeUJ5QnlCeUJ5QnlCeUJ5QnlCeUJ5QnlCeUJ5QnlCeVJ5QnlCeUJ5QnlSeVJ5UnlSeUJ5UnlCeVJ5UnlSeVJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelJ6U3pSeUJ5UnlSeVJ6UnpSelJ6UnlSelJ5UnpSelJ6UnpSelJ6UnpSelJ6U3pTelN6U3pSelJ6UnpTelN6U3pTelN6U3pTelN6U3pTelN6U3pTelN6U3pTelN6U3pTemN6U3pjemN6Y3pjemN6Y3pjemN6Y3pjemN6Y3pjemR6Y3pkemN6U3pTelN6U3pTemN6Y3pjelN6U3pTemN6Y3pjemN6Y3pjemN6Y3pkemR6ZHpke2N6ZHpjemR6ZHtke2R7ZHtkemR6ZHpke2R7ZHtke2R7ZHpke2R7ZHtke2R7ZHtke3R7ZHt0e3R7dHt1e3R7dXt0e3R7dHt0e3V7dXt1e3V7dHtke2R7ZHtke2R7dHt0e3R7ZHtke2R7dHt0e3R7dHt0e3V7dHt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXyFe3V8hXyGfIV8hnyGfIZ8hnyGfIV8hnyGfIZ8hnyGfIZ8hnyFe3V7dXt1e3V8hXyFfIZ8hXt1fIV7dXyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyHfJZ8hnyGfIZ8hnyHfJd8l3yXfJd8l3yXfJd9l32XfZd9l3yXfZd8l32XfZd9l32XfZZ8hnyGfId8l3yXfJd8l3yWfJd8lnyXfJd8l32XfJd9l3yXfZd9l32XfZd9l32XfZd9l32XfZd9l32YfZd9mH2nfZd9l32YfZh9mH2ofah9p32YfZd9mH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qX2ofal9qH2Yfah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qX6pfal+qH2ofah9qX2pfql+uX6pfrh9qX6pfal+qX65frl+uX65fql+uX6pfrl+uX65frl+uX65frl+uX65frl+uX66frl+uX65frl+uX66frp+un65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frp+un66frp+un65frp+un66frp+un66frp+un66frp+un66frp+yn66fsp+un66frp+un7Kfsp+yn7Kfsp+yn7Kfsp/yn/Kf8t/yn7Kf8p+yn/Kf8t/yn/Lf8p+un7Kfsp+yn7Kfsp+yn/Kfsp+yn7Kfsp+yn/Kfsp/yn/Kf8p/y3/Lf8t/y3/Lf8p/y3/Kf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/bf9t/23/bf8t/23/Lf9t/23/bf9t/23/Lf8t/y3/Lf8t/y3/Lf9t/y3/Lf8t/y3/Lf9t/y3/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/cf9t/3H/bf9t/23/bf9t/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/bf9x/23/cf9x/3H/cf9x/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9t/23/bf9x/3H/cf9x/3H/bf9t/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/23/cf9t/23/bf9t/23/bf9t/23/bf9t/23/Lf9t/y3/bf9t/23/bf9t/y3/Lf8t/23/Lf9t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y37Lfst/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lfst+y37Lfst/y37Lf8t+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfsp+yn7Kfst+y37Lfsp+yn7Kfsp+yn67fsp+yn7Kfsp+yn66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66fsp+yn7Kfsp+un66frp+un7Kfrp+yn66frp+un66frp+un66frp+un66frp+un26frp+un66frp+un26fbp9un66frp+un26fbp9un26fbp+un26frp9un26fbp9un26fbp9un26fbp9uX25fbl9un26fbp9uX25fbl9uX25fap9un26fbp9un26fbp9un26fbp9un26fbp9un26fbl9un25fbp9uX25fbl9qX25fal9uX25fbl9qX2pfal9qX2pfbl9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qXypfal8qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal8qXypfKl8qX2pfKl9qXypfKh8qXyofKl8qXypfKl8qHyofKh8qHypfKh8qXyofKh8qHyofKh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfKh8qHyofKh8qHyYfJh8mHyofJh8qHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8l3yYfJd7l3yXe5d7l3uHe5d7h3yXe5d7l3uHe4d7h3uHe4h8mHyYfJh8mHyXe5d8l3uYfJh8mHyXfJd7l3uXe5d7h3uXe4d7l3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7hnuGe4Z7hnuHe4Z7h3uGe4Z7hnuGe4Z7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7hnuHe4Z7hnuGe4Z7hnuGe4Z7dnuGe4Z7hnuGe4Z6dnp2enZ7hnt2e4Z6dnp2enZ6dnp2e3Z6dnt2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp1enV6dXp2enZ6dnp1enV6dXp1enV6dXp1enV6dXp1enV6dXp1enV6dXp1enV6dXp1emV6dXplemV6ZXplemV6ZXllemV5ZXplemV6ZXpleWV5ZXlleWV6dXp1enV6ZXplemV6ZXplenV6ZXplemV6ZXplemV5ZXpleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZHlleWV5ZXlleWV5ZHlleWR5ZXlleWV5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeVR5VHlUeWR5ZHlkeVR5VHlUeVR5VXlkeWV5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlUeWR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHhUeVR4VHhUeFR4VHhTeFN4U3hTeFR4U3hUeFN4U3hTeFN4U3hUeVR5VHlUeVR5VHhUeFR4VHlUeVR5VHhUeFN4VHhTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4Q3hTeFN4U3hTeFN4Q3hDeEN4U3hTeFN4U3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4U3hDeFN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4QnhDeEN4Q3hDeEN4QnhCeEJ4Q3hCeEN4QnhCeEJ3QndCd0J4QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QnhCeEJ4QnhCeEJ3QndCd0J4QndCeEJ3QndCd0J3QndCd0J3QndCd0J3Qncyd0J3MndCd0J3QndCdzJ3MncydzJ3Qncyd0J3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzF3MncydzJ3MncydzF3MXcxdzJ3MncydzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzJ3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdjF2MXcxdzF3MXcxdjF2MXcxdjF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYhdjF2IXcxdjF3MXYxdjF2MXYxdjF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2IXYxdiF2MXYxdjF2MXYxdiF2IXYhdiF2MXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXlBeUF5QXlBeUJ5QnlCeUF5QXlBeUJ5QnlCeUJ5QnlCeUJ5QnlCeUJ5UnlSeVJ5UnlCeUJ5QnlSeVJ5UnlSelF5QnlCeUJ5QnlCeUJ5QnlCeUJ5QnlCeUJ5QnlCeUJ5UnlCeVJ5UnlSelJ6UnpSelJ5UnlSeVJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpTelJ6U3pTelN6U3pTelN6U3pTelN6U3pTelN6U3pTelN6YnpSelJ6UnpTelN6U3pTelJ6UnpSelN6U3pTelN6U3pTelN6U3pTelN6Y3pjemN6Y3pTelN6U3pjemN6Y3pjemN6U3pjemN6Y3pjemN6Y3pjemN6Y3pjemN6Y3pjemR6ZHpke2R6ZHtke2R7ZHtke2R7ZHtke2R7ZHtke2R7ZHtzemN6Y3pjemR6ZHpkemR6Y3pjemN6ZHpkemR7ZHpke2R7ZHtke2R7ZHtke3R7ZHt0e2R7ZHtke3R7dHt0e3R7dHtke3R7ZHt0e3V7dHt1e3R7dHt0e3R7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V8hXt1fIR7dXt0e3V7dXt1e3V7dXt0e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1fIV8hXyGfIV7dXx1e3V8hXyGfIZ8hnyFfIV8hXyGfIZ8hnyGfIZ8hXyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8h3yWfIZ8hnyGfIZ8l3yXfJd8lnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfJd8l3yXfJd8lnyHfJZ8l3yXfJd8l3yXfZd8l3yXfJd8l32XfZd9l32XfJd8l3yXfZd9l32XfZd9l32XfZd9l32YfZh9qH2ofad9mH2XfZh9qH2ofah9qH2nfJd9l32XfZd9l32XfZd9l32XfZd9l32XfZh9l32Yfah9mH2ofZh9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qX2ofal+qX2pfql+uX65frl+uX2pfql+qX65frl+uX65frh9qH2ofah9qH2pfql9qX6ofah9qH2pfal9qX6pfql+uX6pfrl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frp+uX65frl+uX65frp+un66frp+un66frp+un66fsp+un7Kfrp+un66frp+yn7Kfsp+yX65frl+un66frp+un66frl+un65frp+un66frp+un66frp+yn7Kfsp+yn7Kfsp+yn7Kfsp+yn7Kfsp+yn7Kf8p+yn7Kfsp+yn/Kf8p/y3/Kfsp/yn7Kf8p/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Kf8p/yn/Lf8t/y3/Lf8t/yn/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/bf8t/23/Lf8t/y3/Lf9t/23/bf9t/y3/bf8t/23/bf9t/23/bf9t/23/bf9t/3H/bf9t/23/bf9t/23/bf9x/3H/cf9t/y3/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/3H/cf9x/3H/cf9t/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/23/cf9x/3H/cf9x/3H/bf9t/23/bf9t/23/bf9t/23/bf8t/y3/Lf9t/23/bf9t/23/Lf8t/zH/cf9x/3H/bf9t/23/bf9x/23/bf9t/23/bf9t/23/bf9t/y3/bf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lf8t+y3/Lfst+y37Lfst+y3/Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Kfsp+yn7Kfsp+u37Kfst+yn7Kfsp+un7Kfrt+y37Lfst+y37Lfst+yn7Lfst+y37Lfst+yn7Kfsp+yn7Kfsp+yn66frp+un66frp+yn66fsp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp9un26fbp9un26frp9un26fbp9un26fbp9un66frp+un66frp+un66fbp+un66frp+un66fbp+un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un25fbp9uX26fbp9un25fbl9uX25fbl9uX25fal9uX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2qfbl9un25fbl9uX2pfbl9qX25fbl9uX25fal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfKl9qXypfKl8qXypfKh8qHyofKh8qXyofKl8qHyofKh8mHyofJl9qX2pfal9qX2pfKl8qXypfal8qX2pfKl8qHypfKh8qXyofKh8qHyofKh8mHyYfJh8qHyYfKh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJd8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8l3yXfJd7mHyYfJh8mHyXfJd7l3uXe5h8l3yXfJd7l3uXe4d7l3uHfJd7l3uXe5d7l3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe5d7l3uXe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4Z7hnuGe4d7h3uHe4Z7hnuGe4Z7hnuGe4Z7dnuGe3Z6dnp2enZ6dnuGenZ7dnp2enZ6dnp2end7hnuHe4Z7hnuGe3Z7hnt2e4Z7hnuGe4Z7hnp2e3Z6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp1enZ6dXp1enV6dXp1enV6dXp1enV6dXp1enV6dXplenV6Znp2enZ6dnp2enV6dXp1enZ6dnp2enV6dXp1enV6dXp1enV6dXp1emV6dXplemV6ZXp1emV6dXplemV6ZXplemV6ZXplemV6ZXpleWV5ZXllemV6ZXplemV5ZXlleWV5ZXlleWV5ZXlleWR5ZXlkeWV5ZXlleWV5ZHlkeWR5ZHllemV5ZXpleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlkeWV5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5VHlkeVR5ZHlkeWR5ZHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR4VHlUeFR5ZHlUeWR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR4VHhUeFR5VHlUeVR5VHhTeFR4U3hUeVR4VHhUeFN4U3hTeFN4VHhTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeEN4U3hDeFN4U3hTeEN4Q3hDeEN4Q3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4Q3hTeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEJ4QnhCeEN4QnhDeEJ4QnhCeEJ4QndDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hCeEJ4QnhCeEJ3QndCd0J3QndCeEJ3QnhCd0J3QndCd0J3QnhCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3MndCdzJ3MncydzJ3MndCdzJ3MncydzJ3MncydzJ3QndCd0J3QndCdzJ3Qncyd0J3QndCd0J3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MXcxdzJ3MXcydzJ3MncydzF3MXcxdzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MXcydzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF2MXcxdjF3MXcxdzF3MXcxdjF2MXYxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdjF3MXYxdjF2MXYxdzF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYhdiF2IXYxdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYxdjF2MXYxdiF2IXYxdjF2MXYxdiF2IXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYhdjJ5QnlCeUJ5QnlCeVJ5UnlSeUJ5QnlCeUJ5UnlSeVJ6UnlSelJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelJ6U3pSeUJ5UnlSeVJ5UnpSelJ6UnlSeVJ5UnpSelJ6UnpSelJ6UnpSelJ6UnpTelN6U3pSelJ6UnpSelN6U3pTelN6UnpTelN6U3pTelN6U3pTelN6U3pTelN6U3pTelN6U3pjelN6Y3pjemN6Y3pjemN6Y3pjemN6Y3pjemR6Y3pkemN6U3pTelN6U3pTemN6U3pjelN6U3pTelN6Y3pjemN6Y3pjemN6Y3pkemR6ZHpkemN6ZHpjemR6ZHpke2R7ZHtjemR7ZHpke2R7ZHtke2R7ZHpke2R7ZHtke2R7ZHtke2R7ZHt0e2R7dHt1e3R7dXt0e3R7dHt0e3V7dXt1e3V7dHtke2R7ZHtke2R7dHtke3R7ZHtke2R7ZHt0e3R7dHt0e3R7dHt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXx1e3V8hXuFfIV8hnyGfIZ8hnyGfIV8hnyGfIZ8hnyGfIZ8hnyFe3V7dXt1e3V8dXyFfIV8hXt1e3V7dXyFfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyHfJZ8hnyGfIZ8hnyHfJZ8l3yXfJd8l3yXfJd8l32XfZd9l3yXfJd8l32XfZd9l32XfZZ8hnyGfId8l3yXfJd8l3yWfId8lnyHfJd8l3yXfJd8l3yXfZd8l32XfZd9l32XfZd9l32XfZd9l32YfZd9mH2XfZd9l32XfZh9mH2ofZh9p32YfZd9mH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2Yfah9mH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qX2ofal+qH2ofah9qX2pfql+qX6pfrh9qX2ofal+qX6pfrl+uX65fql+qX6pfrl+uX65frl+uX65frl+uX65frl+uX66frl+uX65frl+uX66frp+un65fql+uX6pfrl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frp+un66frp+un65frp+uX66frp+un66frp+un66frp+un66frp+yn66fsp+un66frp+un7Kfsp+yn7Kfsp+yn7Kf8p/yn/Kf8t/yn7Kfsp+yn/Kf8t/yn/Lf8p+un66frp+yn7Kfsp+yn7Kfsp+yn7Kfsp+yn7Kfsp/yn/Kf8p/yn/Lf8t/y3/Lf8p/y3/Kf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf9t/23/bf8t/y3/Lf9t/23/bf9t/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/bf8t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/cf9t/3H/bf9t/23/bf9t/3H/bf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/bf9t/23/cf9x/3H/cf9x/3H/cf9t/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9t/23/cf9x/3H/cf9x/23/bf9x/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/23/bf9x/23/bf9t/23/bf9t/23/bf9t/23/bf9t/y3/bf9t/23/bf9t/y3/Lf8t/23/bf9t/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t+y37Lfst/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y37Lfst+y37Lfst/y37Lf8t+y37Lfst+y37Lf8t+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfsp+y37Kfst+y37Lfst+y37Kfsp+yn7Lfsp+y37Kfsp+yn66fsp+un7Kfrp+un66frp+un66frp+un66frp+un66frp+un66fsp+yn7Kfsp+un66frp+un7Kfsp+yn66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66fbp9un66frp+un26fbp9un26fbp+un26frp9un26fbp9un26fbp9un26fbp9uX26fbl9un26fbp9uX25fbl9uX25fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un25fbp9uX25fbl9qX25fap9uX25fbl9uX2pfal9qX2pfbl9uX25fal9qX2pfal9qX25fal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qXypfal8qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal8qXypfKl8qX2pfal9qX2pfKl8qXyofKl8qXypfKl8qHyofKh8qHypfKl8qXyofKh8qHyofKh8mHyofJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyZfKh8qHyofKh8qHyYfKh8mHyofKh8qHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8l3yYfJd8l3yXe5d7l3uXe5d7h3yXe5d7l3uXe4d7h3uHe4h8mHyYfJh8mHyXfJd8l3uYfJh8mHyYfJd8l3uXe5d7l3uXe4d7l3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uGe4Z7hnuHe4d7h3uHe4Z7hnuGe4Z7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7hnuHe4Z7h3uGe4Z7hnuGe4Z7dnuGe4Z7hnuGe4Z6dnt2enZ7hnuGe4Z6dnp2enZ6dnp2e4Z7dnt2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp1enV6dXp2enZ6dnp2enV6dXp1enV6dnp1enZ6dXp1enV6dXp1enV6dXp1enV6dXp1emV6dXplemV6ZXplemV6ZXpleWV5ZXplemV6ZXlleWV5ZXlleWV6dXp1enV6dXplemV6ZXplenV6dXp1emV6ZXplemV6ZXplemV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZHlleWR5ZXlleWV5ZXlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlUeWR5ZHlkeWR5VHlUeVR5VXlkeWV5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5VHlkeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR4VHlUeFR5VHhTeFN4U3hTeFR4U3hTeFN4U3hTeFN4U3hUeVR5VHlUeVR5VHhUeFR4VHlUeVR5VHhUeFR4VHhTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4Q3hTeEN4U3hTeFN4U3hTeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4U3hDeFN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4QnhDeEN4Q3hDeEN4QnhCeEJ4Q3hDeEN4QnhCeEJ4QnhCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3Q3hCeEJ4QnhCd0J3QndCd0J4QndCeEJ4QndCd0J3QndCd0J3QndCd0J3Qncyd0J3MndCd0J3QndCd0J3MncydzJ3QndCd0J3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzF3MncxdzJ3MncydzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzJ3MncxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdjF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYhdiF2IXcxdzF3MXYxdzF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2IXYxdjF2IXYxdiF2MXYxdiF2IXYhdiF2IXYxdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYxdjF2MXYhdjF2IXYxdjF2MXYxdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdzF2MXcyeVJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpSelJ6UnpTelJ6U3pTelN6U3pTelN6U3pTelN6U3pTelN6U3pTelN6YnpSelJ6UnpSelN6UnpTelJ6UnpSelJ6U3pTelN6U3pTelN6U3pTelN6U3pjelN6Y3pTelN6U3pTemN6Y3pjemN6U3pjemN6Y3pjemN6Y3pjemN6Y3pjemN6Y3pjemR6ZHpkemR6ZHtke2R7ZHtke2R6ZHtke2R7ZHtke2R7ZHtjemN6Y3pjemN6ZHpkemR7Y3pjemN6ZHpkemR7ZHtke2R7ZHtke2R7ZHtke3R7ZHt0e2R7ZHtke2R7dHt0e3R7dHtke3R7ZHt0e3R7dHt1e3R7dHt0e3R7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V8dXt1fIR7dHt0e3V7dXt1e3V7dXt0e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1fHV8hXyGfIV7dXt1e3V8hXyGfIZ8hnyFfHV8hXyFfIZ8hnyGfIZ8hXyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyWfIZ8hnyGfIZ8h3yWfId8lnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfJd8l3yXfJd8lnyHfJZ8h3yXfJd8l3yXfJd8l3yXfJd8l3yXfZd9l32XfJd8l3yXfZd9l32XfZd9l32XfZd9l32YfZh9qH2Yfad9mH2XfZh9mH2ofah9qH2nfJd9l32XfZd9l32XfZd9l32XfZd9l32XfZh9l32YfZh9mH2ofZh9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofal9qX2pfql+qX65frl+uX2pfql+qX65frl+uX65frh9qH2ofah9qH2pfah9qX6ofah9qH2ofal9qX6pfql+uX6pfrl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frp+uX66frp+un66frp+un66fsp+un7Kfrp+un66frp+un7Kfsp+yX65frl+un66frp+un66frl+un65frp+un66frp+un66frp+yn66fsp+yn7Kfsp+yn66fsp+yn7Kfsp/yn7Kf8p+yn7Kfsp+yn/Kf8p/yn/Kfsp+yn7Kf8p/y3/Kf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Kf8p/yn/Kf8t/y3/Lf8t/yn/Lf8p/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/23/Lf8t/y3/Lf8t/23/bf9t/y3/Lf8t/23/bf9t/23/bf9t/23/bf9t/23/bf9x/23/bf9t/23/bf9x/3H/cf9t/y3/bf8t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/3H/cf9x/3H/cf9t/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/23/cf9t/3H/cf9x/3H/bf9t/3H/bf9t/23/bf9t/23/bf8t/23/Lf9t/23/bf9t/23/Lf8t/zH/cf9x/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/y3/bf9t/y3/Lf8t/y3/bf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y37Lf8t/y3/Lf8t/y3/Lf8t+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lf8t/y3/Lfst+y37Lfst+y3/Lf8t+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Kfsp+yn7Kfsp+y37Lfst+yn7Kfsp+yn7Kfrt+y37Lfst+y37Lfst+y37Lfst+y37Lfst+yn7Lfsp+yn7Kfsp+yn7Kfsp+un66frp+yn66fsp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un26fbp9un26frp9un26fbp9un26fbp9un66frp+un66frp+un66frp+un66frp+un66fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9uX26fbp9un26fbl9uX25fbl9uX25fbl9uX2pfal9qX2pfal9uX2pfal9qX2pfal9qX2qfbl9un25fbl9uX2pfbl9qn25fbl9uX25fal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qXypfKl8qXypfKh8qHyofKh8qXypfKl8qHyofKh8qHyofJl9qX2pfal9qX2pfKl8qXypfal8qX2pfKl8qXypfKh8qXyofKh8qHyofKh8mHyYfJh8qHyofKh8qHyYfJh8mHyYfKh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJd8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8l3yYfJd7mHyYfJh8mHyXfJd7l3uXe5h8l3uXfJd7l3uXe5d7l3uHfJd7l3yXe5d7l3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe5d7h3uXe4d7h3uHe4d7h3uXe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4Z7hnuGe4d7h3uHe4Z7hnuGe4Z7hnuGe4Z7hnuGe3Z6dnp2enZ6dnuGe3Z7hnp2enZ6dnp2end7hnuHe4Z7hnuGe4Z7hnuGe4Z7hnuGe4Z7hnt2e3Z6dnt2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp1enV6dXp1enV6dXp1enV6dXp1enV6dXp1enV6Znp2enZ6dnp2enV6dnp1enZ6dnp2enZ6dXp1enV6dXp1enV6dXp1enV6dXplemV6ZXp1enV6dXplemV6ZXplemV6dXplemV6ZXpleWV6ZXllemV6ZXplemV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlkeWV5ZXlleWV5ZHlkeWR5ZHllemV5ZXpleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5VHlkeVR5ZHlkeWR5ZHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5ZHlkeWR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR4VHlUeFR5VHlUeVR5VHhTeFR4U3hUeVR4VHhUeFN4U3hTeFN4VHhTeFR4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4Q3hDeFN4U3hTeFN4U3hDeEN4Q3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeEN4Q3hDeEN4Q3hTeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEJ4Q3hCeEN4Q3hDeEJ4QnhCeEJ4QndDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEJ4QnhCeEJ4QnhCd0J3QndCeEJ4QnhCeEJ3QndCd0J3QnhCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3MndCdzJ3MncydzJ3MndCdzJ3QncydzJ3MncydzJ3QndCd0J3QndCd0J3QndCd0J3QndCd0J3Qncyd0J3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncxdzJ3MXcydzF3MncydzJ3MXcxdzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzF3MXcxdzF3MXcxdzF3MncxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXYxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF2MXYxdjF2MXYxdjF2MXcxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdiF2MXYhdjF2MXYxdjF2IXYhdiF2IXYxdiF2IXYhdiF2IXYhdiF2MXYxdjF2MXYxdiF2MXYhdjF2MXYxdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYxdjF2MXYxdiF2MXYhdjF2MXYxdjF2MXYxdjF2MXcxdzF3MXcxdzF2MXcxdzF3MXcydzF3MncxdiF2MXYxdjF2MXYxdjF3MXYxdjF2MXYxdjF3MXYxdzF2MXcxdzF3MncydzJ3MncxdzJ3MXcydzJ3MncydzJ3MnpTelN6U3pTelN6U3pTelN6U3pTelN6U3pTelN6U3pjelN6Y3pTemN6Y3pjemN6Y3pjemN6Y3pjemN6Y3pkemN6U3pTelN6U3pTemN6Y3pjelN6U3pTelN6Y3pjemN6Y3pjemN6Y3pjemR6ZHpke2N6Y3pjemN6ZHpke2R6ZHtjemR6Y3pke2R7ZHtke2R7ZHpke2R7ZHtke2R7ZHtke2R7ZHt0e2R7dHt0e3R7dXt0e2R7dHt0e3R7dXt1e3V7dHtke2R7ZHtke2R7dHtke3R7ZHtke2R7ZHt0e3R7dHt0e3R7dHt1e3V7dXt1e3V7dHt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V8hXt1fIV8hnyGfIZ8hnyGfIV8hnyFfIZ8hnyGfIZ8hnyFe3V7dXt1e3V7dXyFe3V8hXt1e3V7dXyFfIZ8hXyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfJZ8hnyGfIZ8hnyHfJZ8l3yXfJd8l3yXfJd8l32XfZd9l3yXfJd8l32XfZd9l32XfZZ8hnyGfIZ8hnyXfJd8l3yWfIZ8lnyHfJd8l3yXfJd8l3yXfZd9l32XfZd9l32XfZd9l32XfZd9l32XfZd9mH2XfZd9l32XfZd9mH2ofZh9p32XfZd9mH2Yfah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9p32Yfah9mH2ofah9qH2ofah9qH2ofaeKiH2ofaa2VrVYfah9qH2ofah9qX2ofal9qH2ofaa1VrVZfal+qIuJfah9qX2ofal+qX6pfrl+qX65fal+qX6pfrl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX66frl+un65fql+uX6pfrl+uX65frl+uX65frl9qX65frl+uYynmXl+uX65frl+un66frp+un65frp+trVWtVp+un62tVa1Wn66frp+un66frp+yn66fsp+un66frp+un66fsp+yn7Kfsp+yn7Kfsp+yn/Kf8p/yn7Kfsp+yn/Kf8t/yn/Lf8p+un66frp+yn7Kfsp+yn7Kfrp+x7VXtmp+yn7ImYp+yn7Kf8p+yn/Kf8t/y3/Lf8p/yn/Kfsp+y3/Lf8mamJmKf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf9t/y3/bf8t/y3/Lf8t/23/bf9t/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/ImYiZi3/Lf8mZiZmLf8t/23/bf9t/23/bf9t/23/bf9mZiZqbf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/bf9t/23/bf9x/3H/cf9x/23/cf9t/23/cf9x/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/ZmZe2bH/cf9x/3H/cf9x/3H/cf9x/3H/Xtme2bH/cf9i2aoysf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9t/3H/cf9x/3H/cf9x/3H/bf9x/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9t/23/bf9t/23/cf9t/23/bf9t/23/bf9t/3H/bf9t/23/bf9t/23/Lf8t/23/bf9t/23/bf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t+y3/Lfst/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t+y37Lfst/y37Lf8t+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfsp+y37Kfst+y37Lfst+y37Kfsp+yn7Lfsp+y37Kfsp+yn66fsp+yn7Kfrp+un66frp+un66frp+un66frp+un66frp+un67fsp+yn7Kfsp+un66frp+un7Kfsp+yn66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un26frmMqn66frp+un66fbp9un26fbp+un26frp9un26fbp9un26fbp9un26fbp9uX26fbl9un26fbp9un26fbl9uX25fbp9un26fbp9un26fbp9un26fbp9uJh4mHp9un24mHiYen26fbp9uX25fbl9uX25fap9uX24mHl9qX25fal9qX2pfbl9uX25fal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal8qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qXypfal8qX2pfal9qX2pfKl8qXyofKl8qXypfal8qHyofKh8qHypfKl8qXypfKh8qHyofKh8qHyofJh8qHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyZfKh8qHyofKh8qHyYfKh8mHyofKh8qHyofJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJd8mHyXfJd7l3uHe5d7h3yXe5d7l3uXe4d7h3uHe4h8mHyYfJh8mHyXfJh8l3uYfJh8mHyYfJd8l3uXe5d7l3uXe5d7l3uHe4d7h3uHe4d7l3uHe5d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uGe4d7hnuHe4d7h3uHe4Z7hnuGe4Z7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4Z7h3uGe4Z7hnuGe4Z7h3uGe4Z7hnuGe4Z7dnuGe3Z7hnuGe4Z7hnt2enZ6dnp2e4Z7dnuGenZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2e3Z6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp1enZ6dXp2enZ6dollllZ6dXp1llWWVnp1enZ6dXp1enV6dXp1enV6dXp1enV6dXp1enV6dXplemV6ZXplemV6ZXplemV5ZXplemV6ZXplemV5ZXlleWV6dXp1enV6dXp1emV6ZXplenV6dYllemV6ZXpleWV5ZXplemV6ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWWXVZZFeWV5ZXlleWV5ZHlleWR5ZXlleWV5ZXlleWR5ZHlkeWR5ZHlkeWR5ZHlkeVR5ZHlUeWR5ZHlkeWR5VHlUeVR5VXlleWV5ZHlkeWR5ZHlkeWR5ZHlllkWHVHlkeWR5ZHlkeWR5ZHlkeVR5VHlUeVR5VHlkeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeFR5VHhTeFN4U3hTeFR4VHhUeFN4U3hTeFN4U3hUeVR5VHlUeVR5VHhUeVR4VHlUeVR5VHlUeFN4VHhTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4Q3hTeEN4U3hTeFN4U3hTeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4U3hDeFN4Q3hDeEN4Q3hDeFN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4QnhDeEN4Q3hDeEN4QnhCeEJ4Q3hDeEN4Q3hCeEJ4QnhCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3Q3hCeEN4QnhCeEJ3QndCd0J4QnhCeEJ4QndCd0J3QndCd0J3QndCd0J3Qncyd0J3MndCd0J3QndCd0J3MndCdzJ3QndCd0J3MncydzJ3Mncyd0J3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MXcxdzJ3MncydzF3MncxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzJ3MXcydzF3MXcxdzF3MXcydzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXYxdzF2MXcxdzF3MXcxdjF3MXcxdjF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYhdjF2MXcxdzF3MXcxdzF2MXYxdjF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYhdiF2IXYxdjF2MXYxdjF2IXYhdiF2MXYhdjF2IXYhdiF2IXYhdjF2IXYxdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYxdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYxdiF2MXYhdiF2IXYxdjF2MXYxdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdjF2MXYxdjF3MXcxdzJ3MXYxdzF3MXcxdzJ3MXcydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3QXcxdzF3MXcydzJ3MncydzF3MncxdzJ3MncydzJ3MncydzJ3MncydzJ3QndCd0J3Qncyd0J3MndCd0J3QndCd0N6U3pjelN6Y3pjemN6Y3pjemN6Y3pjemN6Y3pjemR6Y3pkemN6ZHpke2R7ZHtke2R6ZHtkemR7ZHtke2R7ZHtjemN6Y3pjemN6ZHpkemR6Y3pjemN6Y3pkemR7ZHpke2R7ZHtke2R7ZHtke3R7ZHt0e2R7ZHtke2R7ZHt0e3R7dHtke3R7ZHt0e3R7dHt1e3R7ZHt0e3R7dHt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3R7dHt0e3V7dXt1e3V7dXt0e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V8hXt1fIV7dXt1e3V7dXyGfIV8hnyFe3V8hXyFfIZ8hnyGfIZ8hXyGfIV8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8h3yWfId8lnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8l3yXfJd8lnyHfJZ8h3yXfJd8l3yXfJd8l3yXfJd8l3yXfZd8l32XfJd8l3yXfJd9l32XfZd9l32XfZd9l32XfZh9qH2V0zd9l32XfZeLhrVV8SXyNfEnfJd9l3yXfZd9l32XfZd9l32XfZd9l32XfZd9l32YfZd9lqZXfZXTRfEl8SXxJfEnfZXiOH2V8SXxJfEl8SXxJsRF8SXxJfEl8SXxJfEl8SXxJfEl8SXyNfEl4jamVZhl8SXxJfEl8SXxJsRF8SXxJeM18SWXZdM18SXxJfEl8SXxJcVF8SWnZZhkp1SnU6ZF4jSnVeI0pkOlQ7VDtUO1NKZUtUO1Q7VExDS1Q7VDtUO1Q7VDtUO1Q7VDtUSmRKZYjKenZ5h14zXxJfEl8SXxJqZV8jW1RfEl8SXxJfElxEXxJfEl8SXxJfEl8SXxJfEl8jXxJqhl8jXxJfEl8SXxJLVF4jO1RLVEtUWnVKZEplS1RLZEp1SmVKZUplSmVKdUp1XxJMRF8SXxJfEl8SXxJMQ18SXTNfEl8SXxJfEl8SXxJfEl8SXxJfEl8jXxJfEl8TXyNdM1plXxJfEl4jXiOKh5jKbTR6h18jXxJfEl8Sa2ZsVVp2XURfEl8SXxJfEkxDO1Q8QzxDO1RLVDxDO0Q8QyxDPEM8QzxDO0M8QztUS2VdM0tUXTNfEl8SXxJfEktUXTNLZV0zXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJfI18Sa1VsRF8jaYdqdl8SXxJfEl8SbTSZqV8SXyNfEl8SXiNfEl8SXxJfEl8SXxJbZV8SS1VaZVtVTERfI18SXiNfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8jXxJfEl8SXxJfEkwzPDM8Q7fst+yo26jbt/23/bjst+x6d5jKa2Z5mJjKqNuIuZjKx/3H/bf9x/3H/cf9x/3H/bfst/2o27fsx/2oysf9mZhbVWqGS1RaZXmYiblqdnmYO0RLVDxDS1RaZnmXWmVph6jKuOyYyqjbt/2ZmLfsqNuIuajbibmo27fst+y37LfsuOxtNHxFXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SbFVfEl8SXxJfEl8SXxJfEl8SXiNtNHmYeYdfEl8SbFRfEl8SXxJfEl8SXxJtNF8SXxJ8VV8SqNtsVV8SXxJfE18SanZadl8SXiNbZVtUTERLVF8SXxJfEl8SXxJeI18SXxJtNKjLXxJ8Vbfst+yo26jbXyN6h1xEaoeIuZjKeZiJqLf8t/247Lfsx/3H/bf8t/2o26jbe2ZfI6i6mZhfEl8SW2VadktUS2Vqdmp2WnZrVUxES2VfElxEWnZqh1p2aodfEl8SXxJfEl8SXxJfI18jbTRfI3mYeneJqXqHbFVeI8f9x/3H/cf9x/3H/cf9t/23/bf9XxJtRLf8t/yoy7fst/23/bf9t/23/bf9t/23/bf9t/237G4jt/y3/F8SXyNfEl8SXxJfEm4jmLpfEmtVXyNfEl8SXxJfEl00XxJeI6jbXxKYuV8SXxJfEl8SXxJ5mF8SWnZeI18SXxJfEl8St/y3/Lf8t/y3/Lf8t/y3/Lf8t/yJmLfst/y37LfsbiO37Lfst+y37Lfst+y37Lfst+y37F8SbiO37LfsqMu37HtmqNt6h5jKqNtfEpjKXxJrZomoXERph4moXxJph18SXxJfEl8SXxKKh6jbeod6dl8SXxJfEl8SendeI2mHXxK37Lfst+y37Lfst+y37Lfst+y37Kfse1W37JmpXyNfErfst+y37Lfst+yn7Kfsp+yZqafrXxJfI6frp+t7VafbbURfEl8SXxJfEl8SXxJeI18SXxJfEl8SbER5mGtVXTRfEl8SXxJfEl8Sa1VfEl8jbERfEl8SXxJfEl8SXxJfI6fsp+un66frp+un66frp+un66frp9un26frp+un26fbp+un66frp+un23tmp9ttM6frp+un26fbp9teI6fbXxKYypjKiKiIuZfap9uIyZjKaYd5l1plWXZ4qIi5aZd4qKfbp9uX26fbl9tfEpfaXxKYypfaiLmXypfaXxKXyl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJeI18jWXZfEl8jXxJfEmtVl8pfEm1EXyNfElp1XyNfEl8SXxJfEl8SXxJfEl8SXTRKZV0zSlRfEl8SXxJfEl0zO1RdMztDSlRMQztEO0NfEl8SXyJfEjtDO0M7QztDTSNfEk0zXxKXypfKiLmIuZfKl8qHyYfKbER4qF8SanZ4uIi5aJd4qJfKl8qXyofKl8qHyofKh8qHyYfJbERfE3mXeZdfEl8SXxJdM18SXyNZhltUSmVcRF8SXxJfEl8SS0RKZUxDOlRfEl8SXxJfEl8SXxJeI18SXiNeI0pUW1RZhltVXTNfI4fKh8mHyYfJh8mHyYfJh8mHyYfJXxJsRIfJh8l4qIe5h8mHyYfJh8mHyYfJeJdeI4fJh8l4qF0za1VfEl8SXxJfEl8SXxJfEl4jeKhfEmplXxJfEl8SXxJfElwzXxJNM2p2XxJqZV8jXxJfEl8SXxJZdlmGSmRKZV4jXxJeI18SanZrVV8SXxJ3uHe4eJd3uF8SXiNfEl8SeKhop10zWJZ3uHe4d7h3uHe4d7h3uHe4aKdoqFmGXERnqGl2XxJfEl8SXxJfEl8jXxJbVF4jSlRfEktDXxI8MzpTOkMrQytDXDNfEl4jXxJfEl8SXxJeIztDXiMrQztDXTNJdUtDXSN3uHe4d7h3uHe4Z7h3uGe4aYZ3uF8SXxJnuGe4W0Rnp2e4Z7hnuGe4Z7dnp2enZ6dnp2e4Z6dnp2enZ6dnp2enXxJfEl8SXxJfElwzXxJfEktDXxJfIl8SXxJfEl8SXxJYlliXWWVYhlenZ6dYlliWS0RJdUwzOlRIhViGSWRIdWenZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp1enXERfEl0jXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJnp2enV6dXp2enV6dXp1eWWJZXp1iGV5ZXp1eWV6dZZV8SXxJfEl8SXxJfEl8SOzNfEl8SXxJfEl8SKkNfEitCXiNYhl8SXTNXlleWSIVIhV8SXxJfEl8SSlRJZF4jTSNXllwzWlRfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJOIl8SPSJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SPDJfEl8SPSJfEiwhLCJfEi0iXxJfEl4jXxJfEkeFR4VIhTiFXxJfEl8SXxJKQzhkO0MpU0eFR5U4hUeFR5VHlUeFR4U4dDh0KWM6UziFSHRfIl8SXxJfEl8SXxI8MipCLCIbMl8SXxJfEl8SPiIsIj4SPSI7Q18STiJfEl8SXxJfEl8SXxJfEl8SXxJfEilTTSIqQkeVR4VHhUeFR4U3hUeFN4VJVDeFXxJfEjeFN4VcMzh0N4U3hTeFN4U3hTeFN4U3hDeFN4U3hElkN4U3hF4iXxJfEl8SXiNfEl8SXiNfEl8SKVNMMypCGkJfEl8SXxJfEjh0SlNLMzpDXxJfEl8SXxJeIjtDXxIaQl8SXxJfEl8SN4Q3hDeEN4Q3hDeEN4Q3hDeEN4ReIzhkN4Q3hDeEOGQ3hDeEN4Q3hDeEJ4Q3hCeEN4Q3hF8SXxInhCeETDMndF8SOWNfEihjKHQ6UyhjOkNfEilTXxI7MilTOkMZQjsyXxJfEl8SXxJfEihzXxIoY18SXxJfEl8SXxIpU04iOzInhCd0J4QndCd0J3QndCd0J3QndCd0KGMndCd0TDNfEid0J3QndCdzJ3MncydzJ3M5UzhjXxJfEidzJ3NeIjpDKGNeIkwzXxJfEl8SXxJfEl8SXxJfEl8SXxI6Ql4iOzJfEl8SXiJfEl8SXxJfEl8SGVJOIk4iXxJfEl8SXxJfEidzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3NeIl8SJ3MncydzJ3MncydzJ3MXcydzJ3NeIjpDF3MoU14iXxI5QxhjTSI6Ql8SXxJfEl8STiIrMj0iGjFfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxIsIjsyXxIKMSshF3MXcxdzF3MXcxdzF3MXcxdzF3NeIihjF3MXcxdjF2MXcxdzF3MXcxdzF3MXcxdzF3MXcxdjF3MXcxdjF2MXc18SOzJfEjwyGGIYYhhSGFJfEhpCGzEKMRlCGUIKMQlBF2IXYxhiGGIXYhdjF2IXYxhSGFIZQhhSGGIXYhhiF2IXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdiF2MXYhdiF2IXYhdiF2MXYhdiF2IXYhdiF2MXYxdjF2MXYxdjF2MXYhdjF2MXYxdiF2IXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYhdiF2IXYxdjF2IXYxdiF2MXYhdiF2MXYxdjF2MXYxdjF2MXYxdzF3MXcxdzF2MXcxdzF3MXcydzF3MncxdiF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF3MXYxdzF3MXcxdzF3MncydzJ3MncxdzF3MXcydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3Mncyd0J3MndCdzJ3QndCd0J3Q3dDd0N3QndCd0J3QndDd0N3Q3dDeEJ3MncydzJ3MndCd0J3QndCdzJ3Mncyd0J3QndCd0J3QndDd0J3Q3dDeEN4Q3hDeEN3Q3hDd0N4Q3hDeFN4Q3hTemR6Y3pkemR7ZHtke2R7ZHpke2R6ZHtke2R7ZHtke2R7ZHtke2R7dHt0e3R7dHt0e2R7dHt0e3R7dXt0e3V7dHtke2R7ZHtke2R7ZHtke3R7ZHtke2R7ZHtke3R7dHt0e3R7dHt1e3V7dXt1e3V7dHt1e3R7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1fIV8dXyGfIZ8hnyGfIV8hnyFfIZ8hnyGfIZ8hnyFe3V7dXt1e3V7dXyFe3V8hXt1e3V7dXt1fIV8hXyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyHfJZ8h3yWfJd8l3yXfJd8l32XfJd9l3yXfJd8l3yXfZd9l32XfZZ8hnyGfIZ8hnyXfJd8l3yWfIZ8lnyHfJd8l3yXfJd8l3yXfJd8l32XfZd9l32XfZd9l32XfZd9l32XfZd9l32XfZd9l32XfZd9mH2YfZh9p32XfZd9l32YfZh9qH2ofah9lfEofZXjNfEl8SXxJfEofZXUSHyWp2XxJfEl8SXxJ32YfZh9mH2ofah9qH2ofah9mH2ofah9qH2ofah9qH2ofZeLiH2Xi5XyNfEmp2XxKH2njJh9qIyWioWmV4uGmXXyM7VF8STEM7VDtUO1M7VF8SXyNfEl8SO0M7VF8STTM7VEplSmVZhlp2WYZpl10zSnVpl1tUXURrVV8SXxJfEl8SXxJfEl8SXxJfEl8SXxJfI18SSmVMM18SXxJNM14iXxJfEl8SXxJfEl8SXxJeI18SXxJNI00zXiNadTtUS2Rph1mGeKh4qFmGWYZ5qHmoeZeIyXtmiMqIuYi5iMqIyl1EXxJcRF8SXxJfEl8SXxJsVV8SbFVfEl8SXxJfEl8SeYeIuXmoeaiIyYjJeKiIuVmGaYdKZVp1aZd5qFmGaZdsVV8SbFVfEl8SXxJfEl8Sa2ZfEnmobFVfEl8Sa2VbVDtDO0NLVDtUO1RLZEtUWmVMREtUTERLVEtlWnZKZWqGWnVdRGqGbERfEl8SXxJfEmmXbER5mGxVXxJfEl8SXxJdM0tUXiNLVEplaoZLZVp2XxJLVExES1RLZVp2S2VadnmYbFV5mGxVXxJfEl8SXxJ5mHp2eZeJqV8SXxJ6dmtmXxJfEl8SXxJfEl8SXyNfEl8SXiNfEkxDPENOIzxDPDNfEl8SXxJfEk0zPENfEj0zXxJfEl8SXxJfEl8iXxJfEl8STTNfEl4zPEMsMzxDPDNfEl4jXFRMRDxDPEM7VDtETyJfEk4jXxJfEl8SXxJfEk0zXxJLVExEXxJfEkxETEQ8Q0tUPENLVFplaYdadnmYO0RLVUwzS2VqdnmYanaJqIi5qNuYuqjbt+yo27fse2aYyrjsmMq47Lf8bTS3/G00TiNLZV4jS2VqdomoWnZ5mF4jS1RMREtUWnZ5l1plaoeYyrjsmMqo27fsfFW37Jm6iLmo24mpqMq37LjcuOyo2200iahfEntmaoddRHmHWmZfEm4zXxJfEnmYWnZeM2tVXyNfEktUTDNfEl8SXyNfEktlS1RbVVxETTNfEl8jXxJfEl8SXyNfEl8SXxJfEl8SiZhfI5jKialfEl8Sa1VdNF8SXxJfEl8SXxJfEl8SXxJfEl8SXiNdM18SXxJNM0xEXxJfEl8SXxJadmmHW1Vqdl8SXxJfEl8SXTRcRExEXiNqdl8jXxNfEl8SXxJfEl8SXxJfEl8SXxJfEl00XyNbZV8SXxJfEk0zS0ReMzxETDNOIzxDO0Q8QzxDPEM8QzxDXxJfEl8SXxJfEl8SXxJfEk0zXxI7REtUXxJfEkxDTDNfEl8SXxJfEl8SXiNfEl4jTERfEk0zXxJfEl8iXxJPIktlXjM7RE0zXxJfEl8SXxI8Q0wzPDM8Q18SXxJfI18SXxJfEl8SXxJfEl8iXxJfEl8SXxJNMz0zXxJfEj0iLDMsMzxDLDM8Q00zXxI7RF8jLDM8QzxDO0M7RExES1RLZV0zWnZfI0tlW1VfEl00XxJfEkxDXxJfEl8jXxJfEl8SXxJeI18SXTNbVV8SXERfEl8SXERfI0tUTERfEkxEXxJfEl8SXxJfEl8SXxJfEl8jXxJfEktUXTNfEjwzTEM7Q00zO1Q7QztDO0RfIjtDTTM8QzxDPEM8QztDO0Q7REtUXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJOI04jPDNfEl8SXxJeI18STDM9MzxDPDMsMywzLDIsM00jTiJfEl8SXxJfEl8SXxJfEl8SXxJOI18SS1RMRF8SXxJNM04jTiJfEl8SXxJfEl8SXxJOI18SXxJOI00jXyI8QzxDO0NLVEplO0NLVFl2eZdadWmHO0NLVDtDS1RaZWmHWmVph4i5mMp4qJjKl8pfEpjKXxJ4qIjJeKiIyZjKXxKYyl8SO0NKVDtUSmVadWmHWXZpl0tUSmVLVEplWXZ5l1l2eZd4qIjJeKiYypjKXxKYyl8SiLmIyYi5iMmIyl4ziMp5l18SXxJfEl8STTM7Q00zO0RfEl8SXxJfEl4jO1RfEjtDO0M7QztDO1RMM18STDNfEjtUSlQ7VExDXTNfEl8SXxJfEl8SXxJfEl8SXyJfEl8SXxJfEmplW1RfEl8STEM8M14jXxJfEl8SXxJfEl8SXxJfEl8SPDM8M18SXyI8MztDXxJfEl8SXxJMMztDTDM8M18SXxJfEl8STDNOIztDXiJMM18SXxJfEl8SXxJfEl8SXxJfEl8SXxJfEk0zTiM7Q18SXiNfEkxDO0NeIjtDTSNMQztDO0M7QytDKzMrQytDXxJfEl8SXxJfEl8SXxJfEk0iXxIrQytDXxJfEjwzPDJfEl8SXxJfEl8STSNfEk4iTiNfEk4iXxJfEk8iXxJPEjtDOlQrQztDXxJfEl8SXxIsMitDLDIrMl8SXxJfIl8SXxJfEl8SXxJfEk8SXxJPEl8SXxI9Ij0iXxJOEi0iHCIsMisyLDIrMl4iXxJeIl8SLDIrMiwyKzJOIl8SOzNNI18SPDNfEjwyKzIrMisyKzJfEjwzXxJNIisyK0IrQytDK0NMMzwyXxJfEl8SXxJfEl8iXxJfEl8SXxJfEl8SXiNfEk4iXxJfEitDK0M7QytDXxJNIztDK0M7QytDK0MrQ18SXxJNI18SXxJfEl8SXxI6Q00jOkM6U18SXxI6QzwzXxJfEl8SXxJfEl8SXxJfEjtDTiIqQ18iXxJfEl8SXxJNIipDTSIrMjpUSWQqQzlkPiIrMj4iHDIrQzpTKzI6U18SXxJfEl8SXxJfEl8SXxJfEl8SPDI9Il8SXxItIi0iPiIcIk4iHCIrMipTKzIqQ04SHCIcIRwyKzIqQysyKkNIhViWSHVYhleWWWVXllllSXRIhTlkSIVYlliFWJZYll8SXxJfEl8SXxIrMl8SPDJfEl8SXxJfEl8SPDJfEk0iOWRIdTlkSHVYhliWSIZIljlkSHU5ZEh1SIZIlkiGSJZfEl8SXxJfEl8STiJfEl8SXiNfEklkSkNfEl8SO0M7MhsyXxIbMk8SXxJfEl8SXxIbMj0iGzIcIl8SXxJOEl8STxIcIT4SHCEtIV8SPhJfEj0iHCEcIRwhPhJfEk4SXxIbMhsyGzIbMhsyGzIbMhsyKzIbMhsyGzIbMhsyGzIqQhsyGzEbMhsyTxJfEl8SXxIqQjwyKkMqU18SXxI7MzsyXxJfEl8SXxI+Ej4iPhI+Il8SXxJfEl8SPhI+Ii0iLSJfEl8SXxJfEk0iGkI9IhsyXxJfEl8SXxJOIhsxXxI9Il8SXxJfEl8SLSIcISwiHCFfEl8SPDIsIhwhHCEbMRshXxJfEj4iXxJfEl8SXxJfEhwhThIcIRshXxJfEiwiPSIaMhoyGzIbMk4iXxJPEl8SGzEbMiwiTiJfEl8SXxJfEl8SLDJfEiwiXxJfEk4iXxJfEhwhXxIbMT0iXxIcIV8SXxJfEl8SXxJfEl8SXxJfEl8SXxJOEj0iXxIsIhwhGyFOIhsxKzIbMRshThIbIRwhGzEbIRshGyEbIRshGyEbMV8SPCJfEk4iGjI9IhsxTiJfEl8SXxJfEiwhXxJfEl8SXxJfEl8SXxJNIj0iPCI9Il8SXxJfEk4iGzE9IhshPSJfEl8SXxJfEl8SXxJfEl8SPSJfEhsxLCJfEk8SPSIcIV8SLCE+EgshCyEcIQshCyEcIQwhDCEMIQwhCyELIQshXxJfEl8SXxJfEl8SXxJfEl8SXxJfEl8SXxJOEl8SLRFfEl8SXxJfEl8SXxJOEhwhPRIcIQwQDBAMEC0RDBFfEl8SXxI+El8SXxJfEl8SXxIbIU4SCyELMV8SXxIsIT0iTxI+El8SXxJfEl8SXxJfEl8SXxJOEj4SXxJOEi0RDCEcIQshDCELIV8SXxJfEl8SLREMIU4SCyFfEl8SXxJfEl8SHCFfEgshCyELIQshCyFfEgshXxIcIQshCyELIQshThILIS0hCyFfEl8SXxJfEgshCyELIQshXxJfEiwhLCFfEiwhXxI9IgshCyELIQshXxJOEiwhGyELIQshCyEKMQshCyELIQshCjEKMQoxCjELIQshCyEKMQoxCTEKMRlCGUIYUhlCGFIYUhdiGFIXYhlCGFIYUhhSGGIXYhhiF2IKMQoxCjEJQRlCGFIYUhhSCjEZQgoxGUIYUhhiGFIYYhhSGGIXYhdiF2IXYhdiF2IXYhdjF2MXYxdjF2IXYxdiF2MXYhdjF2MXYhdiF2IXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYxdiF2MXYhdiF2IXYxdjF2MXYxdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYhdjF2IXYxdjF2MXYxdjF2MXYxdjF2MXYxdzF2MXcxdjF2MXYxdjF2MXcxdzF3MXYxdzF2MXcxdzF3MXcydzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3QXcxdzF3MXcxdzJ3MncydzF3MXcxdzJ3MncydzJ3MncydzJ3MncydzJ3MndCd0J3QncydzJ3MndCd0J3QndCd0J3MndCd0J3QndDd0J3Q3dCd0J3QndCd0N3Q3hDd0N4Q3hDeEN4Q3hDeEN4U3hTeFN4Q3hDeEN4U3hUeFN4VHhSd0N3QndDd0N4Q3hDeEN4Q3dDeEN3Q3hDeEN4Q3hDeFN4Q3hTeFN4VHhUeFR4VHhTeFR4U3hUeFR4VHhUeFR4VHtke2R7ZHt0e3R7dHt0e3R7ZHt0e3R7dHt1e3R7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3R7dHt0e3R7dXt1e3V7dXt0e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V8hXx1fIV7dXt1e3V7dXx1fIV8hnyFe3V8hXt1fIV8hnyGfIZ8hXyFfIV8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfId8lnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8h3yXfJd8lnyGfJZ8h3yXfJd8l3yXfJZ8l3yXfJd8l3yXfJd8l32XfJd8l3yXfJd8l32XfZd9l32XfZd9l32XfZh9l32Yfad9l32XfZd9mH2Yfah9qH2nfJd8l3yXfZd9l32XfZd9l3yXfZd9l32XfZd9l32YfZd9mH2XfZh9qH2ofah9qH2ofZh9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofaeLloqIjJeLiH2ofal9qX2ofaiMmX2ofah9qH2ofah9qH2ofah9qX2ofah9qH2ofah9qX6pfal+qX6pfal+qX65fal9qX65frl+qX65frl+uX65frl+uX61mGSmVpl1p2O1Q7Q0plO1R4qGmXiMl4qFp2SmVpl1mGO0M7QztDO0M7QztUO0M7VEtkO1Radlp1O1RLVFp1WnaH2ojJl9uX2ni5eKiI2ojKl+uX65frl+uX25fbp+un62mXaZeIuYi5aZdpl4i5iLmX25jap+un65jamNun66frS1RKZUtUSmVadmmXWoZ5mEplWnZahmmXaZd4qHmoiLl5qHmoeKh5qGmXWnZ5mGqGiLmIuZjKmMp5qWmXiMqIuXmoiLmIypjKiMqY2pjbp+uX26frp+yn7Kfst+yn7Lf8qNuo26fsp+yY25jKp+uo27f8t/y3/Lf8t+y37Lf8t/xLZUtlWnVaZUtlWnZadWqGaoZadnmYeZhqhmmXeZiJqHmYial5mIi5ial5mIi5eaiJqYi5mLqYypjKiLmo25jKiLmIuajbmNuIuZjKqNuo26fsp+y3/Lf8t+y37Lf8t/2Y26jbqOy37KjbqNu37Lfst/y3/Lf9t/23/Lf9t/23/Wp2W2Vph1p2S1VLVFplWmV5mGqHiLmJqGqHaod5mHmoS2VaZVp2anZaZUtlanZadmmHeZiJqIm5eZhph4m5iamYypjKqOyo25i6mLqo26jbt+y37Mf9x/237Lfsx/3H/ZjKmMqo27jsmMqYyrjsqNu37Lfsx/3H/bf8t+zH/cf9S1VLZVplWmVaZWqHWnZqh2qHaoZ5qHmYaod5mImoibmJqJjKiamYyqjsuNyo7LjsiLmoy5jKqNu47Lfst+y37JjKmLqo26jbmLqYyqjbqNy37Lfsx/3H/bfst+zH/cf9qNu37Lfst+y37Mf9t/3H/bf9x/3H/cf9x/3H/cf9x/2YyompqNuIuWmHWnZ5mGp2qNuYyrfsqNuJqXmXmMqJqUtlS1RaZUtVS1Q7VEtUO1RadlpleZhqh0tlS1Vqdlp2t/237Mf9t/2o25jKt+yo28f9x/3H/cf9t/23/Mf9t/2YuYmpqNuYynmYeZiYypi6t+y37Lf9t/2o26jbt+y37DtEPEQ7VEtUO0Q7VEtUS2VLVUtlWnZqdlplWnZph3mYS1RLVFplWmVLVEtUWmVLZWqHaYeJqImpaYdqdomoeZh5mHmomLqYyompmLmoyqjbqNuo3Lfst/y37Lfst/y3/JjKmMqo27frmMqYuqjbqNu37Lfst/y3/Lfst+y3/LfsO0Q8Q0tUO1Q8MzwzO0M7RFp2WmV5l2mHS1VLVWp2anY8QztUO1RLVUtVWmVaZVp2SmVadmqGaYdqhmmXeZiIqYi5iamoy5jKeah5mJjKmMqn7Kfst+y37Kfbp9u37LfseaiIqZjKmMqIuZjKmMqo26fbp9u37Lfsp+un7Lfst+xaZUplanZadktUO0RaZUtVeZdph4ipiKhphlp2eZh5lztDO0RLVEtUS1RKZUplWnZadVp2aYdpl2mGaZd5mIiomMqYyqfbqNuIuYi5qNuYyqfrp+u37Lfsp9un26fsp+uIqYi5mMqYyoi5mMqYypfbp9un26frp+un26fbp+un61plSmVphlp2S1Q7VFplSmV5l3mXiLmIuWmHWnZ4qGmXO0M8QztUO0Q8QztDO0M7VEplSlRphlp2S1RKZVp1WnaYypjKp9uX24i5iKiYypjKp9un26frp+un25fap9un23mYaZeIuYi5aZdpl4ioiKiXypjKp9un25jKmMqX25faS1RKZUpUWmVZdnmXaYZ4mEplWXZZdmmHaYd4qHioiLmIuYjKiLmXyofKiLmXyoi5iLmXyojJl8qXyoi5l8qHyXmXeKiIuYi5iLmIyYjJl8qXypfKl9uX2pfal9qX2pfal8qX2pfal9qX2pfKl9qXypfal9qX2pfal9qX2pfal9pol1l2eJhZhkpUO0NKZTtUeKhpl4i5eKhZdUpkaYZZdjtDK0M7QztDK0M7QztDO0M6VDtUSnVKZTtTO1RKZUpliLl4uIfKh8l4qGiXiLl4qJfKl8qX2pfKh8mHyYfKh8pph1mGeKh4qFmGWYZ4p3ioh7mHuYfJh8mIuYe5h8mHyStDK0M7QztDO0M7QztTOlQ7VDpUSmVJdUpkSmVZdlmGO0M7QzpUOlQ7QytDOlQ7U0l1SXVZhliGSXVKZFmGWXZZhmmGeKh4qGiXaJd4qHi4d7l3uYfJh8mHuYe5h8mHyWinaKd3uHe4aJdol3i4eKh3uXe5h8mHyXe4d7h3yXe4KzIsMitDKzMsMiwyKzIrMjpUOlNJdUllO0M7Q0pkSmQsMitDK0M7QytDOlM6UzpUOlM6VElkSXU6ZElkSXVJdViGWYZop2inWXZZdWiXaJd3uHe4d7h3uHeoZ6h3uHe4WYZYhmiXaJdYhliWaKdop2eoZ6h3uHe4Z6hnqHe4Z7g6UzpDOlQ6VDpDOkM6UzpTSWQ5ZEl1SXU5ZDlkSXVJdTpTOlM6VDpUOlMqQzpUOlM5ZElkSXVIdUlkOWRIdUl1WIZYhmiXaJdYhliGaJdol2enZ6dnuGe4Z6dnp2enZ6dYhliGWJdYl1iGWIZYl1iWZ6dnp2enZ6dnp2enZ6dnpytCKzIqQysyHCIcISsyGzI6VCpTSXU5ZCtDK0I6VDpTHCEbMhsyKzIrQipTKkM6UytCKkM6UzlUKlM5ZDlkSXVIhUh1WJZYlkl1SXRYhkiGV6dXl2enZ6dXlleWV6dXpzl0SXVIhUiFSHVIhUiGSJZXlleWV6dXpleWV5ZXpleWOWRIdTlkSHVIlleWSJZHlkh1SIVIhUiFV5ZXlleWV5ZIhTl0SIU4dClTKkM5ZCpDSIVIdUeWSIU5ZClTOHQ5ZEiGV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWR5ZIhUeWR5ZIhTh0R4VIhUeWR5ZHlkeWR5VHlUeWR5YrMhsyKkIqQipCKkMqQylTKlMqUzlkOWMpUzljOWQ4dClTKVM5ZDhkKVMpUzhkKWM4ZDh0OHQ4hTh0OGQ4hDh0OHQ4dEiFOIU4dDh0OIVIhUeFR4VHlUeVR4VHhUeVR5U4hTeFR4VHhTeFOIQ3hTeFR4VHhUeVR5U3hTeFR4U3hSpCGzIpUxpCGzIbMRoyGzIpUylDOGQpUypCGkIpUylTGzEbMRsyGjIbMRsxGjIaMhpCGkIpUylTKUIaQilTKVM4dDhkOIQ4dChjKGM4dDh0N4U3hDeFN4U3hDeEN4U3hShjKGM4dDh0KGMoYzh0OHQ3hDeEN4Q3hDeEN4Q3hDeEGzEbIRsyGzEbIRshGyEbIRpCGjIpUhlCGzEbMRpCGkIbIRshGyEbMRsxGjEaMhpCGjEaMhpCGUIaQhlSGVIoUyhjKVModChjKVMpUyhjKGM3dCd0N4Q3hCh0KHQ3hDeEKVMoUyhjKGMoYyhjKHMncyd0J3QndCd0J3QndCd0J3QaMhoyGUIZQhoxGyEaMhoxGVIZUihjKGMZQhpCGFIZUgshCyEbMRsxCyELMRsxGjEaMhoxGUIZQhoyGUIZQhlSKGMoYydzJ3MoYyhjJ3MoYyd0J3MndCdzJ3MncydzJ3MYUxhSKGMoYxhTGGMoYyhjJ3MncydzJ3MncydzJ3MncxoxGjEaQhlCGjELIRpCGjEZQhlSGFIYUhlCGUIYUhlSCyELIQsxCyEMIQshCyELIRoxCjEZQhlBCzELMRoxGjEYYxhjJ3MncxhjGGInYxhjJ3MncydzJ3MncxdzJ3MncxhSGVIYYxhSGUIZQhhSGFIXYxdjF3MXcxhjGGMXcxdjCyELIQshCjELMQoxCjEKMQoxCjEaMRlBCjEKMRlCGUIKIQshCjEKMQshCjEKMQoxCjEKMRlCGUIKMQkxGUIZQhlCGUIYUhhSGFIYUhhiGGIYYxdjF3MXYxdiF2MXYxdjGFIYUhhiGGIYUhhSGGIYYhdjF2IXYxdjF2IXYhdjF2MJMRlCCUEZQhhSF2IYUhdiGUIYUhhSGFIYUhdiGGIXYhdjF2IXYxdiF2MXYhdiF2IXYxdiF2MXYhdiF2IXYhdiGFIYYhhiF2IXYhdiF2IXYhdiF2IXYxdjF2MXYhdjF2IXYhdiF2MXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYxdiF2IXYhdiF2MXYxdjF2MXYxdjF2MXYxdzF3MXcxdzF2MXYxdjF3MXcxdzF3MncxdiF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF3MXYxdzF2MXcxdzF3MXcydzJ3MncxdzF3MXcydzJ3MncydzJ3MXcydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3QndCd0J3Q3dCd0N3QndCd0J3QndDd0N4Q3dDeEJ3MncydzJ3Mncyd0J3MndCdzJ3Mncyd0J3QndCd0J3QndDd0J3Q3dDd0N4Q3hDeEN3Q3hDd0N4Q3hDeEN4Q3hTd0N4Q3hDeEN4Q3hTeFN4U3hDeEN4Q3hTeFN4U3hUeFR4VHhUeFR4VHhUeVR4VHlkeFR4VHhUeFR5VHlkeWV5Y3hDeFN4U3hTeFR4VHhUeFN4U3hTeFR4VHhUeFR4VHhUeFR5VHhUeWR5ZXlkeWV5ZHlUeWR5ZHlleWV5ZXlleWV7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1e3V7dXt1fIV7dXyFfIZ8hnyGfIV8hXyFfIZ8hnyGfIZ8hnyFe3V7dXt1e3V7dXuFe3V8hXt1e3V7dXt1fHV8hXyGfIV8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyWfId8l3yXfJd8l3yXfJd9l3yXfJd8l3yXfJd9l32XfZZ8hnyGfIZ8hnyHfJZ8l3yWfIZ8hnyHfJd8l3yXfJd8l3yXfJd8l32XfZd9l32XfZd9l32XfZd9l32XfZd9l32XfZd9l32XfZd9mH2XfZh9p32XfZd9l32YfZh9qH2Yfah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9p32YfZd9mH2Yfah9qH2ofah9mH2ofZh9qH2ofah9qH2ofah9qH2ofah9qH2ofal9qH2ofah9qH2ofal9qX2pfqh9qH2ofal9qX6pfrl+qX64fal9qX2pfql+qX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65fal+qX6pfrl+uX65frl+uX6pfrl+uX65frl+uX65frl+uX65frl+uX66frp+un65frl+uX66frp+un66frp+uX66frp+un66frp+un66fsp+un66frp+un66fsp+un7Kfsp+yn7Kfsp+yn/Kf8p/yn7Kfsp+yn7Kf8p/yn/Kf8p+un66frp+un7Kfsp+yn7Kfrp+yn66fsp+yn7Kfsp+yn7Kf8p/yn/Kf8t/yn/Lf8p+yn/Kf8t/y3/Lf8t/y3/Kf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/bf8t/y3/Lf8t/23/bf9t/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/23/Lf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/3H/bf9t/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/bf9t/23/bf9t/3H/cf9x/23/bf9t/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/bf9x/3H/cf9x/3H/bf9x/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/23/bf9t/23/cf9t/3H/cf9t/23/bf9t/3H/bf9t/23/bf9t/y3/bf9t/23/bf9t/23/bf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lfst/23/bf9t/23/Lf8t/y3/Lf9t/y3/bf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t+y37Lfst/y3/Lf8t/y37Lfst+y37Lf8t+y37Lfst+y37Lfst+y3/Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Kfst+y37Lfst+y37Kfst+yn7Lfst+y37Lfsp+yn7Kfsp+yn7Kfrp+yn66frp+un66frp+un66frp+un66frp+un67fsp+yn7Kfsp+yn66fsp+un7Kfsp+yn66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp9un26fbp+un66frp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbl9un25fbp+un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9uX25fbl9uX25fbp9uX26fbl9uX25fbl9uX2pfbl9uX25fbl9qX2pfal9qX25fal9uX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX25fal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal8qX2pfal9qX2pfal8qXypfKl9qX2pfal8qXyofKl8qHypfKl8qXypfKh8qHyofKh8qHyofKh8qHyYfJh8mHyYfJh8qHyYfJh8mHyYfJh8mHyZfKh8qXyofKh8qHyofKh8mXyofKh8qHyofKh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyXfJd7l3uXe5d7mHyXe5h8l3uXe5d7h3uXe4h8mHyYfJh8mHyYfJh8l3yYfJh8mHyYfJh8l3yYfJd7l3uXe5d7l3uXe4d7h3uHe4d7l3uHe5d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7hnuHe4d7h3uHe4d7hnuHe4Z7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uGe4Z7hnuGe4Z7h3uGe4Z7hnuGe4Z7hnuGe3Z7hnuGe4Z7hnt2enZ6dnp2e4Z7hnuGe3Z7dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2e4Z6dnt2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp2enZ6dnp2enZ6dXp2enV6dnp2enZ6dXp1enV6dXp1enZ6dXp1enV6dXp1enV6dXp1enV6ZXp1emV6ZXplemV5ZXplemV6ZXplemV5ZXpleWV6dXp1enV6dXp1emV6dXplenV6dXp1enV6ZXplemV6ZXplemV6ZXlleWV5ZXlleWV6ZXllemV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlUeWR5ZHlkeWR5ZHlUeWR5VXlleWV5ZXlkeWR5ZHlkeWV5ZHlleWR5ZHlkeWR5ZHlkeWR5ZHlkeVR5VHlUeVR5VHlkeWR5ZHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeFR5VHhUeFN4VHhTeFR4VHhUeFN4U3hTeFN4U3hUeVR5VHlUeVR5VHlUeVR4VHlUeVR5VHlUeVR4VHhUeFR4U3hUeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4U3hTeFN4U3hDeEN4Q3hDeFN4U3hTeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4QnhDeEJ4Q3hDeEN4Q3hCeEJ4QnhCeEJ4QndCeEJ3QndCd0J3QndCeEJ3QndCd0J3QndCd0J3Q3hCeEN4QnhCeEJ3QnhCd0J4QnhCeEJ4QnhCd0J3QndCd0J3QndCd0J3QndCd0J3MndCd0J3QndCd0J3MndCdzJ3QndCd0J3QncydzJ3Mncyd0J3QndCdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncxdzJ3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzJ3MncydzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF2MXYxdzF3MXYxdzF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdzF3MXcxdjF2MXcxdjF3MXcxdzF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYhdiF2MXYxdjF2MXYhdjF2IXYxdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYxdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYxdiF2MXYhdiF2IXYhdjF2MXYxdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdjF3MXYxdjF2MXcxdzF3MXcydzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3QXYxdzF3MXcxdzJ3MXcydzF3MXcxdzJ3MncydzJ3MncydzJ3MncydzJ3MndCdzJ3QncydzJ3Mncyd0J3QndCd0J3MndCd0J3QndCd0J3Q3dCd0J3QndCd0N3Q3dDd0N4Q3dDeEN4Q3hDeEN4U3hTeFN4Q3hDeEN4Q3hTeFN4VHhSd0J3QndDd0N3Q3hDeEN4QndDd0N3Q3hDeEN4Q3hDeEN4Q3hTeFN4U3hUeFR4VHhTeFN4U3hUeFR4VHhUeFR4U3hUeFR4VHhUeFR5VHhUeWR4VHhUeFR4VHlUeWR5ZHlkeWV5ZHlleWV5ZXlleWV5ZXlleWV5ZXlleWV5dXlleXR4VHhUeFR5VHlleWR5ZXlkeVR5ZHlkeWV5ZXlleWV5ZXlleWV5ZXlleXZ6dXl2enV5ZXl1eWV5dnp2enZ6dnp1e3V8dXt1fIV8hnyGfIZ8hXuFfIV8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8lXyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8h3yWfJd8lnyGfIZ8hnyHfJd8l3yXfJZ8h3yXfJd8l3yXfJd8l3yXfJd8l3yXfJd8l32XfZd9l32XfZd9l32XfZh9l32YfZd9l32XfZd9mH2Yfah9mH2nfJd8l3yXfZd9l32XfZd9l3yXfZd8l32XfZd9l32XfZd9l32XfZh9mH2ofah9qH2ofZh9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2pfal+qX6pfql+uH2pfqh9qX6pfql+uX65frh9qH2ofah9qH2ofah9qX2ofah9qH2ofah9qX2ofal+qX6pfql+qX65frl+uX65frl+qX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX66frl+un66frp+un63j5p+uY6qfrp+un66frp+un66frp+uX65frl+uX65frp+uX66frl+uX65frp+un66frp+un66frp+un66frp+yn66fsp+un66fsp+un7Kfsp+yn7KfsHfEd8TvzO/Md8R3xHvEP8Kfrp+un65fbWuYP8FrmD/Ad8R3xD/Ae8R3xHfE88zzzD/Ba1g/wSsWIuYi5eah5qKfrmNun65jbWtYP8FrWD/Cn66fbp+yn61rWD/Ba5g/wD/BLtA/wO6Rph2mHWnZadg/wO6QP8DukWnZadlp1WnaI6bfsiNmo27fst/yn67fsmMqYyomoiLmo26jrmMqo27f8t/y3/Lf8t/23/bf9t/237Lf8p+y3/Lf9t/23/cf9aZd5qGqHeZiIuZjKebg75GqGeZhqhnmYPNMP8Ii5LfKo27fsHfI79Lf9x/23/Gn3D/AP8A/wD/AP8A/wD/AP8Lf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9t/23/cf9x/23/Yn4HvFa9g/wD/Ad8Q/wD/AP8Mf9x/2o+8f9x/3H/cf9qPsP8Gr2D/Ae8bfsO/So25jqx/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/1q9jzzx/3H/R3xx/0P8A/wWuYP8A/wWvUP8A/wx/3H/aj7effH/cf9efeY+g/wD/AP8DzjD/AP8B7xD/DH/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/Tzzt+wP8Czzt+y37KjbqNvH/cf9x/3H/cf9x/3H/cf9t/y3/bfsefiJ+B3xD/AP8Mf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9t/3H/cf9x/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/Lf9t/zH/cf9ifh598f9t/1595j5D/AP8A7wS/QP8A/wLPMP8Lf9t/23/Lf8t/y3/Lfst+ws8pjqD/Ae8bfst+yoy6jbt/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t+y3/Lfst/y37Lfst+y37Lfst/y37Lfst+y37Lfst+y37Lf8t/y37Gn3t/y37Fr2O/S37A/wqNt56A/wD/Bp5x3yt+y37B7xLfK37Lfst+y37A/wHfEP8B7xidge8Q/wD/C37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+yn7Kfsp+y37Lfst+y37Kfsp+yn7Kfst+y37Hnoafe37LfsmOqn7A/wD/As4h7xD/A78w/wD/C37Kfsp+un66fsp+yI6Vr2p9un25jKmMod8Q/wedha5qfsp+yn7Kfrp+un66frp+un63nnp+tp5g/weecP8Gnmp+un66frp+un66fbp9un26fbp9un25fbp9un25fbl9un6yzzLPIP8A/wWeYP8DvkD/AP8FrWD/AP8A/wD/As05jKmMpa1VrVl8qXylrViMkP8A/wS7Q7tA/weKhKpXmXp9un26fbp9un26fbp9un26fbl9un25fbp9un26fbl9un25fbl9uX25fal9qX2pfal9uX2pfbl9qX2pfal9qX2pfal9qXypfal9uX25fal9qIuYjKeKiIuZfal9qXyojZl9qX2pfal9qX2pfaeNhZ5ojZLPIO8Q/wD/AP8A7wOuSX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal8qX2pfKl8qHypfKh8qXypfKl8qXyofKh8qHyofKl9qX2lnmadeX2pfKl8qXyg/wD/A75B7xHfFZ1g/wD/CXyofKh8qHyofKh8qHyVnVh8mHyVnGeLiHyQ/weLlZxofKh8qHyofJh8mHyYfJh8mHyofJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJSuUr44fJh8kO8B3xD/AP8EnVHfEP8B3xD/AP8IfJh8mHuXe5h8mHyVnWSdVZxQ7wD/AP8A/wD/Ac4g7wh8mHyYfJh8l3yXe5d7l3uYfJd7l3yXfJd7l3uHe5d7h3uXe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHfJd7lox3e4d7l3uHe4d7gP8CvjD/AP8He4d7hop2ind7h3uHe4d7h3uHe4d7h3uHe4d7hop2eod7h3uGe4Z7h3uHe4d7h3uHe4d7h3uGe4d7h3uHe4d7h3uGe4d7hnuGe4Z7hnuGe4Z7hnp2e3Z6dnuGe4Z7hnt2e3Z6dnp2end7h3uHe4d7hnuGe4Z7hnuHe4Z7hnuGe4Z7hnuGe4Z7hnuGe3Z7dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp1enV6dXp2enV6dnp1enV6dXp1enV6dnp2enZ6dnp2enZ6dnp1enZ6dnp2enZ6dnp1enV6dXp1enV6dXp1enV6dXplenV6ZXp1enV6dXp1emV6ZXplemV6dXplenV6ZXplemV6ZXplemV6ZXplemV6ZXllemV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlkeWV5ZHllemV6ZXpleWV5ZXlleWV5ZXpleWV6ZXlleWV5ZXlleWV5ZXlleWV5ZHlkeWR5ZHlleWV5ZXlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlUeWR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5ZHlkeWR5ZHlUeVR5VHlUeWR5VHlkeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeFR5VHlUeVR5VHhUeFR5VHhUeVR4VHlUeVR4U3hUeFN4VHlUeFR5VHhTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hDeFN4U3hTeFN4U3hDeEN4RHhTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hDeEN4Q3hTeEN4Q3hDeEN4Q3hDeEN4U3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hCeEN4Q3hDeEN4Q3hCeEJ4QnhDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEJ4QnhCeEJ4QndDeEJ4QnhCeEJ4QndCd0J3QnhCeEJ4QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3MncydzJ3MndCdzJ3QncydzJ3MncydzJ3QndCd0J3QndCd0J3QndCd0J3QndCd0J3Qncyd0J3MndCdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncxdzJ3MncydzJ3MncydzF3MXcxdzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncxdzF3MXcxdzF3MncxdzJ3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdjF2MXYxdjF2MXcxdzF2MXYxdjF2MXYxdjF2MXYxdzF2MXYxdjF2MXYxdjF2MXYxdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYhdiF2MXYxdjF2MXYxdiF2IXYxdjF2MXYxdjF2IXYhdjF2MXYxdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYhdiF2IXYhdiF2MXYxdiF2IXYhdiF2MXYxdjF2MXYxdjF2MXYxdjF3MXYxdzF2MXYxdjF3MXcxdzF3MXcxdiF2IXYhdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdjF3MXcydzJ3MncxdzF3MXcydzJ3MncydzJ3MXcydzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3Qncyd0J3QndCd0N3QndCd0J3QndCd0N3Q3dDeEJ3MncydzJ3Mncyd0J3MndCdzJ3MncydzJ3QndCd0J3QndCd0J3Q3dDd0N4Q3hDeEJ3Q3dDd0N3Q3hDeEN4Q3hDd0N4Q3hDeEN4Q3hTeEN4U3hDeEN4Q3hTeFN4U3hUeFN4VHhUeFR4VHhUeFR4VHlkeFR4VHhUeFR4VHlkeWR5Y3hDeFN4Q3hTeFR4VHhUeFN4U3hTeFR4VHhUeFR4VHhUeFR4VHhUeVR5ZXlkeWV5ZHhUeWR5VHlleWV5ZXlleWR5ZXlkeWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5dXl2eXV5dnp2enZ6dnp2enZ5dnp2enZ6dnp2eoZ6d3qFeWV5ZXlleWV5ZXl1eXZ6dXlleWV5ZXl2eXZ6dnp2enZ6dnp2enZ6dnqHeod6h3uGenZ6hnp3eod6h3uHe4d7hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfIZ8hnyGfId8lnyXfJd8l3yXfJd9l3yXfJd8l3yXfJd9l3yXfZZ8hnyGfIZ8hnyHfJZ8l3yWfIZ8hnyGfJd8l3yXfJd8l3yXfJd8l32XfZd9l32XfZd8l32XfJd9l32XfZd9l32XfZd9l32XfZd9mH2XfZh9l32XfZd9l32XfZh9qH2Yfah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9p32XfZd9mH2Yfah9qH2ofad9mH2ofZh9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofal9qH2pfqh9qH2ofal9qX2pfql+qX6ofal+qH2pfql+qX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65fal+qX6pfrl+uX65frl+uX6pfrl+uX65frl+uX65frl+uX65frl+uX66frl+un65frl+uX65frp+un66frp+uX66frl+un66frp+un66frp+un66frp+un66fsp+un7Kfrp+yn7Kfsp+yn7Kfsp/yn7Kfsp+yn7Kf8p/yn/Kf8p+un66frp+un66fsp+yn7Kfrp+un66fsp+yn7Kfsp+yn7Kfsp+yn/Kf8t/yn/Lf8p+yn/Kf8p/y3/Lf8t/yY+6fsp+un7KfsWuYP8GrmD/C3/Kfst/y37GrmD/Bq5g/wD/BLpA/wS7Radlp2WnZadg/wS7QP8Eu0WnZadlp2Wna3/Lfst/y3/GrnD/Bq5w/wt/y3/Dv0O/Rq5w/wHfIP8A/wS7QP8Eu0WnZadlp2WnYP8Eu0D/Ae4Vp2WnYtwi3Caod5mGmHeaiIuTzjiLk842mHeahph3momLk845i6POMP8A/wD/Ae8WrXS9V5qEu1D/Ae8Q/wHvFpl0ukaoc8pGmHiahph4momLo845i6PONph4moapZ5qJi6PONq1x7xD/Ae8Q/wHvFqhzyTaoc8kw/wHvEP8A/waoc8lEu0HtEP8A/wD/AP8DzTS9V5h0u1D/AP8A/wD/BadjukS2U8kw/wD/AP8A/wmLqYynmYiagP8A/wD/AP8GqGaodaZVp2D/AP8A/wD/BLVTyDS1Qsgw/wD/AP8A/wS2U8gyyjHcEP8A/wD/AP8EtlWmVLZVtlD/AP8A/wD/BLZVtlLbJbZZjKD/CJqQ/wD/Ae8Q/wS8V5lw/wanYP8A/waocP8Gp2ebiJuXmYeZeJqTzjeZdql2qGanZadlp2anZqdlp2WnZadg/wWnYP8A/wWnYP8EuVWnYP8Fp2D/AP8A7gD/AP8Fp2WnZadlp2WnZadmp2aodahWp2D/AtwmqHPMMO8A/wD/AP8A/wD/B5yJjKPNOJqQ/wD/Ae4Q/wLNJ5mC3Caoeo2x7xascP8A/wLfIP8GnXPNMP8CzSD/AP8Ii5D/B5mB7hD/AP8A/wLcJqdizDWnYP8A/wD/At0lqWanZph2p2PLMP8EuFD/AP8GmHD/BLlFp2HtFadkt1D/Ae4Q/gD/Co26jKmMqIuZjKiciJqXmoial5mHmXaYd5l2mHaYdqhw/wD/At4g/wPOOYyg/wialLtA/wS6QP8A/wWqYP8Eu0aodqhlp2WnZqhmqHaodph1p2WnYP8B3SaYdaph7hD/BLtA/wLdIP8A/wWoYP8Gp2D/AP8A/wHeI8w2qGeZdqhpjKqMuIuZi6qNs845i6PON5mImoaYd5mIipLON5qCzTD/AP8A/wD/AP8DvULdJphg/wD/AP8B7hWoVaZVplSmVqhmmHWnZqhnmYLNJphyzSWnZqdlqFLcJphyzSLNIe4Q/wHuEP8B7hWmVLZVp1SmUP8B7hD/AP8Fp2WmUtwi3Ceah5qGmGaYcs4lrGaYdpl1plWnVLZUplWnZphlplWnaIqYi5eZh5qIi5iLl4qIi5aYdpl2mHaZd5mHioeZh4qEtUSmVKZVplWnVphlp2aYdaZVp2O5RphmmHeZh5l4ipaZd5mHmoiKl4qIi5iLmIuYi5iLmYypfamMqYypfbp9uIuQ/weKgP8A/wS7QP8DukeKgP8HioD/AP8DuTD/A7o1p2WnVKZUplWXZphkplWXZKVEtUSlRLVEplWnVKZVp1iKgP8Ii5D/AP8DujD/A7pJjKDvCXyjvUD/Ad0Q/wD/BKZUpkSmVKZUplWXYd0Q/wWmVLhA7gD/AP8B3hD/A7s3mXeKhph3ioiLkr44i5D/BphniXaYd4qHioD/CIuQ/wD/AO8A/wLOJ4yIi5eKh4lw/wD/AP8A7wHvEe4Q7hDuFph3ioaZd4qIi5D/CIuQ7weJd4qGmXeKiIuTvTeLh4qA/wLMMP8B3RWXZKZUplSlQP8A/wDvAP8CuTOlQP8A/weKh4p2mXaYYP8A/wHeEP8A7hDuEO4A7gD/AP8A7gDuAs4ninDuFph3ioeKhol2iXD/BZdQ7RSmVZhlmGSmVZdUpkSlQ6VDpUSlRKVDtkD/A7VDpUHcEP8A7RD/AP8ByySlRKZB3BSlRKZUl1SmRJZSuDSlRKZEpkSmRJZTp0HMJ4qCziaJcs0g/wD/AP8A/waIYs0lmGLNIP8A/wD/AO4A/wOrQcwkllWYZJlUllSWU6dDpUOlQ6UzpUOlQ7QzpTWXYc0ll2HNIP8A7gD/AO4Fl1HNIc0g7wD/AO4A/wD/A6VDtDOlQ6UztDOlM6UzpUSmQ6VB3BHbE6VDpkK4NJZB3hOqRJdUl1WIZYlkl1WIY6VEpkOlQ6ZEllSXVJZUl1aJdop1iGaJdnp2eoaKdnp1iGWJZYhliWaJdnp2iXZ6c6VElkOmRJdUl1WXVZhliGSWVZhkl1WIZYhmiXaJdnp1iGWJdYlmiXaKdnp2enZ6dol2enZ6dnp2enZ6dnp2enZ7hnuGe4Z7hnuGe3Z7hnp2e4Z7hnp2e3Z6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp2enZ6dnp2enZ6dXp1enV6dnp2enZ6dnp1enV6dXp1enZ6dXp1enV6dXp1enV6dXp1enV6ZXp1emV6ZXplemV6ZXplemV6ZXplemV6ZXpleWV6dXp1enV6dXp1emV6dXplenV6dXp1enV6ZXplemV6ZXplemV6ZXpleWV5ZXlleWV6ZXllemV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlUeWR5VXlleWV5ZXlleWR5ZHlkeWV5ZXlleWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5VHlUeVR5VHlkeVR5ZHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHhUeFN4VHhTeFR5VHhUeFR4U3hTeFN4U3hUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR4VHhUeFR4U3hUeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeEN4U3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4U3hTeFN4U3hDeEN4Q3hDeFN4Q3hTeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEJ4Q3hDeEN4Q3hDeEJ4QnhCeEJ4QnhCeEJ3QndCd0J3QndCd0J3QndCd0J3QndCd0J3Q3hDeEN4QnhCeEJ4QnhCd0N4QnhCeEJ4QnhCd0J4QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCdzJ3Mncyd0J3QndCdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3Mncyd0J3MndCdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncxdzJ3MncydzJ3MncxdzJ3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzJ3MncydzF3MncxdzF3MXcydzJ3MncxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXYxdzF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdzF3MXcxdzF2MXYxdjF3MXcxdzF2MXcxdjF2MXYxdjF2MXYxdjF2MXYxdjF2IXYxdjF2MXYxdiF2IXYxdjF2MXYxdjF2IXYhdjF2IXYhdjF2IXYxdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYhdiF2IXYhdjF2MXYxdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYxdjF2MXYxdjF2IXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdjF3MXYxdjF2MXYxdzF3MXcxdzF3MncxdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MXYxdzF2MXcxdzJ3MncydzF3MXcxdzF3MncydzJ3MncydzJ3MncydzJ3MndCdzJ3QncydzJ3MncydzJ3QndCd0J3MndCdzJ3QndCd0J3Q3dCdzJ3QndCd0J3Q3dDd0N3Q3dDeEN4Q3hDeEN4U3hDeFN4Q3hDeEN4Q3hTeFN4U3hSd0J3QndDd0N3Q3hDeEN4QndDd0N3Q3dDeEN4Q3hDeEN4Q3hTeEN4U3hUeFR4VHhTeFN4U3hUeFR4VHhUeFR4U3hUeFR4VHhUeFR4VHhUeVR4VHhUeFR4VHhUeWR5VHlkeWV5ZHlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleXR4VHhUeFR5VHlleWR5ZXlkeFR5ZHlUeWR5ZXlleWV5ZXlleWV5ZXlleWV5dXl2enV5ZXlleWV5dXl2enZ6dnp1eWV6dXl2enZ6dnp2enZ6dXl2enZ6dnp2enZ6hnp3eoZ6h3qHeod7h3uHe5d7iHuXeod7h3uHe4d7mHuYe5h7lnp2enZ6dnp2eod6h3qHeoZ6dnqGend6h3qHe4d7h3uHe4d7l3uIe5h7mHyYe5h8l3uYe5h7mHuYe5l8qHyZfKZ8h3yWfId8l3yXfJd8l3yWfJd8l3yXfJd8l32XfJd9l32XfZd9l32XfZd9l32YfZd9l32XfZd9l32Yfah9mH2nfJd8l3yXfJd9l32XfZd9l3yXfZd8l32XfZd9l32XfZd9l32XfZh9mH2ofah9qH2nfZh9qH2Yfah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofal9qX6pfal+qH2pfah9qX6pfql+uX6pfrh9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qX2ofal+qX2pfql+qX65frl+uX65frl+qX65fql+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+un65frp+un66frp+un66frp+un66frp+un7Kfrp+yX65frl+uX65frp+uX66frl+uX65frl+un66frp+un66frp+un66frp+un7Kfsp+yn66fsp+un7Kfsp+yn7Kfsp+un7Kfsp+yn7Kfsp+yn/Kfsp+yn7Kfsp+yn/Kf8p/yn/Lf8p/y3/Lf8efi3/Lf8t/y3/Lf8t/y3/Lf8t/y37Kfsp+yn7Kf8p/y3/Kf8t/yn/Kf8p/yn/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lfst/y3/Lf8t/y3/Lf8t/y3/Lf8t/wP8A/wt+yn6w/wD/CYyoi5p+yo66fsqNuYyompmMqJqA/wD/B5l2qGD/AP8Fp1WnVpl2p2eZdqhlp1WnZadlp2p+yo27fsqNuYyompmNuYyrfsp+y3/LfsqNuY27fsqNt5mGmHial5qGqGaoZ5mHmYmMqYuqjbqNuIuYi5qNuo20uleZhqhnmYPOMP8ImpiLlqhnmXaoZ5l4moibl5qImpD/AP8ImpeZge4Q/waodadompeZiJqXmYaodadmmHanZph3mYiaiJuYmoiLmYupjKmLqYyqjbqNuoy6jbqOy47Im5iaiYypi6eZhph4m5iaio26jLuOy47JjKmMqo26jbD/AP8EtlS2UP8A/wS2VLVVplW2VadlpmW2VLZVplWmUP8A/wS1RLZQ/wW2VLZVtlS2VLZVplWmVLZVplWmUtwmqHaoZ5mHmYanZqdnmYeZiYupi6qNuo25i6mLqo26jbanZqdnmYeZhqdkuleZh5mJi5mLmo26jbmLmYuajbqNtaZg/wWmYP8A/wLMMP8Gp2S5QP8A/wD/AP8EuUD/AP8A/wD/Badlp2D/AP8GqGaodadlp2LcJaZVp2WnZaZVp2LcItwnmYeZctwi3CaYdqdom5iaiYyoi5eZhqh3moeZc7lFtlWnZaZVplWnZadmp2WnZadmqHaodqdmmHaYd5mDzTeZdqh2mHaYdqdmqHanZqdmqGWnZqdmqHaoZqh2mHWnZadlp2WnZadR3CanZqdmqGaYd5l3mYaYdph3mYeZhadmqHaYd5mHmXeZiJqIi5eZiJqYmpmMqYupjKqNuo24moiLmYupjKiLmIuajLqMuo26jbt+y37Kfrp9u37LfsD/AP8Fp2anYP8A/waYdph2mHaod5mGmHaYdph2mHaYc803mYaZdph2mHanZph2p2aYdph2mHaoZph2qGaYdph4ipeaiYyoi5eZh5l4ipiaio25jKt+yn25jKmLqo26jbaYdph3moeahph3mXiaiIqYi5iLmYy5jKmLmYyqjbqNtLlA/wWnZqhg/wD/Bph3mXaoZph2mHeZd5l3mXeZh5mA/wD/Bph2mGD/AP8Fp2WmVph2mGaZdph1p2WmVadlpleZiIqIi5mLmIqXiomLqIuZjKmMqn26fbmMqYyqfbp9t5mGmHiKl5qGmGWnZ5l2mXmMqIuZjKmMqIuYipmMqYyh7RaYZadWmGeZeIuXmXiLladWmGWnZphmmXiKlpl3iomMqn25jKp9un26fbp9un25jKl9qIyZfap9un26fbp9tadmmHaZd5mHmXeKh4qIi5iKmIuZjKmMqIuZjKmMqXyoi5l8qYypfal9un25fbp9uXypfbl9qX25fbp9un25fbl9p4yJfaiLkd4g/weKhph5fbiMmX25jKeKhpl4i5eJgP8B3RWnZKZTujWXZKZVp1WXZadWmGWnZKZVp1WnVadafbl8qX25faiLl4qJjKiLmX25fbp9uX25fKiMmX2pfKaZdphnioeJdZdll2aZdpl4i5eKiXyojJeKh4qIi5iLlphniXWXZph3ioaJdol2iXWXZZhll2WYZpl2iXaZdol1mWLMJphll2D/AP8EplSmRpl1mGaJdpl1l1SmVZhll1WYZph2iXeJdol3ioeKh4uHioeLiIuYfJiLmHuYfJh8l4qHioeLl4uGiXWYZ4qGiXh8mHuYfJh8l4uXioh8mHuQ/wD/BKVEpUHcFKZEpkSmVKZEpkSmVKZUpkSmVKZUplSmVKZUplSWU7ow/wSXVZdkllSXVJdVl1WXVZhlmGWIZZdll1aJdZhll1WXVZhlmGeKhol3i4eKhol2iXeKh4qFl2WYZZhmiXWIZolmiXaJdol2ineKh4uGioeKh3uHe4D/AP8FmGWYYP8A/wWXVJZViGWYZYhlmGWXVJZVl1SWUP8A/wOmQ6VB2xSWQ6VElkOlQ6VDpkOlQ6VElkOlRJZGiXWIZol2iXWXZJdViGWYZ4p2ind7h3qGiXWJdoqGinSWQ6ZEl1SXVKZEllSXVZdViGWIZol2iXWIZYhmiXaKdJdViWSXVYhminZ6hop2eoSXVYhkl1WIZol2enaJdnp2e4Z7hnuGenZ6dnp2e4Z6dnp2enZ6dnp2enZ6dnp2enSXVYhliGWJZYl2enaKdnp1iWaJdop2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp1enV6dXp2enV6dnp1enV6dXp1enV6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp1enV6dXp1enV6dXplenV6ZXp1enV6dXp1enV6ZXplemV6dXp1enV6ZXplemV6ZXplenV6ZXplemV6ZXllemV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZHllemV6ZXplemV6ZXlleWV5ZXpleWV6ZXlleWV5ZXlleWV5ZXlleWV5ZXlkeWR5ZHlleWV5ZXlkeWR5ZHlkeWR5ZXlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeVR5ZHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5ZHlkeWR5ZHlkeVR5VHlUeWR5ZHlkeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeFR5VHlUeVR5VHlUeFR5VHhUeVR5VHlUeVR4U3hUeFN4VHlUeFR4VHhTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4RHhUeFR4U3hTeFN4U3hTeFR4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4Q3hDeEN4Q3hTeFN4U3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hCeEJ4QnhDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4QnhCeEJ4QndDeEJ4Q3hCeEJ3QndCeEJ3QnhCeEJ4QnhCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3Qncyd0J3MndCd0J3QncydzJ3MncydzJ3QndCd0J3QndCd0J3QndCd0J3QndCd0J3Qncyd0J3QndCdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncxdzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzF3MXcxdzF3MncxdzF3MXcxdzF3MXcxdzJ3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdjF3MXYxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdjF3MXYxdzF2MXcxdjF2MXYxdjF2MXcxdjF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYhdiF2IXYhdjF2MXYhdiF2IXYhdiF2MXYxdjF2MXYxdjF2MXYhdjF2MXYxdjF2MXYxdjF2MXYhdiF2MXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYxdiF2IXYhdiF2IXYxdjF2MXYxdjF2MXYxdjF3MXYxdzF2MXYxdjF2MXcxdzF3MXcxdiF2IXYhdjF2MXYxdjF2MXYhdjF2IXYxdjF2MXYxdjF2MXYxdzF3MXcydzF3MncxdjF3MXcxdzJ3MncydzJ3MXcydzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3Qncyd0J3QndCd0N3Qncyd0J3QndCd0N3Q3dDd0J3MncydzJ3MncydzJ3MndCdzJ3MncydzJ3MndCd0J3QndCd0J3Q3dDd0N4Q3dDeEJ3Q3dCd0N3Q3hDeEN4Q3hDd0N4Q3hDeEN4Q3hTeEN4U3hDeEN4Q3hDeFN4U3hUeFN4VHhTeFR4VHhUeFR4VHlUeFR4VHhUeFR4VHlkeFR5Y3hDeFN4Q3hTeFR4U3hUeFN4U3hTeFN4VHhUeFR4VHhUeFR4VHhUeVR5ZHlkeWV5ZHhUeWR4VHlkeWV5ZXlleWR5ZHlkeWV5ZXlleWV5ZXlkeWV5ZXlleWV5ZXlleWV5dXlleXV5dnp2enZ6dnp2enV5dnp2enZ6dnp2enZ6dnqFeWV5ZXlleWV5ZXl1eXZ6dXlleWV5ZXl1eXZ6dnp2enZ6dnp2enZ6dnp3eoZ6h3qGenZ6dnp2eod6h3uHeod7hnp3eod6h3qHe4d7l3uIe5d6h3uHe4d7h3uYe5h7mHuYe5h7mHuYfJl8qXypfKl8qHuZfKh8mXypfKl8qXypfKd7h3uXe4h7mHuYe5h7mHyXe5h7mHuYe5h7mHyofJl8qXypfKl8qXypfKp8uXyqfbl8qXypfKl8qny6fbp9un23fZd9l32XfZd9l32XfZh9l32XfZd9l32XfZh9qH2Yfah9mH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9p32XfZd9mH2YfZh9qH2ofad9mH2YfZh9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofal9qH2pfqh9qH2ofah9qX2pfql+qX6ofal9qH2pfql+qX65fql+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65fal+qX2pfql+uX65frl+uX6pfrl+qX65frl+uX65frl+uX65frl+uX65frl+un65frl+uX65frp+un66frp+uX66frl+un66frp+un66frp+un66frp+un66frp+un7Kfrp+yn7Kfsp+yn7Kfsp+yn7Kfsp+yn7Kf8p/yn/Kf8p+un66frp+un66fsp+yn7Kfrp+un66frp+yn7Kfsp+yn7Kfsp+yn/Kf8p/yn/Lf8p+yn/Kf8p/yn/Lf8t/y3/Kf8t/yn/Lf8t/y3/Lf8t/yn/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/bf9t/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf9t/23/bf9t/23/Lf9t/y3/bf9t/23/bf9t/y3/Lf9t/23/Lf8t/23/bf9t/23/bf9t/23/bf9t/237Lfst/3H/bfst+zH/cf9x/3H/cf9x/3H/cf9x/3H/bf9t/23/bf9t/3H/bf9x/23/bf9t/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/237Lfsx/3H/bf8t/3H/cf9x/3H/cf9x/3H/cf9x/3H/bf9t/3H/cf9t/y37Mf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/bfst+zH/cf9t+y37Mf9x/3H/cf9x/3H/cf9x/3H/cf9t+y37Mf9x/237Lfsx/23/cf9x/3H/cf9x/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9qNuYyrfsqNuYuYmomMqYurfst+y3/Lf8qNuo27fst+x5mHmYmLmIuYmoiLmYupjKqMuoy7jsqOyo26jbt+y37Mf9x/3H/cf9t/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9t+y37Mf9x/23/Lf8x/23/cf9t/3H/bf9t/23/bf9t/2YyqjbqNu37Lfst+y37Lf8t+y37Lfst+y37Lf8t/y3/bfst/y3/Lf8t+y37Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf9t/23/bf8t/23/Lf9t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lfst/y3/Lf8t/y3/Lfst+y37Lfst+y37Lf8t+y37Lfst+y37Lfst+y37Lfst+y37Lfsp+yn67fst+yn7Kfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfsp+yn7Lfst+yn7Kfbt+yn7Lfst+y37Lfst+yn7Kfsp+yn26fbp+yn66fbp9un66frp+yn66frp+un66frp+un67fst+y37Kfsp+yn7Kfsp+yn7Kfsp+yn7Kfsp+un7Kfrp+un66frp+un66frp+un66frp+un66frp+un66frp+uX25fbp+un66fbp9un66fbp+un66frp+un66fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un25fbp+un66frp9un26fbp9un26frp9un26fbp9un26fbp9un26fbp9un26fbl9uX25fbp9un26fbp9uX25fbl9uX2qfbl9uX25fbl9qX2pfal9qX25fbl9uX2pfal9qX2pfal9qXypfal9qXypfKl9qX2pfal9qX2pfal9qX2pfal9qX25fal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal8qX2pfKl8qHypfal8qXyofKl8qHypfal8qXypfKl8qHypfKh8qHyofJh8qHyofJh8mHyYfJh8qHyYfJh8mHyYfJh8mHyZfKl8qXypfKh8qHyofKh8qXyofKh8qHyofKh8mHyofJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYe5h8mHyXe5d7mHyYfJh8mHyYfJh8mHyYfJh8mHyXe5d7mHyYfJd7l3uHfJd7mHyXfJh8l3uXe5d7l3uXe5h8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8l3yYfJd8mHyXe5d7l3uXe5d7h3uXe4d7l3uXe5d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4Z6hnqHe4d7hnp2eod7h3uHe4d7h3uHe4d7hnuHe4Z7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7hnuGe4Z7h3uHe4d7hnuGe4Z7hnuGe4Z6dnp2e4Z7hnp2enZ7hnp2e4Z7hnuGe4Z7hnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2e4Z7dnuGe3Z6dnp2enZ6dnt2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp2enV6dnp2enZ6dnp1enV6dXp1enZ6dnp2enV6dXp1enV6dXp1enV6dXp1emV6ZXplemV6ZXp1emV6ZXplemV6ZXpleWZ6dXp1enV6dXp1enV6dXplenV6dXp1enV6dXplenV6ZXplemV6ZXplemV5ZXlleWV6ZXplemV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlkeWV5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5VXlleWV5ZXlleWR5ZXlkeWV5ZXlleWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlUeVR5VHlkeWR5ZHlkeVR5VHlUeVR5ZHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeFR4VHhTeFR5VHhUeVR4U3hTeFN4U3hUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR4VHlUeFR4U3hUeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hDeEN4Q3hTeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4U3hTeFN4U3hTeEN4Q3hDeFN4U3hTeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEJ4QnhCeEJ4QnhCeEJ3QndCd0J3QndCeEJ3QndCd0J3QndCd0J3Q3hDeEN4QnhCeEJ4QnhCeEN4QnhCeEJ4QnhCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCdzJ3Qncyd0J3QndCdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3Mncyd0J3MndCdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncxdzJ3MXcydzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzJ3MncydzJ3MncxdzF3MXcydzF3MncxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF2MXcxdzF3MXYxdzF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdzF3MXcxdzF3MXcxdjF3MXcxdzF2MXcxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2IXYhdjF2MXYxdjF2MXYhdiF2MXYhdjF2IXYxdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYxdiF2IXYhdiF2IXYhdiF2MXYxdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2IXYxdjF2MXYxdjF2IXYxdiF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdjF3MXYxdjF2MXYxdzF3MXcxdzF3MXcxdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MXYxdzF2MXcxdzJ3MXcydzF3MXcxdzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3QncydzJ3MncydzJ3QndCd0J3MndCdzJ3QndCd0J3QndCd0J3QndCd0J3Q3dCd0N3Q3dDeEN3Q3hDeEN4U3hDeFN4Q3hDeEN4Q3hDeFN4U3hSd0J3QndCd0N3Q3hDd0N4QndDd0J3Q3dDeEN4Q3hDeEN4Q3hDeEN4U3hUeFN4VHhTeEN4U3hTeFR4VHhUeFR4U3hUeFN4VHhUeFR4VHhUeFR4VHhUeFR4VHhUeVR4VHlkeWR5ZHlleWV5ZXlleWV5ZHlleWV5ZXlleWV5ZXlleXR4VHhUeFR4VHlkeWR5ZXlkeFR5VHhUeWR5ZXlleWV5ZXlleWV5ZXlleWV5dXl2enV5ZXlleWV5dXl2enZ6dnp1eWV5dXl2enZ6dnp2enZ6dXl2enZ6dnp2enZ6dnp2eoZ6d3qGeod6h3uHe5d7iHuXeod7h3qHe4d7mHuYe5h7lnp2enZ6dnp2end6hnqHeoZ6dnp2enZ6h3qHe4d6h3uHe4d7h3uIe5h7mHuYe5h8l3uYe5h7mHuYe5h8qHyZfKh7mHuYe5h8mXypfKl8qXyoe5h8qHyZfKl8qXypfKl8qXyqfLl8qn26fbp9un26fbp8un26fbp9un27fbp9u33IfKl8qXypfKl8qny5fKp9uXypfKl8qXypfLp9un26fbp9un26fbp9un27fct9y33Kfbp9un27fct9y37Lfct+yH2Yfah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qH2ofal9qX6pfal+qH2ofah9qX6pfql+qX6pfrh9qH2ofah9qH2ofah9qH2ofah9qH2ofah9qX2ofal9qX2pfql+qX6pfrl+uX65frl+qX65fql+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+un65frp+un66frp+un65frp+un66frp+un66frp+yX65frl+uX65frp+uX66frl+uX65frl+un66frp+un66frp+un66frp+un7Kfrp+yn66frp+un66fsp+yn7Kfsp+un7Kfsp+yn7Kfsp+yn/Kfsp+yn7Kfsp+yn/Kf8p/yn/Lf8p/y3/Lf8t/y3/Lf8p/y3/Lf8t/y3/Lf8t/y3/Kfsp+yn7Kfsp/yn/Kf8t/yn7Kf8p+yn/Kf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/y3/Lf8t/y3/bf9t/23/bf8t/y3/Lf9t/23/bf9t/23/bf9t/23/bf9x/3H/cf9t/23/bf9x/23/cf9x/3H/bf9x/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/bf9x/23/cf9t/23/bf9t/23/bf9t/23/bf9t/23/Lf9t/zH/cf9x/3H/cf9x/23/bf9x/3H/cf9x/3H/bf9t/23/bf9t/23/bf9t/23/Lf8t/y3/bf8t/23/Lf8t/y3/Lf8t/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lfst/y37Lfst+y37Lfst/y37Lfst+y37Lfst+y37Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfsp+y37Lfst+y37Lfsp+yn7Kfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Kfst+yn7Kfsp+yn7Kfrp+yn7Kfsp+yn7Kfrp+un66fsp+yn7Kfsp+un66frp+un7Kfrp+yn66frp+un66frp+un66frp+un66frp+un26frp+un66frp+un26fbp9un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66fbp9un26fbp9un66fbp+un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbl9un25fbl9uX25fbl9qX2pfal9uX25fbl9qX2pfal9qX2qfbp9un26fbl9uX25fbl9un26fbp9uX25fbl9uX25fal9uX2pfbl9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfKl8qXypfKl8qX2pfKl8qXypfKh8qXyofKl9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qXypfKl8qXypfKl8qHyofKh8qHyofKl8qHypfKh8qHyofJh8qHyYfKh8qHyofKh8mHyYfJh8mHyofJh8qHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyofJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyXfJh8mHyYfJh8mHyXfJd8l3uYfJh8mHyXfJd7l3uXe5d7h3uXe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uIfJd7l3yXe5d7l3uHe5d7h3yXe5d7l3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7hnuGe4Z7hnuGe4Z7hnt2e4Z6dnuGe4Z7hnuGe3Z6dnt2end7h3uHe4d7h3uGe4Z7hnuHe4Z7h3uGe4Z7hnuGe4Z7hnuGe4Z7hnp2enZ6dnp2enZ7dnp2e3Z6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp1enV6dXp2enV6dnp1enV6dXp1enV6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp1enV6dXp1enV6dXp1enV6dXp1enV6dXp1enV6ZXp1emV6dXp1enV6ZXplemV6ZXplenV6ZXplemV6ZXplemV6ZXpleWV6ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZHllemV6ZXplemV6ZXlleWV5ZXplemV6ZXlleWV5ZXlleWV5ZXlleWV5ZXlkeWR5ZHlleWV5ZXlkeWR5ZHlkeWR5ZXlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlUeWR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5ZHlkeWR5ZHlkeVR5ZHlUeWR5ZHlkeWR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeFR5VHhUeVR5VHlUeVR4VHhUeFN4VHlUeFR5VHhUeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4RHhUeFR4U3hTeFN4U3hTeFR4U3hUeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hDeEN4Q3hTeFN4U3hTeEN4Q3hDeEN4U3hDeFN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4QnhDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4QnhCeEJ4QnhDeEJ4Q3hCeEJ4QnhCd0J3QnhCeEJ4QnhCd0J3QndCd0J4QndCeEJ3QndCd0J3QndCd0J3QndCd0J3QncydzJ3MndCd0J3QndCdzJ3MncydzJ3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3MndCd0J3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzF3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MXcxdzF3MncydzJ3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXYxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdjF3MXYxdzF3MXcxdjF2MXYxdjF2MXcxdjF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2IXYhdiF2IXYxdjF2MXYhdiF2IXYhdiF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYhdiF2IXYhdiF2IXYhdiF2MXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYxdiF2IXYhdiF2IXYxdjF2MXYxdjF2MXYxdjF3MXYxdzF2MXYxdjF2MXYxdzF3MXcxdiF2MXYhdjF2IXYxdjF2MXYhdiF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdzF3MncxdjF3MXcxdzF3MncydzJ3MXcxdzF3MncydzJ3MncydzF3MncydzJ3MncydzJ3MncydzJ3Mncyd0J3QndCd0J3Qncyd0J3QndCd0N3QndDd0J3MncydzJ3MncydzJ3MndCdzJ3MncydzJ3MndCd0J3QndCd0J3QndDd0N4Q3dDeEJ3Q3dCd0N3Q3dDeEN4Q3hDd0N4Q3dDeEN4Q3hDeEN4U3dDeEN4Q3hDeEN4U3hTeFN4VHhTeFR4VHhUeFR4VHhUeFR4VHhUeFR4VHlUeFR5Y3hDeFN4Q3hTeFR4U3hUeFN4Q3hTeFN4U3hUeFR4VHhUeFR4VHhUeFR5VHlkeWV5ZHhUeVR4VHlkeWV5ZXlleWR5ZHlkeWV5ZXlleWV5ZXlkeWV5ZXlleWV5ZXlleWV5dXlleXV5dXl2enZ6dnp2enV5dnp2eXZ6dnp2enZ6dnqFeWV5ZXlleWV5ZXl1eWV5dXlleWV5ZXlleXZ6dnp2enZ6dnp2enZ6dnp3eoZ6h3qGenZ6dnp2eod6h3uHeod7hnp3eoZ6h3qHe4d7h3uIe5d6h3uHeod7h3uIe5d7mHuYe5h7mHuYe5h8qXypfKl8qHuYfKh7mXypfKl8qXypfKd7h3uHe4h7mHuYe5h7mHuXe4h7l3uYe5h7mHyoe5l8qHypfKl8qXypfKl8uXyqfbl8qXypfKl8qXyqfbp8un25fKl8uXyqfbp9un26fbp9uXy6fbp8un26fbp9un27fcp9u33Lfct9y33Lfst+y37Lfct+y33Lfst+zH7Lfsx+2n26fbp9un26fbt9y33Lfcp9un26fbt9y33Lfst9y37Lfct+y37Lfsx+zH7cftx+237Mfst+zH7cftx+3H7cfth9qH2ofah9qH2pfql9qX6ofal9qH2pfal+qX6pfql+uX65frl+uX65frl+uX65frl+uX65frl+uX65frl+uX64fal+qX6pfql+uX65frl+uX6pfrl+qX65frl+uX65frl+uX65frl+uX65frl+un65frl+uX65frl+un66frp+uX66frl+un66frp+un66frl+un66frp+un66frp+un66frp+yn7Kfsp+yn7Kfsp/yn7Kfsp+yn7Kfsp+yn/Kf8p+un66frp+un66fsp+un7Kfrp+un66frp+yn7Kfsp+yn7Kfsp+yn7Kf8p/yn/Lf8p+yn/Kfsp/yn/Lf8t/y3/Kf8p/yn/Lf8t/y3/Lf8t/yn/Lf8p/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/bf8t/y3/Lf8t/y3/bf8t/23/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf9t/23/bf9t/23/Lf8t/y3/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/3H/cf9x/3H/cf9t/3H/cf9x/3H/cf9x/3H/bf9t/23/bf9t/23/bf9x/23/bf9t/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/bf9x/23/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/cf9x/3H/bf9x/23/cf9x/3H/bf9t/23/bf9t/3H/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf9t/23/bf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/23/bf9t/23/bf8t/y3/Lf9t/23/bf8t/y3/Lf8t/y3/Lf8t/y3/Lf8t/y3/Lfst/y3/Lf8t/y3/Lfst+y37Lf8t/y3/Lf8t+y37Lfst+y3/Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+y37Lfst+yn7Lfst+y37Lfst+yn7Lfsp+yn7Kfsp+yn66frp+un66frp+yn66fsp+un66frp+un67fst+y37Kfsp+yn7Kfsp+y37Kfst+yn7Kfsp+yn7Kfrp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp+un66frp9un66fbp+un66frp+un66fbp9un26fbp9un26fbp9un26fbp9un26fbp9un26fbp9un25fbp+un66frp+un26fbp9un26frp9un66fbp9un26fbp9un26fbp9un26fbl9uX25fbp9un26fbl9uX25fbl9uX26fbl9uX25fbl9uX2pfbl9qX25fbl9uX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX25fal9uX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal9qX2pfal8qX2pfKl9qX2pfal8qX2pfKl8qXypfal8qX2pfKl8qHyofKh8qHyofKh8qHyofJh8mHyYfJh8qHyofKh8mHyYfJh8mHyZfal8qXypfKh8qHyofKh8qXypfKl8qHyofKh8mHyofJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8l3uXfJd7mHyYfJh8l3yXe5d7l3uXe4h8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJh8mHyYfJd8mHyXe5d8l3uXe5d7h3uXe4d7l3uXe5d7h3uHe4d7h3uHe5d7h3uXe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7hnuHe4Z7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4d7h3uHe4Z7hnuGe4Z7h3uHe4d7hnuGe4Z7hnuGe4d7hnuGe4Z7hnuGe4Z7hnt2e4Z7hnuGe4Z7dnp2e3Z6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2e4Z7dnuGe3Z6dnp2enZ6dnuGe3Z6hnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dnp2enZ6dXp2enZ6dnp2enZ6dnp1enV6dXp1enZ6dXp2enV6dXp1enV6dXp1enV6dXp1enV6ZXplemV6ZXp1emV6dXplemV6ZXpleWZ6dXp1enV6dXp1enV6dXp1enV6dXp1enV6dXplenV6ZXplemV6ZXplemV5ZXpleWV6ZXplemV5ZXlleWV5ZXllemV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZXlleWV5ZHlleWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZXlleWV5ZXlleWR5ZHlkeWV5ZXlleWR5ZHlkeWR5ZHlkeWR5ZHlkeWR5ZHlUeWR5VHlkeWR5ZHlUeVR5VHlUeVR5ZHlUeWR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeFR4VHhTeFR5VHlUeVR4VHhTeFN4U3hUeVR5VHlUeVR5VHlUeVR5VHlUeVR5VHlUeVR4VHlUeFR5VHhUeFN4U3hTeFN4U3hUeFN4VHhTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4U3hTeFN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4U3hTeFN4U3hTeEN4U3hDeFN4U3hTeFN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hDeEN4Q3hCeEN4QnhCeEJ4QnhCd0J3QndCeEJ3QndCd0J3QndCd0J3Q3hDeEN4Q3hCeEJ4QnhCeEN4QnhDeEJ4QnhCd0J4QndCeEJ3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCd0J3QndCdzJ3Qncyd0J3QndCd0J3QncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3Mncyd0J3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncxdzJ3MXcydzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzJ3MncydzJ3MXcxdzF3MXcydzJ3MncydzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdzF3MXcxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXcxdzF3MXcxdzF2MXcxdjF3MXcxdzF3MXYxdzF3MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdiF2MXYxdjF2IXYhdiF2MXYhdjF2MXYxdjF2IXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYxdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2MXYhdiF2IXYhdiF2MXYhdjF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdiF2IXYhdjF2MXYxdjF2IXYhdiF2MXYxdjF2MXYxdjF2MXYxdjF2MXYxdjF3MXYxdjF2MXYxdjF3MXcxdzF3MXcxdzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MXYxdjF2MXcxdzF3MXcydzF2MXcxdzF3MXcydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3MncydzJ3Qncyd0J3MncydzJ3QndCd0J3QndCdzJ3Qncyd0J3Q3dCd0N3Q3dDd0N3Q3hDeEN4Q3hDeFN4Q3hDeEN4Q3hDeFN4U3hSd0J3QndCd0N3Q3dDd0N4QndDd0J3Q3dDd0N4Q3hDeEN4Q3hDeEN4U3hUeFN4VHhTeEN4U3hTeFN4VHhUeFR4U3hUeFN4VHhUeFR4VHhUeFN4VHhUeFR4VHhUeVR4VHlkeVR5ZHlkeWV5ZXlleWV5ZHlleWR5ZXlleWV5ZXlleWR4VHhUeFR4VHlUeWR5ZHlkeFR5VHhUeWR5ZXlkeWV5ZXlleWV5ZXlleWV5dXlleXV5ZXlleWV5ZXl2enV5dnp1eWV5dXlleXZ6dnp2enZ6dXl2enV5dnp2enZ6dnp2eoZ6d3qGeod6h3uHe4d7h3uXeod7h3qHe4d7iHuXe5h7lnp2enZ6dnp2end6hnp3eoZ6dnp2enZ6h3qHe4d6h3uHeod7h3uHe5h7mHuYe5h7l3uIe5d7mHuYe5h8mHuZfKh7mHuYe5h7mHyZfKl8qXyoe5h8mHuZfKl8qXypfKl8qXypfKl8qny6fbp9un26fbl8qn26fLp9un26fbp9u33IfJl8qXypfKl8qXypfKp8uXypfKl8qXypfKp9uny6fbp9un26fbp9un27fct9y33Kfbp9un27fct9y33Lfct+yn27fct9y33Lfct+y37Lfst9y37Lfct+y37Lfst+zH7bfsx+3H7cftx+3H7cftx+3H7cftx+3H7cftx+3H7cftt9y37Lfst+zH7Mftx+3H7bfst+y37Mftx+3H7cftx+3H7cftx+3H7cftx+3H7cftx+3H7cftx+3H7cftx+3H7Q== + + + + + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/banner_dummy.bcwav b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/banner_dummy.bcwav new file mode 100644 index 0000000..d579907 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/banner_dummy.bcwav differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/banner_imp.cbmd b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/banner_imp.cbmd new file mode 100644 index 0000000..e64d183 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/banner_imp.cbmd differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/icon2_24.ctpk b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/icon2_24.ctpk new file mode 100644 index 0000000..a96f378 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/icon2_24.ctpk differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/icon2_48.ctpk b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/icon2_48.ctpk new file mode 100644 index 0000000..550e559 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/banner/icon2_48.ctpk differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/romfiles/importee.cia b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/romfiles/importee.cia new file mode 100644 index 0000000..8b91509 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/romfiles/importee.cia differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/romfiles/nnfont_RectDrawerShader.shbin b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/romfiles/nnfont_RectDrawerShader.shbin new file mode 100644 index 0000000..4290c2c Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/romfiles/nnfont_RectDrawerShader.shbin differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/source/main.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/source/main.cpp new file mode 100644 index 0000000..b2e3e68 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/source/main.cpp @@ -0,0 +1,223 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: main.cpp + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +//#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include "demo.h" +#include "../common/ver.h" +#include "../common/sleep.h" +#include "../common/common.h" +#include "../common/shfnt.h" +#include "test_data.h" + +demo::RenderSystemDrawing s_RenderSystem; +nn::fnd::ExpHeap appHeap; +uptr heapForGx; + +namespace +{ + bit8 readBuf[64 * 1024]; +} + +bool ImportFile(nn::fs::MediaType mediaType, wchar_t* filename) +{ + nn::Result result; + + nn::fs::FileOutputStream* stream; + result = nn::am::BeginImportProgram(&stream, mediaType); + if (result.IsSuccess()) + { + //NN_LOG("Importing: %ls...", filename); + nn::fs::FileInputStream in(filename); + + while(s32 read = in.Read(readBuf, sizeof(readBuf))) + { + stream->Write(readBuf, read); + } + result = nn::am::EndImportProgram(stream); + } + return result.IsSuccess(); +} + + +//#define setColor(r,g,b,a) s_RenderSystem.SetColor(r,g,b,a) +void setColor(f32 r,f32 g,f32 b,f32 a){ shf_SetColor(r,g,b,a);} +//#define setText(x,y,s) s_RenderSystem.DrawText(x,y,s) +void drawText(u16 x,u16 y,char *s){ shf_DrawText_0( x,y,s);} + + +nn::hid::PadReader *hpr; +//---------------------------------------------------------------- 蜈・蜉帛セ縺。 +nn::hid::PadStatus padStatus; +u32 WaitKey(u32 mask) +{ + + while(1){ + hpr->ReadLatest(&padStatus); + if(padStatus.trigger & mask)return padStatus.trigger; + CheckSysBreak(); + } +} + + +void endfunc() +{ + nn::hid::Finalize(); + SharedFontFinalize(); + nngxWaitVSync(NN_GX_DISPLAY_BOTH);//SDK2.0莉・髯阪〒縺ッ荳崎ヲ√°繧ゑシ + s_RenderSystem.Finalize(); +} + +char ver[16]; +void nnMain( void ) +{ + nn::Result result; + + nn::os::Initialize(); + nn::fs::Initialize(); + + //DEA-SUP縺ォ縺ヲ謗ィ螂ィ縺ョ繝輔Μ繝シ繧コ證ォ螳壼ッセ遲厄シ夂┌邱壹ョ繝シ繝「繝ウ繧貞●豁「 (2011.3.1 迴セ蝨ィ) + //縺溘□縺励√せ繝ェ繝シ繝玲凾縺ョ"縺縺、縺ョ縺セ縺ォ騾壻ソ。"縺ッ豁「縺セ繧峨↑縺 + //辟。邱壹ッ菴ソ繧上↑縺縺悟ソオ縺ョ轤コ縲∵悽菴薙せ繧、繝繝√〒蛻縺」縺ィ縺上ョ縺檎「コ螳 + nn::ndm::SuspendScheduler(); + + //荳ュ譁ュ蜃ヲ逅縺ョ貅門y + InitSysBreak((uptr)endfunc); + // 繧ー繝ゥ繝輔ぅ繝繧ッ繧ケ繝ゥ繧、繝悶Λ繝ェ縺ョ蛻晄悄蛹悶ッ縲∽サ・髯阪〒陦後o縺ェ縺代l縺ー縺ェ繧峨↑縺 + // 莉悶√い繝励Μ繧ア繝シ繧キ繝ァ繝ウ縺ョ蛻晄悄蛹門ヲ逅 + + nn::hid::Initialize(); + nn::hid::PadReader padReader; + hpr = &padReader; + + //result = nn::ns::CTR::InitializeForShell(); + //if (result.IsSuccess()) + result = nn::am::InitializeForLocalImporter(); + + nn::applet::DisableSleep();//繧ケ繝ェ繝シ繝鈴撼蟇セ蠢 + + const size_t ROMFS_BUFFER_SIZE = 1024 * 64; + static char buffer[ROMFS_BUFFER_SIZE]; + + // 繝偵シ繝励ョ遒コ菫 + appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + const u32 s_GxHeapSize = 0x800000; + // RenderSystem 縺ョ貅門y + heapForGx = reinterpret_cast(appHeap.Allocate(s_GxHeapSize)); + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + SharedFontInit(); + + // 繧ケ繝ェ繝シ繝苓ヲ∵アゅ↓蟇セ縺吶k霑皮ュ斐r譛牙柑縺ォ縺吶k + // 縺セ縺溘∬搭縺ョ迥カ諷九メ繧ァ繝繧ッ繧定。後>闢九′髢峨§繧峨l縺ヲ縺繧九↑繧峨せ繝ェ繝シ繝苓ヲ∵アゅ′逋コ逕溘☆繧 +// nn::applet::EnableSleep(true); + + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); + s_RenderSystem.Clear(); +// s_RenderSystem.SetFontSize(12); + shf_SetScale(0.8,0.6); + setColor(1.0,1.0,1.0,1.0); + drawText(20,20,"CTR Card Savedata Mover Setup"); + s_RenderSystem.SwapBuffers(); + + shf_SetScale(0.5,0.5); + sprintf(ver,"version %.2f",VERSION); + drawText(250,40,ver); + + shf_SetScale(0.7,0.7); + if (result.IsFailure()){//蛻晄悄蛹悶↓螟ア謨 + setColor(1.0, 0.0, 0.0,1.0); + drawText(10,70,"Initialize Error"); + drawText(10,90,"check *.desc file"); + drawText(10,110,"Push B : Quit"); + s_RenderSystem.SwapBuffers(); + while(1){ + padReader.ReadLatest(&padStatus); + if(padStatus.trigger & nn::hid::BUTTON_B)break; + } + finish(); + } + + nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE); + + drawText(80,100,"Push X : Import"); + drawText(80,140,"Push Y : Delete"); + drawText(80,160,"Push R : Test Data"); + s_RenderSystem.SwapBuffers(); + + u32 trg = WaitKey(nn::hid::BUTTON_X | nn::hid::BUTTON_Y | nn::hid::BUTTON_R); + if (trg & nn::hid::BUTTON_R){ + shf_SetScale(0.6,0.6); + TestMain();//繝繧ケ繝医ョ繝シ繧ソ縺ク + } + shf_SetScale(0.8,0.8); + // CIA 縺ョ繝励Ο繧ー繝ゥ繝 ID 繧貞叙蠕励☆繧九 + nn::am::ProgramInfo programInfo; + if (nn::am::GetProgramInfoFromCia(&programInfo, ROMFS_IMPORTEE_PATH).IsFailure()) + { + s_RenderSystem.Clear(); + setColor(1.0, 0.0, 0.0,1.0); + drawText(10,50,"cia infomation Error"); + drawText(10,120,"Push B : Quit"); + s_RenderSystem.SwapBuffers(); + + while(1){ + padReader.ReadLatest(&padStatus); + if(padStatus.trigger & nn::hid::BUTTON_B)break; + } + + } else + { + s_RenderSystem.Clear(); + if(padStatus.trigger & nn::hid::BUTTON_X) + drawText(10,120,"Importing"); + else drawText(10,120,"Delete"); + s_RenderSystem.SwapBuffers(); + + // 譌「縺ォ蟄伜惠縺吶k繧ゅョ繧偵う繝ウ繝昴シ繝医☆繧九→繧ィ繝ゥ繝シ縺瑚ソ斐▲縺ヲ縺上k縺ョ縺ァ縲√≠繧峨°縺倥a豸医@縺ヲ縺翫¥縲 + nn::am::DeleteProgram(nn::fs::MEDIA_TYPE_NAND, programInfo.id); + // 繧ソ繧、繝医Ν骰オ縺碁&縺繧ア繝シ繧ケ縺ォ蟇セ蠢懊☆繧九◆繧√↓縲√メ繧ア繝繝医b豸医@縺ヲ縺翫¥縲 + nn::am::DeleteTicket(programInfo.id); + + if(padStatus.trigger & nn::hid::BUTTON_X) + { + // CIA 繧偵う繝ウ繝昴シ繝 + if (ImportFile(nn::fs::MEDIA_TYPE_NAND, ROMFS_IMPORTEE_PATH)==false) + { + s_RenderSystem.Clear(); + setColor(1.0, 0.0, 0.0,1.0); + drawText(10,50,"Impoprt fail"); + s_RenderSystem.SwapBuffers(); + } + } + s_RenderSystem.Clear(); + drawText(10,50,"Complate"); + } + + drawText(10,120,"Push Power Button & Power Off"); + s_RenderSystem.SwapBuffers(); + + WaitKey(0); + +} + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/source/test_data.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/source/test_data.cpp new file mode 100644 index 0000000..b881b4f --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/source/test_data.cpp @@ -0,0 +1,673 @@ +サソ/*---------------------------------------------------------------------------* + 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 +#include +#include +#include +#include +#include +#include "demo.h" + +nn::Result res; + +nn::fs::FileOutputStream fout; +nn::fs::FileInputStream fin; + +nn::fs::Directory dc[256]; + +wchar_t file_pathw[1024]; +char file_path[1024]; +char file_path2[1024]; +char src_buff[1024*1024]; +char get_buff[1024*1024]; +char str[512]; + + +extern demo::RenderSystemDrawing s_RenderSystem; + +//邨ゆコ蜃ヲ逅 +extern void finish(void); +extern u32 WaitKey(u32 mask); + +extern void setColor(f32 r,f32 g,f32 b,f32 a); +extern void drawText(u16 x,u16 y,char *s); +void drawText(u16 x,u16 y,char *s,int v) +{ + sprintf(str,s,v); + drawText( x,y,str); +} + + +//----------------------------------------縲縲繝繧ケ繝医ヱ繧ソ繝シ繝ウ +void make_pattern() +{ + int i,j; + j=0; + for (i=0;i<1024*1024;i++){ + src_buff[i] = j+i; + if (i & 0x100)j++; + } +} + +//TEST 繝ゥ繧、繝 +s32 size; +#define SIZE_TEST1 421888 +//#define SIZE_TEST1 244736 //dup +bool Test1_W() +{ + int total,size2; + + res = nn::fs::FormatSaveData(1,0,false); + if (res.IsFailure()){ + drawText(8,100,"format Fail"); + return false; + } + res =nn::fs::MountSaveData(); + if (res.IsFailure()){ + drawText(8,100,"Mount Fail"); + return false; + } + res = nn::fs::TryCreateFile(L"data:/test1.bin",SIZE_TEST1); + if (res.IsFailure()){ + drawText(8,100,"Create Fail"); + nn::fs::Unmount("data:"); + return false; + } + res = fout.TryInitialize(L"data:/test1.bin",true); + if (res.IsFailure()){ + drawText(8,100,"open Fail"); + nn::fs::Unmount("data:"); + return false; + } + total =0; + size2 = 512; + //size2 = 4096; + //size2 = SIZE_TEST1; + while(1){ + res = fout.TryWrite( &size,&src_buff[total],size2); + if (res.IsFailure()){ + drawText(8,100,"write Fail"); + fout.Finalize(); + nn::fs::Unmount("data:"); + return false; + } + total += size; + sprintf(str,"size %d",total); + s_RenderSystem.Clear(); + drawText(10,80,str); + s_RenderSystem.SwapBuffers(); + //if (size<512)break; + if (total >= SIZE_TEST1)break; + if ((SIZE_TEST1 - total) < 512)size2 = SIZE_TEST1 - total ; + } + fout.Finalize(); + nn::fs::CommitSaveData(); + nn::fs::Unmount("data:"); + NN_LOG("total %d",total); + drawText(10,100,"end"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + return true; +} + +//繝吶Μ繝輔ぃ繧、 +bool Test1_V() +{ + int i,total; + + res = fin.TryInitialize(L"data:/test1.bin"); + if (res.IsFailure()){ + drawText(8,100,"open Fail"); + nn::fs::Unmount("data:"); + return false; + } + total =0; + while(1){ + res = fin.TryRead( &size,&get_buff[total],512); + if (res.IsFailure()){ + drawText(8,100,"read Fail"); + fin.Finalize(); + nn::fs::Unmount("data:"); + return false; + } + //if (size == 0)break; + for (i=0;i= SIZE_TEST1)break; + + total += size; + s_RenderSystem.Clear(); + sprintf(str,"now %d",total); + drawText(10,80,str); + s_RenderSystem.SwapBuffers(); + if (size<512)break; + } + fout.Finalize(); + nn::fs::Unmount("data:"); + drawText(10,100,"end"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + return true; +} + + +//繝輔ぃ繧、繝ォ謨ー +bool Test2_W(int n) +{ + int total,size2; + + res = nn::fs::FormatSaveData(680,1,false);//dup縺ェ縺励ヵ繧。繧、繝ォ680 + if (res.IsFailure()){ + drawText(8,100,"format Fail"); + return false; + } + res =nn::fs::MountSaveData(); + if (res.IsFailure()){ + drawText(8,100,"Mount Fail"); + return false; + } + + total =0; + int num = 0; + size2 = 512; + while(1){ + sprintf(file_path,"data:/test%d.bin",num); +// res = nn::fs::TryCreateFile(L"data:/test2.bin",SIZE_TEST1); +// if (res.IsFailure()){ +// drawText(8,100,"Create Fail"); +// nn::fs::Unmount("data:"); +// return false; +// } + res = fout.TryInitialize(file_path,true); + if (res.IsFailure()){ + drawText(8,100,"open Fail"); + nn::fs::Unmount("data:"); + return false; + } + res = fout.TryWrite( &size,&src_buff[total],size2); + if (res.IsFailure()){ + drawText(8,100,"write Fail"); + fout.Finalize(); + nn::fs::Unmount("data:"); + return false; + } + fout.Finalize(); + total += size; + num++; + sprintf(str,"size %d , num %d",total,num); + s_RenderSystem.Clear(); + drawText(10,80,str); + s_RenderSystem.SwapBuffers(); + //if (size<512)break; + if (num == n)break; + } + fout.Finalize(); + nn::fs::CommitSaveData(); + nn::fs::Unmount("data:"); + NN_LOG("total %d",total); + drawText(10,100,"end"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + return true; +} + +bool Test2_V(int n) +{ + int total,size2,i; + + total =0; + int num = 0; + size2 = 512; + while(1){ + sprintf(file_path,"data:/test%d.bin",num); + res = fin.TryInitialize(file_path); + if (res.IsFailure()){ + drawText(8,100,"open Fail"); + nn::fs::Unmount("data:"); + return false; + } + res = fin.TryRead( &size,&get_buff[total],size2); + if (res.IsFailure()){ + drawText(8,100,"read Fail"); + fin.Finalize(); + nn::fs::Unmount("data:"); + return false; + } + for (i=0;i= SIZE_TEST5)break; + } + fout.Finalize(); + nn::fs::CommitSaveData(); + nn::fs::Unmount("data:"); + drawText(10,100,"end"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + return true; +} + + +bool Test5_V() +{ + int i,pos; + + res = fin.TryInitialize(L"data:/test5.bin"); + if (res.IsFailure()){ + drawText(8,100,"open Fail"); + nn::fs::Unmount("data:"); + return false; + } + pos =0; + while(1){ + fin.SetPosition(pos); + res = fin.TryRead( &size,&get_buff[pos],512); + if (res.IsFailure() || (size!=512)){ + drawText(8,100,"read Fail"); + fin.Finalize(); + nn::fs::Unmount("data:"); + return false; + } + sprintf(str,"position %d",pos); + s_RenderSystem.Clear(); + drawText(10,80,str); + s_RenderSystem.SwapBuffers(); + + for (i=0;i<512;i++) if (src_buff[pos+i] != get_buff[pos+i]) + { + drawText(8,100,"verifi Fail at %d",i); + return false; + } + pos += 1024;//512鬟帙ー縺 + if (pos >= SIZE_TEST5)break; + } + fin.Finalize(); + nn::fs::Unmount("data:"); + drawText(10,100,"end"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + return true; +} + + + + +#define menu_ct 6 +#define menu_max (menu_ct-1) +char* menu_str[menu_ct] = {"Casual check","Large size","many files","Deep directry","max size name","data < create size"}; + +#define menu_top_Y 80 +#define menu_top_X 60 +#define menu_spc 14 + +//---------------------------------------------------------------- main +void TestMain() +{ + u32 value; + int curs = 0; + int i; + bool sccs; + + //Render + setColor(1.0f,1.0f,1.0f,1.0f); + + //TEST PATTERN + make_pattern(); + + while(1){ + + //menu 陦ィ遉コ + s_RenderSystem.Clear(); + drawText(8,20," Backup Verifi for SaveDataMover Test "); + drawText(8,40," for 512KB Backup"); + for (i=0;i"); + drawText(menu_top_X,menu_top_Y+menu_spc*(menu_max+2),"push A:Write ,X:Verifi"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + + //繝懊ち繝ウ蠕縺。 + value = WaitKey(nn::hid::BUTTON_A | nn::hid::BUTTON_X |nn::hid::BUTTON_UP |nn::hid::BUTTON_DOWN); + if (value & nn::hid::BUTTON_A){//繝ゥ繧、繝 + sccs = false; + s_RenderSystem.Clear(); + drawText(10,70,"writing"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + switch(curs){ + case 0:sccs = Test2_W(10);break; + case 1:sccs = Test1_W();break; + case 2:sccs = Test2_W(680);break; + case 3:sccs = Test3_W();break; + case 4:sccs = Test4_W();break; + case 5:sccs = Test5_W();break; + default:break; + } + }else if (value & nn::hid::BUTTON_X) + {//繝吶Μ繝輔ぃ繧、 + sccs = false; + s_RenderSystem.Clear(); + drawText(10,70,"verifi"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + res =nn::fs::MountSaveData(); + if (res.IsFailure()){ + drawText(8,100,"Mount Fail"); + }else + switch(curs){ + case 0:sccs = Test2_V(10);break; + case 1:sccs = Test1_V();break; + case 2:sccs = Test2_V(680);break; + case 3:sccs = Test3_V();break; + case 4:sccs = Test4_V();break; + case 5:sccs = Test5_V();break; + default:break; + } + }else if (value & nn::hid::BUTTON_UP){ + if(curs > 0)curs--; + }else if(curs < menu_max)curs++; + + if (value & (nn::hid::BUTTON_A | nn::hid::BUTTON_X)){ + if (sccs == false)drawText(8,120,"Failed"); + sprintf(str,"desc %d",res.GetDescription()); + drawText(10,140,str); + s_RenderSystem.SwapBuffers(); + NN_LOG("desc %d",res.GetDescription()); + WaitKey(nn::hid::BUTTON_B); + } + } +} + + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/source/test_data.h b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/source/test_data.h new file mode 100644 index 0000000..3525aa4 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/Imp/source/test_data.h @@ -0,0 +1,6 @@ +サソ#ifndef TEST_DATA_H_ +#define TEST_DATA_H_ + +void TestMain(); + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/OMakefile b/branches/0thNUP_No_NUP/CardSaveDataMover/OMakefile new file mode 100644 index 0000000..b69eb88 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/OMakefile @@ -0,0 +1,30 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakefile +# +# 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. +# +# $Rev: 34658 $ +#---------------------------------------------------------------------------- + +#表示にDemoライブラリを使用します +#PC環境に合わせてサンプルデモのディレクトリを指定 +#SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir ../common/include) +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir ../CTR_SDK/sampledemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) + +LIBS += lib_demo libnn_am + +.SUBDIRS: $(exist-dirs \ + body \ + Imp \ + ) + +DefineDefaultRules() diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/OMakeroot b/branches/0thNUP_No_NUP/CardSaveDataMover/OMakeroot new file mode 100644 index 0000000..7260486 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/OMakeroot @@ -0,0 +1,73 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakeroot +# +# 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. +# +# $Rev:$ +#---------------------------------------------------------------------------- + +# ディレクトリレイアウトについての説明 +# +# a) ソースコードがルートディレクトリ直下に配置される場合 +# 例: +# /OMakeroot +# /foo/bar/OMakefile +# +# 結果: +# OMakefile と同じディレクトリ以下に objects や images が生成されます。 +# +# /foo/bar/objects/... +# /foo/bar/images/.. +# +# +# b) ソースコードが sources 以下に配置される場合 +# 例: +# /OMakeroot +# /sources/foo/bar/OMakefile +# +# 結果: +# ルートディレクトリ以下に objects や images が生成されます。 +# +# /objects/foo/bar/... +# /images/foo/bar/... +# +# + +# ルート環境変数の取得 +public.HORIZON_ROOT = +if $(defined-env HORIZON_ROOT) + HORIZON_ROOT = $(absname $(getenv HORIZON_ROOT)) + export + +if $(defined-env CTRSDK_ROOT) + CTRSDK_ROOT = $(absname $(getenv CTRSDK_ROOT)) + if $(and $(defined-env HORIZON_ROOT), $(not $(equal $(HORIZON_ROOT), $(CTRSDK_ROOT)))) + eprintln(HORIZON_ROOT と CTRSDK_ROOT が一致しません。同じパスを設定するか、どちらか一方だけを定義して下さい。) + exit(1) + HORIZON_ROOT = $(CTRSDK_ROOT) + export + +if $(not $(HORIZON_ROOT)) + eprintln($"$$CTRSDK_ROOT が定義されていません") + exit(1) + +include $(HORIZON_ROOT)/build/omake/commondefs + +DefineCommandVars() + +.PHONY: all build clean clobber +.PHONY: run run-scripts + +# +# OMakefile の読み込み +# +.SUBDIRS: . + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/OMakefile b/branches/0thNUP_No_NUP/CardSaveDataMover/body/OMakefile new file mode 100644 index 0000000..d5a78c7 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/OMakefile @@ -0,0 +1,63 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: Omakefile +# +# 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. +# +# $Rev: 25650 $ +#---------------------------------------------------------------------------- + +SUPPORTED_TARGETS = CTR-T*.Process.MPCore.* +#CTR_APPTYPE = BOTH +#CTR_APPTYPE = CARD +CTR_APPTYPE = NAND + +#demoライブラリ位置指定 +#SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir ../common/include) +#SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir ../CTR_SDK/sampledemos/common/include) +#INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) + +# ビルドするソースコードを指定します。 +#SDにセーブする場合はmembak -> exsave 変更 +SOURCES[] = + ./source/main.cpp + ./source/savefile/savedata.cpp + ./source/savefile/membak.cpp + ./source/savefile/savefile.cpp + ./source/screen/screen.cpp + ./source/gui/gui.cpp + ./source/gui/shfnt.cpp + ../common/sleep.cpp + ../common/common.cpp + +#LIBS += lib_demo libnn_am + +TARGET_PROGRAM = CtrSaveDataMover + +TITLE = CSM_body + +# ROMFS のルートパスを指定します。 +#ROMFS_ROOT = + +# 独自の RSF ファイルを指定する場合 +ROM_SPEC_FILE = body.rsf +DESCRIPTOR = $(CTRSDK_ROOT)/resources/specfiles/repairtool.desc + +# バナー、アイコン +CTR_BANNER_SPEC = banner.bsf + + +#Cia バージョン:マスタリング毎に更新すること +#メジャーはrsfで指定(Remasterversion) +MAKECIAFLAGS = -minor 0 -micro 6 + +include $(ROOT_OMAKE)/modulerules + +build: $(DEFAULT_TARGETS) diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner.bsf b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner.bsf new file mode 100644 index 0000000..516f44d Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner.bsf differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/BannerModel_test/COMMON/COMMON.cmdl b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/BannerModel_test/COMMON/COMMON.cmdl new file mode 100644 index 0000000..63f2c7a --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/BannerModel_test/COMMON/COMMON.cmdl @@ -0,0 +1,274 @@ +サソ + + + + + MetaData + + + + + + + + + ContentSummaries + + + + + + + + + + + + + + + + + + + + + + + + + + + + ModelDccToolInfo + + + OptimizationLogs + + + + + + + + + + + + Skeleton.Bones["*"].AnimatedTransform + + + + + + + IsVisible + + + Meshes["*"].IsVisible + + + IsBranchVisible + + + + + + + Materials["*"].MaterialColor.Emission + + + Materials["*"].MaterialColor.Ambient + + + Materials["*"].MaterialColor.Diffuse + + + Materials["*"].MaterialColor.Specular0 + + + Materials["*"].MaterialColor.Specular1 + + + Materials["*"].MaterialColor.Constant0 + + + Materials["*"].MaterialColor.Constant1 + + + Materials["*"].MaterialColor.Constant2 + + + Materials["*"].MaterialColor.Constant3 + + + Materials["*"].MaterialColor.Constant4 + + + Materials["*"].MaterialColor.Constant5 + + + Materials["*"].TextureMappers["*"].Sampler.BorderColor + + + Materials["*"].TextureMappers["*"].Texture + + + Materials["*"].FragmentOperation.BlendOperation.BlendColor + + + Materials["*"].TextureCoordinators["*"].Scale + + + Materials["*"].TextureCoordinators["*"].Rotate + + + Materials["*"].TextureCoordinators["*"].Translate + + + + + + + + + + + + + + + + + + + + 0 + + + + 0 1 2 1 3 2 + + + + + + + +-12 -6 6.5 +12 -6 6.5 +-12 6 6.5 +12 6 6.5 + + 0 0 1 + +0 0 +1 0 +0 1 +1 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + Textures["banner"]@file:Textures/banner.ctex + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DccToolSourceNode + + BONE_00 + + + + Shapes[0] + Materials["MT_00"] + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/BannerModel_test/COMMON/Textures/banner.ctex b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/BannerModel_test/COMMON/Textures/banner.ctex new file mode 100644 index 0000000..c36b19c --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/BannerModel_test/COMMON/Textures/banner.ctex @@ -0,0 +1,17 @@ +サソ + + + + + + + + + + + B/YH9gf2B/YH9gf2B/YH9wf2B/YH9gf2B/YH9wf2B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf2B/YH9gf2B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/gH9wf3B/cH9wf3B/gH+Af4B/cH9wf3B/cH+Af4B/gH+Af3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Af5B/gH+Af4B/gH+Qf5B/kH+Qf4B/kH+Af5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+Qf6B/kH+Qf5B/kH+gf6B/oH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/sH+gf6B/oH+gf6B/sH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf6B/oH+gf7B/sH+wf7B/oH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf8B/sH/Af7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH/Af8B/wH/Af7B/wH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf8B/0H/Qf9B/0H/Qf8B/0H/Qf9B/0H/Qf9B/0H/Af8B/wH/Af8B/0H/Af9B/wH/Af8B/wH/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/4H/Qf+B/0H/Qf9B/0H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/gf9B/4H/gf+B/4H/gf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/wf+B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/4H/gf+B/4H/wf/B/8H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/gf/B/4H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/8H/gf/B/4H/wf/B/4H/gf+B/4H/gf+B/8H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf9B/0H/Qf9B/4H/Qf9B/0H/Qf9B/0H/Qf+B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf8B/0H/Af8B/wH/Af8B/0H/Af8B/wH/Af8B/wH/Af9B/0H/Qf9B/0H/Af9B/wH/Qf9B/0H/Qf9B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af7B/wH/Af8B/wH/Af7B/sH+wf8B/sH/Af7B/sH+wf7B/sH/Af7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/oH+wf6B/sH+wf7B/sH+gf6B/oH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf4B/gH+Af4B/gH9wf4B/cH+Af4B/gH+Af4B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf4B/gH+Af4B/gH+Qf4B/kH+Af4B/gH+Af5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf5B/oH+Qf5B/kH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/sH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/sH+wf7B/sH+wf6B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/wH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/wH/Af8B/sH+wf7B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af9B/wH/Qf8B/wH/Af8B/0H/Qf9B/0H/Af9B/wH/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/gf9B/0H/Qf9B/0H/gf+B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/4H/Qf+B/4H/gf+B/4H/Qf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/8H/gf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf/B/8H/wf/B/4H/wf+B/8H/wf/B/8H/wf+B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/8H/wf/B/4H/wf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/8H/wf/B/8H/gf+B/4H/gf/B/8H/wf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/gf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/0H/Qf9B/0H/gf9B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf8B/0H/Qf9B/0H/Af8B/wH/Af9B/0H/Qf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af7B/wH+wf7B/sH+wf7B/sH+wf8B/sH+wf7B/sH+wf8B/wH/Af8B/wH/Af8B/sH/Af8B/wH/Af8B/sH/Af7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf7B/sH+wf7B/sH+gf6B/oH+wf7B/sH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/oH+Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/kH+Qf6B/oH+gf5B/kH+Qf5B/kH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/gH9wf4B/cH9wf3B/cH+Af4B/gH+Af3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af5B/gH+Af4B/gH+Af5B/kH+Qf4B/gH+Af5B/kH+Qf5B/kH+Af5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+Qf6B/kH+Qf5B/kH+gf6B/oH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf6B/oH+wf7B/sH+wf7B/oH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH/Af7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf8B/wH/Af7B/wH+wf8B/wH/Af8B/wH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/0H/Qf9B/0H/Qf8B/0H/Qf9B/0H/Qf9B/0H/Af8B/wH/Af8B/0H/Af9B/wH/Af8B/wH/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/0H/Qf9B/0H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/Qf9B/4H/gf+B/4H/gf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/wf+B/8H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/4H/gf+B/4H/wf+B/8H/gf+B/4H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/4H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/gf+B/4H/wf+B/8H/wf+B/4H/gf+B/8H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/gf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf9B/0H/Qf9B/4H/gf+B/0H/Qf9B/0H/Qf+B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Af8B/wH/Af8B/0H/Af8B/wH/Af8B/wH/Af9B/0H/Qf9B/0H/Qf9B/wH/Qf9B/0H/Qf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af7B/wH/Af8B/wH/Af7B/wH+wf8B/wH/Af7B/sH+wf7B/sH/Af7B/wH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/oH+wf6B/sH+wf7B/oH+gf6B/oH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf6B/sH+gf7B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf6B/oH+gf6B/kH+Qf5B/oH+Qf6B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/gH+Af4B/gH9wf4B/gH+Af4B/gH+Af4B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Qf5B/kH+Qf5B/gH+Qf5B/kH+Qf5B/kH+Qf4B/gH+Af4B/gH+Af4B/kH+Af4B/gH+Af4B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf5B/oH+Qf5B/kH+Qf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf5B/kH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/sH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf7B/sH+wf6B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf8B/sH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/wH/Af8B/sH+wf7B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf8B/wH/Af8B/wH/Qf8B/0H/Af8B/wH/Qf9B/0H/Qf9B/0H/Qf8B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/gf+B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/Qf+B/0H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf/B/8H/wf/B/4H/gf+B/8H/wf/B/8H/wf+B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/8H/gf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/8H/wf/B/8H/wf+B/8H/gf/B/4H/wf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/Qf+B/0H/gf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/Qf9B/0H/gf9B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf8B/0H/Qf9B/0H/Qf8B/0H/Af9B/0H/Qf8B/wH/Af8B/wH/Qf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/wH+wf7B/sH+wf7B/sH+wf8B/wH/Af8B/wH/Af8B/sH/Af8B/wH/Af8B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf7B/sH+wf7B/sH+gf7B/oH+wf7B/sH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf6B/sH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/oH+Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/kH+Qf6B/oH+gf6B/kH+Qf5B/kH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/gH9wf4B/cH9wf3B/cH+Af4B/gH+Af3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Af5B/gH+Af4B/gH+Af5B/gH+Qf4B/gH+Af5B/kH+Qf5B/kH+Af5B/gH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+Qf6B/kH+Qf5B/kH+gf6B/oH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+gf6B/oH+gf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf6B/oH+wf7B/sH+wf7B/oH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH/Af7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf8B/wH/Af7B/sH+wf8B/wH/Af8B/wH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf9B/0H/Qf8B/0H/Qf9B/0H/Qf9B/0H/Af8B/wH/Af8B/wH/Af9B/wH/Af8B/wH/Af9B/wH/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/4H/Qf+B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/gf9B/0H/gf+B/4H/gf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/wf+B/4H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/4H/gf+B/8H/wf/B/8H/gf+B/4H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/gf+B/4H/wf/B/8H/wf+B/4H/gf+B/8H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf9B/0H/Qf9B/4H/gf+B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf8B/0H/Qf8B/wH/Af8B/0H/Af8B/wH/Af8B/wH/Af9B/0H/Qf9B/0H/Qf9B/wH/Qf9B/0H/Qf9B/wH/Qf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af7B/wH+wf8B/wH/Af8B/sH+wf7B/sH/Af7B/wH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf6B/sH+wf7B/sH+wf6B/oH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/oH+gf6B/oH+gf7B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/oH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf6B/oH+gf6B/kH+Qf5B/oH+Qf6B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/gH+Af4B/gH9wf4B/cH+Af4B/gH+Af4B/cH9wf3B/cH9wf3B/cH+Af3B/cH9wf3B/cH9wf3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af5B/kH+Qf5B/gH+Qf5B/kH+Qf5B/kH+Qf4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf5B/oH+Qf5B/kH+Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf6B/kH+gf6B/oH+gf6B/kH+gf6OPsH+gf6m/2r/gf6B/oH+gf6B/oH+gf6B/oH+gf6q/6r/gf6B/o4+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/oH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oo+2n8B/oH+gf6B/sH+wf7B/sH+wf6B/qr/qv+B/sH+6v+q/4H+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/ur/pv+B/sH+2n9B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7Wf1p/Qf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf8B/sH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/wH/Af8B/sH+2n9af0H/Af8af1p/Qf8B/wH/Af8B/wH/Af8B/wH/Af8af1Z/Qf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af9B/wH/Qf8B/wH/Af8B/wH/Qf8B/0H/Af9B/wH/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Wn+q/8H/Qf9B/0H/Qf9B/0H/Qf9B/0H/av/q/8H/Qf9m/44/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/gf9B/0H/Qf9B/0H/gf+B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/Qf+B/0H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/8H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/8H/wf/B/4H/gf+B/4H/wf/B/8H/wf+B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/GP8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/9p/2n/B/8H/2n/af8H/wf/B/8H/wf/B/8H/wf/B/8H/2n/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8Y/2n/B/8H/2n/af8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/gf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/8H/wf/B/8H/gf+B/4H/gf/B/8Y/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+Wf9p/wf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/mn/OP4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/gf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/Qf9B/0H/gf+B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf8B/wH/Af9B/0H/Qf9B/wH/Af8B/wH/Qf8B/0H/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af7B/sH+wf7B/wH+wf7B/sH+wf7B/sH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/sH/Af7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf7B/oH+wf7B/sH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf7B/sH+gf6B/oH+gf6B/sH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/oH+Qf6B/oH+gf5B/kH+Qf5B/kH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf4B/kH+Af5B/kH+Qf4B/gH+Af4B/gH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Af5B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/cH9wf3B/gH+Af4B/gH+Af3B/cH9wf4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af5B/kH+Qf4B/gH+Af4B/kH+Qf5B/kH+Af5B/gH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+c3uB/kH+Qf5GPqb7N/dz9zPzAf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/lq2wf5jbq/u7+7r6qvqgf5jqkH+Y+In5mfmY+Ij4i8/f//7+7v7v/////v7u/u393f3c/Mz8zf3c7dSskJpv/////v7u/u//+8/e/u7+6+3N/dCZaNut/d393PzM/Mv7t8ua+qGpYJlgqFCoUKZI6ZCoV+iAp0CmQLZAtkC1MKdBt1C2QLUzyGK3ULUwtkC1MLUwtkC2QLZAtkCnQKdQjpevxJ2s7t/////+/u7+5aud/dW6jPzN/d393PzIy6/////+/u7+7/////7+7v7t/d390al7/M393f3c/Mz8wrdp66C2QLZEuXCnUKZAp0C2QLZAp1CnUKZApkCnUKdQp1v7s8hq+qv7u/u6+qr6pMhp+ZXXePiJ+Zn5mPiI+I/////+/u7+7//+//7+7v7t/dz92Nuhp2393f3a67rstq7Bjrve1a2+/////v7u/uW7mMywqGjbrf3d/dz8zPzDx2C1QcVAxDC1QrdQxDC1MMQwxDDEMMQwxDC0MMQwtUC2R9qQtUbZi/u7+7r6qvqgtUXYcLZF13n5mfmY+Ij4j/////7+7v7v/////v7u/u393f3c/MW6mc3M/dCYYal//////v7u/u3f5J7O/u3+7f3d/drsvPzN/d393PzM/Mv7srhq+qC2QKdSt2HGWfqZ+ZfoiPiI+In5mfmY+Ij4i/u7+7r6qvqr+7v7uvqp+pn5mfmY+Ij4ifmSxVHFQMQwf7B/wI2gjrB/wH/AjrB/xaygjJS6kJqAjKCOsIuQjKB/wH/Af8B/wH/Qf9B/wH/QfsB/wI6wf8B/w4/Qf8Wew7hwqGC1QKZQmXCbkKhgmoC1QLVAxDC1QKdQmXCmUJhwjKCOsIygjrB/xJ7Af8GOwIuQjbCbkI2wfsB/wH7AfsGP3d/7zu7+7/////7+7v7t/d393PzM/M393f3c/MjMv/////7+7v7v/////v7u/uzt293QmoCZff3d/dbKnPzL+7v7uvqq+qv7uNuq+qr6psup+ZCNtcmJ+Zn5mPiI+IGocKdq+qfpkLZSt2PHYLVJ+Zn5mPiI+In5l+iI+Ij4jN/hjs7+6c7QfsB/0I2wjs390qumypCocIugjKCZgJqQf9B/0I7Af9B/0H/gf9B/4I2wjsa8vPzDjtWe3PzM/MC2UKdgtVC2UKhzqpCnZLmSxlC2WPiCx2CnYKhwp2Coe/u7+7r6qvqr+7v7uvqq+qfZmfmQmYKpkJuhqpTJh+iAf+B/4H/gf+B/4H/gf+B/4H/gf+z8yt3Qf+B/4Y7Qf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/r7dB/4H/s/Mz92/u7+7r6qvqq7MGNyvqmu6j5mfmY+Ij4ifmX2Zj4h+iAjsv7sIy6+qv7u/u6+qr6oJqZ+ZCod+iJ+Zn5mPiI+IB/4H/gf+B/4H/gf+B/4H/gf+B/5Z7Qf+B/4H/gf+vt0H/gf/B/4H/wf/B/8H/wf/B/8H/8/Mvt0H/wf/GP4H/nvMCO1KywjMCO2/uwjMr6pLqgm6XIgJmAm6n5kJmI+Iv7u/u6+qr6pK3QjtSstay5+Zn5mPiI+IKqqOmQmZj4gH/wf/B/8H/wf/B/8H/wf/B/8H/wf+i90H/0n+z93PzAf/B/8H/wf/B/8H/wf/B/9J/gf/z8zP3Qf/B/+L3Qf+ncy/u6+qr6q/u7+7r6qeu5+Zn5mPiI+IbKoJqjuIXYi/u7+7r6qvqr+7e8yvqq+qbJmfmY+Ij4ifmZ+Zj4h/iAf/B/8H/wf/B/8H/wf/B/8H/wf/B/4H/wf/B/8H/wf/B/8H/wf/B/8H/5v/B//N7gf/B/8H/wf/B//e7Qf/z8wI3QjuCMsIzAfuB/4I3QjuCZkJqgp3CYgIywjdCaoIywf/B/8H/gf/B/+/uwf/r6oI7gf/CN0H7gf+n5kH7o+I/////+/u7+7/////7+7v7t/d393PzM/M392+3c/MGan//+//7+7v7pv/B+7v7r3uz93f3RqZv8zf3d/dz8zPzL+7v7uvqq+qjbsKd22ZCmafmZ+Zj4iPiF2IC2VddwtVCnY8iAtVC1W/u7+7n6qvqgtVC1ULVQtVXXefmT1mj4gH/gf/CN0I7gf/B/8H7gf/nN0IzM/MKrsI3QjuCLsIzAf/B/8H/wf/B/8H/wf/B/8H/wf/jN3P3Un/Sf/PzM/Mv7uNqq+qn6oJmWu7Cohsqp+Zn5mPiI+IG3cKiCx3Cma/u7+7r6qvqr+7v7ueu6+qjpmOmQp3O4gJqjuqXYh/iAf/B/8H/wf/B/8H/wf/B/8H/wf/z8yc3Qf/B/8Y7gf/B/8H/wf/B/8H/wf/OP/e7gf/B/8Y/63di+7f3c/Mz8y/u7+7r6qvqq7MCN2vqjq7n5mfmY+Ij4ifmWyZj4hdiErdv7tKu6+7v7u/u6+qr6oJqgmqCogKiI6Zn5l+iI+Iev+b/+/u7+4H/wf/OP8H/9/dzt3PzM/MCO4I7a3MCMwH/wf/B/8H/wf/B/8H/wf/CO4I7hnMnN0H/lnuz8zPzL+7v7uvqq+qv7tbu56qGoifmTuIj4gsdwpmCmYLVQtVfLu/u46qr6q/u7+7r6qeugt3jpkLZht3fZkJmSuIbYgH/wf/B/8H/wf/B/8H/wf/Sf4H/8/Mz90H/wf/i90H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/4H/gf/B/8H/gf/v7u/u6+qr6q/u4zMr6qvqkuZn5l/iI+In5mfmY+Ij4gI3QjtKbsIzAfuB/4I3QjtO5kJqkyHCogIuwjcCakIuwf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+vP///83u7+7/////7+7v7t/d393PzM/M393f3c/Mz8wH/gf/B/4H/gf/B/4H/wf+CO0H/gjcB+4H/gf+B/45y7+7v7uvqq+qv7u/u6+qO4ifmZ+Zj4iPiJ+ZCnaPiAtm3v8Y/u/uve4H/gf+CNwI7d/d393PzM/MWssZy67MncsH/rz/eu3v7v/////v7u/u393f3c/Mz8zf3d/dz8zPzL+7v7uvqq+qv7u/u6+qr6p+iJ+ZPWaPiJ+Zn5mPiI+Iv7u/u6+qr6q/u7+7XJivqp+ZXXePiBxUPGafmS1Vj4j//97/7+7v7gf9B/0I3Ajc393f3c/Mz8xaywi6S6oJmAf9B/0I7AftB/0H/Qf9B/0IywjcCak6ywjsOO3PzM/Mv7u/u6+qr6pMiAp2PHYLZZ+Zn5mPiI+IXncsZU5mTWY7mL+7jqqvqr+7v7uvqq+qn5mfmY+Ij4ifmRmoXYgKhwf+B/0H/Qf9B/0H/Qf9B/1Z7Qf9z8zPzAf9B/2s3RjsB/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/UnsB/0H/c7cz8y/u7+7nrqvqr+7rsuvqq+qCalcmQqHCoefmZ+Zj4iPiAjbSttbukq6v7u/u6+qr6qOmTuYj4gKhp+Zn5mPiI+IB/0H/Qf9B/0H/Qf9B/0H/Qf9B/2+3CjsB/0H/Qf8KOwH/Qf9B/0H/Af8B/wH/Af8B/0H/M/cz8wH/Af8rNwH/L+7KduvqgjKCOtK2wjKSsqfmRmpj4g7hwm5OqkJlzuXv7u/u6+qr6q/uwjrr6oIyp+Zn5mPiI+In5kZuX6IO5cH/Af8B/wH/Af8B/wH/Af8B/wH/Af8GPwH/Af8rNzPzAf8B/wH/Af8B/wH/Af8B/xZ/Tj8z8zPzAf8B/vO3GrsGOuuy3y6r6q/u7+7r6qvqp+Zn5mPiI+In5k6qX6IO4e/u7+7nrqvqr+7v7uvqq+qCaiOmW6Ij4ifmZ+Zj4iPiAf8B/wH/Af8B/sH+wf7B/sH+wf7B/sH+wf7B/vO3M/MB/sH+wf7B/sH+wf7B/sH+wf7B/u+3HrsB/s4/M7cz8w52gjajbpKub+7v7uvqq+qjpk7mF2HCnWfmZ+Zj4iPiL+7v7uvqq+qv7u/u6+qr6qfmZ+Zj4g8hkuYn5kKdSt2B/sH+wf7B/sH+wf7B/sH+wf7B/u+3BjrB/sH+wf6B/oH+wf7B/sH+wf7B/sH+wf6B/sH+wf6B/oH+wf6B/oH+r+7e8uvqmy5COkI6gjICMifmQqWC3UKdQmnCacKhQmWB+oH+gjZCOkH+gf6B/oH+gjICNkJpwjICOkH+gjpB/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf6B/oH+gf6B/kH+Qf5B/oH+gf6B/oH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/gH+Af4B/kH+Qf5B/kH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Qf5B/kH+Qf5B/gH+Qf4B/kH+Qf5B/kH+Qf4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Af5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+Qf5B/kH+Qf6B/oH+gf6B/l/dwf5XnZ/d393b2ZvZgf5PXUH+RqWX1VfVU9ET0QH+Qf5B/kH+gf6B/oH+gf6B/kH+gf6B/oH+gf6B/oH+gf5CNgH+QjYLzM/MwqGLyIH+QjpB/oI6QjHCnUIyAmnb3cLZG9mLGQLUwtTC1MLZF9VT1RPRE9EC1MLZD9ELVQLZAp1CnQJhgqFCZYJp112CnUJlhtkLVQ7dl9VT0RPRD8zPzMvIi8iPzM/My8iLyIfER8RCnUMMh8RHxENIQ4RPzM/My8iLyI/Mz8zLyIeMh8RHxENIQ0yHiEKdQtkC2QJlgmWCLgItwmWCZYJtwm3GagI2SuGCNkIyQjICNkI2U12f3dMdm9mf3d/d29mb2Y8dl9VLGVPRF9VX1VPRE9EGZcIyQmnCbcIyQjZCLgIyAmGCZYKdQp1CZcJpwmGCacsZT8zHFQvIj8zPzMvIi8iC2UfEQmnDEMfER8RC2QLUwtTC1MLVAtUC1MLZAtkCnUcVAtUHFQLZAtkCoYKZQqGCnVNdgqGPHZ/d393b2ZvZgmXPHYJpyxlX1VfVU9ET0QdQwtkHiILVAplCoYLZAqGHxELVAxDC1QLZAp2C2QKdQmnHGUJpxxUPzM/My8iLyIJlwp1CZcJuB8RHxEKdQtlf3d/d29mb2Z/d393X1VvZl9VPlRPRBxEDEMuRAxDDDN/d393b2ZvZj1VDENvZh1EX1VfVT9DT0RfVU9ET0RPRD8zHUMvIh4yDEMMMgxDDDMfER4hDEMMQwxDDEMLVAtULzI/Mx4iLyI/Mz8zLyIvIg0yHxELVAxDHxEfEQxDDDMMQwtUDEMLVAplCZcKdQmXC0MLZBxEC2UKdgmoCoYJqAi5CNsIuQjbB+wI6wf8S5gIygjrCMoI7Af8TWYH/D1VHjMLZR4iC2UKhgmoCnYJmB4hC1QMQwtUCnUJlwplCocIygjsCMoI6wf8LGUH7Am5CLkI2wmpCMsH7AjsCOwI7G2ICalvZjuHCoc9dgmXCnZfVU5lT0RPRAmYCnY+VBtmb3d/dwtUHFR/d393X2VvZgtlC1QLZRxUHVRfVT9ET0Q/Mz8zLyIvIj8zPzMvIi8iCZcfIQjKCakfER8RC1QNMj8zPzMvIi8iPzM/My8iLyIfER8RDiENIh8RHxENMgxEf3d/d29mb2YKdgmHK3YKh19VX1VPRE9EPVUsZRxUPkQqmH93b2ZvZn93f3dvZm9mX1VfVU9ET0RfVT1lP0QLZj8zPzMvIh0zC1QeQwxEDEMOIgxEC1QMRAxEDEQMRAxEPzM/My8iLyI/My8zLyIvIg0zHxELVAtUHxEfEQwzDDN/d393b2ZvZn93bndvZl5VLFVfVS1ET0RfVU9ET0Q/QwtlXncLVD1Vf3d/d29mb2YMRBxEDEMMRF9VX1U/RE9EPzM/My8iLyI/My8zLyIvIh8RHxENMw0yHxEfEQ0iDDMMQwxEDEMMRB1DPzMLVB8iDEMMRAxDC0QLVAxEC1ULZl13CndfZgtmK3d/dz1mb2ZfVSxVT0RPRE9VX1VPRE9Ef3dud29mTWYrd393LGZvZl9VLGU/RAtlHFVfVQxVT0Q/Mz8zLyIvIj8zPzMvIh8iHxEfEQtUDSIfEQwzDEQLRB1DC1ULVAtUC1UvMwtUDTMMRAxEDEQMRAtUC1ULVQtVf3d/d29mb2Z/d393b2ZvZl9VX1VPRE9ET1UuRC5EDER/d393b2ZeZX93LGYdVAxEHEQMRAxDDDMMRC1ELkM/RD8zPzMvIi8iPzMvMy8iLyIOIh8RC2YMRB8RHxENIg4RHjMvMy8iLyI/My8zLyIeMx8RHxEOIg0iHxEMRAxEC1ULZgp3C1ULZgmICaoKhwmqC1QLZgtVC2YKdwmZCncJqgjMCO4IzAjuB+5/dwjub2YIzAjtCMwI7QjuX1UI7k9EC1UKZgtlCncKiAmqCYgJqgtmCncLZgp3CZkJuwmZCbsIzAjuCMwI7gjuPzMI7i8iCMwI7gjMCO4I7h4zCO4Jqn93f3dvZm9mTXcLVT1mC1VfVV9VT0RPRD5VC2U/RAtVC1ULVQtVC2YsZn93LGZvZgtmCmYLZhxVPVVfVU9ET0Q/Mz8zLyIvIj8zLzMvIi8iHxEfEQp3C1UfER8RDEQMMy4zPzMvIi8iPzM/My8iLyIfER8RDDMMMx8RHxEMRAtVf3d/d29mb2YsZgtmLGYsVV9VX1VPRE9EHFU+VQtVPkQ8d393b2ZvZn93f3dvZm9mX1VfVU9ET0RfVS1VPkQLVT8zLjMvIgxVC1UuMwtVDTMMVQtVC1ULVQtVC1ULVQtVPzM/My8iLyI/My8zLyIvIg0iHxELVQtVHxEfEQwzDDN/d393b2ZvZn93TWZvZj5VPlVfVT5ET0RfVU9ET0Q/RAtmCncLVQtmf3d/d29mb2YMRAtVDEQLVV9VX1U/RE9EPzM/My8iLyI/My8zLyIfIh8RHxENMw0iHxEOEQ0iDDMMRAtEDEQLRC4zPzMeIi8iDEQLRAxEC1UOIh8RC1QNIn93LGZvZhxVC1ULVQtVC1VfVRxVT0QtRAtVC1ULVQtVC1U8ZixVb2Z/d393b2ZvZk9VX1VPRE9EX1VPVU9EPkQ/My4zLyIvIgtVC2YLVQtmHxENMwtlC2YLVQtmC2YLZi8zPzMdMy8iPzM/My8iLyIKdg0zCnYKdx8RHxEKZgxEf3d/d29mb2Z/d393b2ZvZhtmTlUKZj9EX1VfVU9ET0RNZgp2PVULVQqICakKdgmYLkQLVC5DDEQLZgqIC1UKdy8zPzMvIi8iPzM/My8iLyIfER8RDEMNMx8RHxENIg0iHjMMRB4iDEQLVQp3C1UKdw4iDEQMMwxEC1UKdwtVCncIywjtCLoI3Af+ObsH7im6CaoIzAmpCMsI7QjcCO0I7X93f3dvZm9mf3cLZm9mLGZfVV9VT0RPRF9VHGVPRC1UCZkIywmZCMsI7QjtCO0I7QmZCMsJmQjLCO0I7QjtCO0/Mz8zLyIvIj8zLjMvIh8iHiIfEQmpCnYfER8RC1ULVAtEf3cLVF9Vf3d/d29mb2YLVC1EC1UMRF9VX1U+RD9Eb2YMMz5VDDMtRH93PkRvZi1EDDMMRAxDLkRfVS5DT0QLVQtUC1ULVQtUC1QLVQtVC1QLVQtlC2ULZQtlC2UKdgtUC1QLZQtlLzM/My8iLyIKdgxUCocKhx8RHxELVQtUf3d/d29mb2ZOVU5lPlU+VV9VX1VPRE9ELkQuRB1DHUN/d393b2ZvZk12CnY9ZQtlX1VfVU9ET0Q+VAtUT0QtRD8zPzMvIi8iDUMMQwxDDEMfER8RDEQMRAxEDEQLVAtULzM/Mx4yLyI/Mz8zLyIvIgxDDiIMRAtEHxEfEQwzDSIKdgplC2ULZW53f3dfZm9mC1ULZQxUPkRfVV9VT0RPRH93LHZvZixlf3d/d05lb2ZfVQxUP0QLVC1UX1UMVE9EPzM/My8iLyI/Mz8zLyIvIh8RHxEOEQ0iHxEMQwxDC1QuQwtUC1QLVAtULjMLVAxDC2QLVAtUC1QLVAtUC1QLZH93PHZvZk5lCnZNdgtlTmZfVU9VT0RPRBxUX1VPRE9Ef3d/d29mb2ZNd012PGY9ZV9VX1VPRC5EC2U9VAtUHUQ/Mz8zLyIvIj8zPzMvIi8iDTIfEQtlDEMfER8RDSIMQz8zDEMeMgtTC1QMUwtTC1MMQwxDDEMMQwxDC1MLQwtUf3d/d29mb2Z/d393b2ZvZl9VX1VPRE9EX1VOVE9EHUN/d393b2ZvZn93f3dOVRxDLUQMQwxDDEMMQx1DDDM/Qz8zPzMeMi8iPzM/My8iLyILUx4hC2QLZB8RHxEMMg0hLzMuMy8iLyIvMz8zLyIvIh8RHxEOEQ4hHxEOIQ0yDEMcVAtkDEMLU393f3dvZm9mHUMMQy5DC0NfVV9VT0RPRH93HGVvZgtTC2QLVAtTC1NfVQtTT0QMQwtDC0MLQwtTLjMLUw1DC1Q/Mz8zLyIvIgtTC2QLVAtkHxEfEQxDDEM/MwxDLyIdMgtTC1QLVAtkHxEOIQxDC1MLVAtkC2QKZAtUC2QLUwtUCnQKhQpkCoULUwtkC2QKdAp1CZYKhQmnCacIyAmmCMgI2Qf6CNkH+gmnCMgIyAjZCOkH+gjpB/oKZAqFCnUJlgmmCLgItwjZCoUJpgqFCacIyAjpCMgI6QjZCOkH6Qf6B/kH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/oH+Qf6B/oH+gf5B/kH+Qf5B/kH+gf5B/oH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf4B/kH+Af5B/kH+Qf5B/gH+Af4B/gH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af5B/gH+Af4B/gH+Af5B/kH+Qf4B/gH+Af4B/kH+Qf5B/kH+Af5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf6B/kH+Qf5B/kH+Qf6B/oH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B+kH+gf6CNgItwjpCMgH+gf6B/oH+gfpCNkH+gfpB/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gmWCnUJpwqFC2QLUwp0C2QIyAmnCNkIyAqFCnUJpwmWC0MLQwtTC1MLUwtTC1MLUwtkC2QKhQp1C2QLZAp1CoUH6QjZB/oH6gjICLgI6QjZB/oH+gf6B/oH+gfqB/sH+wmnCacIyQjICacJpwjICMkH6gjqB/sH+wjqCOoH+wf7C2QKdQtkCnUKhgmXCoYJpwp1CoUKhgmXCZcIuAm4CMkJpwmnCLgJuAmXCoYJpwqGCMkIyQjZCNkJuAmXCMkIuAmnCLgIyQjZCMkI6gjqB/sH6gf6B/sH+wf7B/sH+wf7COoI6gf7B/sI2gjJB+sI6gf7B/sH+wf7B/sH+wf7B/sLZAtkCnUKZQtlCoYKdQqGCoYKhgmnCZcKhgmXCacJqAmXCbgJpwi4CbgJlwi5CagJuAjJCMkI2gjJCLkI2gjJCMkIuQjaCNoIyQjJCNoI6gf7B+sH/Af8B/sH+wf8B/wI2gjqCOsH6wjrCNsH+wfrB/wH/Af8B/wH/Af8B/wH/AqGC2UJhgp1C1QLVAp1CnUJqAqGCLkJqAqGCoYJqAmoC2UKZQp2CoYKZQtlCoYKdgmHCZcJqAm5CZcJhwm5CagI2gjJCOsI6wjJCMkI2wjbB/wH/Af8B/wH/Af8B/wH/AjKCMoI6wjrCMoIygjrCOsH/Af8B/wH/Qf8B/wH/Qf9C2QLZQp1CmUKZQqHCnYKhwqGCoYJqAmoCocJmAmoCbkJqAjKCakIygjsCOwI7AjsCLkI2wjKCNsI7AfsB+wH/QjKCMoI2wjbCMoIygjbCOwH/Af8B/0H/Qf8B/0H/Qf9CNsH7AfsB/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0IywmpCNsIugmXCnYJmAqHCOwIygfsCNwJqQmYCMoJqQtlC1UKZgtlC1QLVAtUC1QKdgpmCZgKhwtlC2UKhwp2B/0H7Af9B/0I3AjLB+0I7Af9B/0H/Qf+B/0H/Qf+B/4IugmpCNwIywmpCZgIywjLB/0H7Qf+B/4I7AjsB/0H/QtEDEQLVAtUC0QLVAtVC2ULZQtlCncKhwp2CncJmAmZC1ULZQpmCnYLVQtVCnYLZgqHCZgJqQm6CYgKhwm6CakJqQmpCMsIywm6CMsI3AjcCOwI7Qf+B/4H7Qf9B/4H/gjLCNsI7QftCMwIywjtCO0H/gf+B/4H/gf+B/4H/gf+C0QMRAtVC1QMQwxDC0QLVAp2CmYJmAmIC2ULZQqHCocMRAtVC1ULZQtlCnYKdgqHCmYKdwqICZkKiAmZCakIugi7CboI3AjcCakJqgjMCMwH/gfuB/4H/gftB+0H/gf+CaoIuwjcCNwIywjcCO0I7QfuB+4H/gf/B/4H/gf/B/8Kdwp2CogKhwtlC1UKdgtmCakJmQi7CLsJiAqHCaoJqQtUC1ULZQtmC2UKZgp3CogKdwqHCZkJqQmICakJqgi7CNwI3AfuCO0IzAjLCO0I7Qf+B/4H/wf/B/4H/gf/B/8IywjLCN0I7QjMCN0I7QfuB/4H/gf/B/8H/wf/B/8H/wp3CncJiAqIC2YLVQp3CmYJqgmqCMwIzAmZCogIuwmqC1QMRAtVC1UMRAtVC1ULVQp3CmYJmQqIC2YKZgqICogI7QjdB/4H/gjcCMwI7gjtB/8H/wf/B/8H/wf+B/8H/wm7CaoI3QjMCaoJqgjMCMwH7gjuB/8H/wjuCO4H/wf/C2YKdwpmCocJmQm7CZkIuwp3CYgJmQmqCaoIzAi7CNwIzAjuCN0H7gfuCN0H7gjdCN0H7gjuB/8H/gjuB/8H7gm7CMsI3AjdCNwI7gjuB/4H7gf+B/8H/wf/B/8H/wf/B/4H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8IuwmZCMsJmQp3C1UKdwtmCMwJqgjdCMwJiAp3CaoJmQtVC1ULVQtVC1ULVQtVC1UKZgtmCogKiAtmC2YKiAqICO4I3Qf/B+4IzAi7CO4I3Qf/B/8H/wf/B/8H7gf/B/8JqgmqCMwIzAmqCaoIzAjMB+4H7gf/B/8I7gfuB/8H/wtVC1ULVQtVC1ULVQtmCmYLZgp3CogJmQp3CogJmQmqC2YLZgp3CncLZQtVCncLZgmZCZkJuwi7CZkKiAm7CaoJqgm7CMwI3QjLCMwI3QjuB+4H7gf/B/8H/wf/B/8H/wjdCN0H7gfuCMwIzAjuCO4H/wf/B/8H/wf/B/8H/wf/C0QMRAtVC1UMRAxEC0QLVQp3CmYJmQmIC2YLZgqICogMRAtVC1ULZgtmCnYKdwp3CmYKdwmICZkKiAmYCaoJqgi7CbsI3QjdCaoJqgjMCMwH/gfuB/8H/wfuB+4H/wf/CbsIuwjdCN0IywjMCN0I7QfuB+4H/wf/B/4H/gf/B/8KdgpmCncKdwpmCmYKdwp3CZgJiAmqCaoJiAmYCaoJqgp3CncKhwqICncKZgqICncJmQmZCboIuwmZCZgIuwm6CMwIzAjtCO0IzAjMCO0I7Qf+B/4H/wf/B/4H/gf/B/8IzAjcCO0I7QjcCMwI7QjtB/4H/gf/B/8H/gf+B/8H/wtVC1QKZgtVDEQMQwtUC0QKiAp3CaoJmQtmC2UKiAqIDEQLRAtUC1ULZQp3CmYKiAtmCnYKiAmYCocJmQmZCboIywi7CO0I3Qm6CaoI3AjMB/4H/gf/B/8H7gfuB/4H/gmqCboIzAjcCLsIzAjcCO0H7QftB/4H/gf+B/4H/gf+CakIywmqCMsI7QftCO0H7Qi6CNwIywjtB+0H/Qf9B/4I3Am6CNwIugmYCnYJmQqHCO0IywftCNwJqgmYCMsJugjcB+0H7Qf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0I7Qf+B/0I3AjLB+0I7Af+B/4H/gf+B/4H/Qf+B/4LZgtlCnYKdgp2CocKhwmYCocKhwmpCakJmAmpCakIygmYCakJqQi6CagJmAi6CakIygjLCNsI7AjLCLoI7AjbCMsIywjcCNwIywjbCOwI7Af9B/0H/gf+B/0H/Qf+B/0I7AftB/0H/QftCOwH/Qf9B/0H/Qf9B/4H/Qf9B/0H/QqHC2UJlwp2C1ULVAplC2UJqQmHCLoJqQqHCnYJqAmYC1QLVAtlCnULZQtVCnYKdQqGCocJqAmpCYcKhwmpCagI2wjKCOwI7AjKCLoI2wjbB/0H/Af9B/0H/Af8B/0H/QjKCMoI2wjrCMoIygjsCOsH/Af8B/0H/Qf8B/wH/Qf9C1QLVAtlC1ULVAtUC1QLVAp2CnUJmAmXC2ULZQqGCoYLVAtUC1QLZQtlCnUKdQqGCmUKdgqGCZcKhwmXCagIuQi5CbkI2wjaCagJqAjKCMoH/AfsB/wH/AjrCOsH/Af8CagIuQjKCNoIygjaCOsH6wfrB+wH/Af8B/wH/Af8B/wKdQp1CYcJhwplC1QKhgp1CagJqAjJCMkJlwqGCLkJqAtUC1QLZAtkC1QLZAtlCnUKdgp1CZcJlwqGCZcJpwm4COsI6wf7B/sI2gjJB+sI6wf8B/wH/Af8B/wH+wf8B/wIyQjJCOoI2gjJCMkI6gjqB/sH+wf7B/sH+wf7B/sH+wp1CnUKhgmWCnULZAqGCnUJpwmoCMkIyQmnCZYIyQm4C1QLQwtkC1QMQwtDC1MLVAqFCnUJpwmWC2QLZAqGCoUI2gjqB+sH+wjaCMkH6wjqB/sH+wf7B/sH+wf7B/sH+wjICbgI2gjZCacJpwjJCMgH+gfqB/sH+wjqCOoH+wf7C1QLZAtkCmQLZApkCnUKdQp1CnUKhgmWCoUKhQmWCacKZAtkCnUKdAtkCnUKdQqFCoUKhQmnCaYKhQmWCacJpwmnCbcIyQjZCLgIyAjZCNkI6gfqB/sH+wfqB/oH+wf6CMgIyAjZCNkIyAjICNkI6Qf6B/oH+gf6B/oH+gf6B/oJhgmnCZYJtwjIB+kI2AfpCaYItwi3CMgI2QfpCOkH+Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6CMgI2QjpB+kH6Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf6B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf6B/oH+gf6B/kH+gf5B/oH+gf6B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/gH+Qf4B/kH+Qf5B/kH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Af4B/gH+Af4B/gH+Af5B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af5B/kH+Qf5B/gH+Qf4B/kH+Qf5B/kH+Qf4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+Qf5B/kH+Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf5B/kH+Qf6B/oH+gf6B/kH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/oH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/sH+wf6B/sH+gf7B/sH+wf7B/sH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH/Af7B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/wH+wf8B/sH+wf7B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf8B/0H/Af8B/wH/Qf9B/0H/Qf9B/wH/Qf8B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/gf9B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/gf+B/4H/Qf+B/0H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf/B/4H/gf+B/4H/wf/B/8H/wf+B/8H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/4H/gf+B/4H/gf+B/4H/wf+B/4H/gf+B/4H/gf+B/8H/wf/B/8H/wf+B/8H/gf/B/8H/wf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/gf9B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/Qf9B/0H/gf+B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf8B/0H/Af9B/0H/Qf9B/0H/Af8B/wH/Qf9B/0H/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af7B/sH+wf7B/wH/Af8B/sH+wf7B/sH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/sH/Af7B/wH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf7B/oH+wf7B/sH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf7B/sH+gf6B/oH+gf6B/sH+gf7B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/oH+Qf6B/oH+gf6B/kH+Qf5B/kH+gf5B/oH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf4B/kH+Af5B/kH+Qf5B/kH+Af4B/gH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/gH+Qf4B/gH+Af4B/gH+Qf4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/cH+Af4B/gH+Af4B/cH9wf3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf4B/gH+Af4B/kH+Qf5B/kH+Af5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf6B/kH+Qf5B/kH+Qf6B/oH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf6B/oH+gf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf6B/oH+gf6B/sH+wf7B/oH+wf6B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH/Af7B/sH+wf7B/sH/Af8B/wH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf9B/0H/Qf8B/0H/Qf9B/0H/Qf9B/0H/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af9B/wH/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/Qf9B/4H/gf+B/4H/gf9B/4H/Qf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/8H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/4H/gf+B/4H/wf+B/8H/gf+B/4H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/4H/wf/B/8H/wf+B/4H/gf+B/8H/gf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/gf9B/4H/gf+B/0H/Qf9B/0H/Qf+B/0H/gf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf8B/wH/Af8B/0H/Af9B/wH/Af8B/wH/Af9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/wH/Qf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af7B/wH+wf8B/wH/Af8B/wH+wf7B/sH/Af7B/wH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH/Af7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf6B/sH+wf7B/sH+wf6B/sH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf6B/oH+gf7B/oH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf6B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf6B/oH+gf6B/kH+gf5B/oH+gf6B/oH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Af4B/kH+Qf5B/kH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Af5B/gH+Af4B/gH+Af5B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH9wf4B/gH+Af4B/gH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf4B/gH+Af3B/cH9wf3B/cH+Af3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf5B/kH+gf6B/oH+gf6B/kH+gf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/sH+wf6B/oH+gf7B/sH+wf7B/sH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH/Af7B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/sH+wf8B/sH+wf7B/sH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf8B/0H/Af8B/wH/Af8B/0H/Qf9B/wH/Qf8B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/4H/gf+B/4H/Qf+B/0H/gf+B/4H/gf+B/0H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf/B/4H/gf+B/4H/wf/B/8H/wf+B/8H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/4H/gf+B/4H/wf+B/4H/gf+B/4H/gf+B/8H/wf/B/8H/wf+B/4H/gf/B/8H/wf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf9B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/Qf+B/0H/gf+B/4H/gf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Af9B/0H/Qf9B/wH/Af8B/wH/Qf9B/0H/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af7B/sH+wf7B/wH/Af8B/sH+wf7B/sH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/sH/Af7B/wH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf7B/sH+gf6B/oH+gf6B/sH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/oH+Qf6B/oH+gf6B/kH+Qf5B/kH+gf5B/oH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Af5B/kH+Qf5B/kH+Af4B/gH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/gH+Qf4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/cH+Af4B/gH+Af3B/cH9wf3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH9wf3B/cH9wf3B/gH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf6B/kH+Qf5B/kH+Qf6B/kH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+gf6B/oH+gf5B/oH+Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/oH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf6B/oH+gf7B/sH+wf7B/oH+gf6B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf8B/sH/Af7B/sH+wf7B/wH/Af8B/wH+wf8B/sH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf9B/0H/Qf8B/wH/Af9B/0H/Qf9B/0H/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af9B/wH/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/0H/gf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/Qf9B/0H/gf+B/4H/gf9B/4H/Qf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf/B/4H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/4H/gf+B/4H/wf+B/8H/gf+B/4H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/gf/B/4H/wf/B/8H/wf+B/4H/gf+B/8H/gf/B/4H/gf+B/4H/gf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf9B/4H/gf+B/4H/Qf9B/0H/Qf+B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/wH/Af8B/0H/Af9B/wH/Af8B/wH/Af9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf8B/0H/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af7B/wH+wf8B/wH/Af8B/sH+wf7B/sH/Af8B/wH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf6B/sH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/oH+gf6B/oH+gf7B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf6B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf6B/oH+gf6B/kH+gf5B/oH+gf6B/oH+gf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf4B/kH+Qf5B/kH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Af5B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH9wf4B/gH+Af4B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf4B/gH+Af3B/cH9wf3B/cH+Af3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/oH+Qf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf5B/kH+gf6B/oH+gf6B/kH+gf5B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/oH+wf6B/oH+gf7B/sH+wf7B/sH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH/Af7B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/sH+wf8B/sH+wf7B/sH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf8B/0H/Af8B/wH/Af9B/0H/Qf9B/wH/Af9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/4H/gf+B/4H/Qf+B/0H/gf+B/4H/gf+B/0H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf/B/4H/gf+B/4H/gf/B/8H/wf+B/8H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/gf/B/4H/wf+B/4H/gf+B/4H/wf+B/4H/gf+B/4H/gf+B/8H/wf/B/8H/wf+B/8H/gf/B/8H/wf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf9B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/Qf+B/0H/gf+B/4H/gf+B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Af9B/0H/Qf9B/0H/Af8B/wH/Qf9B/0H/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/sH+wf7B/wH/Af8B/sH+wf7B/sH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/oH+wf7B/sH+wf7B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf7B/sH+wf6B/oH+gf6B/sH+gf7B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+Qf6B/oH+gf6B/kH+Qf5B/kH+gf6B/oH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf4B/kH+Af5B/kH+Qf5B/kH+Af4B/gH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf4B/gH+Af4B/gH+Qf4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/cH+Af4B/gH+Af3B/cH+Af3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af3B/cH9wf3B/gH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+gf6B/oH+gf6B/sH+wf7B/oH+gf6B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf8B/sH/Af7B/sH+wf7B/wH/Af8B/wH+wf7B/sH/Af8B/wH/Af8B/sH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af9B/0H/Qf8B/0H/Af9B/0H/Qf9B/0H/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf+B/0H/gf9B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/Qf9B/0H/Qf+B/4H/gf9B/0H/Qf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf+B/4H/gf+B/4H/wf+B/8H/gf+B/4H/gf+B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/4H/wf/B/8H/wf+B/4H/gf+B/8H/wf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/0H/gf9B/4H/gf+B/4H/gf9B/0H/Qf+B/0H/gf9B/0H/Qf9B/0H/gf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/wH/Af8B/0H/Af9B/wH/Af8B/wH/Af9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/wH/Qf8B/0H/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf8B/sH/Af8B/wH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH/Af7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf6B/oH+gf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/oH+gf6B/oH+gf7B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+gf6B/oH+gf6B/oH+gf5B/oH+gf6B/oH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf4B/kH+Qf5B/kH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/kH+Af5B/gH+Af4B/gH+Af5B/gH+Qf4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf4B/gH+Af4B/cH9wf3B/cH9wf3B/gH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/YH9wf3B/cH9wf2B/cH9wf2B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf7B/sH+wf6B/oH+gf6B/sH+wf7B/sH+gf7B/oH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/wH+wf8B/sH+wf7B/sH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/0H/Af8B/wH/Af9B/0H/Qf9B/wH/Af8B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/4H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/gf+B/4H/Qf9B/0H/gf+B/4H/gf+B/0H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/8H/gf/B/4H/gf+B/4H/gf/B/4H/wf+B/8H/gf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/8H/wf/B/4H/wf/B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/8H/wf/B/8H/wf/B/8H/gf/B/8H/wf/B/8H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/gf+B/4H/Qf9B/0H/Qf9B/4H/Qf9B/0H/Qf9B/0H/Qf+B/4H/gf+B/4H/gf+B/0H/gf+B/4H/gf+B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Qf9B/0H/Af9B/0H/Qf9B/0H/Af8B/wH/Qf9B/0H/Qf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Qf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/sH+wf7B/wH/Af8B/sH+wf7B/sH+wf8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH/Af8B/wH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/sH+wf7B/oH+wf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+wf7B/sH+wf6B/oH+gf6B/sH+gf7B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf6B/oH+gf5B/oH+Qf6B/oH+gf6B/oH+Qf5B/kH+gf6B/oH+Qf5B/kH+Qf5B/oH+Qf6B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf4B/kH+Af5B/kH+Qf5B/gH+Af4B/gH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/kH+Qf5B/gH+Qf5B/gH+Af4B/gH+Qf4B/kH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/cH+Af3B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af4B/gH+Af3B/cH9wf3B/gH9wf4B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/cH9wf3B/YH9gf2B/YH9wf2B/cH9gf2B/YH9gf2B/cH9wf3B/cH9wf2B/cH9wf3B/cH9wf3B/cH9gf3B/YH9wf2B/YH9gf2B/YH9gf2B/YH9gf2B/YH9gf2B/YH9g== + + + + + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/banner.cbmd b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/banner.cbmd new file mode 100644 index 0000000..2364568 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/banner.cbmd differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/banner_dummy.bcwav b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/banner_dummy.bcwav new file mode 100644 index 0000000..d579907 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/banner_dummy.bcwav differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/icon_24.ctpk b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/icon_24.ctpk new file mode 100644 index 0000000..cc54fe7 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/icon_24.ctpk @@ -0,0 +1 @@ +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMァUァUMMMMMMMMMMMMMァUァUァUMUァUァUァUィ]ィ]ネ]ァUィ]ネ]ノ]ノ]ノe馥麥MMMァUァUァUィUネ]ァUィUィ]ネ]ネ]ノeノe麁ネ]ノ]ノ]麁馥麥麥 n麁麥m v v,v,v-~ネ]ノeノe麁麁mm v麁 n n v v,~-~M v,~,~-~-~NNo皿~NNo姉姿鱒桝 n,v,v-~-~NNo-~NNo姉姿朴桝墨姉姿諮鱒務楹楷ヲ走イ楷榠ヲメヲモョモョカo姿鱒桝梠夢楷榠ヲ憎イヲイヲモヲモヲヤョョカモヲヤョョカカソソ7ヌカソソ7ヌ7ヌ8マXマYマMUァUァUァUィ]ネ]ノ]ィUネ]ネ]ノeノ]馥麁麥ノ]馥馥j]麥keK*!麥ヒ2 vk+;-~LmNノe麁麁麥麥 v v,vm v v,~,v-~-~N vォ!-~桑 mo錆*.uNo諮弥Sャ:憎イ v-~ォ!ヘdMョ}K*ォ!Nnuo姿嗣Ndl2o諮豊2ア楹楷ヲkミtア楷ヲr榑耕.Kl2kp桝飽}ーイ柤Kーtd Ctモヲヤョ KヘBカソヘ:注kウ箆B.KヘB|ヲ7ヌ7ヌcニXマyラモヲョョ|カソk7ヌキm:寨!kXマkYラ7ヌXマXマYラYマzラzラz゚Yラzラzラ已已帷帷シm:深kVカ:WカJョOSz゚z゚已txセシ郛已帷懃シシスン゙シンン゙゙,~-~M~NNo姉諮鋒o姉諮鱒桝楹楷ヲ趨憎ア楷ヲイ榠ヲモヲョイヲモョモョカョカキソ趨ア楹榑ヲイヲモョモョカイヲモョヤョカカソソソカキキソソ7ヌ7ヌXマソ7ヌ7ヌXマXマYラyラz゚ヤョカカソソ7ヌ7ヌXマソ7ヌ7ヌXマXマYマYラzラ8マYマYマyラyラz゚z゚帷zラ壤壤帷帷シ郛鄂XマYラyラzラzラ已已帷z゚已已懃懃シシン帷シ郛ススンン゙ン゙゙゙已懃シ鄂シンン゙スンン゙゙゙゙゙ \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/icon_48.ctpk b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/icon_48.ctpk new file mode 100644 index 0000000..24fd5a8 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/banner/icon_48.ctpk @@ -0,0 +1,2 @@ +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMUァUMUァUァUァUァUァUァUMMMMMMMァUMUUァUUァUァUァUァUァUァUァUァUァUィUィ]ァUィUィUネ]ネ]ネ]ネ]ノ]ァUァUァUァUァUィUィ]ィ]ァUィ]ィ]ィ]ネ]ネ]ネ]ノ]ィ]ネ]ネ]ノ]ノ]ノeノeノeノ]ノeノeノe馥麁麁麥ィ]ネ]ネ]ネ]ノ]ノ]ノeノeノ]ノ]ノe馥ノe麁麁麥ノe馥麁麁麁麥麥 n麥麥麥 n n n v vノe麁麁麥麥麥麥 n麥mm n n v v v n v v v v,v,v,~ v,v,v-~-~-~-~Mm n n v v v,v,~ v,v v,~,~-~-~M~,~-~-~-~M~NNN-~NNNNo姉姉,~-~-~M~M~NNNMNNNNo姉姉晒o姉姉姉姿姿鱒撲姿鱒鱒鱒桝桝桝朦No姉姉姉姉姿撲姿姿諮鱒鱒鱒桝梵鱒鱒桝梠楹楹楷梠楹楹楷ヲイ楷ヲイヲモヲ趨走走憎憎ア楷楷ヲ憎イ楷楷ヲイヲモヲモヲモョイヲイヲウヲモヲモヲモョモョョモョヤョヤョョョカカカMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMUMMMMMMMMMMMMMMMUMMMUUUァUァUUUァUァUァUァUァUィUMMMMMUUァUMUァUァUァUァUァUィUァUァUァUィUィUィ]ィ]ネ]ィUィ]ィ]ネ]ネ]ネ]ネ]ノ]ァUァUァUィUィUィ]ィ]ネ]ィUィ]ィ]ネ]ネ]ノ]ノ]ノeネ]ノ]ノ]ノeノeノeノe麁ノeノeノe麁麁麥麥麥ネ]ネ]ネ]ノ]ノ]ノeノe馥ノ]ノeノe麁馥麁麁麥馥麁麁麥麥m n n麥mm n n v v,v麁麁麥麥麥m n v麥 n n v v v v,v n v v,v,v,~,~-~ v,~,~-~-~M~MN n v v v v,v,v-~ v,~,~-~-~-~-~N-~-~-~NMNNoNNNO晒姉姉姿-~M~M~NNNNo晒NNo姉姉姉姿飽姉姉姿姿諮鱒桝朴諮鱒桝桝桝梠楷柤o姉姉姉姿鱒鱒撲諮朴鱒鱒桝梠楹梵桝桝楹梠楷楷楷ヲア楷楷楷ヲイヲモヲモヲモョ走憎憎ア楹楷楷ヲメヲイ楷ヲイヲウヲメヲモヲモョモョメヲモヲモヲモョモョョョカモョョョカカカカソイヲモヲモヲモョモョヤョヤョョモョヤョョカョカカキョカカカキソソソキソソソソ7ヌ7ヌ7ヌカカカキキソソソソソソソソ7ヌ7ヌ7ヌソ7ヌ7ヌ7ヌ7ヌ7ヌ8マXマ7ヌ8マXマXマXマYマYマyラMMMァUUァUァUァUァUァUァUァUァUィUァUィ]ァUァUァUィ]ィ]ィ]ネ]ネ]ィ]ネ]ネ]ネ]ネ]ノ]ノ]ノeァUィUィUィ]ィ]ネ]ネ]ノ]ィ]ネ]ネ]ノ]ノ]ノeノe馥ネ]ノ]ノ]馥ノe馥麁麁馥麁麁麥麁麥麥mネ]ノ]ノ]ノeノeノe馥麁ノe馥麁麁麁麥麥亀麁麥麥m +n n n+e+]ヒ2kkkk2ヒK麁麥麥 nォeォ! Lk n n v vヒ2k2kkKT+;,~,~-~-~-~d-~u-~-~NNN v v稽,v,v-~-~-~kk+;K*l\N e~-~MMNNNnumm *ォ!kkk幸ュK-~NNNN構O詩dNo姉姉姉/姿諮北ュKkBp鱒鱒桝椨!k殉 *ャ:P}kko姉姉姿朴鱒鱒桝枳S *Nd走ア楹楷梠務楹楷楷楷ヲイヲモヲl2kkkミtモョ Cョ憎ア楹楷楷楷ヲイヲモヲイ楷ヲュ:r榠ヲ2榠ョ注kkkォ!k幡kム|knSk0dk.Km:kモヲモヲモョヤョモョョョカヤョョョカカ腎キ *カカカソソソソソkヘBkホBヌ7ヌ7ヌ7ヌカキカソ挂ckソソユカS * 2kck 2ヒ!k7ヌXマXマXマホBkホBkXマYラYラyラソ7ヌ7ヌ7ヌ7ヌXマXマXマ7ヌXマXマXマXマYマYマyラXマYマYマyラYラyラzラz゚yラzラzラz゚z゚壤z゚已XマYラYラyラyラzラzラz゚yラzラzラz゚z゚壤已帷z゚z゚壤已已帷帷懃已帷帷懃懃シ郛シノ]ノeノeノeノe麁麁麥馥麁麁麥麥麥 n n麁麥麥 n n v v v n v v v v,v,v-~麥mm n n v v v n v v v v,~,~-~ v,v,~-~-~-~-~M-~-~-~NNNNo v,v,v,~2k靴k-~-~-~M ekN: eNm\NNo姉姉 *k *o姿鮪d/uNNNN晒o姉始姉姉姿姉姿鱒鱒豊Ckp役kkNd\趨憎憎ア楹楷楷楷ヲo姿姿鱒鱒桝桝桝梵桝厄t\憎イu憎イ楷楷ヲッl *ウヲr楷ヲウヲ Colモヲヤョq/dkk\p\ョSモヲモョイヲモヲモヲモョモョヤョヤョカkkメ頻lkk0d2カカカキキソソソkヘ: *kョ注カ注l2kk *カ0lソ0lk0lk奏奏kuョkkウ斌エ7ヌm:7ヌイ|ヒ!攘ョソソPl7ヌuョソ6ヌ7ヌ7ヌ7ヌ7ヌ7ヌXマkヤ旄暝セXマ慮XマYラXマXマXマYラYラyラyラzラ充.Sヒ!k6ョ,2Yマkkkkイиラキセzラ深krtkクセzラュ壤r|kr|kュ已ョ帷k:・クセzラz゚z゚壤zラz゚z゚壤壤已已帷r|k:ラカU幣釟ホシ逶郛郛郛郛郛シスz゚已已帷帷帷帷シ逶逵逶郛郛郛シスシ郛郛ススンスンスススンン゙゙゙シ郛シススンンンスンンンン゙゙゙ン゙゙゙゙゙゙,v,~,~-~-~M~M~N-~M~M~NNNNo晒NNo三姉姉姿姉姉姉姿朴諮鱒桝鋒NNo姉姉姉姿撲姉姉姿鱒鱒鱒桝朴鱒鱒桝桝桝楹楷梠務楹楷楷楷ヲイヲモヲp諮鱒桝鱒桝梠楹梠桝楹楷楷楷ヲイヲイヲア楷ヲイヲイヲイヲモヲモヲモョイヲモヲモヲモョモョョョカイ楷ヲイヲモヲモヲモョモョヤョモヲモョモョヤョヤョョカカヤョョョカカカカソカカキソソソソソモョヤョョカカカカソカカカソソソソソキソソソソ7ヌ7ヌ7ヌソ7ヌ7ヌ7ヌ7ヌ8マ8マXマソソソソソ7ヌ7ヌ7ヌソ7ヌ7ヌ7ヌ7ヌ8マXマXマ7ヌXマXマXマXマYマYマyラXマYマYラyラyラzラzラz゚7ヌ8ヌ8ヌXマXマXマXマYラXマYマYマYラYラyラyラzラYラyラyラzラzラz゚z゚已z゚z゚z゚已已帷帷帷Yラyラzラz゚z゚壤壤已z゚壤壤已已帷帷シ逶゚帷帷懃帷シ郛郛帷シ郛郛シススン已帷已帷帷懃懃シ帷シ郛郛シスススシシシススンンンスンン゙ン゙゙゙シススンスンン゙ンンン゙゙゙゙゙゙゙゙゙゙゙ン゙゙゙゙゙゙゙p鱒鱒桝梠楹楹楷梠楹楷楷楷榑ヲメヲモヲイ楷ヲイヲモヲモヲモョモョヤョモヲモョモョヤョヤョカカカイヲウヲイヲモヲモヲモョモョョモョヤョヤョョョカカキョカカカカソソソカソソソソソ6ソ7ヌヤョョカカカキキソカキキソソソソ7ヌソソソ7ヌ7ヌ7ヌ7ヌ8ヌ7ヌ7ヌ7ヌ8マ8ヌXマXマXマソソソ7ヌ7ヌ7ヌ7ヌXマ7ヌ7ヌ7ヌXマXマXマXマYマ8マXマXマYマYマYラyラyラYマYラyラyラyラzラz゚壤7ヌXマXマXマXマYラYラyラXマYラyラyラyラzラzラz゚yラzラzラz゚z゚壤已已z゚已已已已帷帷シ轌ラzラz゚z゚z゚已已帷z゚已已帷帷帷懃シ逶逶逶郛郛郛シシシ郛シススンスン已帷帷シ郛郛郛郛懃シ郛シシススンシススンスンン゙ンンン゙゙゙゙シススンンンン゙ン゙゙゙゙゙゙゙゙゙゙゙゙゙゙゙゙ \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/body.rsf b/branches/0thNUP_No_NUP/CardSaveDataMover/body/body.rsf new file mode 100644 index 0000000..44da92e --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/body.rsf @@ -0,0 +1,28 @@ +# アプリケーションのデフォルト値 +BasicInfo: + # プログラムのタイトル名を指定します。 + Title : $(TITLE) +# BackupMemoryType: 128KB + BackupMemoryType: None + Logo : Nintendo + ProductCode : "CTR-N-22NA" + +TitleInfo: +# Category: 0x0010 +# Category: SystemApplication + UniqueId: 0xf8014 + Version: 0 + +Rom: + HostRoot : romfiles +# SaveDataSize: 512K + +AccessControlInfo: + UseExtSaveData : false + + FileSystemAccess: + - CategoryFileSystemTool + +SystemControlInfo: + RemasterVersion: 2 + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/romfiles/banner.icn b/branches/0thNUP_No_NUP/CardSaveDataMover/body/romfiles/banner.icn new file mode 100644 index 0000000..eb780b9 Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/body/romfiles/banner.icn differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/romfiles/nnfont_RectDrawerShader.shbin b/branches/0thNUP_No_NUP/CardSaveDataMover/body/romfiles/nnfont_RectDrawerShader.shbin new file mode 100644 index 0000000..4290c2c Binary files /dev/null and b/branches/0thNUP_No_NUP/CardSaveDataMover/body/romfiles/nnfont_RectDrawerShader.shbin differ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/gui/gui.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/gui/gui.cpp new file mode 100644 index 0000000..dbbb05d --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/gui/gui.cpp @@ -0,0 +1,636 @@ +サソ/*---------------------------------------------------------------------------* + 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 +#include +#include +#include +#include "demo.h" +#include "gui.h" +#include "shfnt.h" + +//----------- types etc --------------- +typedef struct{ + u16 x,y; +}tU16xy; + +typedef struct{ + f32 r; + f32 g; + f32 b; + f32 a; +}tCol; + +typedef struct{ + uptr image; + tCol color; + f32 width; +}tStyle; + +typedef void (*FUNCPTR)(u32 value); + + +//------------------ 繧ウ繝ウ繝昴シ繝阪Φ繝医け繝ゥ繧ケ +class cmBase{ +public: + FUNCPTR callback; + tU16xy pos; + tU16xy size; + bool enable; + bool visible; + u8 scr; + u8 padding[1]; +public: + cmBase():enable(false),visible(false){callback = 0;}; + virtual ~cmBase(){}; + void SetCallback(uptr adrs){ callback = (FUNCPTR)adrs;}; +}; + +//PAD繝懊ち繝ウ +class cmButton: public cmBase +{ +public: + u32 mask;//PadStatus.Trigger 縺ョ繝槭せ繧ッ +public: + cmButton(){mask=0;}; + +}; + +//繝代ロ繝ォ +class cmPanel: public cmBase +{ +public: + tStyle style; + char *caption; +public: + cmPanel(){ + caption="None"; + style.image = 0; + style.color.r = 1.0f; + style.color.g = 1.0f; + style.color.b = 1.0f; + style.color.a = 1.0f; + style.width = 2.0f; + } +}; + +//繝。繝繧サ繝シ繧ク +class cmMessage: public cmPanel +{ +public: + u32 parent;//隕ェ繧ウ繝ウ繝昴シ繝阪Φ繝ID +public: + cmMessage(){style.width = 8.0f;} +}; + + +#define LINES_MAX 20 +#define CHARS_MAX 128 +//繝。繝「 +class cmMemo: public cmBase +{ +private: + char strlst[LINES_MAX][CHARS_MAX]; +public: + tStyle style; + u32 lines;//陦後し繧、繧コ:strlen驟榊玲焚莉・荳九〒縺ゅk縺薙→ + u32 parent;//隕ェ繧ウ繝ウ繝昴シ繝阪Φ繝ID +public: + cmMemo(); + bool setline(char *p,u16 ln); + char* line(u16 ln); + void clr(){ + for (int i=0;ipos.x)return false; + if (x >= (p->pos.x + p->size.x))return false; + if (y <= p->pos.y)return false; + if (y >= (p->pos.y + p->size.y))return false; + return true; +} + +//(2011.3.10)譛ャ菴灘阡オ繝輔か繝ウ繝医↓螟画峩 +//菴懈先凾縺ョ繝輔か繝ウ繝医〒逕サ髱「菴咲スョ繧定ェソ謨エ + +#define setText(x,y,s) shf_DrawText_0(x,y,s) +#define setSize(sz) shf_SetSize(sz) + +void setColor(tCol *col) +{ + //s_RenderSystem.SetColor(col->r, col->g, col->b,col->a); + shf_SetColor(col->r,col->g,col->b,col->a); +} + +//void setSize(f32 sz) +//{ +// s_RenderSystem.SetFontSize(sz); +//} + +/* +#define FONT_CAPTION_SIZE 12 +//caption莉倥″Box謠冗判 +void drawBox(tU16xy top,tU16xy size,tStyle *st,char* str = 0) +{ + u16 xe = top.x + size.x -1; + u16 ye = top.y + size.y -1; + setColor(&st->color); + s_RenderSystem.SetLineWidth(st->width); + s_RenderSystem.DrawLine(top.x, top.y, xe, top.y); + s_RenderSystem.DrawLine(xe, top.y, xe, ye); + s_RenderSystem.DrawLine(xe, ye, top.x, ye); + s_RenderSystem.DrawLine(top.x, ye, top.x, top.y); + if (str != 0){ + int w = (size.x - strlen(str)*FONT_CAPTION_SIZE) >> 1; + int h = (size.y - FONT_CAPTION_SIZE) >> 1; + if ((w>0) && (h>0)){ + setSize(FONT_CAPTION_SIZE); + s_RenderSystem.DrawText(top.x + w,top.y + h,str); + } + } +} +*/ + +//荳顔判髱「縲√Γ繝繧サ繝シ繧ク譫陦ィ遉コ +void drawBox(tU16xy top,tU16xy size,tStyle *st,char* str = 0) +{ + int i; + shf_SetScale(2.0f,2.0f); + setColor(&st->color); + for (i=0;i> 1; + h = (size.y - h) >> 1; + if ((w>0) && (h>0)){ + setText(top.x + w+10,top.y + h,str); + } + } + +} + +//荳狗判髱「繝懊ち繝ウ陦ィ遉コ +void drawBox2(tU16xy top,tU16xy size,tStyle *st,char* str = 0) +{ + int i; + setColor(&st->color); + shf_SetScale(2.0f,2.0f); + for (i=0;i> 1; + h = (size.y - h) >> 1; + if ((w>0) && (h>0)){ + setText(top.x + w+10,top.y + h+10,str); + } + } + +} + + + +//謠冗判 +void drawDisp() +{ + //NN_LOG("draw\n"); + //荳 + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); + s_RenderSystem.Clear(); + int i,j; + + for (i=0;ir = 0.0; + col->g = 0.0; + col->b = 0.0; + break; + case COLOR_GRAY: + col->r = 0.5f; + col->g = 0.5f; + col->b = 0.5f; + break; + case COLOR_RED: + col->r = 1.0f; + col->g = 0.0f; + col->b = 0.0f; + break; + case COLOR_BLUE: + col->r = 0.0f; + col->g = 0.0f; + col->b = 1.0f; + break; + case COLOR_GREEN: + col->r = 0.0f; + col->g = 1.0f; + col->b = 0.0f; + break; + case COLOR_YELLO: + col->r = 1.0f; + col->g = 1.0f; + col->b = 0.0f; + break; + case COLOR_WHITE: + col->r = 1.0f; + col->g = 1.0f; + col->b = 1.0f; + break; + case COLOR_PARPL: + col->r = 1.0f; + col->g = 0.0f; + col->b = 1.0f; + break; + case COLOR_SKY: + col->r = 0.5f; + col->g = 1.0f; + col->b = 1.0f; + break; + default: + col->r = 1.0f; + col->g = 1.0f; + col->b = 1.0f; + break; + } + col->a = 1.0f; +} + +//------------------ class code ---------------------------- + +nn::os::Thread s_thread; + +//thread +//void Gui::thUpdate() +void thUpdate(nn::os::LightEvent* pEvnt) +{ + nn::hid::PadReader padReader; + nn::hid::PadStatus padStatus; + nn::hid::TouchPanelStatus tpStatus; + tU16xy tpOld = {0,0}; + nn::hid::TouchPanelReader tpReader; + u32 value; + int i; + + while(1) + { + if (pEvnt->TryWait())break; + + if (s_Button.enable && (s_Button.callback !=0))//PAD繝懊ち繝ウ + { + padReader.ReadLatest(&padStatus); + value = padStatus.trigger & s_Button.mask; + if (value)(*s_Button.callback)(value); + } + + tpReader.ReadLatest(&tpStatus);//繧ソ繝繝 + if((tpStatus.x != tpOld.x) || (tpStatus.y != tpOld.y)) + { + tpOld.x = tpStatus.x; + tpOld.y = tpStatus.y; + if (tpStatus.touch) + { + for (i=0;iClearSignal(); +} + + +Gui::~Gui() +{ + Finalize(); +} + + +//蛻晄悄蛹悶∫オゆコ +bool Gui::Initialize(uptr pHeap,u32 size,nn::os::LightEvent* pEvnt) +{ + if (Initialized)return false; + Initialized = true; + + //繧ウ繝ウ繝昴シ繝阪Φ繝医ョ蛻晄悄蛹 + int i; + for (i=0;i< PANEL_MAX;i++)PanelEffective(i,false,false); + for (i=0;i< MEMO_MAX;i++)MemoEffective(i,false,false); + for (i=0;i< MESS_MAX;i++)MessEffective(i,false,false); + + //Render + s_RenderSystem.Initialize(pHeap, size); + + SharedFontInit(); + + //HID + nn::hid::Initialize(); + + //Thread + NN_LOG("Thread Start\n"); + nn::Result res =s_thread.TryStartUsingAutoStack(thUpdate,pEvnt,8192); + if (res.IsFailure()){ + NN_LOG("failed :res.desc = %d\n",res.GetDescription()); + return false; + } + + + + return true; +} + +void Gui::Finalize() +{ + if (Initialized != true) return; + if (s_thread.IsAlive()) + { + s_thread.Join(); + s_thread.Finalize(); + } + Initialized = false; + //nn::hid::Finalize(); + // nngxFinalize 髢「謨ー蜻シ縺ウ蜃コ縺励→ VSync 蜑イ繧願セシ縺ソ縺悟酔譎ゅ↓逋コ逕溘☆繧九→ + // 逕サ髱「縺梧囓霆「縺励◆縺セ縺セ豁「縺セ繧倶ク榊キ蜷医r蝗樣∩縺吶k縺溘a縺ォ VSync 蠕縺。繧定。後≧ + nngxWaitVSync(NN_GX_DISPLAY_BOTH); + SharedFontFinalize(); + nngxWaitVSync(NN_GX_DISPLAY_BOTH); + s_RenderSystem.Finalize(); + +} + +void Gui::ButtonCallback(uptr adrs) +{ + s_Button.SetCallback(adrs); +} + +void Gui::ButtonMask(u32 mask) +{ + s_Button.mask = mask; + s_Button.enable = true; +} + +myResult Gui::PanelSet(const tPanel *panel) +{ + if (panel->id >= PANEL_MAX)return RESULT_BAD_PARAM; + s_Panel[panel->id].pos.x = panel->x; + s_Panel[panel->id].pos.y = panel->y; + s_Panel[panel->id].size.x = panel->width; + s_Panel[panel->id].size.y = panel->height; + //if (panel->caption[0] != 0 ) + s_Panel[panel->id].caption = panel->caption; + s_Panel[panel->id].SetCallback(panel->callback); + s_Panel[panel->id].scr = panel->scr; + s_Panel[panel->id].visible = false; + s_Panel[panel->id].enable = false; + return RESULT_OK; +} + +myResult Gui::PanelEffective(u8 id,bool enable,bool visible) +{ + if (id >= PANEL_MAX)return RESULT_BAD_PARAM; + s_Panel[id].enable = enable; + s_Panel[id].visible = visible; + return RESULT_OK; +} + +myResult Gui::PanelLineStyle(u8 id,eColor col,u8 width) +{ + if (id >= PANEL_MAX)return RESULT_BAD_PARAM; + ColorFromCode(col,&s_Panel[id].style.color); + s_Panel[id].style.width = width; + return RESULT_OK; +} + + +myResult Gui::MessEffective(u8 id,bool enable,bool visible) +{ + if (id >= MESS_MAX)return RESULT_BAD_PARAM; + s_Message[id].enable = enable; + s_Message[id].visible = visible; + return RESULT_OK; +} + + +myResult Gui::MessSet(const tMessage *mes) +{ + if ((mes->parent >= PANEL_MAX) || (mes->id >= MESS_MAX))return RESULT_BAD_PARAM; + s_Message[mes->id].pos.x = mes->x; + s_Message[mes->id].pos.y = mes->y; + s_Message[mes->id].caption = mes->str; + s_Message[mes->id].parent = mes->parent; + s_Message[mes->id].style.width = mes->size; + ColorFromCode(mes->color,&s_Message[mes->id].style.color); + s_Message[mes->id].visible = false; + s_Message[mes->id].enable = false; + return RESULT_OK; +} + +myResult Gui::MessStr(u8 id,char *str) +{ + if (id >= MESS_MAX)return RESULT_BAD_PARAM; + s_Message[id].caption = str; + return RESULT_OK; +} + +myResult Gui::MessCol(u8 id,eColor col) +{ + if (id >= MESS_MAX)return RESULT_BAD_PARAM; + ColorFromCode(col,&s_Message[id].style.color); + return RESULT_OK; +} + +myResult Gui::MemoSet(const tMemo *m) +{ + if ((m->parent >= PANEL_MAX) || (m->id >= MEMO_MAX))return RESULT_BAD_PARAM; + if (m->lines > LINES_MAX)return RESULT_BAD_PARAM; + s_Memo[m->id].lines = m->lines; + s_Memo[m->id].pos.x = m->x; + s_Memo[m->id].pos.y = m->y; + s_Memo[m->id].parent = m->parent; + s_Memo[m->id].style.width = m->size; + ColorFromCode(m->color,&s_Memo[m->id].style.color); + s_Memo[m->id].clr(); + s_Memo[m->id].visible = false; + s_Memo[m->id].enable = false; + return RESULT_OK; +} + +myResult Gui::MemoStr(u8 id,char *str,u16 ln) +{ + if ((id < MEMO_MAX) && s_Memo[id].setline(str,ln) )return RESULT_OK; + return RESULT_BAD_PARAM; +} + + +myResult Gui::MemoEffective(u8 id,bool enable,bool visible) +{ + if (id >= MEMO_MAX)return RESULT_BAD_PARAM; + s_Memo[id].enable = enable; + s_Memo[id].visible = visible; + return RESULT_OK; +} + + + +void Gui::Draw() +{ + //s_drawFlag = true; + drawDisp(); +} + + +void Gui::DisableAll() +{ + for (int i=0;i +#include +#include "../my_defs.h" + +typedef struct +{ + uptr callback; + char* caption; + u16 x,y; + u16 width,height; + u8 id; + u8 scr;//0:up,else down screen + u8 padding[2]; +}tPanel; + +typedef enum { + COLOR_BLACK, + COLOR_GRAY, + COLOR_RED, + COLOR_GREEN, + COLOR_BLUE, + COLOR_YELLO, + COLOR_WHITE, + COLOR_PARPL, + COLOR_SKY +}eColor; + +typedef struct +{ + char* str; + u16 x,y;//隕ェ縺ョ蟋狗せ縺ィ縺ョ逶ク蟇セ + eColor color;// + u8 size;//譁蟄励し繧、繧コ + u8 id; + u8 parent;//隕ェ繧ウ繝ウ繝昴シ繝阪Φ繝域欠螳 +}tMessage; + +typedef struct +{ + u16 lines;//陦ィ遉コ陦梧焚 + u16 x,y;//隕ェ縺ョ蟋狗せ縺ィ縺ョ逶ク蟇セ + eColor color;//譁蟄苓牡 + u8 size;//譁蟄励し繧、繧コ + u8 id; + u8 parent;//隕ェ繧ウ繝ウ繝昴シ繝阪Φ繝域欠螳 +}tMemo; + + + +class Gui +{ +private: + bool Initialized; + +public: + Gui(){}; + ~Gui(); + bool Initialize(uptr pHeap,u32 size,nn::os::LightEvent* pEvnt); + void Finalize(); + void ButtonCallback(uptr adrs); + void ButtonMask(u32 mask); + myResult PanelSet(const tPanel *panel); + myResult MessSet(const tMessage *mes); + myResult MemoSet(const tMemo *m); + void Draw(); + void DisableAll(); + myResult PanelEffective(u8 id,bool enable=true,bool visible=true); + myResult MessEffective(u8 id,bool enable=true,bool visible=true); + myResult MemoEffective(u8 id,bool enable=true,bool visible=true); + myResult MessStr(u8 id,char *str); + myResult MessCol(u8 id,eColor col); + myResult MemoStr(u8 id,char *str,u16 ln); + myResult PanelLineStyle(u8 id,eColor col=COLOR_WHITE,u8 width = 2); + //void thUpdate(); +}; + + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/gui/shfnt.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/gui/shfnt.cpp new file mode 100644 index 0000000..db503c2 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/gui/shfnt.cpp @@ -0,0 +1,350 @@ +サソ +#include +#include +#include +#include +#include +#include + +#include "demo.h" + +const char s_ShaderBinaryFilePath[] = "rom:/nnfont_RectDrawerShader.shbin"; + +extern nn::fnd::ExpHeap appHeap; + +//--------------------------------------------------------------------------- +//! @brief 繧キ繧ァ繝シ繝縺ョ蛻晄悄蛹悶r陦後>縺セ縺吶 +//! +//! @param[in,out] pResource 謠冗判逕ィ繝ェ繧ス繝シ繧ケ繧堤ョ。逅縺吶k繧ェ繝悶ず繧ァ繧ッ繝医∈縺ョ繝昴う繝ウ繧ソ縲 +//--------------------------------------------------------------------------- +void* +InitShaders(nn::font::RectDrawer* pDrawer) +{ + const size_t ROMFS_BUFFER_SIZE = 1024 * 64; + static char buffer[ROMFS_BUFFER_SIZE]; + + nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE); + nn::fs::FileReader shaderReader(s_ShaderBinaryFilePath); + + const u32 fileSize = (u32)shaderReader.GetSize(); + + void* shaderBinary = appHeap.Allocate(fileSize); + NN_NULL_ASSERT(shaderBinary); + + shaderReader.Read(shaderBinary, fileSize); + + const u32 vtxBufCmdBufSize = + nn::font::RectDrawer::GetVertexBufferCommandBufferSize(shaderBinary, fileSize); + void *const vtxBufCmdBuf = appHeap.Allocate(vtxBufCmdBufSize); + NN_NULL_ASSERT(vtxBufCmdBuf); + pDrawer->Initialize(vtxBufCmdBuf, shaderBinary, fileSize); + + appHeap.Free(shaderBinary); + + shaderReader.Finalize(); + nn::fs::Unmount("rom:"); + return vtxBufCmdBuf; +} +/*---------------------------------------------------------------------------* + @brief 繧ー繝ゥ繝輔ぅ繝繧ッ繧ケ縺ョ蛻晄悄險ュ螳壹r陦後>縺セ縺吶 + *---------------------------------------------------------------------------*/ +void +InitGX() +{ + glClearColor(0.3f, 0.3f, 0.3f, 1.0f); +} + + +//--------------------------------------------------------------------------- +//! @brief 謠冗判縺ョ蛻晄悄險ュ螳壹r陦後>縺セ縺吶 +//! +//! @param[in] width 逕サ髱「縺ョ蟷縲 +//! @param[in] height 逕サ髱「縺ョ鬮倥&縲 +//--------------------------------------------------------------------------- +void +InitDraw( + int width, + int height +) +{ + // 繧ォ繝ゥ繝シ繝舌ャ繝輔ぃ諠蝣ア + // LCD縺ョ蜷代″縺ォ蜷医o縺帙※縲∝ケ縺ィ鬮倥&繧貞・繧梧崛縺医※縺縺セ縺吶 + const nn::font::ColorBufferInfo colBufInfo = { width, height, PICA_DATA_DEPTH24_STENCIL8_EXT }; + + const u32 screenSettingCommands[] = + { + + // 繝薙Η繝シ繝昴シ繝医ョ險ュ螳 + NN_FONT_CMD_SET_VIEWPORT( 0, 0, colBufInfo.width, colBufInfo.height ), + + // 繧キ繧カ繝シ蜃ヲ逅繧堤┌蜉ケ + NN_FONT_CMD_SET_DISABLE_SCISSOR( colBufInfo ), + + // w繝舌ャ繝輔ぃ縺ョ辟。蜉ケ蛹 + // 繝繝励せ繝ャ繝ウ繧ク縺ョ險ュ螳 + // 繝昴Μ繧エ繝ウ繧ェ繝輔そ繝繝医ョ辟。蜉ケ蛹 + NN_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET( + 0.0f, // wScale : 0.0 縺ァW繝舌ャ繝輔ぃ縺檎┌蜉ケ + 0.0f, // depth range near + 1.0f, // depth range far + 0, // polygon offset units : 0.0 縺ァ 繝昴Μ繧エ繝ウ繧ェ繝輔そ繝繝医′辟。蜉ケ + colBufInfo), + }; + + nngxAdd3DCommand(screenSettingCommands, sizeof(screenSettingCommands), true); + + static const u32 s_InitCommands[] = + { + // 繧ォ繝ェ繝ウ繧ー繧堤┌蜉ケ + NN_FONT_CMD_SET_CULL_FACE( NN_FONT_CMD_CULL_FACE_DISABLE ), + + // 繧ケ繝繝ウ繧キ繝ォ繝繧ケ繝医r辟。蜉ケ + NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(), + + // 繝繝励せ繝繧ケ繝医r辟。蜉ケ + // 繧ォ繝ゥ繝シ繝舌ャ繝輔ぃ縺ョ蜈ィ縺ヲ縺ョ謌仙繧呈嶌縺崎セシ縺ソ蜿ッ + NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK( + false, // isDepthTestEnabled + 0, // depthFunc + true, // depthMask + true, // red + true, // green + true, // blue + true), // alpha + + // 繧「繝シ繝ェ繝シ繝繝励せ繝繧ケ繝医r辟。蜉ケ + NN_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST( false ), + + // 繝輔Ξ繝シ繝繝舌ャ繝輔ぃ繧「繧ッ繧サ繧ケ蛻カ蠕。 + NN_FONT_CMD_SET_FBACCESS( + true, // colorRead + true, // colorWrite + false, // depthRead + false, // depthWrite + false, // stencilRead + false), // stencilWrite + }; + + nngxAdd3DCommand(s_InitCommands, sizeof(s_InitCommands), true); +} + +//--------------------------------------------------------------------------- +//! @brief ResFont繧呈ァ狗ッ峨@縺セ縺吶 +//! +//! @param[out] pFont 讒狗ッ峨☆繧九ヵ繧ゥ繝ウ繝医∈縺ョ繝昴う繝ウ繧ソ縲 +//! @param[in] filePath 繝ュ繝シ繝峨☆繧九ヵ繧ゥ繝ウ繝医Μ繧ス繝シ繧ケ繝輔ぃ繧、繝ォ蜷阪 +//! +//! @return ResFont讒狗ッ峨ョ謌仙凄繧定ソ斐@縺セ縺吶 +//--------------------------------------------------------------------------- +bool +InitFont( + nn::font::ResFont* pFont, + void* pBuffer +) +{ + // 繝輔か繝ウ繝医Μ繧ス繝シ繧ケ繧偵そ繝繝医@縺セ縺 + bool bSuccess = pFont->SetResource(pBuffer); + + // 謠冗判逕ィ繝舌ャ繝輔ぃ繧定ィュ螳壹@縺セ縺吶 + const u32 drawBufferSize = nn::font::ResFont::GetDrawBufferSize(pBuffer); + void* drawBuffer = appHeap.Allocate(drawBufferSize, 4); + pFont->SetDrawBuffer(drawBuffer); + NN_NULL_ASSERT(drawBuffer); + + return bSuccess; +} + +//--------------------------------------------------------------------------- +//! @brief ResFont繧堤エ譽縺励∪縺吶 +//! +//! @param[in] pFont 遐エ譽縺吶k繝輔か繝ウ繝医∈縺ョ繝昴う繝ウ繧ソ縲 +//--------------------------------------------------------------------------- +void +CleanupFont(nn::font::ResFont* pFont) +{ + // 謠冗判逕ィ繝舌ャ繝輔ぃ縺ョ辟。蜉ケ蛹 + // 謠冗判逕ィ繝舌ャ繝輔ぃ縺後そ繝繝医&繧後※縺繧九↑繧 讒狗ッ画凾縺ォ SetDrawBuffer 縺ォ貂。縺励◆繝舌ャ繝輔ぃ縺ク縺ョ + // 繝昴う繝ウ繧ソ縺瑚ソ斐▲縺ヲ縺阪∪縺吶 + void *const drawBuffer = pFont->SetDrawBuffer(NULL); + if (drawBuffer != NULL) + { + appHeap.Free(drawBuffer); + } +} + +//--------------------------------------------------------------------------- +//! @brief 陦ィ遉コ譁蟄怜礼畑繝舌ャ繝輔ぃ繧堤「コ菫昴@縺セ縺吶 +//! +//! @param[in] charMax 陦ィ遉コ縺吶k譁蟄怜励ョ譛螟ァ譁蟄玲焚縲 +//! +//! @return 遒コ菫昴@縺溯。ィ遉コ譁蟄怜礼畑繝舌ャ繝輔ぃ縺ク縺ョ繝昴う繝ウ繧ソ繧定ソ斐@縺セ縺吶 +//--------------------------------------------------------------------------- +nn::font::DispStringBuffer* +AllocDispStringBuffer(int charMax) +{ + const u32 DrawBufferSize = nn::font::CharWriter::GetDispStringBufferSize(charMax); + void *const bufMem = appHeap.Allocate(DrawBufferSize); + NN_NULL_ASSERT(bufMem); + + return nn::font::CharWriter::InitDispStringBuffer(bufMem, charMax); +} + +//--------------------------------------------------------------------------- +//! @brief 譁蟄怜苓。ィ遉コ逕ィ縺ォ繝「繝繝ォ繝薙Η繝シ陦悟励→蟆蠖ア陦悟励r險ュ螳壹@縺セ縺吶 +//! +//! @param[in] pDrawer RectDrawer繧ェ繝悶ず繧ァ繧ッ繝医∈縺ョ繝昴う繝ウ繧ソ縲 +//! @param[in] width 逕サ髱「縺ョ蟷縲 +//! @param[in] height 逕サ髱「縺ョ鬮倥&縲 +//--------------------------------------------------------------------------- +void +SetupTextCamera( + nn::font::RectDrawer* pDrawer, + int width, + int height +) +{ + // 蟆蠖ア陦悟励r豁」蟆蠖ア縺ォ險ュ螳 + { + // 蟾ヲ荳雁次轤ケ縺ィ縺励〆霆ク縺ィZ霆ク縺ョ蜷代″縺碁縺ォ縺ェ繧九h縺縺ォ險ュ螳壹@縺セ縺吶 + nn::math::MTX44 proj; + f32 znear = 0.0f; + f32 zfar = -1.0f; + f32 t = 0; + f32 b = static_cast(width); + f32 l = 0; + f32 r = static_cast(height); + nn::math::MTX44OrthoPivot(&proj, l, r, b, t, znear, zfar, nn::math::PIVOT_UPSIDE_TO_TOP); + pDrawer->SetProjectionMtx(proj); + } + + // 繝「繝繝ォ繝薙Η繝シ陦悟励r蜊倅ス崎。悟励↓險ュ螳 + { + nn::math::MTX34 mv; + nn::math::MTX34Identity(&mv); + pDrawer->SetViewMtxForText(mv); + } +} + +nn::font::RectDrawer drawer; +void *drawerBuf; +nn::font::DispStringBuffer *pDrawStringBuf0; +nn::font::DispStringBuffer *pDrawStringBuf1; +nn::font::ResFont font; +nn::font::TextWriter writer; +//--------------------------------------------------------------------------- +//! @brief ASCII譁蟄怜励r謠冗判縺励∪縺吶 +//--------------------------------------------------------------------------- +void +shf_DrawText_0( u16 x,u16 y,char *s) +{ + writer.SetCursor(x, y); + + writer.StartPrint(); + (void)writer.Print(s); + writer.EndPrint(); + drawer.BuildTextCommand(&writer); + + + drawer.DrawBegin(); + + SetupTextCamera(&drawer, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + writer.UseCommandBuffer(); + + drawer.DrawEnd(); +} + +void shf_SetSize(f32 sz) +{ + writer.SetScale(sz/14,sz/20); +} + +void shf_SetScale(f32 h,f32 v) +{ + writer.SetScale(h,v); +} + + +void shf_SetFontSize(f32 sz) +{ + writer.SetFontSize(sz); +} + +f32 shf_GetFontWidth() +{ + return writer.GetFontWidth(); +} + +f32 shf_GetFontHeight() +{ + return writer.GetFontHeight(); +} + + +void shf_SetColor(f32 r,f32 g,f32 b,f32 a) +{ + writer.SetTextColor(nn::util::FloatColor(r,g,b,a)); +} + +//蛻晄悄蛹 +//AppHeap遒コ菫昴ヽenderSystem.Initit縺ョ蠕後↓蜻シ縺カ +void SharedFontInit() +{ + + InitGX(); + + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ蛻晄悄蛹 + NN_UTIL_PANIC_IF_FAILED(nn::pl::InitializeSharedFont()); + + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ繝ュ繝シ繝峨′螳御コ縺吶k縺セ縺ァ蠕讖 + while (nn::pl::GetSharedFontLoadState() != nn::pl::SHARED_FONT_LOAD_STATE_LOADED) + { + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ繝ュ繝シ繝峨↓螟ア謨励@縺ヲ縺縺ェ縺縺狗「コ隱 + if (nn::pl::GetSharedFontLoadState() == nn::pl::SHARED_FONT_LOAD_STATE_FAILED) + { + NN_TPANIC_("failed to load shared font!\n"); + } + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(1)); + } + + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ遞ョ鬘槭r蜿門セ + //nn::pl::SharedFontType sharedFontType = nn::pl::GetSharedFontType(); + + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ繝シ繧ソ縺ョ繧「繝峨Ξ繧ケ繧貞叙蠕 + void* pFontBuffer = nn::pl::GetSharedFontAddress(); + + InitFont(&font, pFontBuffer); + + // 謠冗判繝ェ繧ス繝シ繧ケ縺ョ讒狗ッ + drawerBuf = InitShaders(&drawer); + + // 謠冗判譁蟄怜礼畑繝舌ャ繝輔ぃ縺ョ遒コ菫 + pDrawStringBuf0 = AllocDispStringBuffer(1024); + pDrawStringBuf1 = AllocDispStringBuffer(512); + + writer.SetDispStringBuffer(pDrawStringBuf0); + writer.SetFont(&font); + SetupTextCamera(&drawer, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + +} + + +void SharedFontFinalize() +{ + drawer.Finalize(); + + // 謠冗判繝ェ繧ス繝シ繧ケ縺ョ遐エ譽 + appHeap.Free(drawerBuf); + + // 繝輔か繝ウ繝医ョ遐エ譽 + CleanupFont(&font); + + // 謠冗判譁蟄怜礼畑繝舌ャ繝輔ぃ縺ョ隗」謾セ + appHeap.Free(pDrawStringBuf1); + appHeap.Free(pDrawStringBuf0); + +} + + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/gui/shfnt.h b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/gui/shfnt.h new file mode 100644 index 0000000..912ae46 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/gui/shfnt.h @@ -0,0 +1,29 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: irp.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef GUI_SHFNT_H_ +#define GUI_SHFNT_H_ + +void SharedFontInit(); +void SharedFontFinalize(); +void shf_DrawText_0(u16 x,u16 y,char* s); +void shf_SetSize(f32 sz); +void shf_SetScale(f32 h,f32 v); +void shf_SetColor(f32 r,f32 g,f32 b,f32 a); +void shf_SetFontSize(f32 sz); +f32 shf_GetFontWidth(); +f32 shf_GetFontHeight(); + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/main.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/main.cpp new file mode 100644 index 0000000..f6b4d3a --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/main.cpp @@ -0,0 +1,1455 @@ +サソ/*---------------------------------------------------------------------------* + 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 +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include "./savefile/savefile.h" +#include "./savefile/savedata.h" +#ifdef BKUP_NOTMEM +#include "./savefile/exsave.h" +#else +#include "./savefile/membak.h" +#endif +#include "./screen/screen.h" +#include "../common/common.h" + +nn::fnd::ExpHeap appHeap; +uptr heapForGx; +//Gui gui; +myResult errRes; +#ifdef BKUP_NOTMEM +const u32 IconBuffSize = 1024*20; +uptr IconBuffer; +size_t IconSize; +#endif + +#ifdef DEBUG_ENABLE +cStrLst memo; +#endif +bool isDebugMode = false;//繝繝舌ャ繧ー繝「繝シ繝 + +//char strBuff[128]; +//bool exist; + +SaveData savedata; +nn::os::LightEvent ejectEvnt(false); +nn::os::LightEvent insEvnt(false); +#ifdef BKUP_NOTMEM +ExSave exsave; +nn::os::LightEvent ejectEvntSd(false); +nn::os::LightEvent insEvntSd(false); +#else +MemBak exsave; +#endif + +//繝舌ャ繧ッ繧「繝繝励ョ迥カ諷 +bool Active,Formatted; +bool exActive,exFormatted; +tArcInfo arcInfo,arcInfo_ex;//繧「繝シ繧ォ繧、繝匁ュ蝣ア + +//繝励Ο繝繧ッ繝医さ繝シ繝峨ョ荳閾エ +bool isAgreePCode; +//繝吶Μ繝輔ぃ繧、邨先棡 +//bool failveri; + +//Top逕サ髱「繧ィ繝ゥ繝シ陦ィ遉コ +int tmerr; + + +#ifdef ENABLE_CRUSH +int CrashForDebug= 0; +#endif + + +//邨先棡 +typedef enum { + SUCCESS + ,ERROR + ,CANCEL + ,INSEXIT +}RetCode; + +//謖ソ謚懊う繝吶Φ繝域凾縺ォ險ュ螳 +typedef enum { + InEx_None + ,InEx_InsCard + ,InEx_EjcCard +#ifdef BKUP_NOTMEM + ,InEx_InsSd + ,InEx_EjcSd +#endif +}tIsInsEject; + +tIsInsEject isInsEject; + +extern u8 scr_evnt; +void WaitUI(); +void PutError(ErcDev dev,int cd=0); + + +//邨ゆコ蜃ヲ逅 +void endfunc() +{ + + nn::fs::UnregisterCardEjectedEvent(); + nn::fs::UnregisterCardInsertedEvent(); + ejectEvnt.Finalize(); + insEvnt.Finalize(); +#ifdef BKUP_NOTMEM + nn::fs::UnregisterSdmcEjectedEvent(); + nn::fs::UnregisterSdmcInsertedEvent(); + ejectEvntSd.Finalize(); + insEvntSd.Finalize(); +#endif + + savedata.Finalize(); + exsave.Finalize(); + + ScrFinalize(); + +#ifdef BKUP_NOTMEM + appHeap.Free(reinterpret_cast(IconBuffer)); +#endif + +} + +//繧ィ繝ゥ繝シ蛛懈ュ「 +void failstop() +{ + NN_LOG("fail %d,stop\n",errRes); + finish(); +} + +#ifdef DEBUG_ENABLE +//繝ュ繧ー霑ス蜉シ陦ィ遉コ +void LogAdd(char *s) +{ + memo.add(s); + if(isDebugMode){ + scr_DgbLog(&memo); + while(ScrGetDrawFlag()){ + nn::os::Thread::Yield();//陦ィ遉コ + } + } +} + +char dst[128],work[64]; +void LogAdd_Int(char *s,int i) +{ + sprintf(dst,s,i); + LogAdd(dst); +} + +void LogAdd_cat(char *s,char *s2) +{ + strcpy(dst,s); + strcat(dst,s2); + LogAdd(dst); +} + +void LogAdd_bytes(char *s,u8 *b,int n) +{ + int i; + for (i=0;i desc = %d",res.GetDescription()); +} + +void LogAdd_Fparam(tArcInfo *p) +{ + LogAdd_Int("FileCount %d",p->FileCount); + LogAdd_Int("DirCount %d",p->DirCount); + LogAdd_Int("FileEntry %d",p->FileEntry); + LogAdd_Int("DirEntry %d",p->DirEntry); +} + +void LogAdd_InfoParam(tArcInfo *p) +{ + LogAdd_Int("Version %d",p->Ver); + LogAdd_cat("> pcode = ",p->Pcode); + LogAdd_Fparam(p); +} +#else +void LogAdd(char *s) +{ + NN_UNUSED_VAR(s); +} + +void LogAdd_Int(char *s,int i) +{ + NN_UNUSED_VAR(s); + NN_UNUSED_VAR(i); +} + +void LogAdd_cat(char *s,char *s2) +{ + NN_UNUSED_VAR(s); + NN_UNUSED_VAR(s2); +} + +void LogAdd_bytes(char *s,u8 *b,int n) +{ + NN_UNUSED_VAR(s); + NN_UNUSED_VAR(b); + NN_UNUSED_VAR(n); +} + +void LogAdd_Res(nn::Result res) +{ + NN_UNUSED_VAR(res); +} + +void LogAdd_Fparam(tArcInfo *p) +{ + NN_UNUSED_VAR(p); +} + +void LogAdd_InfoParam(tArcInfo *p) +{ + NN_UNUSED_VAR(p); +} + +#endif + +char sts[64]; +//繧ィ繝ゥ繝シ陦ィ遉コ +void PutError(ErcDev dev,int cd) +{ + int desc,code; + nn::Result res; + switch (dev) + { + case ERC_DEV_CARD: res = savedata.LastNnResult;break; + case ERC_DEV_OUT: res = exsave.LastNnResult;break; + } + if(dev != ERC_DEV_OTHER)LogAdd_Res(res); + if(isDebugMode==false) + { + if ((cd ==0 ) && (dev != ERC_DEV_OTHER)) + { + desc = res.GetDescription(); + if (desc < 100 ) code = ERC_UNKNOWN;//繧ュ繝シ讀懃エ「螳御コ .. 縺ゅj縺医↑縺 + else if (desc < 180 ) code = ERC_READ;//繝輔ぃ繧、繝ォ縺瑚ヲ九▽縺九i縺ェ縺縺倶ク肴ュ」 + else if (desc < 200 ) code = ERC_WRITE_OW;//繝輔ぃ繧、繝ォ縺悟ュ伜惠 .. 蜑企勁螟ア謨? + else if (desc < 220 ) code = ERC_WRITE_NS;//遨コ縺阪′辟。縺 + else if (desc < 260 ) code = ERC_ACCESS;//謫堺ス懈拠蜷ヲ + else if (desc < 280 ) code = ERC_WRITE_PROTECT;//譖ク縺崎セシ縺ソ遖∵ュ「 + else if (desc < 340 ) code = ERC_ACCESS;//繧「繧ッ繧サ繧ケ繧ィ繝ゥ繝シ + else if (desc < 390 ) code = ERC_FORMAT;//繝輔か繝シ繝槭ャ繝医お繝ゥ繝シ + else if (desc < 400 ) code = ERC_SDK_VERIFI;//謾ケ遶 + else if (desc < 580 ) code = ERC_ROM;//ROM諠蝣ア繧ィ繝ゥ繝シ + else if (desc < 590 ) code = ERC_RETRY;//繝ェ繝医Λ繧、隕∵ア + else if (desc < 600 ) code = ERC_UNKNOWN;//CCI,CXI荳肴ュ」 .. 縺ゅj縺医↑縺 + else if (desc < 900 ) code = ERC_EXEC;//螳溯。梧凾繧ィ繝ゥ繝シ縲√た繝輔ヨ繝舌げ + else code = ERC_FATAL;//譛ャ菴薙↓蝠城。後ョ蜿ッ閭ス諤ァ + }else code = cd; + sprintf(sts,"ERROR %d",dev+code); + scr_Status(sts,COLOR_RED); + } + +} + + +//-------------------------------------------------- Verifi +wchar_t file_pathw[MAX_PATH_LENGTH]; +char file_path[MAX_PATH_LENGTH]; +//繝峨Λ繧、繝舌ョ莉墓ァ倥〒騾溷コヲ逧縺ォシ斐ヰ繧、繝医い繝ゥ繧、繝ウ縺励◆譁ケ縺後>縺(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) + +bool Verifi() +{ + myResult res; + int ct,i,msize,rsize; + s64 total=0; + + LogAdd("Verifi"); + + //繧サ繝シ繝悶ョ繝シ繧ソ縺ョ繝槭え繝ウ繝 + LogAdd("Mount savedata"); + res = savedata.Mount(); + if(res != RESULT_OK){ + PutError(ERC_DEV_CARD); + return false; + } + +/* + if(isDebugMode==false) scr_Status("Ready to Verifi",COLOR_YELLO); + //諠蝣ア繝輔ぃ繧、繝ォ + LogAdd("Directry Info"); + if(savedata.GetInfo(&arcInfo)==false) + { + LogAdd("> get fail");//譛牙柑縺ェ諠蝣ア繝輔ぃ繧、繝ォ縺後↑縺 + savedata.Unmount(); + PutError(ERC_DEV_CARD); + return ERROR; + } + LogAdd_Fparam(&arcInfo); +*/ + + //蜃コ蜉帙ョ繝舌う繧ケ縺ョ繝槭え繝ウ繝 +#ifdef BKUP_NOMEM //繝輔Λ繧ー髢馴&縺医メ繧ァ繝繧ッ逕ィ縺ォ陦ィ遉コ蛻縺 + LogAdd("Mount Device");//荳肴尚逋コ繝。繝繧」繧「 +#else + LogAdd("memory setup");//繝。繝「繝ェ菫晏ュ +#endif + + res = exsave.Mount(); + if(res != RESULT_OK){ + PutError(ERC_DEV_OUT); + return false; + } + + //諠蝣ア繝輔ぃ繧、繝ォ + LogAdd("Directry Info(out)"); + if (exsave.GetInfo(&arcInfo_ex)) + { + //todo:繝輔か繝シ繝槭ャ繝亥、画峩譎ゅッ繝舌シ繧ク繝ァ繝ウ繝√ぉ繝繧ッ蜈・繧後k + LogAdd_InfoParam(&arcInfo_ex); + }else { + LogAdd("> get fail");//譛牙柑縺ェ諠蝣ア繝輔ぃ繧、繝ォ縺後↑縺 + savedata.Unmount(); + exsave.Unmount(); + return false; + } + + //繝輔か繝シ繝槭ャ繝域ュ蝣ア縺ョ豈碑シ + if ((arcInfo.DirEntry != arcInfo_ex.DirEntry) || + (arcInfo.FileEntry != arcInfo_ex.FileEntry) || + (arcInfo.Dup != arcInfo_ex.Dup)) + { + LogAdd("> verifi fail");//譛牙柑縺ェ諠蝣ア繝輔ぃ繧、繝ォ縺後↑縺 + PutError(ERC_DEV_OUT,ERC_VERIFI); + savedata.Unmount(); + exsave.Unmount(); + return false; + } + + ct =0; + if (arcInfo.FileCount == 0)//繝輔ぃ繧、繝ォ縺檎┌縺 + { + LogAdd("> no files"); + savedata.Unmount(); + exsave.Unmount(); + return true;//繝輔か繝シ繝槭ャ繝井ク閾エ縺ョ縺ソ + }else{ + LogAdd("-- file compair --"); + if(isDebugMode==false) scr_Status("file compairing",COLOR_YELLO); + savedata.ResetPath(); + exsave.ResetPath(); + s64 fsize; + res = RESULT_OK; + while(res==RESULT_OK){ + res = savedata.GetPath(file_pathw); + if (res != RESULT_OK) + { + LogAdd("failed to get path"); + if (res == RESULT_DIR_LEVEL_OVER){ + LogAdd("Dir Level Over"); + break; + } + if (res == RESULT_PATH_LENGTH_OVER){ + LogAdd("path name too long"); + break; + } + res = RESULT_FAIL_OPEN; + break; + } + if (file_pathw[0] == 0){LogAdd("end");break;}//root then end + if (ct>=arcInfo.FileCount) + {//繧ォ繧ヲ繝ウ繧ソ螢翫l縲√Γ繝「繝ェ繝輔Ο繝シ縺ョ蜿ッ閭ス諤ァ + LogAdd("memory error"); + res = RESULT_FAIL; + break; + } +#ifdef DEBUG_ENABLE + wcstombs(file_path,file_pathw,510); + LogAdd(file_path); +#endif + if(isDebugMode==false) scr_CountPerMax(ct,arcInfo.FileCount); + if (savedata.Open(file_pathw)==false) + { + LogAdd("Open Error(card)"); + res = RESULT_FAIL_OPEN; + break; + } + fsize = savedata.FileSize; + total += fsize; + if (exsave.Open(file_pathw)==false) + { + LogAdd("Open Error(out)"); + res = RESULT_FAIL_OPENW; + //savedata.Close(); + break; + } + if (fsize != exsave.FileSize)//file size + { + res = RESULT_FAIL; + break; + } + msize=fsize; + if(msize <= FILEBUFF_SIZE ){//荳蝗槭〒隱ュ繧√k繧オ繧、繧コ縺ェ繧峨ご繝シ繧ク縺ッ蜃コ縺輔↑縺 + if(isDebugMode==false) scr_CountPerMax2(0,0,-1); + } + while(fsize) + { + if(msize > FILEBUFF_SIZE ){ + if(isDebugMode==false) scr_CountPerMax2(msize-fsize,msize,0); + } + if (fsize > FILEBUFF_SIZE) + { + rsize = FILEBUFF_SIZE; + fsize -= FILEBUFF_SIZE; + }else{ + rsize = fsize; + fsize = 0; + } + if(savedata.Read(fileBuffer,rsize) != rsize ) + { + //荳ュ霄ォ縺ョ繝繝シ繧ソ縺御ス懈舌し繧、繧コ縺ォ貅縺溘↑縺蝣エ蜷医↓讀懆ィシ繧ィ繝ゥ繝シ縺ィ縺ェ繧句ッセ遲 + //隱ュ繧√↑縺繝悶Ο繝繧ッ縺ッ鄂ョ縺肴鋤縺医k + //讀懆ィシ縺ッ512蜊倅ス阪〒縺輔l繧九ョ縺ァ隱ュ繧√※繧九→縺薙∪縺ァ鄂ョ縺肴鋤縺医↑縺繧医≧ + //繝ェ繝シ繝峨し繧、繧コ縺ッ512縺ォ縺励※縺翫¥ + if(nn::fs::ResultVerificationFailed::Includes(savedata.LastNnResult)) + { + for (i = 0; i < rsize; i++) + { + fileBuffer[i] = 0;//0蝓九a + } + }else{ + LogAdd("Read Error(card)"); + res = RESULT_FAIL_READ; + break; + } + } + if(exsave.Read(fileBuffer_ex,rsize) != rsize ) + { + LogAdd("Read Error(out)"); + res = RESULT_FAIL; + break; + } + } + savedata.Close(); + exsave.Close(); + //verifi + for (i = 0;i detect"); + if(exsave.Delete()) LogAdd("> deleted"); + else{ + savedata.Unmount(); + LogAdd("delete failed"); + PutError(ERC_DEV_OUT); + return ERROR; + } + }else{ + LogAdd("not found"); + } + + if(isDebugMode==false)scr_Status("Create Backup",COLOR_YELLO); + LogAdd("Create bkup"); +#ifdef BKUP_NOTMEM + res = exsave.Create((void*)IconBuffer,IconSize + ,arcInfo.DirEntry+1,arcInfo.FileEntry+1);//邂。逅諠蝣ア +#else + res = exsave.Create(0,0,arcInfo.DirEntry+1,arcInfo.FileEntry+1);//邂。逅諠蝣ア +#endif + + if (res != RESULT_OK){ + savedata.Unmount(); + PutError(ERC_DEV_OUT); + return ERROR; + } + + if (arcInfo.FileCount == 0)//繝輔ぃ繧、繝ォ縺檎┌縺 + { + LogAdd("> no files"); + if(isDebugMode==false)scr_Status("no files",COLOR_YELLO); + savedata.Unmount(); + exsave.Unmount(); + return SUCCESS;//繝輔か繝シ繝槭ャ繝医ョ縺ソ + }else{ + LogAdd("-- file copy --"); + if(isDebugMode==false)scr_Status("file copying",COLOR_SKY); + savedata.ResetPath(); + s64 fsize; + res = RESULT_OK; + while(res==RESULT_OK){ + res = savedata.GetPath(file_pathw); + if (res != RESULT_OK) + { + LogAdd("failed to get path"); + if (res == RESULT_DIR_LEVEL_OVER){ + LogAdd("Dir Level Over"); + PutError(ERC_DEV_CARD,ERC_DIRDEPTH); + break; + } + if (res == RESULT_PATH_LENGTH_OVER){ + LogAdd("path name too long"); + PutError(ERC_DEV_CARD,ERC_PATH); + break; + } + res = RESULT_FAIL_OPEN; + break; + } + if (file_pathw[0] == 0){LogAdd("end");break;}//root then end + if (ct>=arcInfo.FileCount) + {//繧ォ繧ヲ繝ウ繧ソ螢翫l縲√Γ繝「繝ェ繝輔Ο繝シ縺ョ蜿ッ閭ス諤ァ + LogAdd("memory error"); + res = RESULT_FAIL; + break; + } +#ifdef DEBUG_ENABLE + wcstombs(file_path,file_pathw,510); + LogAdd(file_path); +#endif + if(isDebugMode==false) scr_CountPerMax(ct,arcInfo.FileCount); + if (savedata.Open(file_pathw)==false) + { + LogAdd("Open Error(card)"); + res = RESULT_FAIL_OPEN; + break; + } + fsize = savedata.FileSize; + total += fsize; + if (exsave.OpenW(file_pathw,fsize)==false) + { + LogAdd("Open Error(sd)"); + res = RESULT_FAIL_OPENW; + //savedata.Close(); + break; + } + + msize=fsize; + while(fsize) + { + if(msize > FILEBUFF_SIZE * 2){ + if(isDebugMode==false) scr_CountPerMax2(msize-fsize,msize,0); + } + if (fsize>FILEBUFF_SIZE) + { + rsize = FILEBUFF_SIZE; + fsize -= FILEBUFF_SIZE; + }else{ + rsize = fsize; + fsize = 0; + } + if(savedata.Read(fileBuffer,rsize) != rsize ) + { + //荳ュ霄ォ縺ョ繝繝シ繧ソ縺御ス懈舌し繧、繧コ縺ォ貅縺溘↑縺蝣エ蜷医↓讀懆ィシ繧ィ繝ゥ繝シ縺ィ縺ェ繧句ッセ遲 + //隱ュ繧√↑縺繝悶Ο繝繧ッ縺ッ鄂ョ縺肴鋤縺医k + //讀懆ィシ縺ッ512蜊倅ス阪〒縺輔l繧九ョ縺ァ隱ュ繧√※繧九→縺薙∪縺ァ鄂ョ縺肴鋤縺医↑縺繧医≧ + //繝ェ繝シ繝峨し繧、繧コ縺ッ512縺ォ縺励※縺翫¥ + if(nn::fs::ResultVerificationFailed::Includes(savedata.LastNnResult)) + { + for (int i = 0; i < rsize; i++) + { + fileBuffer[i] = 0;//0蝓九a + } + }else{ + LogAdd("Read Error(card)"); + res = RESULT_FAIL_READ; + break; + } + } + if(exsave.Write(fileBuffer,rsize) != rsize ) + { + LogAdd("Write Error(bkup)"); + res = RESULT_FAIL_WRITE; + break; + } + } + savedata.Close(); + exsave.CloseW(); + //todo: 繧イ繝シ繧ク陦ィ遉コ + ct++; + } + savedata.Close(); + exsave.CloseW(); + } + + if (res == RESULT_OK){ + //繝輔か繝シ繝槭ャ繝域ュ蝣ア繧定ィ倬鹸 + //Exsave縺ォ2驥榊喧縺檎┌縺縺ョ縺ァ諠蝣ア蜿門セ輸PI縺ァ縺ッ荳崎カウ - 2011.1 迴セ蝨ィ + //繝励Ο繝繧ッ繝医さ繝シ繝峨r霑ス蜉(2011.1.26) + //繝舌シ繧ク繝ァ繝ウ繧定ソス蜉(2011.1.27) + LogAdd("save systemfile"); + if (exsave.OpenSysW()) + { + strcpy(arcInfo.Pcode,savedata.PrdCode); + if(exsave.WriteSys(&arcInfo)){ + LogAdd("> done"); + }else{ + LogAdd("> write fail"); + res = RESULT_FAIL_WRITE; + } + }else{ + LogAdd("> open fail"); + res = RESULT_FAIL_OPENW; + } + exsave.CloseSysW(); + } + savedata.Unmount(); + //exsave.Commit(); Nand縺ッ繧ウ繝溘ャ繝亥・繧後k(NAND譛ェ螳溯」->MEM螟画峩縲∽サ雁セ後b荳崎ヲシ) + exsave.Unmount(); + LogAdd_Int("> %d files",ct); + if(isDebugMode==false){ + scr_CountPerMax(ct,arcInfo.FileCount); + scr_CountPerMax2(0,0,total); + } + +//邨先棡 + switch(res) + { + case RESULT_OK: + if (Verifi()==false)return ERROR; + if(isDebugMode==false) scr_Status("Complate",COLOR_WHITE); + return SUCCESS; + case RESULT_FAIL_WRITE: + case RESULT_FAIL_OPENW: + PutError(ERC_DEV_OUT); + exsave.Delete();//繝舌ャ繧ッ繧「繝繝励r蜑企勁 + return ERROR; + case RESULT_FAIL_READ: + case RESULT_FAIL_OPEN: + PutError(ERC_DEV_CARD); + exsave.Delete();//繝舌ャ繧ッ繧「繝繝励r蜑企勁 + return ERROR; + } + //縺昴ョ莉悶∝ョ溯。梧凾繧ィ繝ゥ繝シ + PutError(ERC_DEV_OTHER); + return ERROR; +} + +bool mkdir; +//---------------------------------------------------------------- SD->CARD +RetCode Sd2Card() +{ + myResult res; + int ct=0,msize,rsize; + s64 total = 0; + + LogAdd("-- write savedata --"); + + if(isDebugMode == false){ + scr_RestoreYesNo();//螳溯。檎「コ隱 + WaitUI();//蜈・蜉帛セ縺。 + if(isInsEject != InEx_None ){//謖ソ謚懶シ + //isInsEject = InEx_None; + return INSEXIT;//謖ソ謚懊↓繧医k荳ュ譁ュ + } + if (scr_evnt != EVNT_YES)return CANCEL;//繧ュ繝」繝ウ繧サ繝ォ + } + if(isDebugMode==false){ + scr_Restore();//逕サ髱「陦ィ遉コ + scr_Status("Check Backup",COLOR_YELLO); + } + //菫晏ュ伜医ョ繝槭え繝ウ繝 + LogAdd("Mount bkup"); + res = exsave.Mount(); + if(res != RESULT_OK){ + PutError(ERC_DEV_OUT); + return ERROR; + } + + //繧サ繝シ繝悶ョ繝シ繧ソ縺ョ繝輔か繝シ繝槭ャ繝茨シ繝槭え繝ウ繝 + if(isDebugMode==false)scr_Status("Card savedata Create",COLOR_YELLO); + LogAdd("Format savedata"); + res = savedata.Format(&arcInfo);//_ex縺ョ譁ケ縺後>縺縺九b + if(res != RESULT_OK){ + exsave.Unmount(); + PutError(ERC_DEV_CARD); + return ERROR; + } + + //繝代Λ繝。繝シ繧ソ縺ッ繝舌ャ繧ッ繧「繝繝玲凾 + //Top逕サ髱「髢句ァ区凾縲∵諺蜈・繧、繝吶Φ繝医〒蜿門セ + if (arcInfo.FileCount == 0)//繝輔ぃ繧、繝ォ縺檎┌縺 + { + LogAdd("> no files"); + savedata.Unmount(); + exsave.Unmount(); + return SUCCESS;//繝輔か繝シ繝槭ャ繝医ョ縺ソ + }else{ + LogAdd("-- file restore --"); + if(isDebugMode==false)scr_Status("file copying",COLOR_PARPL); + exsave.ResetPath(); + s64 fsize; + res = RESULT_OK; + while(res==RESULT_OK){ + res = exsave.GetPath(file_pathw); + if (res != RESULT_OK) + { + LogAdd("failed to get path"); + if (res == RESULT_DIR_LEVEL_OVER){ + LogAdd("Dir Level Over"); + break; + } + if (res == RESULT_PATH_LENGTH_OVER){ + LogAdd("path name too long"); + break; + } + res = RESULT_FAIL_OPEN; + break; + } + if (file_pathw[0] == 0){LogAdd("end");break;}//root then end + if (ct>=arcInfo.FileCount) + {//繧ォ繧ヲ繝ウ繧ソ螢翫l縲√Γ繝「繝ェ繝輔Ο繝シ縺ョ蜿ッ閭ス諤ァ + LogAdd("memory error"); + res = RESULT_FAIL; + break; + } +#ifdef DEBUG_ENABLE + wcstombs(file_path,file_pathw,510); + LogAdd(file_path);//todo:繝繝舌げ陦ィ遉コ繧ェ繝シ繝仙ッセ遲 +#endif + if(isDebugMode==false) scr_CountPerMax(ct,arcInfo.FileCount); + if (exsave.Open(file_pathw)==false) + { + LogAdd("Open Error(bkup)"); + res = RESULT_FAIL_OPEN; + break; + } + fsize = exsave.FileSize; + total += fsize; +#ifdef ENABLE_CRUSH + //繝繝舌げ逕ィ縺ォ驕輔≧繝輔ぃ繧、繝ォ蜷阪↓縺吶k + if (CrashForDebug & 2)wcscat(file_pathw,L"D"); +#endif + int rev = 0; + while(1){ + if (savedata.OpenW(file_pathw,fsize,&mkdir)==false) + { + if(mkdir)//繝繧」繝ャ繧ッ繝医Μ縺ョ縺ソ菴懈 + {//豺ア縺蝣エ蜷医↓菴懈舌′螟壹>縺ィ逕サ髱「縺梧ュ「縺セ繧九ョ縺ァ + LogAdd("Dir create"); + rev++; + if (rev & 1)scr_MessOnCount2("Create Directry -"); + else scr_MessOnCount2("Create Directry |"); + + }else{ + LogAdd("Open Error(card)"); + res = RESULT_FAIL_OPENW; + //exsave.Close(); + break; + } + }else break; + } + if (res != RESULT_OK)break; + + msize = fsize; + int itvl = 0; + while(fsize) + { + if(isDebugMode==false) + if(msize > FILEBUFF_SIZE * 2){ + scr_CountPerMax2(msize-fsize,msize,0); + if (++itvl & 1)scr_Status("file copying |",COLOR_PARPL); + else scr_Status("file copying -",COLOR_PARPL); + + }else scr_MessOnCount2(""); + + if (fsize>FILEBUFF_SIZE) + { + rsize = FILEBUFF_SIZE; + fsize -= FILEBUFF_SIZE; + }else{ + rsize = fsize; + fsize = 0; + } + if(exsave.Read(fileBuffer,rsize) != rsize ) + { + LogAdd("Read Error(bkup)"); + res = RESULT_FAIL_READ; + break; + } +#ifdef ENABLE_CRUSH + //繝繝舌げ逕ィ縺ォ繝繝シ繧ソ繧貞」翫☆ + if (CrashForDebug & 1)//荳ュ霄ォ + { + int i; + for (i = 0;i %d files",ct); + if(isDebugMode==false){ + scr_CountPerMax(ct,arcInfo.FileCount); + scr_CountPerMax2(0,0,total); + } + +//邨先棡 + switch(res){ + case RESULT_OK: + if (Verifi()==false)return ERROR; +#ifdef SUCCESS_DELETE + if(exsave.Delete()){//繝舌ャ繧ッ繧「繝繝励r蜑企勁 + LogAdd("> deleted"); +#endif + if(isDebugMode==false) scr_Status("Complate",COLOR_WHITE); + return SUCCESS; +#ifdef SUCCESS_DELETE + }else{ + LogAdd("> delete fail"); + PutError(ERC_DEV_OUT); + return ERROR; + } +#endif + case RESULT_FAIL_WRITE: + case RESULT_FAIL_OPENW: + PutError(ERC_DEV_CARD); + return ERROR; + case RESULT_FAIL_READ: + case RESULT_FAIL_OPEN: + PutError(ERC_DEV_OUT); + return ERROR; + } + //縺昴ョ莉悶∝ョ溯。梧凾繧ィ繝ゥ繝シ + PutError(ERC_DEV_OTHER); + return ERROR; +} + + +//繝。繝「繝ェ菫晏ュ倥〒縺ッ荳崎ヲ +#ifdef BKUP_NOTMEM +//------------------------------------------------------------------ 繧「繧、繧ウ繝ウ繝繝シ繧ソ +//NAND襍キ蜍輔〒螟ア謨励ッ辟。縺縺ッ縺 +void ReadIcon() +{ + const size_t ROMFS_BUFFER_SIZE = 1024 * 64; + static char buffer[ROMFS_BUFFER_SIZE]; + nn::Result res; + + Active = false; + Formatted = false; + + //Icon繝繝シ繧ソ + //NN_LOG("ICON Data Read\n"); + LogAdd("Mount Rom"); + nn::fs::FileReader RomFsFile; + res = nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE); + if (res.IsFailure()) + { + //NN_LOG("failed :res.desc = %d\n",res.GetDescription()); + //failstop(); + LogAdd("> failed"); + LogAdd_Res(res); + return; + } + LogAdd("Read Icon data"); + res = RomFsFile.TryInitialize(L"rom:/def.icn"); + if (res.IsFailure()) + { + //NN_LOG("failed :res.desc = %d\n",res.GetDescription()); + nn::fs::Unmount("rom:"); + //failstop(); + LogAdd("> open failed"); + LogAdd_Res(res); + return; + } + //s32 gs = RomFsFile.GetSize(); + //NN_LOG("Icon Size = %d\n",gs); + res = RomFsFile.TryRead((s32*)&IconSize,(void*)IconBuffer,IconBuffSize); + if (res.IsFailure()) + { + //NN_LOG("failed :res.desc = %d\n",res.GetDescription()); + //RomFsFile.Finalize(); + nn::fs::Unmount("rom:"); + //failstop(); + LogAdd("> read failed"); + LogAdd_Res(res); + return; + } + //NN_LOG("Read Size = %d\n",IconSize); + RomFsFile.Finalize(); + nn::fs::Unmount("rom:"); + +} +#endif + +//--------------------------------------------------------------- 繧サ繝シ繝悶ョ繝シ繧ソ縺ョ諠蝣ア蜿門セ +//蜻シ縺カ蜑阪↓ tmerr 縺ョ繧ッ繝ェ繧「繧貞ソ倥l縺ェ縺莠 +void CheckSaveDataState() +{ + myResult myres; + + + Formatted = false;//繝輔か繝シ繝槭ャ繝 + Active = false; + //failveri = false; + + LogAdd("get pcode"); + if (savedata.GetPrdCode()) + { + LogAdd_cat("> pcode = ",savedata.PrdCode); + LogAdd("check savedata"); + myres = savedata.IsExist(); + if (myres != RESULT_FAIL) + { + Active = true;//繧「繧ッ繧サ繧ケ蜿ッ閭ス + switch(myres){ + case RESULT_OK: + LogAdd("> exist"); + Formatted=true; + break; + case RESULT_NO_MEDIA: + LogAdd("> Media not found"); + tmerr |= SDATA_ERRPUT_MEDIA; + break; + case RESULT_NOT_FAUND: + LogAdd("> not Found"); + break; + case RESULT_SDK_VERIFI: + LogAdd("> sdk verifi err"); + //failveri = true; + tmerr |= SDATA_ERRPUT_VERIFI; + break; + default: + LogAdd("> Not/Bad Format"); + break; + } + }else{ + LogAdd("> Invalid state"); + LogAdd_Res(savedata.LastNnResult); + } + }else + { + LogAdd("> fail"); + } + scr_PrdCode(savedata.PrdCode); + //繝励Ο繝繧ッ繝医さ繝シ繝峨ョ繝√ぉ繝繧ッ + isAgreePCode = strcmp(savedata.PrdCode,arcInfo.Pcode)==0; +} + +void CheckExSaveState() +{ + LogAdd("check exsave"); +#ifdef BKUP_NOTMEM + exActive = nn::fs::IsSdmcInserted(); +#else + exActive = true; +#endif + if (exActive){ + exFormatted = exsave.IsExist(); + if (exFormatted){ + LogAdd("> exist"); + if (exsave.GetInfo(&arcInfo)) + { + LogAdd_InfoParam(&arcInfo); + //todo:繝輔か繝シ繝槭ャ繝亥、画峩譎ゅッ繝舌シ繧ク繝ァ繝ウ繝√ぉ繝繧ッ蜈・繧後k + }else { + LogAdd("> sysdata none");//譛牙柑縺ェ諠蝣ア繝輔ぃ繧、繝ォ縺後↑縺 + //arcInfo.Pcode[0] = 0; + exFormatted = false; + } + exsave.Unmount(); + }else{ + LogAdd("> not found"); + //arcInfo.Pcode[0] = 0; + } + }else{ + LogAdd("> not inserted"); + //arcInfo.Pcode[0] = 0; + exFormatted = false; + } + if (exFormatted==false) arcInfo.Pcode[0] = 0; + scr_PrdCodeEx(arcInfo.Pcode); + //繝励Ο繝繧ッ繝医さ繝シ繝峨ョ繝√ぉ繝繧ッ + isAgreePCode = strcmp(savedata.PrdCode,arcInfo.Pcode)==0; +} + + +//---------------------------------------------------------------- 蜈・蜉帛セ縺。 +void WaitUI() +{ + tmerr = 0; + scr_Draw();//逕サ髱「譖エ譁ー + scr_evnt = EVNT_NONE; + while(scr_evnt == EVNT_NONE) + { + nn::os::Thread::Yield();//繧ケ繝ャ繝繝牙ョ溯。 + //scr_GetEvnt();//蜈・蜉帙う繝吶Φ繝 + + CheckSysBreak();//荳ュ譁ュ蜃ヲ逅 + + //謖ソ謚懊r讀懃衍縺励◆繧我クュ譁ュ縺励※謚懊¢繧 + //繝医ャ繝嶺サ・螟悶〒縺ッ繝医ャ繝励Γ繝九Η繝シ縺ク謌サ繧九h縺縺吶k + if (ejectEvnt.TryWait()){ + LogAdd("Card Ejected");//迥カ諷玖。ィ遉コシ壽栢縺 + CheckSaveDataState(); + isInsEject = InEx_EjcCard; + return; + } + if (insEvnt.TryWait()){ + LogAdd("Card Inserted");//迥カ諷玖。ィ遉コ:謖ソ蜈・ + CheckSaveDataState(); + isInsEject = InEx_InsCard; + return; + } +#ifdef BKUP_NOTMEM + if (ejectEvntSd.TryWait()){ + LogAdd("SD Ejected");//迥カ諷玖。ィ遉コシ壽栢縺 + CheckExSaveState(); + isInsEject = InEx_EjcSd; + return; + } + if (insEvntSd.TryWait()){ + LogAdd("SD Inserted");//迥カ諷玖。ィ遉コ:謖ソ蜈・ + CheckExSaveState(); + isInsEject = InEx_InsSd; + return; + } +#endif + } + ScrClr();//逕サ髱「豸亥悉 + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(500));//繝√Ε繧ソ蟇セ遲 +} + +tColStr mess_ReadError = {"[Read] is failed",COLOR_RED}; +tColStr mess_WriteError = {"[Write] is failed",COLOR_RED}; +tColStr mess_ReadOk = {"[Read] is Success",COLOR_GREEN}; +tColStr mess_WriteOk = {"[Write] is Success",COLOR_GREEN}; +tColStr mess_PullOut = {"Pull Out",COLOR_RED}; +tColStr mess_ChkDev = {"check device",COLOR_RED}; +tColStr mess_Insexit = {"Detect Insert or pull out",COLOR_RED}; +tColStr mess_WhenExc = {"When you exchange device",COLOR_WHITE}; +tColStr mess_PoffSys = {"PowerOff or return Top Menu",COLOR_WHITE}; + +//---------------------- main loop -------------------------- +void nnMain() +{ + int i; + myResult mres; + RetCode retc; + tColStr *colstr[4]; + colstr[2] = &mess_WhenExc; + colstr[3] = &mess_PoffSys; + isDebugMode = false; + isInsEject = InEx_None; + + //NN_LOG("Start\n"); + nn::os::Initialize(); + nn::fs::Initialize(); + + //DEA-SUP縺ォ縺ヲ謗ィ螂ィ縺ョ繝輔Μ繝シ繧コ證ォ螳壼ッセ遲厄シ夂┌邱壹ョ繝シ繝「繝ウ繧貞●豁「 (2011.3.1 迴セ蝨ィ) + //縺溘□縺励√せ繝ェ繝シ繝玲凾縺ョ"縺縺、縺ョ縺セ縺ォ騾壻ソ。"縺ッ豁「縺セ繧峨↑縺 + //辟。邱壹ッ菴ソ繧上↑縺縺悟ソオ縺ョ轤コ縲∵悽菴薙せ繧、繝繝√〒蛻縺」縺ィ縺上ョ縺檎「コ螳 + nn::ndm::SuspendScheduler(); + + //荳ュ譁ュ蜃ヲ逅縺ョ貅門y + InitSysBreak((uptr)endfunc); + // 繧ー繝ゥ繝輔ぅ繝繧ッ繧ケ繝ゥ繧、繝悶Λ繝ェ縺ョ蛻晄悄蛹悶ッ縲∽サ・髯阪〒陦後o縺ェ縺代l縺ー縺ェ繧峨↑縺 + // 莉悶√い繝励Μ繧ア繝シ繧キ繝ァ繝ウ縺ョ蛻晄悄蛹門ヲ逅 + + //Heap + appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), + nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + const u32 GxHeapSize = 0x800000; + heapForGx = reinterpret_cast(appHeap.Allocate(GxHeapSize)); +#ifdef BKUP_NOTMEM + IconBuffer = reinterpret_cast(appHeap.Allocate(IconBuffSize)); +#endif + //逕サ髱「蛻晄悄蛹 + if (ScrInitialize(heapForGx,GxHeapSize) == false)failstop(); +#ifdef DEBUG_ENABLE + memo.clr(); + memo.setbuttom(ScrDbgLogGetMax()-1);//陦ィ遉コ陦梧焚縺ァ繝ェ繧ケ繝域焚繧貞宛髯 +#endif + ejectEvnt.ClearSignal(); + insEvnt.ClearSignal(); + nn::fs::RegisterCardEjectedEvent(&ejectEvnt); + nn::fs::RegisterCardInsertedEvent(&insEvnt); +#ifdef BKUP_NOTMEM + ejectEvntSd.ClearSignal(); + insEvntSd.ClearSignal(); + nn::fs::RegisterSdmcEjectedEvent(&ejectEvntSd); + nn::fs::RegisterSdmcInsertedEvent(&insEvntSd); + ReadIcon(); //繧「繧、繧ウ繝ウ繝繝シ繧ソ縺ョ隱ュ霎シ +#endif + + // 繧ケ繝ェ繝シ繝苓ヲ∵アゅ↓蟇セ縺吶k霑皮ュ斐r譛牙柑縺ォ縺吶k + // 縺セ縺溘∬搭縺ョ迥カ諷九メ繧ァ繝繧ッ繧定。後>闢九′髢峨§繧峨l縺ヲ縺繧九↑繧峨せ繝ェ繝シ繝苓ヲ∵アゅ′逋コ逕溘☆繧 + nn::applet::EnableSleep(true); + + LogAdd("-- start --"); + + extern u8 scr_evnt; + while(1) + { + tmerr = 0; + CheckSaveDataState(); //繧サ繝シ繝悶ョ繝シ繧ソ縺ョ迥カ諷句叙蠕 + CheckExSaveState(); //蜷後ヰ繝繧ッ繧「繝繝 +#ifdef DEBUG_ENABLE + //繝医ャ繝励Γ繝九Η繝シ + if (isDebugMode){ + scr_TopMenuDbg(Formatted,Active); + scr_DgbLog(&memo); + while(ScrGetDrawFlag()){ + nn::os::Thread::Yield();//陦ィ遉コ + } + }else +#endif + if (isAgreePCode==false) tmerr |= SDATA_ERRPUT_PCODE; +// scr_TopMenu(Formatted,Active,exFormatted,exActive,isAgreePCode,failveri); + scr_TopMenu(Formatted,Active,exFormatted,exActive,tmerr); + + + WaitUI();//蜈・蜉帛セ縺。 + if (isInsEject != InEx_None){ + ScrClr();//逕サ髱「豸亥悉 + isInsEject= InEx_None; + }else + switch(scr_evnt) + { + case EVNT_PUSH_B: + case EVNT_NONE: + break; + case EVNT_PUSH_Y: +#ifdef ENABLE_CRUSH + CrashForDebug++; + CrashForDebug &= 3; +#endif + break; + case EVNT_SEL_READ://繝ェ繝シ繝 + NN_LOG("select read\n"); + retc = Card2Sd(); + switch (retc){ + case SUCCESS: + //CheckExSaveState(); //迥カ諷九ョ譖エ譁ー + if (isDebugMode){ + colstr[1] = &mess_ReadOk; + scr_SuccessQuitDbg(&colstr[1]);//謌仙粥縺ィQuit繝懊ち繝ウ + }else scr_ResultQuit("Success",COLOR_GREEN);//謌仙粥縺ィQuit繝懊ち繝ウ + break; + case INSEXIT: + //scr_InsExitQuit();//謖ソ謚懈、懃衍陦ィ遉コ & Quit + ScrClr();//逕サ髱「豸亥悉 + scr_Backup(); +#ifdef DEBUG_ENABLE + if (isDebugMode){ + colstr[1] = &mess_PullOut; + scr_ErrorQuitDbg(&colstr[1]);//繧ィ繝ゥ繝シ縺ィQuit繝懊ち繝ウ + }else +#endif + { + if (isInsEject == InEx_EjcCard)PutError(ERC_DEV_CARD,ERC_DEVICE); +#ifdef BKUP_NOTMEM + else if (isInsEject == InEx_EjcSd)PutError(ERC_DEV_OUT,ERC_DEVICE); +#endif + else PutError(ERC_DEV_OTHER); + scr_ResultQuit("Break",COLOR_RED);//繧ィ繝ゥ繝シ縺ィQuit繝懊ち繝ウ + } + break; + case CANCEL: + //scr_ResultQuit("Canseled",COLOR_YELLO);//繧ュ繝」繝ウ繧サ繝ォ + break; + default://errors +#ifdef DEBUG_ENABLE + if (isDebugMode){ + colstr[0] = &mess_ReadError; + colstr[1] = &mess_ChkDev; + scr_ErrorQuitDbg(colstr);//繧ィ繝ゥ繝シ縺ィQuit繝懊ち繝ウ + }else +#endif + scr_ResultQuit("Failed",COLOR_RED);//繧ィ繝ゥ繝シ縺ィQuit繝懊ち繝ウ + break; + } + if (retc == CANCEL)break; + //isInsEject = InEx_None; + while(1){ + WaitUI(); + if (isInsEject != InEx_None){ + isInsEject = InEx_None; + } + if(scr_evnt==EVNT_QUIT)break; + if(scr_evnt==EVNT_PUSH_B)break; + } + break; + case EVNT_SEL_WRITE://繝ェ繧ケ繝医い + NN_LOG("select write\n"); + retc = Sd2Card(); + switch (retc){ + case SUCCESS: + //CheckSaveDataState(); //迥カ諷九ョ譖エ譁ー + //CheckExSaveState(); + if (isDebugMode){ + colstr[1] = &mess_WriteOk; + scr_SuccessQuitDbg(&colstr[1]);//謌仙粥縺ィQuit繝懊ち繝ウ + }else scr_ResultQuit("Success",COLOR_GREEN);//謌仙粥縺ィQuit繝懊ち繝ウ + break; + case INSEXIT: + //scr_InsExitQuit();//謖ソ謚懈、懃衍陦ィ遉コ & Quit + ScrClr();//逕サ髱「豸亥悉 + scr_Backup(); +#ifdef DEBUG_ENABLE + if (isDebugMode){ + colstr[1] = &mess_PullOut; + scr_ErrorQuitDbg(&colstr[1]);//繧ィ繝ゥ繝シ縺ィQuit繝懊ち繝ウ + }else +#endif + { + if (isInsEject == InEx_EjcCard)PutError(ERC_DEV_CARD,ERC_DEVICE); +#ifdef BKUP_NOTMEM + else if (isInsEject == InEx_EjcSd)PutError(ERC_DEV_OUT,ERC_DEVICE); +#endif + else PutError(ERC_DEV_OTHER); + scr_ResultQuit("Break",COLOR_RED);//繧ィ繝ゥ繝シ縺ィQuit繝懊ち繝ウ + } + break; + case CANCEL: + //scr_ResultQuit("Canseled",COLOR_YELLO);//繧ュ繝」繝ウ繧サ繝ォ + break; + default://errors +#ifdef DEBUG_ENABLE + if (isDebugMode){ + colstr[0] = &mess_WriteError; + colstr[1] = &mess_ChkDev; + scr_ErrorQuitDbg(colstr);//繧ィ繝ゥ繝シ縺ィQuit繝懊ち繝ウ + }else +#endif + scr_ResultQuit("Failed",COLOR_RED);//繧ィ繝ゥ繝シ縺ィQuit繝懊ち繝ウ + break; + } + if (retc == CANCEL)break; + while(1){ + WaitUI(); + if (isInsEject != InEx_None){ + isInsEject= InEx_None; + } + if(scr_evnt==EVNT_QUIT)break; + if(scr_evnt==EVNT_PUSH_B)break; + } + break; +/* case EVNT_SEL_END: + NN_LOG("select end\n"); + finish(); + break; + case EVNT_NO: + NN_LOG("select NO\n"); + break; + case EVNT_YES: + NN_LOG("select NO\n"); + break; +*/ + case EVNT_PUSH_L:// ----------------------------------------- 陦ィ遉コ縺ョ蛻繧頑崛縺 + case EVNT_PUSH_DOWN_Y:// ----------------------------------------- 陦ィ遉コ縺ョ蛻繧頑崛縺 +#ifdef DEBUG_ENABLE + isDebugMode = (isDebugMode == false); +#endif + break; + + case EVNT_PUSH_LEFT_X:// ------------------------------------- LEFT + X + //繝舌ャ繧ッ繧「繝繝怜炎髯、 + scr_DelConf();//螳溯。檎「コ隱 + WaitUI(); + if (scr_evnt != EVNT_YES)break; + exsave.Delete(); + //CheckExSaveState(); //迥カ諷区峩譁ー + break; + + case EVNT_PUSH_R:// ------------------------------------------- R + //CARD(NAND)縺ク繝繧ケ繝医ヵ繧。繧、繝ォ譖ク縺崎セシ縺ソ + //繝繝舌げ繝「繝シ繝画凾縺ョ縺ソ + bool flg; + scr_ConfirmDbg("dummy savedata write OK?");//螳溯。檎「コ隱 + WaitUI(); + if (scr_evnt != EVNT_YES)break; + for ( i =0;i failed"); + LogAdd_Res(savedata.LastNnResult); + LogAdd_Int("%d",mres); + break; + } + + i= 2; + LogAdd("create"); + while(i){ + sprintf(file_path,"dir%d/file%d",i,i); + LogAdd(file_path); + mbstowcs(file_pathw,file_path,510); + if (savedata.OpenW(file_pathw,FILEBUFF_SIZE,&flg)==false) + { + LogAdd("> Open Error"); + break; + } + if(savedata.Write(fileBuffer,FILEBUFF_SIZE)!=FILEBUFF_SIZE) + { + LogAdd("> Write failed"); + break; + } + savedata.CloseW(); + i--; + } + i=2; + while(i){ + sprintf(file_path,"dir%d/dir%d/file%d",i,i,i); + LogAdd(file_path); + mbstowcs(file_pathw,file_path,510); + if (savedata.OpenW(file_pathw,FILEBUFF_SIZE,&flg)==false) + { + LogAdd("> Open Error"); + break; + } + if(savedata.Write(fileBuffer,FILEBUFF_SIZE)!=FILEBUFF_SIZE) + { + LogAdd("> Write failed"); + break; + } + savedata.CloseW(); + + sprintf(file_path,"dir%d/dir%d/file%d",i,i,i+2); + LogAdd(file_path); + mbstowcs(file_pathw,file_path,510); + if (savedata.OpenW(file_pathw,FILEBUFF_SIZE,&flg)==false) + { + LogAdd("> Open Error"); + break; + } + if(savedata.Write(fileBuffer,FILEBUFF_SIZE)!=FILEBUFF_SIZE) + { + LogAdd("> Write failed"); + break; + } + savedata.CloseW(); + i--; + } + savedata.CloseW(); + savedata.Commit(); + savedata.Unmount(); + //CheckSaveDataState(); //繧ォ繝シ繝臥憾諷区峩譁ー + break; + default: + NN_LOG("menu error\n"); + failstop(); + break; + } + }//while() + +} + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/my_defs.h b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/my_defs.h new file mode 100644 index 0000000..c79645d --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/my_defs.h @@ -0,0 +1,92 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: irp.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef MYDEFS_H_ +#define MYDEFS_H_ + +//繝繝舌げ繝「繝シ繝画怏蜉ケ蛹 +//#define DEBUG_ENABLE 1 + +//繝ェ繧ケ繝医い謌仙粥譎よカ亥悉 +#define SUCCESS_DELETE 1 + +//SD菴ソ逕ィ譎 +//#define BKUP_NOTMEM 1 + +//繝繝シ繧ソ螢翫☆繝「繝シ繝画怏蜉ケ +//#define CRUSH_ENABLE 1 + + +//繧ィ繝ゥ繝シ陦ィ遉コ繧ウ繝シ繝 +enum { +ERC_UNKNOWN = 0, //荳肴 +ERC_DEVICE, //繝繝舌う繧ケ縺瑚ヲ九▽縺九i縺ェ縺(繧ォ繝シ繝画栢縺) +ERC_PRODCODE,//繝励Ο繝繧ッ繝医さ繝シ繝我ク堺ク閾エ +ERC_VERIFI,//繝吶Μ繝輔ぃ繧、繧ィ繝ゥ繝シ +ERC_PATH,//繝代せ縺碁聞縺吶℃ +ERC_DIRDEPTH,//繝繧」繝ャ繧ッ繝医Μ豺ア縺吶℃ +ERC_MEDIA, //繝。繝繧」繧「縺瑚ヲ九▽縺九i縺ェ縺(繧オ繝門渕逶、螟悶l縺ェ縺ゥ) +//ERC_PULLOUT,//謚懊¢讀懷コ +ERC_READ = 10, //繝輔ぃ繧、繝ォ縺瑚ヲ九▽縺九i縺ェ縺 +ERC_WRITE_OW = 20, //譌「縺ォ蟄伜惠 +ERC_WRITE_NS, //遨コ縺榊ョケ驥上′縺ェ縺 +ERC_WRITE_PROTECT, //譖ク霎シ縺ソ遖∵ュ「 +ERC_ACCESS = 30, //繧「繧ッ繧サ繧ケ繧ィ繝ゥ繝シ +ERC_FORMAT = 50, //繝輔か繝シ繝槭ャ繝医お繝ゥ繝シ +ERC_SDK_VERIFI = 60, //讀懆ィシ縺ォ螟ア謨励∵隼遶 +ERC_ROM = 70, //ROM諠蝣ア繧ィ繝ゥ繝シ +ERC_RETRY = 80, //繝ェ繝医Λ繧、隕∵ア +ERC_EXEC = 90, //螳溯。梧凾繧ィ繝ゥ繝シ +ERC_FATAL = 99 //豺ア蛻サ縺ェ繧ィ繝ゥ繝シ +}; + +typedef enum{ +ERC_DEV_CARD = 100, +ERC_DEV_OUT = 200, +ERC_DEV_OTHER = 300 +}ErcDev; + + +//蜀驛ィ菴ソ逕ィ縺ョ繧ィ繝ゥ繝シ +typedef enum { + RESULT_OK, + RESULT_FAIL, + RESULT_FAIL_OPEN, + RESULT_FAIL_OPENW, + RESULT_FAIL_DELETE, + RESULT_FAIL_CREATE, + RESULT_FAIL_READ, + RESULT_FAIL_WRITE, + RESULT_FAIL_MOUNT, + RESULT_FAIL_FORMAT, + RESULT_FAIL_GETDIR, + RESULT_NOT_FAUND, + RESULT_NO_MEDIA, + RESULT_NOT_FORMAT, + RESULT_BAD_FORMAT, + RESULT_SDK_VERIFI, + RESULT_FILE_EXIST, + RESULT_NO_EXSAVE, + RESULT_ALREADY_MOUNT, + RESULT_INVALID_FILE, + RESULT_BAD_PARAM, + RESULT_DIR_LEVEL_OVER, + RESULT_PATH_LENGTH_OVER, + RESULT_MAX +}myResult; + + + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/exsave.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/exsave.cpp new file mode 100644 index 0000000..309ca80 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/exsave.cpp @@ -0,0 +1,301 @@ +サソ#include +#include +#include +#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";//證ォ螳 +#define PATHLENGTH_MAX_EX 512 +wchar_t expath_w[PATHLENGTH_MAX_EX];//繝代せ蜷 +wchar_t expathu_w[100][PATHLENGTH_MAX_EX];//荳雁ア、繝代せ蜷 +wchar_t expathw_w[PATHLENGTH_MAX_EX];//繝代せ蜷阪Ρ繝シ繧ッ +#define MAX_LEVEL_EX 128 +static nn::fs::DirectoryEntry exdcEntry[MAX_LEVEL_EX]; +static nn::fs::Directory exdc[MAX_LEVEL_EX]; + + +//諡。蠑オ繧サ繝シ繝悶ョ繝シ繧ソ +//蟄伜惠遒コ隱 +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_EX)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); +} +//繝ゥ繧、繝亥ア樊ァ繝輔ぃ繧、繝ォ繧帝哩縺倥k +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(); +} +//繝ゥ繧、繝亥ア樊ァ繝輔ぃ繧、繝ォ繧帝哩縺倥k +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(); +} +//繝ゥ繧、繝亥ア樊ァ繝輔ぃ繧、繝ォ繧帝哩縺倥k +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; + //繝繧」繝ャ繧ッ繝医Μ縺後↑縺代l縺ー繝繧」繝ャ繧ッ繝医Μ繧剃ス懈 + pos = GetPosDelmLast(expath_w,ROOTLENGTH_EX);//繝輔ぃ繧、繝ォ縺悟ュ伜惠縺吶k繝繧」繝ャ繧ッ繝医Μ + if (pos <= 0)return false;//root縺九ヱ繧ケ縺御ク肴ュ」 + //while (1){ + wcscpy(expathw_w,expath_w);//繝ッ繝シ繧ッ縺ォ繧ウ繝斐シ + while (LastNnResult.IsFailure()){//繝繧」繝ャ繧ッ繝医Μ菴懈舌〒縺阪k縺セ縺ァ驕。繧 + 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;//驟咲スョ繝繧」繝ャ繧ッ繝医Μ縺ェ繧画栢縺代k + //todo:繝繧」繝ャ繧ッ繝医Μ縺梧キア縺縺ィ縺肴凾髢薙′縺九°繧九↑繧峨∫┌鬧縺ェTryCreate繧堤怐縺 + //譯茨シ臥峩荳翫°繧画怙蛻昴ョ謌仙粥縺セ縺ァ縺ョ繝繝ェ繝溘ち菴咲スョ繧定ィ倬鹸 + //蜈医↓蜈ィ繝繧」繝ャ繧ッ繝医Μ菴懊▲縺ヲ縺翫¥縺ョ縺後h縺輔£ + //} + } + 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; + //繧キ繧ケ繝繝繝繝シ繧ソ縺九i繝輔か繝シ繝槭ャ繝域ュ蝣ア + 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(); +} + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/exsave.h b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/exsave.h new file mode 100644 index 0000000..0806d88 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/exsave.h @@ -0,0 +1,70 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: irp.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef EXSAVE_H_ +#define EXSAVE_H_ + +#include +#include +#include "../my_defs.h" +#include "savefile.h" + +class ExSave +{ +public: + s64 FileSize; + nn::Result LastNnResult; +private: + nn::fs::FileReader reader; + nn::fs::FileWriter writer; + nn::fs::FileReader readerSys; + nn::fs::FileWriter writerSys; + wchar_t *pPathTop; + tArcInfo m_info; + int s_lv; + int exrootlen; + bool IsMounted; + bool s_serch; +public: + ExSave(); + ~ExSave(); + void Finalize(); + myResult Create(const void* icon,size_t iconSize,u32 entryDir,u32 entryFile); + myResult CreateSys(const void* icon,size_t iconSize); + myResult Mount(); + myResult MountSys(); + bool IsExist(); + void Unmount(); + bool Delete(); + void CloseW(); + bool OpenW(wchar_t *path,s64 size); + bool OpenSysW();//證ォ螳 + void CloseSysW();//證ォ螳 + bool OpenSysR();//證ォ螳 + void CloseSysR();//證ォ螳 + s32 Write(char *buffer,size_t size); + bool WriteSys(tArcInfo *pinfo); + bool ReadSys(tArcInfo *pinfo); + void ResetPath(); + s32 Read(char *buffer,size_t size); + void Close(); + bool Open(wchar_t *path); + myResult GetPath(wchar_t *path); + bool GetInfo(tArcInfo *pinfo); +}; + + + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/membak.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/membak.cpp new file mode 100644 index 0000000..cc54973 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/membak.cpp @@ -0,0 +1,228 @@ +#include +#include +#include +#include +#include "membak.h" + +using namespace nn; + +namespace +{ + const size_t BUFFER_SIZE = 10 * 1024 * 1024; + bit8 s_Buffer[BUFFER_SIZE] NN_ATTRIBUTE_ALIGN(32); +} + +bool info_alive; + +//-------------------------------------------------------------------- +// + + +//コンストラクタ +MemBak::MemBak() +{ + m_Exists = false; + m_pBuffer = s_Buffer; + m_pBufferPos = s_Buffer; + m_pBufferSize = sizeof(s_Buffer); + LastNnResult = ResultSuccess(); + ResetPath(); + + info_alive = false; +} + +void MemBak::Finalize() +{ +} +//デストラクタ +MemBak::~MemBak() +{ +} + + + + + +//-------------------------------------------------------------------- +// mount, unmount, create, delete + +//拡張セーブデータ +//存在確認 +bool MemBak::IsExist() +{ + return m_Exists; +} + +//セーブ作成、成功時はマウント状態 +myResult MemBak::Create(const void* icon,size_t iconSize,u32 entryDir,u32 entryFile) +{ + NN_UNUSED_VAR(icon); + NN_UNUSED_VAR(iconSize); + + if ( m_IsMounted ) + { + return RESULT_ALREADY_MOUNT; + } + + m_NumDirEntry = entryDir; + m_NumFileEntry = entryFile; + + m_Exists = true; + m_IsMounted = true; + return RESULT_OK; +} + +//削除 +bool MemBak::Delete() +{ + m_Exists = false; + info_alive = false; + m_pBufferPos = m_pBuffer; + return true; +} + +//マウント +myResult MemBak::Mount() +{ + if ( m_IsMounted ) + { + return RESULT_ALREADY_MOUNT; + } + + m_IsMounted = true; + return RESULT_OK; +} +void MemBak::Unmount() +{ + m_IsMounted = false; +} + + + + +//-------------------------------------------------------------------- +// SetInfo, GetInfo + +//アーカイブ情報の取得 +bool MemBak::GetInfo(tArcInfo *pinfo) +{ + if (info_alive==false)return false; + *pinfo = m_ArcInfo; + return true; +} + + +//管理用ファイル +//ライト属性で開く +bool MemBak::OpenSysW() +{ + return true; +} +//ライト属性ファイルを閉じる +void MemBak::CloseSysW() +{ +} + +//システムファイルライト +bool MemBak::WriteSys(tArcInfo *pinfo) +{ + info_alive = true; + pinfo->Ver = INFO_VERSION; + m_ArcInfo = *pinfo; + return true; +} + + + + +//-------------------------------------------------------------------- +// Traverse + +//パス検索位置のリセット +void MemBak::ResetPath() +{ + m_pFind = reinterpret_cast(m_pBuffer); +} + + +myResult MemBak::GetPath(wchar_t *path) +{ + if( m_pFind->IsEnd() ) + { + path[0] = '\0'; + return RESULT_OK; + } + + std::wcscpy(path, m_pFind->GetName()); + m_pFind = m_pFind->GetNext(); + + return RESULT_OK; +} + + + + +//-------------------------------------------------------------------- +// Write + +//ライト属性ファイルを閉じる +void MemBak::CloseW() +{ +} + +//ファイルライト +s32 MemBak::Write(char *buffer,size_t size) +{ + return m_ForWrite.Write(buffer, size); +} + + + +//ライト属性ファイルを開く +bool MemBak::OpenW(wchar_t *path,s64 size) +{ + m_ForWrite.Init(reinterpret_cast(m_pBufferPos)); + m_ForWrite.Set(path, size); + m_pBufferPos = reinterpret_cast(m_ForWrite.GetNext()); + return true; +} + +//-------------------------------------------------------------------- +// Read + +//ファイルリード +s32 MemBak::Read(char *buffer,size_t size) +{ + return m_ForRead.Read(buffer, size); +} + + +void MemBak::Close() +{ +} + + +//ファイルを開く +//パス指定はルート以降 +//(ex)data:/dir/file -> dir/file +bool MemBak::Open(wchar_t *path) +{ + EntryHeader* pE = reinterpret_cast(m_pBuffer); + + while( ! pE->IsEnd() ) + { + if( pE->Match(path) ) + { + m_ForRead.Init(pE); + FileSize = m_ForRead.GetSize(); + return true; + } + + pE = pE->GetNext(); + } + + return false; +} + +//-------------------------------------------------------------------- + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/membak.h b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/membak.h new file mode 100644 index 0000000..d3c8677 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/membak.h @@ -0,0 +1,189 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: irp.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef MEMBAK_H_ +#define MEMBAK_H_ + +#include +#include +#include "../my_defs.h" +#include "savefile.h" +#include + +class MemBak +{ +public: + s64 FileSize; + NN_PADDING4; + nn::Result LastNnResult; +private: + struct EntryHeader + { + s16 nameSize; + NN_PADDING2; + s32 dataSize; + s32 nextOffset; + + EntryHeader* GetNext() + { + return reinterpret_cast( + reinterpret_cast(this) + nextOffset); + } + bit8* GetDataPointer() + { + return reinterpret_cast(this + 1) + nameSize; + } + const wchar_t* GetName() const + { + return reinterpret_cast( + reinterpret_cast(this + 1)); + } + void SetName(const wchar_t* name) + { + s32 len = std::wcslen(name); + nameSize = len * 2 + 2; + std::memcpy(this + 1, name, nameSize); + } + void SetSize(size_t size) + { + dataSize = size; + } + s32 GetSize() const + { + return dataSize; + } + void SetNext() + { + nextOffset = nn::math::RoundUp(sizeof(*this) + nameSize + dataSize, 4); + } + bool Match(const wchar_t* p) + { + return std::wcscmp(p, GetName()) == 0; + } + bool IsEnd() const + { + return nameSize == 0; + } + }; + struct FileState + { + EntryHeader* pE; + s32 pos; + + void Init(EntryHeader* p) + { + pE = p; + pos = 0; + } + void Set(const wchar_t* name, size_t size) + { + pE->SetName(name); + pE->SetSize(size); + pE->SetNext(); + pE->GetNext()->nameSize = 0; + } + s32 GetSize() const { return pE->GetSize(); } + EntryHeader* GetNext() + { + return pE->GetNext(); + } + bit8* GetCurrentPointer() + { + return pE->GetDataPointer() + pos; + } + s32 GetRemain() const + { + return pE->dataSize - pos; + } + void Advance(s32 size) + { + pos += size; + } + s32 Write(const void* p, size_t size) + { + s32 remain = GetRemain(); + if( remain <= 0 ) + { + return 0; + } + + s32 copySize = nn::math::Min(remain, size); + std::memcpy(GetCurrentPointer(), p, copySize); + Advance(copySize); + + return copySize; + } + s32 Read(void* p, size_t size) + { + s32 remain = GetRemain(); + if( remain <= 0 ) + { + return 0; + } + + s32 copySize = nn::math::Min(remain, size); + std::memcpy(p, GetCurrentPointer(), copySize); + Advance(copySize); + + return copySize; + } + }; + + tArcInfo m_ArcInfo; + FileState m_ForRead; + FileState m_ForWrite; + + bool m_Exists; + bool m_IsMounted; + NN_PADDING2; + bit8* m_pBuffer; + size_t m_pBufferSize; + bit8* m_pBufferPos; + EntryHeader* m_pFind; + + u32 m_NumDirEntry; + u32 m_NumFileEntry; + +public: + MemBak(); + ~MemBak(); + void Finalize(); + myResult Create(const void* icon,size_t iconSize,u32 entryDir,u32 entryFile); + myResult CreateSys(const void* icon,size_t iconSize); + myResult Mount(); +// myResult MountSys(); + bool IsExist(); + void Unmount(); + bool Delete(); + void CloseW(); + bool OpenW(wchar_t *path,s64 size); + bool OpenSysW();//暫定 + void CloseSysW();//暫定 +// bool OpenSysR();//暫定 +// void CloseSysR();//暫定 + s32 Write(char *buffer,size_t size); + bool WriteSys(tArcInfo *pinfo); +// bool ReadSys(tArcInfo *pinfo); + void ResetPath(); + s32 Read(char *buffer,size_t size); + void Close(); + bool Open(wchar_t *path); + myResult GetPath(wchar_t *path); + bool GetInfo(tArcInfo *pinfo); +}; + + + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savedata.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savedata.cpp new file mode 100644 index 0000000..715bd7f --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savedata.cpp @@ -0,0 +1,445 @@ +サソ#include +#include +#include +#include "savedata.h" +#include +//#include <../fs/fs_ApiSysSaveData.h> +//#include <../fs/ctr/mpcore/fs_FileSystemBasePrivate.h> +#include +#include +#include + +#define MAX_LEVEL 256 +//static nn::fs::DirectoryEntry dcEntry[MAX_LEVEL]; +//static nn::fs::Directory dc[MAX_LEVEL]; +int dc_readed[MAX_LEVEL];//繝ェ繝シ繝画ク医∩繧ィ繝ウ繝医Μ謨ー + +//逕滓先凾縺ョ繝繝舌う繧ケ蜷阪r雜縺医k縺ィ繝代せ髟キ荳企剞繧偵%縺医k +//蜿ッ閭ス諤ァ縺後≠繧九ョ縺ァシ第枚蟄励↓縺吶k(辟。逕ィ縺ェ蠢驟阪°繧) +const wchar_t *sdataRoot_w = L"s:/"; +#define ROOTLENGTH 3 +const char *sdataName = "s:"; +const wchar_t *Dummy_w = L"ncltool"; +//char path[512];//繝代せ蜷 +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];//繝代せ蜷阪Ρ繝シ繧ッ + +//#define SysSaveId 0x20300 + +//繧サ繝シ繝紋ス懈舌∵仙粥譎ゅッ繝槭え繝ウ繝育憾諷 +myResult SaveData::Format(tArcInfo *pinfo) +{ + if ( IsMounted )return RESULT_ALREADY_MOUNT; +#ifdef USE_SYS_SAVE + LastNnResult = nn::fs::CreateSystemSaveData( + SysSaveId,pinfo->FileEntry,pinfo->DirEntry,0x100000,pinfo->Dup); + if (LastNnResult.IsFailure())return RESULT_FAIL_FORMAT; +#else + LastNnResult = nn::fs::FormatCtrCardSaveData(pinfo->FileEntry,pinfo->DirEntry,pinfo->Dup); + if (LastNnResult.IsFailure())return RESULT_FAIL_FORMAT; +#endif + 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;nMAX_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) +{ + + //strcpy(path,readerRoot); + 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); + //wcscpy(pathu_w,path_w); + + int n; + int lv = 0; + bool cont = true; + while(cont){ + LastNnResult = dc[lv].TryInitialize(path_w);//Open + if (LastNnResult.IsFailure())return false; + while(1){ + n = (dc[lv].Read(&dcEntry[lv],1)); + if ( n==0 )//邨らォッ + { + dc[lv].Finalize(); + if (lv == 0){cont=false;break;}// ---- 邨ゆコ + lv--;//荳翫ョ螻、縺ォ謌サ繧 + wcscpy(path_w,pathu_w[lv]);//繝代せ謌サ縺 + }else{ + if(dcEntry[lv].attributes.isDirectory){//繝繧」繝ャ繧ッ繝医Μ + m_info.DirCount++; + wcscpy(pathu_w[lv],path_w);//繝代せ菫晏ュ + wcscat(path_w,dcEntry[lv].entryName);//谺。縺ョ繝繧」繝ャ繧ッ繝医Μ繝代せ + wcscat(path_w,L"/"); + if (++lv == MAX_LEVEL)return false; + break; + }else{//繝輔ぃ繧、繝ォ + m_info.FileCount++; + } + } + } + } + +#ifndef INFO_API_USE + //繧「繝シ繧ォ繧、繝悶ョ繧ィ繝ウ繝医Μ謨ー + //縲.. API縺セ縺ァ縺ョ證ォ螳 + m_info.DirEntry = m_info.DirCount; + m_info.FileEntry = m_info.FileCount; +#else +//API菴ソ逕ィ +#ifdef USE_SYS_SAVE + size_t sz; + LastNnResult = nn::fs::GetSystemSaveDataFormatInfo(SysSaveId, &m_info.FileEntry, &m_info.DirEntry, &sz, &m_info.Dup); +#else + //LastNnResult = nn::fs::GetSaveDataFormatInfo(&m_info.FileEntry,&m_info.DirEntry,&m_info.Dup); + LastNnResult = nn::fs::GetCtrCardSaveDataFormatInfo(&m_info.FileEntry,&m_info.DirEntry,&m_info.Dup); +#endif + if (LastNnResult.IsFailure())return false; + +#endif + + *pinfo = m_info;//讒矩菴薙さ繝斐シ + return true; + +} +*/ +//繧「繝シ繧ォ繧、繝匁ュ蝣ア縺ョ蜿門セ +bool SaveData::GetInfo(tArcInfo *pinfo) +{ +static nn::fs::DirectoryEntry dcEntryl; +static nn::fs::Directory dcl; + + //strcpy(path,readerRoot); + 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); + //wcscpy(pathu_w,path_w); + + int n; + int lv = 0; + for (n = 0;n 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; + //while(1){ + LastNnResult = nn::fs::TryCreateFile(path_w,size); + if(LastNnResult.IsSuccess()) + { + LastNnResult = writer.TryInitialize(path_w,false); + return LastNnResult.IsSuccess(); + } + //繝繧」繝ャ繧ッ繝医Μ縺後↑縺代l縺ー繝繧」繝ャ繧ッ繝医Μ繧剃ス懈 + pos = GetPosDelmLast(path_w,ROOTLENGTH);//繝輔ぃ繧、繝ォ縺悟ュ伜惠縺吶k繝繧」繝ャ繧ッ繝医Μ + if (pos <= 0)return false;//root縺九ヱ繧ケ縺御ク肴ュ」 + //while (1){ + wcscpy(pathw_w,path_w);//繝ッ繝シ繧ッ縺ォ繧ウ繝斐シ + while (LastNnResult.IsFailure()){//繝繧」繝ャ繧ッ繝医Μ菴懈舌〒縺阪k縺セ縺ァ驕。繧 + 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; // 蟶ー蛟、シ喃alse 縺ァ mkdir=true 縺ェ繧峨ョ繧」繝ャ繧ッ繝医Μ菴懈舌ョ縺ソ + return false; + //if (pos2 == pos)break;//驟咲スョ繝繧」繝ャ繧ッ繝医Μ縺ェ繧画栢縺代k + //todo:繝繧」繝ャ繧ッ繝医Μ縺梧キア縺縺ィ縺肴凾髢薙′縺九°繧九↑繧峨∫┌鬧縺ェTryCreate繧堤怐縺 + //譯茨シ臥峩荳翫°繧画怙蛻昴ョ謌仙粥縺セ縺ァ縺ョ繝繝ェ繝溘ち菴咲スョ繧定ィ倬鹸 + //蜈医↓蜈ィ繝繧」繝ャ繧ッ繝医Μ菴懊▲縺ヲ縺翫¥縺ョ縺後h縺輔£ + //} + //} + //LastNnResult = writer.TryInitialize(path_w,false); + //return LastNnResult.IsSuccess(); +} + + +//繝輔ぃ繧、繝ォ繝ゥ繧、繝 +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() +{ +#ifdef USE_SYS_SAVE + LastNnResult=nn::fs::CommitSystemSaveData(sdataName); +#else + LastNnResult=nn::fs::CommitSaveData(sdataName); +#endif + 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); + //wcscpy(pathu_w,path_w); + pPathTop = (wchar_t*)((u32)&path_w+strlen(sdataName)*2+2); + +} + +void SaveData::Finalize() +{ + Close(); + Unmount(); +} +//繝繧ケ繝医Λ繧ッ繧ソ +SaveData::~SaveData() +{ + Finalize(); +} + + + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savedata.h b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savedata.h new file mode 100644 index 0000000..1878008 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savedata.h @@ -0,0 +1,66 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: irp.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef SAVEDATA_H_ +#define SAVEDATA_H_ + +#include +#include +//#include +#include "../my_defs.h" +#include "savefile.h" + +#define MAX_PATH_LENGTH 512 + +class SaveData +{ +public: + s64 FileSize; + nn::Result LastNnResult; + char PrdCode[20]; +private: + nn::fs::FileReader reader; + nn::fs::FileWriter writer; + int s_lv; + wchar_t *pPathTop; + tArcInfo m_info; + bool s_serch; + u8 pad[3];//padding +public: + SaveData(); + ~SaveData(); + myResult Mount(); + void Unmount(); + myResult GetPath(wchar_t *path); + void ResetPath(); + bool Open(wchar_t *path); + void Finalize(); + void Close(); + void CloseW(); + s32 Read(char *buffer,size_t size); + myResult IsExist(); + bool GetInfo(tArcInfo *pinfo); + myResult Format(tArcInfo *pinfo); + bool OpenW(wchar_t *path,s64 size,bool *mkdir); + s32 Write(char *buffer,size_t size); + bool Commit(); + bool GetPrdCode(); +#ifdef USE_SYS_SAVE + void Delete(); +#endif +}; + + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savefile.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savefile.cpp new file mode 100644 index 0000000..8b050d2 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savefile.cpp @@ -0,0 +1,18 @@ +//共通関数 + +#include "savefile.h" + +//終端から前方検索で見つかった境界("/"=0x2f)位置を返す +//top :検索範囲の先頭指定 +int GetPosDelmLast(wchar_t *s,int top) +{ + size_t i = wcslen(s); + if (i < top)return -1; + if (i ==top)return 0; + i--; + while(i > top-1){ + if (s[i]==L'/')return i; + i--; + } + return -1; +} diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savefile.h b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savefile.h new file mode 100644 index 0000000..96775cd --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/savefile/savefile.h @@ -0,0 +1,35 @@ +#ifndef SAVEFILE_H_ +#define SAVEFILE_H_ + +#include +#include +#include + +//API使用してアーカイブ情報を取得 +#define INFO_API_USE 1 + +//カードの変わりにシステムセーブを使用(API対応までの暫定) +//#define USE_SYS_SAVE 1 + +//SD保存 +//#define BKUP_NOTMEM 1 + +int GetPosDelmLast(wchar_t *s,int top); + +//情報ファイルのバージョン +#define INFO_VERSION 1 + +//SDバックアップに同梱する情報 +//変更の際は後方互換とれるよう追加のみとする +typedef struct{ + u32 DirEntry,FileEntry; + u32 DirCount,FileCount; + bool Dup; + u8 Ver;//バージョン + char Pcode[20];//product code save,exsaveクラスのPrdCodeサイズを下回らないこと + u8 padding[3];//パディング +}tArcInfo; + + + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/screen/screen.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/screen/screen.cpp new file mode 100644 index 0000000..dfded5b --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/screen/screen.cpp @@ -0,0 +1,759 @@ +#include +#include +#include "screen.h" +#include "../my_defs.h" +#include "../common/ver.h" + + +Gui gui; +u8 scr_evnt; + +enum{ +//PANEL_END, +PANEL_ERROR, +PANEL_SUCCESS, +PANEL_TOPMENU, +PANEL_TITLE, +PANEL_QUIT, +PANEL_READ, +PANEL_WRITE, +PANEL_YES, +PANEL_NO, +PANEL_CONFIRM, +PANEL_DELCONF, +PANEL_MENU, +PANEL_BKUP, +PANEL_INSEXIT, +PANEL_DBGLOG +}; + +enum{ +MESSAGE_VERSION, +MESSAGE_PRODUCT, +MESSAGE_PRODUCT2, +MESSAGE_ERROR_TITLE, +MESSAGE_ERROR_INFO, +MESSAGE_ERROR_INFO2, +MESSAGE_ERROR_INFO3, +MESSAGE_SUCCESS_TITLE, +MESSAGE_SUCCESS_INFO, +MESSAGE_SUCCESS_INFO2, +MESSAGE_CONFIRM_TITLE, +MESSAGE_CONFIRM_MSG, +MESSAGE_DELCONF_TITLE, +MESSAGE_DELCONF_MSG, +MESSAGE_DELCONF_MSG2, +MESSAGE_DELCONF_MSG3, +//MESSAGE_TOPMENU_HELP_TITLE, +MESSAGE_TOPMENU_HELP_READ, +MESSAGE_TOPMENU_HELP_WRITE, +MESSAGE_TOPMENU_HELP_END, +MESSAGE_TOPMENU_HELP_OPERATE, +MESSAGE_TITLE, +MESSAGE_MENU_READ, +MESSAGE_MENU_WRITE, +//MESSAGE_MENU_END, +MESSAGE_MENU_OPERATE, +MESSAGE_MENU_CAUTION, +MESSAGE_MENU_ERROR, +MESSAGE_MENU_DEBUG, +MESSAGE_INSEXT_1, +MESSAGE_INSEXT_2, +MESSAGE_INSEXT_3, +MESSAGE_OPERATE, +MESSAGE_RESULT, +MESSAGE_QUIT_OPERATE, +MESSAGE_CONF, +MESSAGE_COUNT, +MESSAGE_COUNT2, +MESSAGE_STATUS +}; + +enum{ +MEMO_DBGLOG +}; + + +//画面消去、コンポーネントをディセーブル +void ScrClr() +{ + gui.ButtonMask(0); + gui.DisableAll(); + gui.Draw(); +} + + +//---------------------------------イベントコールバック +//----------------PADボタン +void pushButton(u32 button) +{ + //NN_LOG("button > %4x\n",button); + if (button & nn::hid::BUTTON_LEFT)//同時押し + { + if (button & nn::hid::BUTTON_X) + scr_evnt = EVNT_PUSH_LEFT_X; + } +#ifdef DEBUG_ENABLE + else if (button & nn::hid::BUTTON_DOWN)//同時押し + { + if (button & nn::hid::BUTTON_Y) + if (button & nn::hid::BUTTON_X) + scr_evnt = EVNT_PUSH_DOWN_Y; + } + else if (button & nn::hid::BUTTON_R)scr_evnt = EVNT_PUSH_R; + else if (button & nn::hid::BUTTON_L)scr_evnt = EVNT_PUSH_L; +#endif +#ifdef ENABLE_CRUSH + else if (button & nn::hid::BUTTON_Y)scr_evnt = EVNT_PUSH_Y; +#endif + else if (button & nn::hid::BUTTON_B)scr_evnt = EVNT_PUSH_B; +} + +//-----------------パネルをタッチ +// ---- Top Menu :READ +void touchRead(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_SEL_READ; +} +// ---- Top Menu :WRITE +void touchWrite(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_SEL_WRITE; +} + +//---- Top Menu :END +//void touchEnd(u32 pos NN_IS_UNUSED_VAR) +//{ +// scr_evnt = EVNT_SEL_END; +//} + +//---- YES +void touchYes(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_YES; +} + +//---- NO +void touchNo(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_NO; +} + +void touchQuit(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_QUIT; +} + +#define NULL_PTR 0 +#define NULL_STR 0 +#define SCREEN_UPPER 0 +#define SCREEN_LOWER 1 +#define LOC_CONF_X 60 +#define LOC_CONF_Y 20 +#define LOC_CONF_W (400 - LOC_CONF_X*2) +#define LOC_CONF_H 70 +#define LOC_LOG_X 50 +#define LOC_LOG_W (400 - LOC_LOG_X*2) +#define LOC_LOG_Y (LOC_CONF_Y + LOC_CONF_H + 10) +#define LOC_LOG_H (240 - LOC_LOG_Y - 10) +#define LOG_MAX 10 + +// -------------------------------------------------- コンポーネント設計 +//下画面 + +//Top Menu +const tPanel panel_Read = {(uptr)touchRead,"Backup",80+20,30,160,80,PANEL_READ,SCREEN_LOWER}; +const tPanel panel_Write = {(uptr)touchWrite,"Restore",80+20,130,160,80,PANEL_WRITE,SCREEN_LOWER}; +//const tPanel panel_End = {(uptr)touchEnd,"End",80,180,160,30,PANEL_END,SCREEN_LOWER}; + +//Yes No +const tPanel panel_Yes = {(uptr)touchYes,"YES",40+10,60,80,120,PANEL_YES,SCREEN_LOWER}; +const tPanel panel_No = {(uptr)touchNo,"NO",200+30,60,80,120,PANEL_NO,SCREEN_LOWER}; + +//Quit +const tPanel panel_Quit = {(uptr)touchQuit,"Quit",80+20,60,160,120,PANEL_QUIT,SCREEN_LOWER}; + +//上画面 +//デバグ用 +//エラー表示 +const tPanel panel_Error = {NULL_PTR,NULL_STR,LOC_CONF_X,LOC_CONF_Y,LOC_CONF_W,LOC_CONF_H,PANEL_ERROR,SCREEN_UPPER}; +const tMessage mess_Title_Err = {"title",10,10,COLOR_RED,8,MESSAGE_ERROR_TITLE,PANEL_ERROR}; +const tMessage mess_Info_Err = {"info",10,22,COLOR_RED,8,MESSAGE_ERROR_INFO,PANEL_ERROR}; +const tMessage mess_Info2_Err = {"info2",10,40,COLOR_RED,8,MESSAGE_ERROR_INFO2,PANEL_ERROR}; +const tMessage mess_Info3_Err = {"info3",10,50,COLOR_RED,8,MESSAGE_ERROR_INFO3,PANEL_ERROR}; + +//成功 +const tPanel panel_Success = {NULL_PTR,NULL_STR,LOC_CONF_X,LOC_CONF_Y,LOC_CONF_W,LOC_CONF_H,PANEL_SUCCESS,SCREEN_UPPER}; +const tMessage mess_Title_Suc = {"title",10,10,COLOR_GREEN,8,MESSAGE_SUCCESS_TITLE,PANEL_SUCCESS}; +const tMessage mess_Info_Suc = {"info",10,40,COLOR_WHITE,8,MESSAGE_SUCCESS_INFO,PANEL_SUCCESS}; +const tMessage mess_Info2_Suc = {"info2",10,50,COLOR_WHITE,8,MESSAGE_SUCCESS_INFO2,PANEL_SUCCESS}; + +//実行確認 +const tPanel panel_Confirm = {NULL_PTR,NULL_STR,LOC_CONF_X,LOC_CONF_Y,LOC_CONF_W,LOC_CONF_H,PANEL_CONFIRM,SCREEN_UPPER}; +const tMessage mess_conf_Title = {"title",10,10,COLOR_YELLO,8,MESSAGE_CONFIRM_TITLE,PANEL_CONFIRM}; +const tMessage mess_conf_Msg = {"Do you execute?",10,40,COLOR_WHITE,8,MESSAGE_CONFIRM_MSG,PANEL_CONFIRM}; + +//トップメニュー +const tPanel panel_topmenu_help = {NULL_PTR,NULL_STR,LOC_CONF_X,LOC_CONF_Y,LOC_CONF_W,LOC_CONF_H,PANEL_TOPMENU,SCREEN_UPPER}; +const tMessage mess_topmenu_help_read = {"[Backup] Card -> bkup",10,4,COLOR_WHITE,8,MESSAGE_TOPMENU_HELP_READ,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_notread = {"[Backup] is Invalid",10,4,COLOR_RED,8,MESSAGE_TOPMENU_HELP_READ,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_write = {"[Restore] bkup -> Card",10,16,COLOR_WHITE,8,MESSAGE_TOPMENU_HELP_WRITE,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_notwrite = {"[Restore] is Invalid",10,16,COLOR_RED,8,MESSAGE_TOPMENU_HELP_WRITE,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_end = {"[End] return to SystemMenu",10,28,COLOR_WHITE,8,MESSAGE_TOPMENU_HELP_END,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_operate = {"touch below",10,48,COLOR_GREEN,8,MESSAGE_TOPMENU_HELP_OPERATE,PANEL_TOPMENU}; + +//ログ表示 +const tPanel panel_dbglog = {NULL_PTR,NULL_STR,LOC_LOG_X,LOC_LOG_Y,LOC_LOG_W,LOC_LOG_H,PANEL_DBGLOG,SCREEN_UPPER}; +const tMemo memo_dbglog = {LOG_MAX,10,10,COLOR_WHITE,8,MEMO_DBGLOG,PANEL_DBGLOG}; + + +//通常時 +//タイトル +#define FONT_SIZE_TITLE 12 +#define LOC_TITL_X (40-FONT_SIZE_TITLE*2) +#define LOC_TITL_Y 20 +#define LOC_TITL_W (400 - LOC_CONF_X*2) +#define LOC_TITL_H 50 +#define FONT_SIZE_PRODUCT 10 +const tPanel panel_title = {NULL_PTR,NULL_STR,LOC_TITL_X,LOC_TITL_Y,LOC_TITL_W,LOC_TITL_H,PANEL_TITLE,SCREEN_UPPER}; +const tMessage mess_title = {"title",0,0,COLOR_WHITE,FONT_SIZE_TITLE,MESSAGE_TITLE,PANEL_TITLE}; +const tMessage mess_product = {"product",0,LOC_TITL_H - 22,COLOR_WHITE,FONT_SIZE_PRODUCT,MESSAGE_PRODUCT,PANEL_TITLE}; +const tMessage mess_product2 = {"product2",0,LOC_TITL_H - 10,COLOR_WHITE,FONT_SIZE_PRODUCT,MESSAGE_PRODUCT2,PANEL_TITLE}; +const tMessage mess_version = {"version",LOC_TITL_W-FONT_SIZE_PRODUCT*6,FONT_SIZE_TITLE+2,COLOR_WHITE,FONT_SIZE_PRODUCT,MESSAGE_VERSION,PANEL_TITLE}; + +#define LOC_MESS_X 20 +#define LOC_MESS_W (400 - LOC_MESS_X*2) +#define LOC_MESS_Y (LOC_TITL_Y + LOC_TITL_H + 10) +#define LOC_MESS_H (240 - LOC_MESS_Y - 10) +//TOPメニュー +//情報表示はログと排他 +#define FONT_SIZE 10 +#define STR_LINE(ln) (FONT_SIZE + 2)*ln +const tPanel panel_menu = {NULL_PTR,NULL_STR,LOC_MESS_X,LOC_MESS_Y,LOC_MESS_W,LOC_MESS_H,PANEL_MENU,SCREEN_UPPER}; +const tMessage mess_menu_read = {"[Backup] Card savedata Backup",10,STR_LINE(1),COLOR_WHITE,FONT_SIZE,MESSAGE_MENU_READ,PANEL_MENU}; +const tMessage mess_menu_write = {"[Restore] restore to Card",10,STR_LINE(2),COLOR_WHITE,FONT_SIZE,MESSAGE_MENU_WRITE,PANEL_MENU}; +//const tMessage mess_menu_end = {"[End] close this apprication",10,STR_LINE(3),COLOR_WHITE,FONT_SIZE,MESSAGE_MENU_END,PANEL_MENU}; +const tMessage mess_menu_operate = {"touch below",10,STR_LINE(4),COLOR_GREEN,FONT_SIZE,MESSAGE_MENU_OPERATE,PANEL_MENU}; +const tMessage mess_bkuperr = {"Backup error",10,STR_LINE(6),COLOR_RED,FONT_SIZE,MESSAGE_MENU_ERROR,PANEL_MENU}; +const tMessage mess_carderr = {"CARD error",10,STR_LINE(7),COLOR_YELLO,FONT_SIZE,MESSAGE_MENU_CAUTION,PANEL_MENU}; +const tMessage mess_debug = {"Crush Mode",10,STR_LINE(3),COLOR_YELLO,FONT_SIZE,MESSAGE_MENU_DEBUG,PANEL_MENU}; + +//Backup +//const tPanel panel_bkup = {NULL_PTR,NULL_STR,LOC_LOG_X,LOC_LOG_Y,LOC_LOG_W,LOC_LOG_H,PANEL_BKUP,SCREEN_UPPER}; +const tPanel panel_bkup = {NULL_PTR,NULL_STR,LOC_MESS_X,LOC_MESS_Y,LOC_MESS_W,LOC_MESS_H,PANEL_BKUP,SCREEN_UPPER}; +const tMessage mess_quit_operate = {"touch [Quit],or Push B",10,STR_LINE(4),COLOR_SKY,FONT_SIZE,MESSAGE_QUIT_OPERATE,PANEL_BKUP}; +const tMessage mess_conf = {"Do you execute?",10,STR_LINE(2),COLOR_WHITE,FONT_SIZE,MESSAGE_CONF,PANEL_BKUP}; +const tMessage mess_result = {"result",10,STR_LINE(2),COLOR_WHITE,FONT_SIZE,MESSAGE_RESULT,PANEL_BKUP}; +const tMessage mess_operate = {"touch below",10,STR_LINE(4),COLOR_GREEN,FONT_SIZE,MESSAGE_OPERATE,PANEL_BKUP}; +const tMessage mess_status = {"status",10,STR_LINE(7),COLOR_WHITE,FONT_SIZE,MESSAGE_STATUS,PANEL_BKUP}; +const tMessage mess_count = {"count",10,STR_LINE(8),COLOR_WHITE,FONT_SIZE,MESSAGE_COUNT,PANEL_BKUP}; +const tMessage mess_count2 = {"count2",10,STR_LINE(9),COLOR_GREEN,FONT_SIZE,MESSAGE_COUNT2,PANEL_BKUP}; + + +//挿抜発生時 +//const tPanel panel_insexit = {NULL_PTR,NULL_STR,LOC_LOG_X,LOC_LOG_Y,LOC_LOG_W,LOC_LOG_H,PANEL_INSEXIT,SCREEN_UPPER}; +const tPanel panel_insexit = {NULL_PTR,NULL_STR,LOC_MESS_X,LOC_MESS_Y,LOC_MESS_W,LOC_MESS_H,PANEL_INSEXIT,SCREEN_UPPER}; +const tMessage mess_insexit = {"device insert or pull out is detected",10,STR_LINE(3),COLOR_RED,8,MESSAGE_INSEXT_1,PANEL_INSEXIT}; +const tMessage mess_insexit2 = {"return to top menu",10,STR_LINE(5),COLOR_WHITE,8,MESSAGE_INSEXT_2,PANEL_INSEXIT}; +const tMessage mess_insexit3 = {"please touch or push B",10,STR_LINE(6),COLOR_WHITE,8,MESSAGE_INSEXT_3,PANEL_INSEXIT}; + +//削除確認 +//const tPanel panel_delconf = {NULL_PTR,NULL_STR,LOC_CONF_X-10,LOC_CONF_Y,LOC_CONF_W+10,LOC_CONF_H*2,PANEL_DELCONF,SCREEN_UPPER}; +const tPanel panel_delconf = {NULL_PTR,NULL_STR,LOC_MESS_X,LOC_MESS_Y-36,LOC_MESS_W,LOC_MESS_H,PANEL_DELCONF,SCREEN_UPPER}; +const tMessage mess_delconf_Title = {" *** DELETE *** ",10,10,COLOR_YELLO,16,MESSAGE_DELCONF_TITLE,PANEL_DELCONF}; +const tMessage mess_delconf_Msg = {" caution!",10,50,COLOR_YELLO,12,MESSAGE_DELCONF_MSG,PANEL_DELCONF}; +const tMessage mess_delconf_Msg2 = {"this is delete backup",10,70,COLOR_YELLO,12,MESSAGE_DELCONF_MSG2,PANEL_DELCONF}; +const tMessage mess_delconf_Msg3 = {"Do you execute?",10,90,COLOR_YELLO,12,MESSAGE_DELCONF_MSG3,PANEL_DELCONF}; + + + +nn::os::LightEvent stopEvnt(true); + +char scr_ver[16]; +char scr_err[32]; +char scr_debug[32]; +//menu +bool ScrInitialize(uptr heap,u32 size) +{ + scr_evnt = EVNT_NONE; + + if (gui.Initialize(heap,size,&stopEvnt)==false)return false; + + + gui.ButtonCallback((uptr)pushButton); + //コンポーネント登録 + gui.PanelSet(&panel_Read); + gui.PanelSet(&panel_Write); +// gui.PanelSet(&panel_End); + gui.PanelSet(&panel_Yes); + gui.PanelSet(&panel_No); + gui.PanelSet(&panel_Quit); + gui.PanelSet(&panel_Error); + gui.PanelSet(&panel_Success); + gui.PanelSet(&panel_Confirm); + gui.PanelSet(&panel_delconf); + gui.PanelSet(&panel_topmenu_help); + gui.PanelSet(&panel_title); + gui.PanelSet(&panel_menu); + gui.PanelSet(&panel_bkup); + gui.PanelSet(&panel_dbglog); + gui.PanelSet(&panel_insexit); + + gui.PanelLineStyle(PANEL_TITLE,COLOR_BLACK); + + + gui.MessSet(&mess_Title_Err); + gui.MessSet(&mess_Info_Err); + gui.MessSet(&mess_Info2_Err); + gui.MessSet(&mess_Info3_Err); + gui.MessSet(&mess_Title_Suc); + gui.MessSet(&mess_Info_Suc); + gui.MessSet(&mess_Info2_Suc); + gui.MessSet(&mess_conf_Title); + gui.MessSet(&mess_conf_Msg); + gui.MessSet(&mess_delconf_Title); + gui.MessSet(&mess_delconf_Msg); + gui.MessSet(&mess_delconf_Msg2); + gui.MessSet(&mess_delconf_Msg3); + + gui.MessSet(&mess_topmenu_help_read); + gui.MessSet(&mess_topmenu_help_write); + gui.MessSet(&mess_topmenu_help_end); + gui.MessSet(&mess_topmenu_help_operate); + + gui.MessSet(&mess_title); + gui.MessSet(&mess_version); + gui.MessSet(&mess_product); + gui.MessSet(&mess_product2); + gui.MessSet(&mess_menu_read); + gui.MessSet(&mess_menu_write); +// gui.MessSet(&mess_menu_end); + gui.MessSet(&mess_menu_operate); + gui.MessSet(&mess_quit_operate); + gui.MessSet(&mess_conf); + gui.MessSet(&mess_operate); + gui.MessSet(&mess_bkuperr); + gui.MessSet(&mess_carderr); + gui.MessSet(&mess_debug); + gui.MessSet(&mess_result); + gui.MessSet(&mess_status); + gui.MessSet(&mess_count); + gui.MessSet(&mess_count2); + + gui.MessSet(&mess_insexit); + gui.MessSet(&mess_insexit2); + gui.MessSet(&mess_insexit3); + + gui.MemoSet(&memo_dbglog); + + gui.MemoEffective(MESSAGE_PRODUCT); + gui.MessEffective(MESSAGE_ERROR_TITLE); + gui.MessEffective(MESSAGE_ERROR_INFO); + gui.MessEffective(MESSAGE_ERROR_INFO2); + gui.MessEffective(MESSAGE_ERROR_INFO3); + gui.MessEffective(MESSAGE_SUCCESS_TITLE); + gui.MessEffective(MESSAGE_SUCCESS_INFO); + gui.MessEffective(MESSAGE_SUCCESS_INFO2); + gui.MessEffective(MESSAGE_CONFIRM_TITLE); + gui.MessEffective(MESSAGE_CONFIRM_MSG); + gui.MessEffective(MESSAGE_DELCONF_TITLE); + gui.MessEffective(MESSAGE_DELCONF_MSG); + gui.MessEffective(MESSAGE_DELCONF_MSG2); + gui.MessEffective(MESSAGE_DELCONF_MSG3); + gui.MessEffective(MESSAGE_TOPMENU_HELP_READ); + gui.MessEffective(MESSAGE_TOPMENU_HELP_WRITE); + gui.MessEffective(MESSAGE_TOPMENU_HELP_END); + gui.MessEffective(MESSAGE_TOPMENU_HELP_OPERATE); + gui.MessEffective(MESSAGE_MENU_READ); + gui.MessEffective(MESSAGE_MENU_WRITE); +// gui.MessEffective(MESSAGE_MENU_END); + gui.MessEffective(MESSAGE_MENU_OPERATE); + gui.MessEffective(MESSAGE_INSEXT_1); + gui.MessEffective(MESSAGE_INSEXT_2); + gui.MessEffective(MESSAGE_INSEXT_3); + gui.MessEffective(MESSAGE_TITLE); + gui.MessEffective(MESSAGE_VERSION); + gui.MemoEffective(MEMO_DBGLOG); + + gui.PanelLineStyle(PANEL_DELCONF,COLOR_YELLO); + + sprintf(scr_ver,"ver %.2f",VERSION); + gui.MessStr(MESSAGE_VERSION,scr_ver); + gui.MessStr(MESSAGE_MENU_CAUTION,scr_err); + gui.MessStr(MESSAGE_MENU_ERROR,scr_err); + gui.MessStr(MESSAGE_MENU_DEBUG,scr_debug); + + return true; + +} + +void ScrFinalize() +{ + stopEvnt.Signal(); + while(stopEvnt.TryWait()){ + nn::os::Thread::Yield(); + + }; + gui.Finalize(); +} + +//YES-NO ボタン +void YesNo() +{ + gui.ButtonMask(nn::hid::BUTTON_A | nn::hid::BUTTON_B); + gui.PanelEffective(PANEL_YES); + gui.PanelEffective(PANEL_NO); + gui.Draw(); +} + +void Quit() +{ + gui.ButtonMask(nn::hid::BUTTON_A | nn::hid::BUTTON_B); + gui.PanelEffective(PANEL_QUIT); + gui.Draw(); +} + + +//トップメニュー画面 +//引数:カード状態 +void scr_TopMenuDbg(bool formatted,bool insertted)//デバッグ用 +{ + scr_evnt = EVNT_NONE; + gui.ButtonMask(nn::hid::BUTTON_A | nn::hid::BUTTON_R | nn::hid::BUTTON_L); + + if (formatted) + {//リード可能 + gui.MessSet(&mess_topmenu_help_read); + gui.PanelEffective(PANEL_READ); + }else{//リード不可 + gui.MessSet(&mess_topmenu_help_notread); + gui.PanelEffective(PANEL_READ,false); + } + if (insertted) + {//書き込み可 + gui.MessSet(&mess_topmenu_help_write); + gui.PanelEffective(PANEL_WRITE); + }else{//書き込み不可 + gui.MessSet(&mess_topmenu_help_notwrite); + gui.PanelEffective(PANEL_WRITE,false); + } + + gui.MessEffective(MESSAGE_TOPMENU_HELP_READ); + gui.MessEffective(MESSAGE_TOPMENU_HELP_WRITE); +// gui.PanelEffective(PANEL_END); + gui.PanelEffective(PANEL_TOPMENU); + gui.Draw(); +} + +//通常時 + +//プロダクトコード +//引数:カード、拡張セーブに記録されたもの +char scr_pcode[32]; +void scr_PrdCode(char *s) +{ + strcpy(scr_pcode,"CARD : "); + if (s[0]==0) strcat(scr_pcode,"----"); + else strcat(scr_pcode,s); + gui.MessStr(MESSAGE_PRODUCT,scr_pcode); +} + +char scr_pcode2[64]; +void scr_PrdCodeEx(char *s) +{ + strcpy(scr_pcode2,"BKUP : "); + if (s[0]==0) strcat(scr_pcode2,"----"); + else strcat(scr_pcode2,s); + gui.MessStr(MESSAGE_PRODUCT2,scr_pcode2); +} + +//削除の実行確認 +void scr_DelConf() +{ + scr_evnt = EVNT_NONE; + gui.PanelEffective(PANEL_DELCONF); + YesNo(); +} + + +//Top menu +//引数:デバイス状態 +//arg : プロダクトコード一致 +void scr_TopMenu(bool formatted,bool inserted,bool exfm,bool bkupins,int err) +{ + + int i; + scr_evnt = EVNT_NONE; + + u32 mask = 0; +#ifdef DEBUG_ENABLE + mask | = ( nn::hid::BUTTON_DOWN | nn::hid::BUTTON_Y |nn::hid::BUTTON_X|nn::hid::BUTTON_L | nn::hid::BUTTON_R); +#endif +#ifdef CRUSH_ENABLE + extern bool CrashForDebug; + mask | = nn::hid::BUTTON_Y; + if (CrashForDebug==0) gui.MessEffective(MESSAGE_MENU_DEBUG,false,false); + else{ + sprintf(scr_debug,"Crush mode %d",CrashForDebug); + gui.MessEffective(MESSAGE_MENU_DEBUG); + } +#endif + + gui.MessStr(MESSAGE_TITLE," < CTR Card Savedata Mover >"); + + gui.MessEffective(MESSAGE_MENU_ERROR,false,false); + gui.MessEffective(MESSAGE_MENU_CAUTION,false,false); + gui.MessEffective(MESSAGE_MENU_OPERATE,false,false); + //片方のみ有効 + if (formatted && bkupins && (exfm == false)) + {//バックアップ + gui.MessEffective(MESSAGE_MENU_OPERATE); + gui.PanelEffective(PANEL_READ); + gui.PanelEffective(PANEL_WRITE,false,false); + }else if (exfm && inserted) + {//リストア + mask |= (nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X);//LEFT+X = Delete 有効 + gui.PanelEffective(PANEL_READ,false,false); + i =0; + if (err & SDATA_ERRPUT_MEDIA) i = ERC_MEDIA + ERC_DEV_CARD;//バックアップがない + else + if (err & SDATA_ERRPUT_PCODE) i = ERC_DEV_OTHER + ERC_PRODCODE;//プロダクトコード不一致 + if (i !=0 ) + { + gui.PanelEffective(PANEL_WRITE,false,false); + sprintf(scr_err,"ERROR %d",i); + gui.MessEffective(MESSAGE_MENU_ERROR); + } + else{ + gui.MessEffective(MESSAGE_MENU_OPERATE); + gui.PanelEffective(PANEL_WRITE); + } + }else{//なし + gui.PanelEffective(PANEL_WRITE,false,false); + gui.PanelEffective(PANEL_READ,false,false); + + if (inserted == false) + { + strcpy(scr_err,"Please Insert Card"); + gui.MessEffective(MESSAGE_MENU_CAUTION); + + }else{ + if (err & SDATA_ERRPUT_MEDIA) i = ERC_MEDIA + ERC_DEV_CARD;//バックアップがない + else + if (err & SDATA_ERRPUT_VERIFI) i = ERC_SDK_VERIFI + ERC_DEV_CARD;//データが壊れている + else if (bkupins == false) i = ERC_DEVICE + ERC_DEV_OUT;//書出し先デバイスが無い + else i = ERC_FORMAT + ERC_DEV_CARD;//フォーマットエラー + sprintf(scr_err,"ERROR %d",i); + gui.MessEffective(MESSAGE_MENU_ERROR); + } + } + + gui.ButtonMask(mask); + + gui.MessEffective(MESSAGE_PRODUCT); + gui.MessEffective(MESSAGE_PRODUCT2); + + gui.PanelEffective(PANEL_TITLE); + gui.PanelEffective(PANEL_MENU); + + gui.Draw(); +} + +//デバッグ用、ボタン待ち +void ScrStep() +{ + scr_evnt = EVNT_NONE; + gui.ButtonMask(nn::hid::BUTTON_B); +} + + +void ClearBkupMess() +{ + gui.MessEffective(MESSAGE_CONF,false,false); + gui.MessEffective(MESSAGE_RESULT,false,false); + gui.MessEffective(MESSAGE_OPERATE,false,false); + gui.MessEffective(MESSAGE_QUIT_OPERATE,false,false); + gui.MessEffective(MESSAGE_STATUS,false,false); + gui.MessEffective(MESSAGE_COUNT,false,false); + gui.MessEffective(MESSAGE_COUNT2,false,false); + gui.PanelEffective(PANEL_BKUP); +} + +//Backup +void scr_Backup() +{ + scr_evnt = EVNT_NONE; + gui.PanelLineStyle(PANEL_BKUP,COLOR_SKY); + gui.MessStr(MESSAGE_TITLE," --- Backup Card Savedata ---"); + gui.PanelEffective(PANEL_TITLE); + ClearBkupMess(); + gui.Draw(); + +} +void scr_BackupYesNo() +{ + scr_Backup(); + gui.MessEffective(MESSAGE_CONF); + gui.MessEffective(MESSAGE_OPERATE); + YesNo(); +} + +//restore +void scr_Restore() +{ + scr_evnt = EVNT_NONE; + gui.PanelLineStyle(PANEL_BKUP,COLOR_PARPL); + gui.MessStr(MESSAGE_TITLE,"--- Restore Card Savedata ---"); + gui.PanelEffective(PANEL_TITLE); + ClearBkupMess();//backupと同じパネルを使う + gui.Draw(); + +} +void scr_RestoreYesNo() +{ + scr_Restore(); + gui.MessEffective(MESSAGE_CONF); + gui.MessEffective(MESSAGE_OPERATE); + YesNo(); +} + + +void scr_Status(char *s,eColor col) +{ + gui.MessCol(MESSAGE_STATUS,col); + gui.MessStr(MESSAGE_STATUS,s); + gui.MessEffective(MESSAGE_STATUS); + gui.Draw(); +} + +void scr_ResultQuit(char *s,eColor col) +{ + gui.MessCol(MESSAGE_RESULT,col); + gui.MessStr(MESSAGE_RESULT,s); + gui.MessEffective(MESSAGE_RESULT); + gui.MessEffective(MESSAGE_QUIT_OPERATE); + Quit(); +} + + +void scr_InsExitQuit() +{ + ClearBkupMess(); + gui.PanelLineStyle(PANEL_INSEXIT,COLOR_RED); + gui.PanelEffective(PANEL_INSEXIT); + Quit(); +} + +// カウント/MAX 表示 +char str_Counter[128]; +char str_Counter2[128]; +void scr_CountPerMax(int ct,int max) +{ + sprintf(str_Counter,"%d / %d",ct,max); + gui.MessStr(MESSAGE_COUNT,str_Counter); + gui.MessEffective(MESSAGE_COUNT); + gui.Draw(); +} + +//ゲージ&total +void scr_CountPerMax2(int ct,int max,int total) +{ + if (total == -1) str_Counter2[0]=0; + else if (total != 0){ +// gui.MessCol(MESSAGE_COUNT2,COLOR_WHITE); + sprintf(str_Counter2,"total size %d",total); + }else{ +// gui.MessCol(MESSAGE_COUNT2,COLOR_YELLO); + int i; + int lv = ct/(max/25); + for (i =0;i'; + while ( i < 25 )str_Counter2[i++] = '|'; + str_Counter2[i] = 0; + } + //sprintf(str_Counter2,"%d / %d",ct,max); + gui.MessStr(MESSAGE_COUNT2,str_Counter2); + gui.MessEffective(MESSAGE_COUNT2); + gui.Draw(); + +} + +void scr_MessOnCount2(char *str) +{ +// gui.MessCol(MESSAGE_COUNT2,COLOR_YELLO); + gui.MessStr(MESSAGE_COUNT2,str); + gui.MessEffective(MESSAGE_COUNT2); + gui.Draw(); +} + + +//実行確認 +void scr_ConfirmDbg(char *str) +{ + scr_evnt = EVNT_NONE; + gui.MessStr(MESSAGE_CONFIRM_TITLE,str); + gui.PanelEffective(PANEL_CONFIRM); + YesNo(); +} + + +//エラー表示とQuitボタン +void scr_ErrorQuitDbg(tColStr **s) +{ + scr_evnt = EVNT_NONE; + gui.MessStr(MESSAGE_ERROR_TITLE,s[0]->str); + gui.MessCol(MESSAGE_ERROR_TITLE,s[0]->color); + gui.MessStr(MESSAGE_ERROR_INFO,s[1]->str); + gui.MessCol(MESSAGE_ERROR_INFO,s[1]->color); + gui.MessStr(MESSAGE_ERROR_INFO2,s[2]->str); + gui.MessCol(MESSAGE_ERROR_INFO2,s[2]->color); + gui.MessStr(MESSAGE_ERROR_INFO3,s[3]->str); + gui.MessCol(MESSAGE_ERROR_INFO3,s[3]->color); + gui.PanelEffective(PANEL_ERROR); + Quit(); +} + +//成功表示とQuitボタン +void scr_SuccessQuitDbg(tColStr **s) +{ + scr_evnt = EVNT_NONE; + gui.MessStr(MESSAGE_SUCCESS_TITLE,s[0]->str); + gui.MessCol(MESSAGE_SUCCESS_TITLE,s[0]->color); + gui.MessStr(MESSAGE_SUCCESS_INFO,s[1]->str); + gui.MessCol(MESSAGE_SUCCESS_INFO,s[1]->color); + gui.MessStr(MESSAGE_SUCCESS_INFO2,s[2]->str); + gui.MessCol(MESSAGE_SUCCESS_INFO2,s[2]->color); + gui.PanelEffective(PANEL_SUCCESS); + Quit(); +} + + +//デバッグログ +void scr_DgbLog(cStrLst *p) +{ + gui.PanelLineStyle(PANEL_DBGLOG,COLOR_BLUE); + + for (int i=0;igetpos()+1;i++)gui.MemoStr(MEMO_DBGLOG,p->line(i),i); + + gui.PanelEffective(PANEL_DBGLOG); + gui.Draw(); +} + + + +int ScrDbgLogGetMax() +{ + return LOG_MAX; +} + + +void scr_Draw() +{ + gui.Draw(); +} + +void scr_GetEvnt() +{ +// gui.thUpdate(); +} + + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/screen/screen.h b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/screen/screen.h new file mode 100644 index 0000000..4ecc79e --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/screen/screen.h @@ -0,0 +1,115 @@ +#ifndef SCREEN_H_ +#define SCREEN_H_ + +#include +#include +#include "../gui/gui.h" + +//パネルのID +enum { + EVNT_NONE, + EVNT_YES, + EVNT_NO, + EVNT_QUIT, + EVNT_PUSH_A, + EVNT_PUSH_B, + EVNT_PUSH_R, + EVNT_PUSH_L, + EVNT_PUSH_X, + EVNT_PUSH_Y, + EVNT_PUSH_LEFT_X, + EVNT_PUSH_DOWN_Y, + EVNT_SEL_READ, + EVNT_SEL_WRITE, + EVNT_SEL_END, + EVNT_ERROR, + EVNT_FATAL +}; + +typedef struct{ + char *str; + eColor color; + u8 pad[3]; +}tColStr; + + +#define LST_MAX 30 +#define LST_LENGTH 128 +class cStrLst { +private: + int pos; + int buttom; + char str[LST_MAX][LST_LENGTH]; +public: + cStrLst():pos(0){}; + void add(char *p){ + if (pos>=LST_MAX)return; + //char *s = &str[pos][0]; + int i; + if (pos == buttom) + { + i =0; + while(i < buttom){ strcpy(str[i],str[i+1]);i++;} + }else pos++; + i=0; + while(i < (LST_LENGTH-1)){ //オーバーロード対策 + if (p[i]!=0){ + str[pos][i] = p[i]; + i++; + }else break; + } + str[pos][i] = 0; + //strcpy(str[pos],p); + //for (i =0;i=LST_MAX))return false; + buttom = btm; + return true; + } +}; + + +//Topメニューでのエラー表示用のフラグ +//bitチェック +#define SDATA_ERRPUT_PCODE 1 +#define SDATA_ERRPUT_MEDIA 2 +#define SDATA_ERRPUT_VERIFI 4 + + +bool ScrInitialize(uptr heap,u32 size); +void ScrFinalize(); +void ScrClr(); +int ScrDbgLogGetMax(); +void ScrStep(); +void scr_TopMenuDbg(bool formatted,bool insertted); +void scr_TopMenu(bool formatted,bool inserted,bool exfm,bool sdins,int err); +void scr_ErrorQuitDbg(tColStr **s); +void scr_SuccessQuitDbg(tColStr **s); +void scr_ConfirmDbg(char *str); +void scr_DgbLog(cStrLst *p); +void scr_BackupYesNo(); +void scr_Backup(); +void scr_RestoreYesNo(); +void scr_Restore(); +void scr_InsExitQuit(); +void scr_Status(char *s,eColor col); +void scr_ResultQuit(char *s,eColor col); +void scr_CountPerMax(int ct,int max); +void scr_CountPerMax2(int ct,int max,int total); +void scr_PrdCode(char *s); +void scr_PrdCodeEx(char *s); +void scr_DelConf(); +void scr_MessOnCount2(char *str); +void scr_Draw(); +void scr_GetEvnt(); + +#endif + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/screen/screen_0.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/screen/screen_0.cpp new file mode 100644 index 0000000..cedc552 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/body/source/screen/screen_0.cpp @@ -0,0 +1,791 @@ +#include +#include "screen.h" +#include +#include "../my_defs.h" +#include "../common/ver.h" + +//todo: 初期仕様の名残の"SD"が関数や変数名 +// に残ってるので気になるなら掃除 + +Gui gui; +u8 scr_evnt; + +enum{ +//PANEL_END, +PANEL_ERROR, +PANEL_SUCCESS, +PANEL_TOPMENU, +PANEL_TITLE, +PANEL_QUIT, +PANEL_READ, +PANEL_WRITE, +PANEL_YES, +PANEL_NO, +PANEL_CONFIRM, +PANEL_DELCONF, +PANEL_MENU, +PANEL_BKUP, +PANEL_INSEXIT, +PANEL_DBGLOG +}; + +enum{ +MESSAGE_VERSION, +MESSAGE_PRODUCT, +MESSAGE_PRODUCT2, +MESSAGE_ERROR_TITLE, +MESSAGE_ERROR_INFO, +MESSAGE_ERROR_INFO2, +MESSAGE_ERROR_INFO3, +MESSAGE_SUCCESS_TITLE, +MESSAGE_SUCCESS_INFO, +MESSAGE_SUCCESS_INFO2, +MESSAGE_CONFIRM_TITLE, +MESSAGE_CONFIRM_MSG, +MESSAGE_DELCONF_TITLE, +MESSAGE_DELCONF_MSG, +MESSAGE_DELCONF_MSG2, +MESSAGE_DELCONF_MSG3, +//MESSAGE_TOPMENU_HELP_TITLE, +MESSAGE_TOPMENU_HELP_READ, +MESSAGE_TOPMENU_HELP_WRITE, +MESSAGE_TOPMENU_HELP_END, +MESSAGE_TOPMENU_HELP_OPERATE, +MESSAGE_TITLE, +MESSAGE_MENU_READ, +MESSAGE_MENU_WRITE, +//MESSAGE_MENU_END, +MESSAGE_MENU_OPERATE, +MESSAGE_MENU_CAUTION, +MESSAGE_MENU_ERROR, +MESSAGE_MENU_DEBUG, +MESSAGE_INSEXT_1, +MESSAGE_INSEXT_2, +MESSAGE_INSEXT_3, +MESSAGE_OPERATE, +MESSAGE_RESULT, +MESSAGE_QUIT_OPERATE, +MESSAGE_CONF, +MESSAGE_COUNT, +MESSAGE_COUNT2, +MESSAGE_STATUS +}; + +enum{ +MEMO_DBGLOG +}; + + +//画面消去、コンポーネントをディセーブル +void ScrClr() +{ + gui.ButtonMask(0); + gui.DisableAll(); + gui.Draw(); +} + + +//---------------------------------イベントコールバック +//----------------PADボタン +void pushButton(u32 button) +{ + //NN_LOG("button > %4x\n",button); + if (button & nn::hid::BUTTON_LEFT)//同時押し + { + if (button & nn::hid::BUTTON_X) + scr_evnt = EVNT_PUSH_LEFT_X; + } +#ifdef DEBUG_ENABLE + else if (button & nn::hid::BUTTON_DOWN)//同時押し + { + if (button & nn::hid::BUTTON_Y) + if (button & nn::hid::BUTTON_X) + scr_evnt = EVNT_PUSH_DOWN_Y; + } + else if (button & nn::hid::BUTTON_R)scr_evnt = EVNT_PUSH_R; + else if (button & nn::hid::BUTTON_L)scr_evnt = EVNT_PUSH_L; +#endif +#ifdef ENABLE_CRUSH + else if (button & nn::hid::BUTTON_Y)scr_evnt = EVNT_PUSH_Y; +#endif + else if (button & nn::hid::BUTTON_B)scr_evnt = EVNT_PUSH_B; +} + +//-----------------パネルをタッチ +// ---- Top Menu :READ +void touchRead(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_SEL_READ; +} +// ---- Top Menu :WRITE +void touchWrite(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_SEL_WRITE; +} + +//---- Top Menu :END +//void touchEnd(u32 pos NN_IS_UNUSED_VAR) +//{ +// scr_evnt = EVNT_SEL_END; +//} + +//---- YES +void touchYes(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_YES; +} + +//---- NO +void touchNo(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_NO; +} + +void touchQuit(u32 pos NN_IS_UNUSED_VAR) +{ + scr_evnt = EVNT_QUIT; +} + +#define NULL_PTR 0 +#define NULL_STR 0 +#define SCREEN_UPPER 0 +#define SCREEN_LOWER 1 +#define LOC_CONF_X 60 +#define LOC_CONF_Y 20 +#define LOC_CONF_W (400 - LOC_CONF_X*2) +#define LOC_CONF_H 70 +#define LOC_LOG_X 50 +#define LOC_LOG_W (400 - LOC_LOG_X*2) +#define LOC_LOG_Y (LOC_CONF_Y + LOC_CONF_H + 10) +#define LOC_LOG_H (240 - LOC_LOG_Y - 10) +#define LOG_MAX 10 + +// -------------------------------------------------- コンポーネント設計 +//下画面 + +//Top Menu +const tPanel panel_Read = {(uptr)touchRead,"Backup",80,30,160,60,PANEL_READ,SCREEN_LOWER}; +const tPanel panel_Write = {(uptr)touchWrite,"Restore",80,150,160,60,PANEL_WRITE,SCREEN_LOWER}; +//const tPanel panel_End = {(uptr)touchEnd,"End",80,180,160,30,PANEL_END,SCREEN_LOWER}; + +//Yes No +const tPanel panel_Yes = {(uptr)touchYes,"YES",40,60,80,120,PANEL_YES,SCREEN_LOWER}; +const tPanel panel_No = {(uptr)touchNo,"NO",200,60,80,120,PANEL_NO,SCREEN_LOWER}; + +//Quit +const tPanel panel_Quit = {(uptr)touchQuit,"Quit",80,60,160,120,PANEL_QUIT,SCREEN_LOWER}; + +//上画面 +//デバグ用 +//エラー表示 +const tPanel panel_Error = {NULL_PTR,NULL_STR,LOC_CONF_X,LOC_CONF_Y,LOC_CONF_W,LOC_CONF_H,PANEL_ERROR,SCREEN_UPPER}; +const tMessage mess_Title_Err = {"title",10,10,COLOR_RED,8,MESSAGE_ERROR_TITLE,PANEL_ERROR}; +const tMessage mess_Info_Err = {"info",10,22,COLOR_RED,8,MESSAGE_ERROR_INFO,PANEL_ERROR}; +const tMessage mess_Info2_Err = {"info2",10,40,COLOR_RED,8,MESSAGE_ERROR_INFO2,PANEL_ERROR}; +const tMessage mess_Info3_Err = {"info3",10,50,COLOR_RED,8,MESSAGE_ERROR_INFO3,PANEL_ERROR}; + +//成功 +const tPanel panel_Success = {NULL_PTR,NULL_STR,LOC_CONF_X,LOC_CONF_Y,LOC_CONF_W,LOC_CONF_H,PANEL_SUCCESS,SCREEN_UPPER}; +const tMessage mess_Title_Suc = {"title",10,10,COLOR_GREEN,8,MESSAGE_SUCCESS_TITLE,PANEL_SUCCESS}; +const tMessage mess_Info_Suc = {"info",10,40,COLOR_WHITE,8,MESSAGE_SUCCESS_INFO,PANEL_SUCCESS}; +const tMessage mess_Info2_Suc = {"info2",10,50,COLOR_WHITE,8,MESSAGE_SUCCESS_INFO2,PANEL_SUCCESS}; + +//実行確認 +const tPanel panel_Confirm = {NULL_PTR,NULL_STR,LOC_CONF_X,LOC_CONF_Y,LOC_CONF_W,LOC_CONF_H,PANEL_CONFIRM,SCREEN_UPPER}; +const tMessage mess_conf_Title = {"title",10,10,COLOR_YELLO,8,MESSAGE_CONFIRM_TITLE,PANEL_CONFIRM}; +const tMessage mess_conf_Msg = {"Do you execute?",10,40,COLOR_WHITE,8,MESSAGE_CONFIRM_MSG,PANEL_CONFIRM}; + +//トップメニュー +const tPanel panel_topmenu_help = {NULL_PTR,NULL_STR,LOC_CONF_X,LOC_CONF_Y,LOC_CONF_W,LOC_CONF_H,PANEL_TOPMENU,SCREEN_UPPER}; +const tMessage mess_topmenu_help_read = {"[Backup] Card -> bkup",10,4,COLOR_WHITE,8,MESSAGE_TOPMENU_HELP_READ,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_notread = {"[Backup] is Invalid",10,4,COLOR_RED,8,MESSAGE_TOPMENU_HELP_READ,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_write = {"[Restore] bkup -> Card",10,16,COLOR_WHITE,8,MESSAGE_TOPMENU_HELP_WRITE,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_notwrite = {"[Restore] is Invalid",10,16,COLOR_RED,8,MESSAGE_TOPMENU_HELP_WRITE,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_end = {"[End] return to SystemMenu",10,28,COLOR_WHITE,8,MESSAGE_TOPMENU_HELP_END,PANEL_TOPMENU}; +const tMessage mess_topmenu_help_operate = {"touch below",10,48,COLOR_GREEN,8,MESSAGE_TOPMENU_HELP_OPERATE,PANEL_TOPMENU}; + +//ログ表示 +const tPanel panel_dbglog = {NULL_PTR,NULL_STR,LOC_LOG_X,LOC_LOG_Y,LOC_LOG_W,LOC_LOG_H,PANEL_DBGLOG,SCREEN_UPPER}; +const tMemo memo_dbglog = {LOG_MAX,10,10,COLOR_WHITE,8,MEMO_DBGLOG,PANEL_DBGLOG}; + + +//通常時 +//タイトル +#define FONT_SIZE_TITLE 12 +#define LOC_TITL_X (40-FONT_SIZE_TITLE*2) +#define LOC_TITL_Y 20 +#define LOC_TITL_W (400 - LOC_CONF_X*2) +#define LOC_TITL_H 50 +#define FONT_SIZE_PRODUCT 10 +const tPanel panel_title = {NULL_PTR,NULL_STR,LOC_TITL_X,LOC_TITL_Y,LOC_TITL_W,LOC_TITL_H,PANEL_TITLE,SCREEN_UPPER}; +const tMessage mess_title = {"title",0,0,COLOR_WHITE,FONT_SIZE_TITLE,MESSAGE_TITLE,PANEL_TITLE}; +const tMessage mess_product = {"product",0,LOC_TITL_H - 20,COLOR_WHITE,FONT_SIZE_PRODUCT,MESSAGE_PRODUCT,PANEL_TITLE}; +const tMessage mess_product2 = {"product2",0,LOC_TITL_H - 10,COLOR_WHITE,FONT_SIZE_PRODUCT,MESSAGE_PRODUCT2,PANEL_TITLE}; +const tMessage mess_version = {"version",LOC_TITL_W-FONT_SIZE_PRODUCT*6,FONT_SIZE_TITLE+2,COLOR_WHITE,FONT_SIZE_PRODUCT,MESSAGE_VERSION,PANEL_TITLE}; + +#define LOC_MESS_X 20 +#define LOC_MESS_W (400 - LOC_MESS_X*2) +#define LOC_MESS_Y (LOC_TITL_Y + LOC_TITL_H + 10) +#define LOC_MESS_H (240 - LOC_MESS_Y - 10) +//TOPメニュー +//情報表示はログと排他 +#define FONT_SIZE 10 +#define STR_LINE(ln) (FONT_SIZE + 2)*ln +const tPanel panel_menu = {NULL_PTR,NULL_STR,LOC_MESS_X,LOC_MESS_Y,LOC_MESS_W,LOC_MESS_H,PANEL_MENU,SCREEN_UPPER}; +const tMessage mess_menu_read = {"[Backup] Card savedata Backup",10,STR_LINE(1),COLOR_WHITE,FONT_SIZE,MESSAGE_MENU_READ,PANEL_MENU}; +const tMessage mess_menu_write = {"[Restore] restore to Card",10,STR_LINE(2),COLOR_WHITE,FONT_SIZE,MESSAGE_MENU_WRITE,PANEL_MENU}; +//const tMessage mess_menu_end = {"[End] close this apprication",10,STR_LINE(3),COLOR_WHITE,FONT_SIZE,MESSAGE_MENU_END,PANEL_MENU}; +const tMessage mess_menu_operate = {"touch below",10,STR_LINE(4),COLOR_GREEN,FONT_SIZE,MESSAGE_MENU_OPERATE,PANEL_MENU}; +const tMessage mess_sderr = {"Backup error",10,STR_LINE(6),COLOR_RED,FONT_SIZE,MESSAGE_MENU_ERROR,PANEL_MENU}; +const tMessage mess_carderr = {"CARD error",10,STR_LINE(7),COLOR_YELLO,FONT_SIZE,MESSAGE_MENU_CAUTION,PANEL_MENU}; +const tMessage mess_debug = {"Crush Mode",10,STR_LINE(3),COLOR_YELLO,FONT_SIZE,MESSAGE_MENU_DEBUG,PANEL_MENU}; + +//Backup +const tPanel panel_bkup = {NULL_PTR,NULL_STR,LOC_LOG_X,LOC_LOG_Y,LOC_LOG_W,LOC_LOG_H,PANEL_BKUP,SCREEN_UPPER}; +const tMessage mess_quit_operate = {"touch [Quit],or Push B",10,STR_LINE(4),COLOR_SKY,FONT_SIZE,MESSAGE_QUIT_OPERATE,PANEL_BKUP}; +const tMessage mess_conf = {"Do you execute?",10,STR_LINE(2),COLOR_WHITE,FONT_SIZE,MESSAGE_CONF,PANEL_BKUP}; +const tMessage mess_result = {"result",10,STR_LINE(2),COLOR_WHITE,FONT_SIZE,MESSAGE_RESULT,PANEL_BKUP}; +const tMessage mess_operate = {"touch below",10,STR_LINE(4),COLOR_GREEN,FONT_SIZE,MESSAGE_OPERATE,PANEL_BKUP}; +const tMessage mess_status = {"status",10,STR_LINE(7),COLOR_WHITE,FONT_SIZE,MESSAGE_STATUS,PANEL_BKUP}; +const tMessage mess_count = {"count",10,STR_LINE(8),COLOR_WHITE,FONT_SIZE,MESSAGE_COUNT,PANEL_BKUP}; +const tMessage mess_count2 = {"count2",10,STR_LINE(9),COLOR_GREEN,FONT_SIZE,MESSAGE_COUNT2,PANEL_BKUP}; + + +//挿抜発生時 +const tPanel panel_insexit = {NULL_PTR,NULL_STR,LOC_LOG_X,LOC_LOG_Y,LOC_LOG_W,LOC_LOG_H,PANEL_INSEXIT,SCREEN_UPPER}; +const tMessage mess_insexit = {"device insert or pull out is detected",10,STR_LINE(3),COLOR_RED,8,MESSAGE_INSEXT_1,PANEL_INSEXIT}; +const tMessage mess_insexit2 = {"return to top menu",10,STR_LINE(5),COLOR_WHITE,8,MESSAGE_INSEXT_2,PANEL_INSEXIT}; +const tMessage mess_insexit3 = {"please touch or push B",10,STR_LINE(6),COLOR_WHITE,8,MESSAGE_INSEXT_3,PANEL_INSEXIT}; + +//削除確認 +const tPanel panel_delconf = {NULL_PTR,NULL_STR,LOC_CONF_X-10,LOC_CONF_Y,LOC_CONF_W+10,LOC_CONF_H*2,PANEL_DELCONF,SCREEN_UPPER}; +const tMessage mess_delconf_Title = {" *** DELETE *** ",10,10,COLOR_YELLO,16,MESSAGE_DELCONF_TITLE,PANEL_DELCONF}; +const tMessage mess_delconf_Msg = {" caution!",10,50,COLOR_YELLO,12,MESSAGE_DELCONF_MSG,PANEL_DELCONF}; +const tMessage mess_delconf_Msg2 = {"this is delete backup",10,70,COLOR_YELLO,12,MESSAGE_DELCONF_MSG2,PANEL_DELCONF}; +const tMessage mess_delconf_Msg3 = {"Do you execute?",10,90,COLOR_YELLO,12,MESSAGE_DELCONF_MSG3,PANEL_DELCONF}; + + + +nn::os::LightEvent stopEvnt(true); + +char scr_ver[16]; +char scr_err[32]; +char scr_debug[32]; +//menu +bool ScrInitialize(uptr heap,u32 size) +{ + scr_evnt = EVNT_NONE; + + if (gui.Initialize(heap,size,&stopEvnt)==false)return false; + + + gui.ButtonCallback((uptr)pushButton); + //コンポーネント登録 + gui.PanelSet(&panel_Read); + gui.PanelSet(&panel_Write); +// gui.PanelSet(&panel_End); + gui.PanelSet(&panel_Yes); + gui.PanelSet(&panel_No); + gui.PanelSet(&panel_Quit); + gui.PanelSet(&panel_Error); + gui.PanelSet(&panel_Success); + gui.PanelSet(&panel_Confirm); + gui.PanelSet(&panel_delconf); + gui.PanelSet(&panel_topmenu_help); + gui.PanelSet(&panel_title); + gui.PanelSet(&panel_menu); + gui.PanelSet(&panel_bkup); + gui.PanelSet(&panel_dbglog); + gui.PanelSet(&panel_insexit); + + gui.PanelLineStyle(PANEL_TITLE,COLOR_BLACK); + + + gui.MessSet(&mess_Title_Err); + gui.MessSet(&mess_Info_Err); + gui.MessSet(&mess_Info2_Err); + gui.MessSet(&mess_Info3_Err); + gui.MessSet(&mess_Title_Suc); + gui.MessSet(&mess_Info_Suc); + gui.MessSet(&mess_Info2_Suc); + gui.MessSet(&mess_conf_Title); + gui.MessSet(&mess_conf_Msg); + gui.MessSet(&mess_delconf_Title); + gui.MessSet(&mess_delconf_Msg); + gui.MessSet(&mess_delconf_Msg2); + gui.MessSet(&mess_delconf_Msg3); + + gui.MessSet(&mess_topmenu_help_read); + gui.MessSet(&mess_topmenu_help_write); + gui.MessSet(&mess_topmenu_help_end); + gui.MessSet(&mess_topmenu_help_operate); + + gui.MessSet(&mess_title); + gui.MessSet(&mess_version); + gui.MessSet(&mess_product); + gui.MessSet(&mess_product2); + gui.MessSet(&mess_menu_read); + gui.MessSet(&mess_menu_write); +// gui.MessSet(&mess_menu_end); + gui.MessSet(&mess_menu_operate); + gui.MessSet(&mess_quit_operate); + gui.MessSet(&mess_conf); + gui.MessSet(&mess_operate); + gui.MessSet(&mess_sderr); + gui.MessSet(&mess_carderr); + gui.MessSet(&mess_debug); + gui.MessSet(&mess_result); + gui.MessSet(&mess_status); + gui.MessSet(&mess_count); + gui.MessSet(&mess_count2); + + gui.MessSet(&mess_insexit); + gui.MessSet(&mess_insexit2); + gui.MessSet(&mess_insexit3); + + gui.MemoSet(&memo_dbglog); + + gui.MemoEffective(MESSAGE_PRODUCT); + gui.MessEffective(MESSAGE_ERROR_TITLE); + gui.MessEffective(MESSAGE_ERROR_INFO); + gui.MessEffective(MESSAGE_ERROR_INFO2); + gui.MessEffective(MESSAGE_ERROR_INFO3); + gui.MessEffective(MESSAGE_SUCCESS_TITLE); + gui.MessEffective(MESSAGE_SUCCESS_INFO); + gui.MessEffective(MESSAGE_SUCCESS_INFO2); + gui.MessEffective(MESSAGE_CONFIRM_TITLE); + gui.MessEffective(MESSAGE_CONFIRM_MSG); + gui.MessEffective(MESSAGE_DELCONF_TITLE); + gui.MessEffective(MESSAGE_DELCONF_MSG); + gui.MessEffective(MESSAGE_DELCONF_MSG2); + gui.MessEffective(MESSAGE_DELCONF_MSG3); + gui.MessEffective(MESSAGE_TOPMENU_HELP_READ); + gui.MessEffective(MESSAGE_TOPMENU_HELP_WRITE); + gui.MessEffective(MESSAGE_TOPMENU_HELP_END); + gui.MessEffective(MESSAGE_TOPMENU_HELP_OPERATE); + gui.MessEffective(MESSAGE_MENU_READ); + gui.MessEffective(MESSAGE_MENU_WRITE); +// gui.MessEffective(MESSAGE_MENU_END); + gui.MessEffective(MESSAGE_MENU_OPERATE); + gui.MessEffective(MESSAGE_INSEXT_1); + gui.MessEffective(MESSAGE_INSEXT_2); + gui.MessEffective(MESSAGE_INSEXT_3); + gui.MessEffective(MESSAGE_TITLE); + gui.MessEffective(MESSAGE_VERSION); + gui.MemoEffective(MEMO_DBGLOG); + + gui.PanelLineStyle(PANEL_DELCONF,COLOR_YELLO); + + sprintf(scr_ver,"ver %.2f",VERSION); + gui.MessStr(MESSAGE_VERSION,scr_ver); + gui.MessStr(MESSAGE_MENU_CAUTION,scr_err); + gui.MessStr(MESSAGE_MENU_ERROR,scr_err); + gui.MessStr(MESSAGE_MENU_DEBUG,scr_debug); + + return true; + +} + +void ScrFinalize() +{ + stopEvnt.Signal(); + while(stopEvnt.TryWait()){ + nn::os::Thread::Yield(); + + }; + gui.Finalize(); +} + +//YES-NO ボタン +void YesNo() +{ + gui.ButtonMask(nn::hid::BUTTON_A | nn::hid::BUTTON_B); + gui.PanelEffective(PANEL_YES); + gui.PanelEffective(PANEL_NO); + gui.Draw(); +} + +void Quit() +{ + gui.ButtonMask(nn::hid::BUTTON_A | nn::hid::BUTTON_B); + gui.PanelEffective(PANEL_QUIT); + gui.Draw(); +} + + +//トップメニュー画面 +//引数:カード状態 +void scr_TopMenuDbg(bool formatted,bool insertted)//デバッグ用 +{ + scr_evnt = EVNT_NONE; + gui.ButtonMask(nn::hid::BUTTON_A | nn::hid::BUTTON_R | nn::hid::BUTTON_L); + + if (formatted) + {//リード可能 + gui.MessSet(&mess_topmenu_help_read); + gui.PanelEffective(PANEL_READ); + }else{//リード不可 + gui.MessSet(&mess_topmenu_help_notread); + gui.PanelEffective(PANEL_READ,false); + } + if (insertted) + {//書き込み可 + gui.MessSet(&mess_topmenu_help_write); + gui.PanelEffective(PANEL_WRITE); + }else{//書き込み不可 + gui.MessSet(&mess_topmenu_help_notwrite); + gui.PanelEffective(PANEL_WRITE,false); + } + + gui.MessEffective(MESSAGE_TOPMENU_HELP_READ); + gui.MessEffective(MESSAGE_TOPMENU_HELP_WRITE); +// gui.PanelEffective(PANEL_END); + gui.PanelEffective(PANEL_TOPMENU); + gui.Draw(); +} + +//通常時 + +//プロダクトコード +//引数:カード、拡張セーブに記録されたもの +char scr_pcode[32]; +void scr_PrdCode(char *s) +{ + strcpy(scr_pcode,"CARD : "); + if (s[0]==0) strcat(scr_pcode,"----"); + else strcat(scr_pcode,s); + gui.MessStr(MESSAGE_PRODUCT,scr_pcode); +} + +char scr_pcode2[64]; +void scr_PrdCodeEx(char *s) +{ + strcpy(scr_pcode2,"BKUP : "); + if (s[0]==0) strcat(scr_pcode2,"----"); + else strcat(scr_pcode2,s); + gui.MessStr(MESSAGE_PRODUCT2,scr_pcode2); +} + +//削除の実行確認 +void scr_DelConf() +{ + scr_evnt = EVNT_NONE; + gui.PanelEffective(PANEL_DELCONF); + YesNo(); +} + + +//Top menu +//引数:デバイス状態 +//arg : プロダクトコード一致 +void scr_TopMenu(bool formatted,bool inserted,bool exfm,bool sdins,int err) +{ + + int i; + scr_evnt = EVNT_NONE; + //gui.ButtonMask(nn::hid::BUTTON_A | nn::hid::BUTTON_L nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X); + +#ifdef ENABLE_CRUSH + extern bool CrashForDebug; + //デバグ用 Y-> クラッシュモード,L -> デバグモード + gui.ButtonMask(nn::hid::BUTTON_Y | nn::hid::BUTTON_L | nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X); + if (CrashForDebug==0) gui.MessEffective(MESSAGE_MENU_DEBUG,false,false); + else{ + sprintf(scr_debug,"Crush mode %d",CrashForDebug); + gui.MessEffective(MESSAGE_MENU_DEBUG); + } +#else//DOWN+Y = debug + gui.ButtonMask( nn::hid::BUTTON_DOWN | nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X | nn::hid::BUTTON_Y); +#endif + + //gui.PanelLineStyle(PANEL_MENU,COLOR_WHITE); + //gui.PanelLineStyle(PANEL_TITLE,COLOR_BLACK); + gui.MessStr(MESSAGE_TITLE," < CTR Card Savedata Mover >"); + //bool flg = formatted && sdins; +// gui.PanelEffective(PANEL_READ,flg,flg);//savedata & SD exist + //bool flg2= inserted && exfm; +// gui.PanelEffective(PANEL_WRITE,flg2,flg2);//CARD & exsave exist + + gui.MessEffective(MESSAGE_MENU_ERROR,false,false); + gui.MessEffective(MESSAGE_MENU_CAUTION,false,false); + gui.MessEffective(MESSAGE_MENU_OPERATE,false,false); + //片方のみ有効 + if (formatted && sdins && (exfm == false)) + {//バックアップ + gui.MessEffective(MESSAGE_MENU_OPERATE); + gui.PanelEffective(PANEL_READ); + gui.PanelEffective(PANEL_WRITE,false,false); + }else if (exfm && inserted) + {//リストア + gui.PanelEffective(PANEL_READ,false,false); + i =0; + if (err & SDATA_ERRPUT_MEDIA) i = ERC_MEDIA + ERC_DEV_CARD;//バックアップがない + else + if (err & SDATA_ERRPUT_PCODE) i = ERC_DEV_OTHER + ERC_PRODCODE;//プロダクトコード不一致 + if (i !=0 ) + { + gui.PanelEffective(PANEL_WRITE,false,false); + sprintf(scr_err,"ERROR %d",i); + gui.MessEffective(MESSAGE_MENU_ERROR); + } + else{ + gui.MessEffective(MESSAGE_MENU_OPERATE); + gui.PanelEffective(PANEL_WRITE); + } + }else{//なし + gui.PanelEffective(PANEL_WRITE,false,false); + gui.PanelEffective(PANEL_READ,false,false); + + //if (inserted == false) i = ERC_DEVICE + ERC_DEV_CARD;//カードが無い + //else + if (inserted == false) + { + strcpy(scr_err,"Please Insert Card"); + gui.MessEffective(MESSAGE_MENU_CAUTION); + + }else{ + if (err & SDATA_ERRPUT_MEDIA) i = ERC_MEDIA + ERC_DEV_CARD;//バックアップがない + else + if (err & SDATA_ERRPUT_VERIFI) i = ERC_SDK_VERIFI + ERC_DEV_CARD;//データが壊れている + else if (sdins == false) i = ERC_DEVICE + ERC_DEV_OUT;//書出し先デバイスが無い + else i = ERC_FORMAT + ERC_DEV_CARD;//フォーマットエラー + sprintf(scr_err,"ERROR %d",i); + gui.MessEffective(MESSAGE_MENU_ERROR); + } + //}else if ((flg ==false) || (flg2 == false)) + //{//どっちかダメ + // if (formatted == false) i = ERC_FORMAT + ERC_DEV_CARD;//カード未フオーマット + // else i = ERC_FORMAT + ERC_DEV_OUT;//バックアップ先が未フオーマット + // sprintf(scr_err,"CAUTION %d",i); + // gui.MessEffective(MESSAGE_MENU_CAUTION); + //}else if(agr==false) + } + + + gui.MessEffective(MESSAGE_PRODUCT); + gui.MessEffective(MESSAGE_PRODUCT2); + +/* + eColor col; + if ((flg == false) && (flg2 == false))col = COLOR_RED; + else if ((flg == false) || (flg2 == false))col = COLOR_YELLO; + if (formatted) gui.MessEffective(MESSAGE_MENU_CARDERR,false,false); + else{ + gui.MessCol(MESSAGE_MENU_CARDERR,col); + if (inserted) gui.MessStr(MESSAGE_MENU_CARDERR,"savedata is not format or broken"); + else gui.MessStr(MESSAGE_MENU_CARDERR,"CARD is not found"); + gui.MessEffective(MESSAGE_MENU_CARDERR); + } + if (exfm) gui.MessEffective(MESSAGE_MENU_SDERR,false,false); + else{ + gui.MessCol(MESSAGE_MENU_SDERR,col); + if (sdins) gui.MessStr(MESSAGE_MENU_SDERR,"backup data is not in SD"); + else gui.MessStr(MESSAGE_MENU_SDERR,"SD is not found"); + gui.MessEffective(MESSAGE_MENU_SDERR); + } +*/ +// gui.PanelEffective(PANEL_END); + gui.PanelEffective(PANEL_TITLE); + gui.PanelEffective(PANEL_MENU); + + gui.Draw(); +} + +//デバッグ用、ボタン待ち +void ScrStep() +{ + scr_evnt = EVNT_NONE; + gui.ButtonMask(nn::hid::BUTTON_B); +} + + +void ClearBkupMess() +{ + gui.MessEffective(MESSAGE_CONF,false,false); + gui.MessEffective(MESSAGE_RESULT,false,false); + gui.MessEffective(MESSAGE_OPERATE,false,false); + gui.MessEffective(MESSAGE_QUIT_OPERATE,false,false); + gui.MessEffective(MESSAGE_STATUS,false,false); + gui.MessEffective(MESSAGE_COUNT,false,false); + gui.MessEffective(MESSAGE_COUNT2,false,false); + gui.PanelEffective(PANEL_BKUP); +} + +//Backup +void scr_Backup() +{ + scr_evnt = EVNT_NONE; + gui.PanelLineStyle(PANEL_BKUP,COLOR_SKY); + gui.MessStr(MESSAGE_TITLE," --- Backup Card Savedata ---"); + gui.PanelEffective(PANEL_TITLE); + ClearBkupMess(); + gui.Draw(); + +} +void scr_BackupYesNo() +{ + scr_Backup(); + gui.MessEffective(MESSAGE_CONF); + gui.MessEffective(MESSAGE_OPERATE); + YesNo(); +} + +//restore +void scr_Restore() +{ + scr_evnt = EVNT_NONE; + gui.PanelLineStyle(PANEL_BKUP,COLOR_PARPL); + gui.MessStr(MESSAGE_TITLE,"--- Restore Card Savedata ---"); + gui.PanelEffective(PANEL_TITLE); + ClearBkupMess();//backupと同じパネルを使う + gui.Draw(); + +} +void scr_RestoreYesNo() +{ + scr_Restore(); + gui.MessEffective(MESSAGE_CONF); + gui.MessEffective(MESSAGE_OPERATE); + YesNo(); +} + + +void scr_Status(char *s,eColor col) +{ + gui.MessCol(MESSAGE_STATUS,col); + gui.MessStr(MESSAGE_STATUS,s); + gui.MessEffective(MESSAGE_STATUS); + gui.Draw(); +} + +void scr_ResultQuit(char *s,eColor col) +{ + gui.MessCol(MESSAGE_RESULT,col); + gui.MessStr(MESSAGE_RESULT,s); + gui.MessEffective(MESSAGE_RESULT); + gui.MessEffective(MESSAGE_QUIT_OPERATE); + Quit(); +} + + +void scr_InsExitQuit() +{ + ClearBkupMess(); + gui.PanelLineStyle(PANEL_INSEXIT,COLOR_RED); + gui.PanelEffective(PANEL_INSEXIT); + Quit(); +} + +// カウント/MAX 表示 +char str_Counter[128]; +char str_Counter2[128]; +void scr_CountPerMax(int ct,int max) +{ + sprintf(str_Counter,"%d / %d",ct,max); + gui.MessStr(MESSAGE_COUNT,str_Counter); + gui.MessEffective(MESSAGE_COUNT); + gui.Draw(); +} + +//ゲージ&total +void scr_CountPerMax2(int ct,int max,int total) +{ + if (total == -1) str_Counter2[0]=0; + else if (total != 0){ +// gui.MessCol(MESSAGE_COUNT2,COLOR_WHITE); + sprintf(str_Counter2,"total size %d",total); + }else{ +// gui.MessCol(MESSAGE_COUNT2,COLOR_YELLO); + int i; + int lv = ct/(max/25); + for (i =0;i'; + while ( i < 25 )str_Counter2[i++] = '|'; + str_Counter2[i] = 0; + } + //sprintf(str_Counter2,"%d / %d",ct,max); + gui.MessStr(MESSAGE_COUNT2,str_Counter2); + gui.MessEffective(MESSAGE_COUNT2); + gui.Draw(); + +} + +void scr_MessOnCount2(char *str) +{ +// gui.MessCol(MESSAGE_COUNT2,COLOR_YELLO); + gui.MessStr(MESSAGE_COUNT2,str); + gui.MessEffective(MESSAGE_COUNT2); + gui.Draw(); +} + + +//実行確認 +void scr_ConfirmDbg(char *str) +{ + scr_evnt = EVNT_NONE; + gui.MessStr(MESSAGE_CONFIRM_TITLE,str); + gui.PanelEffective(PANEL_CONFIRM); + YesNo(); +} + + +//エラー表示とQuitボタン +void scr_ErrorQuitDbg(tColStr **s) +{ + scr_evnt = EVNT_NONE; + gui.MessStr(MESSAGE_ERROR_TITLE,s[0]->str); + gui.MessCol(MESSAGE_ERROR_TITLE,s[0]->color); + gui.MessStr(MESSAGE_ERROR_INFO,s[1]->str); + gui.MessCol(MESSAGE_ERROR_INFO,s[1]->color); + gui.MessStr(MESSAGE_ERROR_INFO2,s[2]->str); + gui.MessCol(MESSAGE_ERROR_INFO2,s[2]->color); + gui.MessStr(MESSAGE_ERROR_INFO3,s[3]->str); + gui.MessCol(MESSAGE_ERROR_INFO3,s[3]->color); + gui.PanelEffective(PANEL_ERROR); + Quit(); +} + +//成功表示とQuitボタン +void scr_SuccessQuitDbg(tColStr **s) +{ + scr_evnt = EVNT_NONE; + gui.MessStr(MESSAGE_SUCCESS_TITLE,s[0]->str); + gui.MessCol(MESSAGE_SUCCESS_TITLE,s[0]->color); + gui.MessStr(MESSAGE_SUCCESS_INFO,s[1]->str); + gui.MessCol(MESSAGE_SUCCESS_INFO,s[1]->color); + gui.MessStr(MESSAGE_SUCCESS_INFO2,s[2]->str); + gui.MessCol(MESSAGE_SUCCESS_INFO2,s[2]->color); + gui.PanelEffective(PANEL_SUCCESS); + Quit(); +} + + +//デバッグログ +void scr_DgbLog(cStrLst *p) +{ + gui.PanelLineStyle(PANEL_DBGLOG,COLOR_BLUE); + + for (int i=0;igetpos()+1;i++)gui.MemoStr(MEMO_DBGLOG,p->line(i),i); + + gui.PanelEffective(PANEL_DBGLOG); + gui.Draw(); +} + + + +int ScrDbgLogGetMax() +{ + return LOG_MAX; +} + + +void scr_Draw() +{ + gui.Draw(); +} + +void scr_GetEvnt() +{ +// gui.thUpdate(); +} + + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/common/common.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/common/common.cpp new file mode 100644 index 0000000..0abeace --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/common/common.cpp @@ -0,0 +1,187 @@ +#include +#include +#include "common.h" +#include "sleep.h" +#include "demo.h" + + +extern demo::RenderSystemDrawing s_RenderSystem; +extern nn::fnd::ExpHeap appHeap; +extern uptr heapForGx; + +// ファイルシステム処理と遷移やスリープ処理との排他制御に利用 +//nn::os::CriticalSection g_SleepCS; +// HOME ボタン遷移とファイルシステム処理の排他制御に利用(手動リセット) +nn::os::LightEvent g_TransitionEvent; +// スリープとファイルシステム処理の排他制御に利用(手動リセット) +nn::os::LightEvent g_AwakeEvent; + +void restoreGraphicSetting() +{ + // GPU レジスタ設定の復帰 + // ただし、下記は DMPGL API を使用して設定した状態の復帰のみ + // レジスタ設定コマンドは全て再発行するべき + nngxUpdateState(NN_GX_STATE_ALL); + nngxValidateState(NN_GX_STATE_ALL,GL_TRUE); +} + +FUNCP end_func; +void InitSysBreak(uptr adrs){ + end_func = (FUNCP)adrs; + + SleepHandler::Initialize(); + + //g_SleepCS.Initialize(); + g_AwakeEvent.Initialize(true); + g_TransitionEvent.Initialize(true); + + // 起床中は常に Signal 状態にしておく + g_AwakeEvent.Signal(); + g_TransitionEvent.Signal(); + + // アプレットライブラリに関する機能を有効にする + nn::applet::Enable(false); + // gx, snd, dsp 各ライブラリの Initialize 関数は applet::Enable() の後に呼ばれなければならない + // 特に、gx の初期化である nngxInitialize 関数は、Enable() 直後の終了判定の後に行われるべき + + // ロゴ表示時に電源ボタンが押されたなど、既に終了条件が立っていた場合、ここでアプリを終了させる + if ( nn::applet::IsExpectedToCloseApplication() ) + { + SleepHandler::Finalize(); + nn::Result result = nn::applet::PrepareToCloseApplication(); + NN_UTIL_PANIC_IF_FAILED( result ); + nn::applet::CloseApplication(); + } + // グラフィックスライブラリの初期化は、以降で行わなければならない + // 他、アプリケーションの初期化処理 + +} + + +//終了処理 +void finish() +{ + + SleepHandler::Finalize();//SLEEP + //g_SleepCS.Finalize(); + + (*end_func)(); + + g_AwakeEvent.Finalize(); + g_TransitionEvent.Finalize(); + + nn::fs::Finalize(); + + + appHeap.Free(reinterpret_cast(heapForGx)); + appHeap.Finalize(); + + nn::os::SetDeviceMemorySize(0); + nn::os::SetHeapSize(0); + + NN_LOG("End\n"); + nn::applet::PrepareToCloseApplication(); + nn::applet::CloseApplication(); +} + + +void CheckSysBreak(){ + // スリープからの起床時は、1フレーム分の描画完了を待ってから LCD を有効にする + if ( SleepHandler::s_IsAfterWakeUp ) { + nn::gx::StartLcdDisplay(); + SleepHandler::s_IsAfterWakeUp = false; + } + + // GPU のレジスタ設定の整合性を考慮した場合、 + // 各種遷移、スリープ要求への返答は描画終了後に行うべき + + // 本体スリープ判定 + if ( SleepHandler::IsSleepRequested() ) + { + SleepHandler::SleepSystem(); + } + + // 終了要求をチェック + if ( nn::applet::IsExpectedToCloseApplication() ) + { + finish(); + } + + // アプリケーションの遷移処理を行う + + // HOMEボタン処理(グラフィックスライブラリが初期化済みでなければならない) + if ( nn::applet::IsExpectedToProcessHomeButton() ) + { + // ここでフラグなどを判定してブロックを抜けるようにすれば HOME ボタン禁止区間を実現できる + // nn::applet::ClearHomeButtonState() による HOME ボタンフラグ削除も必要 + + g_TransitionEvent.ClearSignal(); + + // ファイルシステム処理中は遷移を待つ + //if ( g_SleepCS.TryEnter() ) + { + // スリープ要求を REJECT するように + nn::applet::DisableSleep(); + + //nngxWaitCmdlistDone(); + nn::applet::ProcessHomeButton(); + nn::applet::AppletWakeupState wState = nn::applet::WaitForStarting(); + NN_UNUSED_VAR(wState); + + //g_SleepCS.Leave(); + g_TransitionEvent.Signal(); + + // HOME メニューからの中断やバッテリー不足の要因により + // アプリ終了と判断された場合、アプリのメインループを抜けて終了処理へ + if ( nn::applet::IsExpectedToCloseApplication() ) + { + // 描画権は渡されていない + finish(); + } + + nn::applet::EnableSleep(true); + + // グラフィックの設定を戻す + restoreGraphicSetting(); + } + + } + + + // 電源ボタン処理(グラフィックスライブラリが初期化済みでなければならない) + if ( nn::applet::IsExpectedToProcessPowerButton() ) + { + g_TransitionEvent.ClearSignal(); + + // ファイルシステム処理中は遷移を待つ + //if ( g_SleepCS.TryEnter() ) + { + nn::applet::DisableSleep(); + //nngxWaitCmdlistDone(); + nn::applet::ProcessPowerButton(); + nn::applet::AppletWakeupState wState = nn::applet::WaitForStarting(); + + NN_UNUSED_VAR(wState); + + //g_SleepCS.Leave(); + g_TransitionEvent.Signal(); + + // アプリ終了と判断された場合、アプリのメインループを抜けて終了処理へ + if ( nn::applet::IsExpectedToCloseApplication() ) + { + // 描画権は渡されていない + finish(); + } + + nn::applet::EnableSleep(true); + + // グラフィックの設定を戻す + restoreGraphicSetting(); + } + + } + + + + +} diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/common/common.h b/branches/0thNUP_No_NUP/CardSaveDataMover/common/common.h new file mode 100644 index 0000000..730fb6c --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/common/common.h @@ -0,0 +1,11 @@ +#ifndef COMMON_H_ +#define COMMON_H_ + +typedef void (*FUNCP)(); + +void finish(); +void CheckSysBreak(); +void InitSysBreak(uptr adrs); + + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/common/shfnt.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/common/shfnt.cpp new file mode 100644 index 0000000..65ca877 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/common/shfnt.cpp @@ -0,0 +1,368 @@ +サソ +#include +#include +#include +#include +#include +#include + +#include "demo.h" + +const char s_ShaderBinaryFilePath[] = "rom:/nnfont_RectDrawerShader.shbin"; + +extern nn::fnd::ExpHeap appHeap; + +//--------------------------------------------------------------------------- +//! @brief 繧キ繧ァ繝シ繝縺ョ蛻晄悄蛹悶r陦後>縺セ縺吶 +//! +//! @param[in,out] pResource 謠冗判逕ィ繝ェ繧ス繝シ繧ケ繧堤ョ。逅縺吶k繧ェ繝悶ず繧ァ繧ッ繝医∈縺ョ繝昴う繝ウ繧ソ縲 +//--------------------------------------------------------------------------- +void* +InitShaders(nn::font::RectDrawer* pDrawer) +{ + const size_t ROMFS_BUFFER_SIZE = 1024 * 64; + static char buffer[ROMFS_BUFFER_SIZE]; + + nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE); + nn::fs::FileReader shaderReader(s_ShaderBinaryFilePath); + + const u32 fileSize = (u32)shaderReader.GetSize(); + + void* shaderBinary = appHeap.Allocate(fileSize); + NN_NULL_ASSERT(shaderBinary); + + shaderReader.Read(shaderBinary, fileSize); + + const u32 vtxBufCmdBufSize = + nn::font::RectDrawer::GetVertexBufferCommandBufferSize(shaderBinary, fileSize); + void *const vtxBufCmdBuf = appHeap.Allocate(vtxBufCmdBufSize); + NN_NULL_ASSERT(vtxBufCmdBuf); + pDrawer->Initialize(vtxBufCmdBuf, shaderBinary, fileSize); + + appHeap.Free(shaderBinary); + + shaderReader.Finalize(); + nn::fs::Unmount("rom:"); + return vtxBufCmdBuf; +} +/*---------------------------------------------------------------------------* + @brief 繧ー繝ゥ繝輔ぅ繝繧ッ繧ケ縺ョ蛻晄悄險ュ螳壹r陦後>縺セ縺吶 + *---------------------------------------------------------------------------*/ +void +InitGX() +{ + glClearColor(0.3f, 0.3f, 0.3f, 1.0f); +} + + +//--------------------------------------------------------------------------- +//! @brief 謠冗判縺ョ蛻晄悄險ュ螳壹r陦後>縺セ縺吶 +//! +//! @param[in] width 逕サ髱「縺ョ蟷縲 +//! @param[in] height 逕サ髱「縺ョ鬮倥&縲 +//--------------------------------------------------------------------------- +void +InitDraw( + int width, + int height +) +{ + // 繧ォ繝ゥ繝シ繝舌ャ繝輔ぃ諠蝣ア + // LCD縺ョ蜷代″縺ォ蜷医o縺帙※縲∝ケ縺ィ鬮倥&繧貞・繧梧崛縺医※縺縺セ縺吶 + const nn::font::ColorBufferInfo colBufInfo = { width, height, PICA_DATA_DEPTH24_STENCIL8_EXT }; + + const u32 screenSettingCommands[] = + { + + // 繝薙Η繝シ繝昴シ繝医ョ險ュ螳 + NN_FONT_CMD_SET_VIEWPORT( 0, 0, colBufInfo.width, colBufInfo.height ), + + // 繧キ繧カ繝シ蜃ヲ逅繧堤┌蜉ケ + NN_FONT_CMD_SET_DISABLE_SCISSOR( colBufInfo ), + + // w繝舌ャ繝輔ぃ縺ョ辟。蜉ケ蛹 + // 繝繝励せ繝ャ繝ウ繧ク縺ョ險ュ螳 + // 繝昴Μ繧エ繝ウ繧ェ繝輔そ繝繝医ョ辟。蜉ケ蛹 + NN_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET( + 0.0f, // wScale : 0.0 縺ァW繝舌ャ繝輔ぃ縺檎┌蜉ケ + 0.0f, // depth range near + 1.0f, // depth range far + 0, // polygon offset units : 0.0 縺ァ 繝昴Μ繧エ繝ウ繧ェ繝輔そ繝繝医′辟。蜉ケ + colBufInfo), + }; + + nngxAdd3DCommand(screenSettingCommands, sizeof(screenSettingCommands), true); + + static const u32 s_InitCommands[] = + { + // 繧ォ繝ェ繝ウ繧ー繧堤┌蜉ケ + NN_FONT_CMD_SET_CULL_FACE( NN_FONT_CMD_CULL_FACE_DISABLE ), + + // 繧ケ繝繝ウ繧キ繝ォ繝繧ケ繝医r辟。蜉ケ + NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(), + + // 繝繝励せ繝繧ケ繝医r辟。蜉ケ + // 繧ォ繝ゥ繝シ繝舌ャ繝輔ぃ縺ョ蜈ィ縺ヲ縺ョ謌仙繧呈嶌縺崎セシ縺ソ蜿ッ + NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK( + false, // isDepthTestEnabled + 0, // depthFunc + true, // depthMask + true, // red + true, // green + true, // blue + true), // alpha + + // 繧「繝シ繝ェ繝シ繝繝励せ繝繧ケ繝医r辟。蜉ケ + NN_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST( false ), + + // 繝輔Ξ繝シ繝繝舌ャ繝輔ぃ繧「繧ッ繧サ繧ケ蛻カ蠕。 + NN_FONT_CMD_SET_FBACCESS( + true, // colorRead + true, // colorWrite + false, // depthRead + false, // depthWrite + false, // stencilRead + false), // stencilWrite + }; + + nngxAdd3DCommand(s_InitCommands, sizeof(s_InitCommands), true); +} + +//--------------------------------------------------------------------------- +//! @brief ResFont繧呈ァ狗ッ峨@縺セ縺吶 +//! +//! @param[out] pFont 讒狗ッ峨☆繧九ヵ繧ゥ繝ウ繝医∈縺ョ繝昴う繝ウ繧ソ縲 +//! @param[in] filePath 繝ュ繝シ繝峨☆繧九ヵ繧ゥ繝ウ繝医Μ繧ス繝シ繧ケ繝輔ぃ繧、繝ォ蜷阪 +//! +//! @return ResFont讒狗ッ峨ョ謌仙凄繧定ソ斐@縺セ縺吶 +//--------------------------------------------------------------------------- +bool +InitFont( + nn::font::ResFont* pFont, + void* pBuffer +) +{ + // 繝輔か繝ウ繝医Μ繧ス繝シ繧ケ繧偵そ繝繝医@縺セ縺 + bool bSuccess = pFont->SetResource(pBuffer); + + // 謠冗判逕ィ繝舌ャ繝輔ぃ繧定ィュ螳壹@縺セ縺吶 + const u32 drawBufferSize = nn::font::ResFont::GetDrawBufferSize(pBuffer); + void* drawBuffer = appHeap.Allocate(drawBufferSize, 4); + pFont->SetDrawBuffer(drawBuffer); + NN_NULL_ASSERT(drawBuffer); + + return bSuccess; +} + +//--------------------------------------------------------------------------- +//! @brief ResFont繧堤エ譽縺励∪縺吶 +//! +//! @param[in] pFont 遐エ譽縺吶k繝輔か繝ウ繝医∈縺ョ繝昴う繝ウ繧ソ縲 +//--------------------------------------------------------------------------- +void +CleanupFont(nn::font::ResFont* pFont) +{ + // 謠冗判逕ィ繝舌ャ繝輔ぃ縺ョ辟。蜉ケ蛹 + // 謠冗判逕ィ繝舌ャ繝輔ぃ縺後そ繝繝医&繧後※縺繧九↑繧 讒狗ッ画凾縺ォ SetDrawBuffer 縺ォ貂。縺励◆繝舌ャ繝輔ぃ縺ク縺ョ + // 繝昴う繝ウ繧ソ縺瑚ソ斐▲縺ヲ縺阪∪縺吶 + void *const drawBuffer = pFont->SetDrawBuffer(NULL); + if (drawBuffer != NULL) + { + appHeap.Free(drawBuffer); + } +} + +//--------------------------------------------------------------------------- +//! @brief 陦ィ遉コ譁蟄怜礼畑繝舌ャ繝輔ぃ繧堤「コ菫昴@縺セ縺吶 +//! +//! @param[in] charMax 陦ィ遉コ縺吶k譁蟄怜励ョ譛螟ァ譁蟄玲焚縲 +//! +//! @return 遒コ菫昴@縺溯。ィ遉コ譁蟄怜礼畑繝舌ャ繝輔ぃ縺ク縺ョ繝昴う繝ウ繧ソ繧定ソ斐@縺セ縺吶 +//--------------------------------------------------------------------------- +nn::font::DispStringBuffer* +AllocDispStringBuffer(int charMax) +{ + const u32 DrawBufferSize = nn::font::CharWriter::GetDispStringBufferSize(charMax); + void *const bufMem = appHeap.Allocate(DrawBufferSize); + NN_NULL_ASSERT(bufMem); + + return nn::font::CharWriter::InitDispStringBuffer(bufMem, charMax); +} + +//--------------------------------------------------------------------------- +//! @brief 譁蟄怜苓。ィ遉コ逕ィ縺ォ繝「繝繝ォ繝薙Η繝シ陦悟励→蟆蠖ア陦悟励r險ュ螳壹@縺セ縺吶 +//! +//! @param[in] pDrawer RectDrawer繧ェ繝悶ず繧ァ繧ッ繝医∈縺ョ繝昴う繝ウ繧ソ縲 +//! @param[in] width 逕サ髱「縺ョ蟷縲 +//! @param[in] height 逕サ髱「縺ョ鬮倥&縲 +//--------------------------------------------------------------------------- +void +SetupTextCamera( + nn::font::RectDrawer* pDrawer, + int width, + int height +) +{ + // 蟆蠖ア陦悟励r豁」蟆蠖ア縺ォ險ュ螳 + { + // 蟾ヲ荳雁次轤ケ縺ィ縺励〆霆ク縺ィZ霆ク縺ョ蜷代″縺碁縺ォ縺ェ繧九h縺縺ォ險ュ螳壹@縺セ縺吶 + nn::math::MTX44 proj; + f32 znear = 0.0f; + f32 zfar = -1.0f; + f32 t = 0; + f32 b = static_cast(width); + f32 l = 0; + f32 r = static_cast(height); + nn::math::MTX44OrthoPivot(&proj, l, r, b, t, znear, zfar, nn::math::PIVOT_UPSIDE_TO_TOP); + pDrawer->SetProjectionMtx(proj); + } + + // 繝「繝繝ォ繝薙Η繝シ陦悟励r蜊倅ス崎。悟励↓險ュ螳 + { + nn::math::MTX34 mv; + nn::math::MTX34Identity(&mv); + pDrawer->SetViewMtxForText(mv); + } +} + +nn::font::RectDrawer drawer; +void *drawerBuf; +nn::font::DispStringBuffer *pDrawStringBuf0; +nn::font::DispStringBuffer *pDrawStringBuf1; +nn::font::ResFont font; +nn::font::TextWriter writer; +//--------------------------------------------------------------------------- +//! @brief ASCII譁蟄怜励r謠冗判縺励∪縺吶 +//--------------------------------------------------------------------------- +void shf_DrawText_0( u16 x,u16 y,char *s) +{ + writer.SetCursor(x, y); + + writer.StartPrint(); + (void)writer.Print(s); + writer.EndPrint(); + drawer.BuildTextCommand(&writer); + + + drawer.DrawBegin(); + + SetupTextCamera(&drawer, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + writer.UseCommandBuffer(); + + drawer.DrawEnd(); +} + +void shf_DrawText_1( u16 x,u16 y,char *s) +{ + writer.SetCursor(x, y); + + writer.StartPrint(); + (void)writer.Print(s); + writer.EndPrint(); + drawer.BuildTextCommand(&writer); + + + drawer.DrawBegin(); + + SetupTextCamera(&drawer, NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT); + writer.UseCommandBuffer(); + + drawer.DrawEnd(); +} + + +void shf_SetSize(f32 sz) +{ + writer.SetScale(sz/14,sz/20); +} + +void shf_SetScale(f32 h,f32 v) +{ + writer.SetScale(h,v); +} + + +void shf_SetFontSize(f32 sz) +{ + writer.SetFontSize(sz); +} + +f32 shf_GetFontWidth() +{ + return writer.GetFontWidth(); +} + +f32 shf_GetFontHeight() +{ + return writer.GetFontHeight(); +} + + +void shf_SetColor(f32 r,f32 g,f32 b,f32 a) +{ + writer.SetTextColor(nn::util::FloatColor(r,g,b,a)); +} + +//蛻晄悄蛹 +//AppHeap遒コ菫昴ヽenderSystem.Initit縺ョ蠕後↓蜻シ縺カ +void SharedFontInit() +{ + + InitGX(); + + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ蛻晄悄蛹 + NN_UTIL_PANIC_IF_FAILED(nn::pl::InitializeSharedFont()); + + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ繝ュ繝シ繝峨′螳御コ縺吶k縺セ縺ァ蠕讖 + while (nn::pl::GetSharedFontLoadState() != nn::pl::SHARED_FONT_LOAD_STATE_LOADED) + { + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ繝ュ繝シ繝峨↓螟ア謨励@縺ヲ縺縺ェ縺縺狗「コ隱 + if (nn::pl::GetSharedFontLoadState() == nn::pl::SHARED_FONT_LOAD_STATE_FAILED) + { + NN_TPANIC_("failed to load shared font!\n"); + } + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(1)); + } + + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ遞ョ鬘槭r蜿門セ + //nn::pl::SharedFontType sharedFontType = nn::pl::GetSharedFontType(); + + // 蜈ア譛峨ヵ繧ゥ繝ウ繝医ョ繝シ繧ソ縺ョ繧「繝峨Ξ繧ケ繧貞叙蠕 + void* pFontBuffer = nn::pl::GetSharedFontAddress(); + + InitFont(&font, pFontBuffer); + + // 謠冗判繝ェ繧ス繝シ繧ケ縺ョ讒狗ッ + drawerBuf = InitShaders(&drawer); + + // 謠冗判譁蟄怜礼畑繝舌ャ繝輔ぃ縺ョ遒コ菫 + pDrawStringBuf0 = AllocDispStringBuffer(1024); + pDrawStringBuf1 = AllocDispStringBuffer(512); + + writer.SetDispStringBuffer(pDrawStringBuf0); + writer.SetFont(&font); + SetupTextCamera(&drawer, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + +} + + +void SharedFontFinalize() +{ + drawer.Finalize(); + + // 謠冗判繝ェ繧ス繝シ繧ケ縺ョ遐エ譽 + appHeap.Free(drawerBuf); + + // 繝輔か繝ウ繝医ョ遐エ譽 + CleanupFont(&font); + + // 謠冗判譁蟄怜礼畑繝舌ャ繝輔ぃ縺ョ隗」謾セ + appHeap.Free(pDrawStringBuf1); + appHeap.Free(pDrawStringBuf0); + +} + + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/common/shfnt.h b/branches/0thNUP_No_NUP/CardSaveDataMover/common/shfnt.h new file mode 100644 index 0000000..e168087 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/common/shfnt.h @@ -0,0 +1,30 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: irp.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef GUI_SHFNT_H_ +#define GUI_SHFNT_H_ + +void SharedFontInit(); +void SharedFontFinalize(); +void shf_DrawText_0(u16 x,u16 y,char* s); +void shf_DrawText_1(u16 x,u16 y,char* s); +void shf_SetSize(f32 sz); +void shf_SetScale(f32 h,f32 v); +void shf_SetColor(f32 r,f32 g,f32 b,f32 a); +void shf_SetFontSize(f32 sz); +f32 shf_GetFontWidth(); +f32 shf_GetFontHeight(); + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/common/sleep.cpp b/branches/0thNUP_No_NUP/CardSaveDataMover/common/sleep.cpp new file mode 100644 index 0000000..67d32cc --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/common/sleep.cpp @@ -0,0 +1,110 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: sleep.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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include + +#include "sleep.h" + +//extern nn::os::CriticalSection g_SleepCS; +extern nn::os::LightEvent g_TransitionEvent; +extern nn::os::LightEvent g_AwakeEvent; + +volatile bool SleepHandler::s_IsAfterWakeUp = false; + +/*------------------------------------------------------------------------*/ +void SleepHandler::Initialize( void ) +{ + nn::applet::SetSleepQueryCallback(SleepQueryCallback, 0); + nn::applet::SetAwakeCallback(AwakeCallback, 0); +// nn::applet::SetSleepCancelCallback(NULL, 0); // CancelCallback 縺ッ菴ソ繧上↑縺縺薙→繧呈耳螂ィ縺励∪縺 +} + +/*------------------------------------------------------------------------*/ +void SleepHandler::Finalize( void ) +{ + nn::applet::SetSleepQueryCallback(NULL, 0); + nn::applet::SetAwakeCallback(NULL, 0); + + nn::applet::DisableSleep(); +} + +/*------------------------------------------------------------------------* + 繧キ繧ケ繝繝繧ケ繝ェ繝シ繝励ョ謖遉コ縺梧擂縺ヲ縺繧九°縺ゥ縺縺九r霑斐@縺セ縺吶 + *------------------------------------------------------------------------*/ +bool SleepHandler::IsSleepRequested( void ) +{ + if ( nn::applet::IsExpectedToReplySleepQuery() ) + return true; + + return false; +} + +/*------------------------------------------------------------------------* + 譛ャ菴薙せ繝ェ繝シ繝礼憾諷九↓遘サ陦後&縺帙k縺溘a縺ョ蜃ヲ逅繧定。後>縺セ縺吶 + 繧ー繝ゥ繝輔ぅ繝繧ッ繧ケ縺ェ縺ゥ縺ョ蜃ヲ逅縺後せ繝ェ繝シ繝励↓蜈・縺」縺ヲ繧ょ撫鬘後↑縺 + 驕ゥ蛻縺ェ繧ソ繧、繝溘Φ繧ー縺ァ蜻シ縺ウ蜃コ縺吝ソ隕√′縺ゅj縺セ縺吶 + *------------------------------------------------------------------------*/ +void SleepHandler::SleepSystem( void ) +{ + // SleepHandler::IsSleepRequested() == true 縺ォ縺翫¢繧句他縺ウ蜃コ縺励′蜑肴署 + + // 菴輔i縺九ョ逅逕ア縺ァ SleepQuery 縺ォ蟇セ縺励※ REJECT 繧定ソ斐☆蝣エ蜷医ッ縲√%縺薙〒蛻、螳壹@縺ヲ + // REJECT 繧定ソ斐@縲√%縺ョ髢「謨ー繧呈栢縺代k + + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝蜃ヲ逅荳ュ縺ッ繧ケ繝ェ繝シ繝励r縺励↑縺 + //if ( g_SleepCS.TryEnter() ) + { + // 繧ケ繝ェ繝シ繝怜燕蜃ヲ逅 + + nn::applet::ReplySleepQuery(nn::applet::REPLY_ACCEPT); + + g_AwakeEvent.Wait(); + + // 繧ケ繝ェ繝シ繝怜セゥ蟶ー譎ゅョ蜃ヲ逅 + + // g_SleepCS.Leave(); + } +} + +/*------------------------------------------------------------------------* + 繧ケ繝ェ繝シ繝怜撫縺蜷医o縺帶凾縺ォ蜻シ縺ー繧後k繧ウ繝シ繝ォ繝舌ャ繧ッ + *------------------------------------------------------------------------*/ +AppletQueryReply SleepHandler::SleepQueryCallback( uptr arg ) +{ + NN_UNUSED_VAR(arg); + g_AwakeEvent.ClearSignal(); + + if ( !nn::applet::IsActive() ) + { + // Inactive 縺ェ縺ィ縺阪√Γ繧、繝ウ繧ケ繝ャ繝繝峨ッ applet::WaitForStarting() 縺ァ蛛懈ュ「迥カ諷九〒縺ゅj縲 + // 莉悶ョ繧ケ繝ャ繝繝峨b蛛懈ュ「迥カ諷九↓縺ェ縺」縺ヲ縺繧九ッ縺夲シ医い繝励Μ繧ア繝シ繧キ繝ァ繝ウ蛛エ縺ョ螳溯」萓晏ュ假シ + return nn::applet::REPLY_ACCEPT; + } + else + { + return nn::applet::REPLY_LATER; + } +} + +/*------------------------------------------------------------------------* + 繧ケ繝ェ繝シ繝怜セゥ蟶ー譎ゅ↓蜻シ縺ー繧後k繧ウ繝シ繝ォ繝舌ャ繧ッ + *------------------------------------------------------------------------*/ +void SleepHandler::AwakeCallback( uptr arg ) +{ + NN_UNUSED_VAR(arg); + g_AwakeEvent.Signal(); + + s_IsAfterWakeUp = true; +} diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/common/sleep.h b/branches/0thNUP_No_NUP/CardSaveDataMover/common/sleep.h new file mode 100644 index 0000000..15a14f1 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/common/sleep.h @@ -0,0 +1,46 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: sleep.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef NN_SAMPLE_DEMOS_DEMO2_SLEEP_H_ +#define NN_SAMPLE_DEMOS_DEMO2_SLEEP_H_ + +/*------------------------------------------------------------------------* + 譛ャ菴薙せ繝ェ繝シ繝励↓髢「騾」縺吶k蜃ヲ逅 + *------------------------------------------------------------------------*/ + class SleepHandler + { + public: + SleepHandler() {} + ~SleepHandler() {} + + static void Initialize( void ); + static void Finalize( void ); + static bool IsSleepRequested( void ); + static void SleepSystem( void ); + + static AppletQueryReply SleepQueryCallback( uptr arg ); + static void AwakeCallback( uptr arg ); + static void CancelCallback( uptr arg ); + + // 繧ケ繝ェ繝シ繝励°繧峨ョ蠕ゥ蟶ー蠕後1繝輔Ξ繝シ繝蛻謠冗判繧貞セ縺」縺ヲ縺九i LCD 繧呈怏蜉ケ縺ォ縺吶k縺溘a縺ョ繝輔Λ繧ー + static volatile bool s_IsAfterWakeUp; + + private: + static nn::os::LightEvent s_AwakeEvent; + static bool s_IsInitialized; + }; + + +#endif // NN_SAMPLE_DEMOS_DEMO2_SLEEP_H_ diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/common/ver.h b/branches/0thNUP_No_NUP/CardSaveDataMover/common/ver.h new file mode 100644 index 0000000..e638593 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/common/ver.h @@ -0,0 +1,22 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: irp.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef VER_H_ +#define VER_H_ + +#define VERSION 1.02 + + +#endif diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/docs/Error_code.txt b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/Error_code.txt new file mode 100644 index 0000000..0920809 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/Error_code.txt @@ -0,0 +1,37 @@ +サソ +//繧ィ繝ゥ繝シ陦ィ遉コ繧ウ繝シ繝峨ョ荳倶ス搾シ呈。 +0, //荳肴 +1, //繝繝舌う繧ケ縺瑚ヲ九▽縺九i縺ェ縺 +2,//繝励Ο繝繧ッ繝医さ繝シ繝我ク堺ク閾エ +3,//繝吶Μ繝輔ぃ繧、繧ィ繝ゥ繝シ +4,//繝代せ縺碁聞縺吶℃ +5,//繝繧」繝ャ繧ッ繝医Μ豺ア縺吶℃ +6, //繝。繝繧」繧「縺瑚ヲ九▽縺九i縺ェ縺(繧オ繝門渕逶、螟悶l縺ェ縺ゥ) +10, //繝輔ぃ繧、繝ォ縺瑚ヲ九▽縺九i縺ェ縺 +20, //譌「縺ォ蟄伜惠 +21, //遨コ縺榊ョケ驥上′縺ェ縺 +22, //譖ク霎シ縺ソ遖∵ュ「 +30, //繧「繧ッ繧サ繧ケ繧ィ繝ゥ繝シ +50, //繝輔か繝シ繝槭ャ繝医お繝ゥ繝シ +60, //讀懆ィシ縺ォ螟ア謨励∵隼遶 +70, //ROM諠蝣ア繧ィ繝ゥ繝シ +80, //繝ェ繝医Λ繧、隕∵ア +90, //螳溯。梧凾繧ィ繝ゥ繝シ +99 //豺ア蛻サ縺ェ繧ィ繝ゥ繝シ + + +//荳贋ス +CARD = 100, +BKUP DEVICE = 200, +OTHER = 300 + + +縺薙l繧峨ョ蜷域舌〒陦ィ遉コ縺輔l繧 +萓九∴縺ー縲√き繝シ繝峨′蛻コ縺輔▲縺ヲ縺縺ェ縺蝣エ蜷医ッ 101 縺ィ縺ェ繧 + + +騾壼クク譎ゅ↓逋コ逕溘@繧縺吶>縺ィ諤昴o繧後k繧ゅョ + +302 .. 繝励Ο繝繧ッ繝医さ繝シ繝峨′荳閾エ縺励↑縺 +101 .. 繧ォ繝シ繝峨′隕九▽縺九i縺ェ縺 + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/docs/HowTo繝薙Ν繝.txt b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/HowTo繝薙Ν繝.txt new file mode 100644 index 0000000..4733c02 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/HowTo繝薙Ν繝.txt @@ -0,0 +1,24 @@ +動作確認環境: +ARM製 RVC_Nintendo 4.1 +omake 0.9.8.5 +CTR SDK2.0 + Repairtoolプライベートパッチ +SDK2.0用のSampledemos のcommon,gxをビルドしておく + +動作要件:上SDK以降のバージョンにシステムアップデートされた本体 + +omakerootのあるディレクトリでomake +個別の場合 +body下でビルドし出来たcia を、Imp下のomakeで指定 +ビルドするとNANDインポート用のcciができる + +インポート先: +ciaをSDからインポート -> SD .. DevMenuが必要 +カード起動しインポート -> NAND + +量産実機での実行にはマスタリング必須 +cia をOLS付でマスタリングし +そのciaで作成したcciをマスタリング + +カードインポートで失敗する場合はciaをチェック +ciaのマスタリングはSDインポート可否で確認できる + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/docs/release.txt b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/release.txt new file mode 100644 index 0000000..eb95a35 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/release.txt @@ -0,0 +1,55 @@ +//////////////////////////////////////////////////////////////// +本ツールは 「Nintendo for 3DS」および専用カード用です +カード上のセーブデータをバックアップ及びリストアします +//////////////////////////////////////////////////////////////// + +NANDインポートしてから、内臓アプリ同様の手順で起動 + +(インポート手順) +・デバッガもしくはライタで"cci"をカードに書き込む +・Homeメニューよりカード起動しメニューからInport実行 +・メニューのImportを選ぶ +・終了したら電源ボタンを短押し ->"電源を切る"をタッチ +電源を入れなおさないとアイコンがメニューに現れません + + +(NANDから削除) +起動まではインポートと同様 +・メニューからDelete実行 +終了後はメニューに戻ります + +(テストパターン書き込み) +カード上のバックアップにテストデータを書き込みます +手元に使えるゲームカードが無い場合の動作確認用です +起動まではインポートと同様 +・デバッガもしくはライタで"cci"をカードに書き込む +・カードを本体に差しメニューからTest Data実行 +・カーソルで内容を選択、Aでライト、Xでベリファイ +種別はCasual Test を選ぶ、他はリリース時のチェックに使う程度 + +<テスト手順> +ライト後に一旦終了してHomeメニューにもどり +Nand上のツールを起動し、リード&リストア +Homeボタンなどでツール終了、カード起動しベリファイ + + +ツール本体の操作は操作マニュアル参照 + + +[Histry] +1.02 Remaster 2.0.6(予定) + 正式版SDK_2.0 でビルド + 起動時に無線デーモンOFF -> DEA-SUPで出ていたフリーズ暫定対策、本ツールでは発生して無いが一応 + (いつのまに通信は切れない、完全な停止は本体スイッチ) + バナー、アイコンをデフォルトから変更 + Homeメニュー環境で動作確認 + フォントを本体内蔵フォントに変更 +1.01 Remaster 2.0.5 + Homeボタン、電源での中断終了に対応 + 終了が安定しないので表示をスレッドから関数コールに変更 + サブカードなし時などメディア認識できない場合のエラー追加 + +1.00 リリース:Remaser 2.0.4 + デバッグモードの無効化 + + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/docs/繝槭せ繧ソ繝ェ繝ウ繧ー.txt b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/繝槭せ繧ソ繝ェ繝ウ繧ー.txt new file mode 100644 index 0000000..a7d2309 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/繝槭せ繧ソ繝ェ繝ウ繧ー.txt @@ -0,0 +1,9 @@ +量産実機での動作にはマスタリングが必要 + +ciaはサーバ認証(OLS)必須で +取得には前回取得時よりリマスタバージョンを上げる必要あり(2011/2月現在) +メジャーはrsfで指定(Remasterversion) +マイナとマイクロはOmakefile +MAKECIAFLAGS = -minor 0 -micro 1 +上の場合 *.0.1 (*はrsfのRemasterversion) + diff --git a/branches/0thNUP_No_NUP/CardSaveDataMover/docs/謫堺ス懆ェャ譏.txt b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/謫堺ス懆ェャ譏.txt new file mode 100644 index 0000000..5ae7423 --- /dev/null +++ b/branches/0thNUP_No_NUP/CardSaveDataMover/docs/謫堺ス懆ェャ譏.txt @@ -0,0 +1,41 @@ + +<操作メニュー> + +操作が出来る状態のとき下画面にボタン表示 + +・バックアップが無い状態でカードを差すと +バックアップが有効 + +・バックアップがある状態では +リストアが有効 + +(バックアップ) +タッチして実行画面 +カードから本体内メモリに読み出します + +(リストア) +タッチして実行画面 +バックアップした内容をカードへ書きます +成功すると自動で消去 +失敗の場合は消去しません + +(バックアップデリート) +先頭画面で 方向キー LEFT + X 同時押し + + + +以下、ビルド時にフラグ有効(my_dess.h 内)にした場合のみ使える + +//クラッシュモード +書き戻す際にデータを壊す、ベリファイで必ずエラー +先頭画面で Y ボタン + +//デバグモード +先頭画面で 方向下+Y(0.09まで) +先頭画面で 方向下+X+Y(1.00以降) + +クラッシュモード有効時: L ボタン + +//テストデータ書き込み +デバグモード中に先頭画面でRボタン + diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.bsf b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.bsf differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.cpp new file mode 100644 index 0000000..bbb64c3 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.cpp @@ -0,0 +1,449 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: ConsoleBackup.cpp + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "demo.h" + +#include +#include + +#include "ConsoleBackup.h" +#include "DrawSystemState.h" +#include "FileName.h" +#include "Controller.h" +#include "SimplePlayer.h" +#include "Exporter.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "HeapManager.h" +#include "PlayHistoryManager.h" +#include "common_Types.h" +#include "VersionDetect.h" +#include "HardwareInfo.h" + +// svn繝ェ繝薙ず繝ァ繝ウ蝓九a霎シ縺ソ逕ィ +#include "version.h" +#ifndef BACKUP_VERSION_NUM +#define BACKUP_VERSION_NUM 0 +#endif + +namespace { + +// 繧ー繝ゥ繝輔ぅ繝繧ッ繧ケ縺ォ蜑イ繧雁ス薙※繧九Γ繝「繝ェ +const size_t s_GxHeapSize = 0x800000; + + +// 繝舌ャ繝繝ェ谿矩 +u8 batteryRemain = 100; + +// 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ +u8 s_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + +// 繝繝舌う繧ケID +bit32 s_DeviceId; + +// 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ縺瑚ェュ繧√k縺九←縺縺 +bool s_CanReadSerialNumber = false; + +// IVS縺ク縺ョ繝昴う繝ウ繧ソ +void* sp_Ivs; + +size_t s_SizeofIvs; + +// IVS縺瑚ェュ繧√k縺九←縺縺 +bool s_CanReadIvs = false; + +// 繝舌シ繧ク繝ァ繝ウ諠蝣ア +common::VerDef s_VerData; + +nn::Handle s_McuSession; + +} // namespace + +namespace ConsoleBackup{ + +bool IsAdapterConnected() +{ + return nn::ptm::CTR::GetAdapterState() == nn::ptm::CTR::ADAPTERSTATE_CONNECTED; +} + +bool IsBatteryLower() +{ + return batteryRemain <= 10; +} + +bool CanReadIVS() +{ + return s_CanReadIvs; +} + +bool CanReadSerialNumber() +{ + return s_CanReadSerialNumber; +} + +void GetSerialNumber(u8** serial, size_t* size) +{ + *serial = s_SerialNo; + *size = nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN; +} + +void GetIvs(void** ivs, size_t* size) +{ + *ivs = sp_Ivs; + *size = s_SizeofIvs; +} + +bit32 GetDeviceId() +{ + return s_DeviceId; +} + +void GetVersionData(common::VerDef* version) +{ + *version = s_VerData; +} + +nn::Handle GetMcuHandle() +{ + return s_McuSession; +} + + +extern "C" void nnMain(void) +{ + nn::Result result; + + // os 縺ョ蛻晄悄蛹 + nn::os::Initialize(); + + // fs 縺ョ蛻晄悄蛹 + nn::fs::Initialize(); + + // applet縺ョ蛻晄悄蛹 + nn::applet::Enable( false ); + + // hid 縺ョ蛻晄悄蛹 + result = nn::hid::Initialize(); + NN_UTIL_PANIC_IF_FAILED(result); + + // ndm縺ョ蛻晄悄蛹 + result = nn::ndm::Initialize(); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + + // 繝繝シ繝「繝ウ縺ョ閾ェ蠕句虚菴懊r蛛懈ュ「 + result = nn::ndm::Suspend(nn::ndm::DN_CEC); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + result = nn::ndm::Suspend(nn::ndm::DN_BOSS); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + result = nn::ndm::Suspend(nn::ndm::DN_FRIENDS); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + result = nn::ndm::Suspend(nn::ndm::DN_NIM); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + + // cfg 縺ョ蛻晄悄蛹 + nn::cfg::CTR::init::Initialize(); + nn::cfg::CTR::system::Initialize(); + + // 譎りィ郁ィュ螳夂畑ptm蛻晄悄蛹 + nn::ptm::CTR::InitializeForSystemMenu(); + + // ps 縺ョ蛻晄悄蛹 + nn::ps::Initialize(); + + // friends縺ョ蛻晄悄蛹 + result = nn::friends::detail::Initialize(); + + // mcu縺ョ蛻晄悄蛹 + nn::mcu::CTR::InitializeHwCheck(&s_McuSession); + + nn::mcu::CTR::HwCheck mcu(s_McuSession); + + // 繝偵シ繝励ョ遒コ菫 + common::HeapManager::GetHeap()->Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + // RenderSystem 縺ョ貅門y + uptr heapForGx = reinterpret_cast(common::HeapManager::GetHeap()->Allocate(s_GxHeapSize)); + demo::RenderSystemDrawing s_RenderSystem; + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + + // 繧オ繧ヲ繝ウ繝峨せ繝ャ繝繝峨ョ襍キ蜍 + common::InitializeSimplePlayer(); + + // 繝ュ繧ー謠冗判縺ョ蛻晄悄蛹 + common::Logger::GetLoggerInstance()->Initialize(CONSOLE_WIDTH, CONSOLE_HEIGHT, CONSOLE_MAX_LINE, &s_RenderSystem); + + // RenderSystem繧剃ス懊▲縺ヲ縺九i繝ュ繧ー縺悟コ縺帙k + common::Logger::InitializeEjectThread(); + common::Logger::SetEjectHandler(OnSdEjected); + // 襍キ蜍墓凾縺ォ蜑企勁 + common::Logger::GetLoggerInstance()->ClearLog(); + + COMMON_LOGGER("\n"); + COMMON_LOGGER("CTR Console Backup start\n"); + + // 繝懊ち繝ウ蜈・蜉 + nn::hid::PadReader s_PadReader; + nn::hid::PadStatus padStatus; + + // 繝繝シ繧ソ縺ョ貅門y + + // 螳悟ィ諤ァ讀懆ィシSEED縺ョ蜿門セ + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if (result.IsSuccess()) + { + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(common::IVS_NAND_PATHNAME); + if (result.IsSuccess()) + { + s64 fileSize = fis.GetSize(); + s32 ret; + void* addr = NULL; + addr = common::HeapManager::GetHeap()->Allocate(fileSize); + if (addr != NULL) + { + sp_Ivs = addr; + s_SizeofIvs = fileSize; + result = fis.TryRead(&ret, addr, fileSize); + if (result.IsSuccess()) + { + s_CanReadIvs = true; + } + // 蠕後〒IVS繧貞盾辣ァ縺吶k縺ョ縺ァFree縺励↑縺 + } + } + fis.Finalize(); + } + // 荳譌ヲ繧「繝ウ繝槭え繝ウ繝医@縺ヲ縺翫¥ + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + // 繝ェ繝シ繧ク繝ァ繝ウ縺ョ蜿門セ + nn::cfg::CTR::CfgRegionCode region; + region = nn::cfg::CTR::GetRegion(); + + // 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ縺ョ蜿門セ + std::memset(s_SerialNo, '\0', + nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN); + result = nn::cfg::CTR::system::GetSerialNo(s_SerialNo); + if(result.IsSuccess()) + { + s_CanReadSerialNumber = true; + } + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + common::HardwareInfo hwInfo; + hwInfo.AddCheckDigit(reinterpret_cast(s_SerialNo)); + + // 繝繝舌う繧ケID縺ョ蜿門セ + result = nn::ps::CTR::GetDeviceId(&s_DeviceId); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + bit64 infraDeviceId; + result = nn::nim::CTR::InitializeForShop(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + result = nn::nim::CTR::Shop::GetInfraDeviceId(s_DeviceId, &infraDeviceId); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + result = nn::nim::CTR::FinalizeForShop(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // MAC繧「繝峨Ξ繧ケ縺ョ蜿門セ + nn::nwm::Mac mac; + char8 macAddress[nn::nwm::Mac::MAC_STRING_SIZE]; + + result = nn::nwm::GetMacAddress(mac); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + mac.GetString(macAddress); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // 繝輔Ξ繝ウ繝峨さ繝シ繝峨ョ蜿門セ + nn::friends::CTR::FriendKey friendKey; + result = nn::friends::CTR::GetMyFriendKey(&friendKey); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + u64 friendCode = nn::friends::CTR::FriendKeyToFriendCode(friendKey); + + // 繝舌シ繧ク繝ァ繝ウ縺ョ蜿門セ + common::GetSystemVersion(&s_VerData, region); + + // 諠蝣ア蜃コ蜉 + COMMON_LOGGER("CTR Console Backup %s Rev.%s\n", __DATE__, BACKUP_VERSION_NUM); + COMMON_LOGGER("System Ver. %d.%d.%d-%d\n", s_VerData.cup.majorVersion, s_VerData.cup.minorVersion, s_VerData.cup.microVersion, + s_VerData.nup.majorVersion); + COMMON_LOGGER("System Region %s\n", nn::cfg::CTR::GetRegionCodeA3(region)); + COMMON_LOGGER("Serial Number %s\n", s_SerialNo); + COMMON_LOGGER("Device ID %llu\n", infraDeviceId); + COMMON_LOGGER("MAC Address %s\n", macAddress); + COMMON_LOGGER("Friend Code %04u-%04u-%04u\n", + static_cast(friendCode / 100000000ULL % 10000ULL), + static_cast(friendCode / 10000ULL % 10000ULL), + static_cast(friendCode % 10000ULL) ); + + + bool flip = false; + bool continueBackup = false; + + for(;;) + { + bool nextStep = false; + s_PadReader.ReadLatest(&padStatus); + + // A縺セ縺溘ッSTART繝懊ち繝ウ縺ァ騾イ陦 + if(padStatus.trigger & nn::hid::BUTTON_A || + padStatus.trigger & nn::hid::BUTTON_START) + { + nextStep = true; + } + + // L縺セ縺溘ッR繝懊ち繝ウ縺ァ荳贋ク狗判髱「繝輔Μ繝繝 + if(padStatus.trigger & nn::hid::BUTTON_R || + padStatus.trigger & nn::hid::BUTTON_L) + { + flip = !flip; + } + + // 繧ウ繝ウ繧ス繝シ繝ォ繧ケ繧ッ繝ュ繝シ繝ォ + if(padStatus.hold & nn::hid::BUTTON_UP) + { + common::Logger::GetLoggerInstance()->ScrollUp(); + } + + // 繧ウ繝ウ繧ス繝シ繝ォ繧ケ繧ッ繝ュ繝シ繝ォ + if(padStatus.hold & nn::hid::BUTTON_DOWN) + { + common::Logger::GetLoggerInstance()->ScrollDown(); + } + + if(padStatus.hold & nn::hid::BUTTON_LEFT) + { + common::Logger::GetLoggerInstance()->ScrollToBegin(); + } + + if(padStatus.hold & nn::hid::BUTTON_RIGHT) + { + common::Logger::GetLoggerInstance()->ScrollToEnd(); + } + + + // 諠蝣ア譖エ譁ー + // 繝舌ャ繝繝ェ + mcu.GetBatteryRemain(&batteryRemain); + // AC繧「繝繝励ち + std::string adapterState; + if(IsAdapterConnected()) + { + adapterState += ::std::string("Connected"); + } + else + { + adapterState += ::std::string("Not Connected"); + } + + // 謫堺ス懃畑繝。繝繧サ繝シ繧ク + // 騾イ謐礼「コ隱阪Γ繝繧サ繝シ繧ク繧貞シ縺ュ繧具シ + ::std::vector operationMessage; + + ControlState(operationMessage, nextStep, continueBackup); + + nn::util::FloatColor titleColor; + + titleColor.r = 0.3f; + titleColor.g = 0.f; + titleColor.b = 0.2f; + + // 荳顔判髱「陦ィ遉コ + common::DrawSystemState("CTR Console Backup", + s_RenderSystem, + titleColor, + flip, + adapterState, + BACKUP_VERSION_NUM, + &s_VerData, + batteryRemain, + infraDeviceId, + friendCode, + GetProgress(), + macAddress, + operationMessage, + region, + s_SerialNo + ); + + s_RenderSystem.SwapBuffers(); + + // 繝繝輔か繝ォ繝医〒荳狗判髱「縺ォ謠冗判縺吶k繧ゅョ + s_RenderSystem.SetRenderTarget(common::GetRenderTarget(NN_GX_DISPLAY1, flip)); + if(IsBackupSucceeded()) + { + s_RenderSystem.SetClearColor(common::GetRenderTarget(NN_GX_DISPLAY1, flip), SUCCESS_COLOR); + } + if(IsBackupFailed()) + { + s_RenderSystem.SetClearColor(common::GetRenderTarget(NN_GX_DISPLAY1, flip), FAIL_COLOR); + } + s_RenderSystem.Clear(); + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + + common::Logger::GetLoggerInstance()->DrawConsole(); + s_RenderSystem.SwapBuffers(); + + + s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); + + // 髮サ貅宣聞謚シ縺励〒邨ゆコ + if ( nn::applet::IsExpectedToCloseApplication()) + { + common::Logger::GetLoggerInstance()->Finalize(); + // 繧「繝ウ繝槭え繝ウ繝 + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + nn::fs::Unmount(common::SDMC_ARCHIVE_NAME); + s_RenderSystem.Finalize(); + + nn::mcu::CTR::FinalizeHwCheck(&s_McuSession); + nn::friends::detail::Finalize(); + nn::ps::Finalize(); + nn::ptm::CTR::FinalizeForSystemMenu(); + nn::cfg::CTR::system::Finalize(); + nn::cfg::CTR::init::Finalize(); + nn::hid::Finalize(); + nn::fs::Finalize(); + + nn::applet::PrepareToCloseApplication(); + nn::applet::CloseApplication(); + } + } +} + + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.h new file mode 100644 index 0000000..92a2588 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ConsoleBackup.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef NN_CONSOLEBACKUP_H_ +#define NN_CONSOLEBACKUP_H_ + +#include +#include "VersionDetect.h" + +namespace ConsoleBackup +{ + +bool IsAdapterConnected(); +bool IsBatteryLower(); +bool CanReadIVS(); +bool CanReadSerialNumber(); +void GetSerialNumber(u8** serial, size_t* size); +void GetIvs(void** ivs, size_t* size); +nn::Handle GetMcuHandle(); +void GetVersionData(common::VerDef* version); +bit32 GetDeviceId(); + +const u32 CONSOLE_WIDTH = 38; +const u32 CONSOLE_HEIGHT = 24; +const u32 CONSOLE_MAX_LINE = 1000; + +} + +/* NN_CONSOLEBACKUP_H_ */ +#endif diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.rsf b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.rsf new file mode 100644 index 0000000..a30132a --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/ConsoleBackup.rsf @@ -0,0 +1,52 @@ +BasicInfo: + Title : ConsoleBackup + ProductCode: ConsoleBackup + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xf8021 + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 0x4000 + Dependency : + - gpio + - pdn + - spi + - i2c + - mcu + - ptm + - codec + - cfg + - hid + - gsp + - friends + - nim + - ac + - ndm + +AccessControlInfo: + Priority : 16 + DisableDebug : true + + FileSystemAccess: + - DirectSdmc + - Debug + - Core + - CategoryFileSystemTool + + IoAccessControl: + - FsMountCardSpi + - FsMountNand + - FsMountTwln + +Option: + FreeProductCode: true + + +Rom: + # ROM 縺ォ蜷ォ繧√k繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ョ繝ォ繝シ繝医ヱ繧ケ繧呈欠螳壹@縺セ縺吶 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Controller.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Controller.cpp new file mode 100644 index 0000000..32cd6b5 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Controller.cpp @@ -0,0 +1,313 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Controller.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include "Controller.h" +#include "FileChecker.h" +#include "ConsoleBackup.h" +#include "Exporter.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" + +#include + +namespace ConsoleBackup +{ + +namespace +{ + +typedef enum BackupState +{ + STARTUP, // 蛻晄悄蛟、 + EXPORT_TWL_SOUND, // TWL繧オ繧ヲ繝ウ繝蛾伜沺縺ョ蜷ク蜃コ縺嶺クュ + EXPORT_TWL_PHOTO, // TWL蜀咏悄鬆伜沺縺ョ蜷ク蜃コ縺嶺クュ + EXPORT_CTR_NAND, // 蜷ク蜃コ縺嶺クュ + DELETE_NIM, // nim縺ョ繧キ繧ケ繝繝繧サ繝シ繝悶ョ繝シ繧ソ蜑企勁 + DONE, // 蜷ク蜃コ縺怜ョ御コ + FINISHED, // SD繧ォ繝シ繝画栢縺榊ョ御コ + FAIL // 螟ア謨 +} BackupState; + + +// APSetting縺ョ譖ク蠑上′辟。縺隴ヲ蜻翫し繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_ExistAPSettingAnnotation = false; +// SD縺ォ譖ク縺崎セシ縺ソ縺ァ縺阪↑縺隴ヲ蜻翫し繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_SdWriteProetctAnnotation = false; + +BackupState s_BackupState = STARTUP; +bool s_PlayedStartCursor = false; +bool s_PlayedSdPullOutCursor = false; +bool s_PlayedFinishedSound = false; +bool s_PlayedFailSound = false; + +} // namespace + +bool NeedsAcAdateper() +{ + return IsBatteryLower() && !IsAdapterConnected(); +} + +void ControlState(::std::vector& operationMessage, bool& nextStep, bool& continueBackup) +{ + // 迥カ諷矩キ遘サController + switch (s_BackupState) + { + + // 襍キ蜍墓凾 + case STARTUP: + { + bool error = false; + // 螳悟ィ諤ァ讀懆ィシSEED繧定ェュ繧√k縺具シ + if (CanReadIVS()) + { + // SD繧ォ繝シ繝峨′謖ソ蜈・縺輔l縺ヲ縺繧九°シ + if (nn::fs::IsSdmcInserted()) + { + // SD繧ォ繝シ繝峨↓譖ク縺崎セシ縺ソ縺ァ縺阪k縺具シ + if (!nn::fs::IsSdmcWritable()) + { + if (!s_SdWriteProetctAnnotation) + { + s_SdWriteProetctAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + operationMessage.push_back(::std::string("Can*t Write SD Card!!\n")); + break; + } + + // 辟。邱夊ィュ螳壹ヵ繧。繧、繝ォ縺後≠繧九°シ + if (common::ExistsAPSetting()) + { + // 譖ク縺崎セシ縺ソ荳ュ縺ォ謚懊°縺ェ縺繧医≧縺ォ + if (nextStep) + { + // 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ繧定ェュ縺ソ蜿悶l繧九°シ + if (!CanReadSerialNumber()) + { + common::PlaySound(common::SOUND_ANNOTATION); + COMMON_LOGGER("Can't Read Serial Number\n"); + } + } + } + else + { + error = true; + if (!s_ExistAPSettingAnnotation) + { + s_ExistAPSettingAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + operationMessage.push_back(::std::string("Accsess_Point_Setting does not exist!")); + } + } + else + { + error = true; + operationMessage.push_back(::std::string("Insert SD Card!!")); + } + } + else + { + error = true; + operationMessage.push_back(::std::string("Can't Read IVS!!")); + } + + // AC繧「繝繝励ち縺悟ソ隕√°シ + if (NeedsAcAdateper()) + { + error = true; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // 繧ィ繝ゥ繝シ縺檎┌縺代l縺ー騾イ陦檎畑繝。繝繧サ繝シ繧ク陦ィ遉コ + if(!error) + { + operationMessage.push_back(::std::string("Push A or START Button")); + if(!s_PlayedStartCursor) + { + common::PlaySound(common::SOUND_CURSOR); + s_PlayedStartCursor = true; + } + } + + if (nextStep && !error) + { + COMMON_LOGGER("Start Export Data\n"); + s_BackupState = EXPORT_TWL_SOUND; + } + } + break; + + // TWL繧オ繧ヲ繝ウ繝蛾伜沺縺ョ蜷ク蜃コ縺嶺クュ + case EXPORT_TWL_SOUND: + { + static bool init = true; + if(init) + { + // 繝繝シ繧ソ繧呈嶌縺崎セシ繧 + ExportTwlSoundData(); + init = false; + } + + // 蜃ヲ逅縺悟ョ御コ縺励◆ + if (IsExportFinished()) + { + FinalizeExportThread(); + s_BackupState = EXPORT_TWL_PHOTO; + } + } + break; + + // TWL蜀咏悄鬆伜沺縺ョ蜷ク蜃コ縺嶺クュ + case EXPORT_TWL_PHOTO: + { + static bool init = true; + if(init) + { + // 繝繝シ繧ソ繧呈嶌縺崎セシ繧 + ExportTwlPhotoData(); + init = false; + } + + // 蜃ヲ逅縺悟ョ御コ縺励◆ + if (IsExportFinished()) + { + FinalizeExportThread(); + s_BackupState = EXPORT_CTR_NAND; + } + } + break; + + // 蜷ク蜃コ縺嶺クュ + case EXPORT_CTR_NAND: + { + continueBackup = true; + + // AC繧「繝繝励ち縺悟ソ隕√°シ + if (NeedsAcAdateper()) + { + continueBackup = false; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // 繝繝シ繧ソ繧呈嶌縺崎セシ繧 + ExportData(); + + // 蜃ヲ逅縺悟ョ御コ縺励◆ + if (continueBackup && IsExportFinished()) + { + FinalizeExportThread(); + COMMON_LOGGER("Export NAND Data Finished.\n"); + + if(GetProgress() > 99) + { + s_BackupState = DELETE_NIM; + } + else + { + s_BackupState = FAIL; + } + + } + } + break; + + // nim縺ョ繧キ繧ケ繝繝繧サ繝シ繝悶ョ繝シ繧ソ蜑企勁 + case DELETE_NIM: + { + DeleteNimSaveData(); + s_BackupState = DONE; + } + break; + + // 蜷ク蜃コ縺怜ョ御コ + case DONE: + { + operationMessage.push_back(::std::string("Backup Done. Pull Out SD Card.")); + if(!s_PlayedSdPullOutCursor) + { + common::PlaySound(common::SOUND_CURSOR); + s_PlayedSdPullOutCursor = true; + } + } + break; + + // SD繧ォ繝シ繝画栢縺榊ョ御コ + case FINISHED: + { + operationMessage.push_back(::std::string("Backup Succeeded!!\n")); + if(!s_PlayedFinishedSound) + { + common::PlaySound(common::SOUND_OK); + s_PlayedFinishedSound = true; + } + } + break; + + // 蜷ク蜃コ縺怜、ア謨 + case FAIL: + { + operationMessage.push_back(::std::string("Backup Failed.")); + if(!s_PlayedFailSound) + { + common::PlaySound(common::SOUND_NG); + s_PlayedFailSound = true; + } + } + break; + + } +} + +bool InProgress() +{ + return s_BackupState == EXPORT_CTR_NAND; +} + +bool IsBackupSucceeded() +{ + return s_BackupState == FINISHED; +} + +bool IsBackupFailed() +{ + return s_BackupState == FAIL; +} + +void OnSdEjected() +{ + if(s_BackupState == DONE || s_BackupState == FINISHED) + { + s_BackupState = FINISHED; + } + else + { + common::InitializeFileCheck(); + InitializeState(); + } +} + +void InitializeState() +{ + s_BackupState = STARTUP; + s_PlayedFailSound = false; + s_PlayedFinishedSound = false; + s_ExistAPSettingAnnotation = false; + s_PlayedStartCursor = false; + s_PlayedSdPullOutCursor = false; + s_SdWriteProetctAnnotation = false; +} + +} // namespace ConsoleBackup diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Controller.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Controller.h new file mode 100644 index 0000000..d7f2cbf --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Controller.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Contoroller.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef CONTOROLLER_H_ +#define CONTOROLLER_H_ + +#include +#include + +namespace ConsoleBackup +{ + +void ControlState(::std::vector& operationMessage, bool& nextStep, bool& continueBackup); +bool InProgress(); +bool IsBackupSucceeded(); +bool IsBackupFailed(); +void OnSdEjected(); +void InitializeState(); + +} + +#endif /* CONTOROLLER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Exporter.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Exporter.cpp new file mode 100644 index 0000000..766650e --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Exporter.cpp @@ -0,0 +1,564 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Exporter.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include // cfg:nor縺ョ蛻晄悄蛹悶↓蠢隕 +#include +#include +#include +#include +#include + +#include "Exporter.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "ConsoleBackup.h" +#include "HeapManager.h" +#include "SdReaderWriter.h" +#include "FileName.h" +#include "FileTransfer.h" +#include "common_Types.h" +#include "Aes_define.h" +#include "PlayHistoryManager.h" +#include "VersionDetect.h" + +namespace ConsoleBackup +{ + +namespace +{ + +common::SdReaderWriter s_SdWriter; +common::NtrNorData s_NtrNorData; +common::CfgCountryLanguage s_CountryLanguage; + +::std::string s_SysSaveRoot; + +const size_t EXPORT_THREAD_STACK_SIZE = 0x4000; +nn::os::Thread s_ExportThread; +nn::os::StackBuffer s_ExportThreadStack; + +wchar_t s_RootName[256]; + +} + +void DeleteTrash(std::wstring currentDirectory) +{ + // TODO: 繝ェ繝シ繝峨が繝ウ繝ェ繝シ縺ョ繝輔ぃ繧、繝ォ縺梧カ亥悉縺ァ縺阪↑縺 + + COMMON_LOGGER("Delete Trash.\n"); + + nn::fs::FileInputStream fis; + nn::fs::Directory dir; + nn::Result result; + std::vector entryList; //繧ォ繝ャ繝ウ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ繧ィ繝ウ繝医Μ荳隕ァ繧呈シ邏 + std::vector::iterator entryIndex; + + common::SdMountManager::Mount(); + + result = dir.TryInitialize(currentDirectory.c_str()); + + if (result.IsSuccess()) + { + nn::fs::DirectoryEntry entry; + s32 numEntry; + for (;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + if (result.IsFailure()) + { + dir.Finalize(); + } + if (numEntry == 0) + { + // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ繧帝哩縺倥k + dir.Finalize(); + + // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ蟄舌r髢九¥ + for (entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++) + { + // 繝繧」繝ャ繧ッ繝医Μ縺ェ繧牙炎髯、縺吶k + if (entryIndex->attributes.isDirectory) + { + NN_LOG("Try Delete %ls%ls/\n", currentDirectory.c_str(), entryIndex->entryName); + result = nn::fs::TryDeleteDirectoryRecursively((currentDirectory + ::std::wstring( + entryIndex->entryName)).c_str()); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + } + // 繝輔ぃ繧、繝ォ縺ェ繧峨Ο繧ー縺ィAP險ュ螳壻サ・螟悶ッ蜑企勁縺吶k + else + { + if (std::wcscmp(entryIndex->entryName, common::AP_SETTING_FILENAME) != 0 && std::wcscmp( + entryIndex->entryName, common::LOG_FILENAME) != 0) + { + NN_LOG("Try Delete %ls%ls\n", currentDirectory.c_str(), entryIndex->entryName); + result = nn::fs::TryDeleteFile( + (currentDirectory + ::std::wstring(entryIndex->entryName)).c_str()); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + } + } + } + + // 蜑企勁螳御コ + break; + } + else + { + // vector縺ォ菫晏ュ倥☆繧 + entryList.push_back(entry); + if (entry.attributes.isDirectory) + { + NN_LOG("%ls%ls/\n", currentDirectory.c_str(), entry.entryName); + } + else + { + NN_LOG("%ls%ls\n", currentDirectory.c_str(), entry.entryName); + } + } + } + } + else + { + NN_LOG("failed initialize directory\n"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + dir.Finalize(); + } + + common::SdMountManager::Unmount(); +} + +void WriteRegionData() +{ + COMMON_LOGGER("Export Region Data.\n"); + + nn::cfg::CTR::CfgRegionCode region; + region = nn::cfg::CTR::GetRegion(); + + s_SdWriter.WriteBufWithCmac(common::REGION_DATA_PATHNAME, ®ion, sizeof(nn::cfg::CTR::CfgRegionCode)); +} + +void WriteCountryLanguageData() +{ + COMMON_LOGGER("Export Country and Language Data.\n"); + + nn::Result result; + + nn::cfg::nor::CTR::Initialize(); + + // 蝗ス險ュ螳 + s_CountryLanguage.country = nn::cfg::CTR::GetCountry(); + if (s_CountryLanguage.country != nn::cfg::CTR::CFG_COUNTRY_UNKNOWN) + { + // 險隱櫁ィュ螳 + s_CountryLanguage.language = nn::cfg::CTR::GetLanguage(); + + s_SdWriter.WriteBufWithCmac(common::COUNTRY_SETTING_PATHNAME, &s_CountryLanguage, sizeof(s_CountryLanguage)); + } +} + +void WriteNorData() +{ + COMMON_LOGGER("Export NOR Data.\n"); + + nn::Result result; + + nn::cfg::nor::CTR::Initialize(); + + NN_LOG("Get NTR User Setting\n"); + + // NTR險ュ螳 + result = nn::cfg::nor::CTR::GetNtrSetting(&s_NtrNorData.ntrConfig.ncd, &s_NtrNorData.ntrConfig.ncd_ex); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // TWL WiFi險ュ螳 + result = nn::cfg::nor::CTR::ReadTwlWifiSetting(0, s_NtrNorData.TwlWiFiSetting, common::TWL_WIFI_SETTING_SIZE); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // NTR WiFi險ュ螳 + result = nn::cfg::nor::CTR::ReadNtrWifiSetting(0, s_NtrNorData.NtrWiFiSetting, common::NTR_WIFI_SETTING_SIZE); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + s_SdWriter.WriteBufWithCmac(common::NOR_PATHNAME, &s_NtrNorData, sizeof(common::NtrNorData)); +} + +void WriteSerialNumber() +{ + COMMON_LOGGER("Export Serial Number.\n"); + + u8* serial; + size_t size; + GetSerialNumber(&serial, &size); + + s_SdWriter.WriteBufWithCmac(common::SERIAL_PATHNAME, serial, size); +} + +void WriteDeviceId() +{ + COMMON_LOGGER("Export Device ID.\n"); + + bit32 deviceId = GetDeviceId(); + + s_SdWriter.WriteBufWithCmac(common::DEVICE_ID_PATHNAME, &deviceId, sizeof(deviceId)); +} + +void WriteIvs() +{ + COMMON_LOGGER("Export IVS.\n"); + + void* ivs; + size_t size; + GetIvs(&ivs, &size); + + void* enc; + nn::Result result; + enc = common::HeapManager::GetHeap()->Allocate(size); + if(enc != NULL) + { + // AES證怜捷蛹悶☆繧 + nn::crypto::Initialize(); + + nn::crypto::SwAesCtrContext swAesCtrContest; + + swAesCtrContest.Initialize(common::iv, common::key, sizeof(common::key)); + swAesCtrContest.Encrypt(enc, ivs, size); + + s_SdWriter.WriteBufWithCmac(common::IVS_PATHNAME, enc, size); + + common::HeapManager::GetHeap()->Free(enc); + } +} + +// IVS縺九i繧サ繝シ繝悶ョ繝シ繧ソ繝繧」繝ャ繧ッ繝医Μ蜷阪r逕滓舌☆繧 +void GetSaveDataDirectoryRoot() +{ + nn::Result result; + using namespace nn::dbg; + + const size_t SEED_SIZE = 16; + bit8 hash[nn::crypto::Sha256Context::HASH_SIZE]; + const size_t SYS_SAVE_ROOT_LENGTH = 16; + char rootHash[SYS_SAVE_ROOT_LENGTH]; + char rootStr[SYS_SAVE_ROOT_LENGTH * 2 + 1]; + + void* addr; + size_t size; + GetIvs(&addr, &size); + + // 譛蠕後ョ16繝舌う繝医ョ繝上ャ繧キ繝・繧剃スソ縺 + nn::crypto::CalculateSha256(hash, &reinterpret_cast (addr)[size - SEED_SIZE], SEED_SIZE); + + for (u8 i = 0; i < SEED_SIZE / 4; i++) + { + for (u8 j = 0; j < SEED_SIZE / 4; j++) + { + rootHash[i * 4 + j] = hash[i * 4 + 3 - j]; + } + } + + // 蠕励i繧後◆繝上ャ繧キ繝・縺九i譁蟄怜励r逕滓 + for (s32 k = 0; k < SEED_SIZE; k++) + { + for (s32 i = 6; i < 8; ++i) + { + bit32 n = (rootHash[k] >> ((7 - i) * 4)) & 0xf; + NN_TASSERT_(n < 16); + rootStr[i - 6 + k * 2] = static_cast (n < 10 ? '0' + n : 'a' + (n - 10)); + } + } + rootStr[SYS_SAVE_ROOT_LENGTH * 2] = '\0'; + + // 繧サ繝シ繝悶ョ繝シ繧ソ繝繧」繝ャ繧ッ繝医Μ蜷阪r菫晏ュ倥☆繧 + s_SysSaveRoot = ::std::string(rootStr); + + NN_LOG("%s\n", s_SysSaveRoot.c_str()); +} + +void CreateTwlDirectory(enum common::TWL_PATH_INDEX path) +{ + NN_ASSERT(path < common::TWL_PATHNAME_MAX); + + s_SdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + + std::wstring(common::SD_TWL_ROOTNAME_TABLE[path])).c_str()); +} + +void WriteTwlData(enum common::TWL_PATH_INDEX path) +{ + NN_ASSERT(path < common::TWL_PATHNAME_MAX); + + nn::Result result; + + result = nn::fs::MountSpecialArchive(common::TWL_ARCHIVE_NAME_TABLE[path], common::TWL_FS_ARCHIVE_KIND[path]); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = common::SdMountManager::Mount(); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + u32 fileNum = 0; + u32 fileSize = 0; + common::CalculateFileNum(::std::wstring(common::NAND_TWL_ROOT_PATHNAME_WITH_SLASH_TABLE[path]), fileNum, fileSize); + + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + NN_LOG("File Number = %d\n", fileNum); + NN_LOG("File Size = %d\n", fileSize); + // 騾イ謐苓。ィ遉コ逕ィ + common::InitializeTransferProgress(fileSize); + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize, AES_BLOCK_SIZE); + if (buf != NULL) + { + wchar_t archiveName[256]; + ::std::mbstowcs(archiveName, common::TWL_ARCHIVE_NAME_TABLE[path], std::strlen(common::TWL_ARCHIVE_NAME_TABLE[path]) + 1); + std::wstring archiveString(archiveName); + common::CopyDirectory( + (archiveString + ::std::wstring(L"/")).c_str(), + (common::SDMC_ROOT_DIRECTORY_PATH + ::std::wstring(common::SD_TWL_ROOTNAME_TABLE[path])).c_str(), + buf, bufSize, true); + + common::HeapManager::GetHeap()->Free(buf); + } + + common::SdMountManager::Unmount(); + nn::fs::Unmount(common::TWL_ARCHIVE_NAME_TABLE[path]); + +} + +void WriteTwlPhotoData() +{ + COMMON_LOGGER("Export Twl Photo Data.\n"); + CreateTwlDirectory(common::TWL_PHOTO); + WriteTwlData(common::TWL_PHOTO); +} + +void WriteTwlSoundData() +{ + COMMON_LOGGER("Export Twl Sound Data.\n"); + CreateTwlDirectory(common::TWL_SOUND); + WriteTwlData(common::TWL_SOUND); +} + +void ExportTwlPhotoData() +{ + s_ExportThread.Start(WriteTwlPhotoData, s_ExportThreadStack); +} + +void ExportTwlSoundData() +{ + // 荳崎ヲ√↑繝繝シ繧ソ繧貞炎髯、縺吶k + DeleteTrash(common::SDMC_ROOT_DIRECTORY_PATH); + + s_ExportThread.Start(WriteTwlSoundData, s_ExportThreadStack); +} + + +void WriteMcuRtcData() +{ + COMMON_LOGGER("Export RTC Data.\n"); + nn::Result result; + nn::Handle handle = GetMcuHandle(); + + if(handle.IsValid()) + { + nn::mcu::CTR::HwCheck mcu(handle); + + nn::mcu::CTR::RtcData rtc; + result = mcu.GetRtcAll(&rtc); + NN_LOG("RTC = 20%02d/%02d/%02d %02d:%02d:%02d\n", rtc.m_Year, rtc.m_Month, rtc.m_Day, rtc.m_Hour, rtc.m_Minute, rtc.m_Second); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + s_SdWriter.WriteBufWithCmac(common::MCU_RTC_PATHNAME, &rtc, sizeof(rtc)); + } + else + { + NN_LOG("invalid handle\n"); + } +} + +void ExportThreadFunc() +{ + nn::Result result; + + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = common::SdMountManager::Mount(); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize, AES_BLOCK_SIZE); + if (buf != NULL) + { + + common::CopyDirectory( + (::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str(), + (common::SDMC_ROOT_DIRECTORY_PATH + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str(), + buf, bufSize, true); + + common::HeapManager::GetHeap()->Free(buf); + } + + common::SdMountManager::Unmount(); + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + NN_LOG("Export Thread Finalize\n"); +} + +nn::Result WriteSaveData() +{ + // NAND縺九iSD繧ォ繝シ繝峨↓譖ク縺榊コ縺 + nn::Result result; + + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + u32 fileNum = 0; + u32 fileSize = 0; + common::CalculateFileNum(::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH), fileNum, fileSize); + + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + NN_LOG("File Number = %d\n", fileNum); + NN_LOG("File Size = %d\n", fileSize); + // 騾イ謐苓。ィ遉コ逕ィ + common::InitializeTransferProgress(fileSize); + + ::std::mbstowcs(s_RootName, s_SysSaveRoot.c_str(), s_SysSaveRoot.size() + 1); + + NN_LOG("%ls\n", (::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str()); + + // 繧サ繝シ繝悶ョ繝シ繧ソ繝繧」繝ャ繧ッ繝医Μ莉・荳九ョ繝繝シ繧ソ繧担D繧ォ繝シ繝峨↓繧ウ繝斐シ + // 繧ウ繝斐シ逕ィ繝繧」繝ャ繧ッ繝医Μ菴懈 + s_SdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_SAVEDATA_ROOT_NAME)).c_str()); + s_SdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_SAVEDATA_ROOT_NAME) + ::std::wstring(s_RootName) + ::std::wstring(L"/")).c_str()); + + COMMON_LOGGER("Export NAND Data Start...\n"); + + // SD縺ォ繧ウ繝斐シ縺吶k縺溘a縺ョ繧ケ繝ャ繝繝峨ョ菴懈 + s_ExportThread.Start(ExportThreadFunc, s_ExportThreadStack); + + return result; +} + +void FinalizeExportThread() +{ + s_ExportThread.Join(); + s_ExportThread.Finalize(); +} + +void WriteVersionData() +{ + COMMON_LOGGER("Export Version Data.\n"); + + common::VerDef versionData; + GetVersionData(&versionData); + + s_SdWriter.WriteBufWithCmac(common::VERSION_DATA_PATHNAME, &versionData, sizeof(common::VerDef)); +} + +void WritePlayHistory() +{ + common::PlayHistoryManager historyManager; + + COMMON_LOGGER("Export PlayHistory\n"); + historyManager.Export(); +} + +void DeleteNimSaveData() +{ + nn::Result result; + ::std::wstring nimSaveDataPath = + ::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME) + + ::std::wstring(s_RootName) + + ::std::wstring(L"/") + + std::wstring(common::NIM_SAVEDATA_DIRECTORY_NAME); + + common::SdMountManager::Mount(); + + NN_LOG("%ls\n", nimSaveDataPath.c_str()); + result = nn::fs::TryDeleteDirectoryRecursively(nimSaveDataPath.c_str()); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + common::SdMountManager::Unmount(); +} + + +void ExportData() +{ + static bool init = true; + + if (init) + { + // 繝ェ繝シ繧ク繝ァ繝ウ繝繝シ繧ソ繧担D縺ォ譖ク縺崎セシ繧 + WriteRegionData(); + + // 蝗ス繝繝シ繧ソ縺ィ險隱槭ョ繝シ繧ソ繧担D縺ォ譖ク縺崎セシ繧 + WriteCountryLanguageData(); + + // NOR繝繝シ繧ソ繧担D繧ォ繝シ繝峨↓譖ク縺崎セシ繧 + WriteNorData(); + + // 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ繧担D繧ォ繝シ繝峨↓譖ク縺崎セシ繧 + WriteSerialNumber(); + + // 繝繝舌う繧ケID繧担D繧ォ繝シ繝峨↓譖ク縺崎セシ繧 + WriteDeviceId(); + + // 螳悟ィ諤ァ讀懆ィシSEED繧担D繧ォ繝シ繝峨↓譖ク縺崎セシ繧 + WriteIvs(); + + // IVS縺九i繧サ繝シ繝悶ョ繝シ繧ソ繝繧」繝ャ繧ッ繝医Μ蜷阪r險育ョ + GetSaveDataDirectoryRoot(); + + // 繝励Ξ繧、螻・豁エ繧担D縺ォ譖ク縺榊コ縺 + //WritePlayHistory(); + + // RTC繧担D縺ォ譖ク縺榊コ縺 + WriteMcuRtcData(); + + // 繝舌シ繧ク繝ァ繝ウ諠蝣ア繧担D縺ォ譖ク縺榊コ縺 + WriteVersionData(); + + // NAND縺ョ繧サ繝シ繝悶ョ繝シ繧ソ繧担D縺ォ譖ク縺榊コ縺 + WriteSaveData(); + + init = false; + } +} + +u32 GetProgress() +{ + return common::GetProgress(); +} + +bool IsExportFinished() +{ + return s_ExportThread.IsValid() && !s_ExportThread.IsAlive(); +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Exporter.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Exporter.h new file mode 100644 index 0000000..216a277 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/Exporter.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Exporter.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef EXPORTER_H_ +#define EXPORTER_H_ + +#include + +namespace ConsoleBackup +{ + +void ExportTwlPhotoData(); +void ExportTwlSoundData(); +void ExportData(); +void DeleteNimSaveData(); + +u32 GetProgress(); +bool IsExportFinished(); +void FinalizeExportThread(); + + +} + +#endif /* EXPORTER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/OMakefile b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/OMakefile new file mode 100644 index 0000000..b152d3d --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/OMakefile @@ -0,0 +1,84 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakefile +# +# 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. +# +# $Rev$ +#---------------------------------------------------------------------------- +SUPPORTED_TARGETS = CTR-T*.Process.MPCore.* +#MAKECSU = true +#INSTALL_SDK_TOOL = true +CTR_APPTYPE = BOTH +CTR_MAKE_DEVELOPMENT_IMAGE = true + +TARGET_PROGRAM = ConsoleBackup + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + ../common + +SOURCES[] = + ConsoleBackup.cpp + Controller.cpp + Exporter.cpp + ../common/HardwareInfo.cpp + ../common/DrawSystemState.cpp + ../common/FileTransfer.cpp + ../common/FileChecker.cpp + ../common/SdReaderWriter.cpp + ../common/HeapManager.cpp + ../common/SdLogger.cpp + ../common/wave.cpp + ../common/SimplePlayer.cpp + ../common/LogConsole.cpp + ../common/CommonLogger.cpp + ../common/SdMountManager.cpp + ../common/PlayHistoryManager.cpp + ../common/VersionDetect.cpp + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = ../common/romfiles + +LIBS += libnn_cfg \ + libnn_driversEeprom \ + libnn_driversi2c \ + libnn_driversCal \ + libnn_crypto \ + libnn_driversCodec \ + libnn_spi \ + libnn_gpio \ + libnn_pdn \ + libnn_mcu \ + libnn_i2c \ + libnn_driversCamera \ + libnn_ps \ + libnn_driversRsa \ + lib_demo \ + libnn_nwm \ + libnn_friends \ + libnn_nim \ + +INSTALL_SDK_TOOL = true + +ROM_SPEC_FILE = $(TARGET_PROGRAM).rsf +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/_private/RepairTool.desc + +include $(ROOT_OMAKE)/modulerules + +VERSION_H = $(file version.h) + +$(VERSION_H): $(SOURCES) + section + bash genversion.sh + +RequireSetup($(VERSION_H)) +build: $(VERSION_H) $(DEFAULT_TARGETS) diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/model.cbmd b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/model.cbmd differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/sound.cbsd b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/sound.cbsd differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/unknown24x24.ctpk b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +スススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススニススススススススススススススススススススススススススススススススススススススニ8ニ8ニ゙銷スス8ニススススス釡゙ニ鍄踟ススススススススススススススススススススススススススススススススススススススススススニススススススススススススススススススススススススススススススススススススススススススyホスyホスススススYホスススススススススススススススススススススススススススススススススス鍄゙yホYホスロ゙ロ゙ススニススロ゙yボスyホ轌ホ釡゙ススススYホ轌ホ銷スススススyホニロ゙鍄躡ホyホスススyホスコヨスススススyホスyホスススススYホスススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススyホ躡ホ銷スススススニスス轌ホ8ニススススニススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススス \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/unknown48x48.ctpk b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +スススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススYホススススススススススススススススススススススススススス8ニスス8ニ8ニスススコヨ8ニコヨ釡゙銷スススススススススス8ニ8ニススニススススススススススススススススス鍄逧ヨニ銷スス墮ス逧ヨ銷スススススススススススススススススススススススススススススススススススススススススス8ニススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススロ゙スロ゙ススススス銷ズスススススススススススススススススススススコヨスススススススススス鍄8ニ゙ロ゙スス墮スYホススススス躡ホyホ轌ホニススススススススニススススススススススススロ゙ロ゙釡゙踟スス躡ホ銷スススススロ゙スロ゙銷ススYボ墮釡゙コヨス墮スロ゙ススススス踟ス踟スススススススススススススススススススススロ゙スyホススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススYホス墮銷スロ゙スロ゙銷ススススススススススススススススス8ニススコヨロ゙スススススYホニyホ逧ヨ郤ヨスYホス觝ホススススススススススススススロ゙墮ススススススyホス鍄踟ススニスススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススス踟ス銷ズスYホ鍄銷ススススススススススススススススススススス8ニスススススススススス逧ヨスロ゙ス釡゙墮ススススススススススススススススススス8ニススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススス \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/genversion.sh b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/genversion.sh new file mode 100755 index 0000000..8fa6ee8 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleBackup/genversion.sh @@ -0,0 +1,4 @@ +#!/bin/bash -f + +cd ../ +echo "#define BACKUP_VERSION_NUM \"`svn info|grep 'Last Changed Rev:'| awk -F ':' '{print $2}'|tr -d '\n'| sed 's/ //g'`\"" > ./ConsoleBackup/version.h diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.bsf b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.bsf differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.cpp new file mode 100644 index 0000000..7e08570 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.cpp @@ -0,0 +1,469 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: ConsoleRestore.cpp + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "demo.h" + +#include +#include + +#include "ConsoleRestore.h" +#include "DrawSystemState.h" +#include "Controller.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "HeapManager.h" +#include "VersionDetect.h" +#include "HardwareInfo.h" + +// svn繝ェ繝薙ず繝ァ繝ウ蝓九a霎シ縺ソ逕ィ +#include "version.h" +#ifndef RESTORE_VERSION_NUM +#define RESOTRE_VERSION_NUM 0 +#endif + +namespace { + +// 繧ー繝ゥ繝輔ぅ繝繧ッ繧ケ縺ォ蜑イ繧雁ス薙※繧九Γ繝「繝ェ +const size_t s_GxHeapSize = 0x800000; + +demo::RenderSystemDrawing s_RenderSystem; +nn::Handle s_McuSession; + +// 繝舌ャ繝繝ェ谿矩 +u8 batteryRemain = 100; + +// 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ +u8 s_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + +// 繝繝舌う繧ケID +bit32 s_DeviceId; + +// 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ縺瑚ェュ繧√k縺九←縺縺 +bool s_CanReadSerialNumber = false; + +// IVS縺ク縺ョ繝昴う繝ウ繧ソ +void* sp_Ivs; + +size_t s_SizeofIvs; + +// IVS縺瑚ェュ繧√k縺九←縺縺 +bool s_CanReadIvs = false; + +// 繝舌シ繧ク繝ァ繝ウ諠蝣ア +common::VerDef s_VerData; + +} // namespace + +namespace ConsoleRestore{ + +bool IsAdapterConnected() +{ + return nn::ptm::CTR::GetAdapterState() == nn::ptm::CTR::ADAPTERSTATE_CONNECTED; +} + +bool IsBatteryLower() +{ + return batteryRemain <= 10; +} + +bool CanReadIVS() +{ + return s_CanReadIvs; +} + +bool CanReadSerialNumber() +{ + return s_CanReadSerialNumber; +} + +void GetSerialNumber(u8** serial, size_t* size) +{ + *serial = s_SerialNo; + *size = nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN; +} + +void GetIvs(void** ivs, size_t* size) +{ + *ivs = sp_Ivs; + *size = s_SizeofIvs; +} + +bit32 GetDeviceId() +{ + return s_DeviceId; +} + +void GetVersionData(common::VerDef* version) +{ + *version = s_VerData; +} + +void FinalizeAll() +{ + common::Logger::GetLoggerInstance()->Finalize(); + // 繧「繝ウ繝槭え繝ウ繝 + nn::fs::Unmount("nand:"); + nn::fs::Unmount("sdmc:"); + s_RenderSystem.Finalize(); + + nn::mcu::CTR::FinalizeHwCheck(&s_McuSession); + nn::friends::detail::Finalize(); + nn::ps::Finalize(); + nn::ptm::CTR::FinalizeForSystemMenu(); + nn::cfg::CTR::system::Finalize(); + nn::cfg::CTR::init::Finalize(); + nn::hid::Finalize(); + nn::fs::Finalize(); + + nn::applet::PrepareToCloseApplication(); + nn::applet::CloseApplication(); +} + +nn::Handle GetMcuHandle() +{ + return s_McuSession; +} + +extern "C" void nnMain(void) +{ + nn::Result result; + + // os 縺ョ蛻晄悄蛹 + nn::os::Initialize(); + + // fs 縺ョ蛻晄悄蛹 + nn::fs::Initialize(); + + // applet縺ョ蛻晄悄蛹 + nn::applet::Enable( false ); + + // hid 縺ョ蛻晄悄蛹 + result = nn::hid::Initialize(); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + + // ndm縺ョ蛻晄悄蛹 + result = nn::ndm::Initialize(); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + + // 繝繝シ繝「繝ウ縺ョ閾ェ蠕句虚菴懊r蛛懈ュ「 + result = nn::ndm::Suspend(nn::ndm::DN_CEC); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + result = nn::ndm::Suspend(nn::ndm::DN_BOSS); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + result = nn::ndm::Suspend(nn::ndm::DN_FRIENDS); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + result = nn::ndm::Suspend(nn::ndm::DN_NIM); + NN_ERR_THROW_FATAL_IF_FATAL_ONLY(result); + + // cfg 縺ョ蛻晄悄蛹 + nn::cfg::CTR::init::Initialize(); + nn::cfg::CTR::system::Initialize(); + + // 譎りィ郁ィュ螳夂畑ptm蛻晄悄蛹 + nn::ptm::CTR::InitializeForSystemMenu(); + + // ps 縺ョ蛻晄悄蛹 + nn::ps::Initialize(); + + // friends縺ョ蛻晄悄蛹 + result = nn::friends::detail::Initialize(); + + // mcu縺ョ蛻晄悄蛹 + nn::mcu::CTR::InitializeHwCheck(&s_McuSession); + nn::mcu::CTR::HwCheck mcu(s_McuSession); + + // am縺ョ蛻晄悄蛹 + nn::am::InitializeForSystemMenu(); + + // 繝偵シ繝励ョ遒コ菫 + common::HeapManager::GetHeap()->Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + // RenderSystem 縺ョ貅門y + uptr heapForGx = reinterpret_cast(common::HeapManager::GetHeap()->Allocate(s_GxHeapSize)); + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + + // 繧オ繧ヲ繝ウ繝峨せ繝ャ繝繝峨ョ襍キ蜍 + common::InitializeSimplePlayer(); + + // 繝ュ繧ー謠冗判縺ョ蛻晄悄蛹 + common::Logger::GetLoggerInstance()->Initialize(CONSOLE_WIDTH, CONSOLE_HEIGHT, CONSOLE_MAX_LINE, &s_RenderSystem); + + // RenderSystem繧剃ス懊▲縺ヲ縺九i繝ュ繧ー縺悟コ縺帙k + common::Logger::InitializeEjectThread(); + common::Logger::SetEjectHandler(OnSdEjected); + COMMON_LOGGER("\n"); + COMMON_LOGGER("CTR Console Restore start\n"); + + // 繝懊ち繝ウ蜈・蜉 + nn::hid::PadReader s_PadReader; + nn::hid::PadStatus padStatus; + + // 繝繝シ繧ソ縺ョ貅門y + + // 螳悟ィ諤ァ讀懆ィシSEED縺ョ蜿門セ + result = nn::fs::MountSpecialArchive("nand:", nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if (result.IsSuccess()) + { + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(L"nand:/private/movable.sed"); + if (result.IsSuccess()) + { + s64 fileSize = fis.GetSize(); + s32 ret; + void* addr = NULL; + addr = common::HeapManager::GetHeap()->Allocate(fileSize); + if (addr != NULL) + { + sp_Ivs = addr; + s_SizeofIvs = fileSize; + result = fis.TryRead(&ret, addr, fileSize); + if (result.IsSuccess()) + { + s_CanReadIvs = true; + } + } + } + fis.Finalize(); + } + // 荳譌ヲ繧「繝ウ繝槭え繝ウ繝医@縺ヲ縺翫¥ + nn::fs::Unmount("nand:"); + + // 繝ェ繝シ繧ク繝ァ繝ウ縺ョ蜿門セ + nn::cfg::CTR::CfgRegionCode region; + region = nn::cfg::CTR::GetRegion(); + + // 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ縺ョ蜿門セ + std::memset(s_SerialNo, '\0', + nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN); + result = nn::cfg::CTR::system::GetSerialNo(s_SerialNo); + common::HardwareInfo hwInfo; + hwInfo.AddCheckDigit(reinterpret_cast(s_SerialNo)); + if(result.IsSuccess()) + { + s_CanReadSerialNumber = true; + } + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // 繝繝舌う繧ケID縺ョ蜿門セ + result = nn::ps::CTR::GetDeviceId(&s_DeviceId); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + bit64 infraDeviceId; + result = nn::nim::CTR::InitializeForShop(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + result = nn::nim::CTR::Shop::GetInfraDeviceId(s_DeviceId, &infraDeviceId); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + result = nn::nim::CTR::FinalizeForShop(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // MAC繧「繝峨Ξ繧ケ縺ョ蜿門セ + nn::nwm::Mac mac; + char8 macAddress[nn::nwm::Mac::MAC_STRING_SIZE]; + + result = nn::nwm::GetMacAddress(mac); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + mac.GetString(macAddress); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // 繝輔Ξ繝ウ繝峨さ繝シ繝峨ョ蜿門セ + nn::friends::CTR::FriendKey friendKey; + result = nn::friends::CTR::GetMyFriendKey(&friendKey); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + u64 friendCode = nn::friends::CTR::FriendKeyToFriendCode(friendKey); + + // 繝舌シ繧ク繝ァ繝ウ縺ョ蜿門セ + common::GetSystemVersion(&s_VerData, region); + + // 諠蝣ア蜃コ蜉 + COMMON_LOGGER("CTR Console Restore %s Rev.%s\n", __DATE__, RESTORE_VERSION_NUM); + COMMON_LOGGER("System Ver. %d.%d.%d-%d\n", s_VerData.cup.majorVersion, s_VerData.cup.minorVersion, s_VerData.cup.microVersion, + s_VerData.nup.majorVersion); + COMMON_LOGGER("System Region %s\n", nn::cfg::CTR::GetRegionCodeA3(region)); + COMMON_LOGGER("Serial Number %s\n", s_SerialNo); + COMMON_LOGGER("Device ID %llu\n", infraDeviceId); + COMMON_LOGGER("MAC Address %s\n", macAddress); + COMMON_LOGGER("Friend Code %04u-%04u-%04u\n", + static_cast(friendCode / 100000000ULL % 10000ULL), + static_cast(friendCode / 10000ULL % 10000ULL), + static_cast(friendCode % 10000ULL) ); + + + bool flip = false; + bool continueRestore = false; + + for(;;) + { + bool nextStep = false; + + s_PadReader.ReadLatest(&padStatus); + + // A縺セ縺溘ッSTART繝懊ち繝ウ縺ァ騾イ陦 + if(padStatus.trigger & nn::hid::BUTTON_A || + padStatus.trigger & nn::hid::BUTTON_START) + { + nextStep = true; + } + + // L縺セ縺溘ッR繝懊ち繝ウ縺ァ荳贋ク狗判髱「繝輔Μ繝繝 + if(padStatus.trigger & nn::hid::BUTTON_R || + padStatus.trigger & nn::hid::BUTTON_L) + { + flip = !flip; + } + + // 繧ウ繝ウ繧ス繝シ繝ォ繧ケ繧ッ繝ュ繝シ繝ォ + if(padStatus.hold & nn::hid::BUTTON_UP) + { + common::Logger::GetLoggerInstance()->ScrollUp(); + } + + // 繧ウ繝ウ繧ス繝シ繝ォ繧ケ繧ッ繝ュ繝シ繝ォ + if(padStatus.hold & nn::hid::BUTTON_DOWN) + { + common::Logger::GetLoggerInstance()->ScrollDown(); + } + + if(padStatus.hold & nn::hid::BUTTON_LEFT) + { + common::Logger::GetLoggerInstance()->ScrollToBegin(); + } + + if(padStatus.hold & nn::hid::BUTTON_RIGHT) + { + common::Logger::GetLoggerInstance()->ScrollToEnd(); + } + + // 諠蝣ア譖エ譁ー + // 繝舌ャ繝繝ェ + mcu.GetBatteryRemain(&batteryRemain); + // AC繧「繝繝励ち + std::string adapterState; + if(IsAdapterConnected()) + { + adapterState += ::std::string("Connected"); + } + else + { + adapterState += ::std::string("Not Connected"); + } + + // 謫堺ス懃畑繝。繝繧サ繝シ繧ク + // 騾イ謐礼「コ隱阪Γ繝繧サ繝シ繧ク繧貞シ縺ュ繧具シ + ::std::vector operationMessage; + + ControlState(operationMessage, nextStep, continueRestore); + + nn::util::FloatColor titleColor; + + if(GetRestoreMode() == RESTORE_MODE_RESTORE) + { + titleColor.r = 0.1f; + titleColor.g = 0.25f; + titleColor.b = 0.1f; + } + else if(GetRestoreMode() == RESTORE_MODE_NUP_ONLY) + { + titleColor.r = 0.35f; + titleColor.g = 0.35f; + titleColor.b = 0.f; + } + + // 荳顔判髱「陦ィ遉コ + common::DrawSystemState("CTR Console Restore", + s_RenderSystem, + titleColor, + flip, + adapterState, + RESTORE_VERSION_NUM, + &s_VerData, + batteryRemain, + infraDeviceId, + friendCode, + GetProgress(), + macAddress, + operationMessage, + region, + s_SerialNo + ); + + if (GetRestoreMode() == RESTORE_MODE_NUP_ONLY) + { + const u8 spaceSize = 10; + const u8 lineBottom = 23; + const u32 screenWidth = 400; + + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + s_RenderSystem.DrawText(0, lineBottom * spaceSize, "NUP-Only Mode"); + s_RenderSystem.SetColor(titleColor.r, titleColor.g, titleColor.b); + s_RenderSystem.FillRectangle(0, lineBottom * spaceSize, screenWidth, spaceSize); + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + } + + s_RenderSystem.SwapBuffers(); + + // 繝繝輔か繝ォ繝医〒荳狗判髱「縺ォ謠冗判縺吶k繧ゅョ + s_RenderSystem.SetRenderTarget(common::GetRenderTarget(NN_GX_DISPLAY1, flip)); + if(IsRestoreSucceeded()) + { + s_RenderSystem.SetClearColor(common::GetRenderTarget(NN_GX_DISPLAY1, flip), SUCCESS_COLOR); + } + else if(IsRestoreFailed()) + { + s_RenderSystem.SetClearColor(common::GetRenderTarget(NN_GX_DISPLAY1, flip), FAIL_COLOR); + } + else + { + s_RenderSystem.SetClearColor(common::GetRenderTarget(NN_GX_DISPLAY1, flip), NORMAL_COLOR); + } + s_RenderSystem.Clear(); + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + + common::Logger::GetLoggerInstance()->DrawConsole(); + s_RenderSystem.SwapBuffers(); + + + s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); + + // 髮サ貅宣聞謚シ縺励〒邨ゆコ + if ( nn::applet::IsExpectedToCloseApplication()) + { + FinalizeAll(); + } + } +} + + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.h new file mode 100644 index 0000000..ae779d2 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ConsoleRestore.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef NN_CONSOLERESTORE_H_ +#define NN_CONSOLERESTORE_H_ + +#include +#include "VersionDetect.h" + +namespace ConsoleRestore +{ + +bool IsAdapterConnected(); +bool IsBatteryLower(); +bool CanReadIVS(); +bool CanReadSerialNumber(); +void GetSerialNumber(u8** serial, size_t* size); +void GetIvs(void** ivs, size_t* size); +nn::Handle GetMcuHandle(); +void GetVersionData(common::VerDef* version); +bit32 GetDeviceId(); + +void FinalizeAll(); + +const u32 CONSOLE_WIDTH = 38; +const u32 CONSOLE_HEIGHT = 24; +const u32 CONSOLE_MAX_LINE = 1000; + +} + +// 謠冗判濶イ縺ョ螳夂セゥ +#define WHITE_COLOR 1.f, 1.f, 1.f, 1.f +#define GRAY_COLOR 0.5, 0.5, 0.5, 1.f +#define RED_COLOR 1.f, 0.f, 0.f, 1.f +#define GREEN_COLOR 0.f, 1.f, 0.f, 1.f +#define BLUE_COLOR 0.f, 0.f, 1.f, 1.f +#define SUCCESS_COLOR 0.f, 0.6f,0.f, 1.f +#define FAIL_COLOR 0.6f, 0.f,0.f, 1.f +#define NORMAL_COLOR 0.f, 0.f, 0.f, 1.f + +/* NN_CONSOLERESTORE_H_ */ +#endif diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.rsf b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.rsf new file mode 100644 index 0000000..be9685f --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/ConsoleRestore.rsf @@ -0,0 +1,52 @@ +BasicInfo: + Title : ConsoleRestore + ProductCode: ConsoleRestore + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xf8022 + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 0x4000 + Dependency : + - gpio + - pdn + - spi + - i2c + - mcu + - ptm + - codec + - cfg + - hid + - gsp + - friends + - nim + - ac + - ndm + +AccessControlInfo: + Priority : 16 + DisableDebug : true + + FileSystemAccess: + - DirectSdmc + - Debug + - Core + - CategoryFileSystemTool + + IoAccessControl: + - FsMountCardSpi + - FsMountNand + - FsMountTwln + +Option: + FreeProductCode: true + + +Rom: + # ROM 縺ォ蜷ォ繧√k繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ョ繝ォ繝シ繝医ヱ繧ケ繧呈欠螳壹@縺セ縺吶 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Controller.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Controller.cpp new file mode 100644 index 0000000..b456d5c --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Controller.cpp @@ -0,0 +1,940 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Controller.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Controller.h" +#include "FileChecker.h" +#include "ConsoleRestore.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" +#include "Importer.h" +#include "Updater.h" +#include "NtpClient.h" + +namespace ConsoleRestore +{ + +namespace +{ + +typedef enum RestoreState +{ + STARTUP, // 蛻晄悄蛟、 + SERIAL_IS_NOT_IN_SD, // 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ繝輔ぃ繧、繝ォ縺郡D繧ォ繝シ繝峨↓縺ェ縺縺薙→繧定。ィ遉コ + SERIAL_IN_SD, // 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ縺ョ諠蝣ア繧定。ィ遉コ + UPDATE_IN_PROGRESS, // 繧「繝繝励ョ繝シ繝井クュ + UPDATE_DONE, // 繧「繝繝励ョ繝シ繝亥ョ御コ + NUP_ONLY_WAIT_SD_EJECT, // NUP_ONLY繝「繝シ繝峨〒SD繧ォ繝シ繝画栢縺榊セ縺。 + NUP_ONLY_WAIT_NEXT, // NUP_ONLY繝「繝シ繝峨〒繧ュ繝シ蜈・蜉帛セ縺。 + RESTORE_TWL_SOUND, // TWL繧オ繧ヲ繝ウ繝峨ョ譖ク縺崎セシ縺ソ荳ュ + RESTORE_TWL_PHOTO, // TWL蜀咏悄縺ョ譖ク縺崎セシ縺ソ荳ュ + RESTORE_IN_PROGRESS, // 譖ク縺崎セシ縺ソ荳ュ + POST_RESTORE, // 譖ク縺崎セシ縺ソ蠕後ョ蜃ヲ逅 + RESTORE_DONE, // 譖ク縺崎セシ縺ソ螳御コ + REBOOTING, // 蜀崎オキ蜍輔r陦後≧ + ERASE, // 蜑企勁蜃ヲ逅繧定。後≧ + HISTORY_RECOVER, // 繝励Ξ繧、螻・豁エ縺ョ譖ク縺肴綾縺励r陦後≧ + TIME_ADJUST, // 譎りィ医≠繧上○繧定。後≧ + WAIT_SD_EJECT, // SD繧ォ繝シ繝峨〓縺榊セ縺。 + ALL_DONE, // 縺吶∋縺ヲ螳御コ + SHUTDOWN, //縲繧キ繝」繝繝医ム繧ヲ繝ウ荳ュ + FAIL // 螟ア謨 +} RestoreState; + +// Restore迥カ諷狗ョ。逅 +RestoreState s_RestoreState = STARTUP; +// Restore繝「繝シ繝臥ョ。逅 +RestoreMode s_RestoreMode = RESTORE_MODE_RESTORE; + +// 繧、繝ウ繧ソ繝シ繝阪ャ繝郁ィュ螳壹r隱ュ繧薙□縺九←縺縺 +bool s_ReadSettingDone = false; +// 繧、繝ウ繧ソ繝シ繝阪ャ繝郁ィュ螳壹r隱ュ繧薙□邨先棡 +bool s_ReadSettingSuccess = false; +// NUP蟆ら畑繝「繝シ繝峨°縺ゥ縺縺 +bool s_NupOnlyMode = false; + +// APSetting縺ョ譖ク蠑上′辟。縺隴ヲ蜻翫し繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_ExistAPSettingAnnotation = false; +// APSetting縺ョ譖ク蠑上′驕輔▲縺ヲ縺繧玖ュヲ蜻翫し繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_APSettingAnnotation = false; +// 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ縺後↑縺隴ヲ蜻翫し繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_SerialNumberAnnotation = false; +// 螟ア謨励し繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_PlayedFailSound = false; +// 謫堺ス憺幕蟋九し繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_PlayedStartCursor = false; +// 繝ェ繝悶シ繝磯幕蟋句燕繧オ繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_PlayedRebootCursor = false; +// SD謚懊″蜃コ縺怜燕繧オ繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_PlayedSdPullOutCursor = false; +// 繝舌シ繧ク繝ァ繝ウ繝繝シ繧ソ縺檎┌縺隴ヲ蜻翫し繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_ExistsVersionDataAnnotation = false; +// 繝舌シ繧ク繝ァ繝ウ繝繝シ繧ソ繧定ェュ繧薙□縺九←縺縺 +bool s_ReadVersionDone = false; +// 繝舌シ繧ク繝ァ繝ウ繝繝シ繧ソ繧定ェュ繧薙□邨先棡 +nn::Result s_ReadVersionResult = nn::ResultSuccess(); +// SD縺ォ譖ク縺崎セシ縺ソ縺ァ縺阪↑縺隴ヲ蜻翫し繧ヲ繝ウ繝峨r魑エ繧峨@縺溘°縺ゥ縺縺 +bool s_SdWriteProetctAnnotation = false; + +// 繝阪ャ繝医Ρ繝シ繧ッ繧「繝繝励ョ繝シ繝医r髢句ァ九@縺溘°縺ゥ縺縺 +bool s_ExecuteFgNup = false; +// FGNUP繧剃ス募屓繝ェ繝医Λ繧、縺励◆縺 +u32 s_FgNupRetryCount = 0; + + +} // namespace + +bool NeedsAcAdater() +{ + return IsBatteryLower() && !IsAdapterConnected(); +} + +bool CheckAndReadAPSetting(::std::vector& operationMessage) +{ + using namespace common; + + if (!ExistsAPSetting()) + { + if(!s_ExistAPSettingAnnotation) + { + s_ExistAPSettingAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + operationMessage.push_back(::std::string("Accsess_Point_Setting does not exist!")); + return false; + } + + // 險ュ螳壹ヵ繧。繧、繝ォ縺九iAP險ュ螳壹r隱ュ縺ソ霎シ繧 + if (!s_ReadSettingDone) + { + s_ReadSettingDone = true; + s_ReadSettingSuccess = ReadSetting(&s_NupOnlyMode); + } + + if(s_NupOnlyMode) + { + s_RestoreMode = RESTORE_MODE_NUP_ONLY; + } + + if (!s_ReadSettingSuccess) + { + operationMessage.push_back(::std::string("Invalid Accsess_Point_Setting format!")); + if(!s_APSettingAnnotation) + { + s_APSettingAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + + } + + return s_ReadSettingSuccess; +} + +nn::Result CheckAndReadVersionData(::std::vector& operationMessage) +{ + using namespace common; + + if (!ExistsVersionData()) + { + if(!s_ExistsVersionDataAnnotation) + { + s_ExistsVersionDataAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + operationMessage.push_back(::std::string("Version Data does not exist!")); + return nn::Result(nn::Result::LEVEL_PERMANENT, nn::Result::SUMMARY_NOT_FOUND, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_NOT_FOUND); + } + + // 繝舌シ繧ク繝ァ繝ウ諠蝣ア繝輔ぃ繧、繝ォ繧定ェュ縺ソ霎シ繧 + if (!s_ReadVersionDone) + { + s_ReadVersionDone = true; + s_ReadVersionResult = ReadVersionData(); + } + + return s_ReadVersionResult; +} + +void PutAliveMessage(::std::vector& operationMessage, const char* str) +{ + std::string message = std::string(str); + static u8 i = 0; + if (i < 0xff / 4) + { + operationMessage.push_back(message + std::string(" /")); + } + else if (i < 0xff * 2 / 4) + { + operationMessage.push_back(message + std::string(" |")); + } + else if (i < 0xff * 3 / 4) + { + operationMessage.push_back(message + std::string(" \\")); + } + else + { + operationMessage.push_back(message + std::string(" -")); + } + i += 4; +} + +nn::Result ExecSyncMcuRtc() +{ + nn::Result result = nn::ResultSuccess(); + if(!common::ExistsRtcSyncFinishedFile()) + { + result = ImportMcuRtc(); + if(result.IsSuccess()) + { + // RTC繧貞酔譛溷ョ御コ繝輔ぃ繧、繝ォ繧剃ス懊k + CreateRtcSyncFinishedFile(); + } + } + + return result; +} + +// Zero NUP髯仙ョ壹さ繝シ繝 +bool NeedsNup() +{ + if(AlreadyExecutedNup() || s_NupOnlyMode) + { + return !common::ExistsUpdateCheckedFile(); + } + else + { + return false; + } +} + +void ControlState(::std::vector& operationMessage, bool& nextStep, bool& continueRestore) +{ + using namespace common; + nn::Result result; + + // 迥カ諷矩キ遘サController + switch (s_RestoreState) + { + // 襍キ蜍墓凾 + case STARTUP: + { + bool error = false; + bool needsUpdate = false; + bool needsErase = false; + bool validApSetting = false; + + // SD繧ォ繝シ繝峨′謖ソ蜈・縺輔l縺ヲ縺繧九°シ + if (nn::fs::IsSdmcInserted()) + { + // SD繧ォ繝シ繝峨↓譖ク縺崎セシ縺ソ縺ァ縺阪k縺具シ + if (!nn::fs::IsSdmcWritable()) + { + if (!s_SdWriteProetctAnnotation) + { + s_SdWriteProetctAnnotation = true; + PlaySound(SOUND_ANNOTATION); + } + operationMessage.push_back(::std::string("Can*t Write SD Card!!\n")); + break; + } + + result = CheckAndReadVersionData(operationMessage); + if(result.IsFailure()) + { + // 繝舌シ繧ク繝ァ繝ウ諠蝣ア縺ョ蜿門セ励↓螟ア謨 + error = true; + s_RestoreState = FAIL; + } + + validApSetting = CheckAndReadAPSetting(operationMessage); + if (!validApSetting) + { + error = true; + } + else + { + // NUP縺悟ソ隕√°シ + if (!NeedsNup()) + { + if (s_NupOnlyMode) + { + s_RestoreState = NUP_ONLY_WAIT_SD_EJECT; + + // 繝ェ繧ケ繝医い迥カ諷九メ繧ァ繝繧ッ繝輔ぃ繧、繝ォ繧偵☆縺ケ縺ヲ蜑企勁 + DeleteAllCheckFiles(); + + break; + } + + // SD繧ォ繝シ繝峨↓譖ク縺崎セシ縺ソ螳御コ繝輔ぃ繧、繝ォ縺後≠繧九°シ + if (!ExistsWriteFinishedFile()) + { + // IVS繧定ェュ繧√k縺具シ + if (CanReadIVS()) + { + // 譛ャ菴灘晄悄蛹門ョ御コ繝輔ぃ繧、繝ォ縺後≠繧九°シ + if (ExistsConsoleInitializedFile()) + { + // SD繧ォ繝シ繝峨↓繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ縺後≠繧九°シ + if (!ExistsSerialNumberFile()) + { + COMMON_LOGGER("Can't Read Serial Number in SD Card!!\n"); + error = true; + s_RestoreState = SERIAL_IS_NOT_IN_SD; + } + else + { + u8 serial[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + result = ReadSerialNumber(serial); + if(result.IsSuccess()) + { + ::std::string serialStr(reinterpret_cast (serial)); + operationMessage.push_back(::std::string("Serial Number in SD : ") + serialStr); + } + else + { + error = true; + s_RestoreState = FAIL; + } + } + + + // SD繧ォ繝シ繝峨↓繝ェ繝シ繧ク繝ァ繝ウ繝繝シ繧ソ縺後≠繧九°シ + if (ExistsRegionData()) + { + // 繝ェ繝シ繧ク繝ァ繝ウ繝繝シ繧ソ縺ッ荳閾エ縺励※縺繧九°シ + if (EqualsRegionDataandRegion().IsFailure()) + { + COMMON_LOGGER("Current Region and Region in SD differ!!\n"); + error = true; + s_RestoreState = FAIL; + } + } + else + { + // 遘サ陦御ク崎ス縺ェ縺ョ縺ァFAIL + COMMON_LOGGER("Can't Read Region in SD Card!!\n"); + error = true; + s_RestoreState = FAIL; + } + + } + else + { + if (!ExistsIVSFile()) + { + // 遘サ陦御ク崎ス縺ェ縺ョ縺ァFAIL + COMMON_LOGGER("Can't Read IVS in SD Card!!\n"); + error = true; + s_RestoreState = FAIL; + } + else + { + COMMON_LOGGER("Initialize Console\n"); + + // 譛ャ菴灘晄悄蛹門ョ御コ繝輔ぃ繧、繝ォ繧剃ス懊k + CreateConsoleInitializedFile(); + + // 繝輔ぃ繧、繝ォ繧キ繧ケ繝繝縺ョ蛻晄悄蛹悶r陦後≧ + InitializeFileSystem(); + error = true; + s_RestoreState = REBOOTING; + } + } + } + else + { + error = true; + operationMessage.push_back(::std::string("Can't Read IVS!!")); + } + } + else + { + if (validApSetting) + { + // 蜑企勁蜃ヲ逅繧定。後≧ + needsErase = true; + } + } + } + else + { + if (validApSetting) + { + // 繝阪ャ繝医Ρ繝シ繧ッ繧「繝繝励ョ繝シ繝医r陦後≧ + needsUpdate = true; + } + } + + } + } + else + { + error = true; + operationMessage.push_back(::std::string("Insert SD Card!!")); + } + + // AC繧「繝繝励ち縺悟ソ隕√°シ + if (NeedsAcAdater()) + { + error = true; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // 繧ィ繝ゥ繝シ縺檎┌縺代l縺ー騾イ陦檎畑繝。繝繧サ繝シ繧ク陦ィ遉コ + if (!error) + { + operationMessage.push_back(::std::string("Push A or START Button")); + if(needsUpdate) + { + operationMessage.push_back(::std::string("Network Update Mode")); + } + else if(needsErase) + { + operationMessage.push_back(::std::string("Clock Sync Mode")); + } + else + { + operationMessage.push_back(::std::string("Import Data Mode")); + } + + if(!s_PlayedStartCursor) + { + PlaySound(SOUND_CURSOR); + s_PlayedStartCursor = true; + } + } + + if (nextStep && !error) + { + if (needsUpdate) + { + COMMON_LOGGER("Start Network Update\n"); + s_RestoreState = UPDATE_IN_PROGRESS; + } + else if(needsErase) + { + COMMON_LOGGER("Erase Trash\n"); + s_RestoreState = ERASE; + } + else + { + COMMON_LOGGER("Start Import Data\n"); + // Zero NUP髯仙ョ + // RTC蜷梧悄繧定。後≧ + // NUP縺輔l縺ェ縺蝣エ蜷医′縺ゅk縺ョ縺ァ縺薙%縺ァ蜷梧悄 + result = ExecSyncMcuRtc(); + if(result <= nn::fs::ResultVerificationFailed()) + { + s_RestoreState = FAIL; + } + else + { + s_RestoreState = RESTORE_TWL_SOUND; + } + } + } + } + break; + + // 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ縺郡D繧ォ繝シ繝峨↓縺ェ縺縺薙→隴ヲ蜻 + case SERIAL_IS_NOT_IN_SD: + { + operationMessage.push_back(::std::string("Serial Number Is Not In SD Card")); + operationMessage.push_back(::std::string("Push A or START Button")); + operationMessage.push_back(::std::string("Import Data Mode")); + + if (!s_SerialNumberAnnotation) + { + s_SerialNumberAnnotation = true; + PlaySound(SOUND_ANNOTATION); + } + + if (nextStep) + { + s_RestoreState = RESTORE_TWL_SOUND; + } + } + break; + + // 繧「繝繝励ョ繝シ繝井クュ + case UPDATE_IN_PROGRESS: + { + continueRestore = true; + + // AC繧「繝繝励ち縺悟ソ隕√°シ + if (NeedsAcAdater()) + { + continueRestore = false; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // 繧「繝繝励ョ繝シ繝医r陦後≧ + if(!s_ExecuteFgNup) + { + if(ImportCountryLanguageData().IsSuccess()) + { + StartFGNetworkUpdate(); + s_ExecuteFgNup = true; + } + else + { + s_RestoreState = FAIL; + } + } + + // 蜍輔>縺ヲ縺繧九%縺ィ繧定。ィ遉コ + { + PutAliveMessage(operationMessage, "Updating"); + } + + + if (IsNetworkUpdateFinished()) + { + FinishFGNetworkUpdate(); + // 繧ィ繝ゥ繝シ縺後≠縺」縺溘i陦ィ遉コ縺吶k + if(GetUpdateResult().IsFailure()) + { + // AP縺瑚ヲ九▽縺九i縺ェ縺 + if(GetUpdateResult() == nn::ac::ResultNotFoundAccessPoint()) + { + COMMON_LOGGER("No Access Point Found!"); + } + } + + if (GetUpdateResult().IsSuccess()) + { + COMMON_LOGGER("Network Update Finished.\n"); + // 繧「繝繝励ョ繝シ繝亥ョ御コ繝輔ぃ繧、繝ォ繧剃ス懈 + CreateUpdateFinishedFile(); + + s_RestoreState = UPDATE_DONE; + + } + else + { + if (s_FgNupRetryCount++ < RETRY_MAX) + { + // 繧ィ繝ゥ繝シ縺ョ縺溘a繧繧顔峩縺 + COMMON_LOGGER_RESULT_IF_FAILED(GetUpdateResult()); + COMMON_LOGGER("Network Update Failed. Retrying... %d\n", s_FgNupRetryCount); + + // FGNUP逕ィ縺ョ繧ケ繝ャ繝繝峨r菴懊k縺ィ縺薙°繧峨d繧顔峩縺 + s_ExecuteFgNup = false; + } + else + { + s_RestoreState = FAIL; + } + } + + } + } + break; + + // 繧「繝繝励ョ繝シ繝亥ョ御コ + case UPDATE_DONE: + { + operationMessage.push_back(::std::string("Network Update Done.")); + operationMessage.push_back(::std::string("Press A or START Button to Reboot")); + + if(!s_PlayedRebootCursor) + { + PlaySound(SOUND_CURSOR); + s_PlayedRebootCursor = true; + } + + if (nextStep) + { + s_RestoreState = REBOOTING; + } + } + break; + + + // TWL繧オ繧ヲ繝ウ繝蛾伜沺縺ョ譖ク縺崎セシ縺ソ荳ュ + case RESTORE_TWL_SOUND: + { + static bool init = true; + if (init) + { + // 繝繝シ繧ソ繧呈嶌縺崎セシ繧 + ImportTwlSoundData(); + init = false; + } + + // 蜃ヲ逅縺悟ョ御コ縺励◆ + if (IsImportFinished()) + { + FinalizeImportThread(); + s_RestoreState = RESTORE_TWL_PHOTO; + } + } + break; + + // TWL蜀咏悄鬆伜沺縺ョ譖ク縺崎セシ縺ソ + case RESTORE_TWL_PHOTO: + { + static bool init = true; + if (init) + { + // 繝繝シ繧ソ繧呈嶌縺崎セシ繧 + ImportTwlPhotoData(); + init = false; + } + + // 蜃ヲ逅縺悟ョ御コ縺励◆ + if (IsImportFinished()) + { + FinalizeImportThread(); + s_RestoreState = RESTORE_IN_PROGRESS; + } + } + break; + + + // 譖ク縺崎セシ縺ソ荳ュ + case RESTORE_IN_PROGRESS: + { + continueRestore = true; + + // AC繧「繝繝励ち縺悟ソ隕√°シ + if (NeedsAcAdater()) + { + continueRestore = false; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // 繝繝シ繧ソ繧定ェュ縺ソ霎シ繧 + if(ImportData().IsFailure()) + { + s_RestoreState = FAIL; + } + + // 蜃ヲ逅縺悟ョ御コ縺励◆ + if (continueRestore && IsImportFinished()) + { + COMMON_LOGGER("Import NAND Data Finished.\n"); + + if (GetProgress() > 99) + { + s_RestoreState = POST_RESTORE; + } + else + { + s_RestoreState = FAIL; + } + + } + } + break; + + // 繝ェ繝悶シ繝井クュ + case REBOOTING: + { + static bool init = true; + + if (init) + { + // ErrDisp縺九i蠑慕畑 + result = nn::ns::CTR::InitializeForShell(); + if (result.IsSuccess()) + { + COMMON_LOGGER("System Reboot.\n"); + + nn::ns::CTR::HardwareResetAsync(nn::CTR::MEMORY_ARRANGE_NORMAL); + while (!nn::applet::IsExpectedToCloseApplication()) + { + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(5)); + } + + nn::ns::CTR::FinalizeForShell(); + + // INFO: 繝ェ繝悶シ繝医ッ髱槫酔譛溘ョ縺溘a蜃ヲ逅縺ッ邯咏カ + } + init = false; + } + } + break; + + // 譖ク縺崎セシ縺ソ蠕後ョ蜃ヲ逅 + case POST_RESTORE: + { + operationMessage.push_back(::std::string("Post Process...")); + // 譖ク縺崎セシ縺ソ螳御コ繝輔ぃ繧、繝ォ繧剃ス懈 + CreateWriteFinishedFile(); + + s_RestoreState = RESTORE_DONE; + } + break; + + // 譖ク縺崎セシ縺ソ螳御コ + case RESTORE_DONE: + { + operationMessage.push_back(::std::string("Restore Done.")); + operationMessage.push_back(::std::string("Press A or START Button to Reboot")); + + if(!s_PlayedRebootCursor) + { + PlaySound(SOUND_CURSOR); + s_PlayedRebootCursor = true; + } + + if (nextStep) + { + s_RestoreState = REBOOTING; + } + } + break; + + // 蜑企勁蜃ヲ逅 + case ERASE: + { + Cleanup(); + s_RestoreState = HISTORY_RECOVER; + } + break; + + // 蜑企勁蜃ヲ逅 + case HISTORY_RECOVER: + { + static bool init = true; + if (init) + { + // ptm縺ョ繧サ繝シ繝悶ョ繝シ繧ソ遘サ陦悟セ後↓譎りィ医r辟。蜉ケ蛹悶☆繧 + nn::ptm::CTR::InvalidateSystemTime(); + + // cfg縺ョ譛ャ菴灘崋譛牙、繧団al蛟、縺ァ蛻晄悄蛹悶☆繧 + InitializeHardwareDependentSetting(); + + init = false; + } + + s_RestoreState = TIME_ADJUST; + } + + + // 譎りィ医≠繧上○ + case TIME_ADJUST: + { + static bool init = true; + if(init) + { + COMMON_LOGGER("Adjust Time\n"); + AdjustTime(); + init = false; + } + + // 蜍輔>縺ヲ縺繧九%縺ィ繧定。ィ遉コ + { + PutAliveMessage(operationMessage, "Sync Clock"); + } + + if(IsTimeAdjustFinished()) + { + if(IsTimeAdjustSuccessed()) + { + s_RestoreState = WAIT_SD_EJECT; + } + else + { + s_RestoreState = FAIL; + } + + // 繝ェ繧ケ繝医い迥カ諷九メ繧ァ繝繧ッ繝輔ぃ繧、繝ォ繧偵☆縺ケ縺ヲ蜑企勁 + DeleteAllCheckFiles(); + } + } + break; + + // 縺吶∋縺ヲ螳御コ + case WAIT_SD_EJECT: + { + operationMessage.push_back(::std::string("ALL Done. Pull Out SD Card.")); + // SD繧ォ繝シ繝画栢縺代ョ縺ソ縺ァ谺。縺ョ迥カ諷九↓驕キ遘サ縺吶k + + if (!s_PlayedSdPullOutCursor) + { + common::PlaySound(common::SOUND_CURSOR); + s_PlayedSdPullOutCursor = true; + } + + } + break; + + // 縺吶∋縺ヲ螳御コ + case ALL_DONE: + { + operationMessage.push_back(::std::string("Restore Succeeded!!")); + static bool init = true; + if (init) + { + PlaySound(SOUND_OK); + init = false; + } + } + break; + + // 譖ク縺崎セシ縺ソ螟ア謨 + case FAIL: + { + static bool init = true; + if(init) + { + // 迥カ諷句晄悄蛹 + DeleteAllCheckFiles(); + init = false; + } + + operationMessage.push_back(::std::string("Failed.")); + if (!s_PlayedFailSound) + { + PlaySound(SOUND_NG); + s_PlayedFailSound = true; + } + } + break; + + case NUP_ONLY_WAIT_SD_EJECT: + { + operationMessage.push_back(::std::string("Update Done. Pull Out SD Card.")); + + // SD繧ォ繝シ繝画栢縺代ョ縺ソ縺ァ谺。縺ョ迥カ諷九↓驕キ遘サ縺吶k + if (!s_PlayedSdPullOutCursor) + { + common::PlaySound(common::SOUND_CURSOR); + s_PlayedSdPullOutCursor = true; + } + } + break; + + case NUP_ONLY_WAIT_NEXT: + { + operationMessage.push_back(::std::string("A or START Button to Shutdown.")); + + if(nextStep) + { + s_RestoreState = SHUTDOWN; + } + } + break; + + case SHUTDOWN: + { + // 譛ャ菴灘晄悄蛹悶r陦後≧ + InitializeFileSystem(); + + // 繧キ繝」繝繝医ム繧ヲ繝ウ縺吶k + nn::ptm::CTR::ShutdownAsync(0, nn::fnd::TimeSpan::FromSeconds(0)); + } + break; + + } +} + +bool InProgress() +{ + return s_RestoreState == RESTORE_IN_PROGRESS; +} + +bool IsRestoreSucceeded() +{ + return s_RestoreState == ALL_DONE; +} + +bool IsRestoreFailed() +{ + return s_RestoreState == FAIL; +} + +void OnSdEjected() +{ + if(s_RestoreState == WAIT_SD_EJECT || s_RestoreState == ALL_DONE) + { + s_RestoreState = ALL_DONE; + } + else if(s_RestoreState == NUP_ONLY_WAIT_SD_EJECT || s_RestoreState == NUP_ONLY_WAIT_NEXT) + { + s_RestoreState = NUP_ONLY_WAIT_NEXT; + } + // FAIL縺ョ縺ィ縺阪ッ荳譌ヲ髮サ貅舌r蛻繧峨↑縺縺ィ蜍輔°縺ェ縺繧医≧縺ォ縺励※縺翫¥ + else if(s_RestoreState != FAIL) + { + InitializeState(); + ClearFileReadResult(); + } +} + +void InitializeState() +{ + s_RestoreState = STARTUP; + s_RestoreMode = RESTORE_MODE_RESTORE; + + common::InitializeFileCheck(); + + s_ExistAPSettingAnnotation = false; + s_ReadSettingDone = false; + s_ReadSettingSuccess = false; + s_APSettingAnnotation = false; + s_SerialNumberAnnotation = false; + s_PlayedFailSound = false; + s_ExecuteFgNup = false; + s_FgNupRetryCount = 0; + s_PlayedStartCursor = false; + s_PlayedRebootCursor = false; + s_PlayedSdPullOutCursor = false; + s_NupOnlyMode = false; + s_ReadVersionDone = false; + s_SdWriteProetctAnnotation = false; + s_ReadVersionResult = nn::ResultSuccess(); +} + +u32 GetProgress() +{ + if(s_RestoreState == RESTORE_TWL_SOUND || + s_RestoreState == RESTORE_TWL_PHOTO || + s_RestoreState == RESTORE_IN_PROGRESS || + s_RestoreState == POST_RESTORE || + s_RestoreState == RESTORE_DONE) + { + return GetImportProgress(); + } + else if(s_RestoreState == UPDATE_IN_PROGRESS || + s_RestoreState == UPDATE_DONE) + { + return GetUpdateProgress(); + } + else + { + return 0; + } + +} + +RestoreMode GetRestoreMode() +{ + return s_RestoreMode; +} + +} // namespace ConsoleRestore diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Controller.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Controller.h new file mode 100644 index 0000000..d2b802b --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Controller.h @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Contoroller.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef CONTOROLLER_H_ +#define CONTOROLLER_H_ + +#include +#include +#include + +namespace ConsoleRestore +{ + +typedef enum RestoreMode +{ + RESTORE_MODE_RESTORE, + RESTORE_MODE_NUP_ONLY +} RestoreMode; + +const u32 RETRY_MAX = 3; + +void ControlState(::std::vector& operationMessage, bool& nextStep, bool& continueRestore); +bool InProgress(); +bool IsRestoreSucceeded(); +bool IsRestoreFailed(); +u32 GetProgress(); + +void OnSdEjected(); +void InitializeState(); +RestoreMode GetRestoreMode(); + +} + +#endif /* CONTOROLLER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Importer.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Importer.cpp new file mode 100644 index 0000000..10c5e58 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Importer.cpp @@ -0,0 +1,1551 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Importer.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include // cfg:nor縺ョ蛻晄悄蛹悶↓蠢隕 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "FileName.h" +#include "Importer.h" +#include "SdMountManager.h" +#include "ConsoleRestore.h" +#include "HeapManager.h" +#include "SdReaderWriter.h" +#include "CommonLogger.h" +#include "FileTransfer.h" +#include "common_Types.h" +#include "Aes_define.h" +#include "configLoader.h" +#include "PlayHistoryManager.h" +#include "FileChecker.h" +#include "VersionDetect.h" + +#include +#include + +namespace ConsoleRestore +{ +namespace +{ +const size_t IMPORT_THREAD_STACK_SIZE = 0x4000; +nn::os::Thread s_ImportThread; +nn::os::StackBuffer s_ImportThreadStack; + +const size_t TIME_ZONE_LENGTH = 9; // "+23:45" +char s_TimeZoneStr[TIME_ZONE_LENGTH]; + +TimeZone s_TimeZone; +const size_t NTP_SERVER_NAME_LENGTH = 256; +char s_NtpServerName[NTP_SERVER_NAME_LENGTH]; + +bool s_CheckedEqualsDeviceIdFileandDeviceId = false; +bool s_CheckedEqualsRegionDataandRegion = false; +bool s_ReadSerialNumber = false; + +// 繧キ繝ェ繧「繝ォ繝翫Φ繝舌シ +u8 s_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + +// 遨コ縺ョ繝輔ぃ繧、繝ォ繧剃ス懈舌☆繧 +bool CreateEmptyFile(const wchar_t* path); +// SD縺九iNAND縺ォ繧サ繝シ繝悶ョ繝シ繧ソ繧偵さ繝斐シ縺吶k +void ImportSaveData(); +// SD縺九iNOR縺ォNOR繝繝シ繧ソ繧偵さ繝斐シ縺吶k +nn::Result ImportNorData(); + +// SD繧ォ繝シ繝峨↓菫晏ュ倥@縺ヲ縺ゅk繝舌シ繧ク繝ァ繝ウ諠蝣ア +common::VerDef s_SDVersionData; + +} + +CheckedNetworkSetting s_CurrentNetowrkSetting1; + +void ConvertTimeZoneString(const char* str) +{ + s_TimeZone.hour = 0; + s_TimeZone.minutes = 0; + s_TimeZone.isMinus = false; + + bool hour = true; + bool ten = true; + u32 count = 0; + for(u32 i = 0; i < TIME_ZONE_LENGTH && count < 2; i++) + { + switch (str[i]) + { + case ':': + { + hour = false; + } + break; + + case '"': + { + // 2蝗櫁ェュ繧薙□繧臥オゆコ + count++; + } + break; + + case '+': + { + s_TimeZone.isMinus = false; + } + break; + + case '-': + { + s_TimeZone.isMinus = true; + } + break; + + default: + { + if(hour) + { + if(ten) + { + s_TimeZone.hour += (str[i] - '0') * 10; + ten = false; + } + else + { + s_TimeZone.hour += str[i] - '0'; + ten = true; + } + } + else + { + if(ten) + { + s_TimeZone.minutes += (str[i] - '0') * 10; + ten = false; + } + else + { + s_TimeZone.minutes += str[i] - '0'; + ten = true; + } + } + } + break; + } + } + + + NN_LOG("Converted TimeZone = "); + if(s_TimeZone.isMinus) + { + NN_LOG("-"); + } + NN_LOG("%02d:%02d\n", s_TimeZone.hour, s_TimeZone.minutes); + +} + +namespace +{ + +bool CreateEmptyFile(const wchar_t* path) +{ + nn::Result result; + bool create = false; + result = common::SdMountManager::Mount(); + + if (result.IsSuccess()) + { + nn::fs::FileOutputStream fos; + + result = fos.TryInitialize(path, true); + if(result.IsSuccess()) + { + fos.TryFlush(); + create = true; + } + fos.Finalize(); + } + + common::SdMountManager::Unmount(); + + return create; +} + +} + +nn::Result ReadSerialNumber(u8* serial) +{ + static nn::Result result = nn::ResultSuccess(); + + if(s_ReadSerialNumber) + { + std::memcpy(serial, s_SerialNo, sizeof(s_SerialNo)); + return result; + } + + COMMON_LOGGER("Read Serial Number in SD.\n"); + + size_t readSize; + common::SdReaderWriter sdReader; + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if(buf != NULL) + { + result = sdReader.ReadBufWithCmac(common::SERIAL_PATHNAME, buf, bufSize, &readSize); + if(result.IsSuccess()) + { + std::memcpy(s_SerialNo, buf, sizeof(s_SerialNo)); + std::memcpy(serial, s_SerialNo, sizeof(s_SerialNo)); + s_ReadSerialNumber = true; + } + common::HeapManager::GetHeap()->Free(buf); + } + else + { + result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } + return result; +} + +nn::Result EqualsDeviceIdFileandDeviceId() +{ + static nn::Result result = nn::ResultSuccess(); + + if(s_CheckedEqualsDeviceIdFileandDeviceId) + { + return result; + } + + COMMON_LOGGER("Check Device Id\n"); + + bit32 sdDeviceId; + common::SdReaderWriter sdReader; + size_t totalSize; + result = sdReader.ReadBufWithCmac(common::DEVICE_ID_PATHNAME, &sdDeviceId, sizeof(sdDeviceId), &totalSize); + s_CheckedEqualsDeviceIdFileandDeviceId = true; + if(result.IsSuccess()) + { + if(GetDeviceId() == sdDeviceId) + { + result = nn::ResultSuccess(); + return result; + } + + result = nn::Result(nn::Result::LEVEL_STATUS, nn::Result::SUMMARY_INVALID_RESULT_VALUE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_INVALID_RESULT_VALUE); + return result; + } + else + { + return result; + } +} + +nn::Result EqualsRegionDataandRegion() +{ + static nn::Result result = nn::ResultSuccess(); + + if(s_CheckedEqualsRegionDataandRegion) + { + return result; + } + + COMMON_LOGGER("Check Region\n"); + + nn::cfg::CTR::CfgRegionCode region; + region = nn::cfg::CTR::GetRegion(); + + nn::cfg::CTR::CfgRegionCode sdRegion; + common::SdReaderWriter sdReader; + size_t readSize; + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + result = sdReader.ReadBufWithCmac(common::REGION_DATA_PATHNAME, buf, bufSize, &readSize); + if (result.IsSuccess()) + { + std::memcpy(&sdRegion, buf, sizeof(sdRegion)); + s_CheckedEqualsRegionDataandRegion = true; + if(region == sdRegion) + { + result = nn::ResultSuccess(); + } + else + { + result = nn::Result(nn::Result::LEVEL_STATUS, nn::Result::SUMMARY_INVALID_RESULT_VALUE, + nn::Result::MODULE_COMMON, nn::Result::DESCRIPTION_INVALID_RESULT_VALUE); + } + } + common::HeapManager::GetHeap()->Free(buf); + } + else + { + result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } + + return result; +} + +void SetCountry(nn::cfg::CTR::CfgCountryCode countryCode) +{ + using namespace nn::cfg::CTR; + using namespace nn::cfg::CTR::detail; + + SimpleAddressIdCfgData simpleAddressId; + TwlCountryCodeCfgData countryData; + + nn::cfg::CTR::system::Initialize(); + + NN_UTIL_PANIC_IF_FAILED(nn::cfg::CTR::system::GetConfig(&simpleAddressId, sizeof(SimpleAddressIdCfgData), GET_CFG_KEY(NN_CFG_SIMPLE_ADDRESS, NN_CFG_SIMPLE_ADDRESS_ID))); + NN_UTIL_PANIC_IF_FAILED(nn::cfg::CTR::system::GetConfig(&countryData, sizeof(TwlCountryCodeCfgData), GET_CFG_KEY(NN_CFG_TWL, NN_CFG_TWL_COUNTRY_CODE))); + nn::cfg::CTR::system::Finalize(); + + simpleAddressId.id = (countryCode << CFG_SIMPLE_ADDRESS_ID_COUNTRY_SHIFT) | (1 + << CFG_SIMPLE_ADDRESS_ID_REGION_SHIFT); + countryData.country = countryCode; + + nn::cfg::CTR::system::Initialize(); + NN_UTIL_PANIC_IF_FAILED(nn::cfg::CTR::system::SetConfig(GET_CFG_KEY(NN_CFG_SIMPLE_ADDRESS, NN_CFG_SIMPLE_ADDRESS_ID), &simpleAddressId, sizeof(SimpleAddressIdCfgData))); + NN_UTIL_PANIC_IF_FAILED(nn::cfg::CTR::system::SetConfig(GET_CFG_KEY(NN_CFG_TWL, NN_CFG_TWL_COUNTRY_CODE), &countryData, sizeof(TwlCountryCodeCfgData))); + nn::cfg::CTR::system::FlushConfig(); + nn::cfg::CTR::system::Finalize(); +} + +void SetLanguage(nn::cfg::CTR::CfgLanguageCode languageCode) +{ + NN_UTIL_PANIC_IF_FAILED(nn::cfg::CTR::init::SetConfig( + GET_CFG_KEY(nn::cfg::CTR::detail::NN_CFG_USER_INFO, + nn::cfg::CTR::detail::NN_CFG_USER_INFO_LANGUAGE), + &languageCode, + sizeof(nn::cfg::CTR::detail::LanguageCfgData))); + NN_UTIL_PANIC_IF_FAILED(nn::cfg::CTR::init::FlushConfig()); + nn::cfg::nor::CTR::Initialize(); + NN_UTIL_PANIC_IF_FAILED(nn::cfg::nor::CTR::SetLanguage(static_cast(languageCode))); + nn::cfg::nor::CTR::Finalize(); +} + +nn::Result ImportCountryLanguageData() +{ + nn::Result result = nn::ResultSuccess(); + + if (common::ExistsCountryLanguageFile()) + { + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::COUNTRY_SETTING_PATHNAME, buf, bufSize, &readSize); + if (result.IsSuccess()) + { + // SD縺九i隱ュ縺ソ蜃コ縺玲仙粥 + SetCountry(reinterpret_cast (buf)->country); + + SetLanguage(reinterpret_cast (buf)->language); + } + common::HeapManager::GetHeap()->Free(buf); + + NN_UTIL_RETURN_IF_FAILED(result); + } + } + else + { + // 繝ェ繝シ繧ク繝ァ繝ウ縺九i驕ゥ蠖薙↑蝗ス繧呈欠螳壹☆繧 + nn::cfg::CTR::CfgRegionCode region; + region = nn::cfg::CTR::GetRegion(); + NN_LOG("Country Setting does not exist. Use Default Setting\n"); + switch(region) + { + case nn::cfg::CTR::CFG_REGION_JAPAN: + { + SetCountry(nn::cfg::CTR::CFG_COUNTRY_JAPAN); + } + break; + + case nn::cfg::CTR::CFG_REGION_AMERICA: + { + SetCountry(nn::cfg::CTR::CFG_COUNTRY_UNITED_STATES); + } + break; + + case nn::cfg::CTR::CFG_REGION_EUROPE: + { + SetCountry(nn::cfg::CTR::CFG_COUNTRY_FRANCE); + } + break; + + case nn::cfg::CTR::CFG_REGION_AUSTRALIA: + { + SetCountry(nn::cfg::CTR::CFG_COUNTRY_AUSTRALIA); + } + break; + + case nn::cfg::CTR::CFG_REGION_CHINA: + { + SetCountry(nn::cfg::CTR::CFG_COUNTRY_CHINA); + } + break; + + case nn::cfg::CTR::CFG_REGION_KOREA: + { + SetCountry(nn::cfg::CTR::CFG_COUNTRY_SOUTH_KOREA); + } + break; + + case nn::cfg::CTR::CFG_REGION_TAIWAN: + { + SetCountry(nn::cfg::CTR::CFG_COUNTRY_TAIWAN); + } + break; + } + + } + + return result; +} + +inline u8 DecimalToBcd(u8 param) +{ + u8 theTen, theOne; + theTen = param / 10; + theOne = param - theTen * 10; + return (theTen << 4 | theOne); +} + +nn::Result ImportMcuRtc() +{ + COMMON_LOGGER("Import RTC Data.\n"); + nn::Result result = nn::ResultSuccess(); + nn::Handle handle = GetMcuHandle(); + + if(handle.IsValid()) + { + if (common::CheckFileExists(common::MCU_RTC_PATHNAME)) + { + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::MCU_RTC_PATHNAME, buf, bufSize, &readSize); + if (result.IsSuccess()) + { + // mcu繧剃スソ縺」縺ヲ繧サ繝繝医☆繧 + nn::mcu::CTR::HwCheck mcu(handle); + nn::mcu::CTR::RtcData* rtc = reinterpret_cast (buf); + NN_LOG("RTC = 20%02d/%02d/%02d %02d:%02d:%02d\n", rtc->m_Year, rtc->m_Month, rtc->m_Day, rtc->m_Hour, rtc->m_Minute, rtc->m_Second); + + // BCD螟画鋤縺悟ソ隕 + + size_t RTC_PARAM_SIZE = sizeof(nn::mcu::CTR::RtcData); + u8 bcd[RTC_PARAM_SIZE]; + for (int i = 0; i < RTC_PARAM_SIZE; i++) + { + bcd[i] = DecimalToBcd(reinterpret_cast (rtc)[i]); + } + + result = mcu.WriteBySend(nn::drivers::mcu::CTR::MCU_RTC_SEC_ADDR, bcd, RTC_PARAM_SIZE); + + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + } + + common::HeapManager::GetHeap()->Free(buf); + NN_UTIL_RETURN_IF_FAILED(result); + } + else + { + COMMON_LOGGER("Failed Allocate Heap!!\n"); + result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } + } + } + else + { + result = nn::Result(nn::Result::LEVEL_PERMANENT, nn::Result::SUMMARY_INVALID_STATE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_INVALID_HANDLE); + } + + return result; +} + +void InitializeFileSystem() +{ + nn::Result result; + + for (u32 i = 0; i < common::TWL_PATHNAME_MAX; i++) + { + result = nn::fs::MountSpecialArchive(common::TWL_ARCHIVE_NAME_TABLE[i], common::TWL_FS_ARCHIVE_KIND[i]); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if (result.IsSuccess()) + { + nn::fs::Directory dir; + std::vector entryList; //繧ォ繝ャ繝ウ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ繧ィ繝ウ繝医Μ荳隕ァ繧呈シ邏 + std::vector::iterator entryIndex; + + std::wstring currentDirectory = common::NAND_TWL_ROOT_PATHNAME_WITH_SLASH_TABLE[i]; + result = dir.TryInitialize(currentDirectory.c_str()); + + nn::fs::DirectoryEntry entry; + s32 numEntry; + for (;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + if (result.IsFailure()) + { + dir.Finalize(); + } + if (numEntry == 0) + { + // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ繧帝哩縺倥k + dir.Finalize(); + + // 繝ォ繝シ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ蟄舌r髢九¥ + for (entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++) + { + // 繝繧」繝ャ繧ッ繝医Μ縺ェ繧牙炎髯、縺吶k + if (entryIndex->attributes.isDirectory) + { + NN_LOG("Try Delete %ls%ls/\n", currentDirectory.c_str(), entryIndex->entryName); + result = nn::fs::TryDeleteDirectoryRecursively((currentDirectory + ::std::wstring( + entryIndex->entryName)).c_str()); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + } + // 繝輔ぃ繧、繝ォ縺ェ繧牙炎髯、縺吶k + else + { + NN_LOG("Try Delete %ls%ls\n", currentDirectory.c_str(), entryIndex->entryName); + result = nn::fs::TryDeleteFile( + (currentDirectory + ::std::wstring(entryIndex->entryName)).c_str()); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + } + } + + // 蜑企勁螳御コ + break; + } + else + { + // vector縺ォ菫晏ュ倥☆繧 + entryList.push_back(entry); + if (entry.attributes.isDirectory) + { + NN_LOG("%ls%ls/\n", currentDirectory.c_str(), entry.entryName); + } + else + { + NN_LOG("%ls%ls\n", currentDirectory.c_str(), entry.entryName); + } + } + } + } + nn::fs::Unmount(common::TWL_ARCHIVE_NAME_TABLE[i]); + } + + nn::fs::InitializeCtrFileSystem(); +} + +nn::Result ImportIvs() +{ + nn::Result result = nn::ResultSuccess(); + nn::fs::FileOutputStream fos; + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize() / 2; + void* enc = common::HeapManager::GetHeap()->Allocate(bufSize); + if (enc != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::IVS_PATHNAME, enc, bufSize, &readSize); + if(result.IsSuccess()) + { + // SD縺九i隱ュ縺ソ蜃コ縺玲仙粥 + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if (result.IsSuccess()) + { + void *dec = common::HeapManager::GetHeap()->Allocate(readSize); + if (dec != NULL) + { + // AES蠕ゥ蜿キ蛹悶☆繧 + nn::crypto::Initialize(); + nn::crypto::SwAesCtrContext swAesCtrContest; + + swAesCtrContest.Initialize(common::iv, common::key, sizeof(common::key)); + swAesCtrContest.Decrypt(dec, enc, readSize); + + // IVS譖ク縺崎セシ縺ソ + result = fos.TryInitialize(common::IVS_NAND_PATHNAME, true); + if (result.IsSuccess()) + { + if (result.IsSuccess()) + { + s32 writeSize; + result = fos.TryWrite(&writeSize, dec, readSize, true); + if (result.IsSuccess()) + { + COMMON_LOGGER("Import IVS.\n"); + } + } + } + common::HeapManager::GetHeap()->Free(dec); + } + else + { + COMMON_LOGGER("Failed Allocate Heap!!\n"); + result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } + + } + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + } + else + { + return result; + } + common::HeapManager::GetHeap()->Free(enc); + } + else + { + COMMON_LOGGER("Failed Allocate Heap!!\n"); + result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } + + return result; +} + +void ImportThreadFunc() +{ + nn::Result result; + + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = common::SdMountManager::Mount(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize, AES_BLOCK_SIZE); + if (buf != NULL) + { + + common::CopyDirectory( + (::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME)).c_str(), + common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH, + buf, bufSize, false); + + common::HeapManager::GetHeap()->Free(buf); + } + + common::SdMountManager::Unmount(); + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + NN_LOG("Import Thread Finalize\n"); +} + +namespace +{ + +void ImportSaveData() +{ + // SD繧ォ繝シ繝峨°繧丑AND縺ォ隱ュ縺ソ霎シ縺ソ + nn::Result result; + + // SD繧ォ繝シ繝峨↓縺ゅk繧サ繝シ繝悶ョ繝シ繧ソ繧オ繧、繧コ繧定ィ育ョ + u32 fileNum = 0; + u32 fileSize = 0; + + common::SdMountManager::Mount(); + common::CalculateFileNum(::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME), fileNum, fileSize); + common::SdMountManager::Unmount(); + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ險ュ螳 + common::InitializeTransferProgress(fileSize); + + NN_LOG("File Number = %d\n", fileNum); + NN_LOG("File Size = %d\n", fileSize); + + // SD繧ォ繝シ繝峨↓縺ゅk繧サ繝シ繝悶ョ繝シ繧ソ繝繧」繝ャ繧ッ繝医Μ莉・荳九ョ繝繝シ繧ソ繧誰AND縺ォ繧ウ繝斐シ + COMMON_LOGGER("Import NAND Data Start...\n"); + s_ImportThread.Start(ImportThreadFunc, s_ImportThreadStack); + +} + +nn::Result ImportNorData() +{ + COMMON_LOGGER("Import NOR Data.\n"); + + nn::Result result = nn::ResultSuccess(); + + nn::cfg::nor::CTR::Initialize(); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::NOR_PATHNAME, buf, bufSize, &readSize); + if(result.IsSuccess()) + { + // cfg繧剃スソ縺」縺ヲ繧サ繝繝医☆繧 + result = nn::cfg::nor::CTR::SetNtrSetting(&reinterpret_cast(buf)->ntrConfig.ncd, + &reinterpret_cast(buf)->ntrConfig.ncd_ex); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // TWL WiFi險ュ螳 + result = nn::cfg::nor::CTR::WriteTwlWifiSetting(0, reinterpret_cast(buf)->TwlWiFiSetting, + common::TWL_WIFI_SETTING_SIZE); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // NTR WiFi險ュ螳 + result = nn::cfg::nor::CTR::WriteNtrWifiSetting(0, reinterpret_cast(buf)->NtrWiFiSetting, + common::NTR_WIFI_SETTING_SIZE); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + } + + common::HeapManager::GetHeap()->Free(buf); + + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + NN_UTIL_RETURN_IF_FAILED(result); + } + else + { + COMMON_LOGGER("Failed Allocate Heap!!\n"); + result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } + + return result; +} + + +} + +nn::Result ReadVersionData() +{ + nn::Result result = nn::ResultSuccess(); + std::memset(&s_SDVersionData, 0, sizeof(common::VerDef)); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::VERSION_DATA_PATHNAME, buf, bufSize, &readSize); + if(result.IsSuccess()) + { + // 繝舌シ繧ク繝ァ繝ウ諠蝣ア繧剃ソ晄戟縺吶k + std::memcpy(&s_SDVersionData, buf, readSize); + NN_LOG("SD Version = %02d.%02d.%02d-%02d\n", s_SDVersionData.cup.majorVersion, + s_SDVersionData.cup.minorVersion, + s_SDVersionData.cup.microVersion, + s_SDVersionData.nup.majorVersion); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + } + + common::HeapManager::GetHeap()->Free(buf); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + NN_UTIL_RETURN_IF_FAILED(result); + } + else + { + COMMON_LOGGER("Failed Allocate Heap!!\n"); + result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } + + return result; +} + +bool AlreadyExecutedNup() +{ + return s_SDVersionData.nup.majorVersion != 0; +} + +void Cleanup() +{ + nn::Result result; + bool execCleanup; + + result = nn::am::NeedsCleanup(&execCleanup, nn::fs::MEDIA_TYPE_NAND); + if(result.IsSuccess()) + { + if(execCleanup) + { + COMMON_LOGGER("Cleanup NAND\n"); + nn::am::DoCleanup(nn::fs::MEDIA_TYPE_NAND); + } + } + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); +} + +void DeleteAllCheckFiles() +{ + nn::Result result; + common::SdMountManager::Mount(); + + for(u32 i = 0; i < sizeof(CHECK_FILENAME_TABLE) / sizeof(CHECK_FILENAME_TABLE[0]); i++) + { + if(common::CheckFileExists(CHECK_FILENAME_TABLE[i])) + { + result = nn::fs::TryDeleteFile(CHECK_FILENAME_TABLE[i]); + COMMON_LOGGER_RESULT_IF_FAILED(result); + } + } + common::SdMountManager::Unmount(); +} + +void FinalizeImportThread() +{ + s_ImportThread.Join(); + s_ImportThread.Finalize(); +} + +bool IsImportFinished() +{ + return s_ImportThread.IsValid() && !s_ImportThread.IsAlive(); +} + +void CreateWriteFinishedFile() +{ + CreateEmptyFile(common::WRITE_FINISHED_CHECK_PATHNAME); +} + +void CreateConsoleInitializedFile() +{ + CreateEmptyFile(common::INITIALIZED_CHECK_PATHNAME); +} + +void CreateUpdateFinishedFile() +{ + CreateEmptyFile(common::UPDATE_CHECK_PATHNAME); +} + +void CreateRtcSyncFinishedFile() +{ + CreateEmptyFile(common::RTC_SYNC_CHECK_PATHNAME); +} + +u32 GetImportProgress() +{ + return common::GetProgress(); +} + +bool UpdateNetworkSetting(nn::ac::NetworkSetting& networkSetting) +{ + nn::Result result; + bool retval = true; + + result = nn::ac::InitializeInternal(); + if(result.IsFailure()) + { + retval = false; + COMMON_LOGGER("Error: nn::ac::InitializeInternal() failed\n"); + } + else + { + //迚ケ縺ォ蜈・蜉帙&縺帙k蠢隕√ョ縺ェ縺閾ェ蜍輔〒險ュ螳壹☆繧矩逶ョ + networkSetting.wireless.enable = true; + networkSetting.wireless.multiSsid.enable = false; + networkSetting.ip.enableDHCP = true; + networkSetting.scanlessConnect.hasConnected = false; + networkSetting.proxy.enable = false; + networkSetting.other.enableUPnP = false; + + // 迴セ蝨ィ縺ョ繧、繝ウ繧ソ繝シ繝阪ャ繝郁ィュ螳1繧剃ク譎ら噪縺ォ菫晄戟 + result = nn::ac::LoadNetworkSetting(0, s_CurrentNetowrkSetting1.setting); + if(result.IsSuccess()) + { + s_CurrentNetowrkSetting1.isValid = true; + } + else + { + s_CurrentNetowrkSetting1.isValid = false; + } + + result = nn::ac::UpdateNetworkSetting( 0, networkSetting ); + if(!result.IsSuccess()) + { + retval = false; + COMMON_LOGGER("Error: SetNetworkSetting (Update Error)\n"); + } + else + { + result = nn::ac::FinalizeInternal(); + if (!result.IsSuccess()) + { + retval = false; + COMMON_LOGGER("Error: SetNetworkSetting (Finalize Error)\n"); + } + } + } + + return retval; +} + +bool ReadSetting(bool* nupOnly) +{ + nn::Result result; + bool retval = true; + common::ConfigFileLoader configfileLoader; + + common::SdMountManager::Mount(); + size_t size = common::HeapManager::GetHeap()->GetAllocatableSize(); + void* heapAddr = common::HeapManager::GetHeap()->Allocate(size); + + if(heapAddr != NULL) + { + result = configfileLoader.Initialize(common::AP_SETTING_PATHNAME, heapAddr, size); + if (result.IsSuccess()) + { + nn::ac::NetworkSetting networkSetting; + + { + const char* ssid = configfileLoader.ReadAsChar(L"SSID"); // SSID + if(ssid == NULL) + { + COMMON_LOGGER("SSID: is missing\n"); + retval = false; + } + else + { + std::strncpy(reinterpret_cast (networkSetting.wireless.essidSecurity.ssid), ssid, 32); + networkSetting.wireless.essidSecurity.ssidLength = std::strlen(ssid) % 33; + COMMON_LOGGER("SSID = %s\n", networkSetting.wireless.essidSecurity.ssid); + } + } + + + { + const char* mode = configfileLoader.ReadAsChar(L"MODE"); // MODE + if(mode == NULL) + { + COMMON_LOGGER("MODE: is missing\n"); + retval = false; + } + else + { + if (std::strcmp(mode, "OPEN") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::OPEN; + } + else if (std::strcmp(mode, "WEP40") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WEP_40BIT; + } + else if (std::strcmp(mode, "WEP104") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WEP_104BIT; + } + else if (std::strcmp(mode, "WEP128") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WEP_128BIT; + } + else if (std::strcmp(mode, "WPA-TKIP") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WPA_TKIP; + } + else if (std::strcmp(mode, "WPA2-TKIP") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WPA2_TKIP; + } + else if (std::strcmp(mode, "WPA-AES") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WPA_AES; + } + else if (std::strcmp(mode, "WPA2-AES") == 0) + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::WPA2_AES; + } + else + { + networkSetting.wireless.essidSecurity.securityMode = nn::ac::OPEN; + } + + switch (networkSetting.wireless.essidSecurity.securityMode) + { + case nn::ac::OPEN: + { + COMMON_LOGGER("MODE = OPEN\n"); + } + break; + + case nn::ac::WEP_40BIT: + { + COMMON_LOGGER("MODE = WEP_40BIT\n"); + } + break; + + case nn::ac::WEP_104BIT: + { + COMMON_LOGGER("MODE = WEP_104BIT\n"); + } + break; + + case nn::ac::WEP_128BIT: + { + COMMON_LOGGER("MODE = WEP_128BIT\n"); + } + break; + + case nn::ac::WPA_TKIP: + { + COMMON_LOGGER("MODE = WPA_TKIP\n"); + } + break; + + case nn::ac::WPA2_TKIP: + { + COMMON_LOGGER("MODE = WPA2_TKIP\n"); + } + break; + + case nn::ac::WPA_AES: + { + COMMON_LOGGER("MODE = WPA_AES\n"); + } + break; + + case nn::ac::WPA2_AES: + { + COMMON_LOGGER("MODE = WPA2_AES\n"); + } + break; + + } + + } + } + + { + const char* pass = configfileLoader.ReadAsChar(L"PASS"); // PASS + if(pass == NULL) + { + COMMON_LOGGER("PASS: is missing\n"); + retval = false; + } + else + { + switch (networkSetting.wireless.essidSecurity.securityMode) + { + case nn::ac::WEP_40BIT: + case nn::ac::WEP_104BIT: + case nn::ac::WEP_128BIT: + { + std::strncpy(reinterpret_cast (networkSetting.wireless.essidSecurity.passphrase), + pass, 64); + std::memcpy(networkSetting.wireless.essidSecurity.key, + networkSetting.wireless.essidSecurity.passphrase, 64); + } + break; + + case nn::ac::WPA_TKIP: + case nn::ac::WPA2_TKIP: + case nn::ac::WPA_AES: + case nn::ac::WPA2_AES: + { + std::strncpy(reinterpret_cast (networkSetting.wireless.essidSecurity.passphrase), + pass, 64); + size_t phrase_size = std::strlen( + reinterpret_cast (networkSetting.wireless.essidSecurity.passphrase)); + + nn::nwm::Ssid ssid(reinterpret_cast (networkSetting.wireless.essidSecurity.ssid)); + nn::nwm::ConvertPasswordToPsk( + reinterpret_cast (networkSetting.wireless.essidSecurity.passphrase), + phrase_size, ssid, networkSetting.wireless.essidSecurity.key); + } + break; + + case nn::ac::OPEN: + default: + { + //do nothing + } + break; + } + } + } + + + { + s32 dnsAuto; // DNS_AUTO + if(configfileLoader.ReadAsChar(L"DNS_AUTO") == NULL) + { + COMMON_LOGGER("DNS_AUTO: is missing\n"); + retval = false; + } + else + { + dnsAuto = configfileLoader.ReadAsInteger(L"DNS_AUTO"); + if (dnsAuto == 1) + { + networkSetting.ip.autoDNSSetting = true; + } + else + { + networkSetting.ip.autoDNSSetting = false; + } + + COMMON_LOGGER("DNS_AUTO = %d\n", networkSetting.ip.autoDNSSetting); + + } + } + + { + const char* dnsPrimary = configfileLoader.ReadAsChar(L"DNS_PRI"); // 繝励Λ繧、繝槭ΜDNS + if(!networkSetting.ip.autoDNSSetting) + { + if (dnsPrimary == NULL) + { + COMMON_LOGGER("DNS_PRI: is missing\n"); + retval = false; + + } + else + { + u8 dns[4]; + nn::socket::InAddr addr; + if (1 == nn::socket::InetAtoN(dnsPrimary, &addr)) + { + dns[3] = (0xff & (addr.addr >> 24)); + dns[2] = (0xff & (addr.addr >> 16)); + dns[1] = (0xff & (addr.addr >> 8)); + dns[0] = (0xff & (addr.addr)); + } + std::memcpy(networkSetting.ip.dns[0], dns, 4); + COMMON_LOGGER("DNS_PRI = %03d.%03d.%03d.%03d\n", networkSetting.ip.dns[0][0], + networkSetting.ip.dns[0][1], + networkSetting.ip.dns[0][2], + networkSetting.ip.dns[0][3]); + + } + } + } + + { + const char* dnsSecondary = configfileLoader.ReadAsChar(L"DNS_SEC"); // 繧サ繧ォ繝ウ繝繝ェDNS + if(!networkSetting.ip.autoDNSSetting) + { + if(dnsSecondary == NULL) + { + COMMON_LOGGER("DNS_SEC: is missing\n"); + retval = false; + } + else + { + u8 dns[4]; + nn::socket::InAddr addr; + if (1 == nn::socket::InetAtoN(dnsSecondary, &addr)) + { + dns[3] = (0xff & (addr.addr >> 24)); + dns[2] = (0xff & (addr.addr >> 16)); + dns[1] = (0xff & (addr.addr >> 8)); + dns[0] = (0xff & (addr.addr)); + } + std::memcpy(networkSetting.ip.dns[1], dns, 4); + COMMON_LOGGER("DNS_SEC = %03d.%03d.%03d.%03d\n", networkSetting.ip.dns[1][0], + networkSetting.ip.dns[1][1], + networkSetting.ip.dns[1][2], + networkSetting.ip.dns[1][3]); + + } + } + } + + { + const char* ntpServerName = configfileLoader.ReadAsChar(L"NTPSRV"); // NTP繧オ繝シ繝 + if(ntpServerName == NULL) + { + COMMON_LOGGER("NTPSRV: is missing\n"); + retval = false; + } + else + { + std::strlcpy(s_NtpServerName, ntpServerName, sizeof(s_NtpServerName)); + COMMON_LOGGER("NTPSRV = %s\n", s_NtpServerName); + } + + + } + + { + const char* timeZone = configfileLoader.ReadAsChar(L"TIMEZONE"); // 繧ソ繧、繝繧セ繝シ繝ウ + if(timeZone == NULL) + { + COMMON_LOGGER("TIMEZONE: is missing\n"); + retval = false; + } + else + { + std::strlcpy(s_TimeZoneStr, timeZone, sizeof(s_TimeZoneStr)); + COMMON_LOGGER("TIMEZONE = %s\n", s_TimeZoneStr); + ConvertTimeZoneString(s_TimeZoneStr); + } + + } + + { + NN_NULL_ASSERT(nupOnly); + if (configfileLoader.ReadAsChar(L"NUP_ONLY") != NULL) + { + s32 num = configfileLoader.ReadAsInteger(L"NUP_ONLY"); + if (num == 1) + { + *nupOnly = true; + COMMON_LOGGER("NUP Only Mode.\n"); + } + } + } + + configfileLoader.Finalize(); + + // 譖ク縺崎セシ縺ソ螳御コ縺励↑縺代l縺ーfalse + if(!UpdateNetworkSetting(networkSetting)) + { + retval = false; + } + + } + else + { + NN_LOG("configfileLoader Initialize Failed\n"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + retval = false; + } + common::HeapManager::GetHeap()->Free(heapAddr); + } + else + { + NN_LOG("Can't Allocate Heap\n"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + retval = false; + } + + common::SdMountManager::Unmount(); + return retval; +} + +char* GetNtpServerName() +{ + return s_NtpServerName; +} + +TimeZone GetTimeZone() +{ + return s_TimeZone; +} + +CheckedNetworkSetting* GetTempNetworkSetting() +{ + return &s_CurrentNetowrkSetting1; +} + +void ImportTwlData(enum common::TWL_PATH_INDEX path) +{ + NN_ASSERT(path < common::TWL_PATHNAME_MAX); + + nn::Result result; + + result = nn::fs::MountSpecialArchive(common::TWL_ARCHIVE_NAME_TABLE[path], common::TWL_FS_ARCHIVE_KIND[path]); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = common::SdMountManager::Mount(); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + NN_LOG("AllocatableSize = %d\n", bufSize); + + + u32 fileNum = 0; + u32 fileSize = 0; + + common::CalculateFileNum(::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_TWL_ROOTNAME_TABLE[path]), fileNum, fileSize); + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ險ュ螳 + common::InitializeTransferProgress(fileSize); + + NN_LOG("File Number = %d\n", fileNum); + NN_LOG("File Size = %d\n", fileSize); + + + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize, AES_BLOCK_SIZE); + if (buf != NULL) + { + wchar_t archiveName[256]; + ::std::mbstowcs(archiveName, common::TWL_ARCHIVE_NAME_TABLE[path], std::strlen(common::TWL_ARCHIVE_NAME_TABLE[path]) + 1); + std::wstring archiveString(archiveName); + common::CopyDirectory( + (::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_TWL_ROOTNAME_TABLE[path])).c_str(), + (archiveString + ::std::wstring(L"/")).c_str(), + buf, bufSize, false); + + common::HeapManager::GetHeap()->Free(buf); + } + + common::SdMountManager::Unmount(); + nn::fs::Unmount(common::TWL_ARCHIVE_NAME_TABLE[path]); + +} + +void ImportTwlPhotoDataFunc() +{ + COMMON_LOGGER("Import Twl Photo Data.\n"); + ImportTwlData(common::TWL_PHOTO); +} + +void ImportTwlSoundDataFunc() +{ + COMMON_LOGGER("Import Twl Sound Data.\n"); + ImportTwlData(common::TWL_SOUND); +} + +void ImportTwlPhotoData() +{ + s_ImportThread.Start(ImportTwlPhotoDataFunc, s_ImportThreadStack); +} + +void ImportTwlSoundData() +{ + s_ImportThread.Start(ImportTwlSoundDataFunc, s_ImportThreadStack); +} + + +void ClearFileReadResult() +{ + s_CheckedEqualsDeviceIdFileandDeviceId = false; + s_CheckedEqualsRegionDataandRegion = false; + s_ReadSerialNumber = false; +} + +void ImportPlayHistoryThreadFunc() +{ + common::PlayHistoryManager historyManager; + + COMMON_LOGGER("Import PlayHistory\n"); + historyManager.Import(); +} + +void ImportPlayHistory() +{ + s_ImportThread.Start(ImportPlayHistoryThreadFunc, s_ImportThreadStack); +} + +void ExportCalData() +{ + using namespace nn::cfg::CTR::detail; + + nn::Result result; + common::CfgCalData cfgCalData; + common::SdReaderWriter sdWriter; + + COMMON_LOGGER("Export CalData\n"); + + common::SdMountManager::Mount(); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.touchPanelCfgData, sizeof(TouchPanelCfgData), + GET_CFG_KEY(NN_CFG_HID, NN_CFG_HID_CAL_TOUCHPANEL)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.lcdFlickerCfgData, sizeof(LcdFlickerCfgData), + GET_CFG_KEY(NN_CFG_LCD, NN_CFG_LCD_CAL_FLICKER)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.fcramCfgData, sizeof(FcramCfgData), + GET_CFG_KEY(NN_CFG_FCRAM, NN_CFG_FCRAM_CAL_DELAY)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.rtcCfgData, sizeof(RtcCfgData), + GET_CFG_KEY(NN_CFG_RTC, NN_CFG_RTC_CAL_COMPENSATION)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.gyroscopeCfgData, sizeof(GyroscopeCfgData), + GET_CFG_KEY(NN_CFG_HID, NN_CFG_HID_CAL_GYROSCOPE)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.accelCfgData, sizeof(AccelCfgData), + GET_CFG_KEY(NN_CFG_HID, NN_CFG_HID_CAL_ACCELEROMETER)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.codecCfgData, sizeof(CodecCfgData), + GET_CFG_KEY(NN_CFG_CODEC, NN_CFG_CODEC_CAL)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.mcuSlideVolumeRangeCfgData, sizeof(McuSlideVolumeRangeCfgData), + GET_CFG_KEY(NN_CFG_MCU, NN_CFG_MCU_SLIDE_VOLUME)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + sdWriter.WriteBufWithCmac(common::CFG_CALIBRATION_PATHNAME, &cfgCalData, sizeof(cfgCalData)); + + common::SdMountManager::Unmount(); +} + +nn::Result ImportCalData(common::CfgCalData *data) +{ + using namespace nn::cfg::CTR::detail; + + nn::Result result = nn::ResultSuccess(); + + COMMON_LOGGER("Import CalData\n"); + + common::SdMountManager::Mount(); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::CFG_CALIBRATION_PATHNAME, buf, bufSize, &readSize); + if(result.IsSuccess()) + { + // SD縺九i隱ュ縺ソ蜃コ縺玲仙粥 + std::memcpy(data, buf, readSize); + } + common::HeapManager::GetHeap()->Free(buf); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + NN_UTIL_RETURN_IF_FAILED(result); + } + else + { + result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } + + common::SdMountManager::Unmount(); + return result; +} + +nn::Result InitializeHardwareDependentSetting() +{ + using namespace nn::cfg::CTR::detail; + nn::Result result = nn::ResultSuccess(); + + common::CfgCalData cfgCalData; + result = ImportCalData(&cfgCalData); + NN_UTIL_RETURN_IF_FAILED(result); + + result = nn::cfg::CTR::init::SetConfig(GET_CFG_KEY(NN_CFG_HID, NN_CFG_HID_CAL_TOUCHPANEL), + &cfgCalData.touchPanelCfgData, sizeof(TouchPanelCfgData)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::SetConfig(GET_CFG_KEY(NN_CFG_LCD, NN_CFG_LCD_CAL_FLICKER), + &cfgCalData.lcdFlickerCfgData, sizeof(LcdFlickerCfgData)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::SetConfig(GET_CFG_KEY(NN_CFG_FCRAM, NN_CFG_FCRAM_CAL_DELAY), &cfgCalData.fcramCfgData, + sizeof(FcramCfgData)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::SetConfig(GET_CFG_KEY(NN_CFG_RTC, NN_CFG_RTC_CAL_COMPENSATION), + &cfgCalData.rtcCfgData, sizeof(RtcCfgData)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::SetConfig(GET_CFG_KEY(NN_CFG_HID, NN_CFG_HID_CAL_GYROSCOPE), + &cfgCalData.gyroscopeCfgData, sizeof(GyroscopeCfgData)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::SetConfig(GET_CFG_KEY(NN_CFG_HID, NN_CFG_HID_CAL_ACCELEROMETER), + &cfgCalData.accelCfgData, sizeof(AccelCfgData)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::SetConfig(GET_CFG_KEY(NN_CFG_CODEC, NN_CFG_CODEC_CAL), &cfgCalData.codecCfgData, + sizeof(CodecCfgData)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = nn::cfg::CTR::init::SetConfig(GET_CFG_KEY(NN_CFG_MCU, NN_CFG_MCU_SLIDE_VOLUME), + &cfgCalData.mcuSlideVolumeRangeCfgData, sizeof(McuSlideVolumeRangeCfgData)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + NN_LOG("Set cfgCalData\n"); + + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + nn::cfg::CTR::init::ResetCameraCalibration(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + nn::cfg::CTR::init::ResetAnalogStickCalibration(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + return result; +} + +nn::Result ImportData() +{ + static nn::Result result = nn::ResultSuccess(); + static bool init = true; + if(init) + { + init = false; + + // NAND縺ョ縺斐∩繧貞炎髯、縺吶k + Cleanup(); + + // SD繧ォ繝シ繝峨ョIVS繝輔ぃ繧、繝ォ繧呈嶌縺崎セシ繧 + result = ImportIvs(); + NN_UTIL_RETURN_IF_FAILED(result); + + // NOR繝繝シ繧ソ繧呈嶌縺崎セシ繧 + result = ImportNorData(); + NN_UTIL_RETURN_IF_FAILED(result); + + // 蝗コ菴灘崋譛営alL繝繝シ繧ソ繧担D繧ォ繝シ繝峨↓蜃コ蜉帙☆繧 + // 譛ャ菴灘晄悄蛹門セ後ッcal蛟、縺瑚ィュ螳壹&繧後※縺繧 + ExportCalData(); + + // SD繧ォ繝シ繝峨ョ繧サ繝シ繝悶ョ繝シ繧ソ繧誰AND縺ォ譖ク縺崎セシ繧 + ImportSaveData(); + } + + return result; +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Importer.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Importer.h new file mode 100644 index 0000000..8c31c75 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Importer.h @@ -0,0 +1,95 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Importer.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef IMPORTER_H_ +#define IMPORTER_H_ + +#include +#include "FileName.h" +#include + +namespace ConsoleRestore +{ + +nn::Result EqualsDeviceIdFileandDeviceId(); +nn::Result EqualsRegionDataandRegion(); +nn::Result ReadSerialNumber(u8* serial); + +void FinalizeImportThread(); +bool IsImportFinished(); +void ImportTwlSoundData(); +void ImportTwlPhotoData(); +nn::Result ImportData(); +void CreateWriteFinishedFile(); +void CreateUpdateFinishedFile(); +void CreateConsoleInitializedFile(); +void CreateRtcSyncFinishedFile(); +u32 GetImportProgress(); + +// NAND縺ョ縺斐∩繧貞炎髯、縺吶k +void Cleanup(); + +const wchar_t* const CHECK_FILENAME_TABLE[] = +{ + common::UPDATE_CHECK_PATHNAME, + common::INITIALIZED_CHECK_PATHNAME, + common::WRITE_FINISHED_CHECK_PATHNAME, + common::RTC_SYNC_CHECK_PATHNAME, +}; + +void DeleteAllCheckFiles(); + +struct TimeZone +{ + u32 hour; + u32 minutes; + bool isMinus; + NN_PADDING3; +}; + +bool ReadSetting(bool* nupOnly); +char* GetNtpServerName(); +TimeZone GetTimeZone(); + +struct CheckedNetworkSetting +{ + nn::ac::CTR::NetworkSetting setting; + bool isValid; + NN_PADDING3; +}; + +CheckedNetworkSetting* GetTempNetworkSetting(); +nn::Result ImportCountryLanguageData(); +nn::Result ImportMcuRtc(); + +// TWL蜀咏悄鬆伜沺繧貞晄悄蛹悶@縺ヲ縺九i譛ャ菴灘晄悄蛹悶r陦後≧ +void InitializeFileSystem(); + +void ClearFileReadResult(); + +// 繝励Ξ繧、螻・豁エ繧定ェュ縺ソ霎シ縺ソ縺セ縺吶Qtm縺ョ繧サ繝シ繝悶ョ繝シ繧ソ遘サ陦悟セ後↓蜻シ縺ウ蜃コ縺吝ソ隕√′縺ゅj縺セ縺 +void ImportPlayHistory(); + +// cfg縺ョ繝上シ繝峨え繧ァ繧「蝗コ譛蛾伜沺繧団al蛟、縺ァ蛻晄悄蛹悶@縺セ縺 +nn::Result InitializeHardwareDependentSetting(); + +// SD繧ォ繝シ繝我ク翫ョ繝舌シ繧ク繝ァ繝ウ諠蝣ア繧定ェュ縺ソ縺セ縺 +nn::Result ReadVersionData(); +// 遘サ陦悟譛ャ菴薙′NUP貂医∩縺九←縺縺 +bool AlreadyExecutedNup(); + +} + +#endif /* IMPORTER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/NtpClient.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/NtpClient.cpp new file mode 100644 index 0000000..f2a5114 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/NtpClient.cpp @@ -0,0 +1,376 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: NtpClient.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Importer.h" +#include "CommonLogger.h" + +namespace ConsoleRestore +{ + +namespace { + +const size_t NTP_THREAD_STACK_SIZE = 0x1000; +nn::os::Thread s_NtpThread; +nn::os::StackBuffer s_NtpThreadStack; +bool s_NtpSyncSuccessed = false; + + +struct NTP_Packet{ // NTP繝代こ繝繝 + u32 controlWord; + u32 rootDelay; + u32 rootDispersion; + u32 referenceId; + s64 referenceTimestamp; + s64 startTimestamp; + s64 receiveTimestamp; + u32 transmitTimestampSeconds; + u32 transmitTimestampFractions; +}; + +const size_t TIMEOUT_MILLISECOND = 5000; // 繧ソ繧、繝繧「繧ヲ繝 繝溘Μ遘呈焚 +NTP_Packet s_NTPSendPacket; // 騾∽ソ。縺吶kNTP繝代こ繝繝 +NTP_Packet s_NTPRecvPacket; // 蜿嶺ソ。縺吶kNTP繝代こ繝繝 +const u32 NTP_PORT_NUM = 123; + +nn::Result InitializeNetwork(void) +{ + nn::Result result; + nn::ac::Config config; + + result = nn::ac::Initialize(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // 謗・邯夊ヲ∵アら畑縺ョ繝代Λ繝。繝シ繧ソ繧剃ス懈 + result = nn::ac::CreateDefaultConfig(&config); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + return result; + } + + // 繝繝舌ャ繧ー逕ィ縺ォ謗・邯壹ユ繧ケ繝医r辟。蜉ケ蛹 + nn::ac::DebugSetNetworkArea(&config, nn::ac::NETWORK_AREA_LAN); + + // 謗・邯夊ヲ∵アゅr逋コ陦 + result = nn::ac::ConnectWithoutEula(config); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + return result; + } + + return nn::ResultSuccess(); +} + +nn::Result FinalizeNetwork(void) +{ + nn::Result result; + + // 謗・邯夊ヲ∵アら畑縺ョ繝代Λ繝。繝シ繧ソ繧剃ス懈 + result = nn::ac::Close(); + NN_UTIL_RETURN_IF_FAILED(result); + + result = nn::ac::Finalize(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + return nn::ResultSuccess(); +} + +bool GetNtpTime(u32* ntpTime) +{ + nn::Result result; + + bool retval = true; + NN_LOG("Initializing network.\n"); + + // 譛ャ菴薙↓譖ク縺崎セシ縺セ繧後※縺繧九ロ繝繝医Ρ繝シ繧ッ險ュ螳壹r菴ソ縺」縺ヲ繝阪ャ繝医Ρ繝シ繧ッ謗・邯壹r蛻晄悄蛹 + result = InitializeNetwork(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + { + NN_LOG("Initializing socket..\n"); + + // 荳縺、縺ョ繧ケ繝ャ繝繝峨°繧峨た繧ア繝繝 API 繧貞茜逕ィ縺吶k + const s32 sessionCount = 1; + // 繧ス繧ア繝繝医ョ騾∝女菫。繝舌ャ繝輔ぃ縺ィ縺励※ 64 KB 繧貞牡繧雁ス薙※ + const size_t bufferSizeForSockets = 65536; + // 繧ス繧ア繝繝医Λ繧、繝悶Λ繝ェ縺ォ蠢隕√↑繝ッ繝シ繧ッ繧オ繧、繧コ繧呈アゅa繧 + const size_t workSizeForLibrary = nn::socket::GetRequiredMemorySize(bufferSizeForSockets, sessionCount); + + // 繝ッ繝シ繧ッ繝。繝「繝ェ繧堤「コ菫昴@縺ヲ 4KB 縺ォ繧「繝ゥ繧、繝ウ縺ォ縺吶k + u8* pWorkMemory = new u8[workSizeForLibrary + 4096]; + uptr workMemoryAddress = nn::math::RoundUp(reinterpret_cast (pWorkMemory), 4096); + + // 繧ス繧ア繝繝医Λ繧、繝悶Λ繝ェ縺ョ蛻晄悄蛹 + result = nn::socket::Initialize(workMemoryAddress, workSizeForLibrary, bufferSizeForSockets, sessionCount); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + { + s32 ret; + nn::socket::InAddr addr, netmask; + ret = nn::socket::GetPrimaryAddress(reinterpret_cast (&addr), reinterpret_cast (&netmask)); + NN_ASSERT(ret == 0); + COMMON_LOGGER("host : %s\n", nn::socket::InetNtoA(addr)); + COMMON_LOGGER("netmask : %s\n", nn::socket::InetNtoA(netmask)); + + nn::socket::InAddr dns1, dns2; + ret = nn::socket::GetResolver(reinterpret_cast (&dns1), reinterpret_cast (&dns2)); + if (ret == 0) + { + COMMON_LOGGER("dns1 : %s\n", nn::socket::InetNtoA(dns1)); + COMMON_LOGGER("dns2 : %s\n", nn::socket::InetNtoA(dns2)); + } + + nn::socket::InAddr gateway; + ret = nn::socket::GetDefaultGateway(reinterpret_cast (&gateway)); + if (ret == 0) + { + COMMON_LOGGER("gateway : %s\n", nn::socket::InetNtoA(gateway)); + } + + COMMON_LOGGER("\n"); +#ifndef NN_SWITCH_DISABLE_DEBUG_PRINT + nn::socket::DumpRoutingTable(); +#endif + } + + { + s32 socket = nn::socket::Socket(nn::socket::PF_INET, nn::socket::SOCK_DGRAM, 0); + NN_LOG("socket = %d\n", socket); + + // 繧ッ繝ゥ繧、繧「繝ウ繝医い繝峨Ξ繧ケ縺ョ險ュ螳 + nn::socket::SockAddrIn host_addr; + host_addr.len = sizeof(nn::socket::SockAddrIn); + host_addr.family = nn::socket::AF_INET; + host_addr.addr.addr = 0; + host_addr.port = nn::socket::HtoNs(NTP_PORT_NUM); + + // 繝ュ繝シ繧ォ繝ォ繧「繝峨Ξ繧ケ繧偵ヰ繧、繝ウ繝 + s32 ret = nn::socket::Bind(socket, &host_addr); + NN_LOG("bind = %d\n", ret); + + // ******************************************************************************** + // NTP繝代こ繝繝医r逕滓舌@縺ヲ騾√k + // ******************************************************************************** + + // 繧オ繝シ繝舌い繝峨Ξ繧ケ縺ョ險ュ螳 + nn::socket::SockAddrIn serverSockAddrIn; + serverSockAddrIn.len = sizeof(nn::socket::SockAddrIn); + serverSockAddrIn.family = nn::socket::AF_INET; + + // GetHostByName繧剃スソ縺蝣エ蜷 + nn::socket::HostEnt* serverHostent; + u64 serveraddr = 0; + serverHostent = nn::socket::GetHostByName(GetNtpServerName()); + if (serverHostent == NULL) + { + COMMON_LOGGER("Error: GetHostByName %s\n", GetNtpServerName()); + retval = false; + } + else + { + // 繧オ繝シ繝舌ョ繝帙せ繝域ュ蝣ア縺九iIP繧「繝峨Ξ繧ケ繧偵さ繝斐シ + serveraddr = *(reinterpret_cast (serverHostent->addrList[0])); + } + serverSockAddrIn.addr.addr = serveraddr; + COMMON_LOGGER("Destination address: %s\n", nn::socket::InetNtoA(serverSockAddrIn.addr)); + serverSockAddrIn.port = nn::socket::HtoNs(NTP_PORT_NUM); // 繝昴シ繝育分蜿キ + + // NTP繝代こ繝繝医rSNTP逕ィ縺ォ蛻晄悄蛹悶☆繧 + s_NTPSendPacket.controlWord = nn::socket::HtoNl(0x0B000000); + s_NTPSendPacket.rootDelay = 0; + s_NTPSendPacket.rootDispersion = 0; + s_NTPSendPacket.referenceId = 0; + s_NTPSendPacket.referenceTimestamp = 0; + s_NTPSendPacket.startTimestamp = 0; + s_NTPSendPacket.receiveTimestamp = 0; + s_NTPSendPacket.transmitTimestampSeconds = 0; + s_NTPSendPacket.transmitTimestampFractions = 0; + + // 繧オ繝シ繝舌r謖螳壹@縺ヲNTP繝代こ繝繝医r騾∽ソ。縺吶k + if ((ret = nn::socket::SendTo(socket, reinterpret_cast (&s_NTPSendPacket), sizeof(s_NTPSendPacket), 0, + &serverSockAddrIn)) < 0) + { + COMMON_LOGGER("Error: Failed Send to Server, %d\n", ret); + retval = false; + } + + NN_LOG("SendTo finished\n"); + + // 蜿嶺ソ。蠕縺。 + nn::socket::PollFd pollFd; + pollFd.fd = socket; + pollFd.events = nn::socket::POLLRDNORM; + if ((ret = nn::socket::Poll(&pollFd, 1, TIMEOUT_MILLISECOND)) < 0) + { + COMMON_LOGGER("Error: recv error, %d\n", ret); + retval = false; + } + + NN_LOG("Poll Finished\n"); + + switch (pollFd.revents) + { + case nn::socket::POLLERR: // 繧ス繧ア繝繝医↓繧ィ繝ゥ繝シ縺檎匱逕溘@縺セ縺励◆縲 + COMMON_LOGGER("Error: POLLERR %s %d\n", __FILE__, __LINE__); + retval = false; + break; + case nn::socket::POLLHUP: // 繧ケ繝医Μ繝シ繝繝サ繧ス繧ア繝繝医′譛ェ謗・邯壹〒縺吶 + COMMON_LOGGER("Error: POLLHUP %s %d\n", __FILE__, __LINE__); + retval = false; + break; + case nn::socket::POLLNVAL: // 荳肴ュ」縺ェ繧ス繧ア繝繝郁ィ倩ソー蟄舌〒縺吶 + COMMON_LOGGER("Error: POLLNVAL %s %d\n", __FILE__, __LINE__); + retval = false; + break; + default: + break; + } + + // 繧オ繝シ繝舌°繧画凾蛻サ諠蝣ア繧貞女菫。縺吶k + // 繧オ繝シ繝舌r謖螳壹@縺ヲ蜿嶺ソ。繧定。後≧ + // 蜿嶺ソ。縺吶k縺セ縺ァ蠕縺溘&繧後k + if ((ret = nn::socket::RecvFrom(socket, reinterpret_cast (&s_NTPRecvPacket), sizeof(s_NTPRecvPacket), nn::socket::MSG_DONTWAIT, + &serverSockAddrIn)) < 0) + { + COMMON_LOGGER("Error: RecvFrom, %d\n", ret); + retval = false; + } + + NN_LOG("RecvFrom finished\n"); + + // NTP繧オ繝シ繝舌°繧牙叙蠕励@縺滓凾蛻サ繧堤樟蝨ー譎る俣縺ォ螟画鋤縺吶k + *ntpTime = nn::socket::NtoHl(s_NTPRecvPacket.transmitTimestampSeconds) - 2208988800; /* 1970/01/01 縺九i縺ョ遘呈焚縺ォ螟画鋤 */ + NN_LOG("ntp_time = %d\n", ntpTime); + + nn::socket::Close(socket); + NN_UNUSED_VAR(ret); + } + + NN_LOG("Finalizing socket..\n"); + // 繧ス繧ア繝繝医Λ繧、繝悶Λ繝ェ縺ョ邨ゆコ + result = nn::socket::Finalize(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + } + + NN_LOG("Finalizing network.\n"); + result = FinalizeNetwork(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + return retval; +} + +void RestoreCurrentInternetSetting() +{ + COMMON_LOGGER("Restore Current Internet Setting\n"); + nn::Result result; + if (GetTempNetworkSetting()->isValid) + { + result = nn::ac::CTR::UpdateNetworkSetting(0, GetTempNetworkSetting()->setting); + COMMON_LOGGER_RESULT_IF_FAILED(result); + } + else + { + // 辟。蜉ケ縺ョ蝣エ蜷医ッ豸亥悉縺励※縺翫¥ + result = nn::ac::CTR::RemoveNetworkSetting(0); + COMMON_LOGGER_RESULT_IF_FAILED(result); + } + + result = nn::ac::FlushNetworkSetting(); + COMMON_LOGGER_RESULT_IF_FAILED(result); + + result = nn::ac::FinalizeInternal(); + COMMON_LOGGER_RESULT_IF_FAILED(result); +} + +} + +void NtpThreadFunc() +{ + // NTP譎る俣繧貞叙蠕励☆繧 + u32 ntpTime; + if (GetNtpTime(&ntpTime)) + { + // 繧ソ繧、繝繧セ繝シ繝ウ繧定諷ョ縺励※DateTime縺ォ螟画鋤縺吶k + TimeZone timeZone = GetTimeZone(); + + // 1970/01/01 + nn::fnd::DateTime utc = nn::fnd::DateTime(1970, 1, 1, 0, 0, 0, 0); + nn::fnd::DateTime current = utc + nn::fnd::TimeSpan::FromSeconds(ntpTime); + + if (timeZone.isMinus) + { + current -= (nn::fnd::TimeSpan::FromHours(timeZone.hour) + nn::fnd::TimeSpan::FromMinutes(timeZone.minutes)); + } + else + { + current += nn::fnd::TimeSpan::FromHours(timeZone.hour) + nn::fnd::TimeSpan::FromMinutes(timeZone.minutes); + } + + // SWC繧呈嶌縺崎セシ繧 + nn::ptm::CTR::SetUserTime(current); + + COMMON_LOGGER("Set User Time %04d/%02d/%02d %02d:%02d:%02d\n", + current.GetYear(), current.GetMonth(), current.GetDay(), current.GetHour(), current.GetMinute(), current.GetSecond()); + + s_NtpSyncSuccessed = true; + } + else + { + COMMON_LOGGER("Failed Get Ntp Time\n"); + s_NtpSyncSuccessed = false; + } + + // 繧、繝ウ繧ソ繝シ繝阪ャ繝郁ィュ螳壹r蜈縺ォ謌サ縺 + RestoreCurrentInternetSetting(); +} + +bool IsTimeAdjustFinished() +{ + // Initialize貂医∩縺九▽邨ゆコ + return s_NtpThread.IsValid() && !s_NtpThread.IsAlive(); +} + +bool IsTimeAdjustSuccessed() +{ + return s_NtpSyncSuccessed; +} + +void AdjustTime() +{ + nn::Result result; + + result = nn::ac::CTR::InitializeInternal(); + COMMON_LOGGER_RESULT_IF_FAILED(result); + + if(IsTimeAdjustFinished()) + { + s_NtpThread.Join(); + s_NtpThread.Finalize(); + } + s_NtpThread.Start( NtpThreadFunc, s_NtpThreadStack); +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/NtpClient.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/NtpClient.h new file mode 100644 index 0000000..7c7bcf1 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/NtpClient.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: NtpClient.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef NTPCLIENT_H_ +#define NTPCLIENT_H_ + +namespace ConsoleRestore +{ + +u32 AdjustTime(); +bool IsTimeAdjustFinished(); +bool IsTimeAdjustSuccessed(); + +} + +#endif /* NTPCLIENT_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/OMakefile b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/OMakefile new file mode 100644 index 0000000..90b2103 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/OMakefile @@ -0,0 +1,89 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakefile +# +# 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. +# +# $Rev$ +#---------------------------------------------------------------------------- +SUPPORTED_TARGETS = CTR-T*.Process.MPCore.* +#MAKECSU = true +#INSTALL_SDK_TOOL = true +CTR_APPTYPE = BOTH +CTR_MAKE_DEVELOPMENT_IMAGE = true + +TARGET_PROGRAM = ConsoleRestore + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + ../common + +SOURCES[] = + ConsoleRestore.cpp + Controller.cpp + Importer.cpp + Updater.cpp + Ntpclient.cpp + ../common/HardwareInfo.cpp + ../common/DrawSystemState.cpp + ../common/FileTransfer.cpp + ../common/FileChecker.cpp + ../common/SdReaderWriter.cpp + ../common/HeapManager.cpp + ../common/SdLogger.cpp + ../common/wave.cpp + ../common/SimplePlayer.cpp + ../common/LogConsole.cpp + ../common/CommonLogger.cpp + ../common/SdMountManager.cpp + ../common/configLoader.cpp + ../common/PlayHistoryManager.cpp + ../common/VersionDetect.cpp + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = ../common/romfiles + +LIBS += libnn_cfg \ + libnn_driversEeprom \ + libnn_driversi2c \ + libnn_driversCal \ + libnn_crypto \ + libnn_driversCodec \ + libnn_spi \ + libnn_gpio \ + libnn_pdn \ + libnn_mcu \ + libnn_i2c \ + libnn_driversCamera \ + libnn_ps \ + libnn_driversRsa \ + lib_demo \ + libnn_nwm \ + libnn_friends \ + libnn_ns \ + libnn_am \ + libnn_nim \ + +INSTALL_SDK_TOOL = true + +ROM_SPEC_FILE = $(TARGET_PROGRAM).rsf +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/_private/RepairTool.desc + +include $(ROOT_OMAKE)/modulerules + +VERSION_H = $(file version.h) + +$(VERSION_H): $(SOURCES) + section + bash genversion.sh + +RequireSetup($(VERSION_H)) +build: version.h $(DEFAULT_TARGETS) diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Updater.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Updater.cpp new file mode 100644 index 0000000..5f0c4d8 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Updater.cpp @@ -0,0 +1,249 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Updater.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CommonLogger.h" + +namespace ConsoleRestore +{ + +using namespace ES_NAMESPACE; +using namespace EC_NAMESPACE; + +/* ------------------------------------------------------------------- + GetCustomerSupportCode +-------------------------------------------------------------------- */ +#define NIM_UPDATER_RESULT_CHECK(result) \ +do { \ + if (result.IsFailure()) \ + { \ + ECCustomerSupportCode csc; \ + NN_UTIL_PANIC_IF_FAILED( \ + nn::nim::Updater::GetCustomerSupportCode(&csc)); \ + COMMON_LOGGER("CSCode: %d\n", csc); \ + nn::dbg::PrintResult(result); \ + s_Result = result; \ + goto LABEL_FINALIZE; \ + } \ +} while(0) + +namespace +{ + +nn::Result s_Result = nn::ResultSuccess(); + +const size_t UPDATER_THREAD_STACK_SIZE = 0x1000; +nn::os::Thread s_UpdaterThread; +nn::os::StackBuffer s_UpdaterThreadStack; + +u64 s_Progress = 0; + +} + +nn::Result PrintNetworkSetting() +{ + nn::ac::NetworkSetting networkSetting; + NN_UTIL_RETURN_IF_FAILED(nn::ac::LoadNetworkSetting(0, networkSetting)); + COMMON_LOGGER("SSID: %s\n", networkSetting.wireless.essidSecurity.ssid); + COMMON_LOGGER("DNS : %d.%d.%d.%d\n", + networkSetting.ip.dns[0][0], networkSetting.ip.dns[0][1], + networkSetting.ip.dns[0][2], networkSetting.ip.dns[0][3]); + return nn::ResultSuccess(); +} + + +nn::Result ConnectNetwork() +{ + nn::Result result = nn::ResultSuccess(); + nn::ac::Config config; + + result = nn::ac::CreateDefaultConfig(&config); + NN_UTIL_RETURN_IF_FAILED(result); + + result = nn::ac::ConnectWithoutEula(config); + NN_UTIL_RETURN_IF_FAILED(result); + + NN_LOG("Success nn::ac::ConnectWithoutEula\n"); + + NN_UTIL_RETURN_IF_FAILED(PrintNetworkSetting()); + + return nn::ResultSuccess(); +} + +nn::Result InitializeInternal() +{ + nn::Result result = nn::ResultSuccess(); + + result = nn::ac::InitializeInternal(); + NN_UTIL_RETURN_IF_FAILED(result); + + result = ConnectNetwork(); + NN_UTIL_RETURN_IF_FAILED(result); + + return nn::ResultSuccess(); +} + +nn::Result FinalizeInternal() +{ + nn::Result result = nn::ResultSuccess(); + + nn::ac::CloseAll(); + + result = nn::ac::FinalizeInternal(); + NN_UTIL_RETURN_IF_FAILED(result); + + return nn::ResultSuccess(); +} + +void UpdateThreadFunc() +{ + nn::Result result; + + NN_LOG("********************UpdateThreadFunc Start********************\n"); + nn::cfg::CTR::init::Initialize(); + nn::cfg::CfgCountryCode country; + nn::cfg::CfgRegionCode region; + const char *regionStr; + const char *countryStr; + NN_UNUSED_VAR(regionStr); + NN_UNUSED_VAR(countryStr); + + country = nn::cfg::GetCountry(); + region = nn::cfg::GetRegion(); + countryStr = nn::cfg::GetCountryCodeA2(country); + regionStr = nn::cfg::GetRegionCodeA3(region); + + COMMON_LOGGER("[Updater] country:%2d:%s\n", country, countryStr); + COMMON_LOGGER("[Updater] region :%2d:%s\n", region, regionStr); + + /* ------------------------------------------------------------------- + Initialize + -------------------------------------------------------------------- */ + NN_LOG("[Updater] nn::nim::InitializeForUpdater\n"); + result = nn::nim::InitializeForUpdater(); + NIM_UPDATER_RESULT_CHECK(result); + + NN_LOG("[Updater] InitializeInternal\n"); + result = InitializeInternal(); + NIM_UPDATER_RESULT_CHECK(result); + + + /* ------------------------------------------------------------------- + StartNetworkUpdate + -------------------------------------------------------------------- */ + NN_LOG("[Updater] nn::nim::Updater::StartNetworkUpdate()\n"); + result = nn::nim::Updater::StartNetworkUpdate(); + NIM_UPDATER_RESULT_CHECK(result); + + /* ------------------------------------------------------------------- + GetProgress + -------------------------------------------------------------------- */ + NN_LOG("[Updater] nn::nim::Updater::GetProgress()\n"); + + while(true) + { + nn::nim::NetworkUpdateProgress progress; + NIM_UPDATER_RESULT_CHECK(nn::nim::Updater::GetProgress(&progress)); + NIM_UPDATER_RESULT_CHECK(progress.lastResult); + NN_LOG("\x1b[1A\x1b[K"); + NN_LOG("Downloading %2lld/%2lld %8lld/%8lld (%d)\n", + progress.downloadedTitleNum, + progress.totalTitleNum, + progress.currentDownloadedSize, + progress.currentTotalSize, + progress.state); + + // 繧シ繝ュ髯、邂励r髦イ縺 + if(progress.totalTitleNum == 0) + { + progress.totalTitleNum++; + progress.downloadedTitleNum++; + } + if(progress.state > nn::nim::CTR::NUP_STATE_CHECKING) + { + s_Progress = progress.downloadedTitleNum * 100 / progress.totalTitleNum; + } + + if (progress.state == nn::nim::NUP_STATE_NO_NEED) + { + COMMON_LOGGER("[Updater] No need to NetworkUpdate\n"); + s_Progress = 100; + break; + } + if (progress.state == nn::nim::NUP_STATE_FINISHED) + { + COMMON_LOGGER("[Updater] Finished NetworkUpdate\n"); + s_Progress = 100; + break; + } + + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(300)); + } + + LABEL_FINALIZE: + + /* ------------------------------------------------------------------- + Finalize + -------------------------------------------------------------------- */ + NN_LOG("[Updater] nn::nim::FinalizeForUpdater\n"); + result = nn::nim::FinalizeForUpdater(); + NIM_UPDATER_RESULT_CHECK(result); + + result = FinalizeInternal(); + NIM_UPDATER_RESULT_CHECK(result); + + NN_LOG("[Updater] Finish nim Updater demo.\n"); + +} + +void StartFGNetworkUpdate() +{ + NN_LOG("Start FGNetworkUpdate\n"); + s_Result = nn::ResultSuccess(); + s_UpdaterThread.Start(UpdateThreadFunc, s_UpdaterThreadStack); +} + +void FinishFGNetworkUpdate() +{ + NN_LOG("Finalize FGNetworkUpdate\n"); + s_UpdaterThread.Join(); + s_UpdaterThread.Finalize(); +} + +bool IsNetworkUpdateFinished() +{ + return s_UpdaterThread.IsValid() && !s_UpdaterThread.IsAlive(); +} + +u32 GetUpdateProgress() +{ + return s_Progress; +} + +nn::Result GetUpdateResult() +{ + return s_Result; +} + + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Updater.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Updater.h new file mode 100644 index 0000000..32e6798 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/Updater.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Updater.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef UPDATER_H_ +#define UPDATER_H_ + +#include + +namespace ConsoleRestore +{ + +void StartFGNetworkUpdate(); +void FinishFGNetworkUpdate(); +bool IsNetworkUpdateFinished(); +u32 GetUpdateProgress(); +nn::Result GetUpdateResult(); + +} + +#endif /* UPDATER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/model.cbmd b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/model.cbmd differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/sound.cbsd b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/sound.cbsd differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/unknown24x24.ctpk b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +スススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススニススススススススススススススススススススススススススススススススススススススニ8ニ8ニ゙銷スス8ニススススス釡゙ニ鍄踟ススススススススススススススススススススススススススススススススススススススススススニススススススススススススススススススススススススススススススススススススススススススyホスyホスススススYホスススススススススススススススススススススススススススススススススス鍄゙yホYホスロ゙ロ゙ススニススロ゙yボスyホ轌ホ釡゙ススススYホ轌ホ銷スススススyホニロ゙鍄躡ホyホスススyホスコヨスススススyホスyホスススススYホスススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススyホ躡ホ銷スススススニスス轌ホ8ニススススニススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススス \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/unknown48x48.ctpk b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +スススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススYホススススススススススススススススススススススススススス8ニスス8ニ8ニスススコヨ8ニコヨ釡゙銷スススススススススス8ニ8ニススニススススススススススススススススス鍄逧ヨニ銷スス墮ス逧ヨ銷スススススススススススススススススススススススススススススススススススススススススス8ニススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススロ゙スロ゙ススススス銷ズスススススススススススススススススススススコヨスススススススススス鍄8ニ゙ロ゙スス墮スYホススススス躡ホyホ轌ホニススススススススニススススススススススススロ゙ロ゙釡゙踟スス躡ホ銷スススススロ゙スロ゙銷ススYボ墮釡゙コヨス墮スロ゙ススススス踟ス踟スススススススススススススススススススススロ゙スyホススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススYホス墮銷スロ゙スロ゙銷ススススススススススススススススス8ニススコヨロ゙スススススYホニyホ逧ヨ郤ヨスYホス觝ホススススススススススススススロ゙墮ススススススyホス鍄踟ススニスススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススス踟ス銷ズスYホ鍄銷ススススススススススススススススススススス8ニスススススススススス逧ヨスロ゙ス釡゙墮ススススススススススススススススススス8ニススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススススス \ No newline at end of file diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/genversion.sh b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/genversion.sh new file mode 100755 index 0000000..99daed5 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/ConsoleRestore/genversion.sh @@ -0,0 +1,4 @@ +#!/bin/bash -f + +cd ../ +echo "#define RESTORE_VERSION_NUM \"`svn info|grep 'Last Changed Rev:'| awk -F ':' '{print $2}'|tr -d '\n'| sed 's/ //g'`\"" > ./ConsoleRestore/version.h diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/OMakefile b/branches/0thNUP_No_NUP/ConsoleDataMigration/OMakefile new file mode 100644 index 0000000..203c656 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/OMakefile @@ -0,0 +1,24 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakefile +# +# 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. +# +# $Rev$ +#---------------------------------------------------------------------------- + +#.SUBDIRS: $(glob D, *) +.SUBDIRS: $(exist-dirs \ + common \ + ConsoleBackup \ + ConsoleRestore \ + ) + +DefineDefaultRules() diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/OMakeroot b/branches/0thNUP_No_NUP/ConsoleDataMigration/OMakeroot new file mode 100644 index 0000000..7ee1cb5 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/OMakeroot @@ -0,0 +1,73 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakeroot +# +# 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. +# +# $Rev:$ +#---------------------------------------------------------------------------- + +# ディレクトリレイアウトについての説明 +# +# a) ソースコードがルートディレクトリ直下に配置される場合 +# 例: +# /OMakeroot +# /foo/bar/OMakefile +# +# 結果: +# OMakefile と同じディレクトリ以下に objects や images が生成されます。 +# +# /foo/bar/objects/... +# /foo/bar/images/.. +# +# +# b) ソースコードが sources 以下に配置される場合 +# 例: +# /OMakeroot +# /sources/foo/bar/OMakefile +# +# 結果: +# ルートディレクトリ以下に objects や images が生成されます。 +# +# /objects/foo/bar/... +# /images/foo/bar/... +# +# + +# ルート環境変数の取得 +public.HORIZON_ROOT = +if $(defined-env HORIZON_ROOT) + HORIZON_ROOT = $(absname $(getenv HORIZON_ROOT)) + export + +if $(defined-env CTRSDK_ROOT) + CTRSDK_ROOT = $(absname $(getenv CTRSDK_ROOT)) + if $(and $(defined-env HORIZON_ROOT), $(not $(equal $(HORIZON_ROOT), $(CTRSDK_ROOT)))) + eprintln(HORIZON_ROOT と CTRSDK_ROOT が一致しません。同じパスを設定するか、どちらか一方だけを定義して下さい。) + exit(1) + HORIZON_ROOT = $(CTRSDK_ROOT) + export + +if $(not $(HORIZON_ROOT)) + eprintln($"$$CTRSDK_ROOT が定義されていません") + exit(1) + +include $(HORIZON_ROOT)/build/omake/commondefs + +DefineCommandVars() + +.PHONY: all build clean clobber +.PHONY: run run-scripts run-emumem + +# +# OMakefile の読み込み +# +.SUBDIRS: . + diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/Readme.txt b/branches/0thNUP_No_NUP/ConsoleDataMigration/Readme.txt new file mode 100644 index 0000000..2f2f0d5 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/Readme.txt @@ -0,0 +1,10 @@ +【ビルド環境】 + +・SDK +Horizon 0_14 branch r33437 + + Horizon trunk r33597のcfgライブラリの変更をマージ + + Horizon 1_0 branch r33839のRepairTool.descをマージ + +・cygwin +・svnversion + diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/Aes_define.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/Aes_define.h new file mode 100644 index 0000000..d6fadcb --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/Aes_define.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Aes_define.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef AES_DEFINE_H_ +#define AES_DEFINE_H_ + +//繝槭せ繧ソ繝ェ繝ウ繧ー逕ィ繝薙Ν繝画凾縺ォ譛牙柑縺ォ縺吶k +//#define USE_PROD_KEY + +#include + +namespace common +{ + +#ifndef USE_PROD_KEY + + const bit8 key[AES_KEY_SIZE] NN_ATTRIBUTE_ALIGN(4) = + { + 0x81, 0x35, 0xc6, 0x54, 0x19, 0x1a, 0x47, 0x2a, + 0x6b, 0x78, 0xbe, 0x25, 0x90, 0xf6, 0xee, 0x74 + }; + + const bit8 cmacKey[AES_KEY_SIZE] = + { + 0x87, 0xdd, 0xc6, 0xd6, 0xf2, 0xe0, 0x2c, 0xa6, + 0x04, 0x21, 0x9c, 0x5e, 0x33, 0x8c, 0x3d, 0xaa + }; + + const bit8 iv[AES_BLOCK_SIZE] NN_ATTRIBUTE_ALIGN(4) = + { + 0xdf, 0x0f, 0xf9, 0x1b, 0x34, 0x47, 0x70, 0x7f, + 0x7d, 0x06, 0x85, 0xe6, 0xe7, 0xb6, 0x4e, 0xe9 + }; + +#else + const bit8 key[AES_KEY_SIZE] NN_ATTRIBUTE_ALIGN(4) = + { + 0x64, 0x02, 0x6d, 0xbd, 0x9f, 0xb6, 0x62, 0x39, + 0x86, 0x90, 0x67, 0x8a, 0xe2, 0xfa, 0xe1, 0x6e + }; + + const bit8 cmacKey[AES_KEY_SIZE] = + { + 0xdf, 0x3c, 0x58, 0xeb, 0xeb, 0xbf, 0x45, 0x6d, + 0xc9, 0xbe, 0xe3, 0x10, 0xe2, 0x23, 0xfc, 0x30 + }; + + const bit8 iv[AES_BLOCK_SIZE] NN_ATTRIBUTE_ALIGN(4) = + { + 0xe4, 0xcf, 0x58, 0xe5, 0xc9, 0xd6, 0xac, 0x7d, + 0xf1, 0xb9, 0x82, 0xf9, 0xa2, 0xd8, 0xda, 0x7b + }; +#endif + + +} + +#endif /* AES_DEFINE_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/CommonLogger.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/CommonLogger.cpp new file mode 100644 index 0000000..ffc63b1 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/CommonLogger.cpp @@ -0,0 +1,117 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: CommonLogger.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include "CommonLogger.h" +#include "LogConsole_Private.h" + +namespace common +{ + +namespace Logger +{ + +namespace +{ + static CommonLogger s_CommonLogger; + +} + +CommonLogger::CommonLogger() +{ + // TODO 閾ェ蜍慕函謌舌&繧後◆繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ繝シ繝サ繧ケ繧ソ繝 + +} + +CommonLogger::~CommonLogger() +{ + // TODO Auto-generated destructor stub +} + +void CommonLogger::Initialize(u32 width, u32 height, u32 maxLine, demo::RenderSystemDrawing* renderSystem) +{ + m_CriticalSection.Initialize(); + GetConsoleInstance()->Initialize(width, height, maxLine, renderSystem); +} + +void CommonLogger::Finalize() +{ + +} + +void CommonLogger::Print(const char* fmt, ...) +{ + nn::os::CriticalSection::ScopedLock lock(m_CriticalSection); + va_list vlist; + + va_start(vlist, fmt); + + nn::dbg::detail::VPrintf(fmt, vlist); + GetSdInstance()->Print(fmt, vlist); + GetConsoleInstance()->AddText(fmt, vlist); + + va_end(vlist); +} + +void CommonLogger::PrintResult(const char* fmt, ...) +{ + nn::os::CriticalSection::ScopedLock lock(m_CriticalSection); + va_list vlist; + + va_start(vlist, fmt); + + GetSdInstance()->Print(fmt, vlist); + + va_end(vlist); +} + +void CommonLogger::ClearLog() +{ + nn::os::CriticalSection::ScopedLock lock(m_CriticalSection); + GetSdInstance()->Clear(); +} + +void CommonLogger::ScrollUp() +{ + GetConsoleInstance()->ScrollUp(); +} + +void CommonLogger::ScrollDown() +{ + GetConsoleInstance()->ScrollDown(); +} + +void CommonLogger::ScrollToBegin() +{ + GetConsoleInstance()->ScrollToBegin(); +} + +void CommonLogger::ScrollToEnd() +{ + GetConsoleInstance()->ScrollToEnd(); +} + +void CommonLogger::DrawConsole() +{ + GetConsoleInstance()->Print(); +} + +CommonLogger* GetLoggerInstance() +{ + return &s_CommonLogger; +} + +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/CommonLogger.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/CommonLogger.h new file mode 100644 index 0000000..2105eae --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/CommonLogger.h @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: CommonLogger.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef COMMONLOGGER_H_ +#define COMMONLOGGER_H_ + +#include +#include "demo.h" + +#include "SdLogger.h" +#include "LogConsole.h" + +#define COMMON_LOGGER( ... ) (void)common::Logger::GetLoggerInstance()->Print(__VA_ARGS__) +#define COMMON_LOGGER_RESULT(result, func) \ + (void)nn::dbg::PrintResult(result); \ + (void)common::Logger::GetLoggerInstance()->PrintResult("Func = %s\n", func); \ + (void)common::Logger::GetLoggerInstance()->PrintResult("Result = %X\n", result.GetPrintableBits()); \ + +#define COMMON_LOGGER_RESULT_WITH_LINE(result, line, func) \ + (void)nn::dbg::detail::Printf("%s\n", func); \ + (void)nn::dbg::detail::Printf("%d\n", line); \ + (void)nn::dbg::PrintResult(result); \ + (void)common::Logger::GetLoggerInstance()->PrintResult("Func = %s\n", func); \ + (void)common::Logger::GetLoggerInstance()->PrintResult("line = %d\n", line); \ + (void)common::Logger::GetLoggerInstance()->PrintResult("Result = %X\n", result.GetPrintableBits()); \ + +#define COMMON_LOGGER_RESULT_IF_FAILED(result) \ + if(result.IsFailure()) \ + { \ + COMMON_LOGGER_RESULT(result, __func__); \ + } \ + +#define COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result) \ + if(result.IsFailure()) \ + { \ + COMMON_LOGGER_RESULT_WITH_LINE(result, __LINE__, __func__); \ + } \ + +namespace common +{ + +namespace Logger +{ + +class CommonLogger +{ +public: + CommonLogger(); + ~CommonLogger(); + + void Initialize(u32 width, u32 height, u32 maxLine, demo::RenderSystemDrawing* renderSystem); + void Finalize(); + + void Print(const char* fmt, ...); + void PrintResult(const char* fmt, ...); + void ClearLog(); + void ScrollUp(); + void ScrollDown(); + void ScrollToBegin(); + void ScrollToEnd(); + void DrawConsole(); +private: + nn::os::CriticalSection m_CriticalSection; +}; + +CommonLogger* GetLoggerInstance(); + +} + +} + +#endif /* COMMONLOGGER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/DrawSystemState.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/DrawSystemState.cpp new file mode 100644 index 0000000..b0206a0 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/DrawSystemState.cpp @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: DrawSystemState.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include "DrawSystemState.h" + +const u16 PROGRESS_MAX_LINES = 129; + +namespace common +{ + +u32 GetRenderTarget(u32 target, bool flip) +{ + if(flip) + { + if(target == NN_GX_DISPLAY0) + { + return NN_GX_DISPLAY1; + } + else + { + return NN_GX_DISPLAY0; + } + } + else + { + return target; + } +} + +void DrawSystemState +( + const char* toolName, + demo::RenderSystemDrawing& renderSystem, + nn::util::FloatColor titleColor, + bool flip, + std::string& adapterState, + const char* toolVersion, + common::VerDef* mVerData, + u8 batteryRemain, + u64 deviceId, + u64 friendCode, + u32 progress, + char8* macAddress, + ::std::vector& operationMessage, + nn::cfg::CTR::CfgRegionCode region, + u8* s_SerialNo +) +{ + // 繝繝輔か繝ォ繝医〒荳顔判髱「縺ォ謠冗判縺吶k繧ゅョ + renderSystem.SetRenderTarget(GetRenderTarget(NN_GX_DISPLAY0, flip)); + renderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY0, flip), NORMAL_COLOR); + + + renderSystem.Clear(); + renderSystem.SetColor(1.f, 1.f, 1.f); + u32 line = 0; + + size_t fontSize = 8; + size_t spaceSize = fontSize + 2; + renderSystem.SetFontSize(fontSize); + + renderSystem.DrawText(0, line++ * spaceSize, "%s %s Rev.%s", toolName, __DATE__, toolVersion); + renderSystem.SetColor(titleColor.r, titleColor.g, titleColor.b); + renderSystem.FillRectangle(0, (line - 1) * spaceSize, 400, spaceSize); + renderSystem.SetColor(1.f, 1.f, 1.f); + renderSystem.DrawText(0, line++ * spaceSize, ""); + + fontSize += 2; + spaceSize = fontSize + 2; + renderSystem.SetFontSize(fontSize); + renderSystem.DrawText(0, line++ * spaceSize, "System Ver. %d.%d.%d-%d", mVerData->cup.majorVersion, mVerData->cup.minorVersion, mVerData->cup.microVersion, + mVerData->nup.majorVersion); + renderSystem.DrawText(0, line++ * spaceSize, "System Region %s", nn::cfg::CTR::GetRegionCodeA3(region)); + renderSystem.DrawText(0, line++ * spaceSize, "Serial No. %s", s_SerialNo); + renderSystem.DrawText(0, line++ * spaceSize, "Device ID %llu", deviceId); + renderSystem.DrawText(0, line++ * spaceSize, "MAC Address %s", macAddress); + renderSystem.DrawText(0, line++ * spaceSize, "Friend Code %04u-%04u-%04u", static_cast (friendCode + / 100000000ULL % 10000ULL), static_cast (friendCode / 10000ULL % 10000ULL), + static_cast (friendCode % 10000ULL)); + + renderSystem.DrawText(0, line++ * spaceSize, "Battery %d%%", batteryRemain); + renderSystem.DrawText(0, line++ * spaceSize, "AC Adaper %s", adapterState.c_str()); + renderSystem.DrawText(0, line++ * spaceSize, "Progress %02d%%", progress); + renderSystem.SetColor(0.f, 0.2f, 0.f); + renderSystem.DrawLine(19 * fontSize, (line - 1) * spaceSize, 19 * fontSize + PROGRESS_MAX_LINES, (line - 1) + * spaceSize); + renderSystem.DrawLine(19 * fontSize, (line - 1) * spaceSize, 19 * fontSize, (line) * spaceSize); + renderSystem.DrawLine(19 * fontSize, (line) * spaceSize, 19 * fontSize + PROGRESS_MAX_LINES, (line) * spaceSize); + renderSystem.DrawLine(19 * fontSize + PROGRESS_MAX_LINES, (line - 1) * spaceSize, 19 * fontSize + + PROGRESS_MAX_LINES, (line) * spaceSize + 1); + renderSystem.SetColor(0.f, 0.5f, 0.f); + renderSystem.FillRectangle(19 * fontSize, (line - 1) * spaceSize, progress * PROGRESS_MAX_LINES / 100 + 1, + spaceSize); + + renderSystem.SetColor(1.f, 1.f, 1.f); + renderSystem.DrawText(0, line++ * spaceSize, ""); + + ::std::vector::iterator it; + for (it = operationMessage.begin(); it != operationMessage.end(); it++) + { + renderSystem.DrawText(0, line++ * spaceSize, "%s", it->c_str()); + } + + fontSize -= 2; + renderSystem.SetFontSize(fontSize); +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/DrawSystemState.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/DrawSystemState.h new file mode 100644 index 0000000..b1240a2 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/DrawSystemState.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: DrawSystemState.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef DRAWSYSTEMSTATE_H_ +#define DRAWSYSTEMSTATE_H_ + +#include +#include "demo.h" +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common_Types.h" + +// 謠冗判濶イ縺ョ螳夂セゥ +#define WHITE_COLOR 1.f, 1.f, 1.f, 1.f +#define GRAY_COLOR 0.5, 0.5, 0.5, 1.f +#define RED_COLOR 1.f, 0.f, 0.f, 1.f +#define GREEN_COLOR 0.f, 1.f, 0.f, 1.f +#define BLUE_COLOR 0.f, 0.f, 1.f, 1.f +#define SUCCESS_COLOR 0.f, 0.6f,0.f, 1.f +#define FAIL_COLOR 0.6f, 0.f,0.f, 1.f +#define NORMAL_COLOR 0.f, 0.f, 0.f, 1.f + +namespace common +{ + +u32 GetRenderTarget(u32 target, bool flip = false); + +void DrawSystemState +( + const char* toolName, + demo::RenderSystemDrawing& renderSystem, + nn::util::FloatColor titleColor, + bool flip, + std::string& adapterState, + const char* toolVersion, + common::VerDef* mVerData, + u8 batteryRemain, + u64 deviceId, + u64 friendCode, + u32 progress, + char8* macAddress, + ::std::vector& operationMessage, + nn::cfg::CTR::CfgRegionCode region, + u8* s_SerialNo +); + +} + + +#endif /* DRAWSYSTEMSTATE_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileChecker.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileChecker.cpp new file mode 100644 index 0000000..05f8b41 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileChecker.cpp @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: FileChecker.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include "FileChecker.h" +#include "SdMountManager.h" + +namespace common +{ + +bool s_FileExistsChecked[EXISTS_MAX]; +bool s_FileExistsCheckeResult[EXISTS_MAX]; + +bool CheckFileExists(const wchar_t* path) +{ + nn::Result result; + bool exist = false; + result = common::SdMountManager::Mount(); + + if (result.IsSuccess()) + { + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(path); + if(result.IsSuccess()) + { + exist = true; + } + fis.Finalize(); + } + + common::SdMountManager::Unmount(); + + + return exist; +} + +bool ExistsFile(FileExistsCheck index) +{ + if(index > EXISTS_MAX) + { + NN_LOG("Invalid File index!!\n"); + return false; + } + + if(s_FileExistsChecked[index]) + { + return s_FileExistsCheckeResult[index]; + } + + s_FileExistsChecked[index] = true; + s_FileExistsCheckeResult[index] = CheckFileExists(FILENAME_TABLE[index]); + return s_FileExistsCheckeResult[index]; +} + +bool ExistsUpdateCheckedFile() +{ + return ExistsFile(EXISTS_UPDATE_FINISHED); +} + +bool ExistsSerialNumberFile() +{ + return ExistsFile(EXISTS_SERIAL_NUMBER); +} + +bool ExistsIVSFile() +{ + return ExistsFile(EXISTS_IVS); +} + +bool ExistsConsoleInitializedFile() +{ + // 縺ゥ縺。繧峨°縺ョ繝輔ぃ繧、繝ォ縺後≠繧後ー蛻晄悄蛹匁ク医∩ + return ExistsFile(EXISTS_CONSOLE_INTIALIZED); +} + +bool ExistsWriteFinishedFile() +{ + return ExistsFile(EXISTS_WRITE_FINISHED); +} + +bool ExistsAPSetting() +{ + return ExistsFile(EXISTS_AP_SETTING); +} + +bool ExistsRtcSyncFinishedFile() +{ + return ExistsFile(EXISTS_RTC_SYNC_FINISHED); +} + +bool ExistsCountryLanguageFile() +{ + return ExistsFile(EXISTS_COUNTRY_LANGUAGE); +} + +bool ExistsVersionData() +{ + return ExistsFile(EXISTS_VERSION_DATA); +} + +bool ExistsRegionData() +{ + return ExistsFile(EXISTS_REGION_DATA); +} + +void InitializeFileCheck() +{ + for(u32 i = 0; i < EXISTS_MAX; i++) + { + s_FileExistsChecked[i] = false; + } +} + + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileChecker.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileChecker.h new file mode 100644 index 0000000..96b189c --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileChecker.h @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: FileChecker.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef FILECHECKER_H_ +#define FILECHECKER_H_ + +#include "FileName.h" + +namespace common +{ + +typedef enum FILE_EXISTS_CHECK +{ + EXISTS_UPDATE_FINISHED, + EXISTS_SERIAL_NUMBER, + EXISTS_IVS, + EXISTS_CONSOLE_INTIALIZED, + EXISTS_WRITE_FINISHED, + EXISTS_AP_SETTING, + EXISTS_RTC_SYNC_FINISHED, + EXISTS_COUNTRY_LANGUAGE, + EXISTS_VERSION_DATA, + EXISTS_REGION_DATA, + EXISTS_MAX +} FileExistsCheck; + +const wchar_t* const FILENAME_TABLE[EXISTS_MAX] = +{ + common::UPDATE_CHECK_PATHNAME, + common::SERIAL_PATHNAME, + common::IVS_PATHNAME, + common::INITIALIZED_CHECK_PATHNAME, + common::WRITE_FINISHED_CHECK_PATHNAME, + common::AP_SETTING_PATHNAME, + common::RTC_SYNC_CHECK_PATHNAME, + common::COUNTRY_SETTING_PATHNAME, + common::VERSION_DATA_PATHNAME, + common::REGION_DATA_PATHNAME +}; + +bool CheckFileExists(const wchar_t* path); +bool ExistsUpdateCheckedFile(); +bool ExistsSerialNumberFile(); +bool ExistsIVSFile(); +bool ExistsConsoleInitializedFile(); +bool ExistsWriteFinishedFile(); +bool ExistsAPSetting(); +bool ExistsRtcSyncFinishedFile(); +bool ExistsCountryLanguageFile(); +bool ExistsVersionData(); +bool ExistsRegionData(); + +void InitializeFileCheck(); + +} + +#endif /* FILECHECKER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileName.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileName.h new file mode 100644 index 0000000..2aeda6f --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileName.h @@ -0,0 +1,92 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: FileName.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef FILENAME_H_ +#define FILENAME_H_ + +#include + +namespace common +{ + +const char* const NAND_ARCHIVE_NAME = "nand:"; +const char* const SDMC_ARCHIVE_NAME = "sdmc:"; +const char* const NAND_TWL_PHOTO_ARCHIVE_NAME = "twlp:"; +const char* const NAND_TWL_SOUND_ARCHIVE_NAME = "twls:"; + +const wchar_t* const LOG_ROOT_DIRECTORY_PATH = L"sdmc:/CTR_Console_Repair"; +const wchar_t* const SD_SAVEDATA_ROOT_NAME = L"CTR_Console_Repair/CTRBackup/"; +const wchar_t* const SD_SAVEDATA_TWL_PHOTO_ROOT_NAME = L"CTR_Console_Repair/TWLPhotoBackup/"; +const wchar_t* const SD_SAVEDATA_TWL_SOUND_ROOT_NAME = L"CTR_Console_Repair/TWLSoundBackup/"; +const wchar_t* const NIM_SAVEDATA_DIRECTORY_NAME = L"sysdata/0001002c"; +const wchar_t* const LOG_PATHNAME = L"CTR_Console_Repair/Migration_Log.txt"; +const wchar_t* const LOG_FILENAME = L"Migration_Log.txt"; +const wchar_t* const COUNTRY_SETTING_PATHNAME = L"sdmc:/CTR_Console_Repair/CountrySetting.bin"; +const wchar_t* const AP_SETTING_FILENAME = L"CTR_Repair_Accsess_Point_Setting.txt"; +const wchar_t* const AP_SETTING_PATHNAME = L"sdmc:/CTR_Repair_Accsess_Point_Setting.txt"; +const wchar_t* const NOR_PATHNAME = L"sdmc:/CTR_Console_Repair/NtrNorSetting.bin"; +const wchar_t* const SERIAL_PATHNAME = L"sdmc:/CTR_Console_Repair/serial.bin"; +const wchar_t* const MCU_RTC_PATHNAME = L"sdmc:/CTR_Console_Repair/rtc.bin"; +const wchar_t* const IVS_NAND_PATHNAME = L"nand:/private/movable.sed"; +const wchar_t* const IVS_PATHNAME = L"sdmc:/CTR_Console_Repair/movable.sed"; +const wchar_t* const NAND_DATA_ROOT_PATHNAME_WITH_SLASH = L"nand:/data/"; +const wchar_t* const NAND_TWL_PHOTO_DATA_ROOT_PATHNAME_WITH_SLASH = L"twlp:/"; +const wchar_t* const NAND_TWL_SOUND_DATA_ROOT_PATHNAME_WITH_SLASH = L"twls:/"; +const wchar_t* const SDMC_ROOT_DIRECTORY_PATH = L"sdmc:/"; +const wchar_t* const WRITE_FINISHED_CHECK_PATHNAME = L"sdmc:/CTR_Console_Repair/WriteFinished"; +const wchar_t* const UPDATE_CHECK_PATHNAME = L"sdmc:/CTR_Console_Repair/UpdateFinished"; +const wchar_t* const INITIALIZED_CHECK_PATHNAME = L"sdmc:/CTR_Console_Repair/ConsoleInitialized"; +const wchar_t* const RTC_SYNC_CHECK_PATHNAME = L"sdmc:/CTR_Console_Repair/RtcSyncFinished"; +const wchar_t* const PLAYHISTORY_PATHNAME = L"sdmc:/CTR_Console_Repair/playhistory.bin"; +const wchar_t* const PLAYHISTORY_COUNT_PATHNAME = L"sdmc:/CTR_Console_Repair/playhistoryCount.bin"; +const wchar_t* const CFG_CALIBRATION_PATHNAME = L"sdmc:/CTR_Console_Repair/cfgCalibration.bin"; +const wchar_t* const VERSION_DATA_PATHNAME = L"sdmc:/CTR_Console_Repair/version.bin"; +const wchar_t* const REGION_DATA_PATHNAME = L"sdmc:/CTR_Console_Repair/Region.bin"; +const wchar_t* const DEVICE_ID_PATHNAME = L"sdmc:/CTR_Console_Repair/deviceId.bin"; + +enum TWL_PATH_INDEX +{ + TWL_PHOTO = 0, + TWL_SOUND, + TWL_PATHNAME_MAX +}; + +const char* const TWL_ARCHIVE_NAME_TABLE[TWL_PATHNAME_MAX] = +{ + common::NAND_TWL_PHOTO_ARCHIVE_NAME, + common::NAND_TWL_SOUND_ARCHIVE_NAME +}; + +const wchar_t* const SD_TWL_ROOTNAME_TABLE[TWL_PATHNAME_MAX] = +{ + common::SD_SAVEDATA_TWL_PHOTO_ROOT_NAME, + common::SD_SAVEDATA_TWL_SOUND_ROOT_NAME +}; + +const wchar_t* const NAND_TWL_ROOT_PATHNAME_WITH_SLASH_TABLE[TWL_PATHNAME_MAX] = +{ + common::NAND_TWL_PHOTO_DATA_ROOT_PATHNAME_WITH_SLASH, + common::NAND_TWL_SOUND_DATA_ROOT_PATHNAME_WITH_SLASH +}; + +const u32 TWL_FS_ARCHIVE_KIND[TWL_PATHNAME_MAX] = +{ + nn::fs::CTR::ARCHIVE_TYPE_TWL_PHOTO, + nn::fs::CTR::ARCHIVE_TYPE_TWL_SOUND +}; + +} + +#endif /* FILENAME_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileTransfer.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileTransfer.cpp new file mode 100644 index 0000000..7ce23f6 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileTransfer.cpp @@ -0,0 +1,534 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: FileTransfer.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include + +#include +#include +#include +#include + +#include "Aes_define.h" +#include "FileTransfer.h" +#include "CommonLogger.h" +#include "common_Types.h" + +namespace common +{ + +namespace +{ + +u64 s_TotalFileSize; +u64 s_FinishedFileSize = 0; +u64 s_Progress = 0; + +} + +bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bufSize); + +const char* GetCharStr(const wchar_t* path) +{ + static char filename[256]; + std::memset(filename, 0, sizeof(filename)); + std::wcstombs(filename, path, sizeof(filename)); + filename[sizeof(filename) - 1] = '\0'; + return filename; +} + +nn::Result CalculateFileNum(std::wstring currentDirectory, u32& fileNum, u32& fileSize) +{ + nn::fs::FileInputStream fis; + nn::fs::Directory dir; + nn::Result result; + std::vector entryList; //繧ォ繝ャ繝ウ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ繧ィ繝ウ繝医Μ荳隕ァ繧呈シ邏 + std::vector::iterator entryIndex; + + result = dir.TryInitialize(currentDirectory.c_str()); + + if(result.IsSuccess()) + { + nn::fs::DirectoryEntry entry; + s32 numEntry; + for(;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + if(result.IsFailure()) + { + dir.Finalize(); + return result; + } + if(numEntry == 0) + { + // 繧ォ繝ャ繝ウ繝医ョ繧」繝ャ繧ッ繝医Μ繧帝哩縺倥k + dir.Finalize(); + + // 繧ォ繝ャ繝ウ繝医ョ繧」繝ャ繧ッ繝医Μ縺ョ蟄舌r髢九¥ + for(entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++) + { + if(entryIndex->attributes.isDirectory) + { + CalculateFileNum(currentDirectory + std::wstring(entryIndex->entryName) + std::wstring(L"/"), fileNum, fileSize); + } + } + + return nn::ResultSuccess(); + } + + entryList.push_back(entry); + fileNum++; + fileSize+= entry.entrySize; + } + } + else + { + NN_LOG("failed initialize directory\n"); + dir.Finalize(); + return result; + } + +} + +// 繝繧」繝ャ繧ッ繝医Μ髢薙ョ繧ウ繝斐シ +// 繧「繝シ繧ォ繧、繝冶カ翫@縺ョ繧ウ繝斐シ縺悟庄閭ス +// 繧「繝シ繧ォ繧、繝悶↓繝槭え繝ウ繝医@縺溽憾諷九〒蜻シ縺ウ蜃コ縺吝ソ隕√≠繧 +// 譖ク縺崎セシ縺ソ蜈医ョ繝繧」繝ャ繧ッ繝医Μ縺ッ縺ゅi縺九§繧∵カ亥悉縺励※縺翫¥縺薙→縲 +// 蠑墓焚縺ッ繧ケ繝ゥ繝繧キ繝・莉倥″ +// TODO:蛻蜑イ縺励※遏ュ縺上☆繧 +bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf, const size_t bufSize, bool encode) +{ + nn::fs::Directory from_dir; + nn::fs::DirectoryEntry entry; + s32 numread = 0; + std::wostringstream target_from; + std::wostringstream target_to; + bool ret_value = true; + + nn::Result result = from_dir.TryInitialize(from_path); + + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + return false; + } + + while (1) + { + result = from_dir.TryRead(&numread, &entry, 1); + if (result.IsFailure() || numread != 1) + { + break; + } + + if (std::wcscmp(entry.entryName, L".") == 0 || std::wcscmp(entry.entryName, L"..") == 0) + { + continue; + } + + target_from.str(L""); + target_from.clear(std::stringstream::goodbit); + target_from << from_path << entry.entryName; + + target_to.str(L""); + target_to.clear(std::stringstream::goodbit); + target_to << to_path << entry.entryName; + + // 繝繧」繝ャ繧ッ繝医Μ縺ョ蝣エ蜷 + if (entry.attributes.isDirectory) + { + // 繝繧」繝ャ繧ッ繝医Μ菴懈 + NN_LOG("Create Directory %ls\n", target_to.str().c_str()); + result = nn::fs::TryCreateDirectory(target_to.str().c_str()); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + else + { + target_from << L"/"; + target_to << L"/"; + // 蜀榊クー蜃ヲ逅 + if (!CopyDirectory(target_from.str().c_str(), target_to.str().c_str(), buf, bufSize, encode)) + { + ret_value = false; + } + } + } + // 繝輔ぃ繧、繝ォ縺ョ蝣エ蜷 + else + { + // 繝輔ぃ繧、繝ォ菴懈 + nn::fs::FileInputStream from_file; + nn::fs::FileOutputStream to_file; + s64 filesize; + s64 fileSizeWithoutHeaderAndFooter; + s32 readsize; + s32 writesize; + + NN_LOG("Copy File %ls\n", target_from.str().c_str()); + + // 隱ュ縺ソ霎シ縺ソ蟇セ雎。繝輔ぃ繧、繝ォ髢九¥ + result = from_file.TryInitialize(target_from.str().c_str()); + + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + else + { + // 隱ュ縺ソ霎シ縺ソ蟇セ雎。繝輔ぃ繧、繝ォ縺ョ繧オ繧、繧コ蜿門セ + result = from_file.TryGetSize(&filesize); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + else + { + // 蠕ゥ蜿キ縺吶k縺ェ繧峨∪縺壽、懆ィシ縺吶k + if(!encode) + { + NN_LOG("Verify CMAC %ls\n", target_from.str().c_str()); + if(!VerifyMac(&from_file, filesize, buf, bufSize)) + { + COMMON_LOGGER("Verification Failed %s\n", GetCharStr(target_from.str().c_str())); + ret_value = false; + break; + } + } + + nn::crypto::SwAesCtrContext swAesCtrContext; + swAesCtrContext.Initialize(iv, common::key, sizeof(key)); + + size_t totalReadSize = 0; + nn::crypto::Sha256Context context; + context.Initialize(); + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ繧偵倥ャ繝縺ォ譖ク縺縺ヲ縺翫¥ + if (encode) + { + // 譖ク縺崎セシ縺ソ蟇セ雎。繝輔ぃ繧、繝ォ菴懈 + result = nn::fs::TryCreateFile(target_to.str().c_str(), filesize); + result = to_file.TryInitialize(target_to.str().c_str(), false); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + + BackupDataHeader header; + BackupDataHeader enc; + header.size = filesize; + result = swAesCtrContext.Encrypt(&enc, &header, sizeof(header)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + context.Update(&enc, sizeof(enc)); + s32 writeSize; + result = to_file.TryWrite(&writeSize, &enc, sizeof(enc), false); + if (result.IsFailure()) + { + ret_value = false; + continue; + } + } + else + { + // 繝倥ャ繝繧定ェュ繧 + // 繝上ャ繧キ繝・縺ョ險育ョ励ッ邨ゅo縺」縺ヲ縺繧九ョ縺ァ蠕ゥ蜿キ蛹悶ョ縺ソ + BackupDataHeader header; + BackupDataHeader dec; + s32 readSize; + result = from_file.TryRead(&readSize, &header, sizeof(header)); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + ret_value = false; + continue; + } + s_FinishedFileSize += sizeof(header); + swAesCtrContext.Decrypt(&dec, &header, sizeof(header)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + fileSizeWithoutHeaderAndFooter = dec.size; + + // 譖ク縺崎セシ縺ソ蟇セ雎。繝輔ぃ繧、繝ォ菴懈 + result = nn::fs::TryCreateFile(target_to.str().c_str(), fileSizeWithoutHeaderAndFooter); + result = to_file.TryInitialize(target_to.str().c_str(), false); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + } + + while (1) + { + // 繝舌ャ繝輔ぃ縺ョ蠕悟濠蜊雁繧呈囓蜿キ繝サ蠕ゥ蜿キ逕ィ縺ォ菴ソ縺 + result = from_file.TryRead(&readsize, buf, bufSize / 2); + totalReadSize += readsize; + + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + break; + } + else + { + if (readsize == 0) + { + if (encode) + { + NN_LOG("Add CMAC %ls\n", target_from.str().c_str()); + // SHA256繧定ィ育ョ励@縺ヲCMAC繧剃サ伜刈縺吶k + bit8 sha256Hash[nn::crypto::Sha256Context::HASH_SIZE]; + context.GetHash(sha256Hash); + + bit8 cmac[nn::crypto::AES_CMAC_MAC_SIZE]; + result = nn::crypto::CalculateAesCmacSw(cmac, sha256Hash, + nn::crypto::Sha256Context::HASH_SIZE, common::cmacKey); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = to_file.TryWrite(&writesize, cmac, sizeof(cmac)); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + ret_value = false; + } + } + + result = to_file.TryFlush(); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + break; + } + else + { + if (encode) + { + NN_LOG("EncryptSize = %d\n", readsize); + + u8 paddingSize = 0; + // 譛蠕後ョ譖ク縺崎セシ縺ソ譎ゅ↓縺ッPKCS5縺ァ繝代ョ繧」繝ウ繧ー縺吶k + if (readsize < bufSize / 2) + { + if ((readsize % AES_BLOCK_SIZE) != 0) + { + paddingSize = AES_BLOCK_SIZE - readsize % AES_BLOCK_SIZE; + std::memset(reinterpret_cast (buf) + readsize, paddingSize, + paddingSize); + readsize += paddingSize; + } + } + + // 證怜捷蛹門セ郡HA256繧定ィ育ョ励@縺、縺、譖ク縺崎セシ縺ソ + result = swAesCtrContext.Encrypt(reinterpret_cast (buf) + bufSize / 2, buf, + readsize); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + context.Update(reinterpret_cast (buf) + bufSize / 2, readsize); + + result = to_file.TryWrite(&writesize, reinterpret_cast (buf) + bufSize / 2, + readsize, false); + + // 莠句燕險育ョ励@縺溘ヵ繧。繧、繝ォ繧オ繧、繧コ縺ォ荳閾エ縺輔○繧九◆繧√ヱ繝繧」繝ウ繧ー蛻貂帷ョ + readsize -= paddingSize; + + s_FinishedFileSize += readsize; + s_Progress = s_FinishedFileSize * 100 / s_TotalFileSize; + NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); + } + else + { + // 繝上ャ繧キ繝・讀懆ィシ縺ッ騾壹▲縺ヲ縺繧九ョ縺ァ蠕ゥ蜿キ蛹悶@縺、縺、譖ク縺崎セシ縺ソ + // 繝代ョ繧」繝ウ繧ー莉・髯阪ッ譖ク縺崎セシ縺セ縺ェ縺繧医≧譖ク縺崎セシ縺ソ繧オ繧、繧コ繧貞、画峩縺吶k + + NN_LOG("DecryptSize = %d\n", readsize); + result = swAesCtrContext.Decrypt(reinterpret_cast (buf) + bufSize / 2, buf, + readsize); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // 繝代ョ繧」繝ウ繧ー縺セ縺ァ隱ュ繧薙□縺九←縺縺 + bool readDone = false; + // 繝代ョ繧」繝ウ繧ー縺セ縺ァ隱ュ繧薙〒縺縺溘i譖ク縺崎セシ縺ソ繧オ繧、繧コ繧呈ク帙i縺 + if (fileSizeWithoutHeaderAndFooter < totalReadSize) + { + readsize -= totalReadSize - fileSizeWithoutHeaderAndFooter; + readDone = true; + s_FinishedFileSize += totalReadSize - fileSizeWithoutHeaderAndFooter; + } + + result = to_file.TryWrite(&writesize, reinterpret_cast (buf) + bufSize / 2, + readsize, false); + s_FinishedFileSize += readsize; + s_Progress = s_FinishedFileSize * 100 / s_TotalFileSize; + NN_LOG("finish = %lld, total = %lld, progress = %lld\n", s_FinishedFileSize, s_TotalFileSize, s_Progress); + + // 隱ュ縺ソ縺阪▲縺溘ョ縺ァ谺。縺ョ繝輔ぃ繧、繝ォ縺ク + if (readDone) + { + result = to_file.TryFlush(); + if (result.IsFailure()) + { + ret_value = false; + } + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + break; + } + } + + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + ret_value = false; + } + + } + } + } + to_file.Finalize(); + } + } + from_file.Finalize(); + } + } + + from_dir.Finalize(); + return ret_value; +} + +u32 GetProgress() +{ + return s_Progress; +} + +void InitializeTransferProgress(u64 totalSize) +{ + s_TotalFileSize = totalSize; + s_FinishedFileSize = 0; +} + +bool CalculateAndCompareCmac(nn::crypto::Sha256Context* context, bit8* sdCmac) +{ + nn::Result result; + bit8 sha256Hash[nn::crypto::Sha256Context::HASH_SIZE]; + bit8 cmac[nn::crypto::AES_CMAC_MAC_SIZE]; + + context->GetHash(sha256Hash); + context->Finalize(); + + result = nn::crypto::CalculateAesCmacSw(cmac, sha256Hash, sizeof(sha256Hash), common::cmacKey); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + return false; + } + + return std::memcmp(cmac, sdCmac, sizeof(cmac)) == 0; +} + + +bool VerifyMac(nn::fs::FileInputStream* file, s64 filesize, void* buf, size_t bufSize) +{ + nn::Result result; + bit8 sdCmac[nn::crypto::AES_CMAC_MAC_SIZE]; + + // 繝上ャ繧キ繝・縺御サ伜刈縺輔l縺ヲ縺縺ェ縺縺ィ繧ィ繝ゥ繝シ + if(filesize < nn::crypto::AES_CMAC_MAC_SIZE) + { + return false; + } + + s32 readSize; + // 繝上ャ繧キ繝・繧貞叙蠕励☆繧 + nn::crypto::Initialize(); + result = file->TrySetPosition(filesize - nn::crypto::AES_CMAC_MAC_SIZE); + if (result.IsSuccess()) + { + result = file->TryRead(&readSize, sdCmac, sizeof(sdCmac)); + if(result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + return false; + } + } + else + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + return false; + } + + file->SetPosition(0); + + // 繝上ャ繧キ繝・繧定ィ育ョ励☆繧 + nn::crypto::Sha256Context context; + context.Initialize(); + bool ret_value = false; + + size_t totalReadSize = 0; + while (1) + { + result = file->TryRead(&readSize, buf, bufSize); + totalReadSize += readSize; + + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + ret_value = false; + break; + } + else + { + if (readSize == 0) + { + ret_value = CalculateAndCompareCmac(&context, sdCmac); + break; + } + else + { + bool readDone = false; + // 繝上ャ繧キ繝・驛ィ蛻縺セ縺ァ隱ュ繧薙〒縺縺溘i繝上ャ繧キ繝・讀懆ィシ繧オ繧、繧コ繧呈ク帙i縺 + size_t fileSizeWithoutCmac = filesize - nn::crypto::AES_CMAC_MAC_SIZE; + if (fileSizeWithoutCmac < totalReadSize) + { + readSize -= totalReadSize - fileSizeWithoutCmac; + readDone = true; + } + + context.Update(buf, readSize); + if(readDone) + { + ret_value = CalculateAndCompareCmac(&context, sdCmac); + break; + } + + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + ret_value = false; + } + } + } + } + nn::crypto::Finalize(); + + file->SetPosition(0); + + return ret_value; +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileTransfer.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileTransfer.h new file mode 100644 index 0000000..7af37f2 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/FileTransfer.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: FileTransfer.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef FILETRANSFER_H_ +#define FILETRANSFER_H_ + +#include +#include +#include + +namespace common +{ + +nn::Result CalculateFileNum(std::wstring currentDirectory, u32& fileNum, u32& fileSize); +bool CopyDirectory(const wchar_t * from_path, const wchar_t * to_path, void* buf, const size_t bufSize, bool encode); +u32 GetProgress(); +void InitializeTransferProgress(u64 totalSize); + +} + +#endif /* FILETRANSFER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HardwareInfo.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HardwareInfo.cpp new file mode 100644 index 0000000..abf3edd --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HardwareInfo.cpp @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: HardwareInfo.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include "HardwareInfo.h" + +#include + +namespace common +{ + +HardwareInfo::HardwareInfo() +{ + // TODO 閾ェ蜍慕函謌舌&繧後◆繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ繝シ繝サ繧ケ繧ソ繝 + +} + +HardwareInfo::~HardwareInfo() +{ + // TODO Auto-generated destructor stub +} + +// NULL邨らォッ縺輔l縺溘す繝ェ繧「繝ォ繝翫Φ繝舌シ繧貞女縺大叙繧 +// NULL邨らォッ縺輔l縺溷エ謇縺ォ繝√ぉ繝繧ッ繝繧ク繝繝医r莉伜刈縺励※譁ー縺溘↓NULL邨らォッ縺吶k +void HardwareInfo::AddCheckDigit(char* serial) +{ + size_t len = std::strlen(serial); + + u8 digit = 0; + bool odd = true; + for(u8 i = len - 1; i > 0 && std::isdigit(serial[i]); i--) + { + if(odd) + { + digit += (serial[i] - '0') * 3; + } + else + { + digit += (serial[i] - '0'); + } + odd = !odd; + } + + if(digit % 10 != 0) + { + serial[len] = 10 - (digit % 10) + '0'; + } + else + { + serial[len] = '0'; + } + + serial[len + 1] = '\0'; +} + + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HardwareInfo.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HardwareInfo.h new file mode 100644 index 0000000..e6406cf --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HardwareInfo.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: HardwareInfo.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef HARDWAREINFO_H_ +#define HARDWAREINFO_H_ + +namespace common +{ + +class HardwareInfo +{ +public: + HardwareInfo(); + virtual ~HardwareInfo(); + + void AddCheckDigit(char* serial); +}; + +} + +#endif /* HARDWAREINFO_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HeapManager.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HeapManager.cpp new file mode 100644 index 0000000..29f4367 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HeapManager.cpp @@ -0,0 +1,39 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: HeapManager.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include "HeapManager.h" + +namespace common +{ + +nn::fnd::ThreadSafeExpHeap HeapManager::s_AppHeap; + +HeapManager::HeapManager() +{ + // TODO 閾ェ蜍慕函謌舌&繧後◆繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ繝シ繝サ繧ケ繧ソ繝 + +} + +HeapManager::~HeapManager() +{ + // TODO Auto-generated destructor stub +} + +nn::fnd::ThreadSafeExpHeap* HeapManager::GetHeap() +{ + return &s_AppHeap; +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HeapManager.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HeapManager.h new file mode 100644 index 0000000..b9fc469 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/HeapManager.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: HeapManager.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef HEAPMANAGER_H_ +#define HEAPMANAGER_H_ + +#include + +namespace common +{ + +class HeapManager +{ +public: + HeapManager(); + virtual ~HeapManager(); + + static nn::fnd::ThreadSafeExpHeap* GetHeap(); + +private: + // 繝繝舌う繧ケ繝。繝「繝ェ邂。逅逕ィ諡。蠑オ繝偵シ繝 + static nn::fnd::ThreadSafeExpHeap s_AppHeap; + +}; + +} // namespace common + +#endif /* HEAPMANAGER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/LogConsole.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/LogConsole.cpp new file mode 100644 index 0000000..b77d6d0 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/LogConsole.cpp @@ -0,0 +1,171 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: LogConsole.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include "LogConsole.h" +#include + +namespace common +{ + +const size_t FONT_WIDTH = 8; +const size_t FONT_HEIGHT = 10; + +static LogConsole s_LogConsole; + +LogConsole* GetConsoleInstance() +{ + return &s_LogConsole; +} + +LogConsole::LogConsole() +{ + +} + +LogConsole::~LogConsole() +{ + +} + +void LogConsole::Initialize(u32 width, u32 height, u32 maxLine, demo::RenderSystemDrawing* renderSystem) +{ + m_Width = width; + m_Height = height; + m_MaxLine = maxLine; + m_RenderSystem = renderSystem; + m_CurrentViewLine = 0; + m_LineNum = 0; +} + +void LogConsole::AddText(const char* fmt, ::std::va_list arg) +{ + s32 stringSize; + const size_t STRING_BUFFER_SIZE = 256; + char formatStr[STRING_BUFFER_SIZE]; + + stringSize = nn::nstd::TVSNPrintf(formatStr, sizeof(formatStr), fmt, arg); + ::std::string str(formatStr); + + size_t addedText = 0; + while (addedText < stringSize) + { + if(m_LineNum >= m_MaxLine) + { + // 貅譚ッ縺ェ縺ョ縺ァ蜈磯ュ繧貞炎髯、縺吶k + ::std::vector::iterator it; + it = m_Log.begin(); + m_Log.erase(it); + m_LineNum--; + } + + // 驛ィ蛻譁蟄怜励r霑ス蜉 + AddWrapedText(str.substr(addedText, m_Width).c_str()); + m_LineNum++; + + // 逕サ髱「鬆伜沺莉・荳願ソス蜉縺励◆繧画忰蟆セ縺ォ繧ケ繧ッ繝ュ繝シ繝ォ縺吶k + if(m_LineNum > m_Height) + { + ScrollToEnd(); + } + + + if(stringSize - addedText > m_Width) + { + addedText += m_Width; + } + else + { + addedText += stringSize - addedText; + } + } +} + +void LogConsole::ScrollUp() +{ + if(m_CurrentViewLine > 0) + { + m_CurrentViewLine--; + } +} + + + +void LogConsole::ScrollDown() +{ + if (m_LineNum > m_Height) + { + if (m_CurrentViewLine < m_LineNum - m_Height) + { + m_CurrentViewLine++; + } + + } +} + +void LogConsole::ScrollToBegin() +{ + m_CurrentViewLine = 0; +} + +void LogConsole::ScrollToEnd() +{ + if(m_LineNum > m_Height) + { + m_CurrentViewLine = m_LineNum - m_Height; + } +} + + +void LogConsole::Print() +{ + ::std::vector::iterator it; + + it = m_Log.begin(); + it += m_CurrentViewLine; + + u32 count = 0; + for(; it != m_Log.end() && count < m_Height && count < m_MaxLine; it++) + { + m_RenderSystem->DrawText(0, count++ * 10, "%s", it->c_str()); + } + + if(m_LineNum > m_Height) + { + DrawScrollBar(); + } +} + + +void LogConsole::AddWrapedText(const char* str) +{ + m_Log.push_back(::std::string(str)); +} + +void LogConsole::DrawScrollBar() +{ + m_RenderSystem->SetColor(0.4f, 0.4f, 0.4f); + m_RenderSystem->DrawLine((m_Width + 1) * FONT_WIDTH, 0, (m_Width + 2) * FONT_WIDTH - 1, 0); + m_RenderSystem->DrawLine((m_Width + 1)* FONT_WIDTH, 0, (m_Width + 1)* FONT_WIDTH, m_Height * FONT_HEIGHT); + m_RenderSystem->DrawLine((m_Width + 2) * FONT_WIDTH - 1, 0, (m_Width + 2) * FONT_WIDTH - 1, m_Height * FONT_HEIGHT); + m_RenderSystem->DrawLine((m_Width + 1)* FONT_WIDTH, m_Height * FONT_HEIGHT - 1, (m_Width + 2) * FONT_WIDTH - 1, m_Height * FONT_HEIGHT - 1); + + u32 y = (m_Height * FONT_HEIGHT - 2) * m_CurrentViewLine / m_MaxLine; + m_RenderSystem->SetColor(0.7f, 0.7f, 0.7f); + m_RenderSystem->FillRectangle((m_Width + 1) * FONT_WIDTH, y + 1, FONT_WIDTH - 1, FONT_HEIGHT - 4); + + m_RenderSystem->SetColor(1.f, 1.f, 1.f); +} + +} //namespace ConsoleBackup diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/LogConsole.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/LogConsole.h new file mode 100644 index 0000000..b8a7d52 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/LogConsole.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: LogConsole.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef LOGCONSOLE_H_ +#define LOGCONSOLE_H_ + +#include +#include +#include +#include "demo.h" + +namespace common +{ + +//! @brief 逕サ髱「縺ォ繝繧ュ繧ケ繝医さ繝ウ繧ス繝シ繝ォ繧呈緒逕サ縺励∪縺 +class LogConsole +{ + +public: + LogConsole(); + ~LogConsole(); + + void Initialize(u32 width, u32 height, u32 maxLine, demo::RenderSystemDrawing* renderSystem); + + void AddText(const char* fmt, ::std::va_list arg); + void ScrollUp(); + void ScrollDown(); + void ScrollToBegin(); + void ScrollToEnd(); + void Print(); + +private: + void AddWrapedText(const char* str); + void DrawScrollBar(); + + ::std::vector m_Log; + + //! @brief 繧ウ繝ウ繧ス繝シ繝ォ縺ョ蛻玲焚 + u32 m_Width; + //! @brief 繧ウ繝ウ繧ス繝シ繝ォ縺ョ陦梧焚 + u32 m_Height; + //! @brief 繧ウ繝ウ繧ス繝シ繝ォ縺ョ繝ュ繧ー縺ョ譛螟ァ陦梧焚 + u32 m_MaxLine; + //! @brief 謠冗判縺ョ縺溘a縺ョRenderSystemDrawing縺ク縺ョ繝昴う繝ウ繧ソ + demo::RenderSystemDrawing* m_RenderSystem; + //! @brief 霑ス蜉縺励◆繝ュ繧ー縺ョ陦梧焚 + u32 m_LineNum; + //! @brief 陦ィ遉コ繧帝幕蟋九☆繧九Ο繧ー縺ョ陦梧焚 + u32 m_CurrentViewLine; + + +}; + +} + +#endif /* LOGCONSOLE_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/LogConsole_Private.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/LogConsole_Private.h new file mode 100644 index 0000000..8fbdd42 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/LogConsole_Private.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: LogConsole_Private.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef LOGCONSOLE_PRIVATE_H_ +#define LOGCONSOLE_PRIVATE_H_ + +#include "LogConsole.h" + +namespace common +{ + +LogConsole* GetConsoleInstance(); + +} + +#endif /* LOGCONSOLE_PRIVATE_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/OMakefile b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/OMakefile new file mode 100644 index 0000000..e874cbc --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/OMakefile @@ -0,0 +1,18 @@ +#!/usr/bin/env omake +#---------------------------------------------------------------------------- +# Project: Horizon +# File: OMakefile +# +# 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. +# +# $Rev$ +#---------------------------------------------------------------------------- +include $(ROOT_OMAKE)/modulerules + +DefineDefaultRules() diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/PlayHistoryManager.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/PlayHistoryManager.cpp new file mode 100644 index 0000000..b10d4b7 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/PlayHistoryManager.cpp @@ -0,0 +1,224 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: PlayHistoryManager.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include + +#include "PlayHistoryManager.h" +#include "HeapManager.h" +#include "SdMountManager.h" +#include "SdReaderWriter.h" +#include "CommonLogger.h" +#include "FileName.h" +#include "ProgramId.h" + +namespace common +{ + +PlayHistoryManager::PlayHistoryManager() +{ + // TODO 閾ェ蜍慕函謌舌&繧後◆繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ繝シ繝サ繧ケ繧ソ繝 + +} + +PlayHistoryManager::~PlayHistoryManager() +{ + // TODO Auto-generated destructor stub +} + +void PlayHistoryManager::Export() +{ + nn::Result result; + SdMountManager::Mount(); + SdReaderWriter sd; + + size_t historyNum = nn::pl::CTR::GetPlayHistoryLength(); + if ( historyNum == 0) + { + NN_LOG("No Play Event\n"); + return; + } + + // SD縺ォ譖ク縺崎セシ繧 + result = sd.WriteBufWithCmac(common::PLAYHISTORY_COUNT_PATHNAME, reinterpret_cast(&historyNum), + sizeof(historyNum)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + nn::pl::CTR::PlayEvent* pEvent; + pEvent = reinterpret_cast (HeapManager::GetHeap()->Allocate( + sizeof(nn::pl::CTR::PlayEvent) * historyNum)); + if ( pEvent == NULL ) + { + NN_LOG("Failed to Allocate Heap\n"); + return; + } + + // 荳逡ェ蜿、縺繝繝シ繧ソ縺九i邏逶エ縺ォ蜈ィ驛ィ隱ュ縺ソ霎シ繧 + nn::pl::CTR::GetPlayHistory(pEvent, 0, historyNum); + + // SD縺ォ譖ク縺崎セシ繧 + result = sd.WriteBufWithCmac(common::PLAYHISTORY_PATHNAME, reinterpret_cast(pEvent), + sizeof(nn::pl::CTR::PlayEvent) * historyNum); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + HeapManager::GetHeap()->Free(pEvent); + + SdMountManager::Unmount(); +} + +nn::Result PlayHistoryManager::GetPlayHistoryNums(size_t* nums) +{ + nn::Result result = nn::ResultSuccess(); + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::PLAYHISTORY_COUNT_PATHNAME, buf, bufSize, &readSize); + if (result.IsSuccess()) + { + *nums = *reinterpret_cast (buf); + } + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + HeapManager::GetHeap()->Free(buf); + } + return result; +} + +nn::Result PlayHistoryManager::Import() +{ + nn::Result result = nn::ResultSuccess(); + SdMountManager::Mount(); + SdReaderWriter sd; + + SdMountManager::Mount(); + + // 繝励Ξ繧、螻・豁エ縺ョ莉カ謨ー繧貞叙蠕励☆繧 + size_t historyNum = 0; + + GetPlayHistoryNums(&historyNum); + + if(historyNum == 0) + { + NN_LOG("No PlayHistory found\n"); + return nn::Result(nn::Result::LEVEL_PERMANENT, nn::Result::SUMMARY_NOT_FOUND, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_NOT_FOUND); + } + + size_t bufSize = common::HeapManager::GetHeap()->GetAllocatableSize(); + void* buf = common::HeapManager::GetHeap()->Allocate(bufSize); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::PLAYHISTORY_PATHNAME, buf, bufSize, &readSize); + if(result.IsSuccess()) + { + nn::pl::CTR::PlayEvent* pEvent = reinterpret_cast(buf); + NN_LOG("history num = %d\n", historyNum); + + // 繝励Ξ繧、螻・豁エ繧堤┌蜉ケ蛹悶☆繧 + nn::pl::CTR::ClearPlayHistory(); + + // 繝繝シ繧ソ遘サ陦後ヤ繝シ繝ォ繧堤┌隕悶@縺ヲ譖ク縺崎セシ繧 + for(u32 i = 0; i < historyNum; i++) + { + COMMON_LOGGER("Importing PlayHistory %d/%d", i, historyNum); + if ((pEvent[i].GetProgramId() & WITHOUT_VALIATION_MASK) != CONSOLE_BACKUP_PROGRAM_ID + && (pEvent[i].GetProgramId() & WITHOUT_VALIATION_MASK) != CONSOLE_RESTORE_PROGRAM_ID) + { + NN_LOG("%05d 0x%16llx : %X : %d\n", i, pEvent[i].GetProgramId(), pEvent[i].GetEventType(), + pEvent[i].minutes); + + nn::pl::CTR::NotifyPlayEvent(pEvent[i].GetEventType(), pEvent[i].GetProgramId(), + pEvent[i].GetEventTime()); + } + else + { + NN_LOG("Skipped\n"); + } + } + + } + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + common::HeapManager::GetHeap()->Free(buf); + } + else + { + NN_LOG("Failed Allocate Heap!! %s, %d", __FILE__, __LINE__); + return result; + } + + SdMountManager::Unmount(); + + return result; +} + +void PlayHistoryManager::Dump() +{ + nn::Result result; + + s32 playEventLength = nn::pl::CTR::GetPlayHistoryLength(); + if ( playEventLength == 0 ) + { + NN_LOG("No Play Event\n"); + return; + } + + nn::pl::CTR::PlayEvent* playEvent = reinterpret_cast (HeapManager::GetHeap()->Allocate( + sizeof(nn::pl::CTR::PlayEvent) * playEventLength)); + if ( playEvent == NULL ) + { + NN_LOG("Failed to Allocate Heap\n"); + return; + } + + // 荳逡ェ蜿、縺繝繝シ繧ソ縺九i邏逶エ縺ォ蜈ィ驛ィ隱ュ縺ソ霎シ繧 + (void)nn::pl::CTR::GetPlayHistory(playEvent, 0, playEventLength); + + // 蜿門セ励@縺溘ョ繝シ繧ソ繧帝逡ェ縺ォ縺吶∋縺ヲ陦ィ遉コ縺励※縺縺 + s32 restPlayEventLength = playEventLength; + s32 displayCount = 0; + + nn::pl::CTR::PlayEvent* pEvent; + while ( restPlayEventLength > 0 ) + { + // 荳豌励↓陦ィ遉コ縺ァ縺阪k縺ィ縺薙m縺セ縺ァ陦ィ遉コ縺吶k + int line; + for ( line = 0; line < 24; line++ ) + { + pEvent = &playEvent[displayCount]; + NN_LOG("0x%16llx : %X : %d\n", pEvent->GetProgramId(), pEvent->eventType, pEvent->minutes); + restPlayEventLength--; + displayCount++; + if(restPlayEventLength <= 0) + { + break; + } + } + } + NN_UNUSED_VAR(pEvent); + + HeapManager::GetHeap()->Free(playEvent); + return; +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/PlayHistoryManager.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/PlayHistoryManager.h new file mode 100644 index 0000000..73afb52 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/PlayHistoryManager.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: PlayHistoryManager.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef PLAYHISTORYMANAGER_H_ +#define PLAYHISTORYMANAGER_H_ + +namespace common +{ + +//! @brief 繝繝シ繧ソ遘サ陦後ヤ繝シ繝ォ縺ョ螻・豁エ繧呈カ医@縺ェ縺後i繝励Ξ繧、螻・豁エ繧堤ァサ陦後☆繧九◆繧√ョ繧ッ繝ゥ繧ケ縺ァ縺吶 +class PlayHistoryManager +{ +public: + PlayHistoryManager(); + virtual ~PlayHistoryManager(); + + //! @brief SD繧ォ繝シ繝峨↓蜃コ蜉帙@縺セ縺吶 + void Export(); + + //! @brief SD繧ォ繝シ繝峨°繧峨励Ξ繧、螻・豁エ縺ォ譖ク縺崎セシ縺ソ縺セ縺 + nn::Result Import(); + + //! @brief 繝繝舌ャ繧ー逕ィ縲ゅ励Ξ繧、螻・豁エ繧偵ョ繝舌ャ繧ー蜃コ蜉帙@縺セ縺吶 + void Dump(); + +private: + nn::Result GetPlayHistoryNums(size_t* nums); + +}; + +} + +#endif /* PLAYHISTORYMANAGER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/ProgramId.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/ProgramId.h new file mode 100644 index 0000000..c565f11 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/ProgramId.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ProgramId.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef PROGRAMID_H_ +#define PROGRAMID_H_ + +namespace common +{ + +const u64 CONSOLE_BACKUP_PROGRAM_ID = 0x000400000f802200L; +const u64 CONSOLE_RESTORE_PROGRAM_ID = 0x000400000f802300L; +const u64 WITHOUT_VALIATION_MASK = 0xffffffffffffff00L; + +} + +#endif /* PROGRAMID_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdLogger.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdLogger.cpp new file mode 100644 index 0000000..5fb7068 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdLogger.cpp @@ -0,0 +1,267 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdLogger.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include "SdLogger.h" +#include +#include "SDMountManager.h" +#include "FileName.h" + +namespace common +{ + +namespace Logger +{ + +static SdLogger s_SdLogger; +static nn::os::LightEvent s_SdEjectedEvent; +static nn::os::LightEvent s_SdInsertedEvent; + +const size_t SDMC_EVENT_THREAD_STACK_SIZE = 1024; +nn::os::Thread s_SdmcEjectedEventThread; +nn::os::StackBuffer s_SdmcEjectedEventThreadStack; + +nn::os::Thread s_SdmcInsertedEventThread; +nn::os::StackBuffer s_SdmcInsertedEventThreadStack; + +void (*s_SdEjectedEventFunc)() = NULL; +void (*s_SdInsertedEventFunc)() = NULL; + +void PrintResultIfFailed(nn::Result result, u32 line = 0) +{ + if (result.IsFailure()) + { + if(line != 0) + { + NN_LOG("%s, %d\n", __FILE__, line); + } + nn::dbg::PrintResult(result); + } +} + +void SdmcEjectedEventThreadFunc() +{ + NN_LOG("********************:SD Ejected Event Thread Start**********************\n"); + + for(;;) + { + s_SdEjectedEvent.Wait(); + NN_LOG("********************:SD Card Ejected**********************\n"); + + if(s_SdEjectedEventFunc != NULL) + { + s_SdEjectedEventFunc(); + } + SdMountManager::ForceUnmount(); + s_SdEjectedEvent.ClearSignal(); + s_SdLogger.Inactivate(); + } +} + +void SdmcInsertedEventThreadFunc() +{ + NN_LOG("********************:SD Inserted Event Thread Start**********************\n"); + + for(;;) + { + s_SdInsertedEvent.Wait(); + NN_LOG("********************:SD Card Inserted*********************\n"); + + if(s_SdInsertedEventFunc != NULL) + { + s_SdInsertedEventFunc(); + } + s_SdInsertedEvent.ClearSignal(); + } +} + +void InitializeEjectThread() +{ + s_SdEjectedEvent.Initialize(true); + s_SdInsertedEvent.Initialize(true); + nn::fs::RegisterSdmcEjectedEvent(&s_SdEjectedEvent); + nn::fs::RegisterSdmcInsertedEvent(&s_SdInsertedEvent); + + // SD繧ォ繝シ繝画栢縺代r讀懃衍縺吶k縺溘a縺ョ繧ケ繝ャ繝繝我ス懈 + s_SdmcEjectedEventThread.Start(SdmcEjectedEventThreadFunc, s_SdmcEjectedEventThreadStack); + + // SD繧ォ繝シ繝画諺蜈・繧呈、懃衍縺吶k縺溘a縺ョ繧ケ繝ャ繝繝我ス懈 + s_SdmcInsertedEventThread.Start(SdmcInsertedEventThreadFunc, s_SdmcInsertedEventThreadStack); + +} +void SetEjectHandler(void (*func)()) +{ + s_SdEjectedEventFunc = func; +} + +void SetInsertHandler(void (*func)()) +{ + s_SdInsertedEventFunc = func; +} + +SdLogger::SdLogger() : m_TryActivate(false), m_Permitted(false) +{ + +} + +SdLogger* GetSdInstance() +{ + return &s_SdLogger; +} + +void SdLogger::Print(const char* fmt, ::std::va_list arg) +{ + Activate(); + if(!m_Permitted) + { + NN_LOG("SD Write Not Permitted\n"); + return; + } + + nn::Result result; + result = SdMountManager::Mount(); + if (result.IsFailure()) + { + PrintResultIfFailed(result, __LINE__); + } + + s32 stringSize; + const size_t STRING_BUFFER_SIZE = 256; + char str[STRING_BUFFER_SIZE]; + + stringSize = nn::nstd::TVSNPrintf(str, sizeof(str), fmt, arg); + + ::std::wstring log(common::SDMC_ROOT_DIRECTORY_PATH); + log += common::LOG_PATHNAME; + + // 繝繧」繝ャ繧ッ繝医Μ縺檎┌縺代l縺ー菴懊k + nn::fs::Directory dir; + result = dir.TryInitialize(common::LOG_ROOT_DIRECTORY_PATH); + if(result.IsFailure()) + { + result = nn::fs::TryCreateDirectory(common::LOG_ROOT_DIRECTORY_PATH); + } + + result = sd.TryInitialize(log.c_str(), true); + if (result.IsSuccess()) + { + // 霑ス險倥☆繧 + // 繧オ繧、繧コ蜿門セ + s64 fileSize; + result = sd.TryGetSize(&fileSize); + if (result.IsSuccess()) + { + // 譛ォ蟆セ縺ォ遘サ蜍 + result = sd.TrySetPosition(fileSize); + if (result.IsSuccess()) + { + s32 writeSize; + result = sd.TryWrite(&writeSize, str, stringSize, true); + if (result.IsSuccess()) + { + result = sd.TryFlush(); + if (result.IsFailure()) + { + NN_LOG("SD TryFlush failed\n"); + PrintResultIfFailed(result, __LINE__); + } + } + else + { + NN_LOG("SD TryWrite failed\n"); + PrintResultIfFailed(result, __LINE__); + } + } + else + { + NN_LOG("SD TrySetPosition failed\n"); + PrintResultIfFailed(result, __LINE__); + } + } + else + { + NN_LOG("SD TryGetSize failed\n"); + PrintResultIfFailed(result, __LINE__); + } + } + else + { + NN_LOG("SD TryInitialize failed, %s, %d\n", __FILE__, __LINE__); + PrintResultIfFailed(result, __LINE__); + } + + dir.Finalize(); + sd.Finalize(); + SdMountManager::Unmount(); +} + +void SdLogger::Clear() +{ + Activate(); + if(!m_Permitted) + { + return; + } + + nn::Result result; + SdMountManager::Mount(); + + ::std::wstring log(common::SDMC_ROOT_DIRECTORY_PATH); + log += common::LOG_PATHNAME; + + result = nn::fs::TryDeleteFile(log.c_str()); + if(result.IsFailure()) + { + nn::dbg::PrintResult(result); + } + + SdMountManager::Unmount(); +} + +void SdLogger::Inactivate() +{ + m_TryActivate = false; + m_Permitted = false; +} + +void SdLogger::Activate() +{ + if(m_TryActivate) + { + return; + } + + nn::Result result; + result = common::SdMountManager::Mount(); + + if (result.IsSuccess()) + { + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(common::AP_SETTING_PATHNAME); + if(result.IsSuccess()) + { + m_Permitted = true; + } + fis.Finalize(); + } + + common::SdMountManager::Unmount(); + m_TryActivate = true; +} + +} // namespace Logger +} // namespace ConsoleBackup + + diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdLogger.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdLogger.h new file mode 100644 index 0000000..2dc736f --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdLogger.h @@ -0,0 +1,57 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdLogger.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef SDLOGGER_H_ +#define SDLOGGER_H_ + +#include + +namespace common +{ + +namespace Logger +{ + +class SdLogger +{ +public: + SdLogger(); + ~SdLogger() {}; + + void Print(const char* fmt, ::std::va_list arg); + void Clear(); + void Inactivate(); + +private: + void Activate(); + + nn::fs::FileOutputStream sd; + bool m_TryActivate; + bool m_Permitted; + NN_PADDING2; + +}; + +void InitializeEjectThread(); +// SD繧ォ繝シ繝峨′謚懊¢縺滓凾縺ォ蜻シ縺ー繧後k繧ウ繝シ繝ォ繝舌ャ繧ッ +void SetEjectHandler(void (*func)()); +// SD繧ォ繝シ繝峨′謖ソ蜈・縺輔l縺滓凾縺ォ蜻シ縺ー繧後k繧ウ繝シ繝ォ繝舌ャ繧ッ +void SetInsertHandler(void (*func)()); +SdLogger* GetSdInstance(); + +} // namespace Logger +} // namespace ConsoleBackup + +#endif /* SDLOGGER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdMountManager.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdMountManager.cpp new file mode 100644 index 0000000..336bebb --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdMountManager.cpp @@ -0,0 +1,67 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdMountManager.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include "SdMountManager.h" +#include "FileName.h" + +namespace common +{ + +u32 SdMountManager::m_MountCounter = 0; + +SdMountManager::SdMountManager() +{ + // TODO 閾ェ蜍慕函謌舌&繧後◆繧ウ繝ウ繧ケ繝医Λ繧ッ繧ソ繝シ繝サ繧ケ繧ソ繝 + +} + +SdMountManager::~SdMountManager() +{ + // TODO Auto-generated destructor stub +} + +nn::Result SdMountManager::Mount() +{ + nn::Result result = nn::ResultSuccess(); + + if(m_MountCounter == 0) + { + result = nn::fs::MountSdmc(); + } + m_MountCounter++; + + return result; +} + +nn::Result SdMountManager::Unmount() +{ + nn::Result result = nn::ResultSuccess(); + if(m_MountCounter != 0 && --m_MountCounter == 0) + { + result = nn::fs::Unmount(common::SDMC_ARCHIVE_NAME); + } + + return result; +} + +nn::Result SdMountManager::ForceUnmount() +{ + m_MountCounter = 0; + return nn::fs::Unmount(common::SDMC_ARCHIVE_NAME); +} + + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdMountManager.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdMountManager.h new file mode 100644 index 0000000..c4db65b --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdMountManager.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdMountManager.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef SDMOUNTMANAGER_H_ +#define SDMOUNTMANAGER_H_ + +namespace common +{ + +//! @brief SD繧ォ繝シ繝峨ョMount迥カ諷九r邂。逅縺吶k縺溘a縺ョ繧ッ繝ゥ繧ケ縺ァ縺 +class SdMountManager +{ +public: + SdMountManager(); + virtual ~SdMountManager(); + + //! @brief 繝槭え繝ウ繝医′蠢隕√↑繧峨槭え繝ウ繝医@縺セ縺吶 + static nn::Result Mount(); + //! @brief 繧「繝ウ繝槭え繝ウ繝医′蠢隕√↑繧峨い繝ウ繝槭え繝ウ繝医@縺セ縺吶 + static nn::Result Unmount(); + //! @brief 蠑キ蛻カ逧縺ォ繧「繝ウ繝槭え繝ウ繝医@縺セ縺吶 + static nn::Result ForceUnmount(); + +private: + static u32 m_MountCounter; +}; + +} + +#endif /* SDMOUNTMANAGER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdReaderWriter.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdReaderWriter.cpp new file mode 100644 index 0000000..4bea638 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdReaderWriter.cpp @@ -0,0 +1,249 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdReaderWriter.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include "SdReaderWriter.h" +#include "SdMountManager.h" +#include "CommonLogger.h" +#include "Aes_define.h" + +#include +#include +#include +#include + +#include + +namespace common +{ + +nn::Result SdReaderWriter::Initialize() +{ + nn::Result result; + + // 蛻晄悄蛹匁ク医∩縺ェ繧我ス輔b縺励↑縺 + if(m_IsInitialized) + { + return nn::ResultSuccess(); + } + + result = SdMountManager::Mount(); + if(result.IsSuccess()) + { + m_IsInitialized = true; + return nn::ResultSuccess(); + } + else + { + return result; + } +} + + +nn::Result SdReaderWriter::Finalize() +{ + nn::Result result; + result = SdMountManager::Unmount(); + + m_IsInitialized = false; + return result; +} + +nn::Result SdReaderWriter::WriteBufCore(const wchar_t* path, void* buf, size_t size) +{ + NN_ASSERT(path != NULL); + NN_ASSERT(size > 0); + + nn::Result result = Initialize(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = file.TryInitialize(path, nn::fs::OPEN_MODE_WRITE | nn::fs::OPEN_MODE_CREATE); + + if (result.IsSuccess()) + { + s32 writeSize; + result = file.TryWrite(&writeSize, buf, size, false); + if (result.IsSuccess()) + { + // 菴輔b縺励↑縺 + } + else + { + NN_LOG("SD TryWrite failed\n"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + } + } + else + { + NN_LOG("SD TryInitialize failed\n"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + } + + return result; +} + +nn::Result SdReaderWriter::WriteBuf(const wchar_t* path, void* buf, size_t size) +{ + nn::Result result; + + result = WriteBufCore(path, buf, size); + NN_UTIL_RETURN_IF_FAILED(result); + + result = file.TryFlush(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + file.Finalize(); + + result = Finalize(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + return result; +} + +nn::Result SdReaderWriter::WriteBufWithCmac(const wchar_t* path, void* buf, size_t size) +{ + nn::Result result; + + result = WriteBufCore(path, buf, size); + NN_UTIL_RETURN_IF_FAILED(result); + + nn::crypto::Initialize(); + bit8 sha256Hash[nn::crypto::Sha256Context::HASH_SIZE]; + nn::crypto::CalculateSha256(sha256Hash, buf, size); + + bit8 cmac[nn::crypto::AES_CMAC_MAC_SIZE]; + result = nn::crypto::CalculateAesCmacSw(cmac, sha256Hash, nn::crypto::Sha256Context::HASH_SIZE, common::cmacKey); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + s32 writeSize; + result = file.TryWrite(&writeSize, cmac, sizeof(cmac), false); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = file.TryFlush(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + file.Finalize(); + + result = Finalize(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + return result; + +} + +nn::Result SdReaderWriter::ReadBufCore(const wchar_t* path, void* buf, size_t size, size_t* totalSize) +{ + NN_ASSERT(path != NULL); + NN_ASSERT(size > 0); + + nn::Result result; + + if(!m_IsInitialized) + { + Initialize(); + } + + result = file.TryInitialize(path, nn::fs::OPEN_MODE_READ); + if (result.IsSuccess()) + { + s32 readSize; + result = file.TryRead(&readSize, buf, size); + if (result.IsSuccess()) + { + // TODO 繝舌ャ繝輔ぃ繧定カ縺医k繧オ繧、繧コ縺ョ繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ + *totalSize = readSize; + } + else + { + NN_LOG("SD TryRead failed\n"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + } + } + else + { + NN_LOG("SD TryInitialize failed\n"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + } + + return result; +} + +nn::Result SdReaderWriter::ReadBuf(const wchar_t* path, void* buf, size_t size, size_t* totalSize) +{ + nn::Result result; + + result = ReadBufCore(path, buf, size, totalSize); + NN_UTIL_RETURN_IF_FAILED(result); + + file.Finalize(); + return result; +} + +nn::Result SdReaderWriter::ReadBufWithCmac(const wchar_t* path, void* buf, size_t size, size_t* totalSize) +{ + nn::Result result; + + NN_ASSERT(size > nn::crypto::AES_CMAC_MAC_SIZE); + + result = ReadBufCore(path, buf, size, totalSize); + NN_UTIL_RETURN_IF_FAILED(result); + + file.Finalize(); + // 繝上ャ繧キ繝・縺御サ伜刈縺輔l縺ヲ縺縺ェ縺 + if(*totalSize < nn::crypto::AES_CMAC_MAC_SIZE) + { + return nn::fs::ResultVerificationFailed(); + } + *totalSize -= nn::crypto::AES_CMAC_MAC_SIZE; + + // CMAC縺ョ讀懆ィシ繧定。後≧ + nn::crypto::Initialize(); + bit8 sha256Hash[nn::crypto::Sha256Context::HASH_SIZE]; + nn::crypto::CalculateSha256(sha256Hash, buf, *totalSize); + + bit8 cmac[nn::crypto::AES_CMAC_MAC_SIZE]; + result = nn::crypto::CalculateAesCmacSw(cmac, sha256Hash, nn::crypto::Sha256Context::HASH_SIZE, common::cmacKey); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + if(std::memcmp(reinterpret_cast(buf) + *totalSize, cmac, sizeof(cmac)) != 0) + { + // 辟。蜉ケ縺ェ繝輔ぃ繧、繝ォ + char filename[256]; + std::wcstombs(filename, path, sizeof(filename)); + filename[sizeof(filename) - 1] = '\0'; + COMMON_LOGGER("Verification Failed %s\n", filename); + return nn::fs::ResultVerificationFailed(); + } + + return result; +} + +void SdReaderWriter::CreateDirectory(const wchar_t* path) +{ + nn::Result result; + + if(!m_IsInitialized) + { + Initialize(); + } + + NN_LOG("Create Directory %ls\n", path); + result = nn::fs::TryCreateDirectory(path); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + result = Finalize(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdReaderWriter.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdReaderWriter.h new file mode 100644 index 0000000..81a10d7 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SdReaderWriter.h @@ -0,0 +1,80 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SdReaderWriter.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef SDWRITER_H_ +#define SDWRITER_H_ + +#include + +namespace common +{ + +//! @brief SD繧ォ繝シ繝峨↓譖ク縺崎セシ繧縺溘a縺ョ繧ッ繝ゥ繧ケ縺ァ縺吶 +class SdReaderWriter +{ +public : + SdReaderWriter() : m_IsInitialized(false) {}; + ~SdReaderWriter() {}; + + //! @brief 貂。縺輔l縺溘ヰ繝繝輔ぃ縺九isize繝舌う繝域欠螳壹&繧後◆繝代せ蜷阪〒譖ク縺阪%縺ソ縺セ縺吶CMAC縺御サ伜刈縺輔l縺セ縺吶 + //! @param[in] path sdmc:縺ァ蟋九∪繧句コ蜉帙ヱ繧ケ蜷阪ゆコ医a繝繧」繝ャ繧ッ繝医Μ繧剃ス懊▲縺ヲ縺翫¥蠢隕√′縺ゅj縺セ縺吶 + //! @param[in] buf 蜈・蜉帙ョ繝シ繧ソ縺ク縺ョ繝昴う繝ウ繧ソ + //! @param[in] size 蜈・蜉帙ョ繝シ繧ソ縺ョ繧オ繧、繧コ + nn::Result WriteBufWithCmac(const wchar_t* path, void* buf, size_t size); + + //! @brief 貂。縺輔l縺溘ヰ繝繝輔ぃ縺ク(size - CMAC)繝舌う繝域欠螳壹&繧後◆繝代せ蜷阪°繧芽ェュ縺ソ霎シ縺ソ縺セ縺 + //! @param[in] path sdmc:縺ァ蟋九∪繧気MAC莉倥″縺ョ蜈・蜉帙ヱ繧ケ蜷 + //! @param[in] buf 蜃コ蜉帙ヰ繝繝輔ぃ縺ク縺ョ繝昴う繝ウ繧ソ + //! @param[in] size 繝舌ャ繝輔ぃ繧オ繧、繧コ + //! @param[out] totalSize 隱ュ縺ソ霎シ繧薙□繝繝シ繧ソ - CMAC 縺ョ繧オ繧、繧コ + nn::Result ReadBufWithCmac(const wchar_t* path, void* buf, size_t size, size_t* totalSize); + + //! @brief 貂。縺輔l縺溘ョ繧」繝ャ繧ッ繝医Μ蜷阪ョ繝繧」繝ャ繧ッ繝医Μ繧剃ス懈舌@縺セ縺 + void CreateDirectory(const wchar_t* path); + +private: + //! @brief 貂。縺輔l縺溘ヰ繝繝輔ぃ縺九i繧オ繧、繧コ蛻謖螳壹&繧後◆繝代せ蜷阪〒譖ク縺阪%縺ソ縺セ縺 + //! @param[in] path sdmc:縺ァ蟋九∪繧句コ蜉帙ヱ繧ケ蜷阪ゆコ医a繝繧」繝ャ繧ッ繝医Μ繧剃ス懊▲縺ヲ縺翫¥蠢隕√′縺ゅj縺セ縺吶 + //! @param[in] buf 蜈・蜉帙ョ繝シ繧ソ縺ク縺ョ繝昴う繝ウ繧ソ + //! @param[in] size 蜈・蜉帙ョ繝シ繧ソ縺ョ繧オ繧、繧コ + nn::Result WriteBuf(const wchar_t* path, void* buf, size_t size); + + nn::Result WriteBufCore(const wchar_t*path, void* buf, size_t size); + + //! @brief 貂。縺輔l縺溘ヰ繝繝輔ぃ縺ク繧オ繧、繧コ蛻謖螳壹&繧後◆繝代せ蜷阪°繧芽ェュ縺ソ霎シ縺ソ縺セ縺 + //! @param[in] path sdmc:縺ァ蟋九∪繧句・蜉帙ヱ繧ケ蜷 + //! @param[in] buf 蜃コ蜉帙ヰ繝繝輔ぃ縺ク縺ョ繝昴う繝ウ繧ソ + //! @param[in] size 繝舌ャ繝輔ぃ繧オ繧、繧コ + //! @param[out] totalSize 隱ュ縺ソ霎シ繧薙□繝繝シ繧ソ縺ョ繧オ繧、繧コ + nn::Result ReadBuf(const wchar_t* path, void* buf, size_t size, size_t* totalSize); + + nn::Result ReadBufCore(const wchar_t* path, void* buf, size_t size, size_t* totalSize); + + //! @brief 蛻晄悄蛹悶@縺セ縺吶 + nn::Result Initialize(); + + //! @brief 邨ゆコ縺励∪縺吶 + nn::Result Finalize(); + + nn::fs::FileStream file; + + NN_PADDING3; + bool m_IsInitialized; + +}; + +} + +#endif /* SDWRITER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SimplePlayer.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SimplePlayer.cpp new file mode 100644 index 0000000..97e8a76 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SimplePlayer.cpp @@ -0,0 +1,240 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: SimplePlayer.cpp + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include + +#include +#include "SimplePlayer.h" +#include "wave.h" +#include "HeapManager.h" + +namespace common +{ + +namespace +{ + const int nFiles = 4; // 菴ソ逕ィ縺ァ縺阪k voice 縺ョ譛螟ァ蛟、縺ッ 24 + const char* apFileNames[nFiles] = + { + "rom:/ok.wav", + "rom:/ng.wav", + "rom:/cursor.wav", + "rom:/annotation.wav" + }; + + nn::snd::CTR::Voice* apVoice[nFiles]; + nn::snd::CTR::WaveBuffer aBuffer[nFiles]; + WaveFmt fmt[nFiles]; + WaveData data[nFiles]; + u8* apMemory[nFiles]; + + nn::os::CriticalSection s_CriticalSection; + bool s_SoundThreadInitialized = false; + + // 繧オ繧ヲ繝ウ繝峨せ繝ャ繝繝蛾未騾」 + const int SOUND_THREAD_STACK_SIZE = 4096; + nn::os::StackBuffer s_SoundThreadStack; + nn::os::Thread threadSound; + bool threadSoundFlag; + void SoundThreadFunc() + { + // 繧オ繧ヲ繝ウ繝牙コ蜉帙r繧ケ繝繝ャ繧ェ縺ォ + nn::snd::SetSoundOutputMode(nn::snd::OUTPUT_MODE_STEREO); + + // 繝槭せ繧ソ繝シ繝懊Μ繝・繝シ繝繧定ィュ螳 + nn::snd::SetMasterVolume( 1.0 ); + + NN_LOG("Loading wav files...\n"); + + // 繝輔ぃ繧、繝ォ繧帝幕縺 + for (int i = 0; i < nFiles; i++) + { + if (apFileNames[i] == NULL) continue; + + nn::snd::Voice* pVoice = NULL; + + nn::fs::FileReader fileReader; + nn::Result result = fileReader.TryInitialize(apFileNames[i]); + NN_UTIL_PANIC_IF_FAILED(result); + if (::std::strcmp(::std::strrchr(apFileNames[i], '.'), ".wav") == false) + { + // 騾」邯壹Γ繝「繝ェ鬆伜沺縺ョ蜿門セ励∫「コ隱 + apMemory[i] = reinterpret_cast(HeapManager::GetHeap()->Allocate(GetWaveLength(fileReader), 32)); + if (apMemory[i] == NULL) + { + NN_LOG("Failed to allocate continuous memory\n"); + continue; + } + + + // Wave 繝繝シ繧ソ繧定ェュ縺ソ霎シ縺ソ縲√く繝」繝繧キ繝・繧堤┌蜉ケ縺ォ + data[i].buf = apMemory[i]; + LoadWave(fileReader, &fmt[i], &data[i]); + nn::snd::FlushDataCache(reinterpret_cast(apMemory[i]), data[i].size); + + NN_LOG("%s (%1dch, %5dHz, %2d-bit wav file)\n", + apFileNames[i], fmt[i].channel, fmt[i].sample_rate, fmt[i].quantum_bits); + + pVoice = apVoice[i] = nn::snd::AllocVoice(128, NULL, NULL); + NN_TASSERT_(pVoice); + + nn::snd::SampleFormat format = (fmt[i].quantum_bits == 8) ? + nn::snd::SAMPLE_FORMAT_PCM8 : + nn::snd::SAMPLE_FORMAT_PCM16; + + pVoice->SetChannelCount( fmt[i].channel ); + pVoice->SetSampleFormat( format ); + + nn::snd::InitializeWaveBuffer(&aBuffer[i]); + aBuffer[i].bufferAddress = apMemory[i]; + aBuffer[i].sampleLength = nn::snd::GetSampleLength(data[i].size, format, fmt[i].channel); + aBuffer[i].loopFlag = false; + + fileReader.Finalize(); + + // 髻ウ驥上ョ險ュ螳 + nn::snd::MixParam mix; + mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_LEFT ] = 0.707f; // 繝。繧、繝ウ繝懊Μ繝・繝シ繝 (L) + mix.mainBus[nn::snd::CHANNEL_INDEX_FRONT_RIGHT] = 0.707f; // 繝。繧、繝ウ繝懊Μ繝・繝シ繝 (R) + pVoice->SetMixParam(mix); + pVoice->SetVolume(1.0f); + + // pitch 縺ョ險ュ螳 + pVoice->SetSampleRate(fmt[i].sample_rate); + pVoice->SetPitch(1.0f); + + } + } + + // 蜀咲函髢句ァ + for (int i = 0; i < nFiles; i++) + { + if (apFileNames[i] != NULL) + { + apVoice[i]->SetState( nn::snd::Voice::STATE_PLAY ); + } + } + + s_SoundThreadInitialized = true; + + threadSoundFlag = true; + while (threadSoundFlag) + { + nn::snd::WaitForDspSync(); // DSP 縺九i縺ョ繝繝シ繧ソ蜿嶺ソ。繧貞セ縺、縲 + + + s_CriticalSection.Enter(); // 繝。繧、繝ウ繧ケ繝ャ繝繝峨→縺ョ謗剃サ門宛蠕。 + nn::snd::SendParameterToDsp(); // 繝代Λ繝。繝シ繧ソ繧 DSP 縺ォ騾∽ソ。縲 + s_CriticalSection.Leave(); // 繝。繧、繝ウ繧ケ繝ャ繝繝峨→縺ョ謗剃サ門宛蠕。 + } + + // 蜀咲函邨ゆコ + for (int i = 0; i < nFiles; i++) + { + if (apVoice[i]) + { + nn::snd::FreeVoice(apVoice[i]); + } + } + } +} + +void InitializeSimplePlayer() +{ + NN_LOG("Initialize SimplePlayer\n"); + + nn::Result result; + + const size_t ROMFS_BUFFER_SIZE = 1024 * 64; + static char buffer[ROMFS_BUFFER_SIZE]; + NN_UTIL_PANIC_IF_FAILED( + nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE)); + + // dsp, snd 縺ョ蛻晄悄蛹 + result = nn::dsp::Initialize(); + NN_UTIL_PANIC_IF_FAILED(result); + result = nn::dsp::LoadDefaultComponent(); + NN_UTIL_PANIC_IF_FAILED(result); + result = nn::snd::Initialize(); + NN_UTIL_PANIC_IF_FAILED(result); + + s_CriticalSection.Initialize(); + + // 繧オ繧ヲ繝ウ繝峨せ繝ャ繝繝峨r襍キ蜍包シDSP 蜑イ繧願セシ縺ソ繧、繝吶Φ繝亥セ縺。シ + threadSound.Start(SoundThreadFunc, s_SoundThreadStack); +} + +void PlaySound(u8 index) +{ + NN_ASSERT(index <= nFiles); + + while(!s_SoundThreadInitialized) + { + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(1)); + } + + nn::snd::CTR::Voice* pVoice = apVoice[index]; + + if (!pVoice->IsPlaying()) + { + nn::snd::InitializeWaveBuffer(&aBuffer[index]); + aBuffer[index].bufferAddress = apMemory[index]; + nn::snd::SampleFormat format = (fmt[index].quantum_bits == 8) ? nn::snd::SAMPLE_FORMAT_PCM8 + : nn::snd::SAMPLE_FORMAT_PCM16; + + aBuffer[index].sampleLength = nn::snd::GetSampleLength(data[index].size, format, fmt[index].channel); + aBuffer[index].loopFlag = false; + + pVoice->AppendWaveBuffer(&aBuffer[index]); + NN_LOG("[voice%d] %s (pitch = %f)\n", + index, + (pVoice->GetState() == nn::snd::Voice::STATE_PAUSE ? "pause" : "play "), + pVoice->GetPitch()); + } +} + +void FinalizeSimplePlayer() +{ + nn::Result result; + + // 繧オ繧ヲ繝ウ繝峨せ繝ャ繝繝峨ョ遐エ譽 + threadSoundFlag = false; + threadSound.Join(); + + // SND 縺ョ邨ゆコ蜃ヲ逅 + result = nn::snd::Finalize(); + NN_UTIL_PANIC_IF_FAILED(result); + + s_CriticalSection.Finalize(); + + // DSP 縺ョ邨ゆコ蜃ヲ逅 + result = nn::dsp::UnloadComponent(); + NN_UTIL_PANIC_IF_FAILED(result); + nn::dsp::Finalize(); + + + NN_LOG("Finalize SimplePlayer\n"); + +} + +} // namespace ConsoleBackup +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SimplePlayer.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SimplePlayer.h new file mode 100644 index 0000000..b7fe76e --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/SimplePlayer.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: SimplePlayer.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef SIMPLEPLAYER_H_ +#define SIMPLEPLAYER_H_ + +namespace common +{ + +enum SoundEffect +{ + SOUND_OK, + SOUND_NG, + SOUND_CURSOR, + SOUND_ANNOTATION +}; + +void InitializeSimplePlayer(); +void FinalizeSimplePlayer(); +void PlaySound(u8 index); + +} // namespace ConsoleBackup + + +#endif /* SIMPLEPLAYER_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/VersionDetect.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/VersionDetect.cpp new file mode 100644 index 0000000..f028569 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/VersionDetect.cpp @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: VersionDetect.cpp + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#include +#include +#include + +#include "VersionDetect.h" +#include "HeapManager.h" +#include "CommonLogger.h" + +namespace common +{ + +void GetCupVersion(nn::pl::CTR::CardUpdateVersion* cup, nn::cfg::CTR::CfgRegionCode region) +{ + nn::Result result; + const size_t BUF_SIZE = 1024; + u8 buf[BUF_SIZE]; + // CUP繝舌シ繧ク繝ァ繝ウ + { + result = nn::fs::MountContent("cver:", nn::fs::MEDIA_TYPE_NAND, common::cCupVerId[region], 0, 1, 1, buf, + BUF_SIZE); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(L"cver:/version.bin"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if (result.IsSuccess()) + { + s64 fileSize = fis.GetSize(); + NN_LOG("version.bin size = %lld\n", fileSize); + s32 ret; + void* addr = NULL; + addr = common::HeapManager::GetHeap()->Allocate(fileSize); + if (addr != NULL) + { + result = fis.TryRead(&ret, addr, fileSize); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if (result.IsSuccess()) + { + nn::pl::CTR::CardUpdateVersion* ver_buf = reinterpret_cast (addr); + + std::memcpy(cup, ver_buf, sizeof(nn::pl::CTR::CardUpdateVersion)); + } + common::HeapManager::GetHeap()->Free(addr); + } + } + fis.Finalize(); + + nn::fs::Unmount("cver:"); + } + +} + +void GetNupVersion(nn::pl::CTR::NetworkUpdateVersion* nup, nn::cfg::CTR::CfgRegionCode region) +{ + nn::Result result; + const size_t BUF_SIZE = 1024; + u8 buf[BUF_SIZE]; + + // NUP繝舌シ繧ク繝ァ繝ウ + { + result = nn::fs::MountContent("nver:", nn::fs::MEDIA_TYPE_NAND, common::cNupVerId[region], 0, 1, 1, buf, + BUF_SIZE); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(L"nver:/version.bin"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if (result.IsSuccess()) + { + s64 fileSize = fis.GetSize(); + NN_LOG("version.bin size = %lld\n", fileSize); + s32 ret; + void* addr = NULL; + addr = common::HeapManager::GetHeap()->Allocate(fileSize); + if (addr != NULL) + { + result = fis.TryRead(&ret, addr, fileSize); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if (result.IsSuccess()) + { + nn::pl::CTR::NetworkUpdateVersion* ver_buf = + reinterpret_cast (addr); + + std::memcpy(nup, ver_buf, sizeof(nn::pl::CTR::NetworkUpdateVersion)); + } + common::HeapManager::GetHeap()->Free(addr); + } + } + + fis.Finalize(); + nn::fs::Unmount("nver:"); + } + +} + +void GetSystemVersion(common::VerDef* mVerData, nn::cfg::CTR::CfgRegionCode region) +{ + GetCupVersion(&mVerData->cup, region); + GetNupVersion(&mVerData->nup, region); +} + +} + diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/VersionDetect.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/VersionDetect.h new file mode 100644 index 0000000..652ed09 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/VersionDetect.h @@ -0,0 +1,30 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: VersionDetect.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef VERSIONDETECT_H_ +#define VERSIONDETECT_H_ + +#include +#include "common_Types.h" + +namespace common +{ + +void GetSystemVersion(common::VerDef* mVerData, nn::cfg::CTR::CfgRegionCode region); + +} + + +#endif /* VERSIONDETECT_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/common_Types.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/common_Types.h new file mode 100644 index 0000000..2a354a3 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/common_Types.h @@ -0,0 +1,92 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: common_Types.h + + Copyright 2009 Nintendo. 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef COMMON_TYPES_H_ +#define COMMON_TYPES_H_ + +#include +#include +#include +#include +#include +#include + +namespace common +{ + +const u32 NTR_WIFI_SETTING_SIZE = 0x400; // NTR Wifi 險ュ螳壹ョ繧オ繧、繧コ +const u32 TWL_WIFI_SETTING_SIZE = 0x600; // TWL Wifi 險ュ螳壹ョ繧オ繧、繧コ + + +// NOR鬆伜沺縺ョ縺ソ縺ォ縺ゅk險ュ螳壹ョ繝シ繧ソ逕ィ讒矩菴 +struct NtrNorData +{ + nn::cfg::CTR::NtrConfig ntrConfig; + u8 TwlWiFiSetting[TWL_WIFI_SETTING_SIZE]; + u8 NtrWiFiSetting[NTR_WIFI_SETTING_SIZE]; +}; + +struct CfgCountryLanguage +{ + enum nn::cfg::CTR::CfgCountryCode country; + enum nn::cfg::CTR::CfgLanguageCode language; + NN_PADDING1; +}; + +struct VerDef +{ + nn::pl::CTR::CardUpdateVersion cup; + nn::pl::CTR::NetworkUpdateVersion nup; +}; + +struct CfgCalData +{ + nn::cfg::CTR::detail::TouchPanelCfgData touchPanelCfgData; + nn::cfg::CTR::detail::LcdFlickerCfgData lcdFlickerCfgData; + nn::cfg::CTR::detail::FcramCfgData fcramCfgData; + nn::cfg::CTR::detail::RtcCfgData rtcCfgData; + nn::cfg::CTR::detail::GyroscopeCfgData gyroscopeCfgData; + nn::cfg::CTR::detail::AccelCfgData accelCfgData; + nn::cfg::CTR::detail::CodecCfgData codecCfgData; + nn::cfg::CTR::detail::McuSlideVolumeRangeCfgData mcuSlideVolumeRangeCfgData; + NN_PADDING2; + +}; + +// TODO:繝ェ繝シ繧ク繝ァ繝ウ霑ス蜉譎ゅ↓遽蝗イ螟悶い繧ッ繧サ繧ケ縺ォ縺ェ繧峨↑縺繧医≧豕ィ諢 +const nn::ProgramId cCupVerId[] = +{ + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_JP, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_US, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_EU, +}; + +const nn::ProgramId cNupVerId[] = +{ + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_JP, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_US, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_EU, +}; + +struct BackupDataHeader +{ + s64 size; // 繝代ョ繧」繝ウ繧ー繧貞性縺セ縺ェ縺繝輔ぃ繧、繝ォ繧オ繧、繧コ + NN_PADDING4; + NN_PADDING4; +}; + +} + +#endif /* COMMON_TYPES_H_ */ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/configLoader.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/configLoader.cpp new file mode 100644 index 0000000..b262ba9 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/configLoader.cpp @@ -0,0 +1,181 @@ +#include +#include +#include +#include "configLoader.h" + +namespace common +{ + +Result ConfigFileLoader::Initialize(const wchar_t* fileName, void* buffer, const size_t bufferSize) +{ + s64 fileSize; + FileInputStream fi; + NN_UTIL_RETURN_IF_FAILED(fi.TryInitialize(fileName)); + NN_UTIL_RETURN_IF_FAILED(fi.TryGetSize(&fileSize)); + + // NULL邨らォッ縺カ繧楢ェュ繧√k繧オ繧、繧コ繧呈ク帙i縺 + if (fileSize > bufferSize - sizeof(wchar_t)) + { + NN_TLOG_("Too Large File\n"); + return Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, nn::Result::DESCRIPTION_TOO_LARGE); + } + + m_Buffer = static_cast(buffer); + NN_UTIL_RETURN_IF_FAILED(fi.TryRead(&m_UsedBufferSize, m_Buffer, fileSize)); + NN_LOG("config size = %d\n", m_UsedBufferSize); + return ParseData(); +} + +void ConfigFileLoader::Finalize() +{ + m_Buffer = 0; + m_ParamNum = 0; +} + +Result ConfigFileLoader::ParseData() +{ + if (!m_Buffer) + { + return Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_INVALID_STATE, nn::Result::MODULE_COMMON, nn::Result::DESCRIPTION_NOT_INITIALIZED); + } + + int pos = 0; + + // 繝薙ャ繧ー繧ィ繝ウ繝繧」繧「繝ウ縺ァ縺ェ縺縺薙→繧堤「コ隱 + NN_ASSERTMSG(m_Buffer[0] != 0xfffe, "Invalid Config File's Endian\n"); + + if (m_Buffer[0] == 0xfeff) + { + // UTF-16 BOM縺ョ隱ソ謨エ + pos++; + } + + m_ParamNum = 0; + m_ParamName[m_ParamNum] = &(m_Buffer[pos]); + m_ParamValue[m_ParamNum] = L""; + m_Buffer[m_UsedBufferSize / sizeof(wchar_t)] = L'\0'; // NULL邨らォッ縺励※縺翫¥ + + // 繝繝悶Ν繧ッ繧ヲ繧ゥ繝シ繝井クュ縺ェ繧 : 繧よ枚蟄励→縺励※隱ュ縺ソ蜿悶k + bool inEscape = false; + // # 縺ァ陦梧忰縺セ縺ァ繧ウ繝。繝ウ繝 + bool inComment = false; + // : 縺ァ陦碁ュ縺九i:縺セ縺ァ縺渓ey縲:縺九i陦梧忰縺セ縺ァ縺計alue + bool inSettingKeyValue = false; + + while (pos < m_UsedBufferSize / sizeof(m_Buffer[0])) + { + switch (m_Buffer[pos]) + { + case L'"': + { + inEscape = !inEscape; + } + break; + + case L'#': + { + inComment = true; + } + break; + + case L':': + { + if (inEscape || inComment) + { + break; + } + + if (inSettingKeyValue) + { + break; + } + else + { + inSettingKeyValue = true; + } + m_Buffer[pos] = L'\0'; + m_ParamValue[m_ParamNum++] = &(m_Buffer[pos + 1]); + + } + + break; + case L'\r': + case L'\n': + { + if (inComment) + { + inComment = false; + } + if (inSettingKeyValue) + { + inSettingKeyValue = false; + } + + m_Buffer[pos] = L'\0'; + m_ParamName[m_ParamNum] = &(m_Buffer[pos + 1]); + m_ParamValue[m_ParamNum] = L""; + } + break; + + } + + if (PARAM_MAX_NUM <= m_ParamNum) + { + NN_TLOG_("Too Many Params\n"); + return Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_TOO_LARGE); + } + pos++; + } + + return ResultSuccess(); +} + +s32 ConfigFileLoader::SearchParamName(const wchar_t *paramName) +{ + if (!m_Buffer) + { + NN_TLOG_("ConfigFileLoader not initialized.\n"); + return -1; + } + + for (s32 i = 0; i < m_ParamNum; i++) + { + if (wcscmp(m_ParamName[i], paramName) == 0) + { + return i; + } + } + return -1; +} + +const wchar_t *ConfigFileLoader::ReadAsWChar(const wchar_t *paramName) +{ + s32 idx = SearchParamName(paramName); + if (idx < 0) + { + NN_LOG("Unknown Parameter Name %ls\n", paramName); + } + return (idx < 0) ? NULL : m_ParamValue[idx]; +} + +const char *ConfigFileLoader::ReadAsChar(const wchar_t *paramName) +{ + memset(m_ReadCharBuffer, 0, sizeof(m_ReadCharBuffer)); + const wchar_t *value = ReadAsWChar(paramName); + if(value == NULL) + { + return NULL; + } + wcstombs(m_ReadCharBuffer, value, sizeof(m_ReadCharBuffer)); + // NULL邨らォッ縺吶k + m_ReadCharBuffer[sizeof(m_ReadCharBuffer) - 1] = '\0'; + return m_ReadCharBuffer; +} + +int ConfigFileLoader::ReadAsInteger(const wchar_t *paramName) +{ + return atoi(ReadAsChar(paramName)); +} + +} diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/configLoader.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/configLoader.h new file mode 100644 index 0000000..67e1edf --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/configLoader.h @@ -0,0 +1,78 @@ +#ifndef NN_CONFIG_LOADER_H_ +#define NN_CONFIG_LOADER_H_ + + +namespace common +{ + using namespace nn; + using namespace nn::fs; + using namespace std; + +class ConfigFileLoader +{ +private: + static const int PARAM_VALUE_MAX_STRING_LENGTH = 128; + static const int PARAM_MAX_NUM = 64; + + char m_ReadCharBuffer[PARAM_VALUE_MAX_STRING_LENGTH]; + wchar_t *m_ParamName[PARAM_MAX_NUM]; + wchar_t *m_ParamValue[PARAM_MAX_NUM]; + wchar_t *m_Buffer; + + s32 m_UsedBufferSize; + s32 m_ParamNum; + +public: + ConfigFileLoader() : m_Buffer(0), m_UsedBufferSize(0), m_ParamNum(0) + { + } + +/* + @brief ConfigFileLoader 繧貞晄悄蛹悶@縺セ縺呻シ + + 菴ソ逕ィ縺吶k繝輔ぃ繧、繝ォ縺悟ュ伜惠縺吶k繧「繝シ繧ォ繧、繝悶ッシ後≠繧峨°縺倥a繝槭え繝ウ繝医@縺ヲ縺翫¥蠢隕√′縺ゅj縺セ縺呻シ + 隱ュ縺ソ霎シ縺ソ縺ォ菴ソ逕ィ縺吶k繝舌ャ繝輔ぃ繧堤「コ菫昴@シ悟シ墓焚 buffer 縺ォ荳弱∴繧句ソ隕√′縺ゅj縺セ縺呻シ + Finalize 繧貞他縺カ縺セ縺ァ縺薙ョ繝舌ャ繝輔ぃ縺ッ髢区叛縺励↑縺縺ァ縺上□縺輔>シ + + 隱ュ縺ソ霎シ縺セ縺帙k縺薙→縺ョ縺ァ縺阪k繝輔か繝シ繝槭ャ繝 + 繝サ繧ィ繝ウ繧ウ繝シ繝繧」繝ウ繧ーシ啅TF-16 + 繝サ繝舌う繝医が繝シ繝縲縲シ壹Μ繝医Ν繧ィ繝ウ繝繧」繧「繝ウ + 繝サ謾ケ陦瑚ィ伜捷縲縲縲縲シ壻ク榊撫 + + 蜊願ァ偵さ繝ュ繝ウ繧貞性繧陦後ョ縺ソ繝代Λ繝。繝シ繧ソ險倩ソー陦後→縺励※隱ュ縺ソ霎シ縺ソシ悟性縺セ縺ェ縺陦後ッ辟。隕悶@縺セ縺呻シ + 蜊願ァ偵さ繝ュ繝ウ繧医j蜑阪ョ譁蟄励ッ縺吶∋縺ヲ繝代Λ繝。繝シ繧ソ蜷阪→縺励※蜿門セ励@シ + 蜊願ァ偵さ繝ュ繝ウ繧医j蠕後ョ譁蟄励ッ縺吶∋縺ヲ繝代Λ繝。繝シ繧ソ縺ョ蛟、縺ィ縺励※蜿門セ励@縺セ縺呻シ + ParameterName : ParameterValue; + 縺ィ險倩ソー縺吶k縺ィ + 繝代Λ繝。繝シ繧ソ蜷阪ッ L"ParameterName " + 繝代Λ繝。繝シ繧ソ蛟、縺ッ L" ParameterValue;" + 縺ィ縺ェ繧翫∪縺呻シ + + @param[in] fileName 險ュ螳壹ヵ繧。繧、繝ォ蜷 + @param[in] buffer 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ逕ィ縺ョ繝舌ャ繝輔ぃ + @param[in] bufferSize 荳願ィ buffer 縺ョ螟ァ縺阪& + + @return 邨先棡繧定ソ斐@縺セ縺呻シ + +*/ + Result Initialize(const wchar_t* fileName, void* buffer, const size_t bufferSize); + void Finalize(); + + // 繧ケ繝ャ繝繝峨そ繝シ繝輔〒縺呻シ + const wchar_t *ReadAsWChar(const wchar_t *paramName); + + // 繧ケ繝ャ繝繝峨そ繝シ繝輔〒縺ッ縺ゅj縺セ縺帙sシ + const char *ReadAsChar(const wchar_t *paramName); + + // 繧ケ繝ャ繝繝峨そ繝シ繝輔〒縺呻シ + int ReadAsInteger(const wchar_t *paramName); + +private: + Result ParseData(); + s32 SearchParamName(const wchar_t *paramName); +}; + +} + + +#endif // NN_CONFIG_LOADER_H_ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/annotation.wav b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/annotation.wav new file mode 100644 index 0000000..b64f77b Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/annotation.wav differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/cursor.wav b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/cursor.wav new file mode 100644 index 0000000..85765b3 Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/cursor.wav differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/ng.wav b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/ng.wav new file mode 100644 index 0000000..dc2f3ef Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/ng.wav differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/ok.wav b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/ok.wav new file mode 100644 index 0000000..bf5149f Binary files /dev/null and b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/romfiles/ok.wav differ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/wave.cpp b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/wave.cpp new file mode 100644 index 0000000..a897109 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/wave.cpp @@ -0,0 +1,150 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: wave.c + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* includes */ +#include "wave.h" + +/*---------------------------------------------------------------------------*/ +/* functions */ + +/*---------------------------------------------------------------------------* + Name: LoadWave + + Description: Wave 繝繝シ繧ソ繧定ェュ縺ソ霎シ繧. + + Arguments: filepath : 繝輔ぃ繧、繝ォ繝代せ + fmt : Wave 繝繝シ繧ソ縺ョ fmt 繝√Ε繝ウ繧ッ繧呈シ邏 + data : Wave 繝繝シ繧ソ縺ョ data 繝√Ε繝ウ繧ッ繧呈シ邏 + + Returns: None. + *---------------------------------------------------------------------------*/ +void LoadWaveCore(nn::fs::FileReader& reader, WaveFmt * fmt, WaveData * data, bool isSizeOnly) +{ + reader.SetPosition(0); + + WaveRiff riff; // RIFF 繝倥ャ繝 + WaveChunk chunk; // CHUNK + u32 readbyte = 0; // 繝輔ぃ繧、繝ォ隱ュ縺ソ霎シ縺ソ縺ョ蛻、螳壹↓菴ソ逕ィ + u32 fsize = reader.GetSize(); + + // RIFF 繝倥ャ繝隱ュ縺ソ霎シ縺ソ + reader.Read((u8*)&riff, sizeof(WaveRiff)); + + // 繧オ繧、繧コ繧堤ゥ咲ョ + readbyte += sizeof(WaveRiff); + + // "RIFF" 縺ィ縺ョ荳閾エ繧堤「コ隱 + if (riff.tag != MAKE_WAVE_TAG_VALUE('R','I','F','F')) + { + NN_PANIC("Not RIFF format.\n"); + } + // "WAVE" 縺ィ縺ョ荳閾エ繧堤「コ隱 + if ( riff.type != MAKE_WAVE_TAG_VALUE('W','A','V','E') ) + { + NN_PANIC("Not Wave format.\n"); + } + + // 繝輔ぃ繧、繝ォ繧オ繧、繧コ繧医j螟ァ縺阪¥縺ェ繧九∪縺ァ隱ュ縺ソ霎シ繧 + while(fsize > readbyte) + { + // CHUNK 縺ョ隱ュ縺ソ霎シ縺ソ + reader.Read((u8*)&chunk, sizeof(WaveChunk)); + readbyte += sizeof(WaveChunk); + + // "fmt " + if (chunk.tag == MAKE_WAVE_TAG_VALUE('f','m','t',' ')) + { + reader.Read((u8*)fmt, sizeof(WaveFmt)); + readbyte += sizeof(WaveFmt); + + // 諡。蠑オ鬆伜沺縺後≠繧後ー隱ュ縺ソ謐ィ縺ヲ + if (chunk.size > sizeof(WaveFmt)) + { + u16 ext_size; + + reader.Read((u8*)&ext_size, sizeof(ext_size)); + readbyte += sizeof(ext_size); + + readbyte += chunk.size; + if (readbyte == fsize) break; + + reader.Seek(ext_size, nn::fs::POSITION_BASE_CURRENT); + } + } + // "data" + else if (chunk.tag == MAKE_WAVE_TAG_VALUE('d','a','t','a')) + { + data->size = chunk.size; + + if (isSizeOnly) + { + return; + } + else + { + reader.Read((u8*)data->buf, data->size); + // 8-bit wav 繝輔ぃ繧、繝ォ縺ョ蝣エ蜷医ッ unsigned -> signed 縺ョ螟画鋤縺悟ソ隕 + if (fmt->quantum_bits == 8) + { + s8* p = (s8*)data->buf; + for (int i = 0; i < data->size; i++) + { + p[i] -= 128; + } + } + } + readbyte += chunk.size; + } + // 縺昴l莉・螟 + else + { + readbyte += chunk.size; + if (readbyte == fsize) break; + + // 隱ュ縺ソ鬟帙ー縺 + reader.Seek(chunk.size, nn::fs::POSITION_BASE_CURRENT); + } + } +} + +#ifndef NN_BUILD_RELEASE // Release 繝薙Ν繝峨〒縺ッ HostIO 縺ッ菴ソ縺医∪縺帙s縲 +void WriteWaveHeader(nn::hio::CTR::HostFile& hostFile, WaveFmt* fmt, s32 size) +{ + WaveRiff riff; + riff.tag = MAKE_WAVE_TAG_VALUE('R','I','F','F'); + riff.size = + + sizeof(WaveRiff) // riff header + + sizeof(WaveChunk) + sizeof(WaveFmt) // wave fmt header + + sizeof(WaveChunk) + size // wave data + - 8; + riff.type = MAKE_WAVE_TAG_VALUE('W','A','V','E'); + hostFile.Write(&riff, sizeof(WaveRiff)); + + WaveChunk chunk; + chunk.tag = MAKE_WAVE_TAG_VALUE('f','m','t',' '); + chunk.size = sizeof(WaveFmt); + hostFile.Write(&chunk, sizeof(WaveChunk)); + hostFile.Write(fmt, sizeof(WaveFmt)); + + chunk.tag = MAKE_WAVE_TAG_VALUE('d','a','t','a'); + chunk.size = size; + hostFile.Write(&chunk, sizeof(WaveChunk)); +} +#endif // NN_BUILD_RELEASE + +/*---------------------------------------------------------------------------*/ +/* end of file */ +/*---------------------------------------------------------------------------*/ diff --git a/branches/0thNUP_No_NUP/ConsoleDataMigration/common/wave.h b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/wave.h new file mode 100644 index 0000000..cbaf2f3 --- /dev/null +++ b/branches/0thNUP_No_NUP/ConsoleDataMigration/common/wave.h @@ -0,0 +1,148 @@ +サソ/*---------------------------------------------------------------------------* + Project: Horizon + File: wave.h + + 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. + + $Rev$ + *---------------------------------------------------------------------------*/ + +#ifndef __WAVE_HEADER__ +#define __WAVE_HEADER__ + +/*---------------------------------------------------------------------------*/ +/* includes */ +#include +#include +#ifndef NN_BUILD_RELEASE // Release 繝薙Ν繝峨〒縺ッ HostIO 縺ッ菴ソ縺医∪縺帙s縲 +#include +#endif // NN_BUILD_RELEASE + +/*---------------------------------------------------------------------------*/ +/* constants */ + +#define MAKE_WAVE_TAG_VALUE(c1, c2, c3, c4) \ + ( c1 | (c2<<8) | (c3<<16) | (c4<<24) ) + +#define MAKE_WAVE_TAG_STRING(str, val) \ + { \ + str[3] = (char) ( (val>>24)&0xff ) ; \ + str[2] = (char) ( (val>>16)&0xff ) ; \ + str[1] = (char) ( (val>> 8)&0xff ) ; \ + str[0] = (char) ( (val )&0xff ) ; \ + str[4] = (char) ( 0 ) ; \ + } + +#define MAKE_FMT_CHUNK(ch, s) \ + { \ + ch.tag = MAKE_WAVE_TAG_VALUE('f', 'm', 't', ' '); \ + ch.size = s; \ + } + +#define MAKE_DATA_CHUNK(ch, s) \ + { \ + ch.tag = MAKE_WAVE_TAG_VALUE('d', 'a', 't', 'a'); \ + ch.size = s; \ + } + +#define saturate(v, min, max) \ + { \ + if ( v < min ) {v = min;} \ + else if ( v > max ) {v = max;} \ + } + +#define swap(v,t) swap_##t##_(v) + +#define swap_u16_(v) \ + { \ + v = (u16)(((v)>> 8)&0x00ff | \ + ((v)<< 8)&0xff00); \ + } + +#define swap_s16_(v) \ + { \ + v = (s16)(((v)>> 8)&0x00ff | \ + ((v)<< 8)&0xff00); \ + } + +#define swap_u32_(v) \ + { \ + v = (u32)(((v)>>24)&0x000000ff | \ + ((v)>> 8)&0x0000ff00 | \ + ((v)<< 8)&0x00ff0000 | \ + ((v)<<24)&0xff000000); \ + } + +#define swap_s32_(v) \ + { \ + v = (s32)(((v)>>24)&0x000000ff | \ + ((v)>> 8)&0x0000ff00 | \ + ((v)<< 8)&0x00ff0000 | \ + ((v)<<24)&0xff000000); \ + } + +/*---------------------------------------------------------------------------*/ +/* typedef */ +typedef struct _riff +{ + u32 tag; + u32 size; + u32 type; +} +WaveRiff; + +typedef struct _chunk +{ + u32 tag; + u32 size; +} +WaveChunk; + +typedef struct _fmt +{ + u16 fmt_id; + u16 channel; + u32 sample_rate; + u32 trans_rate; + u16 block_size; + u16 quantum_bits; +} +WaveFmt; + +typedef struct _data +{ + u32 size; + u8* buf; +} +WaveData; + +/*---------------------------------------------------------------------------*/ +/* prototype */ + +void LoadWaveCore(nn::fs::FileReader&, WaveFmt*, WaveData*, bool); +static inline void LoadWave(nn::fs::FileReader& reader, WaveFmt* fmt, WaveData* data) +{ + LoadWaveCore(reader, fmt, data, false); +} +static inline int GetWaveLength(nn::fs::FileReader& reader) +{ + WaveFmt fmt; + WaveData data; + LoadWaveCore(reader, &fmt, &data, true); + return data.size; +} +#ifndef NN_BUILD_RELEASE // Release 繝薙Ν繝峨〒縺ッ HostIO 縺ッ菴ソ縺医∪縺帙s縲 +void WriteWaveHeader(nn::hio::CTR::HostFile& hostFile, WaveFmt* fmt, s32 size); +#endif // NN_BUILD_RELEASE + +#endif // __WAVE_HEADER__ + +/*---------------------------------------------------------------------------*/ +/* end of file */ +/*---------------------------------------------------------------------------*/