diff --git a/branches/1stNUP_7/BoxyardEraser/BoxyardEraser.bsf b/branches/1stNUP_7/BoxyardEraser/BoxyardEraser.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/branches/1stNUP_7/BoxyardEraser/BoxyardEraser.bsf differ diff --git a/branches/1stNUP_7/BoxyardEraser/BoxyardEraser.rsf b/branches/1stNUP_7/BoxyardEraser/BoxyardEraser.rsf new file mode 100644 index 0000000..9735c38 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/BoxyardEraser.rsf @@ -0,0 +1,37 @@ +BasicInfo: + Title : BoxyardEraser + ProductCode: CTR-P-237A + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xf802D + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 0x4000 + Dependency : + - gpio + - pdn + - spi + - i2c + - mcu + - ptm + - codec + - cfg + - hid + - gsp + +AccessControlInfo: + Priority : 16 + DisableDebug : true + +Option: + FreeProductCode: true + + +Rom: + # ROM に含めるファイルシステムのルートパスを指定します。 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/branches/1stNUP_7/BoxyardEraser/BoxyardRemover.desc b/branches/1stNUP_7/BoxyardEraser/BoxyardRemover.desc new file mode 100644 index 0000000..3125817 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/BoxyardRemover.desc @@ -0,0 +1,232 @@ +AccessControlDescriptor: + AffinityMask: 1 + AutoGen: true + CoreVersion: 2 + DescVersion: 2 + Descriptor: | + AP///wAABAACAAAAAAAFGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIAAAAAAAABBUFQ6VQAAACRo + aW9GSU8AJGhvc3RpbzAkaG9zdGlvMWFjOnUAAAAAYm9zczpVAABjYW06dQAA + AGNlY2Q6dQAAY2ZnOnUAAABkbHA6RktDTGRscDpTUlZSZHNwOjpEU1BmcmQ6 + dQAAAGZzOlVTRVIAZ3NwOjpHcHVoaWQ6VVNFUmh0dHA6QwAAbWljOnUAAABu + ZG06dQAAAG5ld3M6dQAAbndtOjpVRFNwdG06dQAAAHB4aTpkZXYAc29jOlUA + AABzc2w6QwAAAHkycjp1AAAAaXI6VVNFUgBsZHI6cm8AAGFtOnUAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAD+//vw/7//8ec/APIA8JH/APaR/1D/gf9Y/4H/cP+B/3j/gf8B + AQD/AAIA/v////////////////////////////////////////////////// + ////////////////////////////////////////AAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAI= + DisableDebug: false + EnableInterruptNumbers: [] + EnableSystemCalls: + ArbitrateAddress: 34 + Break: 60 + CancelTimer: 28 + ClearEvent: 25 + ClearTimer: 29 + CloseHandle: 35 + ConnectToPort: 45 + ControlMemory: 1 + CreateAddressArbiter: 33 + CreateEvent: 23 + CreateMemoryBlock: 30 + CreateMutex: 19 + CreateSemaphore: 21 + CreateThread: 8 + CreateTimer: 26 + DuplicateHandle: 39 + ExitProcess: 3 + ExitThread: 9 + GetCurrentProcessorNumber: 17 + GetHandleInfo: 41 + GetProcessAffinityMask: 4 + GetProcessId: 53 + GetProcessIdOfThread: 54 + GetProcessIdealProcessor: 6 + GetProcessInfo: 43 + GetResourceLimit: 56 + GetResourceLimitCurrentValues: 58 + GetResourceLimitLimitValues: 57 + GetSystemInfo: 42 + GetSystemTick: 40 + GetThreadAffinityMask: 13 + GetThreadContext: 59 + GetThreadId: 55 + GetThreadIdealProcessor: 15 + GetThreadInfo: 44 + GetThreadPriority: 11 + MapMemoryBlock: 31 + OutputDebugString: 61 + QueryMemory: 2 + ReleaseMutex: 20 + ReleaseSemaphore: 22 + SendSyncRequest1: 46 + SendSyncRequest2: 47 + SendSyncRequest3: 48 + SendSyncRequest4: 49 + SendSyncRequest: 50 + SetProcessAffinityMask: 5 + SetProcessIdealProcessor: 7 + SetThreadAffinityMask: 14 + SetThreadIdealProcessor: 16 + SetThreadPriority: 12 + SetTimer: 27 + SignalEvent: 24 + SleepThread: 10 + UnmapMemoryBlock: 32 + WaitSynchronization1: 36 + WaitSynchronizationN: 37 + FileSystemAccess: + - Debug + - DirectSdmc + - DirectSdmcWrite + HandleTableSize: 512 + IORegisterMapping: + - 1ff50000-1ff57fff + - 1ff70000-1ff77fff + IdealProcessor: 1 + MemoryMapping: + - 1f000000-1f5fffff:r + MemoryType: Application + Priority: 24 + ProgramId: 0x00040000ffffff00L + ServiceAccessControl: + - APT:U + - $hioFIO + - $hostio0 + - $hostio1 + - ac:u + - boss:U + - cam:u + - cecd:u + - cfg:u + - dlp:FKCL + - dlp:SRVR + - dsp::DSP + - frd:u + - fs:USER + - gsp::Gpu + - hid:USER + - http:C + - mic:u + - ndm:u + - news:u + - nwm::UDS + - ptm:u + - pxi:dev + - soc:U + - ssl:C + - y2r:u + - ir:USER + - ldr:ro + - am:u + Signature: | + hiQzwen590fW0thDfToCcvkG0S+Uw+X9LKyUJarMsCJ5T14SlKlhKgT9Kkmd + yt1cCDqoEQguN5pQny5iS6usQ51/ORdfO0Qf/ZSYvXNqEZyP2zG54sGd1Uie + /TftK28EhpufbgOCFaPbv3Tnbp5EUZaG0OAwNs0ez4605+e1AzGUrEspzCYK + sqYfTDFDmBz2dul/gvU2kRjGUUYyrw1Eg5ZJPt53LX/DePKXZnvb3eeel/sq + ZOgYLnc2n2upzkpO/dr6Wer2D4o3lpPk1parE6orOyRDB0TTFu6u5aqRldf8 + t8D2fz7keTdyYlhjEgAGUkcEU7ZU1SrvpwD5ktNyaA== + StorageId: + - 0 +CommonHeaderKey: + D: | + xsiNQCpJR94/2XdRoz1v6+OKN8UF+Ev/J5/u4e+EOY1Jjpc7BMg3KRZkrNym + +LYe8vqMT7I/5d3rgasgrX3FAEoIPL9VvL4IqfjZcyo/75o+NE6TOWUp3K3Z + UbDwgMscl9nLPnOFiGFbZsMV/Aa0ro1w7+hXt3+diJaCHzimI0NNy5a8Beqi + Tm1Od3e5lCepBcypiniam9AyMwd3tGHKuMPg3WV6KPyE8lefPkrMkiYHVITY + wvcDvra83T4vprQySXAKuzUDZdrlzCtPe+Bz1eJkWQUuY3MuGNb9OmjQvKzc + w+GF9oNWvV729IH4pwcsgZYMyT+0ok81VeqMHm2HLQ== + DP: | + YdqZEbc18syS7xGY/emuqX+bQPcxgnXpCQVFA8Yh43ztQKPWTxCe9aUE1sY6 + sraf/MT3x3hTlATlOqxJxQZeXxPlQm6Vcpq5iCn78GThugKS5yEkbNaSdQ8T + atWoGbDlQfWgcRovbhd71vzguIP028yGIDuzNnlz5IDZthMfiNU= + DQ: | + ixmQMZXKCcoocsnule/XIpYFQcX3W61Jl6xQs0J4kZCFxUQOb9rjoalVsdRA + 9J11fi5GJ0OTsVc7GuN6dRful9IXDscM3BiJUA8aMmTCxuZpc5xjpXQZ1O1e + wk8IwtamgurCUqW2gsRDMtGjh4gyYT1ybxiyKDI235aBCpTiGws= + Exponent: | + AQAB + InverseQ: | + EMZs1VAoSlb/lK8k5JK+8jJqnZdkikQBZglABYxOdnUy0k//ZQv7bvPsWJFi + fC/KK4U5Cs1ecNIEv6yHqUmpLYVro+7pAcUckvCiknBLJZ1zYNq02cObUhjr + AnHhuKZmS7E+jRyEKH5Sh8wQf1LNG1lR6fH6Q86Adr7ltkKzwbI= + Modulus: | + 6zhbyBHBgjpggDJ9GPgrtqvMTV84dPgPqIHIwUYrkt4qg6vddoqxc6/NzLDJ + 7Avi/wgZc267X/g9tq0vkd+vFY7cR1idP0zCCiEs55a9RM1YMtRGyxdx52Y8 + +6k0ld48l5T24a1mwWWEIpXh8UImxHsKU9yXoCazpaCLukE09x3OxTkZYhYK + HJlRfsVAPWr2BbW4/chR061pzskxjEp9Iw9LEu9Msor/lCd6jASF9rdBbDoH + beY4+67JPDtVnJYyU55vUoLglXXAK73YksTWjFVG2fNp9OQLDZYSuhyInlry + mInm7uKcgQMdXxwe8DIYo4SGIlHg/TfRwcxaB1vd9Q== + P: | + 9o+b9xrx8fhM9rvVFRvR+BHXfpPHKrDDk7eenDWtTPmwQLvwhFmBuZtveP4v + DkjSG+ILlDUZnP2NO9Y7vIWnRoNrKrvoyKDnhVv837SWxjBazYJUCLDXOrH+ + e7+y/KTKTvbUs2SnPocYfhFwFDQFReoC67kXEn2SknY1fhbFehM= + Q: | + 9Dma3JAhr2OJRobNddJfR0zOGrp1KjQePO22IhSBUgoo0bZMcSvQbz+UNYkc + GryMnsgrN8bZdKxIoVo+dKYUHt333ztUJwUF6LnLE+4REynUyvawLNL76aLu + PdxKDhxAc461k5IHNFrRRJ+DS+0qntnUz2Ojo3FeR5+2tLO/SNc= +DefaultSpec: + AccessControlInfo: + AffinityMask: 1 + FirmwareVersion: 2 + HandleTableSize: 512 + IORegisterMapping: + - 1ff50000-1ff57fff + - 1ff70000-1ff77fff + IdealProcessor: 0 + MemoryMapping: + - 1f000000-1f5fffff:r + Priority: 16 + BasicInfo: + CompanyCode: "00" + Logo: Nintendo + Title: default + ExeFs: + ReadOnly: + - RO + ReadWrite: + - RW + Text: + - STUP_ENTRY + Media: + MediaType: Card + PlainRegion: + - .module_id + Rom: + DefaultReject: + - .* + File: + - "*" + SystemControlInfo: + Dependency: + ac: 0x0004013000002402L + am: 0x0004013000001502L + boss: 0x0004013000003402L + camera: 0x0004013000001602L + cecd: 0x0004013000002602L + cfg: 0x0004013000001702L + codec: 0x0004013000001802L + csnd: 0x0004013000002702L + dlp: 0x0004013000002802L + dsp: 0x0004013000001a02L + friends: 0x0004013000003202L + gpio: 0x0004013000001b02L + gsp: 0x0004013000001c02L + hid: 0x0004013000001d02L + http: 0x0004013000002902L + i2c: 0x0004013000001e02L + mcu: 0x0004013000001f02L + mic: 0x0004013000002002L + ndm: 0x0004013000002b02L + news: 0x0004013000003502L + nim: 0x0004013000002c02L + nwm: 0x0004013000002d02L + pdn: 0x0004013000002102L + ps: 0x0004013000003102L + ptm: 0x0004013000002202L + ro: 0x0004013000003702L + socket: 0x0004013000002e02L + spi: 0x0004013000002302L + ssl: 0x0004013000002f02L + StackSize: 16384 diff --git a/branches/1stNUP_7/BoxyardEraser/HeapManager.cpp b/branches/1stNUP_7/BoxyardEraser/HeapManager.cpp new file mode 100644 index 0000000..29f4367 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/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/1stNUP_7/BoxyardEraser/HeapManager.h b/branches/1stNUP_7/BoxyardEraser/HeapManager.h new file mode 100644 index 0000000..b9fc469 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/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/1stNUP_7/BoxyardEraser/OMakefile b/branches/1stNUP_7/BoxyardEraser/OMakefile new file mode 100644 index 0000000..f277296 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/OMakefile @@ -0,0 +1,68 @@ +#!/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.* +CTR_APPTYPE = BOTH +CTR_MAKE_DEVELOPMENT_IMAGE = true + +TARGET_PROGRAM = BoxyardEraser + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + +SOURCES[] = + main.cpp + ResFont.cpp + HeapManager.cpp + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = romfiles + +SHADER_BIN = nnfont_RectDrawerShader.shbin +SHADER_PATH = $(ROMFS_ROOT)/$(SHADER_BIN) + +ROMFS_DEPENDENCIES = $(SHADER_PATH) + +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 \ + +INSTALL_SDK_TOOL = true + +ROM_SPEC_FILE = $(TARGET_PROGRAM).rsf +DESCRIPTOR = BoxyardRemover.desc + +include $(ROOT_OMAKE)/modulerules + +VERSION_H = $(file version.h) + +build: $(DEFAULT_TARGETS) diff --git a/branches/1stNUP_7/BoxyardEraser/OMakeroot b/branches/1stNUP_7/BoxyardEraser/OMakeroot new file mode 100644 index 0000000..7ee1cb5 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/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:$ +#---------------------------------------------------------------------------- + +# fBNgCAEgɂ‚Ă̐ +# +# a) \[XR[h[gfBNgɔzuꍇ +# : +# /OMakeroot +# /foo/bar/OMakefile +# +# : +# OMakefile ƓfBNgȉ objects images ܂B +# +# /foo/bar/objects/... +# /foo/bar/images/.. +# +# +# b) \[XR[h sources ȉɔzuꍇ +# : +# /OMakeroot +# /sources/foo/bar/OMakefile +# +# : +# [gfBNgȉ objects images ܂B +# +# /objects/foo/bar/... +# /images/foo/bar/... +# +# + +# [g‹ϐ̎擾 +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 v܂BpXݒ肷邩Aǂ炩`ĉB) + 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/1stNUP_7/BoxyardEraser/RepairTool.desc b/branches/1stNUP_7/BoxyardEraser/RepairTool.desc new file mode 100644 index 0000000..d3d0e19 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/RepairTool.desc @@ -0,0 +1,232 @@ +AccessControlDescriptor: + AffinityMask: 1 + AutoGen: true + CoreVersion: 2 + DescVersion: 2 + Descriptor: | + AP///wAABAACAAAAAAAFGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjIEAAAAAAABBUFQ6VQAAACRo + aW9GSU8AJGhvc3RpbzAkaG9zdGlvMWFjOnUAAAAAYm9zczpVAABkc3A6OkRT + UGZyZDp1AAAAZnM6VVNFUgBnc3A6OkdwdWhpZDpVU0VSaHR0cDpDAABuZG06 + dQAAAG53bTo6VURTcHRtOnUAAABweGk6ZGV2AHNvYzpVAAAAc3NsOkMAAABs + ZHI6cm8AAHBzOnBzAAAAY2ZnOm5vcgBtY3U6OkhXQ2FtOnUAAAAAY2ZnOmkA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAD+//vw/7//8ec/APIA8JH/APaR/1D/gf9Y/4H/cP+B/3j/gf8B + AQD/AAIA/v////////////////////////////////////////////////// + ////////////////////////////////////////AAAAAAAAAAAAAAAAAAAA + ABUAAAAAAAAAAAAAAAAAAAI= + DisableDebug: false + EnableInterruptNumbers: [] + EnableSystemCalls: + ArbitrateAddress: 34 + Break: 60 + CancelTimer: 28 + ClearEvent: 25 + ClearTimer: 29 + CloseHandle: 35 + ConnectToPort: 45 + ControlMemory: 1 + CreateAddressArbiter: 33 + CreateEvent: 23 + CreateMemoryBlock: 30 + CreateMutex: 19 + CreateSemaphore: 21 + CreateThread: 8 + CreateTimer: 26 + DuplicateHandle: 39 + ExitProcess: 3 + ExitThread: 9 + GetCurrentProcessorNumber: 17 + GetHandleInfo: 41 + GetProcessAffinityMask: 4 + GetProcessId: 53 + GetProcessIdOfThread: 54 + GetProcessIdealProcessor: 6 + GetProcessInfo: 43 + GetResourceLimit: 56 + GetResourceLimitCurrentValues: 58 + GetResourceLimitLimitValues: 57 + GetSystemInfo: 42 + GetSystemTick: 40 + GetThreadAffinityMask: 13 + GetThreadContext: 59 + GetThreadId: 55 + GetThreadIdealProcessor: 15 + GetThreadInfo: 44 + GetThreadPriority: 11 + MapMemoryBlock: 31 + OutputDebugString: 61 + QueryMemory: 2 + ReleaseMutex: 20 + ReleaseSemaphore: 22 + SendSyncRequest1: 46 + SendSyncRequest2: 47 + SendSyncRequest3: 48 + SendSyncRequest4: 49 + SendSyncRequest: 50 + SetProcessAffinityMask: 5 + SetProcessIdealProcessor: 7 + SetThreadAffinityMask: 14 + SetThreadIdealProcessor: 16 + SetThreadPriority: 12 + SetTimer: 27 + SignalEvent: 24 + SleepThread: 10 + UnmapMemoryBlock: 32 + WaitSynchronization1: 36 + WaitSynchronizationN: 37 + FileSystemAccess: + - Debug + - DirectSdmc + - DirectSdmcWrite + - Core + - CategoryFileSystemTool + HandleTableSize: 512 + IORegisterMapping: + - 1ff50000-1ff57fff + - 1ff70000-1ff77fff + IdealProcessor: 1 + IoAccessControl: + - FsMountCardSpi + - FsMountNand + - FsMountTwln + MemoryMapping: + - 1f000000-1f5fffff:r + MemoryType: Application + Priority: 24 + ProgramId: 0x00040000ffffff00L + ServiceAccessControl: + - APT:U + - $hioFIO + - $hostio0 + - $hostio1 + - ac:u + - boss:U + - dsp::DSP + - frd:u + - fs:USER + - gsp::Gpu + - hid:USER + - http:C + - ndm:u + - nwm::UDS + - ptm:u + - pxi:dev + - soc:U + - ssl:C + - ldr:ro + - ps:ps + - cfg:nor + - mcu::HWC + - am:u + - cfg:i + Signature: | + aktZ4eHHc/0DJOO0+J0yS+OCTUDkOocI441pzjNa56jmsr3CsVoD5IGi9K+R + m+3gVcMc6DJHlflrsjGaEAg7a2s2b/yQ9kZAx8mwHgqihlD33eU73kOo0xV1 + hVLn2kWDDpweFKxPfjyfalqtwZLFAAnaz8HS852tokldYDVU6bchxCvF28aJ + vrVN0hHAvaJ2rVv/OMjgYIGwARPS7z5yDs2DxGbcJH55Q8KetUG0QFuXJZIC + g4eOXC2soHSnve1jKKvPfcaIJyBH+3fUVt1FQX88b8t8H51j5uSMbzTmskJY + rsMv6W6bler0T0zs8tHOS9aXCd75QTvpijFFgLQ14Q== + StorageId: + - 0 +CommonHeaderKey: + D: | + kVlG6tIpWOE416smaUI8k/v3soWJXEmzahOtNDHwHUyIKG/U7TWu2RsPHT+q + PvXaLZ6Rt34GqvZzVTpS0595/hqdkQEvFNQZyWTgi1XZJclnNFztAp4cje+l + c9rYm27XiqN01c4z/mJFf9EOFGDKuVTxS9YgOywWHCiOzsLMLc3bV09LGhGX + pMMtWk8CkubDU03onDLvIXT60Z0wJL2D65+cEtf2bt2CqBtIqBqwf7SYToNq + RnlPTohUQp0pXslnMllZ++PoWMOZhENAY6eA/ddwX43e3oHKDsAQPUtf8aX2 + nPf5fMKohI0SjqpFhsSh8mbBm+Bah02Xtd1OiF0XgQ== + DP: | + KRRQMwUuh9j3rsFqFXmkVfci7cnOObNolT5mISNLjOVyb5oBZSnjQGtwAGy3 + F3uUcdykCQi4ZZq1k+mzfuRr+tkKMfQbt9TJ2hHCUfmH5m7CSVr6uTlHaHmX + qXYgsknFDMEOHbwNFrI+89mAlyXwg0M2J9y5hHD3TYp3OfViHZE= + DQ: | + DsFfTFpoPFZYh5Hkb5apEE2WeS29NBt5wxhbqQ838TYeATtnFRKZJzbrVQ4G + TrNy8/pmaoZIUbK+xVCbO/FTid28jGVBOWQVig1KNrdk5nFjlvw3OHCwLIL7 + FyugGwkS7CTM0z+oNorMF71FRapRX0REE9FaCwmi4SNzi9UK2FM= + Exponent: | + AQAB + InverseQ: | + VhhJpDTD3EGpkm8BsN/SCBYOh9ozOVeMig81EjfFctH0u7TLwlMLVEJ96Z8h + 7oVh2c9ZQqWSBO8t/xhrQKdNjKo781rySHWDBjAewzULhUutV0QKUx1IG0wx + WeR3KdKWEURIsArdxT6dacyqOyb7xWdO40N/awZ+9Jv5G+RjCN4= + Modulus: | + 0DQPmbjwh2wztNIEgD/0To/vEjP93JCVQt71+OwxrsfxQYh3xPjcUSqGsZzv + vknSF68QjS5otNOhWMCGubCqn4+1wiFky5mp84xjSSJE0ji+JBomOaCmaC/q + WrEQGuZHIwWAvuMA68Hj/XC/FEV3nmol37j72CPoO3Aac39pgowuMiY4eshZ + TYmJL9K9mUMOXsJq++KoZl1mXEQmQIHfSQalG93yJwybdQs+TUJZy9LEEdGS + CL7Ei7i0bXb7HzS39AOC+g4OHhdCSGyRzutGkm7HoiiZdlK6ShpmBRUerAIl + ED9SuU+SQi9sjnsq3qTVNKbRF/Gzlr+7WrjWBCaxDw== + P: | + /UQWt9VELddu6yu01cCPt3MvdyGSXP+3xHFd3RDsNWQ3amiLFQf1EuXCiZQA + SzPfYOMZInTiVnvctanE9psQ43ZeMAdD3SPsg3uN11g8fr1O2YvTmKMB67K+ + 59DZhpX4vVdkr1/3NCW0ht/iWH4vhSvREH5rb/LL5aXaP5feKZk= + Q: | + 0nNwlIODzVV0tqZbySDZ4/UDG13lse24DQshAVSSb9/dpQs3POBP4bJBZ8HJ + /8N6CODEYhfkXYuWJi8p3vAXzNC5FcXQkZg0CxPK9jp6HPyadN/dfqFEUJ/8 + G8jqXVQt+aIfUDKOorzKRGE4J6UF8ChMqlZ1WkrfkAkszw+xaOc= +DefaultSpec: + AccessControlInfo: + AffinityMask: 1 + FirmwareVersion: 2 + HandleTableSize: 512 + IORegisterMapping: + - 1ff50000-1ff57fff + - 1ff70000-1ff77fff + IdealProcessor: 0 + MemoryMapping: + - 1f000000-1f5fffff:r + Priority: 16 + BasicInfo: + CompanyCode: "00" + Logo: Nintendo + Title: default + ExeFs: + ReadOnly: + - RO + ReadWrite: + - RW + Text: + - STUP_ENTRY + Media: + MediaType: Card + PlainRegion: + - .module_id + Rom: + DefaultReject: + - .* + File: + - "*" + SystemControlInfo: + Dependency: + ac: 0x0004013000002402L + am: 0x0004013000001502L + boss: 0x0004013000003402L + camera: 0x0004013000001602L + cecd: 0x0004013000002602L + cfg: 0x0004013000001702L + codec: 0x0004013000001802L + csnd: 0x0004013000002702L + dlp: 0x0004013000002802L + dsp: 0x0004013000001a02L + friends: 0x0004013000003202L + gpio: 0x0004013000001b02L + gsp: 0x0004013000001c02L + hid: 0x0004013000001d02L + http: 0x0004013000002902L + i2c: 0x0004013000001e02L + mcu: 0x0004013000001f02L + mic: 0x0004013000002002L + ndm: 0x0004013000002b02L + news: 0x0004013000003502L + nim: 0x0004013000002c02L + nwm: 0x0004013000002d02L + pdn: 0x0004013000002102L + ps: 0x0004013000003102L + ptm: 0x0004013000002202L + socket: 0x0004013000002e02L + spi: 0x0004013000002302L + ssl: 0x0004013000002f02L + StackSize: 16384 diff --git a/branches/1stNUP_7/BoxyardEraser/ResFont.cpp b/branches/1stNUP_7/BoxyardEraser/ResFont.cpp new file mode 100644 index 0000000..b0183df --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/ResFont.cpp @@ -0,0 +1,417 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ResFont.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$ + *---------------------------------------------------------------------------*/ + +//------------------------------------------------------------------ +// デモ: ResFont +// +// 概要 +// nn::font::ResFont の構築と破棄のサンプルです。 +// +// 操作 +// なし。 +// +//------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "ResFont.h" +#include "demo.h" +#include "HeapManager.h" + +namespace common +{ + +namespace +{ +const char s_ShaderBinaryFilePath[] = "rom:/nnfont_RectDrawerShader.shbin"; +const char s_FontFilePath[] = "rom:/lc.bcfnt"; + +const u8 s_Color = 255; + +nn::font::RectDrawer s_Drawer; +void* s_DrawerBuf; +nn::font::ResFont s_Font; +nn::font::DispStringBuffer *s_pDrawStringBuf0; +nn::font::TextWriter s_TextWriter; +void (*s_DrawTextFunc)() = NULL; + +//--------------------------------------------------------------------------- +//! @brief シェーダの初期化を行います。 +//! +//! @param[in,out] pResource 描画用リソースを管理するオブジェクトへのポインタ。 +//--------------------------------------------------------------------------- +void* +InitShaders(nn::font::RectDrawer* pDrawer) +{ + nn::fs::FileReader shaderReader(s_ShaderBinaryFilePath); + + const u32 fileSize = (u32)shaderReader.GetSize(); + + void* shaderBinary = HeapManager::GetHeap()->Allocate(fileSize); + NN_NULL_ASSERT(shaderBinary); + +#ifndef NN_BUILD_RELEASE + s32 read = +#endif // NN_BUILD_RELEASE + shaderReader.Read(shaderBinary, fileSize); + NN_ASSERT(read == fileSize); + + const u32 vtxBufCmdBufSize = + nn::font::RectDrawer::GetVertexBufferCommandBufferSize(shaderBinary, fileSize); + void *const vtxBufCmdBuf = HeapManager::GetHeap()->Allocate(vtxBufCmdBufSize); + NN_NULL_ASSERT(vtxBufCmdBuf); + pDrawer->Initialize(vtxBufCmdBuf, shaderBinary, fileSize); + + HeapManager::GetHeap()->Free(shaderBinary); + + return vtxBufCmdBuf; + +} + +//--------------------------------------------------------------------------- +//! @brief 描画の初期設定を行います。 +//! +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +InitDraw( + s32 width, + s32 height +) +{ + // カラーバッファ情報 + // LCDの向きに合わせて、幅と高さを入れ替えています。 + 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 ), + + // ステンシルテストを無効 + NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(), + + // デプステストを無効 + // カラーバッファの全ての成分を書き込み可 + NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK( + false, // isDepthTestEnabled + 0, // depthFunc + true, // depthMask + true, // red + true, // green + true, // blue + true), // alpha + + // アーリーデプステストを無効 + 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, + const char* filePath +) +{ + // フォントリソースをロードします + nn::fs::FileReader fontReader(filePath); + + s32 fileSize = (s32)fontReader.GetSize(); + if ( fileSize <= 0 ) + { + return false; + } + + void* buffer = HeapManager::GetHeap()->Allocate(fileSize, nn::font::GlyphDataAlignment); + if (buffer == NULL) + { + return false; + } + + s32 readSize = fontReader.Read(buffer, fileSize); + if (readSize != fileSize) + { + HeapManager::GetHeap()->Free(buffer); + return false; + } + + // フォントリソースをセットします + bool bSuccess = pFont->SetResource(buffer); + NN_ASSERT(bSuccess); + + //--- 既にリソースをセット済みであるか,ロード済みであるか、リソースが不正な場合に失敗します。 + if (! bSuccess) + { + HeapManager::GetHeap()->Free(buffer); + } + + // 描画用バッファを設定します。 + const u32 drawBufferSize = nn::font::ResFont::GetDrawBufferSize(buffer); + void* drawBuffer = HeapManager::GetHeap()->Allocate(drawBufferSize, 4); + NN_NULL_ASSERT(drawBuffer); + pFont->SetDrawBuffer(drawBuffer); + + return bSuccess; +} + +//--------------------------------------------------------------------------- +//! @brief ResFontを破棄します。 +//! +//! @param[in] pFont 破棄するフォントへのポインタ。 +//--------------------------------------------------------------------------- +void +CleanupFont(nn::font::ResFont* pFont) +{ + // 描画用バッファの無効化 + // 描画用バッファがセットされているなら 構築時に SetDrawBuffer に渡したバッファへの + // ポインタが返ってきます。 + void *const drawBuffer = pFont->SetDrawBuffer(NULL); + if (drawBuffer != NULL) + { + HeapManager::GetHeap()->Free(drawBuffer); + } + + // フォントがセットされているなら SetResource 時に渡したリソースへの + // ポインタが返ってきます。 + void *const resource = pFont->RemoveResource(); + if (resource != NULL) + { + HeapManager::GetHeap()->Free(resource); + } + + // RemoveResource 後は再度 SetResource するまでフォントとして使用できません。 +} + +//--------------------------------------------------------------------------- +//! @brief 表示文字列用バッファを確保します。 +//! +//! @param[in] charMax 表示する文字列の最大文字数。 +//! +//! @return 確保した表示文字列用バッファへのポインタを返します。 +//--------------------------------------------------------------------------- +nn::font::DispStringBuffer* +AllocDispStringBuffer(s32 charMax) +{ + const u32 DrawBufferSize = nn::font::CharWriter::GetDispStringBufferSize(charMax); + void *const bufMem = HeapManager::GetHeap()->Allocate(DrawBufferSize); + NN_NULL_ASSERT(bufMem); + + return nn::font::CharWriter::InitDispStringBuffer(bufMem, charMax); +} + +//--------------------------------------------------------------------------- +//! @brief 文字列表示用にモデルビュー行列と射影行列を設定します。 +//! +//! @param[in] pDrawer RectDrawerオブジェクトへのポインタ。 +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +SetupTextCamera( + nn::font::RectDrawer* pDrawer, + s32 width, + s32 height +) +{ + // 射影行列を正射影に設定 + { + // 左上原点とし、Y軸とZ軸の向きが逆になるように設定します。 + 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); + } + + // モデルビュー行列を単位行列に設定 + { + nn::math::MTX34 mv; + nn::math::MTX34Identity(&mv); + pDrawer->SetViewMtxForText(mv); + } +} + +//--------------------------------------------------------------------------- +//! @brief ASCII文字列を描画します。 +//! +//! @param[in] pDrawer RectDrawerオブジェクトへのポインタ。 +//! @param[in] pDrawStringBuf DispStringBufferオブジェクトへのポインタ。 +//! @param[in] pFont フォントへのポインタ。 +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +DrawAscii( + nn::font::RectDrawer* pDrawer, + nn::font::DispStringBuffer* pDrawStringBuf, + nn::font::ResFont* pFont, + s32 width, + s32 height +) +{ + s_TextWriter.SetDispStringBuffer(pDrawStringBuf); + s_TextWriter.SetFont(pFont); + + s_TextWriter.SetCursor(0, 0, 1.f); + + s_TextWriter.StartPrint(); + if(s_DrawTextFunc != NULL) + { + s_DrawTextFunc(); + } + + s_TextWriter.EndPrint(); + pDrawer->BuildTextCommand(&s_TextWriter); + + + // 文字の色は、文字列の描画コマンドを再作成しなくても変更できます。 + s_TextWriter.SetTextColor(nn::util::Color8(s_Color, s_Color, s_Color, s_Color)); + + pDrawer->DrawBegin(); + + SetupTextCamera(pDrawer, width, height); + s_TextWriter.UseCommandBuffer(); + + pDrawer->DrawEnd(); +} + +} // namespace + +void SetDrawTextHandler(void (*func)()) +{ + s_DrawTextFunc = func; +} + + +//--------------------------------------------------------------------------- +//! @brief サンプルのメイン関数です。 +//--------------------------------------------------------------------------- +void +InitializeResFont() +{ + 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)); + + // フォントの構築 + { +#ifndef NN_BUILD_RELEASE + bool bSuccess = +#endif // NN_BUILD_RELEASE + InitFont(&s_Font, s_FontFilePath); + NN_ASSERTMSG(bSuccess, "Fail to load ResFont."); + } + + // 描画リソースの構築 + s_DrawerBuf = InitShaders(&s_Drawer); + + // 描画文字列用バッファの確保 + s_pDrawStringBuf0 = AllocDispStringBuffer(512); + + nn::fs::Unmount("rom:"); + +} + +void DrawResFont(s32 display) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if(display == NN_GX_DISPLAY0) + { + InitDraw(NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + + DrawAscii(&s_Drawer, s_pDrawStringBuf0, &s_Font, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + } + else if(display == NN_GX_DISPLAY1) + { + InitDraw(NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT); + + DrawAscii(&s_Drawer, s_pDrawStringBuf0, &s_Font, NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT); + } + + nngxUpdateState(NN_GX_STATE_ALL); +} + +void FinalizeResFont() +{ + s_Drawer.Finalize(); + + // 描画リソースの破棄 + HeapManager::GetHeap()->Free(s_DrawerBuf); + + // フォントの破棄 + CleanupFont(&s_Font); + + // 描画文字列用バッファの解放 + HeapManager::GetHeap()->Free(s_pDrawStringBuf0); +} + +nn::font::TextWriter* GetTextWriter() +{ + return &s_TextWriter; +} + +} diff --git a/branches/1stNUP_7/BoxyardEraser/ResFont.h b/branches/1stNUP_7/BoxyardEraser/ResFont.h new file mode 100644 index 0000000..ca53420 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/ResFont.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ResFont.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 RESFONT_H_ +#define RESFONT_H_ + +#include + +namespace common +{ + +void InitializeResFont(); +void DrawResFont(s32 display); +void SetDrawTextHandler(void (*func)()); +nn::font::TextWriter* GetTextWriter(); + + +} + + +#endif /* RESFONT_H_ */ diff --git a/branches/1stNUP_7/BoxyardEraser/banner/model.cbmd b/branches/1stNUP_7/BoxyardEraser/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/BoxyardEraser/banner/model.cbmd differ diff --git a/branches/1stNUP_7/BoxyardEraser/banner/sound.cbsd b/branches/1stNUP_7/BoxyardEraser/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/BoxyardEraser/banner/sound.cbsd differ diff --git a/branches/1stNUP_7/BoxyardEraser/banner/unknown24x24.ctpk b/branches/1stNUP_7/BoxyardEraser/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +888yyYyYyyyYyyYyyyyYyYy8 \ No newline at end of file diff --git a/branches/1stNUP_7/BoxyardEraser/banner/unknown48x48.ctpk b/branches/1stNUP_7/BoxyardEraser/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +Y8888ƺ8888YYyyYYޚ޺yY8YyYYޚyY8ޚ8 \ No newline at end of file diff --git a/branches/1stNUP_7/BoxyardEraser/main.cpp b/branches/1stNUP_7/BoxyardEraser/main.cpp new file mode 100644 index 0000000..409f34b --- /dev/null +++ b/branches/1stNUP_7/BoxyardEraser/main.cpp @@ -0,0 +1,314 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: main.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 "demo.h" +#include "ResFont.h" +#include "HeapManager.h" + +#define UTIL_RETURN_IF_NOT_AM_NOT_FOUND(result) \ + if(result.IsFailure()) \ + { \ + if(result != nn::am::ResultNotFound()) \ + { \ + return result; \ + } \ + nn::dbg::PrintResult(result); \ +} \ + +// リリースする際には↓をコメントアウトしてReleaseビルドすること +//#define USE_PROD_CIA + +namespace { + +nn::Result DeleteBoxyard(nn::ProgramId programId); +nn::Result DownGradeNupVersion(nn::cfg::CTR::CfgRegionCode region); +void FatalDrawing(nn::Result result); + +const size_t ERASE_THREAD_STACK_SIZE = 0x1000; +nn::os::Thread s_EraseThread; +nn::os::StackBuffer s_EraseThreadStack; + +demo::RenderSystemDrawing s_RenderSystem; + +// グラフィックスに割り当てるメモリ +const size_t s_GxHeapSize = 0x800000; + +::std::vector* s_pOperationMessage; + +// インポートする +bit8 s_ReadBuf[64 * 1024]; + +const nn::ProgramId BOXYARD_PROGRAM_ID[] = +{ + 0x0004001000023000ULL, // JP + 0x0004001000024000ULL, // US + 0x0004001000025000ULL // EU +}; + +const nn::ProgramId NUP_VERSION_PROGRAM_ID[] = +{ + 0x000400DB00016202ULL, // JP + 0x000400DB00016302ULL, // US + 0x000400DB00016102ULL // EU +}; + +const wchar_t* ROM_NUP_VERSION_PATH[] = +{ +#ifndef USE_PROD_CIA + L"rom:/000400DB00016202-0_0_0-nup.version.JP-UnfixedKey.cia", // JP + L"rom:/000400DB00016302-0_0_0-nup.version.US-UnfixedKey.cia", // US + L"rom:/000400DB00016102-0_0_0-nup.version.EU-UnfixedKey.cia" // EU +#ifdef NN_BUILD_RELEASE +#warning !! Using Development Nup Version cia on Release Build !! +#endif +#else +#ifndef NN_BUILD_RELEASE +#warning !! Using Product Nup Version cia on Development Build !! +#endif + + L"rom:/000400DB00016202-0_0_0-nup.version.JP.master.ols.cia", // JP + L"rom:/000400DB00016302-0_0_0-nup.version.US.master.ols.cia", // US + L"rom:/000400DB00016102-0_0_0-nup.version.EU.master.ols.cia" // EU +#endif +}; + +void EraseThreadFunc(nn::cfg::CTR::CfgRegionCode region) +{ + nn::Result result; + + s_pOperationMessage->push_back(std::string("")); + s_pOperationMessage->push_back(std::string("Deleting...")); + // BOXYARDを消去する + result = DeleteBoxyard(BOXYARD_PROGRAM_ID[region]); + if(result.IsFailure()) + { + nn::dbg::PrintResult(result); + s_pOperationMessage->push_back(std::string("Failed Delete Program")); + FatalDrawing(result); + } + s_pOperationMessage->push_back(std::string("Done.")); + s_pOperationMessage->push_back(std::string("")); + + s_pOperationMessage->push_back(std::string("Updating System...")); + // NUPバージョンを更新する + result = DownGradeNupVersion(region); + if (result.IsFailure()) + { + nn::dbg::PrintResult(result); + s_pOperationMessage->push_back(std::string("Failed DownGrade NUP Version")); + FatalDrawing(result); + } + + + s_pOperationMessage->push_back(std::string("Done.")); + s_pOperationMessage->push_back(std::string("")); + + s_pOperationMessage->push_back(std::string("Finished.")); + s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 0, 1, 0, 0); + s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 0, 1, 0, 0); +} + +nn::Result DownGradeNupVersion(nn::cfg::CTR::CfgRegionCode region) +{ + nn::Result result = nn::ResultSuccess(); + + if(region > sizeof(NUP_VERSION_PROGRAM_ID) / sizeof(NUP_VERSION_PROGRAM_ID[0]) - 1) + { + return nn::Result(nn::Result::LEVEL_STATUS, nn::Result::SUMMARY_INVALID_ARGUMENT, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_INVALID_ENUM_VALUE); + } + nn::ProgramID programId = NUP_VERSION_PROGRAM_ID[region]; + + // リージョンに合わせて削除する + result = nn::am::DeleteProgram(nn::fs::MEDIA_TYPE_NAND, programId); + UTIL_RETURN_IF_NOT_AM_NOT_FOUND(result); + + nn::fs::FileOutputStream* stream; + result = nn::am::BeginImportProgram(&stream, nn::fs::MEDIA_TYPE_NAND); + NN_UTIL_RETURN_IF_FAILED(result); + + NN_LOG("Importing: %ls...", ROM_NUP_VERSION_PATH[region]); + nn::fs::FileInputStream in; + + 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)); + + result = in.TryInitialize(ROM_NUP_VERSION_PATH[region]); + NN_UTIL_RETURN_IF_FAILED(result); + + s64 fileSize = in.GetSize(); + s32 totalRead = 0; + s32 readSize = 0; + do + { + result = in.TryRead(&readSize, s_ReadBuf, sizeof(s_ReadBuf)); + stream->Write(s_ReadBuf, readSize); + totalRead += readSize; + } while (totalRead < fileSize); + + in.Finalize(); + nn::fs::Unmount("rom:"); + + result = nn::am::EndImportProgram(stream); + NN_UTIL_RETURN_IF_FAILED(result); + NN_LOG(" done.\n"); + + return result; +} + +nn::Result DeleteBoxyard(nn::ProgramId programId) +{ + nn::Result result; + + NN_LOG("Deleting Boxyard Program..."); + // リージョンに合わせて削除する + result = nn::am::DeleteProgram(nn::fs::MEDIA_TYPE_NAND, programId); + UTIL_RETURN_IF_NOT_AM_NOT_FOUND(result); + NN_LOG("Done\n"); + + NN_LOG("Deleting Boxyard eTicket..."); + // チケットを削除する + result = nn::am::DeleteTicket(programId); + UTIL_RETURN_IF_NOT_AM_NOT_FOUND(result); + NN_LOG("Done\n"); + + return result; +} + +void SetTextWriterCore() +{ + using namespace common; + + GetTextWriter()->Print("3DMovie Eraser\n\n"); + ::std::vector::iterator it; + for (it = s_pOperationMessage->begin(); it != s_pOperationMessage->end(); it++) + { + GetTextWriter()->Printf("%s\n", it->c_str()); + } + +} + +void FatalDrawing(nn::Result result) +{ + char resultStr[32]; + std::snprintf(resultStr, sizeof(resultStr), "%X", result.GetPrintableBits()); + s_pOperationMessage->push_back(resultStr); + + for(;;) + { + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); + s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 1.f, 0, 0, 0); + s_RenderSystem.Clear(); + + common::SetDrawTextHandler(SetTextWriterCore); + common::DrawResFont(NN_GX_DISPLAY0); + s_RenderSystem.SwapBuffers(); + + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); + s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 1.f, 0, 0, 0); + s_RenderSystem.Clear(); + + s_RenderSystem.SwapBuffers(); + } +} + +} + +extern "C" void nnMain(void) +{ + // os の初期化 + nn::os::Initialize(); + + // fs の初期化 + nn::fs::Initialize(); + + // appletの初期化 + nn::applet::Enable( false ); + + // hid の初期化 + nn::Result result = nn::hid::Initialize(); + NN_UTIL_PANIC_IF_FAILED(result); + + // cfg の初期化 + nn::cfg::CTR::Initialize(); + + // リージョンの取得 + nn::cfg::CTR::CfgRegionCode region; + region = nn::cfg::CTR::GetRegion(); + + // am の初期化 + nn::am::InitializeForLocalImporter(); + + // ヒープの確保 + common::HeapManager::GetHeap()->Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + // RenderSystem の準備 + uptr heapForGx = reinterpret_cast(common::HeapManager::GetHeap()->Allocate(s_GxHeapSize)); + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + + // ResFontの初期化 + common::InitializeResFont(); + + std::vector operationMessage; + s_pOperationMessage = &operationMessage; + + operationMessage.push_back(std::string("Region: ") + std::string(nn::cfg::CTR::GetRegionCodeA3(region))); + + s_EraseThread.Start(EraseThreadFunc, region, s_EraseThreadStack); + + // ボタン入力 + nn::hid::PadReader padReader; + nn::hid::PadStatus padStatus; + + s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 0, 0, 0, 0); + s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 0, 0, 0, 0); + + for(;;) + { + padReader.ReadLatest(&padStatus); + + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); + s_RenderSystem.Clear(); + + common::SetDrawTextHandler(SetTextWriterCore); + common::DrawResFont(NN_GX_DISPLAY0); + s_RenderSystem.SwapBuffers(); + + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); + s_RenderSystem.Clear(); + s_RenderSystem.SwapBuffers(); + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(10)); + + if ( nn::applet::IsExpectedToCloseApplication() ) + { + nn::applet::PrepareToCloseApplication(); + nn::applet::CloseApplication(); + } + + } +} diff --git a/branches/1stNUP_7/BoxyardEraser/romfiles/000400DB00016102-0_0_0-nup.version.EU-UnfixedKey.cia b/branches/1stNUP_7/BoxyardEraser/romfiles/000400DB00016102-0_0_0-nup.version.EU-UnfixedKey.cia new file mode 100644 index 0000000..e00a27f Binary files /dev/null and b/branches/1stNUP_7/BoxyardEraser/romfiles/000400DB00016102-0_0_0-nup.version.EU-UnfixedKey.cia differ diff --git a/branches/1stNUP_7/BoxyardEraser/romfiles/000400DB00016202-0_0_0-nup.version.JP-UnfixedKey.cia b/branches/1stNUP_7/BoxyardEraser/romfiles/000400DB00016202-0_0_0-nup.version.JP-UnfixedKey.cia new file mode 100644 index 0000000..466972a Binary files /dev/null and b/branches/1stNUP_7/BoxyardEraser/romfiles/000400DB00016202-0_0_0-nup.version.JP-UnfixedKey.cia differ diff --git a/branches/1stNUP_7/BoxyardEraser/romfiles/000400DB00016302-0_0_0-nup.version.US-UnfixedKey.cia b/branches/1stNUP_7/BoxyardEraser/romfiles/000400DB00016302-0_0_0-nup.version.US-UnfixedKey.cia new file mode 100644 index 0000000..a061dce Binary files /dev/null and b/branches/1stNUP_7/BoxyardEraser/romfiles/000400DB00016302-0_0_0-nup.version.US-UnfixedKey.cia differ diff --git a/branches/1stNUP_7/BoxyardEraser/romfiles/lc.bcfnt b/branches/1stNUP_7/BoxyardEraser/romfiles/lc.bcfnt new file mode 100644 index 0000000..28d1db0 Binary files /dev/null and b/branches/1stNUP_7/BoxyardEraser/romfiles/lc.bcfnt differ diff --git a/branches/1stNUP_7/BoxyardEraser/romfiles/nnfont_RectDrawerShader.shbin b/branches/1stNUP_7/BoxyardEraser/romfiles/nnfont_RectDrawerShader.shbin new file mode 100644 index 0000000..4290c2c Binary files /dev/null and b/branches/1stNUP_7/BoxyardEraser/romfiles/nnfont_RectDrawerShader.shbin differ diff --git a/branches/1stNUP_7/CardCup/HeapManager.cpp b/branches/1stNUP_7/CardCup/HeapManager.cpp new file mode 100644 index 0000000..8e95885 --- /dev/null +++ b/branches/1stNUP_7/CardCup/HeapManager.cpp @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------------* + 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" + +nn::fnd::ThreadSafeExpHeap s_AppHeap; + + +HeapManager::HeapManager(size_t byteSize, s32 alignment, bit8 groupId, nn::fnd::ExpHeapBase::AllocationMode mode, bool reuse) +{ + m_Ptr = s_AppHeap.Allocate(byteSize, alignment, groupId, mode, reuse); +} + +HeapManager::~HeapManager() +{ + if(m_Ptr != NULL) + { + s_AppHeap.Free(m_Ptr); + } +} +void* HeapManager::GetAddr() +{ + return m_Ptr; +} + +void InitializeHeap() +{ + s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); +} + +size_t GetAllocatableSize(s32 alignment) +{ + return s_AppHeap.GetAllocatableSize(alignment); +} + +void* ForceAllocate(size_t byteSize, s32 alignment, bit8 groupId, nn::fnd::ExpHeapBase::AllocationMode mode, bool reuse) +{ + return s_AppHeap.Allocate(byteSize, alignment, groupId, mode, reuse); +} + +void ForceFree(void* ptr) +{ + if(ptr != NULL) + { + s_AppHeap.Free(ptr); + } +} diff --git a/branches/1stNUP_7/CardCup/HeapManager.h b/branches/1stNUP_7/CardCup/HeapManager.h new file mode 100644 index 0000000..f50f3fe --- /dev/null +++ b/branches/1stNUP_7/CardCup/HeapManager.h @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------------* + 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 +#include + +class HeapManager +{ +public: + explicit HeapManager(size_t byteSize, s32 alignment = nn::fnd::ExpHeapBase::DEFAULT_ALIGNMENT, bit8 groupId = 0, + nn::fnd::ExpHeapBase::AllocationMode mode = nn::fnd::ExpHeapBase::ALLOCATION_MODE_FIRST_FIT, bool reuse = false); + virtual ~HeapManager(); + + void* GetAddr(); + +private: + void* m_Ptr; + +}; + +void InitializeHeap(); +size_t GetAllocatableSize(s32 alignment = nn::fnd::ExpHeapBase::DEFAULT_ALIGNMENT); + +// HeapManagerを使わず確保する場合のみ +void* ForceAllocate(size_t byteSize, s32 alignment = nn::fnd::ExpHeapBase::DEFAULT_ALIGNMENT, bit8 groupId = 0, + nn::fnd::ExpHeapBase::AllocationMode mode = nn::fnd::ExpHeapBase::ALLOCATION_MODE_FIRST_FIT, bool reuse = false); + +// HeapManagerを使わず解放する場合のみ +void ForceFree(void* ptr); + +#endif /* HEAPMANAGER_H_ */ diff --git a/branches/1stNUP_7/CardCup/OMakefile b/branches/1stNUP_7/CardCup/OMakefile new file mode 100644 index 0000000..26a88d5 --- /dev/null +++ b/branches/1stNUP_7/CardCup/OMakefile @@ -0,0 +1,47 @@ +#!/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=CARD + +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 + VersionDetect.cpp + HeapManager.cpp + +LIBS += lib_demo \ + libnn_am \ + libnn_cup \ + libnn_ns \ + +ROMFS_ROOT = romfiles + +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/SelfCup.desc + +TARGET_PROGRAM = SelfCupTool + +TITLE = SelfCupTool +ROM_SPEC_FILE = SelfCupTool.rsf + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +include $(ROOT_OMAKE)/modulerules + +build: $(DEFAULT_TARGETS) diff --git a/branches/1stNUP_7/CardCup/OMakeroot b/branches/1stNUP_7/CardCup/OMakeroot new file mode 100644 index 0000000..7ee1cb5 --- /dev/null +++ b/branches/1stNUP_7/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:$ +#---------------------------------------------------------------------------- + +# fBNgCAEgɂ‚Ă̐ +# +# a) \[XR[h[gfBNgɔzuꍇ +# : +# /OMakeroot +# /foo/bar/OMakefile +# +# : +# OMakefile ƓfBNgȉ objects images ܂B +# +# /foo/bar/objects/... +# /foo/bar/images/.. +# +# +# b) \[XR[h sources ȉɔzuꍇ +# : +# /OMakeroot +# /sources/foo/bar/OMakefile +# +# : +# [gfBNgȉ objects images ܂B +# +# /objects/foo/bar/... +# /images/foo/bar/... +# +# + +# [g‹ϐ̎擾 +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 v܂BpXݒ肷邩Aǂ炩`ĉB) + 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/1stNUP_7/CardCup/Readme.txt b/branches/1stNUP_7/CardCup/Readme.txt new file mode 100644 index 0000000..01dd48d --- /dev/null +++ b/branches/1stNUP_7/CardCup/Readme.txt @@ -0,0 +1,4 @@ +rh‹ +ESDK + Horizon 2.3 branch r38025 + r38091 SelfCup.desc + + trunk r38944 pl_SharedDataTitleId.h diff --git a/branches/1stNUP_7/CardCup/SelfCupTool.bsf b/branches/1stNUP_7/CardCup/SelfCupTool.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/branches/1stNUP_7/CardCup/SelfCupTool.bsf differ diff --git a/branches/1stNUP_7/CardCup/SelfCupTool.rsf b/branches/1stNUP_7/CardCup/SelfCupTool.rsf new file mode 100644 index 0000000..4a361c9 --- /dev/null +++ b/branches/1stNUP_7/CardCup/SelfCupTool.rsf @@ -0,0 +1,26 @@ +BasicInfo: + Title: SelfCupTool + ProductCode: CTR-P-234A + BackupMemoryType: None + Logo: Nintendo + +CardInfo: + CardDevice: None + +TitleInfo: + Use: Evaluation + UniqueId: 0xf802a + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 65536 + Dependency: + - nwm + - socket + - ssl + - friends + - ac + - cecd + - boss + - ndm diff --git a/branches/1stNUP_7/CardCup/VersionDetect.cpp b/branches/1stNUP_7/CardCup/VersionDetect.cpp new file mode 100644 index 0000000..0204041 --- /dev/null +++ b/branches/1stNUP_7/CardCup/VersionDetect.cpp @@ -0,0 +1,67 @@ +/*---------------------------------------------------------------------------* + 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" + +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, cNupVerId[region], 0, 1, 1, buf, + BUF_SIZE); + + nn::fs::FileInputStream fis; + + result = fis.TryInitialize(L"nver:/version.bin"); + if (result.IsSuccess()) + { + s64 fileSize = fis.GetSize(); + NN_LOG("version.bin size = %lld\n", fileSize); + s32 ret; + void* addr = NULL; + HeapManager heap(fileSize); + addr = heap.GetAddr(); + if (addr != NULL) + { + result = fis.TryRead(&ret, addr, fileSize); + if (result.IsSuccess()) + { + nn::pl::CTR::NetworkUpdateVersion* ver_buf = + reinterpret_cast (addr); + + std::memcpy(nup, ver_buf, sizeof(nn::pl::CTR::NetworkUpdateVersion)); + } + } + } + + fis.Finalize(); + nn::fs::Unmount("nver:"); + } + +} + +void GetSystemVersion(VerDef* mVerData, nn::cfg::CTR::CfgRegionCode region) +{ + GetNupVersion(&mVerData->nup, region); +} diff --git a/branches/1stNUP_7/CardCup/VersionDetect.h b/branches/1stNUP_7/CardCup/VersionDetect.h new file mode 100644 index 0000000..7f94174 --- /dev/null +++ b/branches/1stNUP_7/CardCup/VersionDetect.h @@ -0,0 +1,55 @@ +/*---------------------------------------------------------------------------* + 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 +#include + +struct VerDef +{ + nn::pl::CTR::CardUpdateVersion cup; + nn::pl::CTR::NetworkUpdateVersion nup; +}; + +// 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, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_EU, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_CN, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_KR, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_TW, +}; + +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, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_EU, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_CN, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_KR, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_TW, +}; + +// リージョンコードに基づいてバージョン情報を取得する +void GetSystemVersion(VerDef* mVerData, nn::cfg::CTR::CfgRegionCode region); + +#endif /* VERSIONDETECT_H_ */ diff --git a/branches/1stNUP_7/CardCup/banner/model.cbmd b/branches/1stNUP_7/CardCup/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/CardCup/banner/model.cbmd differ diff --git a/branches/1stNUP_7/CardCup/banner/sound.cbsd b/branches/1stNUP_7/CardCup/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/CardCup/banner/sound.cbsd differ diff --git a/branches/1stNUP_7/CardCup/banner/unknown24x24.ctpk b/branches/1stNUP_7/CardCup/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/1stNUP_7/CardCup/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +888yyYyYyyyYyyYyyyyYyYy8 \ No newline at end of file diff --git a/branches/1stNUP_7/CardCup/banner/unknown48x48.ctpk b/branches/1stNUP_7/CardCup/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/1stNUP_7/CardCup/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +Y8888ƺ8888YYyyYYޚ޺yY8YyYYޚyY8ޚ8 \ No newline at end of file diff --git a/branches/1stNUP_7/CardCup/main.cpp b/branches/1stNUP_7/CardCup/main.cpp new file mode 100644 index 0000000..c97922c --- /dev/null +++ b/branches/1stNUP_7/CardCup/main.cpp @@ -0,0 +1,358 @@ +/*---------------------------------------------------------------------------* + 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 +#include + +#include + +#include "demo.h" +#include "scrollBuffer.h" +#include "VersionDetect.h" +#include "HeapManager.h" + +namespace +{ +const s32 s_GxHeapSize = 0x800000; +uptr s_GxHeap; + +demo::RenderSystemDrawing s_RenderSystem; +ScrollBuffer s_scrollBufferInstance; +ScrollBuffer *s_scrollBuffer; + +char s_updaterBuffer[1 << 20] NN_ATTRIBUTE_ALIGN(4096); + +// デモの初期化 +void Initialize() +{ + // NuiShellの初期化 (CUPに必須) + NN_UTIL_PANIC_IF_FAILED(nn::ns::CTR::InitializeForShell()); + + // ndmの初期化 + nn::ndm::Initialize(); + + // 全デーモンの自律動作をacの自動接続も含めて止める + nn::ndm::SuspendScheduler(); + + // amの初期化 + nn::am::InitializeForSystemMenu(); + + // 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(); + + nn::cfg::Initialize(); + + // デバイスメモリの設定 + const s32 DEVICE_MEMORY_SIZE = 32 * 1024 * 1024; + NN_UTIL_PANIC_IF_FAILED(nn::os::SetDeviceMemorySize(DEVICE_MEMORY_SIZE)); + + // ヒープの初期化 + InitializeHeap(); + + // 描画インスタンスの初期化 + s_GxHeap = reinterpret_cast(ForceAllocate(s_GxHeapSize));s_RenderSystem + .Initialize(s_GxHeap, s_GxHeapSize); + + // 描画インスタンスの初期化 + 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[] = "-\\|/"; +s32 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()); + + // ステータスがStartedになるまで、プログレスは取得できない + 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がFAILEDかどうか確認 + 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がFAILEDかどうか確認 + 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がFAILEDかどうか確認 + 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(); + + /********************* 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するために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; +} +} + +nn::Result ExecuteCup(ScrollBuffer* scrollBuf) +{ + nn::Result result; + bool isHandledError = false; + result = UpdateSequence(&isHandledError); + if (isHandledError == false && result.IsFailure()) + { + { + // それ以外の場合は、Resultを表示 + scrollBuf->AppendText(" - Unhandled Error: 0x%08x", result.GetPrintableBits()); + scrollBuf->AppendText("")->Render(); + } + } + + return result; +} + +extern "C" void nnMain() +{ + NN_LOG("Start cup demo\n"); + nn::Result result; + Initialize(); + + nn::ProgramId MMEN_PROGRAM_ID = 0x0004003000008202; + + nn::cfg::CfgRegionCode region = nn::cfg::GetRegion(); + switch (region) + { + case nn::cfg::CFG_REGION_AMERICA: + { + MMEN_PROGRAM_ID = 0x0004003000008f02; + } + break; + + case nn::cfg::CFG_REGION_EUROPE: + case nn::cfg::CFG_REGION_AUSTRALIA: + { + MMEN_PROGRAM_ID = 0x0004003000009802; + } + break; + + case nn::cfg::CFG_REGION_JAPAN: + { + MMEN_PROGRAM_ID = 0x0004003000008202; + } + break; + } + + nn::am::ProgramInfo outInfos; + result = nn::am::GetProgramInfos(&outInfos, nn::fs::MEDIA_TYPE_NAND, &MMEN_PROGRAM_ID, 1); + if (result.IsSuccess()) + { + result = ExecuteCup(s_scrollBuffer); + // CUP不要だがNUPバージョンのほうが新しかったら強制的に実行 + if (result == nn::cup::CTR::ResultUpdateNotRequired()) + { + // バージョンの取得 + VerDef versionData; + GetSystemVersion(&versionData, region); + + const size_t ROMFS_BUFFER_SIZE = 1024 * 32; + u8 buffer[ROMFS_BUFFER_SIZE]; + result = nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE); + if (result.IsSuccess()) + { + nn::fs::FileReader fileReader; + result = fileReader.TryInitialize("rom:/nup_version.bin"); + if (result.IsSuccess()) + { + u8 buf[1024]; + s32 readSize; + result = fileReader.TryRead(&readSize, buf, sizeof(buf)); + if (result.IsSuccess()) + { + if (versionData.nup.majorVersion < *reinterpret_cast(buf)) + { + // CUPバージョンを削除 + result = nn::am::DeleteProgram(nn::fs::MEDIA_TYPE_NAND, cCupVerId[region]); + if (result.IsSuccess()) + { + result = ExecuteCup(s_scrollBuffer); + } + } + } + } + } + } + } + else if (result == nn::am::ResultNotFound()) + { + s_scrollBuffer->AppendText("Cannot find Home Menu"); + } + + 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/1stNUP_7/CardCup/romfiles/nup_version.bin b/branches/1stNUP_7/CardCup/romfiles/nup_version.bin new file mode 100644 index 0000000..45a8ca0 --- /dev/null +++ b/branches/1stNUP_7/CardCup/romfiles/nup_version.bin @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/branches/1stNUP_7/CardCup/scrollBuffer.cpp b/branches/1stNUP_7/CardCup/scrollBuffer.cpp new file mode 100644 index 0000000..54de11e --- /dev/null +++ b/branches/1stNUP_7/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/1stNUP_7/CardCup/scrollBuffer.h b/branches/1stNUP_7/CardCup/scrollBuffer.h new file mode 100644 index 0000000..1d3563a --- /dev/null +++ b/branches/1stNUP_7/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(); // キー入力を参照して、スクロールする + ScrollBuffer *AppendText(const char *fmt, ...); // 文字列を追加する + ScrollBuffer *ReplaceText(const char *fmt, ...); // 最新の文字列を置換する + void Render(); // レンダリング +}; + +#endif // SCROLL_BUFFER_H diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/Imp.rsf b/branches/1stNUP_7/CardSaveData/Mover/Imp/Imp.rsf new file mode 100644 index 0000000..a5ba6f1 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/Imp.rsf @@ -0,0 +1,18 @@ +BasicInfo: + Title : $(TITLE) + BackupMemoryType: None + Logo : Nintendo +# Companycode: "00" + ProductCode : "CTR-P-22MA" +# MediaSize: 2GB + +AccessControlInfo: + FileSystemAccess: + - Debug + +Rom: + HostRoot : $(ROMFS_ROOT) + +TitleInfo: + UniqueId: 0xf8015 + Version: 0 diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/OMakefile b/branches/1stNUP_7/CardSaveData/Mover/Imp/OMakefile new file mode 100644 index 0000000..b16c825 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/OMakefile @@ -0,0 +1,69 @@ +#!/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 + ../../common/test_data.cpp + ../../common/shfnt.cpp + ../../common/sleep.cpp + ../../common/common.cpp + +OBJECTS[] = + $`(ObjectFromBinary $(TARGET), ./Imp_list/key/Public_Key.der) + +TARGET_PROGRAM = CtrSaveDataMover_imp + +TITLE = CSM_imp + +LIBS += libnn_ps + +IMPORTEE_CIA = importee.cia + +SRC_IMPORTEE_PATH = ../body/images/$(BUILD_TARGET_DIR)/$(BUILD_TYPE_DIR)/CtrSaveDataMover.cia +#とりあえず、マスタリング時は直おき、配置時に改名 +#SRC_IMPORTEE_PATH = CtrSaveDataMover_master.cia + +# ビルドタイプ別に romfs を作る +#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) + +# プログラムから参照するためのROMFSのパスとプログラムIDを定義する +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 +CTR_BANNER_SPEC = banner_null_icon.bsf + +include $(ROOT_OMAKE)/modulerules + +build: $(DEFAULT_TARGETS) + \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/banner.bsf b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner.bsf new file mode 100644 index 0000000..a18d99e Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner.bsf differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/BannerModel_imp/COMMON/COMMON.cmdl b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/BannerModel_imp/COMMON/COMMON.cmdl new file mode 100644 index 0000000..3e85377 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/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/1stNUP_7/CardSaveData/Mover/Imp/banner/BannerModel_imp/COMMON/Textures/banner_imp.ctex b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/BannerModel_imp/COMMON/Textures/banner_imp.ctex new file mode 100644 index 0000000..83e936f --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/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/1stNUP_7/CardSaveData/Mover/Imp/banner/banner_dummy.bcwav b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/banner_dummy.bcwav new file mode 100644 index 0000000..d579907 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/banner_dummy.bcwav differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/banner_imp.cbmd b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/banner_imp.cbmd new file mode 100644 index 0000000..e64d183 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/banner_imp.cbmd differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/icon2_24.ctpk b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/icon2_24.ctpk new file mode 100644 index 0000000..a96f378 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/icon2_24.ctpk differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/icon2_48.ctpk b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/icon2_48.ctpk new file mode 100644 index 0000000..550e559 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner/icon2_48.ctpk differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/banner_null_icon.bsf b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner_null_icon.bsf new file mode 100644 index 0000000..ef62f22 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/Imp/banner_null_icon.bsf differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/csm_list.txt b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/csm_list.txt new file mode 100644 index 0000000..5f9944f --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/csm_list.txt @@ -0,0 +1,3 @@ +# +EJF10000237 +EJF10000308 diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/csm_sign.dat b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/csm_sign.dat new file mode 100644 index 0000000..65d55eb Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/csm_sign.dat differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/makekey.bat b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/makekey.bat new file mode 100644 index 0000000..813beb0 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/makekey.bat @@ -0,0 +1,4 @@ +openssl genrsa -out private_key.pem 2048 +openssl enc -d -base64 -in private_key.pem -out private_key.der +openssl rsa -pubout -inform DER -outform DER -in private_key.der -out public_key.der + diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/makekey_100.bat b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/makekey_100.bat new file mode 100644 index 0000000..0524431 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/makekey_100.bat @@ -0,0 +1,3 @@ +rem ver1.0.0p +openssl genpkey -out private_key.der -outform DER -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 +openssl rsa -pubout -inform DER -outform DER -in private_key.der -out public_key.der diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/makesign.bat b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/makesign.bat new file mode 100644 index 0000000..1d87ba0 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/batch/makesign.bat @@ -0,0 +1,7 @@ +@echo off +if "%1"=="" goto 1 +openssl dgst -sha256 -binary -keyform DER -sign ../key/private_key.der -out csm_sign.dat %1 +goto end +:1 +openssl dgst -sha256 -binary -keyform DER -sign ../key/private_key.der -out csm_sign.dat csm_list.txt +:end diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/caution.txt b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/caution.txt new file mode 100644 index 0000000..496953d --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/caution.txt @@ -0,0 +1,5 @@ +閧̈͒ +쐬Kv̖ɂ͏oȂ + +쐬́AzzŎgpo[WɓĂ +ƃyA̔閧g diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/digit.txt b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/digit.txt new file mode 100644 index 0000000..6691db8 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/digit.txt @@ -0,0 +1,45 @@ + +{̈̃VAŌ̎lpgɓ +digitƂ̂炵 +Xg쐬ɓ͈Ⴂ`FbN̂Ɏg +R}hCŃt@Cw肷ȒPȃ`FbJ[Ƃ + + +ȉAJ삳񃁁[ +---------------- +`FbNfWbǧvZ@͈ʓIȂ̂炵A +"WX10 EFCg3E1iM10W31j"Ƃ̂炵łB + + +// NULLI[ꂽVAio[󂯎 +// NULL̏ꏊɃ`FbNfWbgtĐVNULLI[ +void 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/1stNUP_7/CardSaveData/Mover/Imp/imp_list/import.txt b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/import.txt new file mode 100644 index 0000000..e94a4f3 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/import.txt @@ -0,0 +1,27 @@ + +ړIF‚{̂̂݃C|[g + +JROMǂݍ + +SCj@c[p{̂̃VA[ȂǂRED֘A +RED)@Xg(csm_list)Ə(csm_sign)쐬 + + +C|[g菇 +E@XgASDCTRɍ +E@C|[gpAvJ[hN +E@LȖ{̂ȂC|[gj[\ + + +Openeelō쐬 +ɎSD[gɒu + +Xg̏ +C|[gƒVAeLXgŗ +--- +aaaaaaaa +bbbbbbbb +---- +{̗VAI[digit(lpg̐)͏Ȃ +digitmFꍇ̓Xg쐬ɂƂ +t@CTCY64K܂(VÂ݋LڂŁA悻4000) diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/key/public_key.der b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/key/public_key.der new file mode 100644 index 0000000..1fa5839 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/Imp/imp_list/key/public_key.der differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/romfiles/nnfont_RectDrawerShader.shbin b/branches/1stNUP_7/CardSaveData/Mover/Imp/romfiles/nnfont_RectDrawerShader.shbin new file mode 100644 index 0000000..4290c2c Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/Imp/romfiles/nnfont_RectDrawerShader.shbin differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/Imp/source/main.cpp b/branches/1stNUP_7/CardSaveData/Mover/Imp/source/main.cpp new file mode 100644 index 0000000..32e77e2 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/Imp/source/main.cpp @@ -0,0 +1,490 @@ +/*---------------------------------------------------------------------------* + 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 +#include "demo.h" +#include "../../body/ver.h" +#include "../../../common/sleep.h" +#include "../../../common/common.h" +#include "../../../common/shfnt.h" +#include "../../../common/test_data.h" + +#define INF_FILE "sdmc:/csm_inf.txt" + +#define KEY_LENGTH 2048 +#define LIST_FILE "sdmc:/csm_list.txt" +#define SIGN_FILE "sdmc:/csm_sign.dat" + + +extern "C" { + extern u8* PUBLIC_KEY_BEGIN[]; + extern u8* PUBLIC_KEY_END[]; + + const void* PUBLIC_KEY = PUBLIC_KEY_BEGIN; +} + +demo::RenderSystemDrawing s_RenderSystem; +nn::fnd::ExpHeap appHeap; +uptr heapForGx; +void ErrorStop(char *s); +void ErrorPOff(char *s); + +const size_t ROMFS_BUFFER_SIZE = 64*1024;//ROMマウント用 +const size_t READ_BUFFER_SIZE = 64*1024; + +#define SDK_SER_LEN nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN + +namespace +{ + u8* readBuf; + u8* romfsBuf; + +} +nn::Result result; + + +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, READ_BUFFER_SIZE)) + { + stream->Write(readBuf, read); + } + result = nn::am::EndImportProgram(stream); + } + return result.IsSuccess(); +} + +#define LIST_MAX 4000 +#define LIST_LENGTH (LIST_MAX * (nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1)) +u8 s_list[LIST_MAX][nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1];//シリアルリスト +u8 sign[256];//署名 +u8 serialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1]; + +//本体シリアル取得 +int GettedSerLen; +bool GetSerial(){ + nn::cfg::CTR::init::Initialize(); + nn::cfg::CTR::system::Initialize(); + result = nn::cfg::CTR::system::GetSerialNo(serialNo); + nn::cfg::CTR::system::Finalize(); + nn::cfg::CTR::init::Finalize(); + serialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN] = 0; + GettedSerLen = strlen((char*)serialNo); + 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);} +//上はASCIIのみ対応したTextWriterへのラッパ +//日本語表示の場合、WideTextWriterを使う(要sft_側の関数追加) + + +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(); + int i = nn::ndm::GetDaemonStatus( nn::ndm::DN_CEC ); + if (i !=3 )NN_LOG("DN_CEC %d\n",i); + i = nn::ndm::GetDaemonStatus( nn::ndm::DN_BOSS ); + if (i !=3 )NN_LOG("DN_BOSS %d\n",i); + i = nn::ndm::GetDaemonStatus( nn::ndm::DN_NIM ); + if (i !=3 )NN_LOG("DN_NIM %d\n",i); + i = nn::ndm::GetDaemonStatus( nn::ndm::DN_FRIENDS ); + if (i !=3 )NN_LOG("DN_FRIENDS %d\n",i); + } +} + +//終了 +void endfunc() +{ + appHeap.Free(reinterpret_cast(readBuf)); + appHeap.Free(reinterpret_cast(romfsBuf)); + nn::hid::Finalize(); + SharedFontFinalize(); + nngxWaitVSync(NN_GX_DISPLAY_BOTH);//SDK2.0以降では不要? + s_RenderSystem.Finalize(); +} + +//署名検証 +bool VeriRsa(u8* src,size_t sz,u8* sig) +{ + nn::crypto::RsaKey key; + //nn::crypto::Initialize(); + nn::ps::CTR::Initialize(); + result = key.InitializePublicKey(PUBLIC_KEY_BEGIN,KEY_LENGTH); + if (result.IsSuccess()) + { + result = nn::ps::CTR::VerifyRsaSha256(src,sz,sig,key); + } + //nn::crypto::Finalize(); + nn::ps::CTR::Finalize(); + return result.IsSuccess(); +} + +//エラー +void ErrorCommon(char *s,char *ss) +{ + char str[128]; + nn::am::FinalizeForLocalImporter(); + nn::fs::Unmount("sdmc:"); + nn::fs::Unmount("rom:"); + NN_LOG(s); + NN_LOG(" result = %d\n",result.GetDescription()); + shf_SetScale(0.7,0.7); + setColor(1.0, 0.0, 0.0,1.0); + strcpy(str,"Error: "); + strcat(str,s); + drawText(10,100,str); + drawText(10,140,ss); +} + + +void ErrorStop(char *s) +{ + ErrorCommon(s,"Push Home Button & end"); + s_RenderSystem.SwapBuffers(); + WaitKey(0); +} + +void ErrorPoff(char *s) +{ + ErrorCommon(s,"Push Power Button & Power Off"); + drawText(10,160,"Home Button is invalid"); + s_RenderSystem.SwapBuffers(); + WaitKey(0); +} + + +//改行後の位置を返す、0=見つからなかった +int CrLf(int n,int max) +{ + u8 d; + while(n < max) + { + d = readBuf[n]; + if (d==0x0a)return n+1;//LF + if (d==0x0d)//CR + { + if (n == max-1)return 0;//終端 + n++; + if (readBuf[n]==0x0a)return n+1;//CR+LF + ErrorStop("list broken");//CRのみは異常、署名時にファイル壊れてた? + } + n++; + } + return 0; +} + + +nn::fs::FileInputStream fi; +//ファイルリード +s32 FileRead(char* fname) +{ + s32 size; + result = fi.TryInitialize(fname); + if (result.IsFailure()){//open error + //NN_LOG("desc= %d\n",result.GetDescription()); + return 0; + } + result = fi.TryRead(&size,readBuf,READ_BUFFER_SIZE); + fi.Finalize(); + if (result.IsFailure()){ + //NN_LOG("desc= %d\n",result.GetDescription()); + return 0; + } + return size; +} + + +char ver[16]; +char seri[32]; +void nnMain( void ) +{ + //nn::Result result; + bool flg_applove=false; + bool flg_test=false; + int i,j,n; + s32 fsize; + extern bool prohibitHome;// HOME ボタン禁止 + + nn::os::Initialize(); + nn::fs::Initialize(); + + //DEA-SUPにて推奨のフリーズ暫定対策:無線デーモンを停止 (2011.3.1 現在) + //ただし、スリープ時の"いつのまに通信"は止まらない + //無線は使わないので本体横スイッチ切っとくのが確実 + nn::ndm::Initialize(); + result = nn::ndm::SuspendScheduler(); + NN_LOG("%d",result.GetDescription()); + + //中断処理の準備 + InitSysBreak((uptr)endfunc); + // グラフィックスライブラリの初期化は、以降で行わなければならない + // 他、アプリケーションの初期化処理 + + nn::hid::Initialize(); + nn::hid::PadReader padReader; + hpr = &padReader; + + //result = nn::ns::CTR::InitializeForShell(); + //if (result.IsSuccess()) + result = nn::am::InitializeForLocalImporter(); + + nn::applet::DisableSleep();//スリープ非対応 + + // ヒープの確保 + appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + const u32 s_GxHeapSize = 0x800000; + // RenderSystem の準備 + heapForGx = reinterpret_cast(appHeap.Allocate(s_GxHeapSize)); + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + SharedFontInit(); + + // 共有フォントの種類を取得 + //nn::pl::SharedFontType sftype = nn::pl::GetSharedFontType(); + + // スリープ要求に対する返答を有効にする + // また、蓋の状態チェックを行い蓋が閉じられているならスリープ要求が発生する +// 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())ErrorStop("Initialize");//初期化に失敗 + if (READ_BUFFER_SIZE < LIST_LENGTH)ErrorStop("buffer size");//バッファサイズのチェック + + //ファイルバッファ + //カゲマイ上のSDリード速度比較実験で32アラインが良かったので、おまじない + //回数もサイズも少ないので気にする必要ないかも + if (READ_BUFFER_SIZE > appHeap.GetTotalFreeSize())ErrorStop("memory alloc"); + readBuf = reinterpret_cast(appHeap.Allocate(READ_BUFFER_SIZE,32)); + if (ROMFS_BUFFER_SIZE > appHeap.GetTotalFreeSize())ErrorStop("memory alloc"); + romfsBuf = reinterpret_cast(appHeap.Allocate(ROMFS_BUFFER_SIZE,32)); + + + //シリアルチェック + if( GetSerial() == false)ErrorStop("Get Serial");//本体シリの取得に失敗 + + result = nn::fs::MountSdmc();//ダイレクトでマウント..マスタリング時にワーニング + if (result.IsFailure())ErrorStop("Mount SD"); + fsize = FileRead(INF_FILE);//設定ファイルがあるか + if((fsize < 1024) && (fsize > 0))//サイズチェック,増えても1Kは超えない + {//不具合調査時に状況にあわせて現場で作成&変更を想定したオプション + //通常は不要なので無しでも動くようしとく + n = 0; + while(n < fsize) + { + if (readBuf[n] == '-'){ + if (n == fsize-1)break;//終端 + n++; + switch (readBuf[n]){ + case 'p':// -p .. 本体シリアル表示 + strcpy(seri,"s/n: "); + strcat(seri,(char *)serialNo); + shf_SetScale(0.5,0.5); + drawText(10,40,(char*)seri); + shf_SetScale(0.7,0.7); + break; + case 't':// -t .. テストメニュー有効 + flg_test = true; + break; + } + } + n++; + } + } + + //シリアル表示(オプション)後にチェック + //デバッガ=15,実機=11 + if (GettedSerLen < 11)ErrorStop("invalid Serial"); + + fsize = FileRead(SIGN_FILE);//署名リード + if(fsize != 256)ErrorStop("sign file");//鍵のbit長は2046固定 + memcpy(sign,readBuf,256);//readBuf -> sign + fsize = FileRead(LIST_FILE);//リストリード + if((fsize > LIST_LENGTH ) || (fsize == 0))ErrorStop("list file"); + + nn::fs::Unmount("sdmc:"); //検証後はSDから読まないでメモリバッファ上のデータを使う: 差替え対策 + if (VeriRsa(readBuf,fsize,sign) == false)ErrorStop("sign verify"); + + //署名検証OK + int list_ct = 0; + n=0; + while(n < fsize)//リスト作成 + { + if (readBuf[n] == '#')//コメント行を無視、ワイド文字非対応 + { + i = CrLf(n,fsize);//コメントの次行 + if (i == 0)break;//ファイル終わりまで改行が見つからない + }else + { + //改行さがし + if ((fsize-n) > (SDK_SER_LEN+2)) + {//シリアルは改行つける + i = CrLf(n,n+SDK_SER_LEN+2); + if (i == 0)ErrorStop("list broken");//改行が見つからない + }else{ + i = CrLf(n,fsize); + if (i ==0)i = fsize;//改行以外でファイル終 + } + if ((i-n) > GettedSerLen)//シリアルをリスト化 + { + j = 0; + while(n=LIST_MAX)ErrorStop("List too Long"); + } + } + if ((fsize-i) < GettedSerLen)break;//ファイル終 + n=i;//ポインタを改行の次へ + } + + //プログラムミス、コードバグ対策 + //値が小さいと判定が緩くなるが、動作確認時にスルーしそうなので + //念の為チェック + if (GettedSerLen < 11)ErrorStop("invalid Serial"); + + //本体シリアルがリストにあるかチェック + n =0; + while(n exsave ύX +SOURCES[] = + ./source/main.cpp + ./source/screen/screen.cpp + ../../common/savefile/savedata.cpp + ../../common/savefile/membak.cpp + ../../common/savefile/savefile.cpp + ../../common/gui/gui.cpp + ../../common/shfnt.cpp + ../../common/sleep.cpp + ../../common/common.cpp + +#LIBS += lib_demo libnn_am +#LIBS += libnn_ps + +TARGET_PROGRAM = CtrSaveDataMover + +TITLE = CSM_body + +# ROMFS ̃[gpXw肵܂B +#ROMFS_ROOT = + +# Ǝ RSF t@Cw肷ꍇ +ROM_SPEC_FILE = body.rsf +DESCRIPTOR = $(CTRSDK_ROOT)/resources/specfiles/repairtool.desc + +# oi[AACR +CTR_BANNER_SPEC = banner_null_icon.bsf + + +#Cia o[W:}X^OɍXV邱 +#W[rsfŎw(Remasterversion) +MAKECIAFLAGS = -minor 0 -micro 12 + +include $(ROOT_OMAKE)/modulerules + +build: $(DEFAULT_TARGETS) diff --git a/branches/1stNUP_7/CardSaveData/Mover/body/banner.bsf b/branches/1stNUP_7/CardSaveData/Mover/body/banner.bsf new file mode 100644 index 0000000..516f44d Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/body/banner.bsf differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/body/banner/BannerModel_test/COMMON/COMMON.cmdl b/branches/1stNUP_7/CardSaveData/Mover/body/banner/BannerModel_test/COMMON/COMMON.cmdl new file mode 100644 index 0000000..63f2c7a --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/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/1stNUP_7/CardSaveData/Mover/body/banner/BannerModel_test/COMMON/Textures/banner.ctex b/branches/1stNUP_7/CardSaveData/Mover/body/banner/BannerModel_test/COMMON/Textures/banner.ctex new file mode 100644 index 0000000..c36b19c --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/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/1stNUP_7/CardSaveData/Mover/body/banner/banner.cbmd b/branches/1stNUP_7/CardSaveData/Mover/body/banner/banner.cbmd new file mode 100644 index 0000000..2364568 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/body/banner/banner.cbmd differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/body/banner/banner_dummy.bcwav b/branches/1stNUP_7/CardSaveData/Mover/body/banner/banner_dummy.bcwav new file mode 100644 index 0000000..d579907 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/body/banner/banner_dummy.bcwav differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/body/banner/icon_24.ctpk b/branches/1stNUP_7/CardSaveData/Mover/body/banner/icon_24.ctpk new file mode 100644 index 0000000..cc54fe7 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/body/banner/icon_24.ctpk @@ -0,0 +1 @@ +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMUUMMMMMMMMMMMMMUUUMUUUU]]]U]]]]eemMMMUUUU]UU]]]eee]]]eemm nemm v v,v,v-~]eeeemm ve n n v v,~-~M v,~,~-~-~NNoM~NNoop n,v,v-~-~NNo-~NNooppnopӦҦӮӮopӦӦӦԮӦԮ7778XYφMUUUU]]]U]]e]eem]eej]mkeK*!m2 vk+;-~LmNeeemm v v,vm v v,~,v-~-~N v!-~K moK*.uNoS: v-~!dM}K*!NnuopkNdl2oL2ktrҍk.Kl2kpO}nKtd CtӦԮ KB:kB.KB|77cXyӦ|k7m:!kXkY7XXYYzzzYzzכߛߛm:[kV:WJOSzzߛtxߛ,~-~M~NNooNooӦӦӮӮҦӮӮӮԮ77X77XXYyzԮ77X77XXYYz8YYyyzzߛzךߚߛXYyzzכߛߛzߛߛߜߜ \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/Mover/body/banner/icon_48.ctpk b/branches/1stNUP_7/CardSaveData/Mover/body/banner/icon_48.ctpk new file mode 100644 index 0000000..24fd5a8 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/body/banner/icon_48.ctpk @@ -0,0 +1,2 @@ +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMUUMUUUUUUUMMMMMMMUMUUUUUUUUUUUUUU]UUU]]]]]UUUUUU]]U]]]]]]]]]]]]eee]eeeeeem]]]]]]ee]]eeeeemeeeeemm nmmm n n n v veeemmmm nmmm 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-~NNNNooo,~-~-~M~M~NNNMNNNNoooNooooppopNNooooopoppӦӦӦӮӦӦӮӮӮԮԮMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMUMMMMMMMMMMMMMMMUMMMUUUUUUUUUUUUUMMMMMUUUMUUUUUUUUUUUU]]]U]]]]]]]UUUUU]]]U]]]]]]e]]]eeeeeeeeeemmm]]]]]eee]eeeeeemeeemmm n nmmm n n v v,veemmmm n vm n n v v v v,v n v v,v,v,~,~-~ v,~,~-~-~M~MN n v v v v,v,v-~ v,~,~-~-~-~-~N-~-~-~NMNNoNNNONoop-~M~M~NNNNoNNNoooopOoopppnoooopopӦӦӮҦҦӦӮӮҦӦӦӮӮӮӦӦӮӮԮԮӮԮ777777777778X78XXXYYy׆MMMUUUUUUUUUUUU]UUU]]]]]]]]]]]]eUUU]]]]]]]]]]eee]]]eeeeeeeememmm]]]eeeeeeeeeemmTemmm +n n n+e+]2kkkk2Kemm ne! Lk n n v v2k2kkKT+;,~,~-~-~-~d-~u-~-~NNN v vm,v,v-~-~-~kk+;K*l\N e~-~MMNNNnumm *!kkkKK-~NNNN\OdNoooo/pkKkBp!k} *:P}kkoooppkS *NdӦl2kkktӮ CӦ:rӦ2Ӯkkk!kk|knSk0dk.Km:kӦӦӮԮӮԮt *kBkB777kckնS * 2kck 2!k7XXXBkBkXYYy7777XXX7XXXXYYyXYYyYyzzyzzzzߚzߛXYYyyzzzyzzzzߚߛߛzzߚߛߛߛߛ]eeeeeemeeemmm n nemm n n v v v n v v v v,v,v-~mmm n n v v v n v v v v,~,~-~ v,v,~-~-~-~-~M-~-~-~NNNNo v,v,v,~2kCk-~-~-~M ekN: eNm\NNooo *k *opd/uNNNNNoonoopopLCkpkkNd\oppt\ul *r ColӦԮq/dkk\p\SӦӮӦӦӮӮԮԮkkҕplkk0d2k: *kl2kk *0l0lk0lkttkukkk7m:7Dz|!󝵮Pl7u677777XkԝԝXϗXYXXXYYyyz[.S!k6,2Ykkkky׷zא[krtkzr|kr|kk:zzzߚzzzߚߚߛߛߛr|k:Uμzߛߛߛ,v,~,~-~-~M~M~N-~M~M~NNNNoNNNoOoopoooppNNNoooopoooppӦpӦӦӮӦӦӮӮӦӦӮӮԮӦӮӮԮԮԮӮԮ777777788X77777778XX7XXXXYYyXYYyyzzz788XXXXYXYYYYyyzYyyzzzzߛzzzߛߛߛYyzzzߚߚߛzߚߚߛߛߛߛߛߛpҦҦӦӦӦӮӮԮӦӮӮԮԮӦӦӮӮӮԮԮ67Ԯ77777877788XXX7777X777XXXXY8XXYYYyyYYyyyzzߚ7XXXXYYyXYyyyzzzyzzzzߚߛߛzߛߛߛߛߛyzzzzߛߛߛzߛߛߛߛ \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/Mover/body/banner_null_icon.bsf b/branches/1stNUP_7/CardSaveData/Mover/body/banner_null_icon.bsf new file mode 100644 index 0000000..9b21bc2 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/body/banner_null_icon.bsf differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/body/body.rsf b/branches/1stNUP_7/CardSaveData/Mover/body/body.rsf new file mode 100644 index 0000000..ffe9238 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/body/body.rsf @@ -0,0 +1,29 @@ +# AvP[ṼftHgl +BasicInfo: + # vÕ^Cgw肵܂B + Title : $(TITLE) +# BackupMemoryType: 128KB + BackupMemoryType: None + Logo : Nintendo +# CompanyCode: "00" + 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/1stNUP_7/CardSaveData/Mover/body/romfiles/nnfont_RectDrawerShader.shbin b/branches/1stNUP_7/CardSaveData/Mover/body/romfiles/nnfont_RectDrawerShader.shbin new file mode 100644 index 0000000..4290c2c Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/Mover/body/romfiles/nnfont_RectDrawerShader.shbin differ diff --git a/branches/1stNUP_7/CardSaveData/Mover/body/source/main.cpp b/branches/1stNUP_7/CardSaveData/Mover/body/source/main.cpp new file mode 100644 index 0000000..7da7521 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/body/source/main.cpp @@ -0,0 +1,966 @@ +/*---------------------------------------------------------------------------* + 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 +//#include +#include "../../../common/savefile/savefile.h" +#include "../../../common/savefile/savedata.h" +#include "../../../common/savefile/membak.h" +#include "./screen/screen.h" +#include "../../../common/common.h" + +nn::fnd::ExpHeap appHeap; +uptr heapForGx; +//Gui gui; +myResult errRes; + + +//char strBuff[128]; +//bool exist; + +SaveData savedata; +nn::os::LightEvent ejectEvnt(false); +nn::os::LightEvent insEvnt(false); +MemBak exsave; + +//バックアップの状態 +bool Active,Formatted; +bool exActive,exFormatted; +tArcInfo arcInfo,arcInfo_ex;//アーカイブ情報 + +//プロダクトコードの一致 +bool isAgreePCode; +//ベリファイ結果 +//bool failveri; + +//Top画面エラー表示 +int tmerr; + +//結果 +typedef enum { + SUCCESS + ,ERROR + ,CANCEL + ,INSEXIT +}RetCode; + +//挿抜イベント時に設定 +typedef enum { + InEx_None + ,InEx_InsCard + ,InEx_EjcCard +}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(); + + savedata.Finalize(); + exsave.Finalize(); + + ScrFinalize(); + +} + +//エラー停止 +void failstop() +{ + NN_LOG("fail %d,stop\n",errRes); + finish(); +} + +char sts[64]; +void PutError(ErcDev dev,int cd) +{ + nn::Result res; + switch (dev) + { + case ERC_DEV_CARD: res = savedata.LastNnResult;break; + case ERC_DEV_OUT: res = exsave.LastNnResult;break; + } + GetErrorStr(dev,res,cd,sts); + scr_Status(sts,COLOR_RED); +} + + +//-------------------------------------------------- Verifi +wchar_t file_pathw[MAX_PATH_LENGTH]; +char file_path[MAX_PATH_LENGTH]; +//ドライバの仕様で速度的に4バイトアラインした方がいい(SDK 0.14.23 時点) +char fileBuffer[512] NN_ATTRIBUTE_ALIGN(4);//検証が512単位なので +char fileBuffer_ex[512] NN_ATTRIBUTE_ALIGN(4); +#define FILEBUFF_SIZE sizeof(fileBuffer) + +bool Verifi() +{ + myResult res; + int ct,i,msize,rsize; + s64 total=0; + + //セーブデータのマウント + res = savedata.Mount(); + if(res != RESULT_OK){ + PutError(ERC_DEV_CARD); + return false; + } + +//ファイル数の再取得..ファイル多いと時間かかる +//arcInfoの保持があやしい or 出来ない場合に有効にする +/* + scr_Status("Ready to Verifi",COLOR_YELLO); + //情報ファイル + LogAdd("Directry Info"); + if(savedata.GetInfo(&arcInfo)==false) + { + savedata.Unmount(); + PutError(ERC_DEV_CARD); + return ERROR; + } +*/ + + //出力デバイスのマウント + res = exsave.Mount(); + if(res != RESULT_OK){ + PutError(ERC_DEV_OUT); + return false; + } + + //情報ファイル + if (exsave.GetInfo(&arcInfo_ex) == false) + { + savedata.Unmount(); + exsave.Unmount(); + return false; + }//todo:将来、構造体を変更したらバージョンチェック入れる + + //フォーマット情報の比較 + if ((arcInfo.DirEntry != arcInfo_ex.DirEntry) || + (arcInfo.FileEntry != arcInfo_ex.FileEntry) || + (arcInfo.Dup != arcInfo_ex.Dup)) + { + PutError(ERC_DEV_OUT,ERC_VERIFI); + savedata.Unmount(); + exsave.Unmount(); + return false; + } + + ct =0; + if (arcInfo.FileCount == 0)//ファイルが無い + { + savedata.Unmount(); + exsave.Unmount(); + return true;//フォーマット一致のみ + }else{ + 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) + { + if (res == RESULT_DIR_LEVEL_OVER){ + break; + } + if (res == RESULT_PATH_LENGTH_OVER){ + break; + } + res = RESULT_FAIL_OPEN; + break; + } + if (file_pathw[0] == 0)break;//root then end + if (ct>=arcInfo.FileCount) + {//カウンタ壊れ、メモリフローの可能性 + res = RESULT_FAIL; + break; + } + scr_CountPerMax(ct,arcInfo.FileCount); + if (savedata.Open(file_pathw)==false) + { + res = RESULT_FAIL_OPEN; + break; + } + fsize = savedata.FileSize; + total += fsize; + if (exsave.Open(file_pathw)==false) + { + res = RESULT_FAIL_OPENW; + //savedata.Close(); + break; + } + if (fsize != exsave.FileSize)//file size + { + res = RESULT_FAIL; + break; + } + msize=fsize; + if(msize <= FILEBUFF_SIZE ){//一回で読めるサイズならゲージは出さない + scr_CountPerMax2(0,0,-1); + } + while(fsize) + { + if(msize > FILEBUFF_SIZE ){ + scr_CountPerMax2(msize-fsize,msize,0); + } + if (fsize > FILEBUFF_SIZE) + { + rsize = FILEBUFF_SIZE; + fsize -= FILEBUFF_SIZE; + }else{ + rsize = fsize; + fsize = 0; + } + if(savedata.Read(fileBuffer,rsize) != rsize ) + { + //中身のデータが作成サイズに満たない場合に検証エラーとなる対策 + //読めないブロックは置き換える + //検証は512単位でされるので読めてるとこまで置き換えないよう + //リードサイズは512にしておく + if(nn::fs::ResultVerificationFailed::Includes(savedata.LastNnResult)) + { + for (i = 0; i < rsize; i++) + { + fileBuffer[i] = 0;//0埋め + } + }else{ + res = RESULT_FAIL_READ; + break; + } + } + if(exsave.Read(fileBuffer_ex,rsize) != rsize ) + { + res = RESULT_FAIL; + break; + } + } + savedata.Close(); + exsave.Close(); + if (res != RESULT_OK)break; + //verifi + for (i = 0;i MEM_BKUP_SIZE) + { + savedata.Unmount(); + PutError(ERC_DEV_OUT,ERC_WRITE_NS);//容量オーバ + return ERROR; + } + //カウント異常なら実行エラー + if (arcInfo.FileCount > arcInfo.FileEntry) + { + savedata.Unmount(); + PutError(ERC_DEV_OTHER,ERC_EXEC); + return ERROR; + } + + scr_Status("BackUp Check",COLOR_YELLO); + if(exsave.IsExist()){ + if(exsave.Delete()==false) + { + savedata.Unmount(); + PutError(ERC_DEV_OUT); + return ERROR; + } + } + + scr_Status("Create Backup",COLOR_YELLO); + res = exsave.Create(arcInfo.DirEntry+1,arcInfo.FileEntry+1); + if (res != RESULT_OK){ + savedata.Unmount(); + PutError(ERC_DEV_OUT); + return ERROR; + } + + if (arcInfo.FileCount == 0)//ファイルが無い + { + scr_Status("no files",COLOR_YELLO); + savedata.Unmount(); + exsave.Unmount(); + return SUCCESS;//フォーマットのみ + }else{ + scr_Status("file reading",COLOR_SKY); + savedata.ResetPath(); + s64 fsize; + res = RESULT_OK; + while(res==RESULT_OK){ + res = savedata.GetPath(file_pathw); + if (res != RESULT_OK) + { + if (res == RESULT_DIR_LEVEL_OVER){ + PutError(ERC_DEV_CARD,ERC_DIRDEPTH); + break; + } + if (res == RESULT_PATH_LENGTH_OVER){ + PutError(ERC_DEV_CARD,ERC_PATH); + break; + } + res = RESULT_FAIL_OPEN; + break; + } + if (file_pathw[0] == 0)break;//root then end + if (ct>=arcInfo.FileCount) + {//カウンタ壊れ、メモリフローの可能性 + res = RESULT_FAIL; + break; + } + + scr_CountPerMax(ct,arcInfo.FileCount); + if (savedata.Open(file_pathw)==false) + { + res = RESULT_FAIL_OPEN; + break; + } + fsize = savedata.FileSize; + total += fsize; + if (exsave.OpenW(file_pathw,fsize)==false) + { + res = RESULT_FAIL_OPENW; + //savedata.Close(); + break; + } + + msize=fsize; + while(fsize) + { + if(msize > FILEBUFF_SIZE * 2){ + scr_CountPerMax2(msize-fsize,msize,0); + } + if (fsize>FILEBUFF_SIZE) + { + rsize = FILEBUFF_SIZE; + fsize -= FILEBUFF_SIZE; + }else{ + rsize = fsize; + fsize = 0; + } + if(savedata.Read(fileBuffer,rsize) != rsize ) + { + //中身のデータが作成サイズに満たない場合に検証エラーとなる対策 + //読めないブロックは置き換える + //検証は512単位でされるので読めてるとこまで置き換えないよう + //リードサイズは512にしておく + if(nn::fs::ResultVerificationFailed::Includes(savedata.LastNnResult)) + { + for (int i = 0; i < rsize; i++) + { + fileBuffer[i] = 0;//0埋め + } + }else{ + res = RESULT_FAIL_READ; + break; + } + } + if(exsave.Write(fileBuffer,rsize) != rsize ) + { + res = RESULT_FAIL_WRITE; + break; + } + } + savedata.Close(); + exsave.CloseW(); + //todo: ゲージ表示 + ct++; + } + savedata.Close(); + exsave.CloseW(); + } + + if (res == RESULT_OK){ + if (ct != arcInfo.FileCount)//ファイル数に満たないパス検索終了 + {//ディレクトリ情報かパス取得で失敗してると思われる + PutError(ERC_DEV_OTHER,ERC_EXEC); + return ERROR; + } + //フォーマット情報を記録 + //Exsaveに2重化が無いので情報取得APIでは不足 - 2011.1 現在 + //プロダクトコードを追加(2011.1.26) + //バージョンを追加(2011.1.27) + if (exsave.OpenSysW()) + { + strcpy(arcInfo.Pcode,savedata.PrdCode); + if(exsave.WriteSys(&arcInfo) ==false) + { + res = RESULT_FAIL_WRITE; + } + }else{ + res = RESULT_FAIL_OPENW; + } + exsave.CloseSysW(); + } + savedata.Unmount(); + //exsave.Commit(); Nand,SDはコミット入れる + exsave.Unmount(); + scr_CountPerMax(ct,arcInfo.FileCount); + if(total>0)scr_CountPerMax2(0,0,total); + +//結果 + switch(res) + { + case RESULT_OK: + if (Verifi()) + { + scr_Status("Complate",COLOR_WHITE); + return SUCCESS; + } + //PutError(ERC_DEV_OTHER,ERC_VERIFI); + break; + case RESULT_FAIL_WRITE: + case RESULT_FAIL_OPENW: + //本体メモリなので容量以外でエラーはない + PutError(ERC_DEV_OUT,ERC_WRITE_NS);//容量オーバ + break; + case RESULT_FAIL_READ: + case RESULT_FAIL_OPEN: + PutError(ERC_DEV_CARD); + break; + } + exsave.Delete();//バックアップを削除 + return ERROR; +} +bool mkdir; +//---------------------------------------------------------------- SD->CARD +RetCode Sd2Card() +{ + myResult res; + int ct=0,msize,rsize; + s64 total = 0; + + + scr_RestoreYesNo();//実行確認 + WaitUI();//入力待ち + if(isInsEject != InEx_None ){//挿抜? + //isInsEject = InEx_None; + return INSEXIT;//挿抜による中断 + } + + if (scr_evnt != EVNT_YES)return CANCEL;//キャンセル + scr_Restore();//画面表示 + scr_Status("Check Backup",COLOR_YELLO); + //保存先のマウント + res = exsave.Mount(); + if(res != RESULT_OK){ + PutError(ERC_DEV_OUT); + return ERROR; + } + + //セーブデータのフォーマット&マウント + scr_Status("Card savedata format",COLOR_YELLO); + res = savedata.Format(&arcInfo);//_exの方がいいかも + if(res != RESULT_OK){ + exsave.Unmount(); + PutError(ERC_DEV_CARD); + return ERROR; + } + //パラメータはバックアップ時 + //Top画面開始時、挿入イベントで取得 + if (arcInfo.FileCount == 0)//ファイルが無い + { + savedata.Unmount(); + exsave.Unmount(); + return SUCCESS;//フォーマットのみ + }else{ + scr_Status("file writing",COLOR_PARPL); + exsave.ResetPath(); + s64 fsize; + res = RESULT_OK; + while(res==RESULT_OK){ + res = exsave.GetPath(file_pathw); + if (res != RESULT_OK) + { + if (res == RESULT_DIR_LEVEL_OVER)break; + if (res == RESULT_PATH_LENGTH_OVER)break; + res = RESULT_FAIL_OPEN; + break; + } + if (file_pathw[0] == 0)break;//root then end + if (ct>=arcInfo.FileCount) + {//カウンタ壊れ、メモリフローの可能性 + res = RESULT_FAIL; + break; + } + + scr_CountPerMax(ct,arcInfo.FileCount); + if (exsave.Open(file_pathw)==false) + { + res = RESULT_FAIL_OPEN; + break; + } + fsize = exsave.FileSize; + total += fsize; + + int rev = 0; + while(1){ + if (savedata.OpenC(file_pathw,fsize,&mkdir)==false) + { + if(mkdir)//ディレクトリのみ作成 + {//深い場合に作成が多いと画面が止まるので + rev++; + if (rev & 1)scr_MessOnCount2("Create Directry -"); + else scr_MessOnCount2("Create Directry |"); + + }else{ + res = RESULT_FAIL_OPENW; + //exsave.Close(); + break; + } + }else break; + } + if (res != RESULT_OK)break; + + msize = fsize; + int itvl = 0; + while(fsize) + { + if(msize > FILEBUFF_SIZE * 2){ + scr_CountPerMax2(msize-fsize,msize,0); + if (++itvl & 1)scr_Status("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 ) + { + res = RESULT_FAIL_READ; + break; + } + if(savedata.Write(fileBuffer,rsize) != rsize ) + { + res = RESULT_FAIL_WRITE; + break; + } + } + savedata.CloseW(); + exsave.Close(); + ct++; + } + savedata.Close(); + exsave.CloseW(); + } + savedata.Commit(); + savedata.Unmount(); + exsave.Unmount(); + scr_CountPerMax(ct,arcInfo.FileCount); + scr_CountPerMax2(0,0,total); + +//結果 + switch(res){ + case RESULT_OK: + if (Verifi()==false)return ERROR; + if(exsave.Delete()){//バックアップを削除 + scr_Status("Complate",COLOR_WHITE); + return SUCCESS; + } + 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; +} + +//--------------------------------------------------------------- セーブデータの情報取得 +//呼ぶ前に tmerr のクリアを忘れない事 +void CheckSaveDataState() +{ + myResult myres; + + Formatted = false; + Active = false; + + if (savedata.GetPrdCode()) + { + Active = true;//カード + myres = savedata.IsExist();//セーブマウント + //NN_LOG("%d",savedata.LastNnResult.GetDescription()); + if (myres == RESULT_OK) + { + Formatted=true; + }else{ + tmerr |= SDATA_ERRPUT_MEDIA; + } + } + scr_PrdCode(savedata.PrdCode); + //プロダクトコードのチェック + isAgreePCode = strcmp(savedata.PrdCode,arcInfo.Pcode)==0; +} + +void CheckExSaveState() +{ + exActive = true;//メモリなので常にtrue + //if (exActive){ + exFormatted = exsave.IsExist() && exsave.GetInfo(&arcInfo); + //todo:変更時はバージョンチェック入れる + exsave.Unmount(); + //}else{ + ////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();//中断処理 + + //挿抜を検知したら中断して抜ける + //トップ以外ではトップメニューへ戻るようする + if (ejectEvnt.TryWait()){ + CheckSaveDataState(); + isInsEject = InEx_EjcCard; + return; + } + if (insEvnt.TryWait()){ + CheckSaveDataState(); + isInsEject = InEx_InsCard; + return; + } + } + 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; + isInsEject = InEx_None; + + //NN_LOG("Start\n"); + nn::os::Initialize(); + nn::fs::Initialize(); + + //DEA-SUPにて推奨のフリーズ暫定対策:無線デーモンを停止 (2011.3.1 現在) + //ただし、スリープ時は止まらない + //心配なら本体スイッチで切っとく + nn::ndm::Initialize(); + nn::ndm::SuspendScheduler(); + + //中断処理の準備 + InitSysBreak((uptr)endfunc); + // グラフィックスライブラリの初期化は、以降で行わなければならない + // 他、アプリケーションの初期化処理 + + nn::applet::DisableSleep();//スリープ非対応 + + //Heap + appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), + nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + const u32 GxHeapSize = 0x800000; + heapForGx = reinterpret_cast(appHeap.Allocate(GxHeapSize)); + //画面初期化 + if (ScrInitialize(heapForGx,GxHeapSize) == false)failstop(); + ejectEvnt.ClearSignal(); + insEvnt.ClearSignal(); + nn::fs::RegisterCardEjectedEvent(&ejectEvnt); + nn::fs::RegisterCardInsertedEvent(&insEvnt); + + // スリープ要求に対する返答を有効にする + // また、蓋の状態チェックを行い蓋が閉じられているならスリープ要求が発生する + //nn::applet::EnableSleep(true); + + extern u8 scr_evnt; + while(1) + { + tmerr = 0; + CheckSaveDataState(); //セーブデータの状態取得 + CheckExSaveState(); //同バックアップ + 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: + break; + case EVNT_SEL_READ://リード + NN_LOG("select read\n"); + retc = Card2Sd(); + switch (retc){ + case SUCCESS: + //CheckExSaveState(); //状態の更新 + scr_ResultQuit("Success",COLOR_GREEN);//成功とQuitボタン + break; + case INSEXIT: + //scr_InsExitQuit();//挿抜検知表示 & Quit + ScrClr();//画面消去 + scr_Backup(); + { + if (isInsEject == InEx_EjcCard)PutError(ERC_DEV_CARD,ERC_DEVICE); + else PutError(ERC_DEV_OTHER); + scr_ResultQuit("Break",COLOR_RED);//エラーとQuitボタン + } + break; + case CANCEL: + //scr_ResultQuit("Canseled",COLOR_YELLO);//キャンセル + break; + default://errors + 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(); + scr_ResultQuit("Success",COLOR_GREEN);//成功とQuitボタン + break; + case INSEXIT: + //scr_InsExitQuit();//挿抜検知表示 & Quit + ScrClr();//画面消去 + scr_Backup(); + { + if (isInsEject == InEx_EjcCard)PutError(ERC_DEV_CARD,ERC_DEVICE); + else PutError(ERC_DEV_OTHER); + scr_ResultQuit("Break",COLOR_RED);//エラーとQuitボタン + } + break; + case CANCEL: + //scr_ResultQuit("Canseled",COLOR_YELLO);//キャンセル + break; + default://errors + 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 YES\n"); + break; +*/ + //old debug key + case EVNT_PUSH_L:// ------------------------------- 表示の切り替え + case EVNT_PUSH_DOWN_Y:// ---------------------------------- 表示の切り替え + 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 +#include +#include "screen.h" +#include "../../../../common/my_defs.h" +#include "../../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 +}; + + +//ʏAR|[lgfBZ[u +void ScrClr() +{ + gui.ButtonMask(0); + gui.DisableAll(); + gui.Draw(); +} + +nn::os::Tick holdTck; +u32 holdVal; +//---------------------------------CxgR[obN +//----------------PAD{^ +void pushButton(u32 sts) +{ + //NN_LOG("button > %4x\n",button); + u32 trg = sts & 0x0ffff; + u32 hld = sts >> 16; + + if( holdVal )// + { + if (hld != holdVal) + { + holdVal = 0; + }else + if (nn::fnd::TimeSpan::FromMilliSeconds(4000) < (nn::os::Tick::GetSystemCurrent()-holdTck)) + { + holdVal = 0; + scr_evnt = EVNT_PUSH_LEFT_X; + } + }else if (hld == ( nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X )) + { + holdVal = hld; + holdTck = nn::os::Tick::GetSystemCurrent(); + } + else if (trg & nn::hid::BUTTON_B)scr_evnt = EVNT_PUSH_B; +} + +//-----------------pl^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 + +// -------------------------------------------------- R|[lg݌v +// + +//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}; + +// +//foOp +//G[\ +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}; + +//smF +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}; + +//gbvj[ +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}; + +//O\ +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}; + + +//ʏ펞 +//^Cg +#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) +//TOPj[ +//\̓OƔr +#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}; + +//폜mF +//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; + holdVal = 0; + holdTck = nn::fnd::TimeSpan(0); + + if (gui.Initialize(heap,size,&stopEvnt)==false)return false; + + gui.ButtonCallback((uptr)pushButton); + //R|[lgo^ + 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(); +} + + +//gbvj[ +//:J[h +void scr_TopMenuDbg(bool formatted,bool insertted)//fobOp +{ + scr_evnt = EVNT_NONE; + gui.ButtonMask(nn::hid::BUTTON_A | nn::hid::BUTTON_R | nn::hid::BUTTON_L); + + if (formatted) + {//[h”\ + gui.MessSet(&mess_topmenu_help_read); + gui.PanelEffective(PANEL_READ); + }else{//[hs + gui.MessSet(&mess_topmenu_help_notread); + gui.PanelEffective(PANEL_READ,false); + } + if (insertted) + {//݉ + gui.MessSet(&mess_topmenu_help_write); + gui.PanelEffective(PANEL_WRITE); + }else{//ݕs + 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(); +} + +//ʏ펞 + +//v_NgR[h +//:J[hAgZ[uɋL^ꂽ +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); +} + +//폜̎smF +void scr_DelConf() +{ + scr_evnt = EVNT_NONE; + gui.PanelEffective(PANEL_DELCONF); + YesNo(); +} + + +//Top menu +//:foCX +//arg : v_NgR[hv +void scr_TopMenu(bool formatted,bool inserted,bool exfm,bool bkupins,int err) +{ + + int i; + scr_evnt = EVNT_NONE; + + u32 mask = 0; + mask |= (nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X);//LEFT+X = Delete L + + 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); + //Е̂ݗL + if (formatted && bkupins && (exfm == false)) + {//obNAbv + gui.MessEffective(MESSAGE_MENU_OPERATE); + gui.PanelEffective(PANEL_READ); + gui.PanelEffective(PANEL_WRITE,false,false); + }else if (exfm && inserted) + {//XgA + mask |= (nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X);//LEFT+X = Delete L + gui.PanelEffective(PANEL_READ,false,false); + i =0; + if (err & SDATA_ERRPUT_PCODE) i = ERC_DEV_OTHER + ERC_PRODCODE;//v_NgR[hsv + //else + //if (err & SDATA_ERRPUT_MEDIA) i = ERC_MEDIA + ERC_DEV_CARD;//obNAbvȂ + 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;//Z[uf[^}EgłȂ + else if (bkupins == false) i = ERC_DEVICE + ERC_DEV_OUT;//ofoCX + else i = ERC_DEV_OTHER;//s + 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(); +} + +//fobOpA{^҂ +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Ɠplg + 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(); +} + +// JEg/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(); +} + +//Q[Wtotal +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(); +} + + +//smF +void scr_ConfirmDbg(char *str) +{ + scr_evnt = EVNT_NONE; + gui.MessStr(MESSAGE_CONFIRM_TITLE,str); + gui.PanelEffective(PANEL_CONFIRM); + YesNo(); +} + + +//G[\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(); +} + + +//fobOO +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/1stNUP_7/CardSaveData/Mover/body/source/screen/screen.h b/branches/1stNUP_7/CardSaveData/Mover/body/source/screen/screen.h new file mode 100644 index 0000000..081be50 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/body/source/screen/screen.h @@ -0,0 +1,115 @@ +#ifndef SCREEN_H_ +#define SCREEN_H_ + +#include +#include +#include "../../../../common/gui/gui.h" + +//plID +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)){ //I[o[[h΍ + 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; + } +}; + + +//Topj[ł̃G[\p̃tO +//bit`FbN +#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/1stNUP_7/CardSaveData/Mover/body/ver.h b/branches/1stNUP_7/CardSaveData/Mover/body/ver.h new file mode 100644 index 0000000..78aaf06 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/body/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.10 + + +#endif diff --git a/branches/1stNUP_7/CardSaveData/Mover/release.txt b/branches/1stNUP_7/CardSaveData/Mover/release.txt new file mode 100644 index 0000000..cf32e59 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/Mover/release.txt @@ -0,0 +1,46 @@ +//////////////////////////////////////////////////////////////// +{c[ uNintendo for 3DSvѐpJ[hpł +J[h̃Z[uf[^obNAbvyуXgA܂ +//////////////////////////////////////////////////////////////// + +NANDC|[gĂAAvl̎菇ŋN +{̃VXe2.0ȍ~ɂĂ +CUP(v1.02ȍ~)͖{̃VXeÂꍇXVj[N +AUPP(?)Homej[NłȂƎgȂ + +(C|[g菇) +EfobK̓C^"cci"J[hɏ +E{̃VA܂񂾃XgƏSD +EHomej[J[hNj[Inports +Ej[ImportI +EId{^Z ->"d؂"^b` +dȂȂƃACRj[Ɍ܂ + + +(NAND폜) +N܂ł̓C|[gƓl +Ej[Deletes +I̓j[ɖ߂܂ + + +c[{̂̑͑}jAQ + + +[Histry] +#\ver@}X^Over +# ύXe +v1.10 - Remaster 2.0.12 + body:[gfBNg̍ŏȂsC(`Q[eȂ) + t@C̊mۃTCY𒴂ɃG[\ + tH[}bgnG[\𓝍(G[ԍ106) + +v1.04 - Remaster 2.0.10 - svnrW 190 + body,imp: ACRHɕύXFj[̃oOŋۃtOݒ肵Ăt@[ł͗ɌĂ܂ + 쒆̖~ + +v1.03 - Remaster 2.0.8 - svnrW 181 + body: "LEFT+X"SbɕύX + ^b`̒ + imp: C|[g{̃VAԍŐ + ݒt@CŃIvVL悤 + SDK2.0+`j[œmF diff --git a/branches/1stNUP_7/CardSaveData/OMakefile b/branches/1stNUP_7/CardSaveData/OMakefile new file mode 100644 index 0000000..9890e86 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/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 $ +#---------------------------------------------------------------------------- + +#\DemoCugp܂ +#PC‹ɍ킹ăTvf̃fBNgw +#SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir ../common/include) +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/sampledemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) + +LIBS += lib_demo libnn_am + +.SUBDIRS: $(exist-dirs \ + Mover \ + ToSD \ + ) + +DefineDefaultRules() diff --git a/branches/1stNUP_7/CardSaveData/OMakeroot b/branches/1stNUP_7/CardSaveData/OMakeroot new file mode 100644 index 0000000..7260486 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/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:$ +#---------------------------------------------------------------------------- + +# fBNgCAEgɂ‚Ă̐ +# +# a) \[XR[h[gfBNgɔzuꍇ +# : +# /OMakeroot +# /foo/bar/OMakefile +# +# : +# OMakefile ƓfBNgȉ objects images ܂B +# +# /foo/bar/objects/... +# /foo/bar/images/.. +# +# +# b) \[XR[h sources ȉɔzuꍇ +# : +# /OMakeroot +# /sources/foo/bar/OMakefile +# +# : +# [gfBNgȉ objects images ܂B +# +# /objects/foo/bar/... +# /images/foo/bar/... +# +# + +# [g‹ϐ̎擾 +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 v܂BpXݒ肷邩Aǂ炩`ĉB) + 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/1stNUP_7/CardSaveData/ToSD/Imp/Imp.rsf b/branches/1stNUP_7/CardSaveData/ToSD/Imp/Imp.rsf new file mode 100644 index 0000000..158e306 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/Imp.rsf @@ -0,0 +1,19 @@ +BasicInfo: + Title : $(TITLE) + BackupMemoryType: None + Logo : Nintendo +# Companycode: "00" + ProductCode : "CTR-P-23BA" +# MediaSize: 2GB + +AccessControlInfo: + FileSystemAccess: + - Debug + +Rom: + HostRoot : $(ROMFS_ROOT) + +TitleInfo: +# UniqueId: 0xffff6 + UniqueId: 0xf8031 + Version: 0 diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/OMakefile b/branches/1stNUP_7/CardSaveData/ToSD/Imp/OMakefile new file mode 100644 index 0000000..c55d0fe --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/OMakefile @@ -0,0 +1,70 @@ +#!/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 + ../../common/test_data.cpp + ../../common/shfnt.cpp + ../../common/sleep.cpp + ../../common/common.cpp + +OBJECTS[] = + $`(ObjectFromBinary $(TARGET), ./Imp_list/key/Public_Key.der) + +TARGET_PROGRAM = CtrSaveToSd_imp + +TITLE = imp + +LIBS += lib_demo libnn_am +LIBS += libnn_ps + + +IMPORTEE_CIA = importee.cia + +SRC_IMPORTEE_PATH = ../body/images/$(BUILD_TARGET_DIR)/$(BUILD_TYPE_DIR)/CtrSaveToSd.cia +#とりあえず、マスタリング時は直おき、配置時に改名 +#SRC_IMPORTEE_PATH = CtrSaveToSd_master.cia + +# ビルドタイプ別に romfs を作る +#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) + +# プログラムから参照するためのROMFSのパスとプログラムIDを定義する +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/1stNUP_7/CardSaveData/ToSD/Imp/banner.bsf b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner.bsf new file mode 100644 index 0000000..140ac49 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner.bsf differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/BannerModel_imp/COMMON/COMMON.cmdl b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/BannerModel_imp/COMMON/COMMON.cmdl new file mode 100644 index 0000000..aaa5fbd --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/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["tosdimp"]@file:Textures/tosdimp.ctex + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DccToolSourceNode + + BONE_00 + + + + Shapes[0] + Materials["MT_00"] + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/BannerModel_imp/COMMON/Textures/tosdimp.ctex b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/BannerModel_imp/COMMON/Textures/tosdimp.ctex new file mode 100644 index 0000000..ed9df3e --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/BannerModel_imp/COMMON/Textures/tosdimp.ctex @@ -0,0 +1,17 @@ + + + + + + + + + + + + oKqgqqCqoKqgqqCqoKqgqqCqoKqgqqCqoKqgqqCqoKqgqqCqoKqgqqCqoKqgqqCqoKqgqqCqoaqgqqiqrKqvqqCqoKqgqqCqoKqgqqCqoaqgqqCqoKqgqqCqrKqoqq+qo6quqq6qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qgqqCqoaqpqqCqpKqvqq+qr6qvqq+qr6qvqq+qr6qvqqiqrKqvqq+qrKqvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvuq+qr6qvqq+qv7qvu7+7v6qvur+6r6q/q6+7r6uvqr+rr7u/ur+7r6uvq7+7r6u/u6+qv6qvqr+7r6qvu6+rv7uvqq+7r6qvq6+rv7qvq6+6r7qvq6+rr6u/u7+7v7u/u7+7v7uvqr+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u8/Mv7u/y7+8v7vPzM/Mz7vPzL+7z7vPu7/Lz8zPzM/Mz8y/u7+7v7u/u7+7z7u/y8/Mv7u/u7+7v8u/zL+8v7y/vL/Lz8y/vM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzc/Mz8zPzM/Mz8zPzc/cz93PzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/d39zP3c/M393PzN/dz8zPzM/M393f3d/d393PzN/N393f3d/d393f3d/N393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393v7d/d7+3f3d/d393f3e/t7+7v3e/u393f7d/d793v7u/u7+7v7t/t7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7s7u/u7+7s7uju7+7v7u/u7+7v7u/u7+7v7u/u7+7k7uDu7+7v7uDv8P75/vH/7+7v7u/u7+7/7////////+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u/+7v7u/v7+7////////////////////u///////////////////w//D/8P/w//D/8P/w//D/+P/w/////P/w//D/8f/w//D/8P/w//D/8P/w//D/8P/w//D/8P/w//D/8P/w//D////////////+//P////+///////////////////////w//D/8f/w//D/8P/w//D//P/w////+P/w//D/8P/w/6Cqoaqgqqmqr6qvqq+qr6qgqq+qpaqvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qpqq+qrKqvqq+qr6qvqq+qrqqvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvu6+qr7uvqq+qr6qvqq+rv6q/q7+6r6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+6r6qvur+rv7uvu6+7v6u/q7+7r6qvur+6v7qvu6+rv7qvqq+rr7qvq7+7r7uvuq+qr6qvqr+6v7uvq7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7uvqq+6r6uvu6+rv7u/u7+7v7uvq6+6v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/y7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7/Lz7u/vL+7v7u/u7/Lv8y/u8+8v7y/u8/Lv8vPvL+7z8zPvM/Mv7vPvL+7z8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mv8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzN/Mz8zPzM/Mz8zPzM/M38zfzc/cz9zP3d/d393f3d/d393fzN/d393f3d/d393f3d/dz8zPzM/Mz83Pzd/dz9zf3c/M383P3M/d39zf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d7+3f3e/e7+7v7u/u7+7v7u/u3+7v7u/u7+7v7u/u393f3d/d393f3e/d393v7d/d393f3d/d797v7u/d7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7v//7+7v7+/u7+7v7u/u7+7/7u/v///v7u/+7+7v///////////////////////////////////////////////////////v////7/7//////////////+7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////H/8P/5//D///////////////D////1//////////////////////////////////////////////////////////n////8///////////////+//////+vqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqr+rr6qvu6+qr6qvqq+qr6q/uq+qv6u/u6+rv7uvqr+6v7u/u7+7v6uvqr+6v7q/uq+rr6u/u6+qr6qvqq+6r6uvq6+6v7qvqq+qr7qvq6+qr6q/qq+7r6qvqq+rr7qvu7+7v7u/u7+7v6qvqr+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u8/Mv7u/u8+7z8y/u8/Mv8vPzM+7z8zPu7+8z8zPzM/Mz8y/u7+7v7u/u7+7v8y/vM/Lv7u/u7+7z7vPu7/Lz8u/y8/Lz8zPvM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zf3M/Mz8zPzM/Mz8zP3c/M39zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzN/cz9zPzM/N393PzN/dz9zPzd/c393f3d/dz9zPzN/M393f3d/d393f3c/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d7+7v7e/u393f7t/d393v7u/u7+7v7t/t7+7f3e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/v7+7v7///7+7v7+/u7+7//////////+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+/v7v/u7/7v7////////////////+/u////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////r6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6uvqq+qr6qvqq+qv7qvq7+6r6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvuq+7v6u/uq+7r6qvur+qv6q/q7+qr6uvq6+6r6qvu6+7r7uvqq+qr6u/u6+rr6qvq7+6r6qvu7+7r6q/u7+7v7u/u7+7v7u/u7+qv7u/q7+7v7u/u7+7v7uvuq+rr7q/qq+7v7u/u7+7r7uvuq+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7vPu7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7/Lv8u/zL+7v7u/u8/Lz7zPu7+8z7u/u8+7v7zPu7+7z8y/u8/Mz8vPu7+7v8vPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz7vPzM+8z8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzK+qb2bPzM/Mz8zPzM/Mz8zPzM/Mz8zPzK+qz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Nz8zPzM/Mz8zPzN/M393PzN/cz93f3N/d393f3d/d393f3N/d393f3d/d393f3d/dz8zPzM/M383f3d/c383f3c/Mz8zP3c/c383f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d793f3d/e7+7v7u/u7+7f7u/u7+3v7u/u7+7v7u/u393f3d/d393f3d/u393f3t/d393f3d/d393v7t/e7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7v/+7+7//+/u7+7v7u/u7+/////u///v7v/v7+7//u/////////////////////////////////////////////////////v/u/u7+//////////////7////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6q/uq+qr6qvqq+qr6qvuq+6v6qvq7+qv6uvqq+6r6q/u7+7v7u/q6+7r7qvqr+6v7q/u6+qr6qvqq+6v7uvur+qv6qvqr+6r6uvqr+6v7u/u6+rv6qvuq+7v6qvur+7v7u/u6+6v7q/ur+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7uvqi8iv7uvqr+7X1UvIg8ADwAPAL+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7r6oPAH93DwAPAE9EDwCPiF9VDwAvIg8ADwC/uw8Av7t/dz8zDwAPAC8iLyIvIg8ALyKfma+qv7u/u6+qv7u/u19VT0QPAA8AX0S/uw8Av7tfVQ8Av7s/Mw8An5kPAH93v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u5+Zv7u/uw8AX1V/d6+qv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7ufmS8iHxEPAL+7v7uvqo+Iv7u/u4+Ij4gPAA8ALyJ/dw8ADwCPiH93v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7uvqr+7v7u/u7+7v7sPAC8iDwAPAL+7v7uPiL+7v7u/u7+7r7q/u7+7j4h/d7+7j4i/u7+7DwAPAI+Ij4i/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u19VHxG/u7+7b2a/uw8ADwAfEQ8AX1WPiC8iDwC/u7+7v7uPiL+7v7uPiL+7DwAPAA8AX1UPAA8ADwAPAL+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7/Mv7u/y8+8v7vPu8/Mz7zPzM+7v7vPy8+7z8zPzM/Mz8y/u7+7v7u/u7+7v8zPy8/Lj4i/u09Ev7vPu8+7z7u/zM+8z8zPu8/Mz8zPzK+qn5m/uz8zLyIPAA8ADwAPAG9mj4g/Ip+ZPzMPAA8ADwAPAM/Mz8zPzM/MDwAPAA8ADwCfmc/Mn5nPzM/Mz8zPzM/Mn5nPzJ+Zz8zPzM/Mz8zPzM/Mz8y/u8/MDwAPAA8ADwAPAE9Eb2YPAA8ADwAPAA8An5nPzJ+Zz8zPzM/Mz8zPzJ+Zz8yfmc/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzL+7LyJ/dz8zDwAPAG9mDwAfEQ8AHxGvqn93z8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzA8ADwAPAA8Af3fPzC8iv7tfVQ8Av7s/Mw8ADwAPAA8APzM/My8iDwBfVX93DwAPAM/Mz8zPzM/Mf3cPAM/Mf3dPRK+qDwBvZs/Mz8zPzM/MDwBvZg8APzPPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8xvZr+7DwAPAM/Mz8xvZr+7HxE/M7+7z8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8y/u8/Mv7vPzE9EPzMPAA8ADwDPzM/Mn5mfmc/Mz8yfma+qDwAPAH93n5kPAA8Aj4gvIs/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zfzM/Mz8zPzM/Mz8zfzM/dz8zPzM/Mz8zPzM/Mz8zPzM/MLyK/uw8Ab2bPzM/Mz8zPzM/Mz8zPzK+qz9zfzJ+Zn5nPzA8Az82vqg8ADwAvIg8Az83fzN/d393f3d/d393f3c/M393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d392fma+q393f3d/d390PAD8zHxGvqt/dn5nf3d/d393f3Z+Zn5nf3d/dn5mvqg8ADwBfVQ8ADwAPAA8An5nf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/dT0Tf3d/d393f3d/d392vqq+qf3cPAA8ADwAPAA8AX1Wvqt/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/dr6rf3d/d393f3d/dDwAPAF9VDwCfmd/dDwCfmd/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3Z+ZPzO/u09E393f3d/d393f3d/d393f3T8zPzMPAA8APzM/Mw8AT0QPAA8ADwAPAG9m391vZt/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d390PAA8ADwAPAG9m391vZt/dDwAPAA8ADwBvZt/db2bf3T8zf3cfEQ8Az8zf3Q8Aj4jf3X93393f3Q8ADwBvZg8A393f3d/d393f3d/d393f3Y+I390PAM/M393f3d/d393f3d/d393f3c/MDwDf3R8R393f3d/d393f3T8z391fVQ8Ab2YPAC8i393f7d/d790PAA8ADwAPAO/t7+7f3u/u393f7t/d3+7v7u/u7+7v7t/d7+7f3u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/ur6rv7m9mj4gPAA8ADwAPAH937+7v7q+qr6rv7u/ur6rv7g8ADwCvqq+qDwAPAE9EDwDv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7q+q7+4/M+/u7+7v7u/u7+7v7u/u7+6vqu/u392PiC8iv7sPAO/uv7sPAA8Ar6qPiO/u7+7v7u/u7+7v7u/u7+5PRD8zPzM/M+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+4PAD8zDwAvIu/u7+6vqq+qDwAPAA8ALyIPAA8Ar6qvqu/u7+6vqs/M7+7v7u/u7+4PAH93r6rf3e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7f3Z+ZHxEPAA8A7+7v7r+7r6rv7u/ur6qvqg8ADwBPRK+qDwAPAK+qj4jv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7t/d7+7v7u/u7+7v7g8Af3cPAA8A7+7v7t/d7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/v7////v//7+7v/+/u7/7v/v///////+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7//v7u/u/+7//u/u/////////////+/v//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+vqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr7qvqq+qr6qvqq+qr6uvq7+6r6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqq+qr6qvqr+7v7uvqq+rr6q/uq+qr7uvuq+qr7qvuq+7v6u/qr+qr7u/q7+rr6u/q7+rv7q/qr+qv6qvqr+7r6q/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u6+6v7uvuq+qv7u/u7+7v7qvuq+qv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7LyIPAC8iDwAPAL+7DwC/u09EDwBfVQ8ADwC/uw8Ar6m/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u4+IDwC/ux8RDwB/dw8ALyK/u393v7u/uw8ADwBPRA8Av7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7b2aPiL+7v7u/u7+7v7u/u7+7v7t/d7+7DwAfEb+7r6o/Mw8Av7uvqr+7T0QPAF9VDwCvql9VDwAPAC8iT0S/u6+qv7u/u6+qv7u/uw8ADwB/dz8zv7u/u7+7v7u/u6+qf3cPAH94v7uvqr+7v7u/u6+qb2ZfVR8RDwAPAA8ADwBPRI+Iv7uvqr+7X1UPAA8ADwAPAL+7T0S/u6+qDwAPAA8ADwAvIq+qr6q/u7+7v7u/u7+7r6q/ux8RX1W/u6+qT0QPAE9EDwAvIg8AT0S/uy8iv7sPAA8AX1UPAC8iv7svIr+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7tfVQ8AX1UPAC8iv7svIr+7PzMPAA8ADwAfES8iDwAPAL+7v7u/u7+7v7u/u7+7v7uvqr+7v7ufmb+7v7tfVV9VLyIPAC8iDwAPAA8ADwCPiC8iDwAvIg8ALyK/u19Vv7u/u7+7v7u/u5+ZPzO/u7+7v7u/u7+7v7u/u7+7v7u/zC8iDwAvIg8AX1W/u19Vv7svIg8ADwAPAF9Vv7svIl9Vv7u/u7+7v7u/u8/Mv8vPu7+7v7tfVb+7z8zPu7/Lz7y/u8/Lv8zPu8/Lf3e/vC8iv8u/zM+8z7zPzA8Az8wPAA8ADwAPAE9Er6rPzM/Mz8wPAH93DwCfmc/Mz8zPzM/Mv8zPzM/Mz8zPzA8Az8wPAM/Mz8zPzM/Mz8xPRM/Mv7sPAI+IDwBfVc/Mz8zPzM/MDwAfES8iDwC/u8/MDwBPRM/Mn5nPzM/MDwAPAA8ADwDPzM/Mz8zPzA8ADwAPAA8An5nPzJ+Zz8zPzM/Mz8zPzJ+Zz8yfmc/Mz8zPzM/Mz8zPzM/Mz8y/uw8ADwAPAA8Az8xPRC8iDwAPAA8ADwAPAJ+Zz8yfmc/Mz8zPzM/Mz8x/d8/MDwA/M8/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8y/u8/Mz8zPzM/Mn5k/M8/Mz8zPzM/MT0S/qs/Mz8zPzM/Mz8zPzM/Mz8zPzK+qz8zPzM/Mz8zPzM/Mz8zPzM/Mz8wPAF9VDwAPAM/Mz8y/u8/MPzMPAE9EDwBPRM/MDwAfEQ8ADwCfmT8zDwAfEQ8ADwDPzM/Mz8zPzH93DwDPzG9mr6rPzA8Ar6rPzM/Mz8zPzA8AHxEPAA8Az8zPzK+qz8zPzM/Mz8zPzM/Mv7vPzL+7z8zPzF9VX1XPzH93HxEPAA8ADwAPAA8An5nPzK+qz8wPAB8RDwCvqs/Mz8zPzM/Mz8wfEc/Mr6oPAG9mPzOvqs/Mz8zPzK+qz8x/dx8RDwDPzM/Mz8y/u8/Mj4iPiE9ELyIPAA8AT0QPAA8Aj4iPiM/MPzOfmQ8ADwAfEQ8Aj4iPiA8Az8wfEQ8An5kPAA8Ar6rPzM/Mz8zPzJ+Zz8yfmc/Mz8xPRF9Vz8xvZh8RDwAPAB8RDwAPAM/Mz8zPzM/dDwAPAA8ADwDPzN/Mz93Pzc/dz8zP3N/dj4gPAN/dDwDfzd/d393f3d/dT0Tf3Y+IDwAPAA8ADwDP3N/Mz93f3Q8ADwAPAA8AT0SfmQ8Ar6rf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3Q8Az8wPAI+I393f3d/d390PAE9EDwAPAN/dn5nPzE9ET0QPAA8ALyKfmd/d393f3Q8Af3cPAL+7393f3d/d390PAA8AT0QPAH93DwAPAA8An5kPAN/dHxEPAA8ADwBPRE9E392PiN/d393f3d/d393PzN/d393f3d/d393f3d/d393f3d/d392fmQ8AX1UPAN/d393f3d/dPzMPAD8zDwAPAK+qLyLf3d/d393f3d/dDwA/Mw8APzM/Mz8zPzM/M9/d393f3d/dPzMPAG9mDwDf3d/d393f3b+7DwDf3W9mPzPf3Q8A393f3d/d393f3Q8Ab2YPAA8A393f3Q8AX1Xf3V9V392fmQ8AHxEPAA8APzMvIj8zPzMPAA8APzM/M9/d393PzN/d393f3d/d392vqt/dv7vf3d/d393f3d/d393f3d/d393f3d/dT0QfEd/dj4g/Mw8ADwBvZj8z393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d390PAA8ADwAPAG9m391vZt/dDwAPAA8ADwBvZt/db2bf3d/d393f3d/d393f3d/d393f3d/d393f3d/d392/u29mDwAPAA8ADwBvZt/db2bf3Q8ADwAPAA8Ab2bf3S8ib2bf3d/d393f3d/db2bf3V9V393f3d/d393f3T8z390fEQ8ADwAPAA8A7+7v7u/u7+4PAA8ADwA/M+/u7+7v7u/u393f3d/d393PzA8Ab2YPAN/dj4g/Mw8ADwAPAA8AX1UPAG9mDwDPzO/u7+7v7t/db2bv7u/u7+7v7s/M7+7v7k9EDwDf3U9EPzPv7p+Z7+7v7u/u390/M6+qT0QPAA8A7+7v7t/dn5nPzA8Af3cPAA8ADwAvIo+IDwAPAM/MDwB/dw8ADwAPAA8An5lfVe/uDwAPAF9VDwB/d+/uDwBPRO/u7+7v7u/u7+4PAO/uDwDv7u/ub2YfEa+qDwAPAA8ADwDPzA8Ar6rv7u/u7+7v7g8Ar6oPAK+q7+7v7u/u7+7v7u/u7+7v7u/ur6rv7q+q7+7v7u/u7+7v7q+q7+6vqg8Ar6oPAK+q7+7v7u/u7+4PAD8zDwAPAI+I7+6PiO/u7+7v7u/u7+7v7q+q7+6vqu/u7+7v7u/u7+6vqu/u7+4PAD8zDwA/M+/u7+7v7u/uDwA/Mw8APzPv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/uDwA/Mw8APzPv7u/u7+7v7g8ADwAfEQ8Av7vv7g8AHxHv7u/uz8wPAO/u7+6fme/ub2YPAA8ALyKvqu/u7+7v7u/un5nv7u/uDwAPAG9mX1Xv7u/u7+7v7u/uz8xvZg8A393v7u/u7+7v7u/uv7uPiF9VDwAPAB8RDwAPAG9mv7vv7q+q7+4/Mw8ADwAPAB8R7+4fEe/un5kPAD8zDwAPAF9V7+7v7u/u7+7v7u/u7+7v7u/uLyJ/d+/uz8xPRA8ALyIPAB8RDwCfme/uf3fv7g8ADwA/Mw8Af3fv7n937+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7j8zDwA/Mw8Af3fv7n937+4fEQ8ADwAPAD8zT0QPAE9E7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u//7+7//u/u7+7v7u/u7////+/u///v7v//7+7v/u/+///////////////////////////////////////////////////v7+/+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////r6qvqq+qr6qvqq+qr6q/qq+qr6qvqq+qr6qvur+qr7q/ur+rv7uvqq+qr6uvu7+qv6u/q7+rv7qvqr+7r7q/u6+qr6qvqr+7r6u/q6+7r6uvqr+7r7q/uq+rv7qvqr+6v7q/uq+qv7uvq7+7v7u/u6+qr7uvur+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7t/d7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/ux8RDwC/u7+7DwAPAL+7v7u/u7+7v7u/u7+7v7u/u7+7T0Svqr+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7uPiB8Rv7u/u7+7v7u/u7+7v7u/u7+7v7sPAA8Av7u/uw8AT0S/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7uPiC8iv7u/uw8Af3e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7b2a/u7+7DwAPAL+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/uw8ADwC/u7+7DwAPAL+7v7u/u7+7v7u/u7+7v7u/u8+7DwCPmL+8v7u/u8/Mz8vPzM/Lv7zPvL+7z8zPzM/Mz8y/u7+7v7u/u7+7v7u/u8+7v7u/u7+7z8u/vL+8v8u/u7/Mz8y/y8/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8y/u09Ez8zPzA8ADwDPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8wPAF9Vz8zPzA8AHxHPzM/Mz8zPzM/Mz8zPzM/Mz8zPzE9Ej4jPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8x/dx8Rz8zPzF9VPzPPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8wPAA8Az8zPzA8APzPPzM/Mz8zPzM/Mz8zPzM/Mz8zPzK+qz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mr6rPzM/MPzMPAM/Mz8zPzM/Mz8zPzM/Mz8zPzM/MDwAPAM/Mz8xPRI+Iz8zPzc/Mz8zPzM/Mz8zfzM/c38zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/d393fzc/N393PzN/dz83PzM/M393f3d/dX1UPAM/d391PRN/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3V9V393PzA8An5mfmd/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/dn5kvIt/d390PAA8A393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/dDwBfVd/d393PzN/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/db2YPAN/d393f3d/d393f3d/d393f3d/dDwAPAN/d390PAA8A393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f7t/d3+3f3d/d393f3d/d797f7u/uDwBPRN/d7+6fme/u7+7v7u/d393v3e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7t/e7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7f3U9E7+7v7g8ADwDv7u/u7+7v7u/u7+7v7u/u7+7v7g8ALyLv7u/uj3ePiO/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7g8ALyLv7u/u393v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/un5lPRO/u7+4PAB8R7+7v7u/u7+7v7u/u7+7v7u/u7+6PiN/d7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7n93DwDv7u/u7+7v7u/u7+7v7u/u7+7v7g8ADwDv7u/uDwBfVe/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7q+qLyLv7u/uDwDPzO/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/+///v7v//7+7//u/u7+7/7////////+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u//7v7u///+/v7//v/////////////+/u/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6+6r7u/u6+7r6q/u6+rr7uvuq+qv7uvuq+rr7u/q7+7r7q/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7uvuq+6v6qvu7+qv7u/u7+7r6u/q7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/y7+7v7u/u8+7z8y/u7+8z7u/u8+8z7y/zL/Mz8y/y8/Mv7y/zM+7z7vPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz7zPzL+8z8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/M393fzd/d38zPzN/d393f3d/d393fzd/d393f3d/d393f3d/dz8zPzM/M38zP3c/M383f3c/Mz9zPzd/c38zf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3e/e3+3v7u/u7+7f3d/e793v7u/u7+7v7u/u393f3d/d393f3d/d393f3d/d393f3d/d393v7e/e7+7v7e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7+/u7+7v7u/u///v/+/////v7v/v7+7////+///////////////////////////////////////////////////v7v//7+7/////////////7+7///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+/qr+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v8u/zM/Mz8vPzM/Mz8zPzL+7z8zPzM/Mz8y/u7+7v7u/u7+7v8y/u8/Mv7u/u7+7v7u/u8+7v7u/vL+8z8zPy8/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zfzM/Mz8zPzM/Mz8zP3N/cz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzN/c383PzM/d393PzM/c39zf3M/M393f3d/dz83f3M/N393f3d/d393f3c/M393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d3+7f3d/d393f3d/d3+7f7u/u393f3d/d3+7v7e/u7+7v7t/d3+3v3u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/d7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u/+7v/v//7+7v7u/u7//v/////////+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7v/u7+7v///u/////////////+/u////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7tfVS8if3gfES8iLyIPAA8Av7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u19Vv7tfVQ8ADwAPAA8Av7tfVb+7X1UPAA8ADwAPAL+7v7u/u7+7v7u/u7+7v7svIi8iPzNfVS8iLyJfVT8zv7u/u7+7v7u/u7+7v7u/uy8iLyIPAA8Aj4i/uz8zv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7tvZp+ZDwC/u4+IDwC/uw8Af3efmb+7DwC/u393r6q/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7uPiI+Iv7u/u7+7v7u/u7/Lv7vPvL+7v7uPiI+Iv7zPu6+qn5m/u8/Mv7vPvM/Lz8zPvM/Mv7y/vM/Mv8vPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mv8zPzM+7z8zPzM/Mz8zPzM/Mz8yfmZ+Zz8zPzJ+Zr6rPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mv7vPzM/Mj4hfVc/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzD8zz8zPzM/Mv7ufmc/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mn5mvqs/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzK+qn5nPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8yfma+qz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8yfmc/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzI+Ib2bPzM/MLyI/M8/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8yvqp+Zz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz7vPzM/Mz8zPzM/Mz8zPzM/Mz8zPzK+qz8yfmc/Mz8y/u4+Iz8xfVU9EDwDPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz93fzd/M383f3d/d393f3d/d393f3N/d393f3d/d393f3d/dDwCvqg8An5nPzd/Mz83f3Q8An5kPAH93z9zf3Z+Zn5nf3d/d393f3d/d393f3d/d393f3Z+Z393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3c/M393f3a+qb2bf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d390PAN/dDwBvZt/db2bf3a+qDwAPAA8Ab2bf3V9Vr6rf3d/d393f3d/d393f3d/d393f3a+qr6rf3d/dz8zf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393PzN/d392vqq+q393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/dv7vf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/t3+7v7u/u7+7f3d/d7+7v7u/u7+7v7u/u393f3d/d393f3d/d393v3d/d393f3d/d393f3d/e7+7v3e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/un5lfVQ8AT0Q/Mw8AHxHv7u/u7+7v7u/ur6rv7k9E7+7v7u/u7+7v7j8z7+5PRA8ADwAPAE9Er6rv7u/u7+4PAF9VDwAPAO/u7+7PzO/u7+7v7u/u7+7v7u/u7+7v7j8zX1UfEQ8Aj4hvZg8ADwDv7u/u7+7v7u/u7+7v7u/un5nv7j8z7+7v7m9m7+6PiO/ur6rv7u/uLyIPAM/MDwDv7u/u7+7v7u/uX1Xv7u/uPzPv7h8R7+7v7u/u7+7v7g8A7+7f3e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/uPzM/My8iDwA/Mz8zDwAfEe/u7+7v7u/u7+7v7u/u7+4/M09ET0QPAJ+Z7+4PAB8Rr6oPAK+qDwAPAO/uDwDv7q+qDwCvqg8ADwDv7g8A7+7v7t/d7+7v7l9VDwDv7h8R7+7v7u/u7+7v7o+I7+6vqu/u7+7v7u/u7+7v7u/u7+7v7u/uv7vv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+4PAL+7DwA/M+/u7+7v7u/uDwAPAA8ADwC/u+/uf3fv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7+/u7+7v7u/u7+7/7u/////v7u/u7+7//v/v///////////////////////////////////////////////////v7v/v/+//////////////7+7//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u19Vv7tfVQ8ADwAPAA8Av7tfVb+7X1UPAA8ADwAPAL+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7tfVb+7X1UPAA8ADwAPAL+7X1W/u19VDwAPAA8ADwC/u7+7LyIvIr+7X1UvIg8ALyIvIr+7v7svIg8Av7tfVQ8Av7sPAL+7v7u/u7+7v7sPAL+7DwC/u7+7v7u/u7+7v7u/u7+7v7u/u19Vv7u/u7+7v7u/u7+7v7u/u7+7v7sPAL+7j4i/u7+7v7u/u7+7v7u/u7+7r6pvZn93DwBPRL+7b2a/u7+7DwAPAI+ILyK/u7+7v7u/u7+7r6q/u7+7DwAPAA8ADwBvZS8iv7uvqg8ADwBfVg8Ab2ZvZg8ADwC/u7+7v7u/u7+7z8u/u8+7v7u/u7+7v7vPu7+7v8u/u7/LHxHPvE9EDwAPAA8ADwCfmQ8ADwAPAA8ADwCfmQ8ADwAPAA8ADwAPAD8zj4ivqg8Ab2YvIs/Mz8zPzM/Mz8zPzG9mz8y/uw8ADwCPiA8Az8zPzM/Mz8zPzA8Az8wPAJ+Zz8yfmc/Mz8zPzM/Mz8wfEc/MDwBvZs/Mz8zPzM/Mz8zPzM/Mz8zPzA8Az8wPAM/Mz8zPzM/Mz8wPAM/MDwAPAH93DwAPAA8ADwAfEW9mDwAvIg8An5m/u8/Mz8zPzA8ADwAvIg8AX1XPzA8AX1XPzG9mz8y/uw8ADwAPAA8ADwDPzA8Az8zPzM/Mz8zPzA8Az8wPAK+qz8zPzM/Mz8zPzM/Mz8zPzB8RDwA/Mw8Az8zPzM/Mz8w/Mw8ADwAPAM/Mz8zPzM/Mz8zPzM/Mr6qvqs/Mb2bPzM/MPzOvqg8Ar6o/Mw8ADwAPAA8AHxF/dw8APzMPAK+qz8zPzM/Mz8xvZs/Mb2bPzG9nDwBvZg8Ab2bPzH9mz8x/dw8Ar6oPAA8Az8wPAM/Mz8zPzM/Mz8wPAM/MDwCvqs/Mz8zPzM/MDwAPAF9VDwBPRL+7DwA/M8/Mv7vPzM/MDwAPAF9VDwDPzM/Mz8zPzM/MDwDPzK+qb2bPzB8Rz8zPzM/Mz8zPzM/Mz8zPzM/Mn5kPAJ+ZDwDPzM/Mz8zPzJ+ZDwBfVQ8ADwC/uw8An5nPzM/Mz8zPzA8Av7sfEc/Mz8zPzM/Mz8wPAA8An5k/Mw8APzMPAC8iz8xvZs/Mb2YPAA8ADwAPAL+7PzMPAA8ADwAPAF9VPzMPAH93X1XPzM/Mz8zPzM/Mz8xvZs/Mb2YPAA8ADwA/M8/Mb2bPzG9mDwA/Mw8APzO/u8/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzA8Ab2YPAA8Az8zPzM/Mz8xfVa+qz8zPzM/Mz8zPzM/MPzMPAL+7n5kPAA8An5kPAM/Mz8zPzM/Mz8wPAN/NDwDPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Nz8wPAM/dDwDPzN/N39zfzM/NDwDf3Q8ADwAPAA8Af3cPAA8An5mfmQ8An5kPAJ+Z393f3d/d390PAN/dr6rf3d/d393f3d/d393f3d/d393f3d/d393f3Q8An5kPAJ+Z393f3d/d390PAJ+ZDwCfmd/d393f3d/d393f3d/d393f3d/d393f3d/d391PRB8R393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d391/d9/d390PAA8Ar6qvqt/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/dDwAPAF9VDwAPAA8AX1Wvqm9mDwBvZg8Ab2bf3W9m390PAA8Ar6qvqq+q393f3d/d393f3d/d393f3d/d393f3W9mDwBvZg8Ab2bf3W9m391vZg8Ab2YPAG9m391vZt/d393f3d/d393f3d/d393f3d/d393f3Z+Z393f3Q8Av7vf3d/d393f3d/dz8zPzC8i393f3d/d391vZg8ADwAPAF9VDwAPAA8ADwAPAG9mb2YfEc/Mf3ff3d/d393f3d/d392vqt/dr6oPAA8ADwAPAN/dv7vf3d/dDwAPAB8RDwCvqt/dr6rf3d/d393f3d/dr6rf3X93393f3d/d393f3Q8APzMfEQ8Av7vf3Q8Az9zf3T8z392fmQ8AT0QPAA8A393f3d/d393f3d/d393f3d/d393PzN/d393f3d/d393f3d/d393f3Q8ADwAPAA8A393f3d/dn5kPAA8ADwAPAI+I391vZt/d393f3d/d396fmd/dz8zf3d/d7+7v3u/u393f3d/d397v7u/u7+7v7t/d397v3e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/t7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/uj4jv7u/u7+7v7u/u7+7v7u/u7+7v7g8ADwB/dw8ADwBfVQ8ADwDv7s/M7+7v7l9VDwDv7s/M7+7v7u/u7+7v7u/u7+5/d+/u7+7v7u/u7+4fEe/uPzPv7u/un5nv7u/u7+7v7u/uLyLv7g8Ar6rv7u/u7+7v7s/M7+4PAF9V7+7v7s/M7+4PAA8AX1UPAA8Aj4gPAA8A7+7v7u/u7+7v7u/u7+7v7u/u7+6PiO/u7+7v7u/u7+7v7q+q7+7v7g8ADwCvqg8A7+7v7u/u7+7v7i8i7+4vIg8Az8wPAI+I7+7v7u/u7+4PAH93DwCPiO/u7+7v7u/ur6oPAK+qDwAPAO/uDwDv7q+qDwCvqg8ADwDv7g8A7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7q+qDwCvqg8ADwDv7g8A7+6vqg8Ar6oPAA8A7+4PAO/u7+7v7u/u7+7v7u/u7+6vqu/u7+7v7u/u7+6PiO/uHxEPAA8ADwAPAF9V7+4/M+/uDwAPAA8ADwA/M+/uPzPv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/uDwAPAA8ADwBvZu/uj4jv7g8ADwAPAD8zv7vv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u//7v////7+7v7u/u/+7v7v///////+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7v/+7+7v/+/u///////////////u//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7tfVY+ILyIPAA8ADwAPAC8iDwC/u7+7DwAPAL+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u19VX1W/u7+7X1VfVQ8ADwC/u7+7DwAPAL+7v7u/uy8iHxEPAA8Aj4gPAL+7DwAPAL+7v7svIr+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u8+7v7vPy7+7v7u/u7+7v8y/y7+8z7u/u8+7v7tvZr+8PzMvIg8Av7sPAM/Mv8sPAA8Az8zPzA8Ab2YPAJ+Zz8xvZs/Mb2YPAG9mz8zPzM/MDwDPzM/Mv7zPzL+7z8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzA8ADwAPAA8An5nPzA8Ab2YPAA8Az8zPzA8ADwDPzM/Mz8zPzM/Mz8zPzA8Az8wPAM/Mz8zPzM/Mz8wPAM/MDwDPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzG9mn5kPAA8ADwDPzJ+Zz8zPzG9mb2bPzM/MDwAvIg8ADwC/u8/MHxFvZg8Ab2YPAM/MHxEPAM/Mz8zPzG9mLyIPAA8ADwAPAF9VDwAfEc/Mz8xvZs/Mz8zPzA8An5oPAA8Az8zPzG9mz8xvZm9mz8zPzK+qz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8yvqs/Mz8zPzM/MT0TPzL+7z8zPzM/Mz8zPzM/Mz8zPzA8APzMvIg8Az8zPzA8AX1W/u19Vz8zPzA8ADwDPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mv7s/Mw8ADwAPAA8AT0QPAB8Rz8zPzH93z8zPzM/Mf3fPzM/Mz8zPzM/Mv7tvZs/Mz8zPzM/Mr6oPAM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8xvZm9mPzMPAD8zDwAPAA8ADwDPzM/MDwAPAM/Mz8zPzM/Mb2ZvZs/Mz8yvqs/MDwAPAM/Mz8xPRM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/cz8zPzM/Mz8zPzM/Mz9zPzd/Nz83P3d/d390vIt/dj4jf3N/d393f3d/dz8zf3d/dz8zPzM/Mz8zf3N/M38zf3c/M38zPzc/M38zf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3Q8AT0QPAA8A392/uy8iDwBPRB8R393f3Q8AT0Tf3d/dDwBPRA8An5nf3d/d393f3Z+Z393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3W9mDwC/uw8ALyLPzA8ADwDf3Y+I393f3S8iDwDf3d/d390/Mx8RDwAPAM/MX1Xf3T8zj4jf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d392PiA8A391fVd/d393f3d/d393f3d/d390fEc/MDwAPAN/d391fVV9Vf3cfEd/d390PAA8A393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3S8iDwAPAA8AX1UvIt/dDwBvZt/d393f3d/d393f3d/d393f3e/e3+7v7u/u7+7f3e/d393v7u/u7+7v7u/u393f3d/d393f3d/d393v3d/d393f3d/d393f7e/d7+7f7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7n937+6PiO/u7+7v7u/u7+6/u+/u7+4PAC8iDwAPAN/d7+4PAF9VDwBvZu/u7+4/Mw8A7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/uf3cvIq+qDwAPAA8ADwAPAO/u7+4vIp+Z7+7v7g8Az8yfme/u7+7v7u/un5nv7u/u7+7v7u/uPzPv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7q+qDwBPRA8ADwDv7g8Ab2YPAA8A7+7v7g8ADwDv7u/u7+7f3X93HxFfVQ8ADwAPAA8ADwDv7u/uX1XPzO/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/uDwCvqp+Z7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7+/u7+7v7u/u7+7v/+/+///v7u/u7+7v/+/u///////////////////////////////////////////////////v7v/u/+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7vPzL+7v8vPy8/Mz7zPzM+7z7u/u7+8z8zPzM/Mz8y/u7+7v7u/u7+7z8u/u7+7v7u/u7+7v7vPvL+7v7zPy7+8z8zPu8/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zfzM/Mz8zPzM/Mz8zPzN/dz9zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz83fzN/N393PzN/Mz8zf3M/d393f3d/d393fzc/c393f3d/d393f3d/c393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d797f3d/d393f3d/d397v3e/u393f3d/d797f3u/u7+7v7t/d393v3u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/d7+7v7u/u7+7v7u/un3vv7u/u7+7v7u/uv5zv7u/u7+7v7m86bzrv7u/ubzpvOp97byrv7p97TwlvKk8Jn3vv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7m86n3vv7u/u7+7v7p97v5zv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7///7///7+7v7u/u7+/v7v///////+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/+7+7//+/u/////////////+/vz73PvU8J/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7/Mv7u/zL+7v7u/u7+7z8u/vM+7v8u/u7+7v7u/u8/Mz8y/zM/Mv8y/u7/Lz7vPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mv8zPzL+7z8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzN/cz8zP3N/N393P3d/d393f3d/d393f3N/d393f3d/d393f3d/dz8zPzM/Mz8zP3N/cz83f3c/Mz8zPzN/N39zf3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/t797v7u/u7+7f3d/e3+3v7u/u7+7v7u/u393f3d/d393f3d/d393f3t/d393f3d/d393f3e/d7+7v3e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+6fe+/un3tPCZ97Twmfe+/un3vv7p97Twmfe08Jn3vv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/un3vv7p97Twmfe08Jn3vv7p977+6fe08Jn3tPCZ977+7v7u/u7+7v7u/u7+6/re/u7+7v7u/u7+6/nO/u7+7v7u/uf0t/S+/u7+6/ra+MTwlPCU8JTwlPCU8Jr4xPCe/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/uTwlvOk8Jbzrv7m867+5vOk8JbzpPCW867+5vOu/ubzrv7u/u7+6/re/u7+6fjN/eXxpPCU8Jj2tPCW86XxpPCe/u7+7v7p+M7+7v7n9Lf0vv7n9L7+7v7k8JXxpvOk8JTwnv7k8J7+5vOk8JbzpPCU8J7+5PCe/ubzpPCW86Twnv7u/u7+7v7m86XxpvOm867+7v7u/u7+5vOm86bzpPCe/u7+7v7q+c7+7v7q+c7+5fGk8Jj1vv7k8JXxrPrU8J7+7v7u/u7+7v7u/u7+7v7q+c7+5PCd/O7+7v7u/uj2vv7u/u7+7v7u/uj2vv7q+M7+7v7t/e7+7v7q+c7+6Pa08Jr5xPCZ987+5PCc+9TwlPCZ98TwmvnO/eTwnv7l8a7+7v7u/u797v7u/ur5yvnI9bTwlPCZ98XxpPCe/u797v7u/u7+7v7u/u7+7v7u/uTwmffH9LTwnv7u/uv63v7l8a7+5vOu/u7+7v7u/u7+5vOu/uTwnv3u/u7+7v7u/u385PCe/uTwl/S+/uTwnv7u/uTwnPvU8JXxrv7o9b7+7v7u/ur5yPW+/u7+5fGk8Jn3xvOu/u7+5PCU8JbzpPCe/u7+7v7r+t7+7v7p98v62PW08JTwnPzU8JTwnv7m867+7v7u/u7+5vOk8JbzpPCe/u7+7v7u/ubzpPCW86TwmvjO/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v/+/u7+7v7u/u7+7v7q+cj1uvnO/uz83//598bzr/////r5xPCU8JTwn/////n3yffE8JTwlvOk8JbzpvOv/////v7v//7+//////////////7+///////////////////286TwlvOk8J//////////9vOk8JbzpPCf///////////////7+d/////////////598///////////////////////////////////f3p98385vOl8aTwlPCW86z73////////////////Pvf//z73/////Xxq/nf//z73//9/eTwlfGk8JTwn/////TwlPCU8Jf0tPCW8qz73Pvf//////////387/////////////TwlfGu/uTwm/rf//Xxr////////f3p98/////286Twnf3m86/////18aTwnPvU8J//9vOk8JTwlPCd/OTwnPvc+9z73//7+tz73//08J/////////////8+9TwnPvU8J///////////PvU8Jz71PCf/////Pvd/e/////598r4yffE8JTwmPW08JTwn//49b/////+/e/////////////18a//+PW/////////////9fGv//v53/////////////z73//8+9//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+/u7+7vru/u7+7v7u/u7+7vLu/u7m7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7tbu/u7C7v7u/u7+7v7u/u7C7ubuwu7G7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/y7+7z7zPy8/Mv8vPzL/Mv8vPu7+7z8zPzM/Mz8y/u7+7v7u/u7+7v8y/u8+8v7u/u7+7v7vPy7/Mv8zPvL+7z8y/vM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zf3c/M38zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/M39zf3c/d383PzN/Mz8zfzM/c393P3d/d39zPzM/Mz93f3d/d393f3c/N393f3N/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d3+3v3e/u393f3d/d393v7u/u7+7v7t/d793f7e/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7t/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7m867+7v7u/u7+7v7u/u7+7v7u/uj2tPCU8JTwmPa08JTwnv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+5PCW867+7f3u/uf0vv7u/u7+7v7u/u7+7v7u/uTwlvKk8JTwnv7m8qTwlPCe/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/uTwnf3k8JTwlvKk8JTwlPCe/u7+7v7u/u7+7v7u/u7+7f3u/ubzrv7m86TwlvOm8q7+7v7u/uj2tvOm86TwlPCe/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+6ffO/u7+6ffJ987+7v7u/u7+7v7u/u7+7v7u/u7+5vKs+tj2tPCa+MTwlPCY9r7+7v7o9r7+7v7u/u7+7v7k8J797fzu/u7+7Pve/u7+7v7u/u7+7v7u/u7+7v7u/un3zv7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7k8Jf0vPvY9bz72vnE8JTwnv7u/u7+7v7u/u7+7v7u/ubypPCW8qz83fzu/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v3k8JTwlvKk8JTwlPCe/u7+7v7u/u7+7v7u/u7+7v7u/uTwlPCe/u/+7//v//7+7v7u/u7+7v/v///////+/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7v/u7+7//v///////////////+/u/////////////////////////////////////////////////////////////598Twnf3m8qj1ufbE8Jbyr//////////////////////////////////////////////////////////////////////////////////////////////////////////08J7+6/rf//////////////////////////////////f0tPCe/uj1t/S7+tTwlPCf//////////////////////////////////////////////////////////////////////////////////////////////////////////n2xPCW86v52vjP//////////////////////////////////n3xPCa+MTwlPCU8J//////////////////////////////////////////////////////////////////////////////////////////////////////////+/nf//TwlPCf////+ffP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+///////////////8////+f/////////////////////////////////////////////////////////1////8P////////////n/8P/x//D/sLuwu7C7sLu4u7+7sLu9u7C7sLuwu7C7sLuyu7C7sLu/u7+7v7u/u7+7v7u/u7+7vru/u7O7vru/u7+7v7u/u7C7sLuwu7C7sLuwu7C7sLuwu7C7sLuwu7C7sLuwu7C7sLuxu7C7sLu8u7+7sLu4u7C7sLuwu7C7sLuwu7C7sLu/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7G7ubuwu7C7v7u/u7C7tLu/u7+7v7u/u7+7v7u/u7+7v7u/u7m7vLu/u7+7vLu/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/y7+7v7u/u7+7z7zPu8/Mv7y/u8+7v7u/vM+8z8y/y8/Mz7u/zM+7z7vPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mv8zPzM+7z8zPzM/Mz8zPzM+7z8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzM/Mz8zPzN/Nz8zfzc/Mz83PzN/N393f3d/d393PzN/dz9zf3d/d393f3d/dz8zPzM/Mz8zPzN/M38zfzM/M383PzN/dz9zf3c/N393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/d393f3d/u3+7v7u/u7+7f3e/e397v7u/u7+7v7u/u393f3d/d393f3d/d393v3d/d393f3d/d393v3t/t7+7v3u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7v7u/u7+7//+/u7+7v7u/u7+7v/v/v///v7u/u7+7v/u/u////7v/////////////////////////////////////////////v7u/v7+7v7////////////+7//+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8///////8//n////////////////////////////0//D/+f/x//D/8P////////////////////////////////////7//v/z////+P/9//D/8P/w//D/8P/y//D/8P/w//D/8P/w//D////8//j/8P/x//D/8P/w//D/8P/w//D/8P/w//D/8P/w//D/8P/w//D/8P/w//D/8P/w//D/8P/w//D/8P/w/w== + + + + + diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/dummy.bcwav b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/dummy.bcwav new file mode 100644 index 0000000..d579907 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/dummy.bcwav differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/icon2_24.ctpk b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/icon2_24.ctpk new file mode 100644 index 0000000..a96f378 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/icon2_24.ctpk differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/icon2_48.ctpk b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/icon2_48.ctpk new file mode 100644 index 0000000..550e559 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/icon2_48.ctpk differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/imp.cbmd b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/imp.cbmd new file mode 100644 index 0000000..aca81c6 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/Imp/banner/imp.cbmd differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/cts_list.txt b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/cts_list.txt new file mode 100644 index 0000000..0f11b78 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/cts_list.txt @@ -0,0 +1 @@ +EJF10000237 diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/cts_sign.dat b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/cts_sign.dat new file mode 100644 index 0000000..990b849 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/cts_sign.dat @@ -0,0 +1,2 @@ +c;qi|x$^DQl_O?OQw]idUʛPL8QLQj)~SVO>( $6i(H?8?0ۄU zOW󃳽$}葯PГ<]Ϩ[ )3v}2^Fo{5TzdNA*-\$4]9KmTF0L39i='[4>Q,/Gȗ]03 += \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/makekey.bat b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/makekey.bat new file mode 100644 index 0000000..813beb0 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/makekey.bat @@ -0,0 +1,4 @@ +openssl genrsa -out private_key.pem 2048 +openssl enc -d -base64 -in private_key.pem -out private_key.der +openssl rsa -pubout -inform DER -outform DER -in private_key.der -out public_key.der + diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/makekey_100.bat b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/makekey_100.bat new file mode 100644 index 0000000..0524431 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/makekey_100.bat @@ -0,0 +1,3 @@ +rem ver1.0.0p +openssl genpkey -out private_key.der -outform DER -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 +openssl rsa -pubout -inform DER -outform DER -in private_key.der -out public_key.der diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/makesign.bat b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/makesign.bat new file mode 100644 index 0000000..f853d3c --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/batch/makesign.bat @@ -0,0 +1,7 @@ +@echo off +if "%1"=="" goto 1 +openssl dgst -sha256 -binary -keyform DER -sign ../key/private_key.der -out cts_sign.dat %1 +goto end +:1 +openssl dgst -sha256 -binary -keyform DER -sign ../key/private_key.der -out cts_sign.dat cts_list.txt +:end diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/caution.txt b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/caution.txt new file mode 100644 index 0000000..496953d --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/caution.txt @@ -0,0 +1,5 @@ +閧̈͒ +쐬Kv̖ɂ͏oȂ + +쐬́AzzŎgpo[WɓĂ +ƃyA̔閧g diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/digit.txt b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/digit.txt new file mode 100644 index 0000000..6691db8 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/digit.txt @@ -0,0 +1,45 @@ + +{̈̃VAŌ̎lpgɓ +digitƂ̂炵 +Xg쐬ɓ͈Ⴂ`FbN̂Ɏg +R}hCŃt@Cw肷ȒPȃ`FbJ[Ƃ + + +ȉAJ삳񃁁[ +---------------- +`FbNfWbǧvZ@͈ʓIȂ̂炵A +"WX10 EFCg3E1iM10W31j"Ƃ̂炵łB + + +// NULLI[ꂽVAio[󂯎 +// NULL̏ꏊɃ`FbNfWbgtĐVNULLI[ +void 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/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/key/private_key.der b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/key/private_key.der new file mode 100644 index 0000000..a6addbc Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/key/private_key.der differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/key/private_key.pem b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/key/private_key.pem new file mode 100644 index 0000000..61e3eb9 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/key/private_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAsOicKm/hXrlKcKyJd+jBeg1yEa5j8tT9UINkCP/UWFyLQ9xs +/EYImuQlGhzqk+TWTU9sdLnOqbQFxzCPSDu/ictKayv8ZZwW53N1YodMITEPLo2i +ZVuknNkl/XQcLGjl9SymFXShry0g433QO2SxuyLcREkV9ZSRanS8Ei/NftyK7OEZ +zbcf5D8MSwhmF5gwU5h9xt0UvEkSwYUjQXBsvwJzVb5c5pDhiGX2+4KWo3+ZQlbS +OCL86HA31SzMNyKvI5zrLPpEJNLLOp8s7wX1S2YPrVbwYtxciHsQCNfhFnZKK4iI +78Sx6L6km8NARte3Q7fmi+lQHNFLKJyOcyKuwwIDAQABAoIBAE9vMufvMp/ozR8I +qfU4gt99+BEuX9yifFfRl3JfBQbkDvhammkwPR7ngC1YfJAJuZwfJJDI+Z3DorCN +Alkp0thZesHij0NEshgdBMFIBQwGTk3V9OxUGPcAnglPQHNEarUK5kxOAWd5+QGM +9ZolnZRsk8DpnD2YBy9o2SXFZx0lxOb3UoMDcm46mMfFf+dJFX3iF8LurLllkzHr +IMiqWkU2q2B2+M93LMDr4Sh4JTta9mMMYnBGE2Yuy1SqxBivByHfnIXFJAooAwuz +0B9uJTxvdyUtNvmGyWKrY0nFdzaDAY64hfpRF0I5D9QTQXso3gKyWxytiDTUWF8S +H7nTZuECgYEA2YH0wVTdIhnpEO3tQZ4wI7r2AM7tUgEsmca4wo4vahScxt/fuXE/ +WZ0qmjBUaky9liRy8GwkRz4SSd6cYRDf5ht5OdFh/0ksFwcZscCDbowx8d0qVRMR +BPIGSjJZg8gBuLzcrdx6XfbUVUzFVIm9l8NTd6DHaDNqxUSrUrCWGlECgYEA0DdX +i5iYqbrgarbJYzDV2yy4mvkL2rTCC34Eya//yDwhsNFVR6GdzmJJoz04Ka5i2/67 +BmPQZXioBMckcUdYDqDsEtCdV6nqbX6HmL/Hxvhe3FgKMK8rPwH3adkYzoWZerza +W3AR4W5KBWwtje/ncDXlNqrR956vNtfausgdntMCgYBXSgUstV8NeXKEXcfShqZx +IG3rgx/QwjHhANRTF/bFTsJgOaYyaNVwpFddi7nE80k+gSAzhmLEyI9UX+dIORpx +4WK0Jmh6qCXuk+Xm5QiaC99bXlPH0qAI6QxHKI+uCE1Qk1LI32uoXA94sBedRq30 +wumzX63HDqNxyY4r4DxNEQKBgDQOcgvLpfdhanQjqOvsrLr0Tl8ofsc6Q/1dj1Lh +dsCYEBBF9d1H0c1kk2aFisIZAExiPl4VnGeSJ+ex5jGQFbrqjrsRfxUIvTyM0tfk +sszTEdxjAoEzektxcWr8RRB1JG8kQi90MHQ8/7KlXipLXYCXaOwm/wG6obHDe8MQ +/x7TAoGAZ+092oEfNVyZaniPn4B7C3FMmCz555THhUHTzlmAITkFeXH006hbqHYX +romWUfA4qexKWKoSb5crBPm9h/3OlwcWgkldDDYDm1SKTrEDKmpmkDOKMXrDivsV +mJULZt10BA0tTb35ToxPy3ChtI2Qy2G+m9nCMu9AdvEos/oRL68= +-----END RSA PRIVATE KEY----- diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/key/public_key.der b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/key/public_key.der new file mode 100644 index 0000000..7a9e751 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/Imp/imp_list/key/public_key.der differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/romfiles/nnfont_RectDrawerShader.shbin b/branches/1stNUP_7/CardSaveData/ToSD/Imp/romfiles/nnfont_RectDrawerShader.shbin new file mode 100644 index 0000000..4290c2c Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/Imp/romfiles/nnfont_RectDrawerShader.shbin differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/Imp/source/main.cpp b/branches/1stNUP_7/CardSaveData/ToSD/Imp/source/main.cpp new file mode 100644 index 0000000..cbb5ec1 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/Imp/source/main.cpp @@ -0,0 +1,482 @@ +/*---------------------------------------------------------------------------* + 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 +#include "demo.h" +#include "../../body/ver.h" +#include "../common/sleep.h" +#include "../common/common.h" +#include "../common/shfnt.h" +#include "../common/test_data.h" + +#define INF_FILE "sdmc:/cts_inf.txt" + +#define KEY_LENGTH 2048 +#define LIST_FILE "sdmc:/cts_list.txt" +#define SIGN_FILE "sdmc:/cts_sign.dat" + + +extern "C" { + extern u8* PUBLIC_KEY_BEGIN[]; + extern u8* PUBLIC_KEY_END[]; + + const void* PUBLIC_KEY = PUBLIC_KEY_BEGIN; +} + +demo::RenderSystemDrawing s_RenderSystem; +nn::fnd::ExpHeap appHeap; +uptr heapForGx; +void ErrorStop(char *s); +void ErrorPOff(char *s); + +const size_t ROMFS_BUFFER_SIZE = 64*1024;//ROMマウント用 +const size_t READ_BUFFER_SIZE = 64*1024; + +#define SDK_SER_LEN nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN + +namespace +{ + u8* readBuf; + u8* romfsBuf; + +} +nn::Result result; + + +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, READ_BUFFER_SIZE)) + { + stream->Write(readBuf, read); + } + result = nn::am::EndImportProgram(stream); + } + return result.IsSuccess(); +} + +#define LIST_MAX 4000 +#define LIST_LENGTH (LIST_MAX * (nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1)) +u8 s_list[LIST_MAX][nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1];//シリアルリスト +u8 sign[256];//署名 +u8 serialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN+1]; + +//本体シリアル取得 +int GettedSerLen; +bool GetSerial(){ + nn::cfg::CTR::init::Initialize(); + nn::cfg::CTR::system::Initialize(); + result = nn::cfg::CTR::system::GetSerialNo(serialNo); + nn::cfg::CTR::system::Finalize(); + nn::cfg::CTR::init::Finalize(); + serialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN] = 0; + GettedSerLen = strlen((char*)serialNo); + 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);} +//上はASCIIのみ対応したTextWriterへのラッパ +//日本語表示の場合、WideTextWriterを使う(要sft_側の関数追加) + + +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() +{ + appHeap.Free(reinterpret_cast(readBuf)); + appHeap.Free(reinterpret_cast(romfsBuf)); + nn::hid::Finalize(); + SharedFontFinalize(); + nngxWaitVSync(NN_GX_DISPLAY_BOTH);//SDK2.0以降では不要? + s_RenderSystem.Finalize(); +} + +//署名検証 +bool VeriRsa(u8* src,size_t sz,u8* sig) +{ + nn::crypto::RsaKey key; + //nn::crypto::Initialize(); + nn::ps::CTR::Initialize(); + result = key.InitializePublicKey(PUBLIC_KEY_BEGIN,KEY_LENGTH); + if (result.IsSuccess()) + { + result = nn::ps::CTR::VerifyRsaSha256(src,sz,sig,key); + } + //nn::crypto::Finalize(); + nn::ps::CTR::Finalize(); + return result.IsSuccess(); +} + +//エラー +void ErrorCommon(char *s,char *ss) +{ + char str[128]; + nn::am::FinalizeForLocalImporter(); + nn::fs::Unmount("sdmc:"); + nn::fs::Unmount("rom:"); + NN_LOG(s); + NN_LOG(" result = %d\n",result.GetDescription()); + shf_SetScale(0.7,0.7); + setColor(1.0, 0.0, 0.0,1.0); + strcpy(str,"Error: "); + strcat(str,s); + drawText(10,100,str); + drawText(10,140,ss); +} + + +void ErrorStop(char *s) +{ + ErrorCommon(s,"Push Home Button & end"); + s_RenderSystem.SwapBuffers(); + WaitKey(0); +} + +void ErrorPoff(char *s) +{ + ErrorCommon(s,"Push Power Button & Power Off"); + drawText(10,160,"Home Button is invalid"); + s_RenderSystem.SwapBuffers(); + WaitKey(0); +} + + +//改行後の位置を返す、0=見つからなかった +int CrLf(int n,int max) +{ + u8 d; + while(n < max) + { + d = readBuf[n]; + if (d==0x0a)return n+1;//LF + if (d==0x0d)//CR + { + if (n == max-1)return 0;//終端 + n++; + if (readBuf[n]==0x0a)return n+1;//CR+LF + ErrorStop("list broken");//CRのみは異常、署名時にファイル壊れてた? + } + n++; + } + return 0; +} + +nn::fs::FileInputStream fi; +//ファイルリード +s32 FileRead(char* fname) +{ + s32 size; + result = fi.TryInitialize(fname); + if (result.IsFailure()){//open error + //NN_LOG("desc= %d\n",result.GetDescription()); + return 0; + } + result = fi.TryRead(&size,readBuf,READ_BUFFER_SIZE); + fi.Finalize(); + if (result.IsFailure()){ + //NN_LOG("desc= %d\n",result.GetDescription()); + return 0; + } + return size; +} + + +char ver[16]; +char seri[32]; +void nnMain( void ) +{ + //nn::Result result; + bool flg_applove=false; + bool flg_test=false; + extern bool prohibitHome;// HOME ボタン禁止 + + nn::os::Initialize(); + nn::fs::Initialize(); + + //DEA-SUPにて推奨のフリーズ暫定対策:無線デーモンを停止 (2011.3.1 現在) + //ただし、スリープに入ると再開 + //無線は使わないので本体横スイッチ切っとくのが確実 + nn::ndm::Initialize(); + nn::ndm::SuspendScheduler(); + + //中断処理の準備 + InitSysBreak((uptr)endfunc); + // グラフィックスライブラリの初期化は、以降で行わなければならない + // 他、アプリケーションの初期化処理 + + nn::hid::Initialize(); + nn::hid::PadReader padReader; + hpr = &padReader; + + //result = nn::ns::CTR::InitializeForShell(); + //if (result.IsSuccess()) + result = nn::am::InitializeForLocalImporter(); + + nn::applet::DisableSleep();//スリープ非対応 .. 無線対策 + + // ヒープの確保 + appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + const u32 s_GxHeapSize = 0x800000; + // RenderSystem の準備 + heapForGx = reinterpret_cast(appHeap.Allocate(s_GxHeapSize)); + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + SharedFontInit(); + + // 共有フォントの種類を取得 + //nn::pl::SharedFontType sftype = nn::pl::GetSharedFontType(); + + // スリープ要求に対する返答を有効にする + // また、蓋の状態チェックを行い蓋が閉じられているならスリープ要求が発生する +// 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 Exporter 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())ErrorStop("Initialize");//初期化に失敗 + if (READ_BUFFER_SIZE < LIST_LENGTH)ErrorStop("buffer size");//バッファサイズのチェック + + //ファイルバッファ + //SDKで4倍数サイズ、4アライン推奨 + if (READ_BUFFER_SIZE > appHeap.GetTotalFreeSize())ErrorStop("memory alloc"); + readBuf = reinterpret_cast(appHeap.Allocate(READ_BUFFER_SIZE,32)); + if (ROMFS_BUFFER_SIZE > appHeap.GetTotalFreeSize())ErrorStop("memory alloc"); + romfsBuf = reinterpret_cast(appHeap.Allocate(ROMFS_BUFFER_SIZE,32)); + + if (nn::os::CTR::GetRunningTargetHardware() != nn::os::TARGET_HARDWARE_PRODUCT) + {//デバッガ + flg_test=true; + flg_applove=true; + }else{//実機ならシリアルチェック + int i,j,n; + s32 fsize; + if( GetSerial() == false)ErrorStop("Get Serial");//本体シリの取得に失敗 + + result = nn::fs::MountSdmc();//ダイレクトでマウント..マスタリング時にワーニング + if (result.IsFailure())ErrorStop("Mount SD"); + fsize = FileRead(INF_FILE);//設定ファイルがあるか + if((fsize < 1024) && (fsize > 0))//サイズチェック,増えても1Kは超えない + {//不具合調査時に状況にあわせて現場で作成&変更を想定したオプション + //通常は不要なので無しでも動くようしとく + n = 0; + while(n < fsize) + { + if (readBuf[n] == '-'){ + if (n == fsize-1)break;//終端 + n++; + switch (readBuf[n]){ + case 'p':// -p .. 本体シリアル表示 + strcpy(seri,"s/n: "); + strcat(seri,(char *)serialNo); + shf_SetScale(0.5,0.5); + drawText(10,40,(char*)seri); + shf_SetScale(0.7,0.7); + break; + case 't':// -t .. テストメニュー有効 + flg_test = true; + break; + } + } + n++; + } + } + + //シリアル表示(オプション)後にチェック + //デバッガ=15,実機=11 + if (GettedSerLen < 11)ErrorStop("invalid Serial"); + + fsize = FileRead(SIGN_FILE);//署名リード + if(fsize != 256)ErrorStop("sign file");//鍵のbit長は2046固定 + memcpy(sign,readBuf,256);//readBuf -> sign + fsize = FileRead(LIST_FILE);//リストリード + if((fsize > LIST_LENGTH ) || (fsize == 0))ErrorStop("list file"); + + nn::fs::Unmount("sdmc:"); //検証後はSDから読まないでメモリバッファ上のデータを使う: 差替え対策 + if (VeriRsa(readBuf,fsize,sign) == false)ErrorStop("sign verify"); + + //署名検証OK + int list_ct = 0; + n=0; + while(n < fsize)//リスト作成 + { + if (readBuf[n] == '#')//コメント行を無視、ワイド文字非対応 + { + i = CrLf(n,fsize);//コメントの次行 + if (i == 0)break;//ファイル終わりまで改行が見つからない + }else + { + //改行さがし + if ((fsize-n) > (SDK_SER_LEN+2)) + {//シリアルは改行つける + i = CrLf(n,n+SDK_SER_LEN+2); + if (i == 0)ErrorStop("list broken");//改行が見つからない + }else{ + i = CrLf(n,fsize); + if (i ==0)i = fsize;//改行以外でファイル終 + } + if ((i-n) > GettedSerLen)//シリアルをリスト化 + { + j = 0; + while(n=LIST_MAX)ErrorStop("List too Long"); + } + } + if ((fsize-i) < GettedSerLen)break;//ファイル終 + n=i;//ポインタを改行の次へ + } + + //文字数チェック + //開発初期のファームアップで空ID本体が発生してたので念の為 + //2011.5現在、製品で報告はない + if (GettedSerLen < 11)ErrorStop("invalid Serial"); + + //本体シリアルがリストにあるかチェック + n =0; + while(n + + + + + 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["tosd"]@file:Textures/tosd.ctex + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DccToolSourceNode + + BONE_00 + + + + Shapes[0] + Materials["MT_00"] + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/banner/BannerModel_test/COMMON/Textures/tosd.ctex b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/BannerModel_test/COMMON/Textures/tosd.ctex new file mode 100644 index 0000000..49e893c --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/BannerModel_test/COMMON/Textures/tosd.ctex @@ -0,0 +1,17 @@ + + + + + + + + + + + + AKqrqgCqq6oAq6qrAKuqqwCrq6oAq6uqAKqqqgCrq6sAq6qqAKuqqgCqqqsAq6urAKqrqgCsq6wAq6urAKusqwCsrKsArKurAKysqwCrq6sAq6ysAKysqwCsq6wArKysAKurrACsrKwAq6urGKusrAmrrKyErKysyaurq/+sq6sAqqqrAKurqwCqqqoArKurAKyrrACrq6wArKusGKyrrACqq6sAq6yrAKusqwCsrKwGq6usyayrq4Srq6v/q6usMKyrq+Gsq6zkq6ur/6ysrP+srKv/q6us/6yrq/+rrKz/rKus/6yrq/+rq6z/rKyr/6ysrP+srKz/rKys/6ysrQCrq6sAq6urGKyrq5mrrKsDraysSK2srfCsra3/rKyt86ysq/+sraz/q6ur/6ytrf+srK3/ra2s/62trf+sra2NrKytyaysrP+srK3/ra2szK2srPysrKz/rK2t/6ytrP+sra3/rays/6ytrf+trK3/rKys/66urf+sra3/ra2u/62srP+sraz/rayt/6ytrP+trK3/rKyt/6ytrf+srK3/rK2s/62srf+srK3/rayt/62trf+srKz/rKys/62srf+traz/rays/62trP+sraz/rq2u/66trf+ura3/rq6t/6ytrf+trq7/rays/66trf+urq7/rq2t/62urf+trq3/ra2t/62trf+urq3/rq2t/66trv+trq7/ra6u/66trv+tra3/rq6u/66urv+tra7/rq6t/66urv+urq7/ra6t/66trf+trq7/rq2t/62urf+urq7/rq+v/66vr/+urq7/ra2t/6+ur/+ura3/rq6u/6+urv+urq7/rq+u/6+ur/+ura7/rq2t/62urv+urq3/rq6u/62trf+tra3/rq6t/62urv+trq3/rq6t/66urv+tra7/r6+u/62trf+vrq//rq6u/6+vr/+vrq//r6+v/6+urv+vrq//r66v/66vr/+vrq7/r66u/66vr/+vr6//r66u/66vr/+urq//r66v/6+vrv+ur67/r66u/66vrv+urq//r6+v/6+ur/+vr7D/r6+u/66ur/+vr67/rq6v/7CvsP+vsLD/sLCw/7Cvr/+vr7D/sK+w/6+vr/+wsK//r7Cw/6+wr/+vr6//sLCv/6+wsP+wr7D/sLCw/6+wr/+vsK//sbGx/6+wr/+xsLH/rq+u/7Cvr/+vr67/sLCw/6+vr/+vsLD/r7Cv/7CwsP+vr6//r7Cw/6+vr/+vsK//r7Cv/7CvsP+vsK//r6+w/6+vsP+vsK//r7Cv/6+wr/+wsLH/sLGw/7CwsP+wsLD/sLCw/7CwsP+vr6//sbCw/7GxsP+wsbH/sbGw/7Gxsf+xsbH/sLGw/7GwsP+xsLD/sbGw/7CxsP+xsLD/sLGw/7Cwsf+wsLH/sLGw/7Cxsf+wsLH/sbGw/7GwsP+xsbH/sLCx/7Gysf+xsLH/srGy/7Gysf+ysrL/sbGx/7Kxsf+xsbH/sbKx/7Gxsf+xsrH/srGy/7Kxsf+xsbH/srGx/7Cwsf+xsLD/sbGw/7Cxsf+xsbD/sbKy/7CxsP+ysbH/sLGx/7CxsP+xsbD/sLGx/7Gxsv+xsrL/srGy/7Kxsf+xsbH/sbKy/7Gysv+ysbL/sbKy/7Gysv+xsbH/srKz/7Kysf+xsbH/sbGy/7Gxsv+xsrL/srKz/7Ozs/+ys7L/srGy/7Gxsf+xsrH/srKy/7Oysv+ys7L/s7Ky/7Ozs/+xsrL/s7Ky/7Kzsv+ysrL/s7Oy/7Kzs/+zs7P/s7Ky/7Kys/+zs7L/s7Ky/7Ozsv+zs7T/tLSz/7OztP+0s7P/s7Oz/7O0s/+ysrL/tLOz/7OztP+0tLP/s7Sz/7Ozs/+zsrL/srKy/7Kys/+ysrL/srOy/7Oysv+ysrL/srKy/7Oys/+zsrL/s7Ky/7Ozsv+zsrL/s7Sz/7Kys/+0s7T/s7Oz/7S0tP+0tLT/s7Sz/7O0tP+zs7T/s7O0/7OztP+0s7T/tLO0/7SztP+0s7T/s7Sz/7SztP+0s7P/tLW1/7O0s/+0s7P/tLOz/7SztP+0s7T/tbW0/7S1tf+0tbT/s7Sz/7SztP+zs7P/tLW0/7W1tP+0tLT/tbW0/7W0tP+0tbT/tbS0/7W0tP+0tbX/tLW1/7a1tf+2tbb/tbW1/7S0tP+1tbX/tbW0/7W2tf+2trb/tra1/7a1tv+2trb/tLOz/7S0tf+0tLT/tLS0/7S1tP+0tLT/tbS0/7S1tf+0tbX/tLS0/7W0tP+0tLT/tLS0/7W0tP+1tLT/tba1/7W0tP+2trb/tbW1/7a1tv+1trX/tbW1/7W2tv+1tbb/trW2/7W1tv+1trX/tba1/7a1tf+2trX/tbW1/7a3t/+1tbX/tba1/7W2tv+2tbb/tba2/7e3t/+3t7b/t7a3/7W2tf+1tbb/trW1/7a2t/+2t7b/t7e2/7a3tv+3trf/tre2/7e3tv+3t7f/tre2/7e2t/+4uLf/uLi3/7i3t/+2t7b/tra2/7a3t/+3uLj/t7e3/7e4t/+3t7j/t7e3/7W2tf+3trb/t7e3/7e2t/+3trb/tra2/7a2tv+2t7b/tra3/7e2tv+2t7b/t7a3/7a2tv+3trf/tre3/7i3t/+3trf/t7i3/7e3t/+4t7j/uLi4/7i4t/+3t7j/t7i3/7i3uP+4uLf/t7e4/7i3t/+3t7f/uLe3/7i4uP+4ubn/uLe4/7e3t/+4uLf/t7e3/7i4t/+5uLj/uLm4/7m4uf+4t7j/t7i4/7i4t/+4ubn/uLi5/7m4uf+5ubj/ubi5/7i4uP+4ubj/uLi5/7i4uf+5ubn/ubm5/7m5uf+5ubr/uLm5/7m5uf+4uLj/ubm5/7m5uf+5urr/urq5/7q5uf+3t7j/uLm4/7i5uf+5uLj/uLm4/7m5uP+5uLn/uLi5/7i5uP+4uLn/ubi4/7m5uP+5uLn/ubm5/7m5uf+5ubn/ubm5/7m5uf+5ubn/ubq5/7m6uf+6ubn/ubm5/7m6uv+5ubn/ubm5/7m6uf+6ubr/urm5/7q6uv+5urr/urq6/7m5uf+5ubr/ubq6/7q6uv+6urr/urq6/7q6uv+6u7r/ubm6/7q6uv+6urr/urq6/7u7uv+6u7v/u7q7/7q7uv+6urr/u7q6/7q6u/+7u7v/u7u7/7u7u/+8vLz/u7u7/7u6u/+7u7v/u7u7/7y7vP+7vLv/u7u8/7u8vP+7u7z/urq6/7q6u/+6urr/u7u7/7u6u/+6u7v/u7u7/7u7u/+7u7r/urq6/7q7u/+6urv/urq7/7u7u/+7u7v/vLu7/7u7u/+7vLz/vLu7/7u7vP+8vLz/vLy8/7y8u/+8vLz/u7y7/7u8u/+8u7z/vLy7/7y8vP+9vLz/vLy8/7y8vP+8vLz/vLy8/7y7vP+8vLz/vLy9/7y9vP+8vbz/vby8/7y8vP+8vLz/vLy8/7y9vP+8vLz/vLy9/728vf+9vb3/vL28/729vf+9vb3/vr2+/769vv++vr7/vb2+/769vf+9vb3/vr69/769vv+9vr3/vr29/76+vv+9vb3/vr6+/728vP+9vb3/vby9/728vf+9vbz/vb29/729vf++vr7/vby9/728vP+9vL3/vb29/729vf++vr3/vb6+/72+vf++vr7/vb69/729vf++vr3/vr6+/7+/vv++vr7/vr+//72+vf++vr7/vr2+/76+vv++v77/v7++/76+v/++vr//vr6+/76+vv++vr7/v7+//76+v/+/v77/v76//7+/v/+/v7//vr++/7+/v/++vr//v76+/7+/v/+/v7//wMDA/7+/v/+/v8D/v8C//7+/v//AwMD/wMDA/8C/v//AwMD/v7+//8C/v//Av7//v7/A/8DAwP/BwcD/wMDA/8HAwf++v77/vr6+/76+v/+/v7//v7+//8C/v/+/v8D/wMDA/7++vv+/v7//v7+//7+/wP+/wMD/v8C//7/Av/+/wL//v7/A/8DAwP+/wL//wMDA/8HAwP/BwcH/wMDA/8HBwP/AwMD/wcDB/8DAwP/BwMH/wMHA/8HBwf/AwcH/wcHB/8DAwf/BwMD/wMHA/8HBwf/BwcH/wsHB/8HBwf/BwsH/wcHA/8HBwf/AwcD/wcHB/8HBwf/CwcH/wcHC/8HCwv/BwcH/wsLC/8LBwf/CwsL/wsLC/8LCw//Dw8L/wsPC/8LCwv/CwsL/wsLC/8LDwv/DwsP/wsLC/8PDwv/Dw8P/wcHB/8HBwf/BwcH/wsHB/8LCwf/BwsL/wcLC/8LCwv/BwcH/wcHC/8HBwf/BwcL/wsHC/8LCwv/CwsL/wsPD/8LCwv/DwsP/w8LD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PC/8LCw//DwsL/w8PD/8PDw//Ew8P/w8PD/8PDw//Cw8P/w8PD/8PDw//Dw8P/w8TD/8PDw//DxMP/xMPE/8PDw//ExMT/w8PD/8TEw//DxMP/xMTE/8PExP/ExMT/xMTE/8TExP/ExMT/xcXE/8XFxf/FxcX/xcXF/8XFxf/ExcT/xcXF/8XExP/ExcX/xcXF/8bGxv/FxcX/xcbG/8PDw//ExMT/xMPE/8PExP/ExMT/xMTE/8TExP/ExMT/w8TE/8TExP/ExMT/xMTE/8TFxf/ExcT/xMTE/8TFxf/FxcT/xcXF/8TFxf/FxcX/xcXF/8XFxf/Fxcb/xsXG/8XFxf/FxcX/xcXF/8bGxv/FxsX/xsbF/8XGxv/Gxsb/xcbF/8bFxf/FxsX/xsXF/8bFxv/Gxsb/xsbG/8fGx//FxsX/xsbG/8bFxf/Gxsb/xsbG/8bGxv/Hxsb/xsbG/8fHxv/Gx8b/xsbH/8fHx//Hx8f/x8fI/8fHyP/Ix8f/xsbG/8fHx//Hx8f/x8fH/8jIx//Hx8j/x8jI/8jIyP/GxcX/xsbG/8bGxv/Gx8f/x8bH/8fGx//Hxsf/x8fH/8bGxv/Gxsb/x8bG/8fGxv/Gx8b/x8fH/8fHx//Hx8j/x8fH/8fHyP/IyMf/yMjH/8fIx//IyMj/yMjI/8jJyf/Ix8f/x8jI/8fIx//IyMj/yMjI/8nIyf/JyMj/ycjI/8fHyP/IyMj/yMjI/8nJyP/JyMn/ycnI/8nJyP/JyMn/yMjI/8jJyP/Jycn/ycnI/8jIyP/Jycn/yMnJ/8nJyf/Jycn/ycnK/8nJyf/Kysn/ycrJ/8rKyv/Kycn/ysrK/8rKyf/Kycr/ysrJ/8rJyf/Kysr/y8rK/8rKyv/Lysv/yMjI/8nJyf/JyMn/yMjI/8nJyf/Jysn/ycnJ/8nKyv/JyMn/ycnJ/8jIyf/Jycn/ysrJ/8rJyf/Kysn/ycnK/8rKyv/Kysr/ycnJ/8rKyv/Kysv/ysvK/8rLyv/Ly8r/ysrK/8rLy//Kysr/ysrK/8vKyv/Ly8v/ysvL/8vLy//Ky8r/y8vL/8vKy//Kysr/y8vL/8vLy//Ly8v/y8vL/8rKyv/Ly8v/y8vK/8vLy//MzMv/y8zL/8vLzP/LzMv/zMzL/8zMzP/MzMv/zMzM/8zNzf/NzM3/zM3M/83NzP/MzMz/zc3N/8zMzP/MzMz/zM3M/83Nzf/MzM3/zc3N/8vLy//My8z/y8vL/8vLy//MzMv/zMzM/8zLy//MzMz/y8zL/8vMy//My8v/y8vM/8zMzP/Mzcz/zMzM/8zNzP/Nzc3/zczM/83NzP/Nzcz/zc3N/83Ozf/Nzc3/zs7N/8zMzP/Nzc3/zM3N/83Nzf/Nzc3/zc3O/87Ozv/Nzc3/zc3N/87Nzv/Nzc3/zc3O/87Ozf/Nzc7/zs7N/87Ozv/Nzs3/zs7O/83Ozv/Nzc7/zc7N/87Ozv/Ozs7/zs7O/87Ozv/Ozs7/zs/P/8/Pz//Pzs//z8/P/8/Pz//P0M//z87P/87Pzv/Ozs//z8/P/8/Pz//P0M//z8/Q/8/Q0P/Ozs3/zs7O/83Nzf/Ozs7/zs7O/8/Pzv/Pzs7/zs7O/83Ozv/Ozs7/zs7O/87Pz//Oz87/z8/P/87Ozv/Pz8//zs/O/8/Pz//Pz8//z9DQ/9DP0P/P0ND/z8/P/9DQ0P/Pz8//0NDQ/8/Pz//Pz8//z8/P/9DQ0P/Q0ND/0NDR/9DQ0P/Pz8//0NDP/9DQ0P/Q0ND/0dDQ/9DR0f/R0dD/0NDP/9DQ0P/Q0ND/0NDQ/9DR0P/Q0dD/0dHR/9HR0f/R0dD/0dHR/9HR0f/S0tL/0dHR/9HR0v/S0dL/0tLS/9HR0f/S0tL/0dLR/9LR0v/S0dL/0tLS/9LS0v/S09P/0NDQ/9DQ0P/R0dD/0NDQ/9DR0f/R0dH/0dHR/9LS0f/R0dD/0dDQ/9HR0f/R0dH/0dHR/9HR0f/R0dL/0dHR/9LR0f/R0tH/0dLS/9LS0v/S0tL/09LS/9PT0v/S0tP/0tLS/9LS0v/S0tL/09LT/9PS0v/T09P/0tPS/9PT0//S0tL/0tPS/9LS0v/S09L/09PS/9PT0//T09P/1NTU/9LT0//T0tP/0tLS/9PT0//T09P/1NTU/9PT0//T1NP/09TT/9PU0//T09T/1NTU/9TU1P/U1dX/1NXU/9XV1P/U1NP/1NTU/9TU1P/U1NT/1dXV/9XV1f/U1NX/1dXV/9PT0//T09P/09PT/9PU0//T09T/09PT/9PT0//U1NT/09PT/9PT0//U1NT/09PT/9PU1P/U1NT/1NTU/9TV1P/U1NT/1NXU/9XU1P/V1NT/1NTV/9XV1f/V1dX/1dXV/9TU1P/U1NT/1dXV/9XV1f/V1dX/1dXV/9XV1f/W1tX/1NTU/9XV1f/V1dX/1dXV/9XV1f/V1tX/1dXW/9bW1v/V1dX/1dXV/9XV1f/V1tX/1tXV/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9fX1v/X19f/19fX/9fX1//X19f/1tbW/9fX1v/X19b/19fX/9fX1//X19f/19fX/9fY1//V1dX/1dXV/9bV1f/W1tb/1tbW/9bW1v/W1tb/19fW/9XV1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bX1v/X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9jY2P/X19f/19fX/9fX1//Y19j/19jX/9jY2P/Y2Nj/2NjY/9fX1//Y19f/19fY/9jY2P/Y2Nj/2NjY/9jY2P/Z2Nj/19fY/9jY2P/Y2Nj/2NjY/9jY2P/Z2Nj/2NnZ/9nZ2f/Y2Nn/2dnZ/9nZ2f/Z2dn/2dnZ/9na2v/Z2dr/2tra/9nZ2f/Z2dn/2dnZ/9na2f/Z2dn/2tra/9ra2v/a2tr/2NjY/9jY2P/Y2Nj/2NjZ/9nY2f/Z2dn/2dnZ/9nZ2f/Y2Nj/2NnZ/9jY2P/Z2dn/2dnZ/9nZ2f/Z2dn/2dna/9nZ2f/a2dr/2dnZ/9ra2v/a2tr/2tra/9ra2v/a29v/2trZ/9ra2v/a2tr/2tra/9ra2v/a29v/29ra/9vb2//a2tr/2tra/9ra2v/b29r/2tva/9vb2//b29v/29vb/9ra2v/b29r/29va/9vb2//b29v/29vb/9vb2//c29v/29vb/9zc3P/b3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c29v/3Nzc/9zc3P/c3Nz/3Nzc/9zd3f/c3Nz/3N3d/9va2v/b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vc/9vb2//c3Nz/29vc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/93d3f/d3Nz/3d3d/9zc3P/d3dz/3Nzc/9zc3P/d3d3/3d3d/93d3f/d3d3/3Nzc/93d3f/c3Nz/3d3d/93d3f/d3t3/3d3d/93d3v/d3d3/3d3d/93d3f/d3d3/3d3d/97e3v/e3d3/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/39/f/9/f3v/f39//3t7e/97e3//e3t7/39/f/9/f3//f39//39/f/9/f3//d3d3/3t3d/93d3f/d3t3/3t7e/97e3v/e3t7/3t7e/93e3f/e3t7/3d7d/97e3v/e3t7/3t/f/97e3v/e3t//397f/9/f3//e39//39/f/9/f3//g3+D/39/f/+Df4P/f39//39/f/9/f3//f39//4N/g/+Dg4P/g39//4ODg/9/f3//f3+D/39/f/+Df3//g4OD/4ODg/+Dg4P/g4OD/39/g/+Dg4P/g4OD/4ODg/+Dg4P/g4OH/4ODg/+Hg4P/g4OH/4eHh/+Hh4P/h4eH/4eHh/+Hh4f/h4eH/4uHi/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4uLh/+Hh4f/i4uL/4ODg/+Dg4P/g4OD/4ODg/+Dg4f/h4eH/4eHh/+Hh4f/g4OD/4OHh/+Dg4P/g4OD/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Lh4v/h4eL/4uLi/+Li4v/i4uL/4eHh/+Hh4f/i4eL/4uLi/+Li4v/i4uL/4uLi/+Li4//h4eL/4uLi/+Li4v/i4uL/4uLi/+Lj4v/j4+P/4+Pj/+Li4v/i4uL/4uLi/+Pj4//j4uL/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pk/+Pj4//k5OT/5OTk/+Tk5P/j4+P/4+Pk/+Pj5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Li4v/j4+L/4uLj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4uPi/+Pj4//j4+P/4+Pj/+Pj4//k4+P/4+Tk/+Tk5P/j4+P/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5eTk/+Tk5P/k5OT/5OTk/+Tk5P/l5OT/5eXl/+Tl5f/l5eX/5OTk/+Tk5P/k5OT/5OXl/+Xl5f/l5eX/5eXl/+Xl5f/l5OT/5eXl/+Tl5f/l5eX/5eXl/+Xm5f/l5eX/5uXl/+bl5v/m5ub/5ebm/+bm5v/m5ub/5ubm/+bm5v/n5uf/5ubm/+bm5v/m5ub/5ubm/+bm5v/n5uf/5+fm/+fn5//l5eX/5eXl/+Xl5f/l5eX/5eXl/+bm5v/m5eX/5ubm/+Xl5f/l5eX/5eXl/+Xl5f/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5+fn/+fn5//n5+f/5+fn/+fn5//m5ub/5+bm/+fm5//n5+f/5+fn/+fn5//n5+f/5+jn/+fn5//n5+f/5+fn/+fn5//n5+f/5+jn/+fn6P/o6Oj/5+fn/+fn5//n5+f/5+fo/+fo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+np6f/p6On/6enp/+jo6P/o6Oj/6Ojo/+jp6P/p6en/6enp/+np6f/p6en/5+fn/+fn6P/o5+f/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/n6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+np6P/o6Oj/6Ojp/+np6f/p6en/6Ojp/+np6f/p6en/6enq/+np6f/p6un/6enp/+np6f/p6en/6enp/+rq6f/p6en/6urp/+rq6v/p6en/6urp/+np6f/p6er/6urq/+rq6v/q6ur/6urq/+nq6v/q6ur/6erp/+rq6v/q6ur/6urq/+rq6v/r6+v/6urq/+rq6v/q6+v/6+vr/+vr6//r6+v/6+vr/+vr6//q6+r/6+vr/+vr6//r6+v/6+vr/+zs7P/r6+v/6+zs/+rq6v/q6ur/6urq/+rq6v/q6ur/6urr/+vr6//r6+v/6urq/+rq6v/q6ur/6uvr/+rr6v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/7Ozr/+zs7P/r6+v/7Ozs/+vr6//s7Ov/6+vr/+vr6//s7Oz/7Ozs/+zs7P/s7Oz/6+zr/+zs7P/r6+v/7Ozs/+zs7P/s7Oz/7Ozs/+3s7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zt7P/t7Oz/7e3t/+3s7f/t7e3/7e3t/+3t7f/t7e3/7e7t/+3t7f/u7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/u7u7/7e7t/+7u7v/s7Oz/7Ozs/+zs7P/s7O3/7Ozs/+3t7f/t7e3/7e3t/+zs7P/t7ez/7O3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+7u7v/u7u7/7u7u/+7u7v/t7e7/7u7u/+3t7v/u7u7/7u7u/+7u7v/u7u7/7u/u/O7u7szu7u7/7u7u/+7u7snu7u6N7u7v/+7u7//v7+//7u7u/+7u7v/u7u7/7u7u/+7v7//v7+//7+/v/+/v70jv7+8D7+/v/+/v7/Dv7+8A7/DvAPDv8Jnw7/AY8PDw/+/v7//v7+//7+/v/+/v7//w8O/z8PDw//Dw8P/w8PD/7u7u/+/v7v/v7+7/7+/v/+/v7//v7+//7+/v/+/v7//v7u//7+/v/+/v7//v7+//7+/v//Dv7//v7+//7/Dv/+/v7//w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8O/v//Dw8P/w8PD/8PDw//Dw8P/w8fD/8PDx//Hw8QDw8PAA8PDwAPDw8ADw8fAA8fDwAPHx8QDx8PAA8fHxhPDw8Anw8fD/8PHxyfDw8ADx8fEA8fHxGPHx8QDx8fEA8fHxAPHx8QDx8fEA8fHxAPHx8QDy8vIA8vLyAPLy8gDx8fEA8fHxAPHx8QDy8vIA8vLyAPLy8gDy8vIA8vLy//Dw8P/x8fH/8PDw//Hx8eTx8fEw8fHx//Hx8eTx8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8QDx8fEA8vLyGPHx8QDy8vIA8vLyAPLy8gDy8vIA8vLyyfLy8gby8vL/8vLyhPLy8gDy8vIA8vLyAPLy8gDz8/MArKurG6yrqwCsrKuTrKur86urrP+rq6v/rKyr/6ysqwyrrKz2q6ysWqusq/+sq6v/q6ur/6urrP+rrKv/rKys/6usrP+rq6v/rKys/6ysrP+srKz/rK2t/6ytrP+srKz/q6ur/62srf+sq6v/rK2t/6ytrf+traz/rays/6ysrZmsq6z/q6usxqysrP+sq6z/rKys/6ysrP+sq6v/rKus6qyrrP+rq6v5rKur/6yrrP+rrKz/rK2s/6urrP+srKz/rK2s/6ysrP+sra3/ra2t/62trf+trKz/rays/6ytrP+tra3/ra2s/62trf+srKz/rayt/62trf+sraz/rays/6ysrP+trK3/rK2s/62trP+sraz/rayt/6ysrP+traz/rKys/62trf+sra3/rK2s/62trf+urq3/rKys/66trv+urq7/ra2u/62urf+tra7/rq2u/66trf+tra7/ra2u/62urf+trq7/rq2t/62trf+trq3/rq6u/62trv+ura7/rKys/62trP+tra3/ra2t/62urv+ura3/rq6t/62urf+srK3/ra2t/62trf+urq3/ra2t/62urf+ura3/ra6u/66urv+ura7/ra2u/66urf+urq7/ra6t/66urf+tra7/rq6t/62urf+ura7/rq2u/62urv+urq7/rq2u/6+vr/+urq7/ra6u/66trf+tra7/r66v/66ur/+vrq7/r66v/66urf+urq//ra6u/66urv+vrq//rq6v/6+vrv+vrq//rq+u/66ur/+ur67/rq6u/6+vrv+vsLD/rq+u/6+wsP+ur6//rq6u/6+vrv+vr6//r7Cv/7Cvr/+wsK//sK+w/66urv+ur67/rq6u/6+vrv+urq//rq6v/6+vrv+vrq7/rq+u/66vrv+vr67/rq+v/66urv+vr6//rq+v/6+ur/+vrq7/r6+w/66vr/+vr7D/sLCv/7CwsP+vsLD/r7Cw/7Cwr/+wsK//sLCw/6+vr/+vr7D/sK+w/7CvsP+vsLD/r7Cv/7CvsP+vr6//r7Cv/6+vsP+vsK//sLCw/6+wsP+vr7D/r6+v/6+vr/+vr6//sK+w/7CxsP+vsK//sbGx/7Cxsf+wsLD/sbCw/7Cxsf+wsbD/sbCx/7Gwsf+xsLD/sLCx/7Gxsf+xsLH/sbGx/7GxsP+xsLH/sLCx/7CwsP+vr6//r6+w/6+wr/+vsLD/r7Cv/7Cwsf+xsLD/sbCw/7CwsP+vsK//r6+w/7CwsP+wsLD/sLCw/7Cwsf+wsLH/sbCx/7Cxsf+wsLH/sbCw/7Gxsf+ysrL/sLCw/7Gysf+wsbH/sLGw/7GwsP+wsLH/srKx/7Kxsf+ysrH/sbKy/7Gxsf+ysbL/sLCx/7Gysf+xsrL/sbGy/7Kxsv+ysbH/sbGx/7Gxsv+ysbL/sbGy/7Gxsv+ysbH/sbKy/7Gxsf+ysbL/srGx/7Gysf+zsrL/s7Ky/7Oysv+ysrP/s7Kz/7Gxsf+ys7L/srKz/7Kzsv+ysrP/s7Oy/7Oys/+ysrL/srKx/7Gysv+ysbL/sbKy/7Gysv+ysbL/sbKy/7Kys/+xsbL/srGy/7Gysf+xsbL/sbGy/7Kysv+zs7L/srOy/7Oysv+ysrP/srKy/7Kys/+ys7L/srOy/7Oys/+ys7P/s7Ky/7Kzs/+zsrP/srKz/7Ozs/+0s7T/s7Kz/7Szs/+ys7L/srOy/7Oysv+zsrP/tLSz/7O0s/+0tLP/s7Sz/7Oys/+ztLP/srOz/7O0s/+0tLT/tLOz/7O0s/+zs7T/tLO0/7S0s/+ztLP/s7Oz/7S0s/+0tLT/tbS0/7W1tP+zs7P/tLSz/7Ozs/+1tLT/tLW0/7W0tf+0tbT/tLS0/7S0tP+0s7P/tLOz/7O0tP+zs7P/s7Sz/7S0tP+ztLT/tLSz/7Szs/+zs7T/tLS0/7OztP+0tLP/tLS0/7W0tf+zs7T/tLS1/7S0tP+0tLT/tLS1/7S0tf+0tbX/tbW0/7W0tf+0tLX/tbW0/7S0tf+0tLT/tbS1/7W0tf+2trb/tLS0/7S1tP+0tbX/tLW0/7S0tf+2trb/tba2/7W1tf+1tbX/tLS0/7S0tf+1tbb/tra1/7W2tv+2trX/tba2/7a2tf+1tbb/trW2/7W2tv+1trb/tre3/7a2tv+2t7f/tra1/7W2tf+1tbX/t7e3/7a2t/+2trf/t7e2/7e2t/+0tLX/tra2/7W1tv+2tbX/tbW1/7a1tv+1tbb/tba2/7a1tf+2trb/trW1/7W2tf+1tbb/tra1/7W2tf+3t7b/trW1/7e2tv+2t7b/t7a2/7e2t/+2trf/t7a2/7a2tv+2trb/tre2/7e3tv+2trb/t7a2/7e2tv+3t7f/t7i4/7a3tv+2t7b/t7e3/7a3tv+3trf/uLi3/7i3uP+4t7f/tra2/7a3tv+2t7f/t7e3/7e4uP+4t7j/t7i4/7i4t/+3t7f/uLi3/7e3t/+3t7j/uLe3/7m4uf+4ubj/uLm4/7i3t/+4t7j/t7e4/7m5uP+4uLj/ubm4/7i4uP+4ubj/tre3/7i3uP+3t7f/uLe3/7i3uP+4t7f/uLe3/7e3uP+3t7f/uLe3/7i3uP+4t7j/t7i4/7e3t/+4uLj/ubm5/7i3t/+5ubn/ubm4/7m4uP+5uLn/ubi4/7i5uf+4ubn/uLm4/7m4uP+5ubn/ubi4/7i4uP+5ubn/uLm5/7m5uf+4uLj/uLi5/7m4uf+4uLn/ubm5/7m5uf+5ubn/urm5/7i4uP+5ubn/uLi4/7m5uf+5ubn/ubq6/7m5uv+6ubr/urq5/7q5uv+5ubn/ubq5/7q6uv+6urv/urq6/7u6uv+5ubn/urq6/7m5uf+6urr/u7u6/7q6u/+7u7r/u7u6/7m5uf+5ubn/ubm5/7m6uf+5urr/ubm6/7q5uv+6ubn/ubm5/7q6uf+5ubn/ubq6/7m5uf+6urr/ubq5/7q6uv+6urr/u7q6/7q6uv+7u7v/u7u7/7u6u/+7u7v/u7u7/7q7uv+6u7v/u7u6/7q6uv+6urr/u7u7/7u7u/+8u7z/u7u7/7u7uv+7u7v/u7u7/7u7u/+7vLv/u7y8/7y7vP+6urr/u7u7/7u7u/+8u7v/vLu7/7y8u/+7vLv/u7u7/7y8u/+8vLz/vLu7/7y8vP+9vLz/vby9/729vP+8vbz/vLy8/7y9vP+8vLz/vby9/729vP+9vL3/vLy8/729vf+7u7v/vLu7/7u8vP+7vLz/vLu7/7y8vP+7vLz/vLy8/7u8vP+7u7z/u7y8/7u7u/+8vLz/vb28/7y8vP+8vL3/vby8/728vP+8vb3/vLy8/729vf+9vb3/vb29/769vv+9vL3/vL28/729vf+9vb3/vb29/769vv+9vr7/vr29/7y9vP+9vb3/vb29/76+vf+9vb3/vr2+/729vf+9vr7/vb29/72+vv+9vb7/vb6+/72+vf++vr7/vr29/76+vv++vr7/v76+/76+vv++v7//v7+//7+/v/+/vr7/v7+//76/vv+/vr7/vr++/7+/v/+/v77/v7+//7+/v/+/v8D/vb6+/72+vv+9vr7/vb69/76+vv+/v7//vr6+/76+vv+9vr3/vr6+/729vv++vr7/vr6+/7++vv++v77/vr6+/76/vv++vr7/v7+//7+/v/+/v7//v7/A/8C/v/+/wL//vr6+/7+/v/+/v7//v7/A/7/AwP+/v7//wMC//7/Av/+/v7//wL/A/7+/wP/AwL//v7+//8DAwP/AwL//wMDA/7+/v//AwL//v7+//8DAwP/AwMD/wMHA/8DAwP/BwcD/wMHA/8HAwP/BwcD/wMDA/8HBwf/BwcH/wcHB/8HCwv/BwcD/wcHB/8HAwf/BwcH/wcHB/8HBwv/CwsH/wcHB/7/AwP/AwMD/wMDA/8DAwP/AwcD/wMDB/8DBwf/AwMH/wMDA/8HBwP/AwMD/wcDB/8DBwf/BwcH/wMHA/8HBwf/BwcH/wcHB/8HBwf/CwsH/wsHC/8LBwv/CwsH/wsLC/8HBwf/BwcL/wcLC/8LBwf/BwcL/wsLC/8LCwv/DwsL/wsLB/8LBwf/CwsH/wsLC/8LCwv/CwsL/w8PD/8LDwv/BwcL/wsLC/8LCwv/Cw8L/wsPD/8LCwv/CwsP/w8PD/8LCw//Dw8P/w8PD/8PDw//Dw8T/w8PD/8PDxP/Ew8P/w8PD/8PEw//Dw8P/w8TD/8PDw//ExMT/xMPD/8TExP/CwsL/w8LC/8PCwv/CwsP/w8LC/8PDw//Dw8P/w8PD/8PDw//Cw8L/wsLD/8PDw//Dw8P/w8TD/8PDw//Dw8T/xMTE/8PDw//Ew8P/w8PE/8TExP/ExcX/xMTE/8XExP/Dw8P/xMTE/8TEw//ExMT/xcTE/8XExf/FxcT/xcXE/8TExP/FxMX/xMTE/8XFxP/ExcX/xcXF/8XFxP/FxcX/xMTF/8XExf/FxcT/xMTF/8XFxf/Fxsb/xcXF/8XFxf/FxcX/xcbG/8XGxf/Fxcb/xsXF/8bGxv/Gxsb/xsbG/8bFxv/Fxsb/xsbG/8bGxv/Gxsb/xsbG/8fGxv/Gxsb/xcTE/8XFxf/ExcT/xcXF/8bFxf/Fxsb/xsbF/8XFxf/FxcX/xsbG/8XFxf/Fxcb/xsbG/8XGxf/Gxcb/xsbG/8XFxf/Gxsb/xsbG/8bHx//Hx8b/xsbG/8fGx//Hx8f/xsbG/8fHxv/Gxsb/x8bG/8fGxv/Hx8f/x8fH/8fHx//Gxsf/xsbG/8fHx//Hx8f/x8fH/8jIx//Ix8f/x8jH/8fHx//Hx8f/x8fH/8jHyP/IyMf/yMfH/8fHyP/IyMj/x8jH/8jIyP/IyMj/yMjI/8jIyf/IyMj/yMjJ/8nIyP/IyMj/ycnJ/8nJyP/Iycn/yMnI/8nJyf/IyMn/ycnJ/8fHx//IyMj/x8fI/8jIx//HyMf/yMjI/8jIyP/Jycj/x8fI/8fIyP/HyMj/yMjI/8jIyP/IyMn/yMnI/8jJyP/IyMj/ycnJ/8jIyf/Iycn/ycnJ/8nKyf/Jycn/ysnJ/8nJyf/Jycn/yMnJ/8nJyf/Jycr/ysnK/8rJyv/Jysr/ycnJ/8nJyv/Jycn/ysrJ/8nJyv/Kysr/ysrJ/8rKyv/Jycn/ycrJ/8nJyv/Kycr/ysrK/8vLyv/Kysr/ysvL/8vLyv/Ky8r/y8rL/8rLy//Ly8v/y8vM/8vLy//Ly8z/ysrK/8vLy//Kysr/y8vL/8zLzP/Ly8v/zMzM/8zMy//Kycn/ysrK/8rKyf/Kysr/ysrK/8vKyv/Lysv/y8vK/8rKyv/Ly8r/ysrK/8vLy//Lysr/y8vL/8vKyv/Ly8v/y8vL/8zLy//Ly8v/y8vM/8zLzP/MzMz/zMzM/8zMzP/LzMv/y8vL/8vLy//LzMz/zMzM/83Mzf/MzMz/zM3M/8vLy//MzMz/y8zL/8zMzP/Mzcz/zczM/8zMzP/MzMz/zMzM/83MzP/MzMz/zMzN/8zNzP/NzM3/zMzM/83Nzf/Nzc3/zc3N/83Nzf/Nzc7/zs3O/87Ozv/Ozc3/zs7O/83Nzf/Ozs7/zc3O/83Ozf/Nzc3/zs7O/87Ozv/Pzs7/zMzM/8zMzP/Nzc3/zc3M/83NzP/Nzc3/zc3N/83Ozf/NzM3/zc3M/8zMzP/Nzc3/zc3N/87Ozv/Ozs3/zc7O/87Ozv/Nzs3/zc7N/87Ozv/Ozs7/z87P/87Pzv/Oz8//zc3N/87Ozv/Ozs7/zs/O/87Pzv/Ozs7/zs7P/8/Pz//Ozs7/zs7O/8/Oz//Ozs//zs7O/8/Pz//Pz8//0M/P/87Oz//Pzs//z8/O/8/Pz//Pz8//z8/P/9DPz//Q0M//z8/Q/8/P0P/P0ND/0NDQ/9DQ0P/Q0NH/0dHR/9DR0P/Qz8//0NDQ/9DQ0P/Q0ND/0NDR/9DQ0f/Q0dH/0dHR/8/Ozv/Pz8//z8/P/8/Qz//P0M//0NDQ/8/P0P/Q0ND/z8/P/9DQz//Pz9D/z9DQ/9DP0P/Q0ND/0NDQ/9DR0f/Q0ND/0NDR/9DQ0P/Q0dD/0NDQ/9HR0f/R0dH/0dLR/9DR0P/R0ND/0dHQ/9HR0f/R0dH/0dHS/9LS0f/R0dH/0NDR/9HR0f/R0dH/0dLS/9LR0v/R0dL/0dLR/9LS0v/R0dH/0tLS/9LS0f/R0dH/0dLS/9LS0v/S0tL/0tLT/9LS0v/T0tP/09LT/9PS0v/S0tP/09PT/9PT0//T09T/0tLS/9PT0v/T09L/09PT/9PT0//T09P/09PT/9TU1P/S0dH/0dHR/9HR0v/S0tL/0tLS/9PT0//T09L/0tPS/9LS0f/S0tL/0tLS/9LS0v/T0tP/0tLS/9PS0v/T09P/0tLS/9PT0//T09P/09PT/9PU1P/U09T/09TU/9TU1P/T09P/1NPT/9TU0//T1NP/09PT/9TU1P/U1NT/1dTU/9TT0//T1NP/1NPU/9TU1P/U1NT/1NXV/9TU1f/V1NT/09TT/9TU1P/U1NT/1NTV/9XU1f/U1NT/1NTV/9XV1f/V1dX/1dXV/9XV1f/V1dX/1dXV/9XW1v/V1db/1tbW/9XV1f/V1dX/1dXV/9XV1f/W1dX/1tbW/9bW1v/W1tb/1NTU/9XU1P/V1NT/1NTU/9TV1P/V1dX/1dXV/9XV1f/U1NX/1NXV/9TV1P/V1dX/1dXV/9XV1f/V1dX/1dbW/9XV1f/V1tX/1dXW/9bW1v/W1tb/1tbW/9bW1v/X1tf/1dXV/9bW1v/W1tb/1tbW/9bW1v/X1tb/1tbX/9fX1//W1tb/1tbW/9bW1v/W1tf/1tfW/9fX1//X19f/19fX/9bW1v/W1tf/1tfW/9fX1//X19f/19fX/9fX1//Y19f/19fX/9fX1//X19j/2NjY/9jY2P/Y2Nj/2NjY/9nZ2P/X2Nf/2NjY/9jY2P/Y2Nj/2NjY/9nY2f/Z2Nj/2dnZ/9fW1v/X19f/19fX/9fX1//X19f/19fX/9jY1//Y2Nj/19fX/9fX1//X19f/19fY/9fY1//Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9jY2P/Z2Nn/2djZ/9nZ2f/Z2dn/2dnZ/9jY2P/Y2dn/2djY/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2NnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dr/2dnZ/9ra2v/Z2dn/2dnZ/9nZ2f/Z2tr/2tna/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9va2v/a2tr/29vb/9vb2//b29v/2tra/9rb2//a2tr/29vb/9vb2//b29v/29vb/9vb2//Z2dn/2dnZ/9nZ2f/a2tr/2tra/9ra2v/a2tr/2tvb/9ra2f/a2tr/2dna/9ra2v/a2tr/2tra/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b3Nv/29vb/9zb2//b29v/29vb/9vb2//b29v/3Nzc/9zc3P/c3Nz/3Nzc/9vb2//b29z/29vb/9zb2//c3Nz/3Nzc/9zc3P/c3Nz/29vc/9zc3P/b29v/3Nzc/9zc3P/d3Nz/3Nzc/93d3f/c3dz/3d3d/9zc3P/d3d3/3d3d/97d3f/d3d3/3t3e/93d3f/d3d3/3d3d/93d3f/d3t3/3t7e/93d3f/e3t7/3Nzc/9zc3P/c3Nz/3Nzc/93c3f/d3d3/3d3c/93d3f/c3Nz/3N3c/9zc3P/d3Nz/3d3d/93d3f/d3d3/3d3d/93d3f/e3d3/3d3d/97d3f/e3t7/3t7e/97e3v/e3t7/3d3d/97e3v/d3d7/3t7e/97e3v/e3t//3t7e/9/e3v/e3t7/3t7e/97e3v/e3t7/3t/e/9/f3//e3t7/39/f/97e3v/e39//3t7e/9/f3//f39//39/f/9/f3//f39//39/f/+Df4P/f39//4ODf/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/9/g4P/g4OD/4ODg/+Dg4P/g4OD/4OHh/9/f3v/f39//397e/9/f3//f39//4N/f/9/f3//g3+D/39/f/9/f3//f39//39/f/+Dg3//g4OD/4N/f/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4eHg/+Hh4f/g4eD/4eHh/+Dg4P/g4eD/4ODg/+Hh4P/g4OH/4eHh/+Hh4f/h4eH/4eDg/+Hh4f/g4eD/4eHh/+Hh4f/h4eH/4eHh/+Li4v/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4uH/4uLi/+Lh4f/i4uL/4uLi/+Li4v/i4uL/4uLi/+Pi4v/j4+P/4uLi/+Li4v/i4uL/4uLj/+Pi4v/j4+P/4+Pj/+Pj4//h4eH/4eHh/+Hh4f/i4eL/4eLh/+Li4v/i4uL/4uLi/+Hh4f/h4uH/4eLh/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pk4//i4uP/4+Pj/+Pj4//j4+P/4+Pj/+Tj5P/j4+T/5OTk/+Pj4//j4+P/4+Pj/+Pj4//j5OP/5OTk/+Tk5P/k5OT/4+Pj/+Pj4//j4+T/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5eXk/+Tk5P/l5OT/5eXl/+Xl5f/l5eX/5eXl/+Xk5P/l5eX/5eXk/+Xl5f/l5eX/5uXm/+Xl5f/l5uX/5OPj/+Tk5P/k5OT/5OTk/+Tk5P/l5eT/5OTk/+Xk5P/k5OT/5OTk/+Tk5P/k5OT/5OTl/+Xl5f/k5eT/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5ub/5ubm/+Xl5v/m5ub/5eXl/+Xl5v/l5eX/5uXm/+bm5v/m5ub/5ubm/+bm5v/l5uX/5ubm/+Xl5f/m5ub/5ubm/+bm5v/m5ub/5+bn/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ufm/+fn5//n5+f/5ubm/+fn5//n5+f/5+fn/+fn5//n6Oj/6Ofn/+jo6P/n5+f/5+fn/+fn5//n5+f/5+fo/+jo6P/o6Oj/6Ojo/+bm5v/m5ub/5ubm/+bn5v/m5ub/5+fn/+fn5//n5+f/5ubm/+bm5v/n5+b/5+fn/+fn5//n5+f/5+fn/+fo6P/n5+f/6Ofo/+fo5//o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo5//o6Oj/6Ojo/+jo6P/o6Oj/6ejo/+jo6P/o6en/6Ojo/+jo6P/o6Oj/6Ojo/+jp6P/p6en/6Ojp/+np6f/o6Oj/6ejp/+jo6P/p6Oj/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+rp6f/p6un/6urq/+rq6v/q6ur/6unp/+rp6v/q6un/6urq/+rq6v/q6ur/6urq/+vq6//p6ej/6enp/+np6f/p6en/6enp/+nq6f/p6en/6unp/+np6f/p6en/6enp/+np6f/p6er/6erq/+np6f/q6ur/6urp/+rq6v/q6ur/6urq/+rq6v/r6+r/6+rq/+vr6//q6ur/6urq/+rq6v/r6ur/6urr/+vr6//r6+v/6+vr/+rq6v/q6ur/6+vq/+vr6//r6+v/6+vr/+vr6//r6+v/6urq/+vr6//r6+v/6+vr/+vr6//r7Oz/6+vr/+zs7P/r6+v/7Ozs/+vr6//s7Oz/7Ozs/+zs7P/s7Oz/7e3s/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7O3s/+3s7P/t7e3/6+vr/+vr6//r6+v/6+vr/+vr7P/s7Oz/6+vr/+zs7P/r6+v/6+vs/+vr6//r7Ov/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zt7f/t7ez/7e3t/+3t7f/t7e3/7Ozs/+3s7P/s7ez/7e3t/+3t7f/t7e3/7e3t/+3t7f/s7O3/7e3t/+3t7f/t7e3/7e3t/+3t7v/t7e3/7u7t/+3t7f/t7e3/7e3t/+3t7f/u7u3/7u7u/+7t7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7+7/7+7v/+/v7//u7u7/7u7u/+7u7v/u7+7/7u/v/+/v7//v7+//7+/v/+3t7f/t7u3/7e3t/+3t7f/u7u7/7u7u/+7u7v/u7u7/7e3u/+7u7v/t7e7/7u7u/+7u7v/u7u7/7u7u/+/v7//u7u7/7u/u/+/v7v/v7+//7+/v/+/v7//v7+//7+/v/+7v7v/v7+//7+/v/+/v7//v7+//8PDw/+/v7//v8O//7+/v/+/v7//v7+//7+/v/+/v7//w7+//7/Dv//Dw8P/v7+//7+/w/+/v7//v8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Hx8f/x8PH/8fHx//Dw8P/x8fH/8PDw//Dw8f/w8PD/8fHx//Hx8f/x8fH/8fHx//Hx8f/v8PD/8PDw/+/v8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dv7//w8PD/8PDw//Dw8P/w8PD/8fDw//Dw8P/x8PD/8PDw//Hx8f/w8PD/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vLz8vLy//Ly8v/y8vIb8vLyAPPz85Pz8/MA8/Pz//Ly8v/y8vL/8vLy//Pz8/bz8/MM8/Pz//Pz81rz8/P/8fHx//Ly8v/x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8/Pz//Ly8v/z8/P/8/Pz//Pz8//z8/OZ8/Pz//Pz88bz8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8+rz8/P/8/Pz+fT09P+rrKv/rKys/6urq/+rq6z/rays/62trf+traz/ra2t/6usrP+trKz/rKus/6ytrP+sra3/rK2t/6ytrf+sra3/rKyt/6ytrf+traz/rayt/62srP+srKz/rK2t/6ysrP+traz/rK2t/6ysrf+trK3/rKys/6ysrf+trKz/rq6u/6ytrf+traz/rayt/6ysrP+traz/rays/6ytrP+trK3/rKys/6ysrP+trKz/rays/6ytrf+srKz/rays/62trP+trK3/rKyt/6ytrf+trK3/rKyt/62urf+tra7/ra6t/62trP+srKz/rK2s/62trf+urq3/ra2t/62urv+urq3/rays/66trf+trq3/rq2t/62urv+urq3/ra2t/62trv+urq7/ra2u/66trv+tra3/ra6t/66trv+tra3/rq2u/66urf+ura7/rq6u/66urf+vrq7/r6+u/6+vrv+vrq7/rq2u/66vrv+trq7/rq6u/6+vr/+ur67/rq6u/6+vrv+trq7/rq2u/62trf+ura7/ra2u/62urf+tra3/rq2t/66urv+tra3/ra6t/62trf+trq7/rq+u/66trf+vrq7/rq6v/66ur/+vr67/rq+v/6+urv+urq7/rq+u/66vrv+vrq//r66u/6+ur/+urq//rq+v/6+urv+vrq7/r6+v/66urv+urq7/r66u/66vrv+ur67/sLCv/66urv+vsLD/rq+u/66ur/+vrq//rq6v/66urv+wr7D/r6+v/7Cwr/+wsLD/r7Cv/7CwsP+vr6//sK+w/7CwsP+wsLD/sLCw/7Cwr/+vr6//sK+w/7CvsP+wr7D/r7Cv/6+wr/+xsbD/rq+u/66vrv+urq7/r6+w/6+wr/+vsK//r6+w/7CvsP+vr67/r6+v/6+vsP+vsK//r6+v/6+vr/+wr6//r7Cw/6+vr/+vr6//r7Cv/6+vsP+vsLD/sbCw/7CwsP+xsLH/sLCw/7Cvr/+vr6//sLCx/7Gxsf+xsbD/sLCx/7GxsP+wsLD/sLGx/7CxsP+xsbD/sbGw/7Gxsf+xsbH/sLCw/7GxsP+wsbD/sLCx/7GxsP+wsbH/sbGw/7GwsP+wsLH/sLCx/7Gxsf+xsLD/sbGy/7Kysv+xsrH/sbKx/7Kysf+ysbL/srGx/7Kxsf+ysbH/srGx/7Gysf+ysrH/sbKy/7Cwsf+xsLH/sLCw/7CxsP+xsbD/srKy/7GwsP+xsbH/sbCx/7Cwsf+xsbH/sLCw/7Kxsf+ysbL/sbKy/7Kysf+ysbH/sbGy/7Gxsv+xsbL/sbKx/7Gysf+xsbL/s7Kz/7Kxsv+ysbL/srGx/7Kxsv+xsrL/srKy/7Oys/+ys7P/srGy/7Kysv+xsbL/srOz/7Oys/+ysrL/srOy/7Ozs/+ysbL/srOz/7Oysv+ys7L/srOy/7Kys/+ysrL/s7Oy/7Oysv+ysrL/s7Ky/7Kzsv+zs7P/s7S0/7O0s/+zs7T/s7Oy/7O0s/+ysrL/tLOz/7OztP+ztLT/s7Sz/7O0s/+zs7P/srKz/7Kysv+ysrL/s7Oz/7Oysv+ys7P/s7Ky/7Oysv+ysrP/s7Oz/7Kzsv+ys7L/tLOz/7Kzs/+ztLP/tLS0/7S0s/+0tLP/tLS0/7Ozs/+ztLP/tLS0/7S0s/+0s7P/tLS0/7OztP+ztLT/s7O0/7Ozs/+0tLP/tbW0/7OztP+0tLT/s7O0/7S0s/+0s7T/tLS1/7W0tf+1tbX/tLO0/7Szs/+ztLT/tLW0/7S1tP+1tLX/tLS0/7S1tP+0tLT/tbW1/7W1tf+1tbT/tLS0/7a2tv+1tbX/tba2/7W0tP+1tLT/tbS0/7a1tv+1trX/tba2/7W1tv+1trX/s7S0/7W1tf+0tLT/tbS1/7W0tP+0tbT/tLS0/7W1tP+0tLX/tLS0/7W1tP+0tLT/tLW0/7S0tf+0tLX/tba1/7S0tP+1tbb/trW1/7a2tf+2trX/trW1/7a2tf+1trX/trW1/7W1tf+2tbb/tbW2/7W2tf+1trX/tba2/7a3tv+2tbX/tra2/7a1tf+1tbX/tba1/7a2tv+2trb/tra3/7W1tf+1tbb/tbW1/7a2t/+3trb/tra2/7a2t/+2t7f/t7e2/7e3tv+3t7b/t7e2/7a3t/+3uLj/uLe3/7e3uP+3t7f/t7e3/7e3tv+4t7j/t7i4/7i4t/+4uLj/t7i4/7a2tf+3trb/tre2/7e2tv+3trf/tra3/7a2t/+2trb/t7e2/7e3tv+3t7b/t7a3/7a3t/+2trb/t7a2/7e3uP+2trb/t7e4/7i4t/+4uLj/uLe3/7i4uP+4t7f/uLe3/7i4t/+3t7j/t7e4/7e3t/+4uLf/t7i3/7e3t/+4ubn/uLe3/7e4t/+3uLj/t7e3/7e4uP+4ubn/uLm5/7m5uf+4uLf/t7e3/7e4uP+5uLj/ubi5/7i5uf+5uLj/ubi5/7m4uP+4uLj/uLm4/7m4uf+5ubn/ubm5/7m5uf+5urn/uLi5/7m5uf+4uLj/ubm5/7m5uf+5urr/urm5/7m6uf+4uLf/uLi5/7m4uf+4ubn/ubi5/7i4uP+5ubj/ubm4/7m5uf+4ubj/ubi4/7m4uP+5uLj/ubm5/7m4uP+5ubn/ubm5/7m5uf+5ubn/ubq5/7m5uf+5urn/urm5/7m5uf+5ubn/urm6/7q6uv+5ubn/ubm5/7q6uv+5ubn/urq6/7q5uf+5urn/ubq6/7q5uf+6urr/uru6/7q6uv+6u7r/ubq5/7q6uv+5urn/urq6/7u6uv+7urr/u7u6/7u7uv+6u7r/u7u6/7u6u/+7u7v/u7u7/7u8vP+8u7v/u7y8/7u6uv+7u7v/u7u7/7y8vP+8vLz/vLu8/7u7vP+8u7z/urq6/7q7u/+6urr/uru6/7u6uv+6urv/uru6/7u7u/+7u7v/uru7/7q6uv+6u7v/uru7/7u7u/+7u7v/u7y8/7u7u/+7vLz/vLu7/7y8vP+7vLv/vLy8/7y7vP+8vLz/u7u8/7y8vP+7u7v/u7y7/7y8vP+8vL3/vLy8/7y9vf+8vLv/vLy8/7u7u/+8vLz/vby8/7y8vf+9vL3/vL28/7y8vP+8vL3/vLy8/7y8vf+9vLz/vby8/7y8vP+9vb3/vLy9/729vf+9vb3/vb29/729vv++vr7/vr29/729vv+9vb3/vb2+/72+vf++vr3/vb2+/76+vv+9vr3/vr6+/7y9vP+9vb3/vLy8/7y8vP+9vLz/vb29/729vf++vb3/vLy8/7y9vP+8vb3/vb29/729vf++vr7/vb29/72+vv+9vb7/vb69/769vf+9vr3/vr6+/76+v/++vr7/vr6+/729vv++vr7/vr29/76+vv+/vr//v7+//76+v/++vr7/vr6+/7+/v/++vr7/v76//7+/vv+/vr7/v76+/7+/v/++vr//vr++/7++vv+/v7//vr6+/7+/v/+/v7//wMDA/7+/v/+/v7//wL+//8DAwP+/v7//wMDA/7+/wP/AwMD/wL+//8DAwP/Av7//v8C//8DAwP/BwcD/wMDA/8DBwf++v77/vr6+/7++v/+/v7//v7+//7/AwP+/wL//wL/A/7+/vv+/v7//v7+//8C/v//Av7//v7/A/8C/wP+/v8D/wL/A/8DAwP/AwL//wMDA/8DBwP/AwMH/wcDA/8DAwf/AwMD/wMHB/8DAwP/BwcD/wcHA/8HBwf/AwcD/wcHB/8DBwP/BwMD/wcDB/8DAwP/BwcH/wcHB/8HBwf/BwsH/wMDA/8HBwf/BwMH/wcHB/8HBwf/BwcH/wcLB/8LBwv/BwcH/wsHC/8HCwf/CwsL/wsLC/8LDw//Dw8P/w8LC/8HCwf/CwsL/wsLC/8PCwv/CwsP/wsPD/8PCw//Dw8P/wcHB/8HBwf/BwcH/wcHB/8HCwv/CwsH/wcHB/8LCwv/BwcH/wcLC/8LBwv/CwsH/wsHC/8LCwv/CwsL/w8PC/8LCwv/Cw8L/wsLC/8LCwv/Dw8L/w8PD/8PDw//Dw8P/w8PD/8PCwv/DwsL/w8PD/8PDw//ExMP/w8PD/8PDxP/DwsP/w8PD/8PDw//Dw8P/xMPD/8TExP/Dw8P/w8PD/8PDw//Dw8P/w8PD/8PExP/Ew8T/xMTE/8TExP/ExMT/xMTE/8TExP/ExMT/xcXE/8XFxP/FxcX/xcTE/8XFxf/FxMT/xMTF/8XFxP/FxcT/xcXF/8XFxf/FxcX/xsXF/8TDxP/DxMT/w8TE/8PDxP/ExMT/xMXE/8TExP/FxcX/xMPE/8TExP/Dw8T/xMTE/8TExf/ExMT/xMXE/8TExP/ExMX/xcTF/8XFxP/FxcX/xcXF/8bFxv/Fxsb/xsXG/8TExP/FxcX/xcXF/8XGxv/Gxsb/xsXG/8XFxf/Gxsb/xcXF/8bFxf/Gxsb/xcbG/8XGxv/Gxsb/xsbG/8fHxv/FxsX/xcbG/8XFxf/Gxsb/xsbG/8bGxv/Hxsb/xsbG/8fGx//Gxsf/x8bG/8fHx//Hx8f/yMjH/8fIx//Hx8j/xsbG/8fHx//Hx8f/yMjI/8fHyP/HyMf/yMfI/8jIyP/GxsX/xsbG/8bGxv/Gx8b/x8bH/8bHx//Gx8b/x8fH/8bGxv/Gxsf/xsfH/8bHx//Hx8b/x8fH/8fHx//HyMj/x8fH/8fIx//Hx8f/yMjH/8fHyP/IyMj/yMfI/8jIyP/Ix8j/yMfH/8fHx//Ix8f/yMjI/8jJyf/IyMj/ycjJ/8fHyP/IyMj/yMjI/8jIyP/Iycj/ycjI/8jIyP/IyMn/yMjI/8jJyP/IyMj/ycnI/8nJyf/Jycn/ycnJ/8nJyf/Jycn/ysrK/8nJyf/Jycn/ysnK/8rKyv/Jycn/ysrK/8nJyv/Kysr/ysnK/8nJyv/Kysr/ysvL/8rKyv/Lysr/ycnI/8nJyf/Jycj/ycnI/8nJyf/Jycn/ycnJ/8rKyf/Iycj/ycnJ/8jIyP/Jycn/ycrJ/8nKyf/Kysn/ycrJ/8rJyf/Kysr/ycnK/8rKyv/Kysv/ysrL/8rKyv/Ky8v/ysrK/8vKy//Kysr/ysvK/8rKyv/Ly8v/y8rK/8vLy//Ly8r/ysvK/8vKy//Lysr/y8vL/8zLzP/Ly8v/zMvL/8rKy//Ly8v/ysrK/8vLy//Ly8z/y8zM/8zLy//Ly8z/y8zM/8zMzP/MzMv/zMzM/8zMzf/MzMz/zc3N/8zMzf/MzMz/zMzM/8zMzP/Mzcz/zczN/83Mzf/Nzcz/zc3N/8vLy//LzMz/y8vL/8vLzP/Ly8v/zMzM/8zMy//MzMz/y8zL/8vMy//LzMv/y8vM/8zMzP/MzMz/zMzM/8zMzf/Mzcz/zM3N/8zNzf/Mzcz/zMzM/83Nzf/Nzc3/zc7O/8zNzP/MzMz/zc3M/83Nzf/Nzc3/zc3O/87Nzf/Nzc7/zczM/83Nzf/Nzc3/zc7N/83Nzf/Nzc7/zc3O/87Ozv/Nzc3/zc3N/87Ozf/Ozs7/zs3N/87Ozv/Ozs7/zs7P/87Ozv/Pz8//zs7O/87Pzv/Pzs7/z8/P/8/Pz//Qz9D/z8/O/8/Oz//Ozs//z8/P/8/Pz//P0ND/z8/P/9DP0P/Ozc7/zc3N/87Ozf/Ozs7/zs7O/87Ozv/Ozs//zs/O/87Ozv/Ozs7/zs7O/87Oz//Pzs7/zs7P/87Pz//Pz8//z8/P/8/Pz//Pz8//0M/Q/8/P0P/Pz8//z9DP/9DQ0P/Pz8//0NDQ/8/P0P/P0M//0M/Q/9DQ0P/Q0ND/0dDQ/8/P0P/Pz8//0M/P/9DQ0P/Q0ND/0NDR/9DQ0f/R0dD/z9DQ/9DQ0P/Q0ND/0dHR/9DQ0P/Q0ND/0NHQ/9HR0f/R0ND/0dHR/9HR0f/R0dH/0tHR/9LS0f/S0dL/0tLS/9HR0f/S0dL/0tHS/9LS0f/R0tL/0tLS/9LS0v/T09P/0NDQ/9HR0P/R0ND/0NDR/9DR0P/R0dH/0dHR/9LS0v/Q0ND/0NHQ/9DQ0f/R0dH/0dHR/9HS0v/S0dH/0tLS/9LS0f/R0dL/0tHS/9LS0v/S0tL/0tLT/9PS0//T09P/0tHS/9LS0v/S0tL/09PS/9PS0v/T0tL/0tLT/9PT0//S0tL/0tLT/9LT0v/T09L/0tLS/9PT0//T09P/09PU/9LS0v/S09L/0tPS/9PT0//T09P/09TT/9PT0//T09T/1NPT/9TU0//T09T/1NTU/9TU1P/U1dX/1dTV/9XV1P/U09T/1NTU/9TU1P/V1NX/1NXU/9TU1P/U1NT/1dXV/9LT0//T09P/09PT/9PT1P/U1NT/1NPT/9PT1P/U1NT/09PT/9TT1P/U1NP/1NTT/9PT0//U1NT/1NTU/9XU1P/U1NT/1dTU/9TV1f/U1NT/1NTV/9XV1f/V1dX/1dXV/9TU1P/V1NT/1NTU/9XV1f/V1dX/1dXV/9XV1f/V1tX/1NTU/9XV1f/V1dX/1dXV/9XV1f/W1db/1dbW/9bW1v/V1dX/1dXV/9XV1f/W1dX/1tXW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/X19f/19fX/9fX1//X19f/1tbW/9bW1//X1tb/19fX/9fX1//X19f/19fX/9fY1//V1dX/1dbW/9bV1f/W1tb/1tbW/9bW1v/W1tb/19bX/9bV1f/W1tb/1tbW/9bW1v/W1tb/1tbW/9bX1v/X19f/1tbX/9fX1//X19f/19fX/9fX1//Y2Nj/2NjX/9jY2P/X19f/19fX/9fX1//X19j/2NjX/9jY2P/Y2Nj/2NjY/9fX1//X19j/19jX/9jY2P/Y2Nj/2NjY/9jY2P/Z2Nn/2NjX/9jY2P/Y2Nj/2NjY/9jY2P/Z2dj/2NjY/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/a2tn/2trZ/9nZ2f/Z2dn/2dnZ/9na2v/Z2dn/2tra/9nZ2f/a2tr/2NjY/9jY2P/Y2Nj/2NjY/9jY2P/Z2dn/2dnZ/9nZ2f/Y2Nj/2NjZ/9jZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2tn/2dnZ/9ra2v/a2tr/2tra/9ra2v/b2tr/2dra/9ra2v/a2tn/2tra/9ra2v/a29r/2tra/9vb2v/a2tr/2tra/9ra2v/a29r/2tvb/9vb2//b29v/29vb/9ra2v/a29v/29ra/9va2//b29v/29vb/9vb2//b29v/29vb/9vb3P/b29v/29zc/9zc3P/c3Nz/3Nzc/9zc3P/c29z/3Nzc/9vc2//c3Nz/3Nzc/9zd3P/c3Nz/3Nzd/9va2v/b29v/29rb/9vb2//b29v/3Nzb/9vb2//b29v/29vb/9vb2//b29v/29vb/9zc2//c3Nz/29vc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3dzd/93d3f/c3d3/3d3d/9zc3P/c3N3/3Nzc/9zc3f/d3d3/3d3d/93d3f/d3d3/3N3d/93d3f/d3dz/3d3d/93d3f/e3d7/3d3d/93e3v/d3d3/3d3d/93d3f/d3d3/3t7d/97e3v/e3d7/3t7e/97e3v/e3t7/3t7e/97e3v/f3t7/39/f/9/e3v/f39//3t7e/9/e3//e3t7/3t/e/9/f3//f39//39/f/9/f3//d3d3/3d3e/93d3f/e3d3/3t7e/97e3v/e3t7/3t7e/93e3v/e3t7/3d7d/97e3v/e3t7/39/e/97e3v/f3t//39/e/9/f3//e39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/+Dg4P/g3+D/4ODg/9/f3//f4OD/39/f/9/f3//g4OD/4ODg/+Dg4P/g4OD/39/g/+Dg4P/f39//4ODg/+Dg4P/g4OD/4ODg/+Dg4f/g4eH/4ODh/+Hg4P/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eLh/+Hh4f/i4uL/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OH/4OHg/+Hh4f/g4OD/4ODg/+Dg4P/g4eH/4OHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4uL/4uLi/+Li4v/i4uL/4eHh/+Lh4f/i4uL/4uLi/+Li4v/i4uL/4uLi/+Lj4//h4eH/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4+Pj/+Li4v/i4uL/4uLi/+Lj4//i4+L/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pk/+Pj5P/k5OT/5OTk/+Tk5P/j4+P/4+Pj/+Tj5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Li4v/i4uP/4uLi/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4uLi/+Pj4//j4+P/4+Pj/+Pj4//k5OP/4+Pj/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Xl5P/k5OT/5eXk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5eXl/+Xl5f/l5eX/5OTk/+Tl5f/k5OT/5eXk/+Xl5f/l5eX/5eXl/+Xl5f/l5OX/5eXl/+Tk5f/l5eX/5eXl/+Xm5f/l5eX/5ebl/+bm5v/m5ub/5ubl/+bm5v/m5ub/5ubm/+bm5v/m5uf/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+fn5//l5eX/5eXl/+Xl5f/l5eX/5ebm/+bm5v/m5uX/5ubm/+Xl5f/l5eX/5eXl/+Xl5f/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubn/+fn5v/n5+f/5+fn/+fn5//m5ub/5ubm/+fm5//n5+f/5+fn/+fn5//n5+f/5+fn/+fm5v/n5+f/5+fn/+fn5//n5+f/6Ojn/+jn6P/o6Oj/5+fn/+fn5//n5+f/6Ofn/+fo5//o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6ejp/+np6f/o6Oj/6enp/+jo6P/p6Oj/6Ojo/+no6P/p6en/6enp/+np6f/p6en/5+fn/+jo6P/n5+f/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/n6Of/6Ojo/+jo6P/o6Oj/6Ojo/+no6P/o6Oj/6Ojo/+jp6f/p6en/6Ojo/+np6f/p6en/6unp/+np6f/p6er/6enp/+np6f/p6en/6enp/+nq6f/q6ur/6unq/+rq6v/p6en/6erp/+np6f/q6un/6erq/+rq6v/q6ur/6urq/+np6f/p6en/6enq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rr6//r6uv/6+vr/+vr6//r6+v/6+vr/+vr6//q6uv/6+vr/+vr6//r6+v/6+vr/+vs6//r6+v/6+zs/+np6v/q6ur/6urq/+rq6v/q6ur/6+rq/+vr6v/r6+v/6urq/+rq6v/q6ur/6+vr/+rr6v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+zr/+zs7P/r6+z/7Ozs/+vr6//s6+v/6+vr/+vs7P/s7Oz/7Ozs/+zs7P/s7Oz/6+vr/+zs7P/s6+z/7Ozs/+zs7P/s7Oz/7Ozs/+3s7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+3s7P/t7ez/7e3t/+3s7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/u7u7/7e3t/+3t7f/t7e3/7e3t/+3u7v/u7u7/7e3t/+7u7v/s7Oz/7Ozs/+zs7P/s7ez/7e3t/+3t7f/t7e3/7e3t/+zs7P/s7ez/7ezs/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3u7v/t7e3/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7e3/7u7u/+7u7f/u7u7/7u7u/+7u7v/u7u7/7u/v/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+/u7v/v7+//7u7u/+7u7v/u7u7/7u/v/+7v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7/Dv/+/v7//v8O//8PDw/+/v7//v8O//7+/v/+/v7//w8PD/8PDw//Dw8P/w8PD/7u7u/+/v7v/u7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+7/7+/v/+/v7//v7+//7+/v/+/w7//v7+//8O/v/+/v8P/v8O//8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/7+/v//Dw8P/w8PD/8PDw//Dw8P/x8PD/8PDw//Dx8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Hx8f/x8PD/8fHx//Dw8P/w8PH/8PDw//Dw8P/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/y8vL/8fHx//Ly8v/x8fH/8fHx//Hx8f/x8fH/8vLy//Ly8v/y8vL/8vLy//Hw8f/x8fH/8fDw//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9PT0//T09P/09PT/8/Pz//Pz8//z8/P/9PT0//T09P/09PT/9PT0//T09P/y8vL/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//09PT/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1/62srf+srKz/rKys/62trP+sra3/rK2s/6ytrP+trKz/rays/62trP+srKz/rK2s/6ysrP+tra3/rK2s/66trf+trK3/rq2t/62trv+urq7/rq6u/62trf+ura3/ra6u/62trf+tra3/rq6t/62urv+ura7/rq2t/66urv+urq7/rKys/6ytrP+srKz/rK2s/6ytrP+trq3/ra2t/66trv+tra3/rK2s/6ytrf+ura7/ra6t/66trf+trq3/rq6t/66urv+tra3/ra6u/66trf+trq7/ra2t/62urv+tra7/rq6t/66urv+tra3/ra6u/66urv+vrq7/ra6u/6+urv+ura3/rq2t/62urf+tra3/rq6v/6+vr/+ur6//r6+u/62trf+vrq//rq2u/6+urv+vrq//rq6u/66urv+ur67/rq+u/66vr/+urq7/rq6v/6+vr/+urq//rq6v/6+wr/+vr6//rq6u/6+vr/+vrq//rq+u/7CvsP+vsK//sK+w/66vrv+vr6//rq6v/66vrv+vrq7/r66v/66ur/+vrq//rq6u/6+vr/+urq7/rq6u/66urv+vrq7/rq+v/66vrv+vrq//r66u/6+urv+vr7D/r7Cw/7Cwr/+wr7D/r7Cw/6+urv+vr7D/sK+v/7Cvr/+wsK//sK+v/6+wr/+vsK//r6+w/6+vr/+vsLD/r7Cw/6+wsP+vr6//r6+v/6+wr/+wsLD/r7Cv/6+vr/+vsK//sK+w/6+vr/+vsLD/sLCw/6+vr/+wsbD/sLGx/7Gwsf+wsbD/sLGx/7GxsP+wsLH/sK+v/7Cwsf+wsK//sbGw/7CxsP+xsLD/sbCx/7CxsP+vr7D/r7Cv/6+vsP+wr6//r7Cw/7GxsP+xsLH/sbCw/6+wsP+vr7D/r7Cw/7Gxsf+xsLH/sLCx/7GxsP+wsLD/sLGx/7Gwsf+wsbH/sLGx/7Gwsf+ysrH/sbGw/7Kysf+xsLH/sLCw/7CxsP+xsLD/sbKx/7Gysf+xsrL/sbKy/7CwsP+xsrL/sLCx/7Kysv+ysrL/srGx/7Gxsv+ysbH/sbGy/7Gxsv+xsbH/srGy/7Gxsf+xsbH/srKx/7Kysf+xsbH/srKy/7Gxsf+zsrL/srKy/7Kysv+ysrL/srKz/7Kxsv+zsrL/s7Ky/7Ozs/+zsrP/srKy/7Oysv+ys7P/sbKx/7Gxsf+xsrH/sbGy/7Kysf+xsbH/sbKx/7Kys/+xsbH/sbKx/7Gxsv+ysrH/sbGx/7Kysv+zs7L/s7Ky/7Oys/+ysrL/s7Kz/7Oys/+zsrL/s7Oy/7Ozsv+zsrL/s7Oy/7Kzsv+ysrP/srOy/7Kzs/+zs7P/srKz/7O0s/+zsrP/srKy/7Oysv+ysrP/tLSz/7S0s/+0s7P/s7O0/7Ozs/+ztLT/s7Kz/7Szs/+zs7T/tLO0/7O0tP+0s7P/s7Oz/7Szs/+zs7T/tLS0/7S0tP+0tbT/tbW1/7S0tP+ztLP/s7Oz/7SztP+1tLT/tbW0/7S0tf+0tLT/tLW1/7O0tP+ztLP/tLSz/7O0s/+0s7P/s7Oz/7O0s/+zs7T/s7O0/7S0s/+zs7P/tLOz/7O0s/+zs7P/s7Oz/7W0tP+ztLP/tbW1/7W0tP+0tbX/tbW1/7W1tP+0tLT/tLW0/7S0tf+1tLX/tbS1/7W0tf+1tLT/tbW0/7S0tP+1trb/tLW1/7W1tP+1tbX/tLS1/7S0tf+1trb/tbW2/7W2tv+1tbX/tLS0/7S1tf+2trX/trW1/7a2tf+2tbb/tra1/7W1tf+2tbX/trW1/7a2tf+1tbX/tra3/7e3t/+2trb/tbW1/7W2tf+2tbX/t7a3/7e2t/+2trf/t7e2/7a2tv+1tbT/tba1/7a1tf+1trX/tbW1/7W2tf+1trX/tbW2/7a2tf+1trX/tbW2/7a1tv+1trb/tba2/7a1tf+2trb/tra2/7a2t/+2trf/tra2/7a3tv+3t7b/tra2/7a2tv+3trb/tra2/7a3t/+2trb/tra2/7a2tv+2trb/t7e3/7e2tv+2t7b/tre3/7a3tv+2t7b/t7i3/7e3t/+3t7f/tre3/7e3tv+2trf/t7e3/7e2tv+3t7f/tra2/7a3t/+3t7f/uLe4/7e4t/+3t7f/t7e3/7m5uf+3t7j/uLi4/7e3t/+3t7f/tra2/7i4uP+3t7j/t7i4/7i4uP+5uLj/t7e3/7a2tv+3t7f/tra2/7e2tv+2trf/tre2/7e4uP+3trf/t7e3/7i4t/+3uLj/t7e3/7i4t/+4uLj/ubm5/7e3t/+3uLj/uLi4/7m4uP+4ubn/ubm5/7m4uf+5ubn/uLi5/7m4uf+5uLj/uLi5/7m4uP+5ubn/uLi4/7m5uf+5uLj/ubi4/7i4uP+5uLj/ubm5/7m5uf+4uLj/urq6/7m5uP+5ubn/ubi5/7m5uf+5ubn/ubm5/7q5uf+6ubr/ubq5/7q6uf+6ubn/urm5/7q6uv+6urr/urq6/7u6uv+5ubr/urq6/7m6uv+6urr/uru7/7u6uv+6u7r/u7q7/7m5uf+5ubn/ubm5/7m5uv+5ubn/ubm5/7q6uv+6urr/ubm5/7q5uf+5ubn/ubm5/7m6uf+6urr/urm6/7q6uv+6urr/urq7/7q6uv+6u7v/u7q7/7q6uv+7urr/u7u7/7u6uv+7urv/urq6/7q6uv+6urr/u7u7/7u7u/+7u7v/urq7/7q6uv+6u7v/u7u7/7u7u/+8vLz/u7y7/7u8vP+7urv/u7u7/7u7u/+7u7z/u7y7/7u7u/+7u7v/u7y7/7u8vP+8vLz/vLy7/7y8vP+8vb3/vL29/7y9vf+8vL3/vLy8/7y8vP+8vLz/vLy8/7y9vf+8vbz/vby9/729vf+7u7v/vLy8/7u7u/+7u7z/u7y8/7y8vP+8vLv/vLy8/7u8u/+8vLv/vLy8/7u8vP+8vLz/vb29/7y8vP+8vLz/vb28/729vP+8vb3/vLy8/729vf+9vb3/vb29/729vf+8vL3/vL29/7y9vf+9vb3/vb29/76+vf+9vb3/vr6+/7y8vf+9vb3/vb29/729vf++vb3/vr29/729vf+9vb7/vb29/769vf+9vb3/vr29/72+vv++vr7/vr69/76+vv++vr7/v76+/76+vv+/vr7/v76+/7++vv++v7//v7+//76+v/++vr//vr6+/7++vv+/vr7/v7+//7+/v//Av7//vb29/729vv+9vb7/vr69/76+vv++vr//vr6+/7++v/++vb3/vr6+/72+vf++vr7/v76+/76+vv+/vr//v76//76+v/+/vr7/vr++/7+/v/+/v7//v7/A/7+/wP+/wMD/vr6//7+/v/+/v7//wL/A/8DAv//Av7//v8C//8C/v/+/v7//wL+//7/Av//Av7//v7+//8DAwP+/v7//wMDA/8C/wP/Av7//v7+//7+/wP/AwMD/wMDA/8DAwP/AwMD/wcDA/8DBwP/AwMH/wMHA/8HBwf/BwcH/wcHB/8HBwf/BwcH/wcHB/8DBwP/BwcH/wcHB/8LCwv/BwsH/wcHC/8C/v//AwMD/wMC//8DAwP/AwcD/wcDB/8HAwP/AwMD/wMDA/8DBwP/AwMD/wMDA/8HBwP/BwMD/qamp/2xsbP/AwcD/wcHB/8HBwf/BwcL/wsLC/8HBwf/CwcL/wsLC/8HBwf/BwsL/qaqp/8LCwf/CwsH/wsLC/8LCwv/CwsP/wsLB/8HBwf/CwsH/wsLC/8LCwv/Cw8L/wsPC/8LDwv/CwsH/wsLC/8LCwv/Dw8L/w8PD/8PCw//DwsP/wsPC/8PDwv/Dw8P/wsPD/8PDw//Ew8T/xMTE/8TEw//DxMT/w8PD/8PDw//Dw8P/xMTE/8PDxP/ExMT/w8PE/8TExP/CwsL/w8LD/8PDw//CwsP/wsPD/8PDw//CwsL/w8PD/8PCw//CwsP/wsPC/8LDw//Dw8P/w8TD/8PDw//Ew8P/xMPD/8PDxP/DxMT/xMPE/8TExP/FxMT/xMTE/8XExf/Dw8T/xMTE/8TDw//ExMT/xMTE/8TExf/FxcX/xMXF/8TExP/ExMX/xMTE/8XFxP/ExMT/xcXF/8TFxP/FxcX/xcTE/8XExf/ExcX/xMXF/8XExP/FxcX/xcXF/8bGxf/FxcX/xcXG/8XFxf/FxcX/xcbF/8bGxv/Gxsb/x8fH/8bFxv/Fxcb/xcXG/8bGxv/Gxsb/xsbH/8fHxv/Hx8b/xMTF/8XExf/FxcT/xcXF/8XFxf/Gxcb/xsXF/8bGxf/FxMT/xcXF/8XFxf/Fxsb/xsXG/8XGxf/GxcX/xsbG/8XGxv/Gxsb/xsbG/8bGxv/Hxsf/x8bH/8fGxv/Hx8f/xsbG/8bGx//Hxsb/xsbH/8bHx//Hx8f/x8fH/8jHx//Gxsb/xsfG/8fGxv/Hx8f/x8fH/8fHyP/IyMf/x8fH/8bHxv/Hx8f/x8fH/8fHx//Hx8f/yMjI/8jHx//HyMj/x8fI/8jIyP/Hx8f/yMjI/8jIyf/Jycj/ycnJ/8jIyf/IyMj/yMjI/8jIyP/Iycj/yMjI/8nJyf/IyMn/ycnJ/8fHx//Hx8f/yMfH/8fHyP/Hx8f/yMjI/8fIyP/IyMj/yMjI/8jHyP/Ix8f/x8fI/8jIyP/Iycn/yMjI/8jJyf/IyMj/ycjI/8jJyP/Jycn/ycnJ/8nJyf/Jycn/ysnK/8nIyf/Jycn/ycjJ/8nJyf/Jysn/ysrK/8rJyv/Kycn/ycnJ/8nJyv/Jycn/ycnK/8rKyv/Kysr/ycnJ/8rKyv/Jycr/ysrJ/8nJyv/Jysn/ysrK/8rLyv/Kysr/y8rL/8rKyv/Ky8r/y8rK/8rLyv/Ly8v/zMvL/8vLy//Ly8v/y8rL/8vLy//Ky8r/y8vL/8zLy//My8v/zMzL/8zLy//Jysn/ysrK/8rJyv/Kysr/ysvK/8rKy//Ly8v/ysvK/8rKyv/Ly8v/ysrK/8rKyv/Ly8v/y8vL/8rKy//Ly8v/y8vL/8vMzP/Ly8v/y8vM/8zLy//My8z/y8vM/8zMzP/Ly8v/zMvL/8vMy//Ly8v/y8zL/8zMzP/MzMz/zM3M/8zMzP/MzMz/y8vL/8zMzP/MzMz/zMzN/83NzP/Mzc3/y8vM/8zMzP/MzMz/zczM/83Mzf/NzM3/zM3N/83Nzf/Nzcz/zc3N/83Nzf/Nzs3/zc3N/83Nzv/Ozs3/zs7O/83Nzf/Nzc3/zs7N/83Ozv/Nzc3/zs7O/87Ozv/Oz8//zMzM/8zMzf/Mzcz/zMzN/8zMzP/Nzc3/zc3N/87Nzf/Nzc3/zczM/83Nzf/Nzc3/zc3N/83Ozv/Ozs7/zc3N/87Nzf/Ozc3/zs7N/87Ozv/Ozs7/z87P/8/Ozv/Pz8//zs7O/87Ozv/Ozs7/zs/P/87Oz//Pzs//z8/P/8/Pz//Ozs7/z8/P/87Ozv/Ozs7/z8/P/8/Pz//Pz8//z9DP/87Ozv/Ozs7/zs7P/8/Pz//Pz8//0M/P/9DQ0P/Pz8//0M/Q/8/Q0P/Qz9D/0NDQ/9DQ0P/R0dD/0NDQ/9HR0P/Qz9D/0NDQ/9DQ0P/Q0dD/0dDQ/9HR0P/Q0dD/0dHR/87Pz//Pz8//z8/P/9DQz//Q0ND/0M/Q/9DQz//Q0ND/z8/P/8/Pz//P0ND/z8/Q/9DQz//Q0ND/0NDQ/9HR0f/Q0ND/0NDR/9HQ0P/R0ND/0NDR/9HR0f/R0dH/0tLR/9HQ0P/Q0NH/0dHQ/9HR0f/R0dH/0dLR/9LR0f/S0tH/0NHR/9HR0f/R0dH/0dHS/9HR0v/R0dH/0dHR/9LS0v/R0dH/0dLS/9LR0f/S0dH/0dLS/9LS0v/S0tL/0tLS/9LS0v/S0tL/0tPT/9PT0v/T09L/09PT/9PT0//U1NT/09LS/9PS0v/T0tL/09PT/9PT0//T1NT/09TT/9PU1P/R0dH/0tHR/9LS0v/S0tL/0tLS/9PS0//T09L/09LT/9HR0v/S0tL/0tLS/9PS0v/S09P/0tPT/9PT0//T09P/0tLS/9PT0//T09P/09TU/9TT0//U1NT/09TT/9TU1P/T09P/1NTU/9PT0//U1NP/1NTT/9TU1P/U1NT/1dXU/9TT0//T09T/09PT/9TU1P/U1NT/1NTU/9XV1P/U1NX/1NPU/9TU1P/U1NT/1NXU/9XV1P/U1NT/1dXU/9XV1f/V1NX/1dXV/9XV1f/V1dX/1dXV/9bW1v/W1dX/1tbW/9XV1f/V1dX/1dXV/9XV1f/V1tX/1tbW/9bW1v/W1tb/1NTU/9XU1P/U1NT/1dTU/9TU1P/V1dX/1dXV/9XV1f/V1dX/1dTU/9TU1P/V1dX/1dXV/9XV1f/V1dX/1tXV/9XV1f/V1dX/1dbV/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tXV/9bW1v/W1tb/1tbW/9bW1v/W1tf/19bW/9fX1//W1tb/1tbW/9bW1v/X19b/19bW/9fX1//X19f/19fX/9bW1v/X1tb/1tfX/9fX1//X19f/19fX/9fX1//Y2Nj/19fX/9fX2P/X19f/2NjY/9jY2P/Y2Nj/2NjY/9nZ2f/Y2Nf/2NjY/9jY2P/Y2Nj/2NjY/9nZ2f/Y2Nj/2dnZ/9fW1v/X19f/19fX/9fX1//X19f/2NfY/9fY2P/Y2Nj/19fX/9fX1//X19f/19jX/9jX2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9jY2P/Z2Nn/2NnY/9nZ2f/Z2dn/2dnZ/9jY2P/Y2Nj/2NnZ/9nY2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnY/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2tn/2dnZ/9ra2v/Z2dn/2dnZ/9nZ2f/Z2dn/2drZ/9ra2v/Z2tn/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/29vb/9rb2v/b29v/2tra/9va2//a2tr/29vb/9vb2//b29v/29vb/9vb2//Z2dn/2tnZ/9nZ2f/a2dn/2tra/9ra2v/a2tr/2tra/9ra2f/a2tr/2dna/9ra2v/a2tr/29ra/9ra2v/b29r/2tra/9vb2//a2tr/29vb/9vb2//b3Nz/29vb/9vb2//b29v/29vb/9vb2//b29v/29vc/9zc3P/b3Nz/3Nzc/9vb2//c3Nz/29vb/9zc2//c3Nz/3Nzc/9zc3P/c3Nz/3Nvb/9zc3P/c29z/3Nzc/9zc3P/c3Nz/3Nzc/93d3P/c3Nz/3d3d/9zc3P/d3d3/3d3d/93e3v/d3d3/3t3d/93d3f/d3d3/3d3d/93d3f/e3t3/3t7e/97e3v/e3t7/3Nzc/9zc3P/c3Nz/3Nzc/93d3P/d3d3/3d3d/93d3f/c3Nz/3d3d/9zc3P/c3Nz/3d3d/93d3f/d3d3/3d3d/93d3f/e3d3/3d3d/93e3v/e3t7/3t7e/97e3v/e3t7/3t7d/97e3v/d3t3/3t7e/97e3v/f3t7/3t7e/9/e3v/e3t7/3t7e/97e3v/e3t7/3t/f/9/f3//f39//39/f/97e3v/f3t7/3t7e/97e3v/f39//39/f/9/f3//f39//39/f/+Df3//f39//3+Df/+Dg4P/g4OD/4ODg/+Dg4P/f4OD/4ODg/+Df4P/g4OD/4ODg/+Dg4P/g4OD/4eDh/9/f3//f39//397e/9/f3//f39//3+Dg/9/f3//f4N//39/f/9/f3//f39//39/f/9/f3//g4OD/3+Df/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dh4f/h4eD/4eHh/+Dg4P/g4OD/4ODg/+Hh4f/h4eD/4eHh/+Hh4f/h4eH/4ODg/+Dg4P/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Li4f/g4eD/4eHh/+Hh4f/h4eH/4eHh/+Hi4v/h4uL/4uLi/+Hh4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/j4+P/4uLi/+Li4v/i4uL/4uPj/+Lj4//j4+P/4+Pj/+Pj4//h4eH/4eHh/+Hh4f/i4eL/4eHh/+Li4v/i4uL/4uLi/+Hh4f/h4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4+P/4uLi/+Pi4v/i4uP/4+Pj/+Pj4//j4+P/4+Pj/+Tk4//j4uL/4+Pj/+Pj4//j4+P/4+Pj/+Tk5P/k5OP/5OTk/+Pj4//j4+P/4+Pj/+Pk4//k4+T/5OTk/+Tk5P/k5OT/4+Pj/+Tj5P/k4+T/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OXl/+Tk5P/l5eT/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5OTk/+Xl5f/l5eX/5eXl/+Xl5f/l5eb/4+Tj/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Xl5f/k5OT/5OTk/+Tk5P/k5OT/5OTl/+Xl5f/k5OT/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5ubm/+bl5v/m5ub/5eXl/+bl5v/l5eX/5ebm/+bm5v/m5ub/5ubm/+bm5v/l5uX/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/n5+f/5ufm/+fn5//n5+f/5+fn/+fn5//o6Oj/5+jn/+jo6P/n5+f/5+fn/+fn5//n5+f/5+fn/+jo6P/o6Oj/6Ojo/+bm5v/m5ub/5ubm/+bn5//m5uf/5+fn/+fn5//n5+f/5ubm/+bn5//m5+f/5+fn/+fn5//n5+f/5+fn/+fn6P/n5+f/5+jn/+fo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6ejp/+jo6P/o6en/6Ojo/+jo6P/o6Oj/6Ojo/+jp6P/p6en/6Ojo/+np6f/o6Oj/6ejp/+jo6P/o6Oj/6enp/+np6f/p6en/6enp/+np6f/p6er/6enp/+nq6f/p6un/6urq/+rq6v/q6ur/6enp/+rq6v/p6en/6urq/+rq6v/q6ur/6urq/+vq6v/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6erp/+np6f/p6en/6enp/+np6f/p6en/6erp/+nq6f/q6ur/6enq/+rq6v/q6ur/6urq/+rq6v/r6ur/6uvq/+vr6//q6ur/6urq/+rq6v/r6ur/6+rr/+vr6//r6+v/6+vr/+rq6v/q6+r/6+rq/+vr6//r6+v/6+vr/+vr6//r6+v/6+vq/+vr6//r6+v/6+vr/+vr6//s7Ov/6+vr/+zr7P/s7Oz/7Ozs/+vs7P/s7Oz/7Ozs/+zs7P/s7Oz/7ezs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7O3t/+zt7P/t7e3/6+vr/+vr6//r6+v/6+vr/+zs6//s7Oz/7Ovs/+zs7P/r6+v/7Ovs/+vr6//s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+3s7f/t7O3/7e3t/+3t7f/t7e3/7Ozs/+3s7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/s7ez/7e3t/+3t7f/t7e3/7e3t/+7u7v/t7e3/7u7t/+3t7f/t7e3/7e3t/+3t7f/u7u7/7u7u/+3t7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7+7u/+/v7//u7u7/7u7u/+7u7v/v7u7/7+7u/+/v7//v7+//7+/v/+3t7f/u7u7/7e3t/+3t7f/u7u7/7u7u/+7u7v/u7u7/7e3t/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7//u7u7/7u7u/+7u7//v7+//7+/v/+/v7//v7+//7+/v/+/u7//v7+//7+/v/+/v7//v7+//8O/w/+/v7//w8PD/7+/v/+/v7//v7+//7+/v/+/w7//w8PD/8O/v//Dw8P/v7+//8PDv/+/v7//w7/D/7/Dw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PH/8fHx//Dx8f/x8fH/8PDw//Dx8f/w8PD/8fHx//Hx8f/x8fH/8fHx//Hx8f/v7/D/7+/v/+/w7//w8PD/8PDw//Dw8P/w8PD/8PDw/+/w8P/w8PD/8PDw//Dw8P/w8PD/8PDx//Dw8P/w8PD/8fHw//Hx8f/w8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Pz8//z8/P/8/Pz//Ly8v/y8vL/8vLy//Pz8//z8/P/8/Pz//Pz8//z8/P/8fHx//Ly8v/x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8/Pz//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/19fX/9fX1//X19f/09PT/9PT0//T09P/19fX/9fX1//X19f/19fX/9fX1//Pz8//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//X19f/09PT/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/rKys/66trv+trq3/rq6t/62trv+ura3/rq2t/62trf+trq3/rq2t/62trv+tra3/ra6t/62trf+trq7/ra6t/66trf+ura3/ra6t/62urf+ur67/rq6v/6+ur/+urq//rq2t/66vr/+tra3/r6+v/6+urv+vrq//r6+v/66urv+tra3/rq2u/66urf+tra3/ra2u/66urv+trq7/rq2t/66urf+trq7/rq2t/62trv+urq7/r66u/66urf+vr67/r66v/66ur/+ur67/rq+v/66ur/+ur6//r6+v/66vr/+urq7/rq6u/66vrv+urq7/rq+v/66ur/+ur6//rq+u/66vrv+urq7/r66v/6+ur/+vrq//rq+u/6+ur/+wr7D/rq6u/66vrv+vrq7/r6+u/66vrv+vr7D/r6+w/7Cvr/+vsK//sK+v/7Cwr/+vr6//r6+w/6+vr/+wsLD/sLCw/7CwsP+wsK//r7Cw/6+vsP+vr6//sK+w/7CvsP+xsbD/r66v/6+urv+ur67/r6+w/7CwsP+vr7D/sK+v/7Cvr/+vrq//sK+w/6+wr/+vr6//sK+w/7CwsP+wsLD/r7Cv/7Cvr/+vr7D/r7Cw/7Cvr/+vr7D/sbCw/7GxsP+xsbH/r6+w/7CvsP+wr7D/sLGw/7CxsP+xsLD/sbGw/7GwsP+wsLD/sLGw/7Cxsf+xsLD/sbGx/7CwsP+xsLD/sLCx/7GwsP+xsbD/sLCx/7Cxsf+xsLD/sbGw/7Cxsf+wsLD/sLCx/7Gxsv+wsLD/sbKy/7Kysf+ysrL/sbGx/7Gxsf+ysrH/srKy/7Gxsv+xsbH/srKy/7Gysf+ysbL/sbKy/7GxsP+wsbD/sbCx/7Gwsf+xsLD/sbKx/7Cwsf+ysrL/sLCx/7Gxsf+wsLD/sbCx/7Kxsv+ysbH/sbGx/7Gysv+ysrL/srGx/7Kysv+xsrH/sbKy/7Kxsf+xsbH/s7Oz/7Kxsv+xsrL/sbKx/7Kysv+ysrL/s7Ky/7Ozsv+zsrP/sbGy/7Gxsv+xsrL/srKy/7Oys/+ysrL/s7Kz/7Kzsv+xsbH/srOy/7Ozsv+ysrL/s7Oy/7Kysv+zs7P/s7Oz/7Oys/+zsrL/s7Kz/7Ozs/+0s7P/s7Sz/7OztP+0s7T/s7Oy/7O0s/+zs7L/s7Sz/7OztP+zs7T/s7S0/7O0s/+ysrP/srOz/7Oysv+ysrL/srOy/7Kysv+zs7L/srOz/7Kzsv+zs7P/s7Oz/7Kys/+zs7P/tLSz/7Ozs/+zs7P/tLO0/7Szs/+0s7P/tLS0/7Ozs/+zs7T/tLO0/7S0tP+ztLP/s7O0/7O0s/+0tLP/tLSz/7S0s/+ztLP/tLS0/7O0s/+0tLP/tLOz/7S0tP+0tLT/tLS0/7S1tf+1tLX/s7O0/7Szs/+0tLT/tbW0/7S0tf+1tLT/tLS1/7W0tf+1tLX/tLW1/7S0tf+0tbT/tbW1/7W1tv+qqqv/IiIh/7W0tf+pqqn/tLS1/1pbW/8hISH/AAAA/wAAAP8LCwv/tLO0/7S1tf+0tbT/tLS0/7S0tP+1tbT/tLW0/7S0tf+0tLT/tLS0/7S0tP+0tbT/tbW0/7W1tP+0tbT/tbW1/6qpqv8LCwv/fHx9/wAAAP8AAAD/T09P/wAAAP+IiIj/W1pa/wAAAP8tLS3/AAAA/wAAAP+1trb/AAAA/7a2t/9xcXH/ODg4/wAAAP8AAAD/LS0t/y0tLf8iIiL/AAAA/yEiIv+Tk5P/q6qq/7a2t/+2t7b/rKys/7a2tv+3trf/W1tb/09PT/8AAAD/AAAA/1BPT/+4uLf/AAAA/7e4t/9bW1v/AAAA/7a3tv85OTn/AAAA/5WVlf8AAAD/c3Ny/7a1tv+2trb/t7e3/7a2tv+2trb/tre2/7a2t/+2t7b/tre3/7a3tv+3trf/t7e3/7a3t/+3trb/tre2/7e3t/+3t7f/lZWV/7e3uP+4t7j/AAAA/1BQUP9+fn7/oaGh/7i3t/+3t7j/t7e3/7e4uP+4t7f/t7e3/7e4t/+5ubj/uLi4/7i4t/+4t7j/uLi4/7e4uP+5uLn/ubi5/7i5uf+4t7f/t7e4/7i3uP+4uLj/uLm4/7m4uf+4uLn/uLi5/7m4uP+4uLn/uLi5/7m4uf+5ubn/ubm5/7m5uf+6ubn/ubi4/7m5uf+5uLj/ubm5/7m5uf+5ubr/ubq5/7m5uv+3t7f/ubi5/7m5uf+5ubj/uLi5/7i5uf+4ubn/uLm5/7i5uP+5uLn/ubi4/7i4uf+Vlpb/Li4u/xYWFv8AAAD/ubm5/7m5uf+ioqL/i4uL/7m6uf+6ubr/i4uL/4uLi/8AAAD/AAAA/yIiIv90c3P/AAAA/wAAAP+Li4v/dHR0/7m6uf+6ubn/urm5/7m6uf+6urr/urq7/7q6uv+7u7r/urm6/7q6uv+6urn/urq6/7u6u/+7u7r/uru6/7u7u/+7urv/u7q7/7q7uv+7u7v/u7u7/7y7u/+8vLv/vLy7/7q7uv+7u7v/u7u7/7u7u/+7u7v/vLu7/7y8u/+7vLv/urq6/7q7u/+jo6P/u7u7/7q7uv+6u7r/u7q6/7u7u/8AAAD/Li4u/wsLC/8AAAD/uru7/7u7u/+MjIz/u7u7/7u7u/+7u7v/u7y7/6+vsP+8u7v/vLy8/4yMjf91dXX/u7y8/4yMjP+8vLv/vLu8/wAAAP8AAAD/jY2N/42Njf+7vLz/vLy8/7u7u/+8vLz/vLy8/728vP+8vbz/vLy9/7y8vP+8vLz/vLy8/729vf+8vbz/vL29/7y8vP+9vb3/vL28/729vf+9vb3/vb29/72+vf+9vb3/vb2+/72+vv+9vb3/vr2+/729vf++vr3/vb6+/76+vv+9vr3/vr6+/7y8vP+8vL3/UlJS/xcXF/+8vL3/vb29/2pqav+9vb3/AAAA/wAAAP8XFxf/AAAA/15eXv+CgoL/IyMj/wAAAP+9vr7/vb29/769vv+Ojo7/vr6+/76+vv+Ojo7/v76//wsLC/8AAAD/CwsL/19fX/8AAAD/CwsL/wsLC/8AAAD/vr6+/76/vv++vr7/vr++/7++v/++v7//vr++/7+/v/++v7//v7+//76+v/++vr7/vr++/7+/v/+/v7//v8DA/7+/v/+/v8D/wMC//7+/v//Av7//wMDA/8DAv//AwMD/wL+//7+/v//Av8D/wL+//8DAwP/AwcD/wMDA/8DAwP+/vr//vr+//76+v/+/v7//v7+//7/AwP/Av8D/wL/A/46Ojv+/v7//R0dH/7+/v//Av7//wL+//8C/v/+/wMD/wMC//8DAwP/Av7//wMDA/8HBwP/AwMD/qamp/5GQkf+0tLT/PDw7/yMjI/8AAAD/AAAA/wAAAP8LCwv/YGBg/4SEhP8wLy//nZyd/zs7O/8AAAD/AAAA/wAAAP8AAAD/wMHA/8HAwf/BwcD/wcHB/wAAAP8AAAD/AAAA/wAAAP+RkZH/wcLB/5GRkf/CwsL/wsLC/8LDw//DwsP/w8PC/5GRkf/CwsL/kZGR/8LCwv/Cw8L/w8PC/8LDwv/Dw8L/wMHA/8HBwf+1tbX/wcLC/wAAAP8AAAD/AAAA/wAAAP8AAAD/SEhI/2BgYf8LCwv/AAAA/wAAAP8AAAD/AAAA/5GRkf/CwsL/kZGS/8LCwv/DwsL/w8PD/8PCwv/Dw8P/kpGR/8LDwv+SkZL/wsPC/8PDw//ExMT/w8PD/8PDw//Cw8L/w8PD/8LCw//Dw8P/w8PE/8PExP/ExMP/xMPE/8PDw//ExMT/w8PD/8PDw//ExMT/xMTE/8TDxP/ExMT/xMTE/8XExf/ExMT/xcXE/8XFxP/ExcT/xMXF/8XFxf/FxMX/xcTE/8XFxP/ExMX/xMTF/8XFxf/FxcX/xsbF/8TEw//ExMP/xMPE/8PExP/ExMT/xMXE/8TExP/FxMT/w8TE/8TExP/ExMP/xMTE/8TFxf/ExcX/xMTF/8TExP/ExMT/xMXF/8TExf/FxcX/xcXF/8XFxf/GxcX/xsbG/8XExf/FxcX/xcXF/8bFxv/FxcX/xsXG/8XGxf/Gxsb/xcXF/8bFxv/Gxcb/xcbF/8bGxv/Gxsb/xsbG/8bGxv/FxsX/xsbF/8bFxv/Gxsb/xsbG/8bGxv/Gx8f/xsfG/8bHxv/Hxsf/u7q7/yUlJf98fHz/MTEx/wAAAP8AAAD/Y2Nj/wAAAP8YGBj/AAAA/xgYGP+vrq7/cHBw/8jIx//Gxcb/xsbG/8bGxv/Gx8f/xsfH/8fGxv/Gx8f/x8fH/8bGxv/Gx8f/x8bH/8bHxv/Gx8b/x8fH/8fHx//Hx8f/AAAA/wAAAP8MDAz/AAAA/319ff/IyMj/JSUl/7u7u/9XV1f/AAAA/7u7u/8+Pj7/AAAA/wwMDP8AAAD/AAAA/zExMf8xMTH/JSUl/wwMDP9XV1f/fX19/wAAAP8AAAD/yMjI/8jIyf/IyMj/yMjI/319ff8MDAz/ycnI/319ff9LS0v/o6Sk/wAAAP9kZWT/ysnK/8rKyv/Kycn/ysrK/wAAAP9lZWT/AAAA/z8/Pv/Kysr/ysvL/8rKyv/Kysv/yMjJ/8jIyP/IyMn/yMnJ/8nJyf/Jysn/ycnJ/8nKyf9kZGT/vLy8/wAAAP8MDAz/ycrK/8nKyv9lZWT/vL29/xkZGP8/Pz//vLy9/8rKyv/Kysr/y8vK/8vLyv/Lysv/ysrK/8rKy//Kysr/y8rK/8vLyv/Ly8v/ysrL/8vLy//Lysr/ysrK/8vLyv/Ly8r/y8vL/8zMzP/Ly8v/y8vM/8rLy//Ly8v/ysrL/8vLy//LzMv/zMzM/8zMy//LzMz/y8zM/8zLy//Ly8v/zMzM/8zMzP/MzM3/zczN/8zMzf/LzMv/zMzM/8zMzP/Mzc3/zczM/8zMzf/Mzcz/zc3N/8vLy//MzMz/y8vL/8vMzP/LzMv/y8vM/8zLy/+/v7//zMvL/7++vv/LzMz/TExM/zIyMv8AAAD/AAAA/wwMDP/MzMz/zM3N/5mZmf+ampr/zM3M/83Nzf+ampr/p6em/wAAAP8AAAD/cnNy/5qamv8AAAD/AAAA/42Njf8mJib/zMzM/83Nzf/Nzc3/zs7O/87Nzv/Nzc3/zs3O/87Ozv/Nzc3/zc7O/83Ozv/Nzc7/zs7N/87Ozv/Ozs7/z87O/87Ozv/Ozs//zs7P/87Ozv/Pz8//z8/P/8/Pz//Qz8//z8/P/87Pzv/Oz8//z8/P/8/Pz//Qz8//z9DQ/8/Pz//Ozs7/zs7N/83Ozv/Ozs7/zs7O/8/Oz//Oz87/z87O/yYmJv+0tLT/AAAA/2dnZ//Pz87/z8/O/8/Pz//Pz8//zs7O/8/Pz//Pz8//qKio/8/P0P/Qz8//nJub/5ycnP/Pz8//AAAA/8/Qz/+pqKj/AAAA/wAAAP8mJib/AAAA/8/Qz//Qz8//0NDQ/9DQ0P/Q0ND/0dHR/9DQ0P/R0ND/z8/P/9DQ0P/Q0ND/0dHR/9DQ0P/R0ND/0NDQ/9HR0f/Q0NH/0dHR/9HR0f/R0tH/0dHS/9LR0f/S0dL/0tLS/9HR0f/R0tH/0tHR/9LS0f/R0dH/0tLS/9LS0v/S09L/0NDQ/9DQ0P+cnJz/qqmq/9HQ0f/R0dH/0dHR/9HS0f8AAAD/MzM0/xkZGf+qqqr/0dHR/52dnf/R0tL/0tLR/9HR0f/S0tH/nZ2d/52dnf/S0tL/0tLT/56env+rqqr/AAAA/wAAAP9bW1v/AAAA/wAAAP8AAAD/DAwM/56env/S0tL/0tLT/9LS0v/S09P/0tLT/9PT0//T09P/09PU/9PS0v/S0tL/0tLT/9PT0//T09P/1NTT/9PU0//U09P/09PU/9TT1P/T1NT/1NTU/9TU1P/U1dX/1NXU/9TU1f/T09T/1NTU/9TU1P/U1NT/1NXV/9TV1f/V1dX/1dXV/9PT0//T09P/09PT/9TT0//U09T/1NPT/9TU1P/U1NT/09PT/9TU0//U09T/1NPT/9PU1P/U1NT/1NTU/09PT//U1NT/1NTU/9XU1P/V1dT/1NXV/9XV1f+goKD/oKCg/3d3d/8MDQ3/AAAA/w0NDf8AAAD/AAAA/11dXf+goKD/1NXU/9XV1f/V1dX/1dXV/9XV1f/V1tb/1tbW/9bW1v/V1dX/1dXV/9XV1f/W1db/1dXW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9fW1v/W19b/19fX/9fX1//X19f/1tbW/9bW1v/X1tf/19fX/9fX1//X19f/19fX/9fX1//V1dX/1tbW/6CgoP/W1tb/1tbW/9bW1v/W1tb/19fW/wAAAP8NDQ3/UFBQ/wAAAP+Tk5P/1tbW/wAAAP+UlJT/1tbW/9fX1//X19f/19fX/9fX1//X2Nj/19jX/9jY2P/X19f/19fX/9fX1//X19f/2NfX/9jY2P/X2Nj/2NjY/9fX1//X19f/2NjY/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9jY2P/Z2Nj/2djZ/9jY2P/Y2Nj/2dnZ/9nZ2f/Z2dn/2dnZ/9rZ2v/Z2dn/2dna/9nZ2f/Z2dn/2dnZ/9nZ2f/a2dn/2tra/9rZ2f/a2tr/2NjY/9jY2P/Y2Nj/2NjY/9jZ2P/Z2dn/2NnY/9nZ2f/Y2Nj/2NnZ/9jY2P/Z2Nj/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2tn/2dnZ/9nZ2v/a2tr/2tra/9ra2v/a2tr/2dna/9ra2v/Z2dn/2tra/9ra2v/b2tr/2tra/9ra2//a2tr/2tra/9ra2v/a2tr/lpaW/zY2Nv+xsrH/RERE/9ra2v/a29v/2tra/9va2//b29v/29vb/9vb2//b29v/NjY2/zY2Nv8AAAD/AAAA/zY2Nv82Njb/DQ0N/0RERP8AAAD/AAAA/wAAAP8AAAD/bm5u/9zd3P9ubm7/3N3d/9vb2v/b29v/2tra/9vb2//b29v/3Nzb/9vb2//b3Nv/29vb/9vb2//b29v/29vb/9vb2//c3Nz/29vb/9zc3P8AAAD/AAAA/wAAAP8AAAD/bm5u/93d3f9ubm7/3d3d/wAAAP8AAAD/AAAA/wAAAP9ubm7/3d3d/25ubv/d3d3/NzY2/3x8fP8bGxv/AAAA/8HBwf/d3t7/DQ0N/4qKiv/d3d3/fHx8/93d3f/d3d3/AAAA/wAAAP9ub27/AAAA/97e3v/e3t7/3t7e/97e3v/f3t//39/f/9/e3//f39//ioqK/97e3v8AAAD/w8LC/9/f3//f39//39/f/9/f3//d3d3/3d7e/93d3f/d3d3/wsLC/wAAAP/e3t7/Gxsb/97d3v/e3t7/3d3d/97e3v/e3t7/Nzc3/97e3v9TU1P/AAAA/2FhYf8AAAD/KSkp/9/f3//f3+D/39/f/+Df3/8AAAD/AAAA/wAAAP8AAAD/4N/g/+Dg4P/f4N//4ODg/9/f3//f4OD/39/f/9/g4P/g4OD/4ODg/+Dg4P/g4OD/39/f/+Dg4P/f4N//4ODg/+Dg4P/g4OD/4ODg/+Hg4f/g4OD/4eDh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4P/h4eH/4eHh/+Hh4f/h4eH/4uHi/+Hh4f/i4uL/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OH/4eDh/6mpqf/g4OD/YmJi/4yMjP8AAAD/AAAA/wAAAP8AAAD/cHBw/+Hh4f/h4eH/qamp/6mpqf/i4uL/4uLi/6mpqf/i4uL/AAAA/wAAAP+pqan/qamp/wAAAP8NDQ3/RkZG/wAAAP/i4eH/4uLi/+Li4v/i4uL/4uLi/+Li4//i4+P/4+Pj/+Li4v/i4uL/4uLi/+Pi4//j4uP/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pk/+Pj4//k5OT/5OTk/+Tk5P/j4+P/4+Pj/+Pj4//j4+T/5OTk/+Tk5P/k5OT/5OTk/+Li4v/i4+P/4+Pi/+Pj4//j4+P/4+Pj/+Pj4//j5OP/qqmp/+Pj4/84ODj/4+Pj/+Pj4//j4+T/4+Pj/+Pk4//j4+T/5OTk/+Pj4/+rq6v/5OTk/9fW1/+AgID/Kioq/7m5uf8AAAD/5OTk/7m5uf8AAAD/AAAA/6ysrP+AgID/5OTk/+Tl5P/k5OT/5OXk/+Xl5f/l5eX/5eXl/+Xl5f9HR0f/OTk5/zk4OP85OTn/5eXl/+Xm5f/l5eX/5ebl/+bl5f/m5ub/5uXl/+bm5v/m5ub/5ubm/+bm5v/n5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5uf/5ubn/+fn5/8NDQ3/OTk5/wAAAP8qKir/5ebl/+bm5v+srKz/rKys/wAAAP8AAAD/AAAA/yoqKv8AAAD/AAAA/6ysrP+srKz/5ubm/+bm5v+srKz/ysnK/+bn5//n5+f/5+fn/+fn5/8AAAD/c3Nz/6ysrf/Z2dn/5+fn/+fn5//n5+f/5+fo/+fn5v/n5+f/5+fn/+fn5//n5+f/5+fn/+fo6P/o6Oj/5+fn/+fn5//n5+f/6Ojo/+jn5//o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6ejp/+np6f/p6On/6enp/+jo6P/o6Oj/6Ojo/+np6f/p6en/6enp/+np6f/p6en/5+fn/+jn5//n5+f/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/n6Of/6Ojo/+jo6P/Z2dn/n5+f/xwcHP8AAAD/AAAA/+no6f/p6en/vby8/6+vr//p6en/6enp/6+vr/+vr6//AAAA/wAAAP9ISEj/oKCg/wAAAP8AAAD/r6+v/4ODg//p6en/6enp/+np6f/q6en/6enp/+rq6v/q6ur/6urq/+np6f/p6un/6enp/+rq6v/q6ur/6urq/+rq6v/r6+v/6urq/+vq6//q6ur/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+rq6v/r6+v/6+vr/+zr6//r6+v/7Ovr/+nq6v/q6ur/29vb/+rq6v/q6ur/6uvq/+vq6//q6+r/AAAA/3V1df8AAAD/AAAA/+vq6//r6+v/29zb/+vr6//r6+v/6+vr/+vr6//r6+v/6+vs/+zs7P/s7Oz/7Ozs/+vr6//s7Oz/6+vr/+vr7P/s7Oz/7Ozs/+zs7P/s7Oz/6+vs/+zs7P/r6+v/7Ozs/+zs7P/s7Oz/7Ozs/+zt7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7f/s7Oz/7e3t/+3s7P/t7e3/7e3t/+3t7f/t7e3/7e7u/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+7t7f/u7u7/7e7u/+7u7v/s7Oz/7Ozs/+zs7P/t7Oz/7Ozs/+3t7f/t7e3/7e3t/+zs7P/t7Oz/7ezt/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+7u7f/t7e3/7u7t/+7u7v/u7u7/7u7u/+7u7v/u7e3/7u7u/+3u7f/u7u7/7u7u/+7u7v/u7u7/7+7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7v/+7v7v/v7+//7u7u/+7u7v/u7u7/7+/u/+7v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7/Dv/+/w8P/w7/D/8PDw/+/v7//v8PD/7+/v/+/v8P/v7/D/8PDw//Dw8P/w8PD/7u7u/+/u7v/v7u//7+/v/+/v7//v7+//7+/v/+/v7//u7u//7+/v/+/v7//v7+//7+/v/+/w8P/v7+//7+/v//Dv7//w7/D/7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/7/Dv//Dw8P/w8PD/8PDw//Dw8P/w8fD/8PDw//Hx8f/w8PD/8PDw//Dw8P/w8PD/8PHw//Hx8f/w8PH/8fHx//Dw8P/x8fH/8PDw//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/y8vL/8fHx//Ly8v/x8fH/8fHx//Hx8f/x8fH/8vLy//Ly8v/y8vL/8vLy//Dx8P/x8fH/8PHw//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9PT0//T09P/09PT/8/Pz//Pz8//z8/P/9PT0//T09P/09PT/9PT0//T09P/y8vL/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//09PT/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/09PT/9PT0//T09P/09PT/9fX1//X19f/19fX/9PT0//T09P/09PT/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//b29v/19fX/9vb2//X19f/19fX/9fX1//X19f/29vb/9vb2//b29v/29vb/9PT0//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v+urq7/rq2t/62urf+urq7/rq6v/66urv+urq7/r66v/62trf+vr6//ra6t/6+ur/+urq7/rq6u/66vrv+vrq7/r66u/66ur/+vrq7/r66v/6+urv+vrq7/rq6v/6+vsP+urq//rq+v/66vrv+ur67/r6+u/6+wr/+vsK//sK+w/66ur/+vr67/r6+v/66vrv+urq//rq+u/66urv+urq//rq+u/6+ur/+urq7/r66u/66urv+vr67/r6+u/6+ur/+vrq7/rq6u/66vrv+vr6//sLCw/7CwsP+vr6//r7Cv/6+vrv+wr7D/r6+v/6+wsP+vr7D/r6+v/6+vsP+vr7D/r7Cw/7Cwr/+wr6//sK+v/6+wsP+wsK//sLCv/6+wr/+wsK//sLCv/7CvsP+wr6//sK+v/7Cvr/+vr6//sLCw/6+vr/+wsbH/sbGw/7CwsP+wsbD/sLCx/7Gwsf+wsbH/sLGw/7CwsP+wsbH/sbCw/7GxsP+wsbH/sLCw/7CwsP+wsLD/r6+w/7CwsP+vr7D/r6+v/7CwsP+xsbH/sLCx/7CvsP+vr7D/r6+v/7Gwsf+xsLH/sLGw/7Gwsf+wsLD/sLGw/7Gwsf+wsbH/sbCx/7Gxsf+xsbH/sLCw/7Gysv+xsLD/sLCx/7GxsP+xsLH/srGx/7Gxsf+ysrH/sbKy/7GwsP+ysbH/sLCx/7Gysf+ysbL/sbGy/7Kysv+ysbH/srKx/7Gxsf+xsbH/sbKy/7Gxsv+ysrH/srGx/7Gysv+xsbH/srKy/7Kysv+ysrP/srKy/7Kzsv+ys7P/s7Ky/7Kysv+zs7L/srOz/7Ozsv+zsrP/srOz/7Kzs/+ysrL/sbGx/7Kxsv+xsbH/sbKy/7Gysf+xsrL/srKx/7Ozsv+ysbL/srGy/7Gysf+xsbH/sbGx/7Kzsv+ysrL/srOz/7Kzs/+ysrP/s7Ky/7Oys/+zsrP/s7Ky/7Kys/+ysrP/s7Kz/7Kzs/+ysrL/s7Oy/7Oys/+zs7T/srKy/7S0s/+zsrL/s7Oz/7Kysv+zsrL/tLSz/7Szs/+0s7P/s7S0/7Kysv+ztLP/srKz/7S0tP+0s7P/s7Oz/7OztP+ztLP/s7S0/7SztP+0tLP/tLSz/7SztP+0tLT/tLS0/7Szs/+zs7T/tLS0/7SztP+0tLT/tLSz/7W1tP+ztLP/tbW1/7S0tP+0s7T/s7Sz/7O0tP+zs7P/s7Oz/7SztP+zs7T/s7Sz/7Ozs/+zs7P/tLS0/7SztP+zs7P/s7Oz/7S1tf+0s7T/s7S0/7S0tP+0tLT/tLS0/7S0tP+0tLX/tbS0/7W0tP+1tbT/tLW0/7W0tf+0tbX/tLW0/7W0tP+1trb/tbW1/7W1tP+1tbT/tLS0/7S1tf+0tbX/tLS0/7W1tf+1tLT/tbS0/7S1tP+1tbX/tLW0/7W1tf+1tbb/tbW1/y0tLf8AAAD/LS0t/wAAAP8AAAD/t7a3/wAAAP+3trf/Q0RE/wAAAP9bWlv/AAAA/wAAAP+3t7f/AAAA/6CfoP+1tbT/trW2/7W1tf+1trX/tbW2/7W1tf+1trX/tba1/7W2tf+1tbX/trW1/7a2tf+1tbb/tbW2/7W1tf+2trb/iIiI/wAAAP+2t7b/FhYW/wAAAP9xcnH/AAAA/y0tLf+3trf/cXJx/7a2tv+3t7f/AAAA/wAAAP9ERET/AAAA/7a3t/+2trf/t7e3/7e3t/+2trb/t7e4/7e4uP+4uLf/t7e3/7a3tv+2t7b/uLi3/7i4t/+4uLj/t7i3/7e4uP+3t7j/uLe3/7i4uP+3t7j/t7e4/7m5uP+4uLj/ubm5/7e3t/+4t7f/uLi3/7m4uf+4uLn/uLm4/2hnZ/+Lior/t7e2/7e3uP+4t7f/t7e4/7i4t/+4t7f/uLe4/7i4t/9zcnP/t7e3/wAAAP8WFhb/t7i3/6ysrP85OTn/AAAA/7e3uP+ioaH/ubm5/0VFRf8AAAD/UVFQ/wAAAP+hoqH/XFxc/wAAAP8AAAD/IiIi/0VFRf+5ubn/rayt/7m5uf+4ubn/oaKh/7i5uP+5uLn/AAAA/wAAAP9zc3P/Ojk6/7m5uP+5ubn/uLm4/7m5uf+5ubn/ra6t/3N0dP8LCwv/f4B//7q5uv+tra3/urm5/7q6uv+7urv/o6Oj/2hoaP9dXV3/FxcX/wAAAP8LCwv/AAAA/wAAAP9FRkX/gICA/7m5uf+tra3/ubm5/11dXf8LCwv/AAAA/wAAAP8AAAD/ubm5/0VFRf+5ubn/o6Ki/wAAAP8LCwv/AAAA/wAAAP8uLi7/rq6u/6Ojo/+7u7v/u7q6/7q7uv+7u7r/u7u7/6+urv+7u7r/FxcX/1FRUf+7u7v/r6+v/0ZGRv8LCwv/RkVF/wAAAP8uLi7/AAAA/0ZGRv+8vLz/Li4u/7y7vP8AAAD/AAAA/11dXf8AAAD/Li4u/7y7vP8uLi7/u7y7/7y7vP+8vLz/u7u8/7y8vP+8vLz/vby9/729vf+8vLz/vLy8/7y8vP+8vLz/vby8/729vP+8vLz/vby8/729vf9dXV3/AAAA/11dXf8AAAD/Li4u/7y8vP8uLi7/vLy8/zo6Ov8AAAD/AAAA/wAAAP8XFxf/Li4u/wAAAP8LCwv/vLy8/728vP+8vbz/vLy8/728vf+9vb3/vb29/729vf+lpaT/vby8/7y8vf+ZmZn/vb29/76+vf9eXl7/Xl9e/y8vL/8AAAD/Ly8v/wAAAP8AAAD/CwsL/wAAAP+Ojo7/Ly8v/wAAAP8vLy//AAAA/y8vL/++vr7/Xl5f/76+vv+ysrL/vr6+/76+vv+/v77/mpqa/zs7O/+/v77/v7+//76+vv+/v77/vr6+/7+/v/+/v77/v7+//7+/v/+/wMD/Ly8v/wAAAP8vLy//AAAA/19fX/++vr7/X19f/7++v/8vLy//AAAA/wsLC/8AAAD/X19f/76+v/8jIyP/X19f/76/v/+/v77/vr6//7+/v/+/v7//wMDA/7+/wP/Av7//vr6+/7+/v/9fX1//tLSz/8DAwP/Av7//v7/A/8DAv/+zs7P/wL/A/7/AwP/Av7//wL/A/3h4eP+/wL//IyMj/7+/wP+/wMD/wMC//8DAv//AwMD/AAAA/8DAwP8AAAD/AAAA/wsLC/8AAAD/SEhI/6moqP/BwcH/wcHB/8HCwv8AAAD/eHh4/wAAAP+RkZH/wcHB/8HBwf/BwcH/wcHC/7/AwP/AwMD/wMDA/8DAwP/BwMD/AAAA/8DAwf8LCwv/wMDA/8HAwf/AwMD/wcHB/8DBwf9ISEj/wMHA/7W1tf8AAAD/hISE/wAAAP9UVFT/wsLC/8LBwf/BwcL/wsLC/wAAAP8XGBf/JCQk/wAAAP+1trX/wsLC/wsLC/9ISEj/wcHB/52dnf/BwsL/wsLC/wAAAP8AAAD/AAAA/wAAAP/BwsH/wsLC/8LCwv/Cw8L/AAAA/wAAAP8AAAD/AAAA/5GRkv/Dw8P/kZKR/8PDw//Dw8P/xMPD/8TEw//DxMP/kpKS/8TDxP+SkpL/xMPD/8PDw//ExMT/w8PE/8TExP/CwsL/wsPC/8LDwv+2t7b/AAAA/wAAAP8AAAD/AAAA/8LCwv9JSEn/JCQk/wAAAP8AAAD/AAAA/wAAAP8AAAD/k5OS/8PDxP+SkpP/w8TD/8TExP/ExMX/xMTE/8TFxP96enr/xMTE/wAAAP89PT3/xcXF/8XExf/FxcX/xMXF/8TExP/ExcX/xMTE/8XFxP/ExMT/xMTF/8TExP/FxcX/xMXF/8TExP/FxMX/xcXE/8TExf/FxcX/xcXF/8bFxf/FxcX/xsbG/8XFxv/Fxcb/xsXF/8bGxv/Gxsb/xsbH/8XGxf/Gxcb/xsXF/8bGxv/Gxsb/x8bG/8bGx//Gxsf/xcTF/8XExP/FxMT/xcXF/8XFxf/FxcX/xsbG/8bFxf/ExcT/xcXF/8XFxf/FxcX/xcXF/8bFxf/FxsX/xsbG/8bFxv/Gxsb/xsbG/8bGx//Hx8b/xsfG/8bHxv/Hx8f/xsbG/8fGxv/Hx8f/xsbH/8bHxv/Hx8f/x8fH/8jHyP/Hxsb/xsbH/8fHx//Hx8f/x8fH/8fIx//IyMj/yMjH/8bGx//Hx8f/x8fH/8fHyP/Ix8j/yMfH/8fIx/+7u7v/x8fH/8jIyP/Ix8f/yMjI/5aWl/8yMjH/yMjI/8jIyP/IyMj/ycjI/0tLS/+wr6//ycnJ/8nJyf/Jycn/ycnJ/8fHx//Ix8f/x8fI/8fIx//IyMj/r6+v/8fHx//IyMj/x8fH/8jHyP/IyMj/yMjH/8jIyP/Iycj/yMjI/8nIyP8AAAD/V1dX/wAAAP8MDAz/ycnJ/8rKyv+8vLz/ycrJ/zIxMv8AAAD/S0tL/wAAAP9LS0v/ysnJ/wAAAP8ZGRj/AAAA/wAAAP+Xl5f/MjIy/wAAAP8ZGRn/AAAA/wAAAP/Jycr/ysnK/8rKyf/Jycn/cXFx/wAAAP/Kysr/ZWVl/6Wkpf/Ky8v/DAwM/6SkpP/Ly8v/y8zL/8vLy//My8v/AAAA/xkZGf8AAAD/AAAA/8zMy//MzMz/paam/8vLzP/Jysr/ysrK/8nJyv/Kysr/ysrK/72+vf/Lysr/vb6+/8rKyv/Kysr/WFhY/1hYWP/Kysr/cnJy/xkZGf8AAAD/AAAA/wAAAP8AAAD/AAAA/5mYmP/My8z/paal/8zMzP8AAAD/GRkZ/wwMDP+mpqb/y8vL/8zMzP/MzMz/zc3M/8zLy/8ZGRn/y8zM/6ampv8AAAD/ZmZm/zIzMv+mpqb/zMvL/8zMzP/MzMz/pqam/8zMzf9/f3//GRkZ/wAAAP/MzM3/zc3N/83Nzf+ztLT/zc3O/4CAgP+AgID/TU1N/yYmJv8AAAD/AAAA/0BAQP8AAAD/AAAA/4CAgP+OjY3/zMzM/zMzM/+ampn/AAAA/wAAAP8ZGRn/AAAA/4CAgP+AgID/AAAA/83NzP8ZGRn/AAAA/5qamv8AAAD/DAwM/6ampv/Ozs3/zc7N/87Ozv/Ozs7/m5qb/8/Oz/+bm5r/zs7O/87Ozv9NTU3/Wlpa/8/Ozv9nZ2f/GRkZ/wAAAP8AAAD/GRkZ/wAAAP8AAAD/zs7P/8/Pz//Pz8//z9DQ/wAAAP8AAAD/AAAA/wAAAP/Pz8//0M/P/8/Q0P/P0M//z9DQ/8/Pz//Pz9D/0NDQ/4+Pj/8AAAD/0NDR/wwMDP/Q0M//0NDQ/9DQ0P/Q0ND/0NHR/01OTf/Q0NH/j4+P/wAAAP8AAAD/AAAA/wAAAP/Pz9D/0M/P/8/Q0P/Q0ND/AAAA/wAAAP8AAAD/AAAA/0BAQP+cnJz/AAAA/6qqqf/Q0ND/0NDR/9DR0f/R0ND/0dHR/9HR0f/R0dH/0dHS/9DR0f/Q0ND/0NDQ/9HR0f/R0dH/0tHS/9LR0f/R0tL/AAAA/8TExP8AAAD/goKD/9LS0f/R0tH/0tLS/9LS0v8AAAD/QUFB/wAAAP8AAAD/0tLS/5CQkP/FxcX/T09P/05OTv8AAAD/DAwM/ycnJ/+dnp3/09PT/9PT0//U09T/AAAA/3Z2dv8AAAD/ubm5/9PT0//T09P/1NTU/9TU0/8MDAz/AAAA/05OTv8AAAD/dnZ2/wAAAP8MDAz/AAAA/52dnf8AAAD/0tLS/xoaGv8AAAD/DAwM/wAAAP9PT0//QUFB/9PT0/+EhIT/1NPT/9PT1P/T09P/1NTT/9TU1P/Gxsb/09PU/9PU0//T09P/1NTU/9TU1P/U1NT/1NTU/9PU1P/T1NP/09PT/9TU1P+fn5//AAAA/1xdXP8AAAD/09TT/9TU1P/U1NT/1NTV/zU0NP8AAAD/NDQ0/wAAAP8AAAD/oKCg/ycnJ//V1dX/1dXV/9XV1v/V1db/1tbW/w0NDf81NTX/DQ0N/zU1Nf81NTX/NTU1/zU1Nf81NTX/1NTU/9TU1P/U1NX/1dXV/zU0Nf8AAAD/ampq/wAAAP/U1dX/1NTU/9XU1P/V1dX/urq6/wAAAP/V1dX/a2tq/zU1Nf/V1db/DQ0N/9bW1v/W1tb/1tbW/9bW1v/W1tb/AAAA/2tra/8AAAD/AAAA/9bW1v/X1tf/DQ0N/15eXf/W1tb/UFBQ/9bW1v+Uk5P/AAAA/xoaGv8AAAD/AAAA/zU1Nf8nKCj/NTU1/zU1Nf8AAAD/AAAA/zU1Nf81NTX/19fX/9jY1//Kysr/2NjY/9jY2P/Y2Nj/2NjY/9jX1/+ioqH/19fX/729vf/Y2Nj/2NjY/9jY2P/Y2Nj/2NnZ/9fW1v/X19f/19fX/9fX1//X19f/19fX/0NDQ/8aGhr/19fX/4aGhv81NTX/AAAA/wAAAP9sbGz/NTU1/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2djY/9nZ2f/Y2dn/2dnZ/9jY2P/Y2Nn/2NjY/9nY2P/Z2dn/2dnZ/9nZ2f/Z2dn/2NjY/9jY2f/Y2Nj/2NjZ/9jZ2f/Z2dn/2NjY/9nZ2f/Z2Nn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2v/Z2tr/2tra/9na2v/a2tn/2dna/9rZ2f/a2tr/29vb/9rb2//b29v/2tra/9rb2v/a2tr/2tra/9vb2//b2tv/29vb/9vb2//Z2dn/2dna/9nZ2f/Z2dr/2tra/9ra2v/a2tr/2tra/9nZ2v/a2tr/2dnZ/9ra2v/a2tr/2tva/9ra2v/b2tv/2tvb/9vb2//a2tr/29vb/9vb2//c3Nv/29vb/9vb2//b29v/29vb/9vb2//b29v/29zb/9zc3P/b29z/3Nzc/9vb2//b29z/29va/9vb2//c3Nz/3Nzc/9zc3P/c3Nz/29zc/9zc3P/b29v/3Nzc/9zc3P/c3N3/3Nzc/9zd3P8AAAD/AAAA/wAAAP8AAAD/bm5u/93d3v9ubm7/3d3e/wAAAP8AAAD/AAAA/wAAAP9vbm7/3t7e/25ubv/e3t7/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/d3d3/3dzc/93d3f/c3Nz/3Nzc/9zc3P/d3d3/3d3d/93d3f+zs7P/YGBg/wAAAP8AAAD/AAAA/wAAAP9vb2//3t7e/29vb//e3t7/AAAA/wAAAP8AAAD/AAAA/29vb//e39//KSkp/29vb//e3t7/3t7e/97e3v/e3t7/397f/29vb//e39//U1NT/97e3v/f3t//3t7e/97e3//f39//Nzc3/9/f3/8bGxv/AAAA/wAAAP8AAAD/AAAA/+Dg4P/g4OD/4ODg/+Dg4P8AAAD/AAAA/wAAAP83Nzf/4ODg/+Dg4P/g4OD/4ODh/97e3v/f39//3t/f/9/f3//Dw8P/AAAA/29vb/8AAAD/39/f/4uLi/83Nzf/AAAA/wAAAP8AAAD/AAAA/1NTU/8AAAD/YmJi/wAAAP/ExMT/4ODg/+Dg4f/g4OD/09PT/2JiYv/g4OD/4ODg/+Hg4P/h4eD/xcXF/+Hh4f/h4eH/RUVF/wAAAP/T09L/RkZG/zg4OP/h4eH/mpqa/+Li4f/h4eD/4eHh/9PT0/84ODj/qamp/0ZGRv8AAAD/AAAA/+Lh4f/i4uL/1NTU/5ubm//Gxsb/AAAA/3Fxcf8AAAD/AAAA/wAAAP8qKir/jY2O/wAAAP8AAAD/x8fH/wAAAP9wcHD/AAAA/w0NDf8AAAD/AAAA/5ubm/9UVFT/4uLi/wAAAP8AAAD/VFRU/wAAAP9xcXH/4uLi/wAAAP9GRkb/4uLi/+Pj4//j4+L/4+Pj/+Pj4/8AAAD/4+Pj/wAAAP/i4+P/4+Pj/2NjY/8cHBz/qqqq/wAAAP8AAAD/AAAA/wAAAP/Hx8f/AAAA/6qqqv/k5OP/5OTk/+Tj5P/k5OT/AAAA/6urq/8AAAD/q6qq/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5eTk/+Tk5P/l5OT/5eXl/6ysrP/l5eX/rKys/+Xk5P/l5eX/5eTk/+Xl5f/l5eX/rKys/+Xl5f+srKz/AAAA/6urq/8AAAD/q6ur/+Tk5P/k5OX/5OTk/+Xk5P8AAAD/ODg4/wAAAP8AAAD/jo6O/+Xl5f+AgID/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eb/rKys/+bl5f+srKz/5eXl/+Xm5f/l5eX/5uXl/+bm5v+srKz/5ubm/+bm5v8AAAD/OTk5/wAAAP85OTn/5ubm/+bm5v/m5ub/5ubm/wAAAP85OTn/AAAA/zk5Of/m5ub/5ubm/+bn5//n5+f/5+fm/+fn5//n5+f/5+fn/+fn5//n5+f/5+jn/+jo6P/n5+f/5+fn/+fn5//n5+j/5+fo/+jo6P/o6Oj/6Ojo/wAAAP85OTn/AAAA/zk5Of/m5uf/5+fn/+fn5//n5+f/AAAA/w4ODv8cHBz/AAAA/7y8vP/n5+f/Dg4O/xwcHP/n5+f/5+fo/8rLyv8ODg7/6Ojo/+jo6P+RkZH/6Ojo/2VlZf8AAAD/AAAA/ysrK/+urq7/6Ono/+jo6P/o6Oj/6Ojo/5GRkf/o6Oj/6Ojo/wAAAP8AAAD/ZWVl/1dXV//o6Oj/6Ojp/+jo6P/o6On/6enp/8zMzP9lZWX/AAAA/9ra2v/p6en/6enp/+nq6v/q6un/6urq/76+vv+Dg4P/V1dX/w4ODv8AAAD/HBwc/wAAAP8AAAD/ZmZm/76+vv/o6en/r6+v/+jo6P86Ojr/AAAA/wAAAP8AAAD/HBwc/+np6f8cHBz/6enp/5GRkf8AAAD/Ojo6/wAAAP8AAAD/V1dX/+rq6v/q6ur/6urq/+rq6v/q6ur/6uvq/+rr6//q6ur/6urq/ysrK/91dXX/6urq/87Ozv9JSEj/AAAA/ysrK/8AAAD/HBwc/wAAAP+Tk5P/6+vr/3V1df/r6+v/AAAA/wAAAP86Ojr/AAAA/3V1df/r6+v/dXV1/+vs6//r6+v/7Ozs/+vr6//s7Oz/7Ozs/+zs7P/s7Oz/7Ozt/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7ezt/+zs7P/t7e3/Ojo6/wAAAP86Ojr/AAAA/3V2dv/s7Oz/dXV2/+zs7P8dHR3/AAAA/wAAAP8AAAD/Ojo6/0lJSf8AAAD/SUlJ/+zs7P/s7Oz/7Ozs/+3t7f/s7e3/7e3t/+3t7f/t7e3/7Ozs/+3t7P/t7ez/7e3t/+3t7f/t7e3/7e3t/+3t7f/s7e3/7e3t/+3t7f/t7e3/7e3t/+3u7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/u7u3/7u7u/+7t7f/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/v7u7/7u7u/+/v7//u7u7/7u7u/+7u7v/v7+7/7u7u/+/v7//u7u7/7+/v/+3t7f/t7e7/7e3t/+3t7f/u7u7/7u7u/+7u7v/u7u7/7u7t/+7u7v/t7e3/7u7u/+7u7v/u7u7/7u7u/+/u7v/u7u7/7u7v/+7v7v/u7u//7+/v/+/v7//v7+//7+/v/+/u7//v7+//7u7v/+/v7//v7+//7/Dw/+/v7//w7/D/7+/v/+/v7//v7+//7+/v/+/w8P/w8PD/7+/v//Dw8P/v7+//8PDw/+/v7//v7/D/7+/w//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PH/8fHx//Dw8P/x8fH/8PDw//Hw8P/w8PD/8fHw//Hx8f/x8fH/8fHx//Hx8f/v8O//7+/w//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PHw//Dw8P/x8fD/8fHx//Hx8f/w8PD/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Pz8//z8/P/8/Pz//Ly8v/y8vL/8vLy//Pz8//z8/P/8/Pz//Pz8//z8/P/8fHx//Ly8v/x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/19fX/9fX1//X19f/09PT/9PT0//T09P/09PT/9fX1//X19f/19fX/9fX1//Pz8//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/19fX/9fX1//X19f/19fX/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//b29v/39/f/9vb2//b29v/29vb/9vb2//f39//39/f/9/f3//f39//19fX/9vb2//X19f/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//f39//29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/6+urv+ur6//rq+u/6+urv+vr6//r6+u/66urv+wr6//r6+u/6+vrv+vrq7/r66u/66vr/+vr7D/sK+v/6+vsP+wr7D/sLCv/7CwsP+vr6//r6+v/6+wr/+vsLD/sK+v/7Cwr/+wsK//sLCv/7CvsP+vr6//sLCw/6+vsP+xsbH/rq+v/6+vrv+ur6//sLCw/6+wr/+wsK//r7Cw/6+wr/+urq7/sLCw/6+vsP+wr7D/r7Cv/7CvsP+vr6//sK+w/7CvsP+wr7D/r6+v/7CwsP+vsK//sbGx/7CwsP+xsLD/r6+v/6+wsP+vr7D/sLCx/7Gwsf+xsLD/sbCx/7CwsP+wsLD/sbGx/7Gwsf+wsbD/sLCx/7CwsP+wsLD/sbGw/7CwsP+xsLD/sbCw/7CwsP+wsbD/sLCx/7GwsP+xsbD/sbGx/7Gysv+wsLH/srKx/7Gysf+xsbH/srKy/7Gysv+xsrH/sbGx/7Kysf+ysbL/sbKx/7Gysv+xsbH/sbKx/7GxsP+xsLH/sLGx/7CwsP+xsLD/sbKx/7Gwsf+xsbL/sbGw/7CxsP+xsbD/sbGw/7Kxsv+ysbL/sbKy/7Kxsf+ysrL/sbKx/7Kysf+xsbH/srGy/7Kysf+xsrH/srKx/7Kysf+xsbL/srKy/7Gxsf+xsbL/s7Kz/7Gysv+ysrP/sbGx/7Kxsf+ysrH/s7Kz/7Oysv+zsrL/srKy/7Kzs/+xsbH/srKy/7Kzs/+zsrL/s7Oy/7Kzsv+zs7L/srKy/7Ozsv+ys7L/srOy/7Oys/+zs7P/s7S0/7Szs/+0tLT/s7Ky/7OztP+zs7P/s7Oz/7S0tP+0s7P/s7Oz/7SztP+ys7L/srKy/7Kzsv+ysrL/srOy/7Kzsv+ys7L/srOy/7Kzs/+ysrL/s7Kz/7Ozs/+ys7L/s7Oz/7Kzsv+ztLP/tLOz/7S0s/+ztLP/tLS0/7O0tP+0tLT/s7Oz/7O0tP+0s7T/s7S0/7Szs/+0tLP/tLOz/7O0tP+0tLT/tbW1/7S0s/+ztLP/s7Oz/7Szs/+zs7P/tbS0/7W0tP+0tLX/s7S0/7O0s/+0s7P/tLS0/7S0tP+0tbX/tbS1/7W0tf+1tLT/tbS1/7W1tf+0tbT/tLS1/7a1tf+1trb/tra2/7W1tP+0tLT/tLS0/7a2tv+1tbb/tbW2/7W1tf+1trX/tLS0/7W0tf+0tLT/tLW0/7W0tP+0tLT/tbW1/7W0tP+0tLX/tLS1/7W0tP+0tLT/tLW0/7S0tf+1tbX/tbW1/7S1tP+2trb/trW2/7a1tv+2tbb/tba1/7a1tf+1trb/trW2/7a1tf+2tbX/trW1/7W1tv+2tbb/tbW2/7e3tv+2trb/tbW2/7W1tv+1tbb/tba1/7e2tv+2trb/tre3/7W2tf+1trb/trW2/7e3t/+2t7f/tra2/7a3tv+3trf/tre3/7a2tv+2trb/tra2/7a2t/9ycnP/t7i3/7e4t/+2t7b/tre3/7a2tv+4t7f/uLe4/7i4t/+3t7j/t7i3/7a1tv+2trb/t7e2/7a2t/+2t7b/tre3/7a3tv+2t7f/tre3/7a2t/+3trb/tre3/7e2tv+3trf/tra3/7i3uP+2trb/uLi3/7i4t/+3uLj/uLi3/7i3uP+4t7j/uLe4/7i3t/+3uLj/t7e4/7i3uP+3uLj/uLi3/7e3t/+4ubj/FhYW/wAAAP+3uLj/t7e3/wAAAP8LCwv/uLm5/7m5uf+3t7j/t7e4/7i3t/+4uLn/ubm5/7i4uf+4uLn/uLi4/0VFRf+trKz/ubi4/7i4uP+5ubn/ubm5/7m5uf+5ubn/ubi4/7m5uf+4uLj/ubm5/7m5uf+5ubn/urm5/7q5uv+3uLf/uLi4/7m5uP+4ubj/ubi5/7m5uP+4uLj/ubm4/7m5uP+4ubj/uLm4/7i4uP+4uLn/uLm4/7i5uP+5ubn/ubm5/7m5uf+5ubn/urm6/7q6uv+6ubn/ubm5/7q5uf+5ubn/urm6/7m5uf+6urn/urm6/7q6uv+5urn/urq6/7m6uv+6urr/ubm5/7q5uv+AgID/FxcX/7q6uv+7u7r/ubm6/7q6uv+5ubn/urq6/7q6u/+7urr/uru7/7q6u/8AAAD/AAAA/7u7uv+7u7v/CwsL/0ZGRv+7u7v/vLy8/7q6u/+7u7v/u7u7/7u7u/+8vLz/vLy8/7u7u/+8vLv/urq6/7u6u/+6urr/uru7/7u6uv+6u7v/uru6/7u7u/+7urr/u7u6/7q6uv+6urv/uru6/7u7u/+7u7v/u7u7/7u7u/+8u7z/u7u7/7u8u/+8u7v/vLy8/7y8vP+8vLz/u7u8/7y7u/+7u7v/u7u8/7y8vP+8vLz/vLy8/728vP+BgYD/Li4u/7u8u/+8vLz/AAAA/3V1dv+9vbz/vLy9/7y8vP+8vLz/vLy8/729vf+8vL3/vLy9/7y8vP+9vb3/vL28/2pqav+9vb3/vb29/wAAAP8AAAD/vr29/729vf+9vb3/vr29/729vf+9vb3/vr69/76+vv+9vr3/vr6+/7y8vP+8vb3/vb28/729vP+9vbz/vb29/729vf+9vb3/vL28/728vP+9vbz/vb29/729vf+9vr3/vb29/72+vv++vr3/vr29/72+vf++vr7/vr6+/76+vv++vr7/vr++/729vv++vr7/vb6+/76+vv++vr7/vr6+/76+vv++vr7/AAAA/wAAAP++vr7/v76+/wAAAP8AAAD/vr++/7+/v/++vr7/vr+//76+v/++v7//vr++/7+/v/+/v7//wL+//wAAAP+Pj5D/v8C//7+/v/+/v7//wMDA/8C/wP/AwMD/wL/A/7/Av//AwL//v7+//8DAwP/AwMH/wMDA/8DAwf++vr7/vr6//7+/vv+/v7//v7+//7+/v/+/v7//wL+//7++v/+/v7//v7+//8C/wP+/wL//v8C//7+/wP+/v7//v8DA/8DAwP+/v8D/wMDA/8HBwf/BwcH/wMHB/8DBwf/AwMD/wMDA/8DAwP/AwMH/wcDA/8HAwf/BwMH/wcHB/8DBwf/BwMD/wcHB/8HAwP/BwMD/wcHB/8HBwf/BwcH/wcDB/8DBwf/AwcH/wcHB/8HBwf/BwcH/wsLC/8HBwf+2trX/SEhI/8LCwf/CwsL/AAAA/wAAAP/Dw8L/w8LC/8LCwv/CwsL/wsLC/8LCw//DwsL/wsLD/8PCwv/Cw8P/wcDA/8HBwf/BwcH/wcLC/8LCwf/CwcH/wsLB/8LCwv/BwcH/wsHC/8LBwf/BwcL/wcHC/8LCwv/CwsL/wsLC/8LCwv/Cw8P/wsLC/8PDwv/Cw8L/w8PD/8LCw//Dw8P/w8PD/8PCwv/Dw8P/w8LC/8PDw//Ew8P/w8PD/8PDw/8LCwv/VVVV/8LCwv/Dw8P/CwwM/xgYGP/Dw8P/w8PE/8PDw//DxMT/w8PD/8TDxP/Dw8T/xMTE/8PDw//ExMT/SUlJ/4eHh//ExMT/xMXF/8TFxP/ExMX/xcXE/8XFxf/ExcX/xcXE/8TExP/ExcX/xMTE/8XFxf/FxcX/xcbG/8TDxP/Dw8T/w8PD/8PEw//ExMT/xMTE/8TExP/ExcX/w8TE/8TExP/Dw8T/xMTE/8TExP/FxcT/xcXE/8TFxf/ExcT/xMXE/8TFxf/FxcX/xcXF/8bFxv/GxsX/xsbG/8XExP/FxcX/xcXF/8XFxv/FxcX/xsXF/8XGxv/Gxsb/xcXF/8XGxv/Fxsb/xcXG/8XFxf/Gxsb/xsbG/8fGxv/Fxcb/xcbF/8XGxf/Gxsb/xsbG/8bGxv/Hxsb/xsfH/8bHx//Hxsb/x8bG/8fHx//Hx8f/x8fI/8jHx//Ix8f/xsbH/8fHx//Hx8f/x8fI/8jHx//HyMj/x8fI/8jHx//Gxcb/xsbG/8bGxv/Gxsb/x8bG/8fHxv/Gxsf/x8fH/8bGxv/Gxsf/x8fG/8fGxv/Hx8b/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fI/8jHx//IyMj/yMfH/8jIyP/Ix8j/x8jH/8fHx//Hx8j/yMjI/8jIyf/IyMj/ycnI/8fHx//IyMj/yMfH/8jIyP/JyMj/ycjJ/8nIyP/IyMj/yMjI/8jJyP/IyMj/ycjJ/8nIyP/Jycn/ycjI/8nJyf9xcXH/GRgZ/8nJyf/Kycn/WFhX/zIyMv/Jysn/ysrK/8nJyf/Jycr/ycnJ/8rKyv/Kysr/ysvL/8rKyv/Lysr/ycjI/8jIyP/IyMn/ycjI/8nJyf/Jycn/ycnJ/8nKyf/Iycn/ycnJ/8nIyP/Jycn/ycrJ/8rJyf/Jysn/ysrJ/8nJyf/Kysr/ysnK/8rKyv/Kysv/ysvK/8vLyv/Ly8v/ysrK/8rKy//Kysr/y8vK/8rKy//Ly8v/ysvL/8vLy/8AAAD/AAAA/8vLy//Ly8r/AAAA/z8/P//Ly8v/y8vL/8rKyv/Ly8v/y8vL/8vLy//LzMz/y8zL/8vLzP/MzMz/pqal/8zLy//LzMv/zMzM/8zMzP/NzMz/zM3M/83Mzf/LzMv/zMzM/8zMzP/Nzcz/zczN/83NzP/MzMz/zc3N/8vLy//Ly8v/y8vL/8zMzP/MzMv/zMvM/8zLzP/MzMz/y8vL/8zMzP/Ly8z/zMvM/8vLzP/MzMz/zMzM/8zMzP/MzMz/zM3M/8zMzP/NzMz/zc3N/83Nzf/Nzc3/zc3O/83Nzf/Mzc3/zM3M/83Nzf/Nzc3/zc7O/83Ozv/Nzc3/zMzN/6ampv/Nzc3/zc7O/zMzM/8AAAD/zc3O/87Ozv/Nzc3/zs3O/83Nzf/Ozc3/zs7N/87Ozv/Ozs7/z87O/wAAAP8AAAD/z8/P/87Pzv9AQED/gYGB/8/Pz//P0M//zs/O/87Ozv/Oz8//z8/P/8/Pz//Qz8//z8/Q/9DPz//Nzs3/zc7O/87Nzf/Ozs7/zs7O/87Pz//Pzs//z87P/87Nzv/Ozs7/zs7O/8/Ozv/Oz87/z87O/87Pzv/Pz8//z8/O/8/Pz//Pz8//z9DQ/9DQ0P/Q0M//z9DP/9DQ0P/Pz8//0NDQ/8/Qz//Pz8//z8/P/9DQ0P/Q0ND/0NHR/1tbW/8AAAD/z9DQ/9DQ0P9NTU3/0dHQ/9DR0P/R0ND/0NDQ/9DQ0P/Q0ND/0NHQ/9DR0P/R0dD/0dHQ/9HR0f/Q0dH/0dHR/9HR0f/R0dL/0tHR/9LR0f/R0dH/0tLS/9HR0f/R0dH/0tLS/9HS0f/R0dH/0tLS/9LS0v/S0tL/0NDQ/9DQ0P/R0NH/0dHQ/9DQ0P/R0dH/0dHR/9HR0f/R0dH/0dDQ/9DQ0f/R0dH/0dHR/9HS0v/S0dL/0dLR/9HS0v/R0tH/0dHR/9LS0v/S0tL/0tLT/9PS0v/S09L/0tHR/9LS0v/S0tL/09LT/9PT0//S09P/09PS/9PT0//S0tL/W1tb/9PT0v/Gxcb/AAAA/56env+enp7/1NTU/9LS0//S0tL/09LS/9PT0//T09P/09PT/9TU0//U1NT/09TT/9PT0//U09T/1NTU/9TU1P/V1NT/1NXU/9TU1P/T09T/1NTU/9TU1P/V1NX/1NXU/9TU1P/U1dX/1dXV/9LT0//T09P/09PT/9PU0//T1NP/09PT/9TU0//U1NT/09PT/9TT1P/U1NT/09PT/9TU0//U1NT/1NTU/9XV1f/U1NT/1NXU/9TU1f/V1NT/1dTV/9XV1f/U1dX/1dXV/9TV1P/U1NT/1dXV/9TU1P/V1dX/1dXV/9XV1f/V1tX/1dXV/9XV1f/V1dX/1dXV/9XV1f/W1dX/1dbV/9bW1v/V1dX/1dXV/9XV1f/V1db/1dXW/9bW1v/W1tb/1tbW/5OTk/8nJyf/1tbW/9bW1v8AAAD/AAAA/9bX1v/X19f/1tbW/9fW1//W1tb/19bW/9fX1//X19f/19fX/9fX1//V1dX/1dXV/9bV1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bV1f/W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/X19b/1tbX/9fX1//W1tb/19fX/9fX1//X19f/19fX/9fY2P/X19f/19fX/9fX1//X19f/19fY/9jY2P/X2Nf/2NjY/w0NDf9QUFD/19fY/9fX1//Kysr/2NjY/9jY2P/Y2Nj/2NfX/9jY2P/X2Nj/2NjY/9jY2P/Y2dn/2NjY/9jY2P/Z2Nn/2dnZ/9nY2P/Z2dn/2dnZ/9na2v/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2tn/2tra/9ra2f/a2tr/2NjY/9jY2P/Y2Nj/2NjY/9jZ2f/Z2dn/2NnZ/9nZ2f/Y2Nj/2djY/9jY2P/Y2Nj/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/a2dn/2dnZ/9na2f/a2tr/2tra/9ra2v/a2tr/2tna/9ra2v/a2dr/2tra/9ra2v/a2tr/2tra/9vb2v/a2tr/2tra/9ra2v/a2tr/2tva/9vb2//a29r/29vb/9ra2v/a2tr/2tra/9va2v/b29v/29vb/9vb2//b29v/29vb/9zb2//b29v/29vb/9zc3P/c3Nz/3Nzc/9zc3P/c29z/3Nzc/9zb3P/c3Nz/3Nzc/9zd3P/c3Nz/3Nzd/9rb2//b29v/29vb/9vb2//b29v/29vb/9vb2//c29v/29vb/9vb2//b29v/29vb/9vb2//c3Nz/3Nzb/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/93d3f/d3d3/3d3d/9zc3P/c3Nz/3Nzc/93d3f/d3d3/3d3d/93d3f/d3d3/3N3d/93d3f/c3N3/3d3d/25ubv8AAAD/3d3d/97e3v/d3d3/3d3d/93d3f/d3d3/3t3d/97e3v/d3d3/3t7e/wAAAP8AAAD/3t7e/97e3v8AAAD/AAAA/97f3v/f39//3t7e/9/e3//e3t7/3t7f/9/f3//f39//39/f/9/f3//d3d3/3d7e/93d3f/d3d7/3t7e/97e3v/e3t7/3t7e/93d3f/e3t7/3t7e/97e3v/e3t7/3t/f/97e3v/e39//39/e/9/f3//f39//39/f/9/f3//f4OD/39/f/9/f4P/f39//39/f/9/f3//f39//39/f/+Dg3//f4OD/4ODg/wAAAP9FRUX/39/f/+Dg4P+ampr/4ODg/+Dg4P/g4OD/4N/f/9/f3//g39//4ODg/+Dg4P/g4OD/4ODg/+Hh4P/g4OD/4OHg/+Hh4P/h4eH/4eHh/+Hh4f/h4eH/4uLh/+Dh4f/h4eH/4eHh/+Hh4f/h4eH/4eHi/+Hi4v/i4uL/3+Df/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODh/+Hh4f/g4OD/4ODg/+Dg4P/h4OH/4eHg/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4v/i4uH/4uLi/+Li4v/i4uL/4eHh/+Li4v/i4eL/4uLi/+Li4v/i4uL/4uLi/+Lj4v/T09T/RkZG/+Li4v/i4uL/AAAA/wAAAP/i4+P/4+Pj/+Li4v/i4uL/4uLi/+Pj4//j4uP/4+Pj/+Pj4//j4+P/AAAA/yoqKv/j4+P/4+Pj/4B/f/+AgID/5OPk/+Tk5P/j4+P/5OPj/+Pj4//j5OT/5OTk/+Tk5P/k5OT/5OTk/+Li4v/i4+L/4+Lj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4uPi/+Pj4//j4+P/4+Pj/+Pj4//j5OT/4+Pj/+Pj4//j4+P/5OTk/+Pj4//k5OT/5OTk/+Tl5P/k5OT/5eXk/+Tk5P/k5OT/5OTk/+Tk5P/l5OT/5eXl/+Xk5f/l5eX/DQ0N/yoqKv/k5OT/5OTl/9fX1//l5eX/5eXl/+Xl5f/k5eX/5eXl/+Xk5P/l5eX/5eXl/+Xl5v/l5eX/5ubl/+Xm5f/m5ub/5eXl/+bm5v/m5ub/5ubm/+bm5v/n5+f/5ebl/+bm5v/m5ub/5ubm/+bm5v/m5uf/5+fm/+fn5//l5eX/5eXl/+Xl5f/l5eX/5ubl/+Xm5f/l5eX/5ubm/+Xl5f/l5ub/5eXl/+Xm5f/m5eb/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ufm/+bm5v/n5+f/5+fn/+fn5//m5ub/5+fm/+fm5//n5+f/5+fn/+fn5//n5+f/5+jo/5+env9ISEj/5+fn/+fn5/8AAAD/HBwc/+jn5//n6Oj/5+fn/+fn5//n5+f/6Ojn/+fn6P/o6Oj/6Ofn/+jo6P+CgoL/2dnZ/+jo6P/o6Oj/6enp/+np6f/p6Oj/6enp/+jo6P/p6ej/6Ojo/+jp6f/p6en/6enp/+np6f/p6en/5+fn/+jo5//o5+f/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o5+f/6Ojo/+jn5//o6Oj/6Ojo/+no6f/o6Oj/6Ojo/+jp6P/p6en/6Onp/+np6f/p6en/6enp/+np6f/q6un/6enp/+np6f/p6en/6enp/+np6f/q6un/6erq/+rq6v/p6en/6enp/+np6f/p6en/dHV1/w4ODv/q6ur/6urq/+np6f/q6ur/6enq/+rq6v/q6ur/6urq/+rq6v/r6+v/AAAA/wAAAP/r6uv/6urr/w4ODv9YWFj/6+vr/+vr6//r6+r/6+vr/+rr6//r6+v/6+vr/+vr6//r6+v/6+zs/+rp6v/q6ur/6urq/+rq6v/q6ur/6uvr/+rr6v/q6ur/6urq/+rq6v/q6ur/6urr/+vq6//r6+v/6uvr/+vr6//r6+v/6+vr/+vr6//r6+v/6+zs/+zr7P/s6+v/7Ozs/+vr6//r6+z/6+vr/+zr6//r6+v/7Ozs/+zs7P/s7Oz/oaKi/ysrK//r6+v/7Ozs/w4ODv/AwMD/7Ozs/+3s7f/r7Ov/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/t7O3/7e3t/+3s7P/t7e3/7e3t/+3t7f/t7e3/7u7u/+3t7f/u7e3/7e3t/+3t7f/t7e3/7e3t/+7u7f/t7u3/7u7t/+7u7v/s7Oz/7Ozs/+zs7P/s7ez/7Ozt/+3t7f/t7e3/7e3t/+zs7P/s7O3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7u3t/+7u7v/u7u7/7u7u/+7u7v/u7u7/7e3t/+3t7f/u7u7/7u7u/+7u7v/u7u7/7+7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u/v/+/u7//v7u//7u7u/+7u7v/u7u7/7+/u/+7v7v/v7+//7u7u/+/v7//v7+//7+/v/+/v7//v7+//7+/w//Dw8P/v7+//8PDw/+/v7//w7/D/7+/v/+/v7//w8O//8PDw//Dw8P/w8PD/7u7u/+/u7v/u7u7/7+7v/+/v7//v7+//7+/v/+/v7//u7u//7+/v/+/u7v/v7+//7+/v//Dv8P/v7+//7/Dw//Dw7//v8O//8PDv//Dw8P/w8PD/8PDw//Dw8P/w8PD/7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PH/8PDw//Hx8P/w8PD/8PDw//Dw8P/w8PD/8fDw//Hx8f/x8fH/8fHx//Dw8P/x8PD/8PDw//Dx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/y8vL/8fHx//Ly8v/x8fH/8fHx//Hx8f/x8fH/8vLy//Ly8v/y8vL/8vLy//Hx8P/x8fH/8PDx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//y8vL/8vLy//Ly8v/y8vL/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9PT0//T09P/09PT/8/Pz//Pz8//z8/P/9PT0//T09P/09PT/9PT0//T09P/y8vL/8/Pz//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//09PT/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9PT0//T09P/09PT/9PT0//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//b29v/19fX/9vb2//X19f/19fX/9fX1//X19f/29vb/9vb2//b29v/29vb/9PT0//X19f/09PT/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//f39//29vb/9/f3//b29v/29vb/9vb2//b29v/39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//j4+P/39/f/9/f3//f39//39/f/9/f3//j4+P/4+Pj/+Pj4//b29v/39/f/9vb2//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/r6+w/6+wsP+wsLD/r7Cw/6+vr/+wsLD/r7Cv/6+wsP+vr7D/r6+v/7CwsP+vr7D/r7Cv/6+wsP+wsK//sLCw/6+vsP+wsLD/sbCw/7Cxsf+xsbH/sLCw/7CwsP+wsLH/sbGw/7CxsP+xsbH/sLGx/7Gxsf+wsLD/sLCx/7Cxsf+vr7D/r6+w/7Cvr/+vsLD/sK+v/7Gxsf+wsLH/sbCw/6+wr/+wsK//sLCw/7Gwsf+xsbH/sLCw/7Cwsf+wsbH/sLCw/7Cxsf+wsLD/sLCx/7Cxsf+xsbH/sLCw/7Kysv+xsLD/sLCw/7Cwsf+xsLD/srGx/7Gxsf+xsbH/sbKy/7CwsP+xsbL/sLGx/7Gysf+ysrH/sbGx/7Gysv+ysbH/srGx/7Kxsv+ysrH/srKx/7Gxsf+xsrH/srKy/7Gxsf+xsrL/sbGy/7Kxsv+ysbH/srOy/7Oys/+zs7L/s7Ky/7Gxsf+ysrL/sbGx/7Oysv+ysrP/s7Oy/7Kysv+zs7P/sbGy/7Kxsf+ysbH/sbKy/7Kysf+ysrL/sbKx/7Gxsv+ysrH/sbGx/7Kysf+xsrH/sbGy/7Kzsv+xsrH/s7Ky/7Oys/+zs7L/s7Kz/7Kzs/+ysrL/s7Oz/7Ozsv+zsrL/s7Kz/7Oys/+zs7L/s7Oy/7Kzsv+ysrL/s7Kz/7S0s/+zsrP/srOz/7Kys/+zs7P/tLO0/7O0s/+zs7T/tLO0/7Oysv+zs7T/srKz/7O0s/+0s7P/tLOz/7OztP+0tLT/tLSz/7Ozs/+0s7P/tLS0/7O0tP+0tbX/tLS1/7S0tf+zs7P/tLO0/7O0tP+1tLT/tbW0/7S1tP+1tLT/tLS0/7Oysv+zs7P/tLO0/7OztP+zs7T/tLSz/7SztP+zs7T/s7O0/7SztP+zs7P/tLS0/7O0s/+0tLT/tLOz/7W1tP+0tLP/tbW0/7S1tf+0tbT/tLS0/7S0tf+0tbT/tbW1/7W0tf+0tLT/tbS1/7S0tP+1tLT/tbW0/7S0tf+1trX/tbS0/7S0tP+1tLX/tbS0/7S0tP+1trb/tba2/7a2tv+0tbT/tLW0/7W0tP+1tbX/tba1/7W1tf+2trX/tba1/7W2tf+2tbX/trW2/7a2tf+2tbX/tre2/7e2t/+3t7f/tba1/7W1tf+2tbX/t7e2/7e3tv+3t7f/tre2/7a2tv+0tbX/trW2/7W2tf+1tbX/tra2/7a1tv+1trX/tba1/7W1tv+2trb/tra2/7W1tv+2trb/tra2/7a1tf+3trb/trW2/7e2t/+2trb/t7a3/7a3tv+2trf/t7e2/7e3tv+2trb/t7e2/7a3tv+2trb/t7a2/7e2tv+2t7b/t7i4/7a3tv+2t7f/tra2/7a2t/+3t7f/uLi3/7e3t/+3uLj/tre3/7a2tv+2t7f/t7i4/7i3t/+3uLf/uLe3/7e3t/+3t7f/t7i3/7e3t/+3t7f/uLe3/7i5uf+5uLj/ubi5/7i4t/+3t7f/t7e3/7m4uP+4ubj/uLm4/7m4uf+5uLj/t7e3/7e4t/+3uLf/uLe4/7i3t/+4uLf/t7e3/7e3t/+3t7j/t7e4/7i3uP+3uLf/uLi3/7e3uP+4uLf/ubi5/7i3uP+4ubj/uLm4/7i5uP+4uLn/ubm5/7m5uP+4ubj/ubi4/7m4uf+4ubj/uLm4/7m4uP+5uLj/ubm5/7m5uf+4ubn/uLi5/7i5uf+5ubj/ubm4/7m5uf+5ubn/ubm5/7i5uf+5ubj/ubi4/7m5uf+5ubn/ubm6/7q6uv+5ubr/urm5/7m5uv+5ubn/ubq6/7q6uv+6urv/urq6/7u6uv+5ubr/urq6/7m5uv+6urr/u7q7/7q6u/+6urr/u7u6/7i5uP+5ubn/ubm5/7q5uv+6ubn/ubm5/7m5uf+5urn/ubm5/7m6uf+6urn/ubq6/7m6uv+6urr/urq5/7q6uv+6urr/uru6/7q6uv+7u7r/urq6/7q6uv+7u7r/u7u7/7u7uv+7urr/urq6/7q7uv+6urr/u7u7/7u7u/+7u7v/uru6/7q6uv+6urv/u7u7/7u7u/+7u7v/u7u7/7u7u/+6urr/u7u7/7u7u/+7u7v/u7y7/7y7u/+7u7v/u7u8/7y7u/+8vLz/u7u7/7y8vP+8vLz/vLy8/729vP+8vbz/vLy8/7y8vP+8vLz/vby9/7y8vf+9vLz/vLy8/729vf+7u7v/u7y7/7u7u/+8u7z/vLy8/7y8vP+8vLv/vLy8/7u7vP+7vLv/u7y7/7u8vP+8vLz/vLy8/7y8vP+8vb3/vLy8/729vP+8vLz/vb28/728vP+9vb3/vb29/729vf+8vbz/vLy8/728vf+9vb3/vb29/769vf+9vb3/vr69/7y9vf+9vb3/vb29/729vf++vb7/vr29/729vv++vb3/vb29/769vv+9vb3/vb69/76+vv++vr7/vr2+/76+vv++vr7/vr6+/76+vv+/v77/vr6+/76+vv+/vr//v7+//76+vv++vr7/vr++/7++vv++vr//v7+//7+/v/+/v7//vr29/769vv++vb3/vr29/76+vv++vr7/vr6+/76/v/+9vr3/vr6+/72+vf++vr7/vr6+/7++v/+/vr7/vr6+/76+vv+/vr//vr6+/7+/v/+/v7//v7+//7+/v/+/v8D/v7++/7+/v/+/v7//wL+//8DAwP+/v7//v8C//8C/v/+/v7//wMC//8DAv/+/wMD/v8DA/8DAwP+/v8D/wMDA/7/Av/+/wMD/wL+//8C/v//AwMD/wcDA/8DAwP/AwcD/wcHB/8HAwP/BwMD/wcHB/8DAwf/BwcH/wcHB/8HBwv/BwMH/wcDB/8HBwf/BwcH/wcHB/8HCwv/BwcL/wsHC/8DAv//AwMD/v8C//8DAwP/AwMD/wcHA/8HAwP/AwcD/wMDA/8HAwf/AwMD/wMDA/8DBwf/BwcD/wcHB/8HBwf/AwMD/wcHB/8HBwf/BwsH/wcHB/8HBwf/BwcL/wsLC/8HBwf/BwcH/wsLB/8HBwv/BwcH/wsLC/8LCwv/CwsL/wcLB/8HBwf/CwcH/wsLC/8LCwv/DwsP/wsLC/8LDwv/CwsH/wsLC/8LCwv/CwsL/wsLC/8LDwv/Dw8P/wsLC/8LDw//Dw8P/w8PD/8PDw//Dw8P/w8TD/8PExP/DxMP/w8PD/8TDxP/Dw8P/xMTD/8TDw//ExMT/xMTD/8TExP/CwsL/w8LD/8LCwv/CwsP/w8LC/8PDw//CwsP/w8PD/8PCw//DwsL/w8PC/8PDw//Dw8P/xMPE/8PDw//DxMP/xMTE/8PDw//Ew8P/w8PD/8TExP/ExMT/xMTE/8TExf/ExMT/xMTE/8TEw//ExMT/xMTE/8XFxf/FxcT/xcTE/8TExP/ExMT/xMTE/8TExf/ExcX/xcXF/8TExf/FxcX/xMTE/8TExf/ExcX/xMXE/8XExf/FxcX/xcXF/8bGxv/FxcX/xcbG/8XFxv/GxcX/xcXF/8bGxv/Gxsb/xsbG/8bGxf/GxsX/xcXF/8bGxv/Gxsb/xsfH/8bGx//Hx8b/xcTE/8TExf/FxcX/xcXF/8XFxf/Gxcb/xsXG/8bGxv/FxMX/xcXF/8XFxf/Gxcb/xcbF/8bFxf/Fxcb/xsbG/8XGxv/Gxsb/xsbG/8bHxv/Hxsf/xsfH/8fGxv/Hx8f/xsbG/8bGxv/Gx8b/x8bG/8bGxv/Hx8f/x8fG/8fHx//Hx8f/xsfG/8bGx//Hxsb/x8fH/8jHyP/Hx8f/x8fH/8bGx//Hx8f/xsfH/8fHx//Hx8f/yMjH/8jIx//Hx8f/yMfI/8jIyP/IyMf/yMjI/8nIyf/Iycj/yMnI/8jIyf/IyMj/ycjJ/8jIyP/Jycn/ycjI/8nJyf/IyMj/ycnJ/8fHx//IyMf/x8fH/8jHyP/Hx8j/yMjI/8fIyP/IyMj/x8fH/8fHx//IyMj/x8fH/8jIyP/Jycj/yMjI/8jJyf/JyMj/yMjI/8jIyP/Jycj/ycnJ/8nJyv/Jycn/ysnJ/8jIyP/Jycn/yMjJ/8nJyf/Jysn/ycrK/8nKyf/Jysn/ycnJ/8nJyf/Jycn/ycnJ/8nJyf/Kysr/ycnJ/8rKyv/Jysn/ycnJ/8rKyf/Jysr/ysrK/8vKyv/Kysr/ysrL/8vLyv/Ky8r/y8rL/8vKyv/Ly8v/y8vM/8vLy//LzMv/y8vL/8vLy//Kysr/y8vL/8vLy//MzMv/zMzL/8zLzP/Jycn/ysrK/8nJyv/Kysr/ysvK/8rKyv/Lysr/y8vK/8rKyv/Ky8r/ysrK/8vKyv/Ky8v/y8rK/8rLy//Ly8v/y8vL/8vLy//Ly8v/zMvM/8vLzP/My8v/y8zL/8zMzP/Ly8v/zMvM/8zLy//LzMz/y8vL/8zMzP/MzMz/zczM/8vLzP/LzMv/y8vL/8zMzP/MzMz/zM3N/8zMzP/Mzcz/zMvL/8zMzP/MzMz/zM3M/8zMzP/Nzcz/zMzN/83Nzf/NzMz/zc3N/83Nzf/Ozc3/zs7N/87Ozv/Ozs3/zs7O/83Nzf/Nzc3/zs3N/83Nzv/Ozs3/zs7O/87Ozv/Oz8//zMzM/8zMzP/MzMz/zczM/83MzP/Nzc3/zc3N/83Nzf/Mzcz/zMzN/8zMzP/Nzc3/zc3N/83Nzf/Nzc3/zs3N/83Nzv/Nzc3/zc3O/87Ozv/Ozs7/zs7O/8/Oz//Pzs//zc3O/87Ozv/Ozs7/zs7O/87Pzv/Pz87/zs/O/8/Pz//Ozs7/zs7O/87Ozv/Pz87/zs/P/8/Pz//Pz8//z8/P/87Pzv/Ozs7/z8/O/8/Pz//Pz8//z8/P/9DQ0P/Q0M//0NDQ/9DPz//Pz8//0NDQ/9DQ0P/Q0ND/0dDQ/9HR0f/Q0M//0NDQ/9DQ0P/Q0ND/0NDR/9HQ0P/R0dD/0dHR/87Pz//Pz8//z8/P/9DPz//P0ND/z8/P/9DQz//Q0ND/z8/P/8/P0P/P0M//0M/Q/9DPz//Q0ND/0NDQ/9HQ0P/Q0ND/0dDQ/9HQ0P/Q0dH/0dDR/9HR0f/R0dH/0tHR/9DR0f/R0NH/0NDQ/9HR0f/R0dH/0dHS/9HR0f/S0dL/0dDQ/9HR0f/R0dH/0dLR/9HR0v/R0dL/0dLS/9LS0v/R0dH/0tLR/9LR0f/R0tL/0tLS/9LS0v/S0tL/09LT/9LS0v/T0tP/0tLS/9LS0//S09L/09PT/9PT0//U1NP/0tPS/9PS0//S0tL/09PT/9PT0//T09P/09PU/9PU1P/R0dH/0tHR/9HR0v/S0tL/0tLS/9PT0v/T0tL/09LT/9HS0f/S0tL/0tLS/9PS0v/T09P/09PS/9LT0//T09P/09PS/9PT0//T09P/1NPU/9TU0//T1NT/09PT/9TU1P/T09P/1NTU/9TT1P/U1NT/09PT/9TU1P/U1NT/1dTV/9TT0//U09T/1NTT/9TU1P/U1NT/1NTV/9XU1P/V1dX/1NPU/9TU1P/U1NT/1NTV/9TV1f/V1NT/1dXV/9TU1P/V1dX/1dXV/9XV1P/V1dX/1dXV/9bV1v/W1db/1tbW/9XV1f/V1dX/1dXV/9bW1f/V1db/1tbW/9XV1f/W1tb/1NTU/9TV1f/V1dT/1NXV/9XU1f/V1dX/1NTV/9XV1f/U1NT/1NXU/9XV1f/U1dX/1dXV/9XV1f/V1dX/1dXV/9XV1f/W1db/1tbV/9XW1v/W1tb/1tbW/9bW1v/W1tb/1tbV/9bW1v/W1dX/1tbW/9bW1v/X19f/1tbW/9fW1//W1tb/1tbW/9bW1v/W1tb/1tbW/9fX1//W19b/19fX/9bW1v/W19f/1tbW/9bX1v/X19f/19fX/9fX1//X19f/19fX/9fY2P/X19f/2NfX/9jY2P/Y2Nj/2NjY/9jY2P/X19j/2NjY/9fY1//Y2Nj/2NjY/9jZ2P/Y2Nj/2djZ/9fX1v/X19f/19fX/9fX1//X19f/19fY/9fX1//Y19f/19fX/9fX1//X19f/19fX/9fY2P/Y2Nj/19jX/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9nZ2f/Y2Nj/2dnZ/9jY2P/Z2Nj/2NjY/9jY2P/Z2dn/2dnZ/9nZ2f/Z2dn/2djY/9nZ2f/Y2Nn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2v/Z2dn/2dnZ/9nZ2f/Z2dn/2dra/9ra2v/Z2tr/2tra/9ra2v/a2tr/2tra/9ra2v/b29v/29vb/9rb2//b29v/2tra/9ra2//a2tr/29rb/9vb2//b29v/29vb/9vb2//Z2dn/2dna/9nZ2f/Z2dr/2tra/9ra2v/a2tr/2tra/9rZ2f/a2tr/2drZ/9ra2v/a2tr/2tva/9ra2v/a2tr/2tra/9vb2//a2tr/29vb/9vb2//b29z/29vb/9vb2//b29v/29vb/9vb2//b29v/3Nzb/9zc3P/b3Nz/3Nzc/9vb2//c29z/29vb/9vb2//c3Nz/3Nzc/9zc3P/c3Nz/3Nzb/9zc3P/b29v/3Nzc/9zc3P/d3Nz/3Nzc/9zd3P/c3Nz/3d3d/9zc3P/d3d3/3d3d/97e3v/d3d3/3t7e/93d3f/d3d3/3d3d/93d3f/d3d7/3t7e/97e3f/e3t7/3Nzc/9zc3P/c3Nz/3Nzc/9zd3f/d3d3/3d3d/93d3f/c3Nz/3Nzc/9zc3P/c3dz/3d3d/93d3f/d3d3/3d3d/93d3f/e3d3/3d3d/93e3f/e3t7/3t7e/97e3v/e3t7/3t3e/97e3v/d3d3/3t7e/97e3v/f3t7/3t7e/9/f3//e3t7/3t7e/97e3v/e3t7/39/f/9/f3//e397/39/f/97e3v/f3t7/3t7e/97f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//4ODf/9/f4P/g4OD/4ODg/+Dg4P/f39//3+Df/+Df3//g4OD/4ODg/+Dg4P/g4OD/4ODg/9/f3//f39//3t7e/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//g3+D/4ODf/+Dg4P/g3+D/4ODg/+Dg4P/g4OD/4ODg/+Dh4P/h4OD/4eHh/+Dg4P/g4OD/4ODg/+Hg4f/h4OH/4eHh/+Hh4f/h4eH/4ODg/+Dh4P/h4OD/4eHh/+Hh4f/h4eH/4eHh/+Hi4f/g4OD/4eHh/+Hh4f/h4eH/4eHh/+Lh4f/h4eH/4uLi/+Hi4f/i4uL/4uLi/+Li4v/i4uL/4uLi/+Lj4//j4+P/4uLi/+Li4v/i4uL/4uLi/+Pj4v/j4+P/4+Pj/+Pj4//h4eH/4eHh/+Hh4f/h4eL/4uHh/+Li4v/i4uL/4uLi/+Hh4f/h4eL/4eHh/+Li4v/i4uL/4uLi/+Li4v/j4uP/4uLi/+Lj4v/i4uP/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//i4+L/4+Pj/+Pj4//j4+P/4+Pj/+Tk5P/j4+P/4+Tj/+Pj4//j4+P/4+Pj/+Pj4//j4+T/5OTk/+Tk5P/k5OT/4+Pj/+Tk5P/j4+P/4+Pk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5eTk/+Tk5P/l5OT/5eXl/+Xl5f/l5eX/5eXl/+Tk5P/l5eX/5OTl/+Xl5f/l5eX/5uXl/+Xl5f/m5uX/4+Pk/+Tk5P/k5OP/5OTk/+Tk5P/l5OX/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OXk/+Xl5f/k5eT/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/m5eX/5ebm/+Xm5f/m5ub/5eXl/+Xm5f/l5eX/5ubl/+Xm5v/m5ub/5ubm/+bm5v/m5uX/5eXl/+Xl5f/m5ub/5ubm/+bm5v/m5ub/5+bm/+Xm5v/m5ub/5ubm/+bm5v/m5ub/5ubn/+fm5v/n5+f/5ufn/+fn5//n5+f/5+fn/+fn5//o6Oj/5+jo/+jo6P/n5+f/5+fn/+fn5//o6Oj/6Ofn/+jo6P/n6Oj/6Ojo/+bm5v/m5ub/5ubm/+fm5//m5ub/5+fn/+fn5//n5+f/5ubm/+bm5//m5ub/5+fn/+fn5//n5+f/5+fn/+fo5//n5+f/5+fn/+fn6P/n6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+fn5//o6Oj/5+fo/+jo6P/o6Oj/6Ojp/+jo6P/p6en/6Ojo/+jo6P/o6Oj/6Ojo/+no6f/p6en/6Ojp/+np6f/o6Oj/6Ono/+jo6P/p6ej/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+rp6v/q6ur/6urq/+rq6v/q6ur/6enp/+rp6f/p6ur/6urq/+rq6v/q6ur/6urq/+vr6//p6ej/6enp/+np6P/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+nq6v/q6ur/6enq/+rq6v/q6ur/6urq/+rq6v/r6ur/6urq/+vr6//q6ur/6urq/+rq6v/q6ur/6uvr/+vr6//q6ur/6+vr/+rq6v/r6+v/6urr/+vq6//r6+v/6+vr/+vr6//r6+v/6+rr/+vr6//r6uv/6+vr/+vr6//r7Ov/6+vr/+vs7P/r7Oz/7Ozr/+zs6//s7Oz/7Ozs/+zs7P/s7Oz/7O3s/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7O3s/+3t7P/s7e3/6+vr/+vr6//r6+v/6+vr/+zs6//s7Oz/7Ozr/+zs7P/r6+v/6+vr/+vr6//r7Ov/6+zs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zt7f/t7Oz/7e3t/+3s7P/t7e3/7Ozs/+3t7f/t7O3/7ezt/+3t7f/t7e3/7e3t/+3t7f/s7Oz/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e7u/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3u/+3u7f/u7u7/7e3u/+7u7v/u7u7/7u7u/+7u7v/u7+//7u7u/+7u7//u7u7/7u7u/+7u7v/v7+//7+/v/+/v7//v7u7/7+/v/+3t7f/t7u3/7e3t/+3u7v/u7u3/7u7u/+7u7v/u7u7/7u7u/+7u7v/t7e3/7u7u/+7u7v/u7u7/7u7u/+/u7//u7u7/7u/u/+/v7v/v7+7/7+/v/+/v7//v7+//7+/v/+/u7//v7+//7u7u/+/v7//v7+//7+/v/+/v7//v8O//7+/v/+/v7//v7+//7+/v//Dw8P/v8PD/7/Dw//Dw8P/v7+//8PDv/+/v7//w8PD/8O/w//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/x8PH/8fHx//Hw8P/x8fH/8PDw//Hw8f/w8PD/8fDx//Hx8f/x8fH/8fHx//Hx8f/v7+//8PDw/+/v7//w8PD/8PDw//Dw8P/w8PD/8PDw/+/v7//w8PD/8PDw//Dw8P/w8PD/8PHx//Dw8P/w8fD/8fDx//Hx8f/w8PD/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Pz8//y8vL/8/Pz//Ly8v/y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//z8/P/8fHx//Ly8v/x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/19fX/9PT0//X19f/09PT/9PT0//T09P/09PT/9fX1//X19f/19fX/9fX1//Pz8//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/19fX/9fX1//X19f/19fX/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//b29v/39/f/9vb2//b29v/29vb/9vb2//f39//39/f/9/f3//f39//19fX/9vb2//X19f/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//f39//29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//4+Pj/9/f3//f39//39/f/9/f3//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//j4+P/5+fn/9/f3//f39//39/f/+Pj4//j4+P/4+Pj/+Pj4//j4+P/39/f/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/5+fn/+fn5//n5+f/5+fn/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f+wr6//sLCw/7Cwsf+wsLH/sLGw/7GwsP+xsbH/sLCx/7Cwsf+wsbH/sbCx/7Cxsf+wsbH/sLGx/7CwsP+xsLD/sLCx/7Kysv+xsLH/sbKy/7Kysv+xsrH/srGx/7Kxsv+wsbD/srGy/7Gxsv+ysbH/sbKx/7Kxsf+ysbL/sbGx/7Gxsf+xsLD/sbCw/7CxsP+xsLD/sbGw/7GxsP+xsbH/sbCw/7Cxsf+wsbH/sLCx/7CxsP+xsbL/sbKx/7Kysf+ysbH/srGy/7Gysv+ysbH/sbGy/7Kxsv+ysrL/srGx/7Kysv+ysbH/srKy/7Gxsf+ysbH/srKy/7Gxsv+ys7L/sbGy/7Gysv+xsrH/sbGy/7Kzs/+ysrP/srKy/7Kzsv+xsbL/srKy/7Kxsv+ysrL/srKy/7Oysv+zs7L/s7Ky/7Kzs/+ys7L/srKy/7Kys/+zs7L/tLOz/7O0s/+zs7P/s7Ky/7Ozs/+zsrP/s7O0/7Szs/+0tLP/s7O0/7OztP+ys7P/s7Oy/7Kzs/+ys7L/srKz/7Kzsv+zs7L/srOz/7Kys/+zsrL/s7Ky/7Kzsv+zsrP/srOy/7Kysv+0tLP/s7Kz/7Szs/+ztLP/tLSz/7S0s/+zs7P/tLS0/7O0s/+zs7T/s7S0/7OztP+zs7T/s7Oz/7OztP+zs7P/tLW1/7SztP+0s7T/tLS0/7S0tP+zs7T/tbW1/7W0tf+0tLT/s7O0/7O0s/+ztLP/tLS1/7W1tP+0tLX/tbW0/7S0tP+1tbX/tLW0/7S0tf+1tLX/tLS1/7W2tv+1tbX/trW2/7W0tP+1tLT/tLS0/7W1tf+2tbb/tbW1/7W2tf+2trX/s7Sz/7S1tP+1tbT/tLS0/7W0tP+0tbT/tbW0/7S0tf+0tbT/tbW1/7S1tP+0tbT/tLW0/7S0tf+1tLT/tbW1/7W0tP+1trb/tba2/7a1tf+1trX/tba1/7W1tv+2trX/tbW2/7W2tv+2trX/tra1/7W1tv+1tbb/trW2/7W1tf+1trb/tba1/7a1tv+1trb/tbW2/7e3t/+2trX/tre2/7W1tf+2tbb/tba2/7a2tf+3trb/t7e3/7e3t/+3trb/tre3/7e2t/+3t7b/tra2/7a3t/+4uLf/t7i4/7e4uP+2t7f/t7e2/7e2t/+3uLj/t7e3/7i3t/+3t7f/uLi3/7a1tf+3trb/tra1/7e3t/+3trb/tra3/7a2tv+2trf/tre3/7e3t/+2trf/t7a2/7a2t/+3t7f/tra2/7i3uP+2trb/t7i4/7e3uP+3uLf/uLe3/7e3t/+4t7j/uLi3/7e3t/+3uLj/t7i4/7i3uP+4t7f/t7e4/7e3t/+5uLj/uLe3/7e3t/+3t7j/uLe3/7i3uP+4uLj/ubi5/7m4uf+3uLf/t7e3/7e4t/+5ubj/uLm4/7m5uP+4uLj/uLi4/7i5uP+4ubj/uLi5/7i4uP+5ubj/ubm5/7m5uf+5ubr/ubi5/7m5uf+5ubj/ubm5/7m5uf+5urr/urq6/7q5uv+3t7f/uLi5/7i4uf+4uLn/uLm5/7m4uf+5uLn/uLm4/7i5uP+4uLj/uLi5/7m4uP+4ubn/ubm5/7m4uP+5ubn/uLm5/7m5uf+5ubn/ubq5/7q6uf+5urn/ubm5/7q5uf+5ubn/urm5/7m6uv+6ubn/urm5/7q6uv+5urr/urq6/7q5uf+6urn/ubq5/7q5uv+6urr/u7u6/7q6uv+7u7r/urm5/7q6uv+5urr/urq6/7u6u/+7urr/uru6/7u6u/+6urr/uru7/7u6uv+7u7v/u7u7/7u8u/+7u7v/vLu8/7q7uv+7u7v/u7u7/7u7u/+8vLv/vLu7/7y8vP+8vLv/urq6/7q6uv+6urr/u7u6/7u7u/+6urv/u7q6/7u7u/+6urr/uru6/7q6u/+6u7r/uru7/7u7u/+7u7v/u7u7/7u7u/+8u7v/u7u7/7y7vP+8u7v/vLy8/7u8u/+8vLz/u7u7/7u8u/+7u7v/vLu8/7y8vP+8vLz/vLy8/7y9vf+7vLv/vLy8/7y7vP+8vLz/vLy8/7y9vP+9vb3/vL28/7y8vP+8vLz/vLy8/728vP+8vLz/vLy9/728vf+9vb3/vLy9/729vf+9vb3/vb29/76+vv++vr7/vr6+/729vf+9vb3/vr6+/729vf+9vr3/vr6+/76+vv++vr3/vr6+/7y8vP+8vb3/vLy9/729vf+8vbz/vb29/728vf+9vb3/vby9/7y8vP+8vbz/vL28/729vf+9vr3/vLy8/729vf+9vb3/vr2+/729vf++vr7/vr6+/76+vv++vb3/v76//72+vv+9vr3/vb2+/769vv+9vb3/vr6+/76/vv++vr7/vr6+/76+vv++vr7/vr+//7+/v/++v7//vr6//7+/v/++vr7/v7++/7+/v/+/v7//v7++/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/wP+/wMD/wMDA/8C/wP/AwMD/wMDA/8DAwP/AwMD/v7+//8DAwP/AwMH/wMDA/8DAwf+/vr7/vr+//76/vv+/v7//v7+//7/AwP+/v7//wMDA/76/vv+/v7//v7+//7+/v/+/v7//wL+//7+/v/+/wL//v8C//8DAwP/Av8D/wMDA/8HAwf/BwMD/wcDA/8HAwP/AwMD/wcHA/8DAwP/AwMH/wcDA/8DAwP/AwMH/wcHB/8HBwP/BwMH/wcHB/8DBwf/AwMD/wcHB/8HBwf/BwcH/wcHA/8DBwf/AwcH/wcHB/8HBwf/CwsH/wcHC/8HCwf/BwcL/wcHC/8LCwf/CwsL/wsLC/8LDwv/CwsL/wsLC/8LBwv/CwsL/wsLC/8LCwv/DwsL/wsLC/8PCw//Cw8P/wcDB/8HBwf/BwcH/wcLC/8LBwf/BwsL/wsHB/8LCwv/BwcH/wcLB/8HBwv/CwcH/wsLB/8LCwv/CwsL/wsLC/8LCwv/CwsP/wsLC/8PDw//Dw8P/w8PD/8LCw//Dw8P/w8PD/8PCwv/Cw8L/w8LC/8PDw//ExMP/w8PD/8TExP/Dw8L/w8PD/8PCwv/Dw8P/xMTD/8TDw//Dw8T/xMTE/8PDw//DxMP/w8PD/8PDw//Dw8P/xMTE/8PDw//ExMT/xMTE/8TExP/ExMT/xcTE/8XExf/ExMX/xcXE/8XFxf/ExMT/xMTF/8XExf/FxcT/xMTE/8XFxf/FxcX/xsbF/8PDw//DxMP/w8TE/8PEw//ExMT/xMTE/8TExP/ExcT/w8PD/8TExP/ExMT/xMTE/8TExP/FxcX/xMTE/8XExf/ExcX/xcTE/8TExf/FxcX/xcXF/8bFxv/Gxcb/xsXG/8XExf/FxcX/xcXF/8bGxv/Fxcb/xcXF/8bFxf/Gxsb/xcXF/8bFxf/GxcX/xsbF/8bFxf/Gxsb/xsbG/8bHx//Fxcb/xsbF/8XFxf/Gxsb/xsbG/8fHxv/Hxsb/xsbG/8bGx//Hx8b/xsfG/8fHx//Hx8f/x8jI/8fHx//Hx8f/xsfG/8fHx//Gxsf/x8fH/8jIyP/IyMj/yMjI/8jIx//Fxsb/xsbG/8bGxv/Gx8f/xsbH/8bGx//Gxsf/xsbG/8bGxv/Hxsb/x8fG/8bHx//Hx8b/x8fH/8bHx//Hx8f/x8fH/8fHx//Hx8f/x8jH/8jIyP/IyMj/yMjH/8jIyP/Ix8j/x8fI/8fHyP/Hx8j/yMjI/8jIyP/IyMj/ycnI/8jHyP/IyMj/yMjI/8jIyP/IyMj/ycjJ/8nIyP/JyMj/yMjI/8jJyf/IyMj/yMjI/8nIyP/Jycn/yMnJ/8nJyf/Jycn/ycnJ/8nJyf/Kysn/ycrJ/8rKyv/Kysr/ysrK/8nKyv/Jysn/ycrK/8rKyf/Kysr/ysrL/8rKyv/Lysv/yMnJ/8nJyf/Jycj/yMnI/8nJyf/Jycn/ycnJ/8rJyv/JyMn/ycnJ/8nIyf/Jycn/ysrJ/8nJyf/Kycn/ycrK/8rJyv/Kysr/ysnK/8rKyv/Kysr/ysrK/8rKyv/Ly8r/ysrK/8rKyv/Kysr/y8vL/8vKyv/Kysr/ysvK/8vLy//Kysv/ysrL/8rLy//Kysr/ysvK/8vLy//Ly8v/y8zL/8rLy//Ky8v/ysrK/8vLy//Ly8v/y8zM/8vMzP/My8z/y8vL/8zLy//LzMv/zMzM/8zMzP/Mzcz/zc3M/8zMzf/Ly8z/zMzM/8zMzP/Mzcz/zM3M/83Nzf/NzM3/zc3N/8rKyv/Ly8v/y8vL/8vMzP/LzMz/zMzL/8vMzP/MzMz/y8vL/8vMzP/My8v/y8vL/8vMy//MzMz/zMzM/8zNzP/MzMz/zczN/83Nzf/Nzc3/zczM/83Nzf/Nzc3/zs7N/83Mzf/MzM3/zM3N/83Nzf/Nzc3/zc7N/87Nzf/Ozs3/zMzM/83Nzf/Nzc3/zs3O/83Ozf/Nzc7/zc7N/87Ozv/Nzc3/zc7O/87Nzv/Nzs3/zs7N/87Ozv/Ozs7/zs7P/87Ozv/Pz8//zs7O/87Oz//Pzs//z8/P/8/Pz//Qz8//z87O/87Ozv/Pzs//z8/P/8/Pz//Pz9D/0M/Q/8/Pz//Ozs7/zs3O/83Nzv/Ozs7/zs7O/87Ozv/Pzs7/zs7O/83Ozf/Ozs7/zs7O/87Pzv/Oz8//z8/O/87Ozv/Pz8//z87P/8/Pz//Pz8//0M/Q/9DQz//Pz8//z9DQ/9DQ0P/Pz8//z8/Q/9DP0P/Qz9D/z8/P/9DQ0P/Q0ND/0NHQ/8/Qz//Qz9D/z9DP/9DQ0P/Q0ND/0dHR/9DQ0f/Q0ND/z8/P/9DQ0P/Q0ND/0NDR/9HQ0P/R0dD/0NHR/9HR0f/Q0NH/0dHR/9HR0f/R0dL/0dHS/9HR0v/S0dH/0tLS/9HR0f/S0dL/0tHS/9HS0v/R0dH/0tLS/9LS0v/T09L/0NDQ/9HR0P/Q0dD/0dHQ/9DQ0P/R0dH/0dHR/9LS0v/Q0dH/0NDQ/9HQ0P/R0dH/0dHR/9HR0f/S0dL/0tHS/9HR0v/R0dH/0tLR/9LS0v/S0tL/09PS/9PS0v/S09L/0dLR/9LS0v/S0tL/09LT/9PS0v/T0tL/09PT/9PT0//S0tL/0tLT/9PT0//S09L/0tLS/9PT0//T09P/1NPU/9LS0v/S09P/0tLS/9PT0//T09P/1NPU/9TT0//T09P/09TT/9TT1P/T1NP/1NTU/9TU1P/U1NX/1NTU/9XU1P/U1NP/1NTU/9TU1P/U1NT/1NTU/9XU1f/U1dX/1dXV/9PS0//T09P/09PT/9PU1P/T09P/1NTT/9TT0//T09P/09PT/9PT1P/U09P/09PT/9TU1P/U1NT/09PU/9TU1P/U1NT/1NTV/9TU1P/V1NT/1NXU/9XV1f/U1NX/1dXV/9TV1f/V1dT/1NTU/9XU1f/V1dX/1dXV/9XV1f/V1dX/1NTU/9XV1f/U1dT/1dXV/9XV1f/V1tX/1dXV/9XV1v/V1dX/1dXV/9XV1f/V1dX/1tXV/9bW1v/V1dX/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tf/19fX/9fX1//X19f/1tbW/9fX1v/W1tb/1tbX/9fX1//X19f/19fX/9fX1//V1dX/1dbV/9XV1f/V1tX/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1dXW/9bW1v/W1tb/1tfX/9bW1v/W1tf/19bW/9fX1//X19f/19fX/9fX1//X19j/19fX/9jY1//X19f/19fX/9fX1//X19f/19fX/9jY2P/Y2Nf/2NjY/9fX1//Y19f/19fX/9jY1//Y2Nj/2NjY/9jY2P/Y2Nj/2NjX/9jY2P/Y19f/2NjY/9jY2P/Z2Nn/2NjY/9jZ2P/Z2dj/2dnZ/9nY2f/Z2dn/2dnZ/9ra2f/Z2dn/2tnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/a2dn/2tra/9rZ2v/a2tr/2NjY/9jY2P/Y2Nj/2NjY/9jZ2f/Z2dn/2NjZ/9nZ2f/Y2Nj/2djY/9jY2P/Z2Nn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2v/a2tr/2tra/9ra2v/a2tr/2tna/9ra2v/Z2tr/2tra/9ra2v/a29v/2tra/9vb2v/a2tr/2tra/9ra2v/a2tr/2tra/9vb2//a29r/29vb/9ra2v/b29v/2tra/9ra2//b29v/29vb/9vb2//b29v/29vb/9vb3P/b29v/29zc/9zc3P/c3Nz/3Nzc/9zc3P/b3Nz/3Nzc/9vb2//c3Nz/3Nzc/93d3P/c3Nz/3Nzd/9ra2v/b29v/29rb/9vb2//b29v/29zb/9vb2//c3Nv/29vb/9vb2//b29v/29vb/9zc3P/c3Nz/3Nzb/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzd/93d3f/d3N3/3d3d/9zc3P/c3Nz/3Nzc/93d3f/d3d3/3d3d/93d3f/d3d3/3Nzc/93d3f/d3N3/3d3d/93d3f/e3t3/3d3d/97e3f/d3d3/3d3d/93d3f/d3d3/3t7d/97e3v/e3d3/3t7e/97e3v/e3t7/3t7e/97e3v/e39//39/f/97e3//f39//3t7e/9/e3//e3t7/397e/97f3//f39//39/f/9/f3//d3d3/3d7d/93d3f/e3d3/3t7e/97e3v/e3t7/3t7e/93d3f/e3t7/3d3e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97f3v/f3t//39/f/9/f3//f39//39/f/9/g4P/e3t//39/f/9/f3//f39//39/f/9/g4P/f4OD/4ODg/9/f3//f39//39/f/9/g4P/g3+D/4ODg/+Dg4P/g4OD/39/f/9/f4P/g4N//4ODg/+Dg4P/g4OD/4ODg/+Dh4P/g4OD/4eHh/+Hh4P/h4eH/4eHh/+Hh4f/h4eH/4eLh/+Dg4f/h4eH/4eHh/+Hh4f/h4eH/4uLh/+Hh4v/i4uL/4N/f/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4eHh/+Hh4f/g4OD/4ODg/+Dg4P/g4eD/4eDg/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/i4uH/4uLi/+Li4v/i4uL/4eHh/+Hh4f/h4eH/4uLi/+Li4v/i4uL/4uLi/+Pi4v/h4uL/4uLi/+Li4v/i4uL/4uLi/+Pj4//i4uL/4+Pj/+Li4v/i4uL/4uLi/+Pi4//i4uP/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pk5P/k5OT/5OTk/+Tk5P/j4+P/4+Pj/+Pj4//k5OP/5OTk/+Tk5P/k5OT/5OTk/+Li4v/i4+P/4uLj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4uLi/+Pj4//i4+P/4+Pj/+Pj4//k5OT/4+Pj/+Pj4//j4+P/5OTk/+Pk4//k5OT/5OTk/+Xk5P/k5OT/5eXk/+Tk5P/k5OT/5OTk/+Tk5P/l5eX/5eXl/+Xk5P/l5eX/5OTk/+Tk5f/k5OT/5OTk/+Xl5f/l5eX/5eXl/+Xl5f/l5OX/5eXl/+Xk5P/l5eX/5eXl/+Xl5f/l5eX/5ubl/+bl5v/l5eb/5uXl/+bm5v/m5ub/5ubm/+bm5v/m5+b/5eXl/+bm5v/m5ub/5ubm/+bm5v/n5+f/5ubm/+fn5//l5eX/5eXl/+Xl5f/l5eX/5eXm/+Xm5v/l5uX/5ubm/+Xl5f/l5eX/5eXl/+bm5v/l5uX/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubn/+fm5v/n5+f/5+fn/+fn5//m5ub/5+bm/+bm5v/n5+f/5+fn/+fn5//n5+f/5+fo/+bm5v/n5+f/5+fn/+fn5//n5+f/5+jn/+fo5//o5+f/5+fn/+fn5//n5+f/6Ojn/+fn5//o6Oj/6Ofo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+np6f/o6Oj/6enp/+jo6P/p6Oj/6Ojo/+jo6P/p6en/6enp/+np6f/p6en/5+fn/+fn6P/n5+f/5+fn/+jo6P/o6Oj/6Ojo/+jo6P/n5+j/6Ojo/+fo6P/o6Oj/6Ojo/+jp6f/o6Oj/6ejo/+no6f/p6en/6ejo/+np6f/p6en/6enp/+np6f/p6er/6enp/+np6f/p6en/6enp/+np6f/p6en/6urp/+rq6v/p6en/6enp/+np6f/q6en/6enp/+rq6v/q6ur/6urq/+np6f/q6ur/6unp/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+vr6v/q6ur/6+rq/+vr6//r6+v/6+vr/+vr6//r6+r/6+vr/+vq6//r6+v/6+vr/+zs6//r6+v/7Ovr/+np6f/q6ur/6urq/+rq6v/q6ur/6+vq/+rq6v/r6uv/6urq/+rq6v/q6ur/6urq/+rr6v/r6+v/6+vq/+vr6//r6+v/6+vr/+vr6//r6+v/6+vs/+zr7P/s7Oz/7Ozs/+vr6//s7Oz/6+vr/+vs7P/r7Ov/7Ozs/+zs7P/s7Oz/6+vs/+zr6//s7Ov/7Ozs/+zs7P/s7Oz/7Ozs/+3t7P/r6+z/7Ozs/+zs7P/s7Oz/7Ozs/+3s7P/t7e3/7O3t/+zt7P/t7e3/7e3s/+3t7f/t7e3/7u7u/+3t7f/u7e7/7e3t/+3t7f/t7e3/7e3t/+7t7f/t7e3/7u3t/+7u7v/s7Oz/7Ozs/+zs7P/s7O3/7ezs/+3t7f/t7Oz/7e3t/+zs7P/t7ez/7Ozs/+3s7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+7t7v/t7e3/7e7u/+7t7f/u7u7/7u7u/+7u7v/u7e7/7u7t/+7u7v/u7u7/7u7u/+7u7v/u7u7/7+7u/+7u7f/u7u7/7u7u/+7u7v/u7u7/7u/v/+/u7//v7u7/7u7u/+7u7v/u7u7/7u/v/+7v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Dv7//v7/D/8PDw/+/v7//v7+//7+/v/+/w8P/v8PD/8PDw//Dw8P/w8PD/7u7u/+7v7v/u7+//7u7u/+/v7//v7+//7+/v/+/v7//v7u7/7+/v/+7v7//v7+//7+/v/+/v7//v7+//8O/v/+/v7//v8PD/8O/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dx8P/w8PD/8PDw//Dw8P/w8PD/8PDx//Hx8f/w8fH/8fHx//Dw8P/w8fD/8PDw//Hx8P/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/y8vL/8fHx//Ly8v/x8fH/8fHx//Hx8f/x8fH/8vLy//Ly8v/y8vL/8vLy//Hx8P/x8fH/8PHw//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//y8vL/8vLy//Ly8v/y8vL/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9PT0//Pz8//09PT/8/Pz//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//T09P/y8vL/8/Pz//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9PT0//T09P/09PT/9PT0//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//b29v/19fX/9vb2//X19f/19fX/9fX1//X19f/29vb/9vb2//b29v/29vb/9PT0//X19f/09PT/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//f39//29vb/9/f3//b29v/29vb/9vb2//b29v/39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//j4+P/39/f/9/f3//f39//39/f/9/f3//j4+P/4+Pj/+Pj4//b29v/29vb/9vb2//f39//39/f/9/f3//f39//39/f/9vb2//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//j4+P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+fn5//r6+v/5+fn/+fn5//n5+f/5+fn/+vr6//r6+v/6+vr/+vr6/7CwsP+wsLH/sLCw/7Kxsf+ysrL/sbKx/7Gxsf+xsrH/sbGw/7Kxsv+ysbH/sbGx/7Kxsv+ysbL/sbKy/7Gysf+ysrH/sbGx/7Kxsf+xsrH/srOy/7Ozsv+zsrP/srOz/7Gysv+ys7L/sbKy/7Ozsv+zs7L/s7Kz/7Kzs/+ysrL/srGx/7Kxsf+xsrH/sbKy/7Kxsf+xsbL/sbGy/7Kysf+xsrL/sbGx/7Kxsv+ysbH/sbKy/7Ozsv+xsbH/s7Oy/7Oys/+zs7L/s7Oy/7Kzsv+zsrP/s7Ky/7Oysv+zs7P/srKz/7Ozs/+ys7L/srOz/7Kysv+zsrL/srOy/7OztP+zs7L/s7Kz/7Kzs/+ys7P/srOz/7SztP+0tLT/s7Oz/7Ozsv+ys7P/srOy/7Ozs/+0tLP/tLOz/7SztP+ztLT/s7Oz/7SztP+0s7P/s7S0/7S0tP+1tbX/tLS1/7W1tf+ztLP/tLOz/7O0s/+1tbT/tLS1/7S1tP+0tbT/tLS1/7Oys/+0tLT/tLO0/7SztP+zs7T/s7Sz/7Ozs/+0tLP/tLS0/7Ozs/+ztLP/s7O0/7O0s/+0s7T/s7Oz/7S0tf+0s7P/tbS1/7S1tP+0tbT/tbS1/7S0tf+1tLT/tLW0/7S0tf+0tLT/tLS0/7S0tf+1tbX/tbW1/7W1tf+2tbX/tLS0/7S0tP+0tLT/tbS1/7W0tf+2trX/tba2/7a2tv+1tLX/tLW0/7S0tf+2trb/trW2/7W1tv+2trX/tba2/7a1tv+1tbX/tra1/7a1tv+1trb/tra2/7a2tf+2trb/trW2/7a2tv+1tbb/tra2/7a2tv+2t7b/t7e2/7a2t/+0tbX/trW2/7W2tv+1trX/trW1/7a1tv+2trX/tba1/7W1tv+1trX/tra2/7W1tf+2trb/tba1/7a2tf+1trb/tbW1/7e3tv+2trb/t7a2/7e2t/+2trf/t7a3/7a3tv+2t7b/tra2/7e2tv+2trf/t7e3/7a2t/+2t7b/uLe3/7a2tv+2trb/tre2/7e3t/+3trf/uLe4/7i4uP+3t7f/t7a3/7e2tv+3t7b/t7e3/7e4uP+3t7f/uLe4/7e4t/+3t7j/uLi3/7e3t/+4uLf/uLe3/7m5uf+4ubn/uLm4/7i4t/+3t7j/t7e4/7i5uP+5ubn/ubm5/7i4uP+4ubj/t7e3/7i3uP+4uLf/uLi3/7e3t/+4t7f/uLe3/7i3uP+4t7j/t7i3/7i3t/+4uLj/t7e4/7i3uP+3uLj/ubi4/7i4uP+5ubn/uLm4/7m5uP+5uLn/uLi4/7i5uP+5uLj/uLi5/7m5uf+5uLn/ubm5/7i4uf+4ubn/uLi5/7m5uf+4ubn/uLm4/7i4uP+4uLn/uLi4/7m5uf+5ubn/urm5/7i5uP+5ubn/uLm5/7m5uf+5ubn/ubm6/7m5uv+6urn/ubq5/7m5uf+6ubn/urq5/7q6uv+6urr/urq6/7q6uv9cXV3/Li4u/3+Af/8XFxf/Li4u/y4uLv8AAAD/AAAA/7i5uf+5ubn/ubm5/7m6uf+6ubn/urq6/7m5uf+5urr/ubm5/7m6uf+6ubn/ubq6/7m5uv+6urr/ubm5/7q6uv+6urr/XV1d/7q6uv9dXV3/AAAA/wAAAP8AAAD/AAAA/7q6uv9dXV3/urq7/11dXf8AAAD/AAAA/wAAAP8AAAD/u7u6/7q6uv+6u7v/u7u7/7u7u/+7u7v/u7u7/7u7vP8uLi7/Li4u/zo6Ov9dXV3/Li4u/y4uLv9dXl7/Ojo6/7u8u/+8vLz/vLu8/7y8vP+8vLz/vby9/728vP+8vL3/Li4u/y4uLv8AAAD/AAAA/4GBgf+8vbz/Ojo6/7y8vf+7u7v/vLu7/7u7u/+8vLv/u7u8/7y8vP+8u7v/vLy8/7u8vP+7u7z/u7y8/7u7u/+7vLv/vLy8/7y8vP9pamr/mZmZ/wsLC/+8vL3/gYKB/wAAAP+xsbH/AAAA/3Z2dv+ZmZn/vby8/wAAAP+9vLz/dnZ2/6alpv+9vb3/vb2+/7y9vP+9vb3/vby8/729vf++vr3/vb29/729vf+9vr7/vb29/729vv+9vb3/vb69/729vf++vr7/vb69/76+vv++vr7/vr6+/76+vv++v7//v7++/7++vv++vr7/v7+//76+vv++vr//vr6+/76/vv++vr7/v7+//7+/v/+/v7//vb69/769vf+9vr7/vr29/76+vv++vr7/vr6+/76/vv+9vr3/vr6+/769vv+ysrL/vr6+/76/v/+Ojo7/j46P/7++v/++vr//vr++/7+/v/+/v7//v7/A/7+/v//AwL//vr+//7+/v/+Pj4//j4+P/7/Av//Av7//p6io/5ucm/+/v7//wMDA/7+/v//AwL//wL/A/8DAwP/AwL//wMDA/7/Av/+/wL//wMDA/7+/wP/AwMD/wMHA/8DAwP/BwcH/wcDB/8HAwP/AwcD/wcHB/8HAwP/BwcH/wcHB/8LBwf/BwcH/wcDA/8DAwP/BwcH/wcHB/8LCwf/BwcH/wsHC/7/AwP/AwMD/wL+//8DAwP/AwMD/wMDA/8DAwP/BwMH/wMDA/8HBwf+QkJD/kZGQ/8DBwP/AwMH/kJGQ/6mpqf/AwMH/wcHB/8HBwf/CwsL/wsHC/8LBwf/CwcL/wsLC/8HBwf/BwcH/wcLC/7W1tf/CwcL/wsLC/4WFhf9UVFT/wcLB/8HBwv/CwcH/wsLC/8LCwv/CwsL/wsLC/8LDw//BwcL/wsLC/8LCwv/CwsL/w8LC/8LCwv/DwsP/wsLD/8LDwv/Dw8P/wsPD/8PDw//Ew8T/xMTD/8PDw//DxMP/w8PD/8TExP/Dw8P/w8PD/8PDw//ExMT/w8PE/8TExP/CwsL/wsLD/8LCwv/Cw8L/w8PC/8PDw//DwsL/w8PD/8PCwv/Dw8P/MDAw/8PCw//Dw8P/w8TD/7e3t/+Sk5L/w8PD/8TDw//DxMP/xMPD/8TExP/ExMT/xMTE/8XExP/Ew8T/w8PD/5KTk/+rq6v/xMTE/8XFxf/FxMT/xMXF/8TExP/ExMT/xMTE/8XFxP/ExMT/xMTE/8XFxP/FxcX/xMTE/8TFxP/FxcT/xMTE/8TFxP/FxcX/xcXF/8XFxf/FxcX/xcXF/8XFxf/FxsX/xsXF/8bGxv/Gxsb/xsbH/8XFxv/Fxsb/xcXF/8bGxv/Gxsb/x8bH/8fGxv/Hx8f/xcXE/8TExP/ExMT/xcXF/8XFxf/FxcX/xcbF/8bGxf/FxcX/xcXF/8XFxf/FxsX/xsbG/8XGxf/GxcX/xsbG/8bFxf/Gxsb/xsbG/8fHx//Gxsb/xsfG/8fGx//Hxsb/xsbG/8bHxv/Gx8f/xsbH/8fHxv/Hx8f/oaGi/5WVlf/Gx8b/xsfH/8bHxv/Gx8b/x8fH/8jIyP/Hx8f/yMfH/8bGx//Hx8f/x8fH/8fHx//Ix8j/x8jI/8fIx//HyMj/x8jI/8jIyP/Ix8f/yMjI/8nJyP/IyMj/yMjI/8jIyf/IyMj/yMnJ/8jIyP/JyMn/yMjI/8nJyf/Iycn/ycnJ/8fHx//Hx8f/x8fH/8fHyP/HyMj/yMjI/8fHx//IyMj/x8jH/8jIx/+VlZX/r66v/8jIyP/IyMj/yMjI/8jJyf/JyMj/ycnJ/8jIyP/Iycn/ycnJ/8nJyf/Jycn/ysrJ/8nIyf/Jycn/yMnJ/8nJyf/Kysr/ycrJ/8nJyv+Xl5f/ycnJ/8nKyf/Jycn/ycrJ/8rKyv/Kysr/ysnJ/8rKyv/Jycr/ysrJ/8nJyv/Kycn/ysrK/8rKyv/Kysr/y8rK/8vKy//Kysv/y8rL/8vLy//Ly8r/y8vL/8vLy//Ly8z/ysrL/8vLy//Kysr/y8vL/8vLy//MzMv/zMvM/8zLzP/Jycr/ysrK/8rKyv/Kysr/ysrK/8vLy//Lysv/y8vK/8nKyv/Kysr/i4uL/2VlZf/Ky8r/y8vL/yUlJf8/Pz//ysrK/8vLy//Ly8v/zMvM/8vLzP/My8v/y8zM/8zMzP/Ly8v/y8vL/8zMzP/MzMz/zMzM/8zMzP+mpqb/mZqZ/8vLy//MzMz/y8vL/8zMzP/MzMz/zM3M/8zMzP/Mzc3/zMvL/8zMzP/MzMz/zczM/8zMzP/MzMz/zM3M/83Nzf/Mzcz/zc3N/83Nzf/Nzs7/zc3O/87Ozv/Nzc7/zs7O/83Nzf/Ozs3/zc7O/83Ozf/Nzs3/zs7O/87Ozv/Ozs7/zMzM/83Mzf/Mzc3/zczM/83MzP/Nzc3/zc3N/83Nzf/NzM3/zMzM/8C/v//Nzc3/zc3N/87Ozv/Nzc7/zc3O/83Ozf/Nzc7/zc3O/87Ozv/Ozs7/p6en/87Pz/+ampr/zc7N/87Ozv+0tLT/jo2O/8/Pz/9aWlr/TU1N/wAAAP/Ozs7/zs7P/87Ozv/Oz8//zs7P/8/Pz//Pz8//z8/P/87Pz//Oz8//zs/P/8/Pz//Pz8//z8/P/8/Q0P/Q0M//0M/P/9DQz//Q0ND/0NDQ/9DQ0P/Q0NH/0dDR/9HQ0f/Qz9D/0NDQ/9DQ0P/Q0ND/0NDR/9HQ0P/R0ND/0dHR/wAAAP+oqKj/AAAA/5ybm//P0M//0M/P/8/Qz//Q0ND/AAAA/5ubnP8AAAD/dXV1/8/P0P/Q0ND/nJyc/52dnP/Q0ND/0dDR/9HR0P/R0dD/0NDQ/9HR0f/R0dH/0tHS/9DR0P/Q0ND/nZyc/9HR0f/R0dH/0tHR/9HS0v/R0dL/0dDR/9HR0f/R0dH/0dHR/9LS0v/R0tH/0tLS/9LS0v/R0dH/0tHR/9HS0v/S0dL/0tHS/9LS0v/S0tL/0tLS/9LS0v/S0tL/09LS/9LS0v/S0tL/09PT/9PT0//U1NP/0tLT/9PS0//S0tP/09PT/9PT0//T1NT/09PT/9PU0//S0dL/0dLS/9HR0f/S0tL/0tLS/9PS0//S0tL/0tLT/9HR0v/S0tL/0tLS/9LS0v/T0tL/09PS/9PT0//T09P/09LS/9PT0//T09P/09PU/9TU1P/U09P/09TT/9PT1P/T09P/1NPU/9TT0//T09P/09TT/9TU1P/T09P/1NTU/9TU0//U1NP/09TU/9PT0//U1NT/1NXU/9TU1P/V1dT/1NPU/9TU1P/T1NP/1NTU/9XV1P/U1NT/1dXU/9TV1P/V1NT/1dXV/9TV1f/V1dX/1dXV/9bV1v/V1dX/1dbV/9XV1f/V1dX/1dXV/9XV1f/W1tX/1tbW/9XW1f/W1tb/1NTU/9XV1P/U1NT/1NTU/9XV1P/V1dX/1NTU/9XV1f/V1dX/1NTU/9XU1P/U1NT/1dXV/9XV1f/V1dX/1dXV/9XV1f/W1db/1dXV/9XW1f/W1tb/1tbW/9bW1v/W1tb/1dbV/9bW1v/V1dX/ycnJ/9bW1v/W1tb/oKCg/2tra//W1tb/1tbW/9bW1v/W1tb/19bX/9fX1//W1tf/19fX/9bW1v/X19b/1tbW/9bX1v/X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9jY2P/Y2Nj/2NjY/9jY2P/X19f/2NjY/9fY2P/Y2Nj/2NjY/9jY2f/Y2Nj/2NjY/9bW1v8NDQ3/1tbW/wAAAP9ra2v/2NfY/2tra//X2Nf/oaGh/wAAAP8NDQ3/AAAA/2tra//Y2Nj/UFBQ/6Kiov/Y2Nj/2NjY/9jY2P/Y2Nj/2djZ/9nZ2f/Y2Nj/2dnZ/9jY2P/Z2Nj/oqKi/6Ojo//Z2dn/2dnZ/8vLy//Z2dn/2dnY/9nZ2f/Y2Nn/2dnZ/9nZ2f/Z2dn/2dnZ/9na2v/Z2dn/2dnZ/9nZ2f/Z2dn/2dna/9ra2v/a2dr/2tra/9ra2v/a2tr/2tra/9ra2v/b2tr/29vb/9ra2//b29v/2tra/9ra2v/a2tr/2trb/9vb2//b29v/29vb/9vb2//Z2dn/2dna/9nZ2f/a2tr/2tra/9ra2v/a2tr/2tra/9rZ2v/a2tr/2tnZ/9ra2v/a2tr/2tra/9ra2v/a2tr/2trb/9vb2//b2tr/29vb/9vb2//b29z/29vb/9vc2//b29v/29vb/9vb2//AwMD/29vc/9zc3P+kpaT/paWl/9vb2//b3Nz/29vb/9zb2//c3Nz/3Nzc/9zc3P/c3Nz/29vb/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3f/c3dz/3d3d/93d3P/d3d3/3d3d/97d3v/d3d3/3d7e/93d3f/d3d3/3d3d/93d3f/d3d7/3t7e/97d3v/e3t7/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/d3d3/3Nzc/93d3f/c3Nz/3Nzc/7Ozs//d3N3/3d3d/93d3f/d3d3/3d3d/93d3f/d3t3/3d3d/97d3v/e3t7/3t7e/97e3v/e3t7/3d7e/97e3v/e3t3/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97f3v/e397/39/f/97e3v/e3t7/3t7e/97e3v/f397/39/f/9/f3//f39//39/f/9/f3//f39//39/g/9/g4P/g4OD/4ODg/+Dg4P/f39//39/f/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4OHh/97e3v/f3t7/39/f/9/f3//f39//39/f/9/f3//g39//397f/9/f3//f39//39/f/9/f3//f39//3+Df/+Dg4P/g39//4ODg/+Dg4P/g4OD/4ODg/+Dg4P/h4eH/4eHh/+Dg4P/g4OD/4ODg/+Hg4f/h4OH/4eHh/+Hh4f/h4eH/4ODg/+Dg4P/h4OH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/g4OH/4eHh/+Hh4f/h4eH/4eHh/+Li4f/h4eL/4uLi/+Lh4v/i4uL/4uLi/+Li4v/i4uL/4+Pj/+Li4//i4+P/4uLi/5ubm/9UVFT/AAAA/0ZGRv84ODj/AAAA/xwcHP/h4eH/4eHh/+Hh4f/h4uH/4eHi/6mpqf/i4uL/RkZG/+Hh4f/i4eL/4uHh/+Li4v/i4uL/ODg4/+Li4v9GRkb/AAAA/wAAAP8AAAD/RkZG/6qqqv/j4+P/4+Pj/+Pj4/8AAAD/VVVV/wAAAP8NDQ3/4+Pj/+Pj5P/Hx8f/5OPj/+Pj4//j4+P/4+Pj/+Pj4//j4+T/5OTk/+Pj4//k5OT/ODg4/1VVVf8cHBz/AAAA/4CAgP9jY2P/AAAA/wAAAP/k5OT/5OXl/+Tk5P/l5eX/5eXl/+Xl5f/l5eX/5eXl/5ycnP/l5eX/ODg4/+Xl5f/l5eX/ZGRk/+Xl5f+Pj4//5OPk/6urq//j5OP/5OTk/yoqKv8AAAD/x8fH/wAAAP/k5OT/5OTk/+Tk5P/k5OT/5OTl/1VVVf/l5eT/5eXl/zk5Of/l5eX/HBwc/+Xl5f/l5eX/5uXm/+bl5f/m5ub/DQ0N/+Xl5f/X19f/5uXm/+Xl5v/m5ub/5ubm/+bm5v/m5eb/5uXl/+Xl5f/m5ub/5ubm/+bm5v/m5ub/5+fm/zk5Of85OTn/Kioq/wAAAP85OTn/OTk5/wAAAP8cHBz/5ubm/+fn5//n5+f/5+fn/+fn5//o5+j/5+fn/+jo5/85OTn/SEhI/0hISP8ODg7/kZCR/+jo6P8AAAD/HBwc/6ysrP8AAAD/rKys/wAAAP8AAAD/5+fn/wAAAP/n5+f/rKys/wAAAP+sraz/AAAA/wAAAP/n5+f/AAAA/+fn5//n5+f/2dnZ/+fn5//o6Of/VlZW/wAAAP/o6Oj/HBwc/+fn6P/o6Oj/5+jo/+jo6P/o6Oj/goKC/+jo6P+vr67/6Ojo/+jo6P/o6Oj/6Ojo/+no6f/p6en/6ejo/+np6f/o6Oj/6eno/7y8vP/p6Oj/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+nq6v/q6en/6urq/+rq6v/q6ur/6enp/+rq6v/p6en/6urq/+rq6v/q6ur/6urq/+rq6v8ODg7/vb29/wAAAP86Ojr/6enp/+np6f/p6en/6enp/wAAAP8AAAD/AAAA/wAAAP+9vb3/6enq/3R1df/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6+v/6urq/+vr6//q6ur/6urq/+rq6v/q6ur/6urr/+vr6//r6+r/6+vr/+rq6v/q6uv/6urq/+rq6v/r6+v/6+vr/+vr6//r6+v/6+vq/+vr6//q6ur/6+vr/+vr6//r7Ov/6+vr/+zr7P/r7Oz/7Ozr/+zr7P/s7Oz/7Ozs/+zs7P/s7Oz/7ezt/+vr7P/s7Oz/7Ozs/+zs7P/s7Oz/7ezt/+3s7P/t7ez/6+vr/+vr6//r6+v/6+vr/+zs6//s7Ov/6+zr/+zs7P/r6+v/7Ovr/+vr6//r7Oz/7Ovr/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7f/s7e3/7e3t/+zt7P/t7e3/7Ozs/+zs7f/s7e3/7e3s/+3t7f/t7e3/7e3t/+3t7f/s7ez/7e3t/+zs7P/t7e3/7e3t/+7u7v/t7e3/7u7u/+3t7f/t7e3/7e3t/+3t7f/t7e3/7u7u/+3t7f/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7//u7u7/7u7u/+7u7v/u7+//7u7u/+/v7//u7u//7+/v/+3t7f/u7e3/7e3t/+3u7v/u7e7/7u7u/+7u7v/u7u7/7u7u/+3u7f/t7u3/7u7u/+7u7v/u7u7/7u7u/+/u7//u7u7/7u7u/+7v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7v/v7+//7+/u/+/v7//v7+//7+/v/+/v7//v8O//7+/v/+/v7//v7+//7+/v/+/v7//w7+//7/Dw//Dw8P/v7+//7+/v/+/v7//w7/D/8PDv//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/x8PD/8fHx//Dx8f/x8fH/8PDw//Dw8P/w8PD/8fDw//Hx8f/x8fH/8fHx//Hx8f/v7+//8PDv//Dw7//w8PD/8PDw//Dw8P/w8PD/8PDw/+/v7//w8PD/8PDw//Dw8P/w8PD/8PDx//Dw8P/w8fH/8fDx//Dw8P/w8fD/8fHx//Hx8f/x8fH/8fHx//Hx8f/w8PH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Pz8//y8vL/8/Pz//Ly8v/y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//z8/P/8fHx//Ly8v/x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/9PT0//Pz8//z8/P/8/Pz//Pz8//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/19fX/9PT0//X19f/09PT/9PT0//T09P/09PT/9fX1//X19f/19fX/9fX1//Pz8//09PT/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/19fX/9fX1//X19f/19fX/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/39/f/9vb2//b29v/29vb/9vb2//b29v/39/f/9/f3//f39//19fX/9vb2//X19f/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//f39//39/f/9/f3//f39//29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//4+Pj/9/f3//f39//39/f/9/f3//f39//4+Pj/9/f3//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/5+fn/9/f3//f39//39/f/9/f3//j4+P/4+Pj/+Pj4//j4+P/39/f/+Pj4//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//r6+v/5+fn/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//n5+f/5+fn/+fn5//n5+f/5+fn/+vr6//n5+f/6+vr/+fn5//n5+f/5+fn/+fn5//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+/v7//r6+v/7+/v/srGy/7Kxsf+ysbL/srGy/7Kzsv+ysrP/srKy/7Oys/+ysbL/srOy/7Gysv+ys7L/s7Oz/7Kzsv+ys7L/srOz/7Kzsv+zsrL/srKy/7Kysv+ysrP/tLS0/7Szs/+0tLP/s7Ky/7Kysv+ys7P/tLSz/7O0s/+zs7P/tLS0/7O0tP+zs7L/s7Kz/7Oys/+zsrL/srKy/7Kzsv+ys7L/srOy/7Oys/+zsrP/s7Kz/7Kys/+ys7P/srKy/7Kzsv+0s7P/srOz/7SztP+0s7P/s7S0/7OztP+ztLP/s7S0/7S0s/+zs7T/tLOz/7O0tP+0tLT/tLSz/7S0tP+0s7P/tLW0/7OztP+0s7P/tLS0/7SztP+ztLP/tLW0/7S1tP+1tbT/tLO0/7S0tP+0s7T/tLW1/7W1tP+1tbT/tbW0/7W1tP+1tbT/tLS0/7S1tP+0tLX/tLW1/7W1tv+2tbX/trW2/7W1tP+0tLT/tLS1/7a2tv+1trX/tbW1/7a1tv+2trX/s7O0/7W0tP+0tLT/tLW1/7S1tP+1tLX/tLS0/7S1tf+1tLT/tLW1/7S0tP+1tLT/tLW0/7S1tP+0tbT/tLW0/7W0tf+1tbb/tLW0/7a1tf+1tbb/tbW2/7W1tv+2tbb/tba1/7W1tv+1trX/trW2/7a1tv+1trX/trW1/7a1tf+2tbb/tbW2/7a2tf+1tbX/trW1/7a2t/+1trb/tra2/7W1tf+2trX/trW1/7W1tv+2t7f/tre3/7a2tv+2t7b/t7a2/7a2tv+3t7b/tra3/7a2tv+4t7f/t7e4/7i4uP+2t7b/t7a3/7a3t/+3t7f/t7i4/7e3uP+3uLj/uLi4/7a2tv+3t7f/tra1/7a2tv+2trf/t7e2/7a2t/+3trb/tra3/7e2t/+3t7b/tre3/7a3t/+2trb/t7e3/7e3tv+2trf/uLi4/7e3tv+3t7j/t7i4/7e3t/+3uLf/t7i3/7i3uP+3t7f/t7e4/7i3uP+3t7j/t7e4/7e3uP+5uLn/t7e3/7i4uP+3t7f/t7e4/7i4t/+4ubn/uLi4/7m5uP+3t7f/t7i3/7e3t/+5uLn/uLm4/7i5uf+5uLj/uLi4/7m4uP+5ubn/uLi4/7i5uP+4uLn/ubm5/7m5uf+5urn/ubi4/7m4uf+4ubn/ubm5/7m5uf+6urr/ubm6/7m5uv+3uLj/ubm4/7i4uP+4uLj/ubm5/7m5uP+5uLj/ubm5/7m5uP+5uLj/uLi4/7m5uP+4ubj/uLm5/7i4uf+5ubn/uLi4/7m5uf+5ubn/urm5/7q5uv+5ubr/urq6/7m5uf+5ubn/urm5/7m6uf+6ubr/ubq5/7q6uv+6ubn/urq6/7m5uf+6ubr/urm5/7q5uf+6urr/urq6/7q6uv+7urr/urm5/7q6uv+6urn/urq6/7q6uv+6urr/urq6/7u6uv+6u7v/XV1d/7q7u/9dXV3/AAAA/wAAAP8AAAD/AAAA/7u6uv9dXV3/u7u7/11dXf8AAAD/AAAA/wAAAP8AAAD/urq6/7q6uv+6urr/u7q7/7q7u/+6urr/urq6/7q6u/+6urr/u7q7/7q6uv+6urr/urq7/7u7u/+7urr/u7u7/7u7u/9dXl3/u7u7/15eXv8AAAD/AAAA/wAAAP8AAAD/u7u7/11eXf+8vLv/Xl1e/wAAAP8AAAD/AAAA/wAAAP+8vLz/vLu7/y4uLv8uLi7/vLy8/1JSUv8uLi//AAAA/y4uLv8uLi7/vLy8/7y9vP8vLi//AAAA/7y9vf9SUlL/AAAA/729vf8AAAD/vb29/769vv+9vb3/vr2+/769vv8AAAD/vr2+/wAAAP+9vr7/vr69/769vv+9vb3/vr6+/7y8vP+9vLz/vLy8/7y9vP+8vLz/Xl5e/728vP+xsbH/vb28/7y9vf+9vbz/vLy9/729vf+9vr7/vb29/76+vf8AAAD/vr29/46Ojv++vb7/vr69/76+vv++vr7/vr+//72+vf+9vb3/vr69/6ampv9ra2v/d3d3/wAAAP9HR0f/vr6+/2tra/++vr7/vr+//wAAAP8AAAD/goOD/yMjI/++vr7/vr6+/7+/vv++v7//vr6//6enp/+/v7//v7+//wAAAP8AAAD/AAAA/wsLC/9gX2D/Ly8v/7O0tP+oqKj/AAAA/wAAAP9fYF//AAAA/2xsbP9gYGD/CwsL/wAAAP++vr7/vr++/76+v/+/v7//v7+//8C/wP+/v7//wL+//7+/v/+/v7//v7+//7+/v//Av7//v7+//7+/wP+0tLT/v7/A/xcXF//AwL//SEhI/wAAAP8AAAD/AAAA/wAAAP+QkJD/AAAA/wsLC/8LCwv/AAAA/wAAAP+RkJH/CwsL/wAAAP8AAAD/CwsL/wAAAP8AAAD/MDAw/4SEhP+qqqr/AAAA/2BgYP8jJCP/wcHB/8HBwf/CwcL/wsLB/8HCwv/BwcL/YGBg/8LCwf+2tbb/AAAA/wAAAP+FhYX/AAAA/8HBwv/CwsL/wcHB/8LCwv/Cw8P/AAAA/8PCwv8AAAD/nZyd/8HBwf+RkZH/wcLC/8LCwv/CwsL/wcHC/8LBwf8XFxf/wcLB/wAAAP9hYWD/wsHC/8LCwv/BwsL/wsLC/8LCwv/CwsL/wsLC/8PCw//Cw8L/AAAA/8LDwv8AAAD/wsPD/8LCw//CwsP/w8PC/8PDw/8AAAD/w8PD/wAAAP8AAAD/enp6/wAAAP8AAAD/CwsM/wAAAP8YGBj/YmFi/wAAAP8kJCT/AAAA/5KSkv+3uLf/w8PE/8TEw//ExMT/AAAA/wAAAP8kJCT/AAAA/1VVVf/FxMX/AAAA/1ZWVv/ExMT/YmJi/8XExf+4ubn/AAAA/wAAAP8AAAD/AAAA/wAAAP/Dw8P/AAAA/8TEw//Dw8T/xMTE/8TExP/FxcT/AAAA/8PDxP8AAAD/q6ur/8TExP/FxcX/xMXF/8TExf/ExMX/xMXF/8TFxP/FxcX/GBgY/wAAAP8xMTH/AAAA/8XExf/FxcX/xcXF/8XGxf8xMTH/AAAA/wAAAP8AAAD/xcXF/8bGxf/FxcX/xcbG/8bGxf/Gxsb/xsbG/6Khov+sraz/xcXF/29ubv/Gxsb/xsbG/zExMf+ioaL/AAAA/6Giof8xMTH/DAwM/wAAAP8AAAD/AAAA/xgYGP9wcHD/AAAA/z4+Pv8AAAD/oqKi/8jIx//Ix8f/x8fH/8fHx/9iYmL/xsbG/2NjY//Hxsf/b3Bv/wAAAP9jY2P/AAAA/2NjY//Hxsf/cG9v/8bHx/98e3v/AAAA/66urv8AAAD/AAAA/8fIyP8AAAD/x8fH/8jHyP/IyMj/yMfH/8jIyP8AAAD/x8fI/wAAAP+ioqL/yMjI/8jIyf/IyMj/ycnI/wAAAP8AAAD/V1dX/wwMDP9LS0v/u7u7/wAAAP8xMjH/yMjI/7y8u//IyMj/yMnJ/wwMDP8AAAD/V1dX/wAAAP/Jycn/ysrJ/8nJyf/Kysr/ycnK/wAAAP/Kycr/pKSk/2RkZf/Kycn/GRgY/8rJyf/Kysn/ysrK/8rKyv/Ly8r/yMjJ/8nIyf/IyMn/ycnI/5eXl/8AAAD/l5eX/wAAAP/IyMn/ycnJ/8jIyP/Jycn/l5eX/wAAAP9YV1f/AAAA/wAAAP+xsbD/AAAA/5eXl//Kysr/ysrK/8vLyv/Kysr/AAAA/729vf8ZGRn/ysvK/8rLy//Kysr/ysrK/8vLy/8AAAD/AAAA/5eXmP8/Pz//AAAA/zIyMv8AAAD/JSUl/8rKyv9lZWX/ysvK/2VlZf8AAAD/AAAA/wAAAP8AAAD/srKy/zIyMv8MDAz/AAAA/wAAAP8AAAD/WVlZ/zIyMv8AAAD/f39//1lZWf/NzM3/zMzN/8zNzf/NzMz/zc3N/8vKyv9lZWX/y8vL/2ZmZf8AAAD/AAAA/wAAAP8yMjL/y8vL/2VmZf/Ly8v/ZmVm/wAAAP8yMjL/AAAA/zIyMv+/v7//zczN/8zNzP/Nzcz/zc3M/83Nzf/Nzc3/zc3O/8zNzf/NzMz/zczN/83Nzf/Nzc3/zc7O/87Ozf/Nzc7/AAAA/2ZmZv8AAAD/DAwM/83Ozf/Ozs3/zs7N/87Ozv9ZWVn/p6em/87Ozf/Nzs7/zc3N/87Ozv/Ozs7/z87O/zMzM/8AAAD/tbW0/5qamv8AAAD/AAAA/5ubm/8AAAD/zs7P/87Ozv/Oz87/z8/P/8/Pz/8AAAD/0NDP/wAAAP/Nzs3/zc7N/87Ozv/Ozs7/zs7O/87Oz//Ozs7/z8/O/83Nzf/Ozs7/zs7O/8/Oz//Ozs7/z87O/87Ozv/Pz8//z8/P/8/Pz//Pz8//z9DP/8/Pz/8AAAD/z9DQ/wAAAP/Pz8//0NDP/9DP0P/Qz8//z9DP/wAAAP/Q0ND/AAAA/wAAAP8AAAD/AAAA/3V1df8AAAD/AAAA/5ydnP+cnJz/AAAA/5ycnP8AAAD/nJyc/9HQ0P/R0NH/0NDR/9HR0f8AAAD/0dHR/6qqqv/S0dL/0dHR/9LS0v/R0tL/0tHS/9HR0f/S0tL/0tLS/9HR0f/R0dL/0tLS/9LR0f/S0tL/AAAA/5ydnP8AAAD/nZ2d/9DR0P/R0dH/0dHR/9HR0v8AAAD/nJyc/wAAAP+dnZ3/0dHR/9HS0v/R0dL/0tHR/9HR0v/R0dH/0tHS/9LR0v/S0tL/0tLT/9LS0v/S09P/0dLR/9LS0v9OTk7/Ghoa/9PT0//S09L/0tPS/9LT0//S0tL/09LT/9LS0v/T0tL/0tLS/9PT0//T09P/09PT/9LS0v/T0tP/0tLS/9PT0//T09P/09PU/9PT0//T09P/1NTU/9TT0//U1NT/1NTT/9TU1P/U1dT/1NTU/9XV1P/U1NT/1NTU/9TT0//U1NT/1dTU/9TV1P/V1dT/1dTU/9LT0//T09P/0tLS/9PT0//T1NP/09PU/9PT0//T1NT/09PT/9PT1P/T09P/09PU/9PU0//U1NT/09TT/9TU1P/U1NT/1NTU/9TU1P/U1NX/1dTU/9XV1f/V1dX/1dXV/9XV1f/V1dX/1dTU/9TV1P/V1dX/1dXV/9XV1f/V1dX/1dXU/9XV1f/U1NT/1dXV/9XV1f/V1dX/1dXV/9XW1v/V1dX/1dXV/9XV1f/V1dX/1tbV/9bW1v/W1db/1tbW/9bW1v94eHj/1tbW/9bW1v8AAAD/AAAA/6Ggof+hoaH/1tbW/9bW1v/W1tb/19bW/9fX1//X19f/19fX/9fX1//V1dX/1dbV/9XV1f/W1tb/1tbW/9bW1v/W1tb/1tbW/9XW1f/W1tb/1tXV/9bW1v/W1tb/1tbW/9bW1v/W19b/1tbX/9fX1//X19f/19fX/9fX1//X2Nf/19fX/9fX1//X19f/19fX/9fX1//X19f/2NfY/9jY2P/Y2Nf/2NjY/wAAAP8AAAD/UFBQ/wAAAP8AAAD/AAAA/1BQUP+ioqL/bGxs/wAAAP9sbGv/AAAA/2xsbP/Y2Nj/bGxs/9jY2f8AAAD/AAAA/6Oiov+jo6P/o6Oj/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dr/2tra/9rZ2f/a2tr/bGxs/wAAAP9sbGz/AAAA/2xsbP/Z2dn/bGxs/9nZ2f9sbGz/AAAA/2xsbP8AAAD/bGxs/9nZ2f9sbGz/2dnZ/9nZ2f/a2tn/2dnZ/9nZ2v/a2tr/2tra/9ra2v/a2tr/2dra/9ra2v/Z2dn/lpaW/9ra2v/b29v/AAAA/7Kxsf/a2tr/2tra/9ra2v/a2tr/29va/83Nzf/NzM3/KCgo/9ra2v/a29r/2tra/9rb2v9tbW3/AAAA/w0NDf8AAAD/UlJS/wAAAP8AAAD/DQ0N/wAAAP8AAAD/YGBg/25ubv8bGxv/zs7O/3t7e//c3Nz/3Nzc/93d3P/c3Nz/3dzc/9rb2v+kpKT/2tva/6SkpP8AAAD/AAAA/wAAAP8AAAD/29vb/7Kysv/b29v/29vb/wAAAP8AAAD/Gxsb/wAAAP+lpaX/3Nzc/6Wlpf/c3Nz/3dzc/93d3f/d3d3/3d3d/6Wlpf/d3N3/e3t7/9zd3P/d3d3/3d3d/93d3f/d3d3/AAAA/zc3N/8bGxv/AAAA/7Ozs//e3t3/DQ0N/8/P0P/d3d3/Nzc3/93d3f+YmJj/AAAA/0VFRf8AAAD/AAAA/97e3v/e3t7/3t7e/97e3v/e3t7/397f/97f3v/f39//3t7e/97e3v/CwsL/3t7f/9/e3v/f39//39/f/9/f3//d3d3/3d7d/93d3f/d3d3/AAAA/wAAAP8AAAD/AAAA/97d3f/e3t7/3t7d/5iYmP8AAAD/AAAA/wAAAP8AAAD/ioqK/97f3/9vb2//39/f/9/f3//f39//39/f/9/g3/+ZmJj/39/f/8PDw//f39//39/f/+Dg4P/g4N//4ODg/9/f3//f39//39/f/9/g3//g4OD/4ODg/+Dg4P/g4OD/39/f/9/g3//g39//4ODg/+Dg4P/g4OD/4ODg/+Dh4f/g4OD/4OHg/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eLi/+Dh4P/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hi4f/i4uL/4N/g/+Dg4P/g4OD/4ODg/+Dg4P/h4OD/4ODg/+Hh4f/g4OD/4ODg/+Dg4P/g4eD/4OHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/i4eL/4uLi/+Li4v/i4uL/4eHh/+Hh4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/h4eL/4uLi/+Li4v/i4uL/4uLi/42Njf/i4uL/4uLj/+Li4v/i4uL/4uLi/+Li4v/i4uL/4+Pj/+Lj4v/j4+P/AAAA/wAAAP9xcXH/AAAA/wAAAP9VVVX/AAAA/wAAAP/j4+P/x8fH/+Pj4//j4+P/VVVV/wAAAP/k5OT/x8fH/+Li4v/i4uL/4uLi/+Lj4//j4+P/4+Pj/+Pj4/9xcXH/4+Pi/+Pj4//i4+P/4+Pj/+Pj4/8cHBz/4+Pj/zg4OP/k4+P/5OTk/5ycnP/k5OT/5OTk/+Tk5f/k5OT/5OXl/yoqKv/k5OT/AAAA/6urq//l5OT/5eXl/+Xk5P/l5eX/x8fH/+Tl5f8AAAD/VVVV/+Xl5f/l5eX/yMjI/+Xl5f8AAAD/AAAA/1VVVf8AAAD/DQ0N/4+Pj/8AAAD/AAAA/+Xl5f/l5uX/5ubl/+bm5v/m5ub/5ubm/+bm5v/n5+f/5ebl/+bm5v+Pj4//5ubm/+bm5v/m5ub/5+bn/+fn5//l5eX/rKys/+Xl5f/l5eX/DQ0N/wAAAP+srKz/AAAA/+Xl5f/l5eX/5eXl/+Xl5v/l5eX/Kioq/+bm5v8qKir/AAAA/8nJyf8AAAD/gYKB/+fm5//n5+f/5+fn/+fn5/8AAAD/c3Nz/wAAAP+CgoL/5+fn/+fn5//n5+f/5+fn/62trP8AAAD/ra2t/wAAAP8AAAD/6Ofn/wAAAP/o6Oj/ra2t/wAAAP+tra3/AAAA/wAAAP/o6Oj/AAAA/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6ejo/+np6f/o6en/6enp/+jo6P/o6ej/6Ojo/+jo6P/p6en/6enp/+np6f/p6en/ra2t/wAAAP+tra3/AAAA/wAAAP/o6Oj/AAAA/+jo6P+ura3/AAAA/66trf8AAAD/AAAA/+no6P8AAAD/6ejo/+np6f/p6en/6Ojo/+np6f/p6en/6enp/+np6f+vr6//6enp/+np6f/p6en/6enp/+np6f+Dg4P/6erq/xwcHP8AAAD/AAAA/wAAAP8AAAD/V1dX/+rq6v86Ojr/6urq/wAAAP8AAAD/AAAA/wAAAP86Ojr/6urq/zo6Ov/q6ur/6urq/+vq6v/q6ur/6uvr/+vr6//r6+v/6+vr/+vr6//q6+v/6+vr/+vq6//r6+v/6+vr/+vs6//r6+v/7Ozs/wAAAP8AAAD/AAAA/wAAAP9mZmb/6urr/4ODg//r6ur/AAAA/wAAAP8AAAD/Ojo6/76+v//r6+v/6urr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vs7P/r7Ov/7Ozs/+vr6//r6+v/6+vr/+vs6//s7Ov/7Ozs/+zs7P/s7Oz/6+zr/+vr7P/r6+z/7Ozs/+zs7P/s7Oz/7Ozs/+zs7f/r7Ov/7Ozs/+zs7P/s7Oz/7Ozs/+3t7P/t7e3/7e3s/+zs7P/t7e3/7ezs/+3t7f/t7e3/7u3u/+3t7f/u7u3/7e3t/+3t7f/t7e3/7e3t/+7t7v/u7u7/7u3u/+7u7v/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+3t7f/s7O3/7e3t/+zs7P/t7ez/7e3s/+3s7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e7t/+7u7v/u7u7/7u7u/+7u7v/t7e7/7e3u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u/v/+3t7f/u7u7/7u7u/+7u7v/u7u7/7+/v/+7u7v/u7u//7u7u/+7u7v/u7u7/7u/v/+7v7v/v7+//7+7v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Dv8P/v8PD/8PDw/+/v7//v7+//7+/v//Dv7//v7+//8PDw//Dw8P/w8PD/7u7u/+/v7v/u7+//7u7u/+/v7//v7+//7+/v/+/v7//u7u7/7+/v/+/u7v/v7+//7+/v/+/v7//v7+//8O/w/+/v7//v8PD/7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/8O/v//Dw8P/w8PD/8PDw//Dw8P/w8fD/8PDw//Hw8P/w8PD/8PDw//Dw8P/w8PD/8fHw//Hw8f/x8fD/8fHx//Dw8P/x8fD/8PDw//Hx8P/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/y8vL/8fHx//Ly8v/x8fH/8fHx//Hx8f/x8fH/8vLy//Ly8v/y8vL/8vLy//Hw8P/x8fD/8fDw//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fDx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//y8vL/8vLy//Ly8v/y8vL/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9PT0//Pz8//09PT/8/Pz//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//T09P/y8vL/8/Pz//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9PT0//T09P/09PT/9PT0//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//b29v/19fX/9vb2//X19f/19fX/9fX1//X19f/29vb/9vb2//b29v/29vb/9PT0//X19f/09PT/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//b29v/29vb/9vb2//b29v/29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//j4+P/39/f/+Pj4//b29v/29vb/9vb2//f39//39/f/9/f3//f39//39/f/9vb2//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/+Pj4//j4+P/4+Pj/+Pj4//f39//4+Pj/9/f3//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//j4+P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+fn5//r6+v/5+fn/+fn5//n5+f/5+fn/+vr6//r6+v/6+vr/+vr6//n5+f/6+vr/+fn5//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+/v7//v7+//7+/v/+/v7//r6+v/7+/v/+vr6//v7+//7+/v/+/v7//v7+//7+/v/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//v7+//6+vr/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+/+ys7P/s7Oz/7Kzs/+ys7P/srOy/7SztP+0tLT/tLOz/7Ozsv+zsrP/srOz/7S0s/+zs7P/tLO0/7Ozs/+0s7T/s7Sz/7Ozs/+0tLT/s7O0/7SztP+1tbT/tLW0/7W0tf+ztLP/s7Oz/7Szs/+1tLT/tLS0/7W1tf+0tLT/tbS1/7Kzsv+ztLP/tLOz/7O0s/+0tLP/tLOz/7O0tP+0tLT/s7Oz/7O0s/+0s7P/s7Sz/7O0tP+ztLP/s7Sz/7S0tP+0s7P/tLW0/7S0tP+0tLT/tLW1/7W1tP+1tbX/tbS1/7W0tP+0tLT/tbW0/7W0tP+1tLT/tLS1/7S1tf+1tbT/tbW1/7S1tP+0tLT/tLS0/7S0tf+2trX/tbS0/7W1tv+0tLT/tLS0/7W0tP+1tLX/tba2/7W1tv+2tbX/tba2/7a1tf+1tbb/tra2/7W1tv+2trX/tra3/7W2tf+2trf/tbW2/7W2tv+2trX/tbW1/7e3tv+3t7f/tre2/7a2t/+1tbT/tba1/7S0tf+1trb/tba1/7W1tv+1tbb/tbW2/7W1tv+2tbb/tbW2/7a2tv+1tbX/tba1/7a2tv+2tbX/tba2/7a2tv+1tbb/tre3/7a3tv+3t7b/t7e2/7e3tv+3trf/t7a3/7a2t/+2trf/tre3/7e2tv+3trf/tre2/7e3t/+3t7b/t7a2/7e3tv+3trf/t7e3/7e3t/+3uLj/t7a2/7e2t/+3trb/t7a2/7e4t/+4t7f/uLi4/7e3t/+3uLf/t7e4/7i3uP+4t7f/uLe4/7i4uf+4ubn/ubm4/7e3t/+3uLf/t7e3/7i4uf+5uLj/ubm5/7m4uP+5uLj/t7e2/7i3t/+3trf/uLe4/7e4t/+3uLf/t7i4/7i4uP+4t7f/t7i4/7e3t/+3t7f/t7e3/7e3t/+2trf/uLe4/7i4t/+4uLj/uLi5/7i3uf+4uLn/ubm5/7i4uP+5uLn/t7e5/7i4uP+5ubj/ubi4/7i4uP+5uLj/uLi5/7m5uf+4ubj/ubm4/7i4uP+5ubn/uLm4/7m5uf+5ubn/urq6/7m4uP+4uLn/uLi5/7m5uf+5ubn/urq5/7m6uv+5urn/urm6/7q6uv+5urr/ubq5/7q6uv+6urr/urq6/7q6u/+5urr/urq6/7q6uf+6urr/urq6/7q7uv+7u7r/u7q6/7m4uP+5ubn/ubm5/7m5uv+5ubn/urq5/7m6uv+6urr/ubm5/7m6uv+5urn/ubm6/7m6uv+6urr/ubq5/7q6uv+6urr/urq6/7q6uv+6urv/urq6/7u6uv+7urv/uru7/7q6uv+6urv/urq7/7q6u/+7u7v/u7u7/7q6uv+7u7v/u7u6/7q6uv+6urr/u7u6/7u7u/+8u7v/u7u7/7u7vP+6u7r/u7u7/7q6u/+7u7v/u7y8/7u7u/+7vLz/u7y7/7y8vP9eXV3/gIGB/y4uLv8AAAD/AAAA/wAAAP8AAAD/Li4u/wAAAP+8vLz/vby8/wAAAP8AAAD/vL29/7y8vf+7u7v/u7y7/7u7u/+8u7v/u7y7/7u7u/+8vLz/vLy8/7u8u/+8u7v/vLu7/7u7u/+7vLv/vLy8/7y8vP+8vLz/vLy8/7y8vf+8vbz/vLy8/7y8vf+9vb3/vL29/729vf+8vLz/vLy9/728vf+9vL3/vb29/72+vv+9vb3/vb2+/7y9vP+9vb3/UlJS/15eXv+9vb7/vr29/15fXv9fX1//AAAA/wAAAP+9vb3/vb69/wAAAP8AAAD/vb2+/76+vv+ysbH/IyMj/xcXF/8AAAD/AAAA/4KDg/8AAAD/s7Oz/wAAAP8AAAD/vr6+/76+v/8vLy//v7+//7+/v/+/v7//vb29/76+vv++vb7/vb29/72+vf++vr7/vr6+/7++vv+9vb3/vr69/769vf++vr7/vr6+/7+/v/+/v77/v76//76+v/+/vr//vr6//76+v/+/v7//wL+//7+/v//Av8D/v7++/7+/v/++v77/v7+//7/AwP+/v8D/v8C//8C/v/+/v7//wL+//7+/v/9ra2v/v8C//zs7O/8jIyP/AAAA/7+/v/8LCwv/wMDA/7+/wP8AAAD/AAAA/8DAwP/BwMD/AAAA/2xsbP8LCwv/nZyc/8DBwf9sbGz/wcHB/2xtbP8AAAD/YGBg/8DBwf/BwcH/wcHB/wsLC//CwcH/wcLC/7/Av//AwMD/v7+//8DAwP/BwMD/wcDA/8HBwf/AwMD/wMDA/8DAwf/AwMD/wMDB/8HAwP/AwcD/wMDB/8HBwf/BwMH/wcHB/8HBwf/CwcL/wsHB/8HBwf/BwsH/wcHB/8HBwf/AwcL/wcHC/8HBwf/BwsH/wcHC/8HCwv/CwsL/AAAA/wAAAP8AAAD/AAAA/52dnf/Dw8L/CwsL/21tbf8AAAD/AAAA/8HBwf/CwsL/AAAA/wAAAP/Dw8L/w8LC/8PCwv/Dw8P/wsPC/8PDw//DxMT/AAAA/8PExP8AAAD/w8PD/8PDw//Dw8P/xMTE/8TDw/8AAAD/w8PE/wAAAP/CwsL/wsLC/8LCwv/CwsL/wsPD/8PDw//Dw8L/w8PD/8LCwv/DwsL/wsLD/8PCw//Dw8P/xMPD/8PDw//Ew8P/w8PD/8PDxP/DxMP/YWJh/5+fnv8AAAD/AAAA/wAAAP/ExMP/np+f/8PDw//ExMT/YmJi/2JiYv/FxMX/xcXE/wAAAP8kJCT/AAAA/wAAAP+4ubj/xcXE/xgYGP9iYmL/AAAA/25ubv8AAAD/xcTF/xgYGP8AAAD/xcXF/8XFxv/FxcX/b25v/yQkJP8AAAD/AAAA/wAAAP8AAAD/VlZW/wAAAP8YGBj/xcbF/8bGxv9vb2//x8bH/8bGxv/Hx8b/AAAA/5+gn/8AAAD/AAAA/8XFxf/FxcX/Y2Ji/8XGxf9iYmL/YmJi/8XFxf/Fxcb/oKCg/8bGxv/FxcX/xcXF/8XFxv/Gxsb/xsXF/8bGxv/Hx8b/xsfH/8bHx//Hxsb/xsbG/8bHx//Gxsb/x8bH/8bGxv/Hx8f/xsfG/8fHx/+urq7/xsfG/8bGxv/Hxsf/x8fH/0tKSv/Hx8f/u7u7/8bHxv/Hx8f/xsbG/8fHx//HyMj/yMjH/8fIyP/Hx8j/AAAA/zExMf8lJSX/AAAA/8nIyP/Iycj/DAwM/1dXV/+7u7v/V1dX/8jIyP/Iycj/DAwM/wAAAP/IyMn/ycnJ/8fHx//Ix8f/x8fH/8jIyP/Hx8j/yMjI/8fIx//IyMj/x8fI/8fHyP/Hx8j/x8fH/8jIyP/JyMj/yMjI/8jIyf/Iycj/ycjJ/8nIyf/JyMj/ycnJ/8rJyv/Jycn/ycnJ/8jJyf/Jycn/yMjI/8nJyf/Kycr/ysrJ/8nKyv/Kysn/ycnJ/728vP8+Pj7/AAAA/wwMDP8AAAD/AAAA/0tLS/8AAAD/GBkZ/8nJyf/Kysn/cXFx/8rKyv/Kysr/ysrL/35+fv/Ly8v/y8rL/8rKyv/Kysr/y8vL/76+vv9mZWX/ysvK/8vKy//Lysr/y8vL/6Wlpf8AAAD/zMzM/8vMy//Kycn/ysnK/8nJyv/Kysr/ysrK/8vKyv/Kysv/ysrL/8rJyf/Kysr/ysrK/8vKyv/Ly8r/y8vK/8rKyv/Ly8v/ysrL/8vLy//Ly8v/zMvL/8vLy//Ly8z/y8vM/8zMzP/Ly8v/zMvM/8zLy//My8z/y8vL/8zMzP/MzMz/zMzN/8vMzP9mZmb/ZWVl/zIyMv8AAAD/MjIy/wAAAP8MDAz/AAAA/wAAAP/MzMz/zMzM/wAAAP8AAAD/zM3N/83Nzf/Mzc3/zc3N/2ZmZv9mZmb/zc3O/87Ozv+np6f/zs7O/wAAAP8AAAD/zc3O/87Nzv9AQED/zs7O/87Ozv/Ozs//zMzM/8zMzP/Nzcz/zc3M/83Mzf/Nzc3/zc3N/83Ozf/Nzcz/zMzM/8zMzf/Nzc3/zc3N/83Nzf/Nzs7/zc7N/83Nzv/Ozc7/zc7N/87Ozv/Ozc7/zs7O/8/Pzv/Pzs7/zc7O/87Ozv/Ozs7/zs/P/8/Ozv/Ozs//zs/P/8/Pz//Ozs7/z87O/8/Pz//Pzs7/z87O/8/Pz//Pz8//z8/Q/87Ozv/Ozs//z8/O/8/Pz//Pz8//z8/P/8/P0P/P0M//0NDP/8/Qz//P0ND/0NDQ/9DQ0P8nJyb/0dDQ/4KCgv/Qz9D/0NDQ/9DQ0P/Q0NH/0NDR/8PExP/Q0ND/0dHR/87Ozv/Pz8//z8/P/8/Pz//Qz9D/0M/P/9DPz//Q0ND/z8/P/9DPz//P0M//z8/P/9DPz//Q0ND/0NDQ/9DR0f/Q0ND/0dDR/9DQ0P/Q0dD/0dHQ/9HR0f/R0dH/0dHR/9DR0f/Q0NH/0dDQ/9HR0f/R0dH/0tHS/9HR0f/S0dL/AAAA/05OTv8AAAD/AAAA/9HR0f+4uLj/Jycn/wAAAP9OTk7/GRoa/9HR0f/S0tH/DAwM/05OTv/S0dL/0tLS/wAAAP9BQUH/AAAA/5CRkP/S0tP/09PT/9PS0v/T09P/np6d/9LS0//S0tL/0tLT/9PT0//U09T/09PT/9TU0//S0tH/0tHS/9HS0f/R0tH/0tLS/9LT0//S0tL/09LT/9LS0f/S0tL/0dLR/9LS0v/T09L/0tPS/9PS0v/T0tP/09PT/9PT0//T09P/09PT/9PT1P/U1NP/1NTT/9PU0//T09P/1NTT/9PT0//T1NP/09TT/9TU1P/U09T/1NTU/9PU0//U09P/09PU/9TU0//U1NT/1NXV/9TU1P/U1NX/09PU/9TU1P/T1NP/1NTU/9TU1P/U1NX/1dTV/9TU1P/V1NT/1dXV/9XV1f/V1dX/1dXV/9XW1v/V1dX/1dXW/9XV1f/V1dX/1dXV/9XV1f/V1tb/1tbW/9XW1v/W1tb/1NTU/9XU1P/U1NT/1NXV/9TU1P/V1dX/1dTU/9XV1f/U1NX/1NTU/9XU1P/V1dT/1dXV/9XV1f/V1dX/1dXV/9XV1f/W1tX/1dXV/9bV1f/W1tb/1tbW/9bW1v/W1tb/1dXW/9bW1v/W1db/1tbW/9bW1v/W19f/1tbW/9bX1v/W1tb/1tbW/9bW1v/W1tb/19bX/9fX1//X1tf/19fX/9bW1v/W19b/1tbW/9bW1v/X19f/19fX/9fX1//X19f/19fX/9fX2P/X19f/19jX/9jY2P/Y2Nj/2NjY/9jY2P/X2Nj/2NjY/9fX2P/Y2Nj/2NjY/9nZ2f/Y2Nj/2djZ/9bW1v/X19f/1tbW/9fX1//X19f/19fY/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX2P/Y2Nj/19fX/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2djY/9nZ2f/Y2Nj/2dnZ/9jY2P/Y2dj/2NjY/9nY2P/Z2dn/2dnZ/9nZ2f/Z2dn/bGxs/wAAAP++vr3/AAAA/ygoKP/MzMv/AAAA/w0NDf/Z2dn/h4eH/9nZ2f/Z2dn/KCgo/wAAAP/Z2dn/2tra/9ra2v82Njb/Gxsb/wAAAP8AAAD/zc3N/19fX//b29v/NjY2/4iJiP/a2tr/29ra/9vb2//b29v/29vb/9vb2//Z2dn/2dna/9nZ2f/a2tn/2tra/9ra2v/a2tr/2tra/9na2f/a2tr/2tnZ/9ra2v/a2tr/2tra/9ra2v/b29v/29ra/9vb2//a2tr/29vb/9vb2//c29v/29vb/9vc2//b29v/29vb/9vb2//b29v/3Nvb/9zc3P/b29v/3Nzc/9vb2//b3Nz/29vb/9vb2/+JiYn/AAAA/9zc3P9SUlL/3Nvc/9zc3P/b3Nv/3Nzc/9zc3P/c3d3/3Nzc/9zc3P8bGxv/z8/P/wAAAP8AAAD/3d3d/97d3f9SUlL/U1NS/3x8fP8bGxv/3d3d/93d3f8AAAD/AAAA/97d3f/e3t7/3Nzc/9zc3P/c3Nz/3Nzc/9zd3P/d3d3/3Nzd/93d3f/c3Nz/3Nzc/9zc3P/c3N3/3d3d/93d3f/d3d3/3d3d/93d3f/e3d3/3d3d/93e3f/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/d3d3/3t7e/97e3v/e3t7/3t7e/9/f3//Q0ND/KSkp/w0NDf8AAAD/AAAA/1NTU/8pKSn/0dHR/w0NDf9hYWH/3t7e/97f3v/Q0NH/39/f/9/f3//f39//39/f/9/f3//f39//4ODf/9/g4P/g4OD/4ODg/+Dg4P/f39//4N/f/9/f3//g4OD/4ODg/+Dg4P/g4OD/4eDh/97e3v/e3t//3t/e/9/f3//f39//39/f/9/f3//g39//39/f/9/f3//f39//39/f/9/f3//f3+D/4N/f/+Dg4P/f4OD/4ODg/+Dg4P/g4OD/4ODg/+Hg4f/g4eD/4eHh/+Dg4P/g4OD/4ODg/+Dg4f/g4OD/4eHh/+Hh4f/h4eH/4ODg/+Hh4f/h4eD/4eHh/+Hh4f/h4eH/4eHh/+Li4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hi4f/i4eL/4uLi/+Hh4f/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4+L/4uLi/+Li4v/i4uL/4uLi/+Li4//j4+P/4uLj/+Pj4//h4eH/4eHh/+Hh4f/i4uH/4uLh/+Li4v/i4uL/4uLi/+Hh4f/i4eH/4eHh/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Lj4//i4uL/4+Lj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pi4v/j4+P/4+Pj/+Pk5P/j4+P/5OPj/+Pj4//j4+P/4+Pj/+Pj4//j5OT/cnJy/+Pj5P+AgID/4+Pj/+Pk4//j4+P/5OTj/+Tk5P+5ubn/5OTk/+Tk5P8AAAD/Kioq/wAAAP8AAAD/19fX/+Xl5f8NDQ3/VVVV/w0NDf9kZGT/5OTk/+Xl5f85OTn/DQ0N/+Xl5f/m5uX/4+Pj/+Tk5P/j5OP/5OTk/+Tk5P/l5OX/5OTk/+Tl5P/k5OT/5OTk/+Tk5P/k5OT/5eTl/+Xl5f/k5OX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5uXl/+bl5v/m5ub/5eXl/+Xl5f/l5eX/5eXl/+bm5f/m5ub/5ubm/+bm5v/l5eX/5ebl/3Nycv8qKir/rKys/wAAAP8AAAD/AAAA/wAAAP8AAAD/5ubm/+bm5v8qKir/np+f/+bm5v/n5+f/AAAA/8rKyv+QkJD/5+fn/+fn5//n5+j/5+fn/5+fn//n5+f/5+fn/+fn5//n5+f/6Ofo/zk5Of/n5+j/6Ojo/+bm5v/m5ub/5ubm/+bn5v/m5uf/5+fn/+fn5//n5+f/5ubm/+bn5v/n5+b/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6Ofo/+fn5//n5+j/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/5+fn/+jo6P/o6Oj/6ejo/+jo6P/o6en/rq6u/wAAAP9ISEj/AAAA/wAAAP/p6en/AAAA/2VlZf8AAAD/AAAA/+jo6P/o6en/AAAA/wAAAP/p6en/6enp/+np6f/a2tr/dHR0/xwcHP9XV1f/AAAA/wAAAP8AAAD/AAAA/w4ODv/p6un/6urq/1dXV//Nzc3/6urq/+rq6v/p6Oj/6enp/+jp6f/p6en/6enp/+np6f/p6en/6enq/+np6f/p6en/6enp/+np6f/p6en/6unp/+np6v/q6ur/6urp/+rq6v/q6ur/6urq/+rq6v/q6+r/6urq/+vq6//q6ur/6urq/+rq6v/q6ur/6+rq/+vr6//r6ur/6+vr/wAAAP+vr6//kpKS/+vr6v/r6+v/6+vr/+vr6//r6+v/6+rq/+vr6//q6ur/6+vr/+vr6//r7Ov/6+vr/+vr7P/s6+z/7Ozs/+vr7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zr7P/s7Oz/7Ozs/+zs7P/s7Oz/7O3s/+zs7f/t7O3/6+vr/+vr6//r6+v/6+vr/+vr6//s6+z/7Ovr/+zs7P/r6+v/6+vr/+vr6//r6+v/7Ovr/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+3t7f/t7O3/7e3t/+3s7f/t7e3/7Ozs/+zs7f/t7O3/7ezs/+3t7f/t7e3/7e3t/+3t7f/s7ez/7e3t/+zs7P/t7e3/7e3t/+3u7f/t7e3/7u7u/+3t7f/t7e3/7e3t/+3t7f/t7e7/7e3t/+3t7v/u7u7/7e3t/+7u7v/u7u7/7u7u/+7u7v/v7+7/7u7u/+/v7v/u7u7/7u7u/+7u7v/u7u7/7+7v/+/v7//v7u//7+/v/+3t7f/t7u3/7e3t/+7u7v/u7e7/7u7u/+7u7v/u7u7/7u7t/+3t7v/t7e7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/v7+7/7+/v/+/v7//v7+//7+/v/+7u7//v7+//7u/v/+/v7//v7+//7+/v/+/v7//v8O//7+/v/+/v7//v7+//7+/v/+/v7//v8PD/7+/w//Dw8P/v7+//7+/v/+/v7//v8PD/7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/x8PH/8fHx//Hw8f/x8fH/8PDw//Hx8P/w8PD/8fDw//Hx8f/x8fH/8fHx//Hx8f/v7+//8O/v//Dw7//w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PHw//Dw8P/w8fH/8PDw//Hw8P/w8PH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Pz8//y8vL/8/Pz//Ly8v/y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//z8/P/8fHx//Ly8v/x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/9PT0//Pz8//z8/P/8/Pz//Pz8//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/19fX/9PT0//X19f/09PT/9PT0//T09P/09PT/9fX1//X19f/19fX/9fX1//Pz8//09PT/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/19fX/9fX1//X19f/19fX/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/39/f/9vb2//b29v/29vb/9vb2//b29v/39/f/9/f3//f39//19fX/9vb2//X19f/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//f39//39/f/9/f3//f39//29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//4+Pj/9/f3//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/5+fn/9/f3//f39//39/f/9/f3//j4+P/4+Pj/+Pj4//j4+P/39/f/+Pj4//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//r6+v/5+fn/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//n5+f/5+fn/+fn5//n5+f/5+fn/+vr6//n5+f/6+vr/+fn5//n5+f/5+fn/+fn5//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+/v7//r6+v/7+/v/+vr6//r6+v/6+vr/+vr6//v7+//7+/v/+/v7//v7+//6+vr/+/v7//r6+v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//8/Pz/+/v7//v7+//7+/v/+/v7//v7+//8/Pz//Pz8//z8/P/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8/7Ozs/+0tLP/s7Oz/7S0s/+ztLP/tLS1/7W1tf+1tLT/tLOz/7Szs/+zs7P/tbW1/7S1tf+1tbX/tbS0/7S0tP+1tbT/tLW1/7W0tP+0tbX/tbS0/7W2tf+1tLT/trW1/7S0tP+0tbX/tbS0/7S0tP+2tbX/tba1/7W1tf+1tbX/s7Oz/7S1tP+0tbT/tLW0/7W1tP+0tbT/tLS0/7W0tf+1tLT/tbS0/7W0tP+0tbX/tLS0/7W1tf+1tbX/tbW1/7W1tf+1trb/tLW0/7W1tv+1tbb/trW1/7W1tv+1trX/trW2/7W2tf+2tbb/trW1/7a2tv+1tbb/tba2/7a1tf+2trX/trW2/7a1tv+1tbb/trW1/7a2tv+1tbX/t7a2/7a2tv+2trX/tba1/7a1tf+2t7b/tra2/7e3tv+3trb/t7a2/7a2t/+2t7f/t7e3/7e2tv+3uLf/tre2/7e4uP+3trf/t7e3/7a3tv+3trf/uLe3/7e4t/+4t7j/uLe3/7W1tv+2t7b/tba1/7e2tv+2t7b/t7a2/7a2t/+2trb/tre2/7a2tv+2trb/t7a2/7e3tv+3t7f/tra2/7a3tv+3t7f/t7e3/7e2t/+3uLj/t7i3/7e4t/+3uLj/uLi4/7e3uP+4t7f/t7e3/7e4t/+4uLf/t7e4/7e3uP+4ubj/t7i3/7W4tv+4uLj/uLe3/7i3uP+4ubj/ubi5/7m5uf+3t7j/t7e3/7e4uP+4ubj/ubi4/7i4uP+5uLn/uLi5/7m5uP+5ubn/uLm4/7m5uP+5uLj/ubm5/7m5uf+6urn/uLm4/7i4uP+4uLn/ubm5/7m5uf+6ubr/ubq5/7q6uf+4uLf/ubi4/7m4uf+4uLj/uLi4/7m5uf+4uLj/uLi4/7m4uP+4ubj/ubi5/7i5uf+5ubn/ubi5/7m4uP+5ubn/uLm4/7m5uf+5ubn/ubm6/7q6uf+5urr/ubq5/7m5uv+5ubn/ubq5/7q6uf+6ubr/urq5/7q6uv+5urr/urq6/7m6uf+6ubn/ubq5/7m6uf+6urr/urq6/7q6uv+6u7v/ubq6/7q6uv+5ubr/urq6/7q6uv+6u7v/u7u7/7q7uv+6u7r/u7q7/7q6u/+6urr/u7u7/7u7u/+7u7v/u7y8/7q6uv+7u7v/urq6/7u7u/+7vLz/u7u8/7y7u/+8u7z/urq6/7q6uv+6urr/u7q7/7u6uv+6urv/uru7/7q6u/+6urr/u7q7/7u6uv+7u7v/u7q7/7u7u/+6urr/u7u7/7u7u/+7vLv/u7u7/7u7u/+8vLv/vLy7/7u7vP+8vLz/u7y7/7y8u/+8u7z/u7u8/7y8u/+8vLz/vLy8/7y9vf+7vLz/u7y7/7u8vP+8vLz/vLy8/7y8vP+8vLz/vLy9/7u8vP+8vLz/vLy8/728vf+8vL3/vb29/7y9vP+9vL3/vby8/729vf+9vbz/vb29/72+vf++vb7/vb29/76+vv+9vb3/vb69/729vf+9vb7/vb2+/76+vf+9vr7/vr6+/7y8vP+9vL3/vby9/729vf+8vb3/vb29/728vf+9vb3/vL28/7y9vf+8vb3/vLy9/729vf+9vr3/vb29/76+vv+9vr7/vr2+/729vv++vb3/vb6+/76+vv++vr7/v76//72+vf+9vr7/vr69/76+vv++vr7/v76//76+vv+/v7//vr29/76+vv++vr7/vr6+/76+vv++vr7/v76+/7++v/++vr7/vr++/76/vv+/vr//vr+//7+/v/++vr7/v7+//7+/v//AwMD/v7+//7+/wP/Av8D/wMDA/8DAv//AwMD/wL+//8C/v/+/v7//v8C//8DAwP/BwcH/wMDA/8HBwf+/vr//v7++/7++v/++v7//v7+//8C/wP+/v7//v7+//7+/vv+/v7//v76//7+/v//AwL//v7+//7/Av//Av8D/v8C//8DAwP/Av7//wMDA/8DAwP/AwMD/wMHB/8DAwf/AwMD/wMDA/8DAwP/AwMH/wcHA/8HBwP/AwcH/wcHB/8DAwP/AwMH/wcHB/8HBwf/BwMD/wcHB/8HBwf/BwcH/wMHA/8HAwP/AwcH/wcHB/8HBwf/BwcH/wsLC/8LBwf/BwcL/wsLC/8HBwf/CwsH/wsLC/8LDw//CwsL/wsPC/8LBwf/CwsL/wcHC/8LCwv/Dw8L/w8PC/8PDw//CwsL/wMHA/8HBwf/BwcH/wcLC/8LBwf/BwcL/wsLC/8HBwf/BwcH/wcLC/8HCwv/BwsH/wcLB/8LCwv/BwsH/wsLC/8LCwv/Dw8L/wsLC/8LCwv/DwsP/w8PD/8PDwv/Dw8P/w8PD/8LDwv/Dw8P/wsPD/8PDw//ExMP/w8PD/8PEw//DwsL/w8PD/8PCw//Dw8P/xMTD/8PDw//Dw8P/xMTD/8PDw//ExMT/w8PD/8PExP/ExMP/xMTE/8PDxP/ExMT/xMPE/8TExP/ExMT/xcXE/8TExf/ExcX/xMXE/8XFxf/ExMT/xcTF/8TExP/FxMT/xMTE/8XFxf/FxcX/xcbF/8TExP/Ew8P/xMPD/8PDxP/DxMT/xMTE/8TExP/FxMX/w8TE/8TExP/Dw8T/xMTE/8TExP/FxMT/xMTF/8XFxP/FxMX/xcXF/8XExf/FxcX/xcXF/8XFxf/GxcX/xsbG/8TExf/FxcX/xcXF/8XFxv/GxsX/xcbG/8XFxf/Gxcb/xcXF/8XGxf/Fxcb/xcbF/8XGxf/Gxsb/xsXG/8bGxv/Gxcb/xcXF/8bGxf/Fxsb/xsbG/8bGxv/Gxsb/x8bG/8bGxv/Hxsf/x8bG/8fGx//Hx8f/x8jH/8fHx//HyMf/x8fH/8fHx//Gxsf/x8fH/8jIyP/Hx8f/x8fI/8jHx//Gxcb/xsbG/8XFxv/Gxsb/xsfG/8fHxv/Gxsb/xsfH/8bGxv/Gx8f/xsbG/8bHxv/Gxsb/x8fH/8bHx//Hx8f/x8fH/8fHx//Hx8f/x8fI/8fIx//IyMj/yMfI/8jIyP/HyMf/x8jH/8jIyP/HyMj/yMjI/8jJyP/IyMj/ycnI/8jHx//IyMj/yMfH/8jIyP/IyMj/ycjI/8nJyf/IyMn/yMjI/8jIyf/IyMj/ycnI/8jJyP/Jycn/yMnI/8nJyf/Jycn/ycnJ/8nJyf/Jycr/ycnK/8nJyv/Kycn/ysrK/8rJyv/Kysn/ycrJ/8nKyv/Jysr/ysrK/8rKyv/Lysv/yMjI/8nJyf/IyMn/ycnJ/8nJyf/Kycr/ycnJ/8rJyf/Iycj/ycnJ/8nIyP/Jycn/ysrK/8rJyf/Jysr/ycrJ/8nKyv/Jycn/ysnJ/8rKyv/Kysr/ysrK/8rKy//Lysv/ycnK/8rKyv/Kysr/y8vK/8vLy//Lysv/y8rK/8vLy//Kysr/y8rL/8vKyv/Ly8r/y8rK/8vLy//Ly8v/zMvL/8rKyv/Kysr/y8vK/8vLy//Ly8v/zMzL/8vLy//My8v/y8vM/8vMy//My8v/zMzM/8zMzP/Mzcz/zczM/83Mzf/MzMz/zMzM/8zMzP/Nzc3/zc3M/8zMzP/Nzc3/zc3N/8vKy//Ly8v/y8vL/8vLzP/Ly8v/zMvM/8vLzP/MzMz/y8vL/8zLy//Ly8z/zMvL/8zMy//MzMz/zMzM/83Nzf/MzMz/zMzN/83Nzf/MzMz/zMzM/83Nzf/Nzc3/zs7O/8zMzf/Nzcz/zM3M/83Nzf/Nzc3/zc3N/83Nzf/Ozs3/zc3N/83Nzf/Nzc3/zs3N/83Ozf/Ozc3/zc3N/87Ozv/Nzc3/zs7N/87Nzv/Nzs7/zc7N/87Ozv/Ozs7/z8/O/87Ozv/Ozs//z87O/87Pzv/Pz8//z8/P/8/Pz//Qz8//z87P/87Ozv/Oz87/z8/P/8/Pz//Pz8//0NDQ/8/P0P/Ozs7/zs7N/83Nzf/Ozs7/zs7O/8/Pz//Ozs7/z8/O/83Nzf/Ozs7/zs7O/87Pz//Oz87/zs/O/87Pzv/Pz8//z87O/8/Pz//Pz8//z8/P/8/Qz//Qz8//0NDP/9DQ0P/Pz8//0M/P/8/Pz//Qz9D/z9DQ/9DQ0P/Q0ND/0NHQ/9DQ0P/Q0M//z8/Q/9DQ0P/Q0ND/0NHR/9DR0f/Q0dH/0M/Q/9DQ0P/Q0ND/0dDR/9HR0P/R0dH/0NDQ/9DQ0f/Q0ND/0dHR/9HR0f/R0dH/0dHS/9LS0v/R0dH/0tLR/9HR0f/S0dH/0dHR/9HS0v/R0dH/0tLS/9HS0v/S0tL/0NDQ/9HR0f/R0dD/0dDQ/9HQ0P/R0dH/0NDQ/9HR0f/R0ND/0NHQ/9DQ0f/Q0dD/0dHR/9HR0f/R0dH/0dLR/9HS0v/S0dL/0dLS/9HR0f/S0tL/0tPT/9LS0v/T0tL/0tLS/9LS0v/R0dH/0tLS/9PT0//T0tL/0tLT/9PT0//S0tL/09LT/9LS0v/S09P/09LS/9PT0//T09L/09PT/9LS0//S0tL/0tLS/9PS0//T09P/1NPT/9PT0//T09P/1NTU/9PU0//U1NT/1NPU/9TU1P/U1dT/1NTU/9TV1P/U09T/1NTU/9TT1P/U1NT/1dXV/9TV1f/U1dX/1NXU/9LS0v/T09P/0tLS/9PT0//U09P/1NTT/9TU0//T1NT/09PT/9PU1P/T09P/09TU/9PT0//U1NT/09TT/9TU1P/U1NT/1dTU/9TU1P/V1NT/1dXU/9XV1f/U1NX/1dXV/9XV1P/V1NT/1dXV/9TU1P/V1dX/1dXV/9XV1f/V1dX/1NXU/9XV1f/U1NT/1dXV/9XV1f/V1dX/1dXV/9XW1v/V1dX/1dXV/9XV1f/V1dX/1tbW/9bW1v/V1dX/1tbW/9bW1v/W1tb/1tbW/9bW1v/W19f/19fX/9fX1v/X19f/1tbW/9fW1//W1tb/1tbX/9fX1//X19f/19fX/9fX1//V1dX/1dXW/9XV1f/V1tX/1tbW/9bW1v/W1tb/1tbW/9XW1f/W1tb/1dXV/9bW1v/W1tb/1tbW/9bW1v/X19f/1tbW/9fX1//X1tb/19fX/9fX1//X2Nf/19fX/9jY1//X19f/19fX/9fX1//X19f/19jY/9jY2P/Y2Nf/2NjY/9fX1//Y19f/19fX/9fY2P/Y2Nj/2NjY/9jY2P/Y2Nj/19jX/9jY2P/X2Nf/2NjY/9jY2P/Y2dj/2NjY/9nY2P/Z2Nj/2dnZ/9nZ2P/Z2dn/2dnZ/9rZ2v/Z2dn/2dna/9nZ2f/Z2dn/2dnZ/9nZ2f/a2tr/2tra/9nZ2f/a2tr/2NjY/9jY2P/Y2Nj/2NjY/9jY2f/Z2dn/2dnY/9nZ2f/Y2Nj/2NjY/9jY2P/Y2dj/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9na2f/a2tr/2tra/9ra2v/a2tr/2tna/9ra2v/a2dr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2trb/9vb2//b29r/29vb/9ra2v/a2tv/2tra/9ra2//b29v/29vb/9vb2//b29v/29vb/9vc2//b29v/29vc/9zc3P/c3Nz/3Nzc/9zc3P/b29z/3Nzc/9vb2//c3Nz/3Nzc/9zc3f/c3Nz/3dzc/9ra2v/b29v/2trb/9vb2//b29v/29zc/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb3P/c3Nz/29vc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3dzc/93d3f/c3N3/3d3d/9zc3P/c3N3/3Nzc/93d3P/d3d3/3d3d/93d3f/d3d3/3N3c/93d3f/d3dz/3d3d/93d3f/d3d7/3d3d/93d3v/d3d3/3d3d/93d3f/d3d3/3d3d/97e3v/e3t3/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97f3v/f39//3t7e/97e3v/e3t7/3t7e/97f3//f39//39/f/9/f3//d3d3/3d7d/93d3f/d3d3/3t7e/97e3v/e3t7/3t7e/93d3v/d3t3/3d7e/97e3v/e3t7/3t7e/97e3v/f397/3t7e/97f3v/e3t//39/f/9/f3//f39//39/f/+Dg3//f397/39/f/9/f3//f39//39/f/9/g3//g39//4ODg/9/f3//f39//39/f/+Dg3//f4N//4ODg/+Dg4P/g4OD/39/f/9/f3//g4N//4ODg/+Dg4P/g4OD/4ODg/+Dh4f/g4OD/4ODg/+Hh4P/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Dh4f/h4eH/4eHh/+Hh4f/h4eH/4eHi/+Hi4f/i4uL/4N/f/+Dg4P/g4OD/4ODg/+Dg4P/h4OH/4ODg/+Hh4f/g4OD/4ODg/+Dg4P/g4OD/4OHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Lh4f/i4uL/4uLi/+Li4v/i4uL/4eHh/+Li4v/i4eL/4uLi/+Li4v/i4uL/4uLi/+Li4v/h4eL/4uLi/+Li4v/i4uL/4uLi/+Li4//i4uL/4+Li/+Li4v/i4uL/4uLi/+Li4v/i4+P/4+Pj/+Pj4v/j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pk4//k5OT/5OPk/+Tk5P/j4+P/5OTk/+Pj4//j4+P/5OTk/+Tk5P/k5OT/5OTk/+Li4v/i4uP/4uLi/+Pi4//j4+P/4+Pj/+Pj4//j4+P/4uPj/+Pj4//i4+L/4+Pj/+Pj4//j4+P/4+Pj/+Tk5P/j5OP/5OTk/+Tk5P/k5OT/5OTk/+Xk5P/k5OT/5OXl/+Tk5P/k5OT/5OTk/+Tk5P/k5eT/5eXl/+Tk5f/l5eX/5OTk/+Xk5f/k5OT/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5OT/5eXl/+Xk5f/l5eX/5eXl/+Xl5f/l5eX/5eXm/+Xl5f/l5uX/5eXm/+bm5v/m5ub/5ubm/+bm5v/n5uf/5ebm/+bm5v/m5ub/5ubm/+bm5v/n5ub/5ubn/+fn5//l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5ubm/+Xl5f/l5eX/5eXl/+Xm5v/m5uX/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ufn/+bm5v/n5+f/5+fn/+fn5//m5ub/5+bm/+bn5//m5+f/5+fn/+fn5//n5+f/5+fn/+bn5v/n5+f/5+fn/+fn5//n5+f/6Ofo/+fn5//n6Oj/5+fn/+fn5//n5+f/5+fn/+fo5//o6Oj/6Ofn/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6enp/+np6f/p6en/6enp/+jo6P/p6On/6Ojo/+np6P/p6en/6enp/+np6f/p6en/5+fn/+fn5//n5+f/6Ofn/+jo6P/o6Oj/6Ojo/+jo6P/n5+f/6Ojo/+fo5//o6Oj/6Ojo/+no6P/o6Oj/6ejp/+jo6P/p6en/6enp/+np6f/p6en/6enp/+np6f/q6en/6ejo/+np6f/p6en/6enp/+np6f/p6ur/6enp/+rq6v/p6en/6enp/+np6f/p6ur/6erp/+rq6v/q6ur/6urq/+np6f/p6er/6erq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6+rr/+vr6//r6+v/6+vr/+vr6//q6ur/6+vr/+rr6v/r6+v/6+vr/+vr6//r6+v/6+vr/+nq6v/q6ur/6urq/+rq6v/q6ur/6+rr/+rq6v/q6uv/6urq/+rq6v/q6ur/6urq/+vr6v/r6+v/6urr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+zr7P/r6+v/7Ozs/+vr6//r6+v/6+vr/+zs6//r6+v/7Ozs/+zs7P/s7Oz/6+vr/+zs7P/r7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7f/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/t7e3/7O3s/+zs7P/t7e3/7O3s/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/u7e3/7e3u/+7u7v/s7Oz/7Ozs/+zs7P/t7O3/7O3t/+3t7f/t7ez/7e3t/+zs7P/s7ez/7Ozt/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e7t/+7t7f/u7u7/7u7u/+7u7v/t7e3/7e3u/+3t7f/u7u7/7u7u/+7u7v/u7u7/7u7u/+3u7v/u7u7/7u7u/+7u7v/u7u7/7+7v/+7u7v/v7+7/7u7u/+7u7v/u7u7/7u7u/+7v7v/v7+//7u7u/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/w8P/w8O//8PDw/+/v7//v7+//7+/v/+/w7//v7+//8PDw//Dw8P/w8PD/7u7u/+7v7v/u7u7/7+7v/+/v7//v7+//7+/v/+/v7//v7u7/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/w/+/v7//w8PD/7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/7/Dv//Dw8P/w8PD/8PDw//Dw8P/x8PH/8PDw//Hx8P/w8PD/8PDw//Dw8P/w8PD/8PHx//Hw8P/x8fD/8fHx//Dw8P/w8PH/8PDw//Dx8f/x8fD/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/y8vL/8fHx//Ly8v/x8fH/8fHx//Hx8f/x8fH/8vLy//Ly8v/y8vL/8vLy//Hw8P/x8PD/8PDw//Hx8f/x8fH/8fHx//Hx8f/x8fH/8PDx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//y8vL/8vLy//Ly8v/y8vL/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9PT0//Pz8//09PT/8/Pz//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//T09P/y8vL/8/Pz//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9PT0//T09P/09PT/9PT0//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//b29v/19fX/9vb2//X19f/19fX/9fX1//X19f/29vb/9vb2//b29v/29vb/9PT0//X19f/09PT/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//b29v/29vb/9vb2//b29v/29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//j4+P/39/f/+Pj4//b29v/29vb/9vb2//f39//39/f/9/f3//f39//39/f/9vb2//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/+Pj4//j4+P/4+Pj/+Pj4//f39//4+Pj/9/f3//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//j4+P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+fn5//r6+v/5+fn/+fn5//n5+f/5+fn/+vr6//r6+v/6+vr/+vr6//n5+f/6+vr/+fn5//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+/v7//v7+//7+/v/+/v7//r6+v/7+/v/+vr6//v7+//7+/v/+/v7//v7+//7+/v/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//v7+//6+vr/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Pz8//v7+//7+/v/+/v7//v7+//7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//v7+//7+/v/+/v7//z8/P/8/Pz//Pz8//z8/P/8/Pz/+/v7//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//39/f/8/Pz//f39//z8/P/8/Pz//Pz8//z8/P/9/f3//f39//39/f/9/f3/tLW0/7W1tP+1tLX/tbS0/7S0tP+2trb/tLW0/7W2tf+0tLT/tbW1/7S0tP+0tLT/trW1/7W2tf+1trb/tba1/7a2tf+2tbX/tbW1/7a1tf+1trX/tra2/7a2tf+2t7f/tra1/7W1tf+2trX/tba1/7e3t/+3trf/tre2/7a2t/+1tLT/tbW1/7S0tf+2tbb/tbW1/7W1tv+1tbb/tbW1/7a1tf+1tbb/trW2/7a1tv+2trX/tra2/7a2tv+2trX/tbW2/7a2t/+1tbX/tra3/7a2t/+2t7f/t7e2/7a2t/+2t7f/tre2/7a2t/+3trf/t7e3/7e3tv+3t7f/t7e2/7a2tv+2t7f/tra2/7a3t/+3trf/uLe3/7a2tv+4t7j/tre2/7e2tv+2trf/t7e2/7e3uP+4t7f/t7i4/7e3t/+3uLj/t7i4/7e3uP+3t7f/t7i4/7i4uP+4ubn/ubm5/7e3t/+3t7j/uLi4/7m5uP+4ubn/uLm4/7m5uf+4ubn/t7a3/7e3t/+3trb/t7e4/7i4uP+4uLf/t7e4/7e4t/+4uLj/t7e4/7e3t/+3t7f/uLi3/7e3t/+4uLf/ubm4/7i4t/+5uLn/ubm4/7m4uP+4ubn/uLi5/7i4uP+4ubj/uLi4/7m5uP+4uLj/ubi5/7m4uP+4ubj/uLi5/7m5uf+4uLj/ubi5/7i4uP+5uLn/ubi4/7m5uf+5ubn/ubq5/7i4uP+4uLn/uLi4/7m5uf+5ubn/urm5/7q6uf+5urr/urq5/7q6uf+5ubr/ubq5/7q6uv+6urr/urq6/7u6u/+6ubr/urq6/7q6uf+6urr/urq6/7q6uv+6urr/uru6/7m4uf+5ubn/ubm5/7q6uf+6urn/urq5/7m5uv+6ubn/ubm5/7m5uv+6ubr/urm6/7m5uf+6urr/urm6/7q6uv+6urr/urq6/7q6uv+6u7v/u7u6/7q7u/+6urv/u7q7/7q6uv+6urr/u7q6/7q6u/+6u7v/u7u7/7q6uv+7u7v/urq7/7q7uv+6u7v/u7q7/7u7u/+8u7v/u7u7/7u8u/+7u7r/u7u7/7q6uv+7u7v/u7u8/7u8u/+8vLz/u7y7/7y7vP+8u7v/u7y7/7y8vP+8vLz/vb29/728vP+9vb3/u7y7/7y8vP+8vLz/vb28/7y8vf+8vLz/vby8/729vP+7u7v/u7u8/7u7u/+8u7z/u7y8/7u8u/+8u7v/vLy8/7y8u/+7u7v/u7y8/7u7u/+8vLz/vLy8/7y8vP+9vbz/vLy8/728vf+9vL3/vby9/729vf+9vb3/vLy9/729vf+8vb3/vL28/7y9vP+9vbz/vb29/729vv+9vb3/vb2+/728vP+9vb3/vby9/729vf+9vb3/vr69/769vv++vb3/vb29/76+vf+9vb3/vb29/769vf+9vr7/vb69/76+vv+9vr7/vr6+/76+vv+/vr7/v76//76/vv++vr7/v76+/76+vv+/v77/v7+//76/vv+/vr//v7+//7++v/+/v7//vr69/769vf+9vb7/vb6+/729vv++vr7/vr6+/76+v/+9vb7/vb69/72+vf++vr7/vr6+/7++v/++vr//v7+//7+/vv+/v7//vr++/7++v/+/v7//v8DA/7+/v/+/wMD/vr6+/7+/v/+/vr7/v7+//8C/wP+/wL//wL+//7+/wP+/v7//v7+//7+/v/+/v7//wMDA/8DAwP+/wMD/wMDA/7/AwP+/v7//v7/A/8C/v//AwMD/wMDA/8DAwP/AwcD/wMDA/8HAwf/AwcH/wcDA/8HBwf/BwcH/wcHB/8HBwv/BwcD/wcDA/8HBwf/BwcH/wcHB/8HBwf/BwcL/wcHB/7/AwP/AwMD/v7+//8DAwP/AwMD/wMDA/8DBwP/BwcH/wMDA/8DAwP/AwMD/wMHA/8HAwP/AwMD/wMDA/8HBwf/AwMD/wcHB/8HBwf/CwcH/wcHC/8HBwv/BwcH/wsHC/8HBwf/BwsL/wcLC/8LBwf/BwcH/wsLC/8HBwf/CwsL/wsHC/8HBwf/CwsH/wsHB/8LCwv/CwsL/wsLC/8PDwv/CwsH/wsLC/8LCwv/CwsL/wsLC/8PDwv/DwsL/w8PD/8PDwv/Dw8P/wsPC/8PDw//Ew8P/xMTD/8PDxP/ExMP/w8PD/8PExP/Dw8P/xMPD/8PExP/Dw8T/w8PD/8TExP/CwsL/wsPC/8LCwv/Cw8P/wsLD/8PDw//CwsP/w8PD/8PCwv/Cw8P/w8PD/8LCwv/Dw8P/xMPD/8PDw//Dw8T/xMPD/8TDxP/Ew8P/xMTD/8TDxP/ExMT/xMTE/8XExP/Dw8T/w8TE/8TDw//ExMT/xMTE/8XFxf/FxcT/xMXF/8TDw//ExMT/xMTE/8XFxf/ExMT/xMTF/8TExP/FxcX/xMTE/8TFxf/ExMT/xMTF/8TExP/FxcX/xcXF/8XFxv/FxcX/xcXG/8bGxf/Fxcb/xcXF/8bGxv/GxcX/xsbG/8XFxf/FxsX/xcbF/8bGxf/Gxsb/xsbH/8bGxv/Hx8b/xcXE/8XFxP/ExMX/xcXF/8XFxf/Gxsb/xcXF/8bFxf/ExMT/xcXF/8XFxf/FxsX/xcbF/8XFxf/Fxsb/xsXF/8XGxf/Gxsb/xcbG/8bGxv/Gx8f/x8bG/8fGxv/Gx8b/xsbG/8fGxv/Gxsb/x8fG/8fGx//Hx8f/x8bG/8fHx//Hxsf/xsbH/8fGxv/Hx8b/x8fH/8fHx//Hx8f/x8jH/8fGx//Hx8f/xsbH/8fHx//HyMj/yMjI/8fHx//Ix8j/x8fI/8jIyP/Hx8j/yMjI/8nIyf/Iycn/yMjI/8nIyf/IyMj/yMnI/8jIyP/Jycj/yMjI/8nJyf/IyMj/ycnJ/8fHx//IyMf/x8fH/8jHx//HyMj/yMjI/8fIx//IyMj/yMjI/8jHyP/HyMj/yMjI/8jIyP/Jycj/yMjI/8jIyP/JyMj/ycnI/8jIyf/JyMn/ycnJ/8rJyv/Jycn/ycnK/8nIyP/Jycn/ycjI/8nJyf/Jycn/ycrK/8nKyf/Jysr/ycnJ/8rKyf/Jycn/ysrJ/8rKyf/Jysn/ycrJ/8rKyv/Jycn/ysrJ/8rJyv/Jycr/ysrJ/8rKyv/Kysr/y8vK/8rKyv/Ky8v/ysvK/8rKy//Kysr/y8vL/8vLy//LzMv/y8vL/8rLyv/Kysv/y8vL/8vLy//Ly8v/zMvM/8vMzP/Kysr/ycrJ/8rJyf/Kysr/ysrK/8rLyv/Lysr/ysvL/8nJyv/Kysr/ysrK/8rLyv/Ky8v/y8rL/8rLyv/Ly8v/y8vL/8vLy//Ly8v/zMvM/8vLy//My8v/zMvL/8zMzP/Ly8v/y8vM/8vLy//MzMz/zMvM/8zMzP/MzMz/zM3M/8vLzP/LzMz/zMzL/8zMzP/MzMz/zc3M/8zMzf/NzM3/y8zL/8zMzP/MzMz/zczM/83NzP/MzMz/zMzN/83Nzf/Mzcz/zc3N/83Nzf/Nzs7/zc3O/83Nzf/Nzc7/zs7O/83Nzf/Ozc7/zc3O/87Nzv/Nzc3/zs7O/87Ozv/Pz8//zMzM/8zMzP/MzM3/zc3N/83MzP/Nzc3/zc3N/83Nzv/NzMz/zczM/83Nzf/Nzc3/zc3N/83Ozf/Nzc7/zc3N/87Ozf/Ozc7/zc3O/87Ozv/Ozs7/zs/O/87Pz//Pzs//zc7N/87Ozv/Ozs7/zs7P/8/Pz//Pz8//zs7O/87Pzv/Ozs7/zs7O/87Oz//Ozs7/z8/O/8/Pz//Pz8//z8/P/8/Ozv/Ozs7/zs/P/8/Pz//Pz8//0M/Q/8/Pz//Pz9D/0NDP/9DQ0P/P0ND/0NDQ/9DQ0P/R0NH/0dHR/9HQ0f/Qz9D/0NDQ/9DQ0P/Q0ND/0dDQ/9DR0f/R0ND/0dHQ/87Ozv/Pz8//z87O/8/Pz//Pz9D/0M/Q/8/Qz//Q0ND/z8/P/8/Pz//Pz8//0NDP/9DP0P/Q0ND/0NDQ/9DQ0P/Q0ND/0NDQ/9DQ0P/Q0ND/0dDR/9HR0f/Q0dH/0dHR/9DR0f/Q0ND/0NDQ/9DR0f/R0dH/0tHR/9HR0f/R0tL/0NHQ/9HR0f/Q0NH/0dHR/9LR0v/R0tL/0tLR/9HR0v/R0dH/0dHR/9HR0f/S0tH/0dHR/9LS0v/S0tH/0tLS/9LS0v/S09P/0tLS/9PS0//S09P/09PT/9LT0v/T09P/09PS/9LT0//S0tL/0tLT/9PT0//U09T/09PT/9TU0//R0dH/0dHR/9HS0f/R0dL/0tLS/9LT0//S0tL/0tLS/9LR0f/S0tL/0dHS/9LS0v/S09L/0tLS/9LT0//T09L/0tLT/9PT0//S09L/09PT/9PT0//U09P/09TT/9PU1P/T09P/09TU/9PT0//U1NP/09PU/9TU1P/T1NP/1NTU/9PT0//U09T/09PU/9PT0//U1NT/1NTU/9TU1P/V1NX/1NPU/9TU1P/T1NP/1NTU/9TV1P/U1NT/1NTV/9XU1P/V1NX/1dXV/9XU1P/V1dX/1dXV/9bV1f/V1dX/1tXW/9XV1f/V1dX/1dXV/9XV1f/V1tX/1tbW/9bW1v/W1tb/1NTU/9TV1P/U1NT/1dTU/9XV1f/V1dX/1NTU/9XV1f/U1NT/1dTV/9TU1P/V1NT/1dXV/9XV1f/V1dX/1dXV/9XV1f/V1tb/1dXV/9XV1v/W1tb/1tbW/9bW1v/W1tb/1tXV/9bW1v/V1dX/1tbW/9bW1v/W1tf/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tfX/9fX1//X1tb/19fX/9bW1v/X19f/1tbW/9bX1//X19f/19fX/9fX1//X19f/19fX/9fY2P/X19f/19jY/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nf/2NjY/9fX1//Y2Nj/2NjY/9jZ2P/Y2Nj/2NjY/9fW1v/X19f/1tfW/9fX1//X19f/19fY/9fX1//X2Nj/19fX/9fX1//X19f/19fX/9jX2P/Y2Nj/19jY/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NnY/9nZ2f/Z2Nn/2dnZ/9jY2P/Z2Nj/2NjY/9jZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2NjY/9nZ2f/Y2dn/2dnZ/9nZ2f/a2dn/2dnZ/9nZ2v/Z2dn/2dnZ/9nZ2f/Z2dn/2drZ/9ra2v/a2dn/2tra/9ra2v/a2tr/2tra/9ra2v/b2tv/29vb/9va2v/b29v/2tra/9va2v/a2tr/29ra/9vb2//b29v/29vb/9vb2//Z2dn/2tra/9nZ2f/a2tn/2tra/9ra2v/a2tr/2tra/9nZ2f/a2tr/2dna/9ra2v/a2tr/2tvb/9ra2v/b2tr/2trb/9vb2//b29v/29vb/9vb2//c29v/29vb/9vc2//b29v/29vb/9vb2//b29v/3Nvc/9zc3P/b29v/3Nzc/9vb2//c29z/29vb/9vc2//c3Nz/3Nzc/9zc3P/c3Nz/29vc/9zc3P/b3Nz/3Nzc/9zc3P/c3N3/3Nzc/9zc3P/d3d3/3d3d/93d3P/d3d3/3d3d/93d3f/d3d3/3t7e/93d3f/d3d3/3d3d/93d3f/d3d3/3d7e/93d3v/e3t7/3Nzc/9zc3P/c3Nz/3Nzc/9zd3P/d3d3/3N3d/93d3f/c3Nz/3Nzc/9zc3P/d3N3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/97d3f/d3t3/3t7e/97e3v/e3t7/3d3d/97d3v/e3d7/3t7e/97e3v/e3t7/3t7e/9/e3v/d3d7/3t7e/97e3v/e3t7/3t7e/97f3v/e3t//39/f/97e3v/e3t7/3t7e/97f3v/f3t7/39/f/9/f3//f39//39/f/9/f3//f39//39/g/+Dg3//g4OD/4ODg/+Dg4P/f39//3+Df/9/f4P/g4OD/4ODg/+Dg4P/g4OD/4eDg/97e3v/f39//3t/f/9/f3//f39//39/f/9/f3//f4N//3t7e/9/f3//f39//39/f/9/f3//f39//4N/f/+Dg4P/g39//4ODg/+Dg4P/g4OD/4ODg/+Hg4P/g4OD/4eHh/+Dg4P/g4OD/4ODg/+Dg4P/g4OH/4eHh/+Hh4f/h4eH/4ODg/+Dh4P/h4eD/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/g4eH/4eHh/+Hh4f/h4eH/4eHh/+Lh4v/i4eL/4eLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4+Pi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Lj4v/j4+P/4uLj/+Pj4//h4eH/4eHh/+Hh4f/h4uL/4uLh/+Li4v/i4uL/4uLi/+Hh4f/i4eH/4eHh/+Lh4f/i4uL/4uLi/+Li4v/i4uL/4uLi/+Pi4v/i4uL/4uPi/+Pj4//j4+P/4+Pj/+Pj4//i4+L/4+Pj/+Pj4v/j4+P/4+Pj/+Pj4//j4+P/4+Tj/+Pj4//j4+P/4+Pj/+Pj4//j5OP/5OTk/+Tj5P/k5OT/4+Pj/+Tj5P/j4+P/4+Tj/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5eXk/+Tk5P/l5eT/5eXl/+Xl5f/l5eX/5eXl/+Tk5P/l5eX/5OXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eb/5OPk/+Tk5P/k5OT/5OTk/+Tk5P/k5eX/5OTk/+Xl5f/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5f/k5OT/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5uXl/+Xl5f/m5ub/5eXl/+Xl5f/l5eX/5eXm/+bm5v/m5ub/5ubm/+bm5v/l5eX/5ebl/+Xm5f/m5ub/5ubm/+bm5v/m5ub/5+bm/+Xm5f/m5ub/5ubm/+bm5v/m5ub/5+bm/+bn5v/n5ub/5+fm/+fn5//n5+b/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6Ojo/+jo6P/n6Of/6Ojo/+bm5v/m5ub/5ubm/+fn5//n5ub/5+fn/+fn5v/n5+f/5ubm/+bn5//m5ub/5ubm/+fn5//n5+f/5+fn/+fn5//n5+f/5+fo/+fn5//n5+j/6Ojo/+jo6P/o6Oj/6Ojo/+fn6P/o6Oj/6Ofo/+jo6P/o6Oj/6ejp/+jo6P/p6ej/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6ej/6ejp/+np6f/o6Oj/6Ojp/+jo6P/p6On/6Ono/+np6f/p6en/6enp/+np6f/p6en/6enp/+rq6f/p6er/6urq/+rq6v/q6ur/6enp/+nq6v/p6un/6urq/+rq6v/q6ur/6urq/+rq6v/p6Oj/6Ojo/+jo6P/p6en/6enp/+np6f/p6en/6erp/+jp6P/p6en/6enp/+np6f/p6en/6unp/+nq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/r6+r/6urq/+vq6//q6ur/6urq/+rq6v/q6ur/6+rq/+vr6//q6uv/6+vr/+rq6v/q6ur/6urq/+rq6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6ur/6+vr/+vr6//r6+v/6+vr/+zr6//r6+v/6+zr/+zr6//s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zr7P/s7Oz/7Ozs/+zs7P/s7Oz/7O3s/+zs7P/t7Oz/6+vr/+vr6//r6+v/6+vr/+vr6//s7Ov/7Ovr/+zs7P/r6+v/6+vr/+vr6//r7Ov/6+zs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/t7Oz/7e3t/+zs7f/t7e3/7Ozs/+zs7f/s7Oz/7O3t/+3t7f/t7e3/7e3t/+3t7f/s7Oz/7e3t/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7u3u/+7t7v/u7u7/7e3u/+7u7v/u7u7/7u7u/+7u7v/u7u//7u7u/+7v7//u7u7/7u7u/+7u7v/u7u7/7u7u/+/v7//u7u//7+/v/+3t7f/t7e3/7e3t/+3t7f/t7u3/7u7u/+7u7v/u7u7/7e3t/+7t7v/t7e3/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7+7u/+7u7v/u7+//7+/v/+/v7//v7+//7+/v/+/v7v/v7+//7+/u/+/v7//v7+//7+/v/+/v7//v8PD/7+/v/+/v7//v7+//7+/v/+/v7//v7+//8PDv//Dw8P/v7+//7+/v/+/v7//w8PD/8PDv//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8fHw//Dx8f/x8fH/8PDw//Dw8f/w8PD/8PHx//Dw8P/x8fH/8fHx//Hx8f/v7+//8PDw/+/w7//w8PD/8PDw//Dw8P/w8PD/8PDw/+/w7//w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/x8PH/8PDw//Hx8P/x8PH/8fHx//Hx8f/x8fH/8fHx//Hx8f/w8PD/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Pz8//y8vL/8/Pz//Ly8v/y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//z8/P/8fHx//Ly8v/x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/9PT0//Pz8//z8/P/8/Pz//Pz8//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/19fX/9PT0//X19f/09PT/9PT0//T09P/09PT/9fX1//X19f/19fX/9fX1//Pz8//09PT/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/19fX/9fX1//X19f/19fX/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/39/f/9vb2//b29v/29vb/9vb2//b29v/39/f/9/f3//f39//19fX/9vb2//X19f/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//f39//39/f/9/f3//f39//29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//4+Pj/9/f3//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/5+fn/9/f3//f39//39/f/9/f3//j4+P/4+Pj/+Pj4//j4+P/39/f/+Pj4//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//r6+v/5+fn/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//n5+f/5+fn/+fn5//n5+f/5+fn/+vr6//n5+f/6+vr/+fn5//n5+f/5+fn/+fn5//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/7+/v/+vr6//r6+v/6+vr/+vr6//v7+//7+/v/+/v7//v7+//6+vr/+/v7//r6+v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//8/Pz/+/v7//v7+//7+/v/+/v7//v7+//8/Pz//Pz8//z8/P/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//f39//z8/P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Pz8//z8/P/8/Pz//Pz8//z8/P/9/f3//Pz8//39/f/8/Pz//Pz8//z8/P/8/Pz//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/fm2tbb/trW26ra2tf+2trb/tbW2/7a3tv+2trb/t7a3xra1tf+1trWZtbW1/7W2tf+3t7f/t7e2/7a2tv+3t7b/t7e3/7a2tv+3trb/tra2/7e3t/+4uLf/tre3/7i4t/+3t7b/tra2/7e2t/+2t7f/t7e4/7e4t/+3uLf/t7e3Wra1tv+3t7YMtrW29ra3tv+2trb/tra2/7e2tv+3trYAtre2lra2tgC2trYbtre3/7a2t/+3t7bztra2/7e3t/+2t7f/uLi3/7e3tv+4t7f/uLe3/7i3t/+3t7f/t7e3/7e3t/+3t7f/t7e4/7e3uP+3t7f/uLe3/7e3t/+5uLj/uLe4/7e4t/+3uLf/t7e3/7e3t/+5uLj/uLm5/7m5uP+3t7j/uLi3/7e3uP+4ubn/uLi4/7m4uf+4uLn/ubi4/7m5uP+4uLn/ubi4/7m5uP+4ubn/ubm5/7m5uf+5ubr/ubi5/7i5uf+5uLn/ubm5/7m5uf+6ubn/ubm6/7m6uv+4t7f/ubi5/7m5uP+4ubn/uLi5/7i4uP+4uLj/ubi4/7m5uP+4uLn/ubi5/7m4uP+4uLj/ubi4/7i4uf+5ubn/uLm5/7m5uf+5ubn/ubm5/7q5uv+6ubn/urq5/7q6uv+5ubn/urq5/7m5uf+5ubn/ubq5/7q6uv+5urr/urq6/7m6uf+5ubr/ubm5/7m6uv+6urr/urq6/7q6uv+6u7r/ubq5/7q6uv+6ubn/urq6/7q6uv+6u7v/u7q7/7q6uv+6urr/uru7/7u6u/+6u7r/u7u7/7y7u/+7u7v/u7u8/7q6uv+7u7v/u7q7/7u7u/+7u7z/u7y7/7u7u/+7u7v/urq6/7q6uv+6urr/u7u6/7q7uv+7urr/u7u6/7q7uv+6urr/u7q6/7u7uv+7urr/uru6/7u7u/+7u7r/u7u7/7u7u/+7u7v/u7u7/7y7u/+7u7v/u7u7/7u8u/+8vLz/vLy8/7u7u/+7vLv/u7u7/7y7u/+8vLz/vLy8/7y8vP+7vLv/u7u7/7y8u/+8vLz/vLy8/7y9vP+8vbz/vby9/7y7vP+8vLz/vLy8/728vP+9vLz/vby8/728vP+8vb3/vb28/729vf+8vbz/vb29/729vv++vb3/vb2+/72+vf+9vb3/vr6+/729vf+9vb7/vr2+/76+vf++vr7/vr6+/7y8vP+9vLz/vL28/7y9vP+8vL3/vb29/7y9vP+9vb3/vLy9/7y8vf+8vL3/vLy9/729vf+9vb7/vb29/729vf+9vr7/vb69/769vv++vr7/vr29/76+vv++vr7/vr++/769vv+9vb7/vb69/76+vv++vr7/vr++/76+v/++v7//vb29/76+vv++vr7/v7+//76/v/++v7//vr++/7++v/++vr7/v76+/76/v/++vr7/v7++/7+/v/+/vr//v7+//7+/v/+/v8D/v7+//8DAv//Av8D/wMDA/7+/wP/AwMD/v8DA/7+/wP/Av7//v7+//8DAwP/AwMD/wMDA/8HAwP+/vr//v76+/76/vv+/v77/v7+//7/AwP+/v7//wMC//76/vv+/v7//vr6+/7+/v//Av8D/v8DA/7/AwP/AwL//v7+//8DAwP+/wL//wMDA/8DAwP/AwMD/wMHA/8HAwf/AwMD/wMDA/8DAwP/AwMH/wcDB/8HAwP/AwMD/wcHB/8DAwP/BwMD/wcDB/8HBwP/BwcD/wcHB/8HBwf/CwsH/wMHA/8DAwP/BwcH/wcHB/8HBwf/CwcH/wsHC/8LBwf/BwcH/wcLB/8LCwv/BwcL/wsLC/8LCwv/CwsL/w8PD/8LCwv/CwsL/wcLB/8LCwv/Dw8L/wsLC/8LDw//DwsP/wMDA/8HBwf/BwcH/wcHB/8HCwv/CwsL/wsHC/8LBwf/BwcH/wsHB/8LBwf/CwcL/wcHC/8LCwv/BwsL/wsLC/8LCwv/Cw8L/wsLC/8PDwv/CwsP/w8PD/8LDw//Dw8P/wsPD/8PDwv/Dw8L/wsPC/8PDw//Dw8T/w8PD/8TExP/Dw8L/w8PD/8LCwv/Dw8P/w8PD/8PDw//Dw8P/w8TD/8PDw//Ew8P/w8PD/8PEw//DxMP/w8PD/8TDxP/ExMT/xMTE/8TExP/ExMT/xcXF/8TExf/FxMX/xcTE/8XFxf/ExMT/xMXF/8XExP/FxcX/xMTF/8XFxf/FxcX/xsbG/8TDw//Dw8T/w8PD/8PDw//ExMP/xMTE/8TExP/ExcT/w8TE/8TExP/Ew8P/xMTE/8TExP/FxcX/xcTE/8XFxP/ExcT/xcTE/8TExP/FxcX/xcXF/8bGxv/Gxcb/xcXG/8XFxP/FxcX/xcXF/8bFxf/GxcX/xsbG/8XFxv/Fxsb/xcXF/8bGxf/Fxcb/xcbF/8bFxv/Gxsb/xcbF/8bGxv/FxsX/xsbG/8XFxv/Gxcb/xsbG/8fHxv/Gxsb/x8bG/8bHxv/Hx8b/x8bG/8fGxv/Hx8f/x8jH/8fHx//Ix8j/xsfH/8fHx//Hxsb/x8fH/8jIyP/HyMf/yMfH/8fHx//Fxcb/xsbG/8XGxv/Gxsb/xsfG/8bGx//Hx8f/x8fG/8bGxv/Gxsf/xsbG/8bGxv/Gxsb/x8fH/8bHxv/Hx8f/x8fH/8jHx//Hx8f/x8fI/8jHyP/IyMj/yMfI/8jIyP/Hx8f/yMfI/8fIyP/HyMf/yMjI/8nIyP/IyMj/yMnJ/8jHx//IyMj/x8jI/8jIyP/IyMn/ycjJ/8nIyP/Jycj/yMjI/8jJyP/IyMj/ycjI/8jIyP/IyMj/yMnI/8nJyf/Jycn/ycnJ/8nJyf/Jycn/ysnJ/8nJyv/Jysr/ysrK/8nJyf/Jysr/ysrK/8rKyv/Jycn/ysrK/8rKyv/Ly8v/yMnJ/8nJyf/IyMj/yMnI/8jIyf/Jycn/ycnJ/8nJyf/IyMn/ycjI/8jIyf/Jycn/ycnJ/8rKyv/Jycr/ycnJ/8nJyf/Jysr/ysnJ/8rKyv/Kysr/y8rK/8vKyv/Lysr/ysnJ/8rKyv/Kysr/y8rK/8rKy//Ky8r/y8vL/8vLy//Kysr/ysrK/8vLy//Kysr/y8vK/8vLy//Ly8v/y8zL/8rLyv/Lysv/y8rK/8vLy//Ly8v/y8vM/8vLzP/MzMz/zMzM/8zLzP/LzMv/zMzM/8zMzP/NzMz/zMzM/83Nzf/My8z/zMzM/8zMzP/MzMz/zMzN/8zNzf/NzMz/zc3N/8vLy//Ly8v/y8vL/8vLy//LzMv/zMzL/8zLy//MzMz/y8vL/8vMy//My8v/zMvL/8vLy//MzMz/zMzM/8zNzP/MzMz/zM3N/83Nzf/MzMz/zM3N/83Nzf/Nzc3/zc7N/83Mzf/Mzcz/zMzM/83Nzf/Nzc3/zc7N/87Ozv/Nzc3/zMzM/83Nzf/Nzc3/zc7N/87Nzv/Nzs7/zs7N/87Ozv/Nzc3/zc3O/87Ozv/Ozs3/zc3O/87Ozv/Ozs7/zs7P/87Ozv/Ozs//z8/O/8/Pz//Oz87/z8/P/87Oz//Pz8//zs/O/8/Pz//Oz87/z87O/8/Pz//Q0ND/z8/P/9DPz//Nzs7/zc7N/83Nzv/Ozs7/zs7O/87Pzv/Oz87/zs7P/83Ozf/Ozs7/zs7O/87Ozv/Pz87/zs7O/87Oz//Pzs7/zs7P/8/Pz//Ozs7/z8/P/9DP0P/Q0ND/z9DQ/9DQz//Pz8//0M/P/8/Pz//Qz8//z8/Q/9DQ0P/P0ND/0NDQ/9DP0P/Pz8//z8/P/8/Q0P/Q0ND/0dHR/9DQ0P/Q0ND/z9DP/9DQ0P/Qz9D/0NDQ/9HQ0f/R0dD/0NDR/9DR0f/R0NH/0dHR/9DQ0P/R0dH/0dLR/9HS0v/S0dL/0tHR/9HR0f/R0dL/0dHR/9HR0f/R0dL/0tLS/9LS0v/S0tL/0NDQ/9HQ0P/Q0ND/0NHR/9DR0P/R0dH/0NDQ/9HR0f/Q0ND/0dDQ/9DQ0f/Q0NH/0dHR/9LS0f/R0dH/0dLS/9HR0v/R0tL/0tLS/9HS0f/S0tL/0tLT/9LS0v/T0tL/0tHS/9LS0v/R0dH/0tLS/9LS0v/S0tL/09PS/9LS0//S0tL/0tLS/9LS0v/S0tP/0tPT/9PT0//T0tL/09PT/9LS0//S09L/09PT/9LS0v/T09P/09PT/9PT0//U1NT/09TU/9TU0//T1NP/1NPU/9TU1P/U1NT/1NTU/9TU1P/U1NT/1NTU/9TT0//U1NT/1NTU/9TV1P/V1NX/1NTU/9PT0v/T09P/0tLT/9PT0//U1NP/1NTT/9TT1P/U1NT/09PT/9TT1P/T09P/1NPT/9PU1P/U1NT/1NPU/9TU1P/U1NT/1NTU/9TU1P/V1NX/1NTV/9XV1f/V1NX/1dXV/9TU1f/V1dT/1dXU/9TV1f/V1dX/1dXV/9XV1f/V1dX/1NTV/9XV1f/V1dT/1dXV/9XV1f/W1dX/1dXV/9XW1v/V1dX/1dXV/9XV1f/V1dX/1dbV/9bW1v/V1db/1tbW/9bW1v/W1tb/1tbW/9bW1v/W19f/19fX/9fX1v/X19f/1tbW/9bX1v/W1tb/1tbW/9fX1//X19f/19fX/9fX1//V1dX/1tXW/9XV1f/V1db/1tbW/9bW1v/W1tb/1tbW/9bV1v/W1tb/1tbV/9bW1v/W1tb/1tfW/9bW1v/W1tb/19bW/9fX1//W1tb/19fX/9fX1//Y2Nf/19fX/9jX1//X19f/19fX/9fX1//X19f/19fY/9jY2P/X19f/2NjY/9fX1//X2Nj/19fX/9fX2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjX/9jY2P/Y2Nf/2NjY/9jY2P/Y2dn/2NjY/9nZ2P/Z2dj/2dnZ/9jY2P/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2tr/2tra/9nZ2f/a2tr/2NjY/9jY2P/Y2Nj/2NjY/9jZ2P/Z2dn/2dnZ/9nZ2f/Y2Nj/2NjY/9jY2P/Y2dj/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9rZ2f/a2tr/2tra/9ra2v/a2tr/2dnZ/9ra2v/Z2tr/2tra/9ra2v/b2tr/2tra/9ra2//a2tr/2tra/9ra2v/a2tr/2tra/9vb2//b29v/29vb/9ra2v/a29v/2tra/9ra2v/b29v/29vb/9vb2//b29v/29vb/9vc3P/b29v/3Nzb/9zc3P/c3Nz/3Nzc/9zc3P/c3Nv/3Nzc/9vc3P/c3Nz/3Nzc/93c3P/c3Nz/3dzc/9va2v/b29v/2tra/9vb2//b29v/29vc/9vb2//b29v/29vb/9vb2//b29v/29vb/9zc2//c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3dzd/93d3f/d3Nz/3d3d/9zc3P/c3d3/3Nzc/9zc3P/c3dz/3d3d/93d3f/d3d3/3d3d/93d3f/c3dz/3d3d/93d3f/d3d3/3d3d/97d3f/d3d3/3d3d/93d3f/d3d3/3d3d/97e3v/d3t3/3t7e/93e3v/e3t7/3t7e/97e3v/e3t7/3t7f/97e3v/f39//3t7e/97e3v/e3t7/3t/e/97e3v/f39//39/f/9/f3//d3d3/3d3d/93d3f/e3d3/3t3d/97e3v/e3t7/3t7e/93d3f/e3t3/3t3d/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/9/e3//f3t//39/f/9/f3//f39//39/f/9/f3//e39//39/f/9/f3//f39//39/f/9/f4P/g39//4ODg/9/f3//f39//39/f/9/f3//g4OD/4ODg/+Dg4P/g4OD/39/f/+Df3//f3+D/4ODg/+Dg4P/g4OD/4ODg/+Dg4f/g4OD/4eDg/+Dg4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hg4f/h4eH/4eHh/+Hh4f/h4eH/4eHi/+Hh4f/h4eH/3+Dg/+Dg4P/g4OD/4ODg/+Dg4P/h4eD/4ODg/+Hh4f/g4OD/4ODg/+Dg4P/h4eH/4eDg/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4uLi/+Hi4f/i4uL/4eHh/+Hi4f/h4eH/4uHi/+Li4v/i4uL/4uLi/+Li4v/h4uL/4uLi/+Hi4f/i4uL/4uLi/+Li4//i4uL/4+Li/+Li4v/i4uL/4uLi/+Li4v/i4uP/4+Pj/+Li4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pk4//k5OT/4+Pj/+Tk5P/j4+P/4+Pj/+Pj4//j4+P/5OTk/+Tk5P/k5OT/5OTk/+Li4v/j4+P/4uLi/+Li4v/j4+P/4+Pj/+Pj4//j4+P/4uPj/+Pj4//i4uP/4+Pj/+Pj4//k5OP/4+Pj/+Tj5P/j4+P/5OTk/+Pk4//k5OT/5OTk/+Tk5P/k5OT/5OXk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tl5f/l5eX/5OTk/+Tk5P/k5OT/5OTk/+Tl5P/l5eX/5eXl/+Xl5f/k5OT/5OTk/+Tl5f/l5eX/5eXl/+Xl5f/l5eX/5ubm/+Xl5f/l5ub/5ebm/+bm5v/m5ub/5ubm/+bm5v/m5+b/5ebl/+bm5v/m5ub/5ubm/+bm5v/n5+f/5+bm/+bm5//k5OX/5eXl/+Xl5f/l5eX/5eXl/+bm5v/l5uX/5ubm/+Xl5f/l5eX/5eXl/+Xl5f/m5uX/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+fm5v/n5+f/5+bm/+fn5//m5ub/5ubm/+fm5//n5+f/5+fn/+fn5//n5+f/5+fn/+bm5//n5+f/5+bm/+fn5//n5+f/6Ojo/+fn5//o6Of/5+fn/+fn5//n5+f/5+fn/+fn5//o6Oj/5+jn/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ono/+np6P/o6On/6enp/+jo6P/p6On/6Ojo/+jo6P/o6ej/6enp/+np6f/p6en/5+fn/+fn6P/n5+f/6Ojn/+jo6P/o6Oj/6Ojo/+jo6P/n6Of/6Ojo/+fn5//o6Oj/6Ojo/+np6P/o6Oj/6ejp/+jp6P/p6Oj/6Ojp/+np6f/p6en/6enp/+np6f/p6en/6Ojo/+np6f/p6en/6enp/+np6f/p6un/6enp/+rq6v/p6en/6enp/+np6f/q6er/6urp/+rq6v/q6ur/6urq/+np6f/p6un/6urp/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+vr6//q6ur/6urq/+vr6//r6+v/6+vr/+vr6//r6+r/6+vr/+vr6v/r6+v/6+vr/+vr6//r6+v/6+vs/+rp6v/q6ur/6urq/+rq6v/q6ur/6urr/+rq6v/q6+r/6urq/+rq6v/q6ur/6urq/+vr6v/r6+v/6urq/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr7P/r7Oz/7Ozs/+vr6//r6+v/6+vr/+zs7P/s6+z/7Ozs/+zs7P/s7Oz/6+vr/+vs7P/s6+v/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/r7Ov/7Ozs/+zs7P/s7Oz/7Ozs/+zs7f/s7Oz/7e3t/+zs7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/u7e7/7e3t/+3t7f/t7e3/7e3t/+3t7f/u7e7/7e7u/+7u7v/s7Oz/7Ozs/+zs7P/s7Oz/7e3s/+3t7f/t7Oz/7e3t/+zs7P/s7ez/7Ozs/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e7u/+3t7v/u7u7/7u7u/+7u7v/t7e3/7e3u/+3t7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7f/u7u7/7u7u/+7u7v/u7u7/7+7u/+7u7v/u7+//7u7u/+7u7v/u7u7/7u7u/+/u7v/v7+//7+7u/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Dv7//w7/D/8PDw/+/v7//v7+//7+/v/+/v7//v7/D/8PDw//Dw8P/w8PD/7u7u/+/v7//u7u7/7+/u/+/v7//v7+//7+/v/+/v7//u7u7/7+/v/+/v7v/v7+//7+/v/+/v7//v7+//8O/v/+/v7//w7/D/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/7+/v//Dw8P/w8PD/8PDw//Dw8P/x8fD/8PDw//Hw8f/w8PD/8PDw//Dw8P/w8PD/8PHw//Dx8P/x8fD/8fHx//Dw8P/w8PH/8PDw//Dx8P/x8fD/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/y8vL/8fHx//Ly8v/x8fH/8fHx//Hx8f/x8fH/8vLy//Ly8v/y8vL/8vLy//Hx8P/w8fH/8fDw//Hx8f/x8fH/8fHx//Hx8f/x8fH/8PDx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//y8vL/8vLy//Ly8v/y8vL/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9PT0//Pz8//09PT/8/Pz//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//T09P/y8vL/8/Pz//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9PT0//T09P/09PT/9PT0//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//b29v/19fX/9vb2//X19f/19fX/9fX1//X19f/29vb/9vb2//b29v/29vb/9PT0//X19f/09PT/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//b29v/29vb/9vb2//b29v/29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//j4+P/39/f/+Pj4//b29v/29vb/9vb2//f39//39/f/9/f3//f39//39/f/9vb2//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/+Pj4//j4+P/4+Pj/+Pj4//f39//4+Pj/9/f3//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//j4+P/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//r6+v/5+fn/+fn5//n5+f/5+fn/+fn5//r6+v/6+vr/+vr6//n5+f/6+vr/+fn5//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//v7+//7+/v/+/v7//r6+v/6+vr/+vr6//v7+//7+/v/+/v7//v7+//7+/v/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+/v7//r6+v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Pz8//v7+//7+/v/+/v7//v7+//7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//v7+//7+/v/+/v7//z8/P/8/Pz//Pz8//z8/P/8/Pz/+/v7//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//f39//z8/P/8/Pz//Pz8//z8/P/8/Pz//f39//39/f/9/f3//Pz8//39/f/8/Pz//f39//39/f/9/f3//f39//39/f/8/Pz//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f35/f39//39/er+/v7//f39//39/f/9/f3//f39//39/cb+/v7//v7+mf7+/v/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//v7+//7+/lr+/v72/v7+DP7+/v/9/f3//v7+//7+/vP+/v6T/v7+AP7+/hv+/v4A/v7+ALe2tgC2trcAtra3ALa3t4S2t7f/t7i3Cba3t9W4uLcAtra2ALe3tgC3trYAt7e3ALi4tyS3t7cAuLi3ALi4t/+4uLf/t7e3/7i3t/+4uLj/t7e4/7m5uP+4uLj/uLi56re4t/+4t7gzuLi45Li3t/+4uLn/uLm5/7i4uP+4uLkAtra2ALe3twC2t7YAt7i3ALe4twC4uLgAt7e4ALe3uAC3t7cAt7i4ALi4uAC4uLcAt7e4ALi3twC3uLcAt7e4ALe4uBi4ubgAt7i3ALi4uMm5ubj/ubm5Cbm4uYe5ubkAuLi4ALi4uAC4uLgAuLi4ALi5uAC5ubkAubi5ALm5uf+4uLj/uLi4/7i5uP+4uLj/uLm4/7m5uf+5ubn/ubm5/7m5uP+5uLj/ubi5/7m5uf+5ubn/ubq5/7m5uf+5ubn/urq6/7m6uf+5urn/ubm6/7q6uv+6urr/urq6/7q6u/+5urr/urq6/7q5uv+6urr/urq6/7u6uv+7u7r/u7u7/7i4uP+5ubn2ubm5/7m5uf+5ubr/urq5/7m5uv+5urkYubm5mbm5uQC5ubkAurq68Lq5uf+6uroGurm6S7q6uv+6urr/urq6/7q6uv+7urv/u7q7/7q6u/+7u7v/u7u7/7q6uv+7u7qTuru7zLq7uv+7u7r/u7u7z7q7uv+7u7v/u7q6/7q6uv+7u7r/urq6/7u7u/+7vLv/u7u7/7y7u/+7urv/u7u7/7u6uv+7u7v/u7y7/7u8vP+8vLz/u7u8/7y7u/+8vLv/vLu7/7y8vP+8vLz/vL29/729vP+8vL3/vLu7/7y8vP+8vLz/vL28/728vP+9vL3/vby9/7y9vf+7u7v/u7u7/7u7u/+8vLz/u7u7/7y8u/+8u7z/vLy8/7y8u/+7u7v/u7u7/7y7vP+8u7z/vLy8/7y8vP+8vbz/vLy8/728vf+8vL3/vby8/7y8vP+9vb3/vLy9/729vf+9vL3/vL28/7y8vP+8vbz/vb29/72+vf+9vb3/vr2+/7y9vP+9vb3/vL29/729vf++vr7/vb6+/729vv++vb3/vb29/729vf+9vb3/vb29/729vf+9vb7/vb29/76+vv++vb3/vr6+/76+vv++vr//vr6//76+v/++vr//vr6+/76+vv++v7//vr6+/7+/v/++vr7/v7+//7++v/+/v7//vr2+/729vv+9vr7/vr69/72+vv++vr7/vr6+/76+v/++vb3/vb6+/72+vv++vr7/vr6+/76+v/++v77/vr6//7++vv+/vr//vr6+/7++vv+/v7//v7+//7+/v/+/v8D/vr6//7+/v/++vr7/v7+//8DAv//Av7//wMDA/7/Av/+/v7//wL+//7+/v/+/wL//wMC//8DAwP+/v8D/wMDA/8C/v/+/wMD/wL+//8C/v//AwMD/wMDA/8DAwP/AwMD/wMDA/8HBwP/BwMD/wMHB/8HAwP/BwcH/wcHB/8HCwf/AwMH/wcDA/8HBwP/BwcH/wcHB/8LBwv/CwsH/wcHB/7/AwP/AwMD/wL+//8DAwP/AwMD/wMDB/8HAwf/AwcD/wL+//8DAwP/AwMD/wcDB/8DBwP/AwcH/wcDB/8HBwf/BwcD/wcHB/8HBwf/BwsL/wcHC/8LCwf/BwcL/wsHB/8HBwf/CwsH/wsLC/8HBwf/CwsH/wsLC/8LBwf/CwsL/wsLB/8HCwf/CwcH/wcHB/8LCwv/Dw8L/wsLC/8LCw//CwcH/wsLC/8HBwv/CwsL/wsPC/8PCw//Cw8L/wsLC/8LDwv/Dw8P/wsLC/8PDw//Ew8T/xMPD/8PDw//ExMP/w8PD/8TEw//Dw8P/w8TD/8TExP/Ew8P/w8TE/8TExP/CwsL/wsPC/8LCwv/Dw8L/w8PD/8PDw//CwsL/w8PD/8LCwv/DwsL/wsLC/8PCw//Dw8P/xMTD/8PDw//Dw8P/xMPD/8TDxP/Dw8T/xMPE/8PDw//ExMT/xMTE/8XExf/Dw8T/xMTD/8TDw//ExMT/xMTE/8XFxf/ExMX/xMTE/8PDw//ExMT/xMTE/8TFxP/ExMT/xcXE/8TExP/FxcX/xMTE/8XFxf/FxcT/xcTF/8XExf/FxcX/xcXF/8XGxf/FxcX/xsXG/8bFxv/GxcX/xsXG/8bGxv/Fxcb/xsbG/8XFxf/Fxcb/xsXG/8XFxv/Gxsb/x8fG/8bGxv/Gxsf/xcXF/8TExf/ExMX/xcXF/8XFxf/GxsX/xsbG/8XGxv/ExMX/xcXF/8XFxf/Fxcb/xcXF/8XFxv/GxsX/xsXF/8XFxv/Gxsb/xsbG/8bGxv/Hx8b/xsbH/8fGx//Hx8b/xsbG/8bHxv/Gxsb/x8fH/8bHx//Hx8f/xsbH/8fHx//Gxsf/xsbG/8fGxv/Gxsb/x8fH/8fIx//Hx8f/x8fH/8fGx//Hx8f/xsbH/8fHx//HyMj/yMjI/8jHx//Hx8j/x8fI/8jIyP/HyMf/yMjI/8jIyf/Iycj/ycnJ/8nIyP/IyMj/ycjI/8jIyP/JyMj/yMjJ/8jJyP/JyMj/ycnJ/8fHx//IyMj/x8fH/8jHx//IyMj/yMjI/8jHx//IyMj/x8jH/8jHyP/HyMj/yMfH/8jIyP/IyMj/yMjI/8nIyP/Iycj/ycjJ/8jIyP/Jycj/ycnJ/8nJyf/Jycn/ysrJ/8jJyf/IyMn/yMjJ/8nJyf/Jycn/ysrK/8rKyf/Kycn/yMjI/8nJyf/Jycn/ysrJ/8nJyv/Jycr/ycnJ/8rKyv/Jycn/ycrJ/8nJyf/Kysn/ysnK/8rKyv/Kysr/ysvK/8rKyv/Ky8v/ysvK/8vLy//Lysr/y8vL/8vLy//LzMv/ysrK/8rKyv/Ky8r/y8vL/8vLy//LzMz/y8vM/8vLzP/Jycn/ycrJ/8nJyv/Kysr/ysrK/8rKyv/Lysr/ysrK/8rJyv/Kysr/ysrK/8rLy//Ky8v/y8rL/8rKy//Ly8v/y8rK/8vLy//Ly8v/y8vM/8vLy//Ly8v/zMvM/8zMzP/Ly8v/y8vL/8vMy//My8z/zMzM/8zMzP/MzMz/zc3N/8vMzP/My8z/y8vM/8zMzP/MzMz/zMzM/8zMzf/Nzcz/zMvL/8zMzP/MzMz/zMzM/8zMzP/Nzc3/zc3N/83Nzf/MzMz/zc3N/83Nzf/Nzc3/zs7N/87Nzv/Nzc3/zs7O/83Nzf/Ozs3/zs7O/87Ozf/Ozs3/zs7O/87Ozf/Ozs7/zMzM/8zNzP/Nzcz/zczN/8zMzf/Nzc3/zc3N/83Ozf/Nzc3/zc3N/8zMzP/Nzc3/zc3N/83Nzf/Ozc7/zc7N/83Nzv/Ozc3/zc3O/83Nzv/Ozs7/zs/P/87Ozv/Oz87/zs7N/87Ozv/Nzc3/zs7O/87Ozv/Pz8//zs/O/8/Pz//Ozs7/z87P/87Ozv/Pzs7/zs7P/8/Pz//Ozs//z8/P/87Oz//Pzs//z87O/87Pz//Pz8//0NDP/8/Pz//Q0M//z8/P/8/Qz//Pz8//0NDP/9DQ0P/Q0dD/0NDQ/9DR0P/Pz8//0NDQ/8/P0P/Q0ND/0NDR/9DQ0P/Q0NH/0NHR/87Oz//Pz8//zs7P/8/Pz//Pz8//0M/P/9DPz//Qz8//z8/P/9DQz//Pz8//0NDQ/8/P0P/Q0ND/z9DP/9DQ0P/Q0ND/0NDR/9DQ0P/R0ND/0dDR/9HR0f/R0dH/0dHR/9DR0P/Q0NH/0NDR/9HQ0f/R0dH/0dHR/9HR0f/R0dL/0dHR/9HR0f/Q0ND/0dHR/9LR0f/S0tL/0dLR/9LS0v/R0dH/0dHR/9HR0f/S0tL/0tHR/9LS0v/R0dH/0tLS/9LS0v/S0tL/0tLS/9LS0v/T0tL/09PT/9PS0v/T09P/09PS/9PS0v/S09L/0tLS/9PT0//U09P/09PT/9TU0//R0dL/0tLS/9LS0f/S0tH/0tLS/9LS0v/S0tL/09PS/9HR0f/S0tL/0dHS/9LS0v/T09P/09LS/9PT0//T0tL/0tLT/9PT0//T09L/09PT/9TU1P/T1NP/1NTT/9TT1P/T09P/1NTT/9PT0//U09P/09TT/9TU1P/U1NP/1NTU/9PU0//T09T/09TU/9PU0//U1NT/1NTU/9TU1P/U1NX/09PU/9TU1P/U1NP/1NTU/9XV1f/V1NT/1NXU/9XU1P/U1NT/1dXV/9XU1P/V1dX/1dXV/9bW1f/V1dX/1dXV/9XV1f/V1dX/1dXV/9XV1f/V1db/1tbW/9XW1v/W1tb/1NTU/9XV1P/U1NT/1dXU/9XU1f/V1dX/1dXV/9XV1f/V1dT/1NXV/9XU1P/V1dX/1dXV/9XV1f/V1dX/1dXV/9XV1f/W1dX/1dXV/9XV1f/W1tb/1tbW/9bW1v/W1tb/1tXW/9bW1v/W1tX/1tbW/9bW1v/X1tf/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tfW/9fX1//W1tf/19fX/9bW1v/X1tb/1tbW/9fX1v/X19f/19fX/9fX1//X19f/19fX/9fY1//X19f/2NjX/9jY2P/Y2Nj/2NjY/9jY2P/Y19j/2NjY/9fX1//Y2Nj/2NjY/9jY2P/Y2Nj/2NjZ/9fX1v/X19f/19fW/9fX1//X19f/2NfY/9fX1//X2Nf/19fX/9fX1//X19f/19fX/9fX1//Y2Nj/2NjX/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2dnY/9nZ2f/Y2Nj/2dnZ/9jY2P/Y2dn/2NjY/9nZ2P/Z2dn/2dnZ/9nZ2f/Z2dn/2NjZ/9nZ2f/Z2dj/2dnZ/9nZ2f/a2tr/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2tnZ/9ra2v/a2dr/2tra/9ra2v/a2tr/2tra/9ra2v/a29r/29vb/9va2//b29v/2tra/9va2v/a2tr/2tra/9vb2//b29v/29vb/9vb2//Z2dn/2dna/9nZ2f/Z2tr/2tra/9ra2v/a2tr/2tra/9nZ2f/a2tr/2dnZ/9ra2v/a2tr/29rb/9ra2v/a2tv/29vb/9vb2//b2tv/29vb/9vb2//c3Nv/29vb/9vc3P/b29v/29vb/9vb2//b29v/29vc/9zc3P/b29v/3Nzc/9vb2//b3Nv/29vb/9zb3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nvc/9zc3P/c29v/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/d3N3/3N3c/93c3f/d3d3/3d3d/93d3f/d3d3/3d3e/93c3f/d3d3/3d3d/93d3f/d3d3/3t3d/93d3v/e3t7/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3d3c/93d3f/c3Nz/3Nzc/9zc3P/d3d3/3d3c/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3v/d3t7/3t7e/97e3v/e3t7/3d3d/93e3v/e3d3/3t7e/97e3v/e3t7/3t7e/97f3v/e3d7/3t7e/97e3v/e3t7/3t7e/97f3v/e397/39/f/97e3v/e3t7/3t7e/97e3v/e3t7/39/f/9/f3//f39//39/f/9/f3//f39//3+Dg/9/g4P/g4OD/4ODg/+Dg4P/f39//4ODf/9/g3//g4OD/4ODg/+Dg4P/g4OD/4eHg/97e3v/f3t7/397f/9/f3//f39//39/f/9/f3//g39//397f/9/f3//f39//39/f/9/f3//g4N//39/g/+Dg4P/g4N//4ODg/+Dg4P/g4OD/4ODg/+Hh4f/h4OD/4eHh/+Dg4P/g4OD/4ODg/+Hg4f/h4OD/4eHh/+Hh4f/h4eH/4ODg/+Dh4f/g4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4OD/4eHh/+Hh4f/h4eH/4eHh/+Hi4v/h4eH/4uLi/+Lh4f/i4uL/4eLh/+Li4v/i4uL/4uLi/+Li4v/j4+P/4uLi/+Li4v/i4uL/4uLi/+Li4//j4+P/4+Pj/+Pj4//h4eH/4eHh/+Hh4f/h4eH/4eHi/+Li4v/h4uH/4uLi/+Hh4f/h4eH/4eHh/+Hi4f/i4uL/4uLi/+Li4v/i4uL/4uLi/+Pj4v/i4uL/4+Li/+Pj4//j4+P/4+Pj/+Pj4//i4+P/4+Pj/+Pi4//j4+P/4+Pj/+Pk5P/j4+P/5OTk/+Pj4//j4+P/4+Pj/+Pj4//k4+T/5OTk/+Tj4//k5OT/4+Pj/+Tk5P/j4+P/4+Tk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Xl5f/l5eX/5eXl/+Tk5P/k5eX/5OXl/+Xl5f/l5eX/5eXl/+Xl5f/m5eb/4+Pj/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5f/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Xk5P/k5eX/5eXl/+Xk5P/l5eX/5eXl/+Xl5f/l5eX/5eXl/+bm5f/m5ub/5eXl/+Xl5f/l5eX/5ubl/+bm5v/m5ub/5ubm/+bm5v/l5eX/5uXm/+Xl5f/m5ub/5ubm/+bm5v/m5ub/5ufm/+bl5v/m5ub/5ubm/+bm5v/m5ub/5+bn/+fn5//m5+b/5ubn/+fn5//n5+b/5+fn/+fn5//n5+f/5+fn/+jo6P/n5+f/5+fn/+fn5//n5+f/5+fn/+jo6P/n5+j/6Ojo/+bm5v/m5ub/5ubm/+bn5//m5+b/5+fn/+fm5//n5+f/5ubm/+bn5//n5+f/5ubm/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jn6P/o6Oj/5+fo/+jo6P/o6Oj/6Ojo/+jo6P/o6On/6Ojo/+jo6P/o6Oj/6Ojo/+jp6P/o6Oj/6Ojo/+np6f/o6Oj/6Ojo/+jo6P/o6ej/6Ono/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/q6er/6urq/+rq6v/q6ur/6enp/+nq6f/p6en/6urq/+rq6v/q6ur/6urq/+rq6v/p6On/6Ojp/+jo6f/p6en/6enp/+np6f/p6en/6enq/+jp6f/p6en/6enp/+np6f/p6en/6unq/+nq6v/q6ur/6enp/+rq6v/q6ur/6urq/+rq6v/r6uv/6urq/+vq6//q6ur/6urq/+rq6v/q6ur/6+vr/+vr6//q6uv/6+vr/+rq6v/q6ur/6urq/+rr6v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//q6ur/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7ezs/+zs7P/t7O3/6+vr/+vr6//r6+v/6+vr/+vr6//r7Oz/6+zr/+zs7P/r6+v/6+vr/+vr6//r7Ov/6+vr/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/t7Oz/7e3t/+zt7P/t7e3/7Ozs/+3t7f/s7Oz/7ezt/+3t7f/t7e3/7e3t/+3t7f/s7Oz/7e3t/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e7u/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+7u7v/u7u7/7e3t/+7u7v/u7u7/7u7u/+7u7v/u7+7/7u7u/+/v7//u7u7/7u7u/+7u7v/u7u7/7u7v/+/v7//u7+7/7+/v/+3t7f/t7e3/7e3t/+7u7v/t7u7/7u7u/+7u7v/u7u7/7e3t/+3t7f/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7+7v/+7u7v/v7+7/7+/v/+/v7//v7+//7+/v/+/v7v/v7+//7+/u/+/v7//v7+//7+/v/+/v7//w8PD/7+/v/+/v7//v7+//7+/v/+/v7//v7/D/8PDv//Dw8P/v7+//7+/v/+/v7//v7/D/7+/v//Dw8P/w7+//8PDw//Dw8P/w8PD/8PDw//Dw8P/w8fD/8fDw//Hw8P/x8fH/8PDw//Hx8P/w8PD/8fDx//Hw8f/x8fH/8fHx//Hx8f/v7+//7/Dv/+/v7//v8O//8PDw//Dw8P/w8PD/8PDw//Dv7//w8PD/7/Dw//Dw8P/w8PD/8fHx//Dw8P/w8fD/8PHw//Dw8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Hx8f/y8vL/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Pz8//y8vL/8/Pz//Ly8v/y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//z8/P/8fHx//Ly8v/x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/8vLy//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/z8/P/9PT0//Pz8//z8/P/8/Pz//Pz8//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/19fX/9PT0//X19f/09PT/9PT0//T09P/09PT/9fX1//X19f/19fX/9fX1//Pz8//09PT/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9fX1//b29v/19fX/9fX1//X19f/19fX/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/39/f/9vb2//b29v/29vb/9vb2//b29v/39/f/9/f3//f39//19fX/9vb2//X19f/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//f39//39/f/9/f3//f39//29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//4+Pj/9/f3//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/5+fn/9/f3//f39//39/f/9/f3//j4+P/4+Pj/+Pj4//j4+P/39/f/+Pj4//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vr6//r6+v/6+vr/+vr6//r6+v/5+fn/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/7+/v/+vr6//r6+v/6+vr/+vr6//r6+v/7+/v/+/v7//v7+//6+vr/+vr6//r6+v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//8/Pz/+/v7//v7+//7+/v/+/v7//v7+//8/Pz//Pz8//z8/P/6+vr/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9/f3//f39//39/f/9/f3//f39//z8/P/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//39/f/8/Pz//Pz8//z8/M/8/Pz//Pz8//39/cz9/f2T/f39//39/f/9/f3//f39//39/f/9/f3//f39//39/fb9/f3//f398P39/Uv9/f0G/f39mf39/Rj9/f0A/f39AP39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//v7+//39/f/9/f3//f39//39/f/9/f3q/v7+5P7+/jP+/v7//v7+hP7+/tX+/v4J/v7+AP7+/gD+/v4A/v7+AP7+/iT+/v4A/v7+AP7+/gD+/v4A/v7+AP7+/gD+/v4A/v7+//39/cn9/f2H/f39Cf7+/hj+/v4A/v7+AP7+/gD+/v4A/f39AP7+/gD+/v4A/v7+AP7+/gD+/v4A/v7+AP7+/gD+/v4A/v7+AP7+/gD+/v4A/v7+AP7+/gD+/v4A/v7+AP7+/gD+/v4A/v7+AP7+/gD+/v4A////AP7+/gD///8= + + + + + diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/banner/body.cbmd b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/body.cbmd new file mode 100644 index 0000000..05869f7 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/body.cbmd differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/banner/dummy.bcwav b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/dummy.bcwav new file mode 100644 index 0000000..d579907 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/dummy.bcwav differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/banner/icon_24.ctpk b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/icon_24.ctpk new file mode 100644 index 0000000..cc54fe7 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/icon_24.ctpk @@ -0,0 +1 @@ +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMUUMMMMMMMMMMMMMUUUMUUUU]]]U]]]]eemMMMUUUU]UU]]]eee]]]eemm nemm v v,v,v-~]eeeemm ve n n v v,~-~M v,~,~-~-~NNoM~NNoop n,v,v-~-~NNo-~NNooppnopӦҦӮӮopӦӦӦԮӦԮ7778XYφMUUUU]]]U]]e]eem]eej]mkeK*!m2 vk+;-~LmNeeemm v v,vm v v,~,v-~-~N v!-~K moK*.uNoS: v-~!dM}K*!NnuopkNdl2oL2ktrҍk.Kl2kpO}nKtd CtӦԮ KB:kB.KB|77cXyӦ|k7m:!kXkY7XXYYzzzYzzכߛߛm:[kV:WJOSzzߛtxߛ,~-~M~NNooNooӦӦӮӮҦӮӮӮԮ77X77XXYyzԮ77X77XXYYz8YYyyzzߛzךߚߛXYyzzכߛߛzߛߛߜߜ \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/banner/icon_48.ctpk b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/icon_48.ctpk new file mode 100644 index 0000000..24fd5a8 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/body/banner/icon_48.ctpk @@ -0,0 +1,2 @@ +MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMUUMUUUUUUUMMMMMMMUMUUUUUUUUUUUUUU]UUU]]]]]UUUUUU]]U]]]]]]]]]]]]eee]eeeeeem]]]]]]ee]]eeeeemeeeeemm nmmm n n n v veeemmmm nmmm 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-~NNNNooo,~-~-~M~M~NNNMNNNNoooNooooppopNNooooopoppӦӦӦӮӦӦӮӮӮԮԮMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMUMMMMMMMMMMMMMMMUMMMUUUUUUUUUUUUUMMMMMUUUMUUUUUUUUUUUU]]]U]]]]]]]UUUUU]]]U]]]]]]e]]]eeeeeeeeeemmm]]]]]eee]eeeeeemeeemmm n nmmm n n v v,veemmmm n vm n n v v v v,v n v v,v,v,~,~-~ v,~,~-~-~M~MN n v v v v,v,v-~ v,~,~-~-~-~-~N-~-~-~NMNNoNNNONoop-~M~M~NNNNoNNNoooopOoopppnoooopopӦӦӮҦҦӦӮӮҦӦӦӮӮӮӦӦӮӮԮԮӮԮ777777777778X78XXXYYy׆MMMUUUUUUUUUUUU]UUU]]]]]]]]]]]]eUUU]]]]]]]]]]eee]]]eeeeeeeememmm]]]eeeeeeeeeemmTemmm +n n n+e+]2kkkk2Kemm ne! Lk n n v v2k2kkKT+;,~,~-~-~-~d-~u-~-~NNN v vm,v,v-~-~-~kk+;K*l\N e~-~MMNNNnumm *!kkkKK-~NNNN\OdNoooo/pkKkBp!k} *:P}kkoooppkS *NdӦl2kkktӮ CӦ:rӦ2Ӯkkk!kk|knSk0dk.Km:kӦӦӮԮӮԮt *kBkB777kckնS * 2kck 2!k7XXXBkBkXYYy7777XXX7XXXXYYyXYYyYyzzyzzzzߚzߛXYYyyzzzyzzzzߚߛߛzzߚߛߛߛߛ]eeeeeemeeemmm n nemm n n v v v n v v v v,v,v-~mmm n n v v v n v v v v,~,~-~ v,v,~-~-~-~-~M-~-~-~NNNNo v,v,v,~2kCk-~-~-~M ekN: eNm\NNooo *k *opd/uNNNNNoonoopopLCkpkkNd\oppt\ul *r ColӦԮq/dkk\p\SӦӮӦӦӮӮԮԮkkҕplkk0d2k: *kl2kk *0l0lk0lkttkukkk7m:7Dz|!󝵮Pl7u677777XkԝԝXϗXYXXXYYyyz[.S!k6,2Ykkkky׷zא[krtkzr|kr|kk:zzzߚzzzߚߚߛߛߛr|k:Uμzߛߛߛ,v,~,~-~-~M~M~N-~M~M~NNNNoNNNoOoopoooppNNNoooopoooppӦpӦӦӮӦӦӮӮӦӦӮӮԮӦӮӮԮԮԮӮԮ777777788X77777778XX7XXXXYYyXYYyyzzz788XXXXYXYYYYyyzYyyzzzzߛzzzߛߛߛYyzzzߚߚߛzߚߚߛߛߛߛߛߛpҦҦӦӦӦӮӮԮӦӮӮԮԮӦӦӮӮӮԮԮ67Ԯ77777877788XXX7777X777XXXXY8XXYYYyyYYyyyzzߚ7XXXXYYyXYyyyzzzyzzzzߚߛߛzߛߛߛߛߛyzzzzߛߛߛzߛߛߛߛ \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/body.rsf b/branches/1stNUP_7/CardSaveData/ToSD/body/body.rsf new file mode 100644 index 0000000..e0d0e65 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/body/body.rsf @@ -0,0 +1,30 @@ +# AvP[ṼftHgl +BasicInfo: + # vÕ^Cgw肵܂B + Title : $(TITLE) +# BackupMemoryType: 128KB + BackupMemoryType: None + Logo : Nintendo +# CompanyCode: "00" + ProductCode : "CTR-N-23AA" + +TitleInfo: +# Category: 0x0010 +# Category: SystemApplication + UniqueId: 0xf8030 + Version: 0 + +Rom: + HostRoot : romfiles +# SaveDataSize: 512K + +AccessControlInfo: + UseExtSaveData : false + + FileSystemAccess: + - CategoryFileSystemTool + - DirectSdmcWrite + +SystemControlInfo: + RemasterVersion: 1 + diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/romfiles/nnfont_RectDrawerShader.shbin b/branches/1stNUP_7/CardSaveData/ToSD/body/romfiles/nnfont_RectDrawerShader.shbin new file mode 100644 index 0000000..4290c2c Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/ToSD/body/romfiles/nnfont_RectDrawerShader.shbin differ diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/source/main.cpp b/branches/1stNUP_7/CardSaveData/ToSD/body/source/main.cpp new file mode 100644 index 0000000..32ccd77 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/body/source/main.cpp @@ -0,0 +1,618 @@ +/*---------------------------------------------------------------------------* + 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 +#include "../../../common/savefile/savefile.h" +#include "../../../common/savefile/savedata.h" +#include "../../../common/savefile/sdmcwo.h" +#include "../../../common/common.h" +#include "./screen/screen.h" + + +nn::fnd::ExpHeap appHeap; +uptr heapForGx; + +myResult errRes; + +SaveData savedata; +nn::os::LightEvent ejectEvnt(false); +nn::os::LightEvent insEvnt(false); +Sdmcwo exsave; +nn::os::LightEvent ejectEvntSd(false); +nn::os::LightEvent insEvntSd(false); + +//バックアップの状態 +bool Active,Formatted; +bool exActive; +tArcInfo arcInfo,arcInfo_ex;//アーカイブ情報 + +//Top画面エラー表示 +int tmerr; + +//結果 +typedef enum { + SUCCESS + ,ERROR + ,CANCEL + ,INSEXIT +}RetCode; + +//挿抜イベント時に設定 +typedef enum { + InEx_None + ,InEx_InsCard + ,InEx_EjcCard + ,InEx_InsSd + ,InEx_EjcSd +}tIsInsEject; + +tIsInsEject isInsEject; + +extern u8 scr_evnt; +void WaitUI(); +void PutError(ErcDev dev,int cd=0); +bool CheckInsExit(); + + +//終了処理 +void endfunc() +{ + + nn::fs::UnregisterCardEjectedEvent(); + nn::fs::UnregisterCardInsertedEvent(); + ejectEvnt.Finalize(); + insEvnt.Finalize(); + nn::fs::UnregisterSdmcEjectedEvent(); + nn::fs::UnregisterSdmcInsertedEvent(); + ejectEvntSd.Finalize(); + insEvntSd.Finalize(); + + savedata.Finalize(); + exsave.Finalize(); + + ScrFinalize(); + +} + +//エラー停止 +void failstop() +{ + NN_LOG("fail %d,stop\n",errRes); + finish(); +} + + + +wchar_t file_pathw[MAX_PATH_LENGTH]; +wchar_t file_pathw2[MAX_PATH_LENGTH]; +char file_path[MAX_PATH_LENGTH]; +//カゲマイ報告の速度実測でFSで4バイトアライン有利(SDK 0.14.23 時点) +char fileBuffer[512] NN_ATTRIBUTE_ALIGN(4);//検証 512単位 +char fileBuffer_ex[512] NN_ATTRIBUTE_ALIGN(4); +#define FILEBUFF_SIZE sizeof(fileBuffer) + +//エラー表示 +char sts[64]; +void PutError(ErcDev dev,int cd) +{ + nn::Result res; + switch (dev) + { + case ERC_DEV_CARD: res = savedata.LastNnResult;break; + case ERC_DEV_OUT: res = exsave.LastNnResult;break; + } + GetErrorStr(dev,res,cd,sts); + scr_Status(sts,COLOR_RED); +} + +//デバグ用ウエイト +void waitSec(int sec) +{ + nn::os::Tick tm,tn; + tm = nn::os::Tick::GetSystemCurrent(); + while(1) + { + tn = nn::os::Tick::GetSystemCurrent()-tm; + if(tn.ToTimeSpan().GetSeconds() > sec)break; + } +} + + +char mes[128]; +//保存先のディレクトリ削除 +bool TryDeleteDir() +{ + if(exsave.Delete())return true; + //フォルダ削除に失敗したら手削除 + strcpy(mes,"Illegal folder [ "); + strcat(mes,exsave.DirName);//フォルダ名 + strcat(mes," ]"); + //scr_Status(sts,COLOR_RED); + scr_MessOnCount(mes); + return false; +} + +//情報ファイルの占有サイズ計算 +//vnfは発生見込み低い上、面倒なので作成時エラー任せ +size_t GetSysSpace(size_t cl) +{ + size_t sz; + int sn; + sn = sizeof(FormatParameters) / cl; + if ((sizeof(FormatParameters) % cl) > 0)sn++; + sz = sn*cl; + sn = sizeof(AdditionalInfo) / cl; + if ((sizeof(AdditionalInfo) % cl) > 0)sn++; + sz += sn*cl; + return sz; +} + +//---------------------------------------------------------------------- CARD to SD +RetCode Card2Sd() +{ + myResult res; + int ct=0,msize,rsize; + s64 total=0,free_size; + + scr_BackupYesNo();//実行確認 + WaitUI();//入力待ち + if(isInsEject != InEx_None )return INSEXIT;//挿抜による中断 + if (scr_evnt != EVNT_YES)return CANCEL;//キャンセル + scr_Backup();//画面表示 + + + //保存先ディレクトリ作成 + //ディレクトリ作成時にクラスタサイズ、空き容量を取得 + scr_Status("Create Dir to SD",COLOR_YELLO); + if (exsave.Create() == false) + { + PutError(ERC_DEV_OUT); + return ERROR; + } + + //セーブデータのマウント + scr_Status("Mount SaveData",COLOR_YELLO); + res = savedata.Mount(); + if(res != RESULT_OK){ + exsave.Unmount(); + TryDeleteDir(); + PutError(ERC_DEV_CARD); + return ERROR; + } + + //ディレクトリ情報 + scr_Status("Get Directry",COLOR_YELLO); + if(savedata.GetInfo(&arcInfo,exsave.ClasterSize)==false) + { + savedata.Unmount(); + exsave.Unmount(); + PutError(ERC_DEV_CARD); + TryDeleteDir(); + return ERROR; + } + strcpy(arcInfo.Pcode,savedata.PrdCode); + + if ((arcInfo.total + GetSysSpace(exsave.ClasterSize)) > exsave.FreeSize) + {//容量不足 + savedata.Unmount(); + exsave.Unmount(); + PutError(ERC_DEV_OUT,ERC_WRITE_NS); + TryDeleteDir(); + return ERROR; + } + + //カウント異常 + if (arcInfo.FileCount > arcInfo.FileEntry){ + savedata.Unmount(); + exsave.Unmount(); + PutError(ERC_DEV_OTHER,ERC_EXEC); + TryDeleteDir(); + return ERROR; + } + + if (arcInfo.FileCount == 0)//ファイルが無い + { + scr_Status("no files",COLOR_YELLO); + savedata.Unmount(); + exsave.Unmount(); + TryDeleteDir(); + return SUCCESS;//何もしない + }else{ + //ファイルコピー + scr_Status("file copying",COLOR_SKY); + savedata.ResetPath(); + s64 fsize; + res = RESULT_OK; + while(res==RESULT_OK){ + if(CheckInsExit())break;//挿抜による中断 + res = savedata.GetPath(file_pathw);//パス取得 + if (res != RESULT_OK) + { + if (res == RESULT_DIR_LEVEL_OVER){ + PutError(ERC_DEV_CARD,ERC_DIRDEPTH); + break; + } + if (res == RESULT_PATH_LENGTH_OVER){ + PutError(ERC_DEV_CARD,ERC_PATH); + break; + } + res = RESULT_FAIL_OPEN; + break; + } + if (file_pathw[0] == 0)break;//ルートなら終了 + if (ct>=arcInfo.FileCount) + { + res = RESULT_FAIL; + break; + } + + if(CheckInsExit())break;//挿抜による中断 + scr_CountPerMax(ct,arcInfo.FileCount); + if (savedata.Open(file_pathw)==false) + { + res = RESULT_FAIL_OPEN; + break; + } + + fsize = savedata.FileSize; + total += fsize; + if(CheckInsExit())break;//挿抜による中断 + //SDで支障あるパス名の場合は別ファイルに格納する + exsave.GetRootPath(file_pathw2);//格納先ルート取得 + ChainPath(file_pathw2,file_pathw);//実パス名に変換 + if (CheckPath(file_pathw2)==false)//パス名チェック + { + if (exsave.OpenVnfW(file_pathw,fsize)==false)//退避ファイル + { + res = RESULT_FAIL_OPENW; + break; + } + }else{ + bool mkdir; + int rev; + while(1){ + if (exsave.OpenC(file_pathw,fsize,&mkdir)==false) + { + if(mkdir)//ディレクトリ作成のみ + {//深いと作成に時間かかるので画面に変化つける + rev++; + if (rev & 1)scr_MessOnCount2("Create Directry -"); + else scr_MessOnCount2("Create Directry |"); + }else{ + NN_LOG("%d\n",exsave.LastNnResult.GetDescription()); + if(nn::fs::ResultInvalidArgument::Includes(exsave.LastNnResult)) + {//パス名エラー + if (exsave.OpenVnfW(file_pathw,fsize)==false)//退避ファイル + { + res = RESULT_FAIL_OPENW; + } + break; + }else{ + res = RESULT_FAIL_OPENW; + break; + } + } + }else break; + } + if (res != RESULT_OK)break; + } + + msize=fsize; + while(fsize) + { + if(msize > FILEBUFF_SIZE * 2){//サイズが大きい場合にゲージ表示 + scr_CountPerMax2(msize-fsize,msize,0); + } + if (fsize>FILEBUFF_SIZE) + { + rsize = FILEBUFF_SIZE; + fsize -= FILEBUFF_SIZE; + }else{ + rsize = fsize; + fsize = 0; + } + if(CheckInsExit())break;//挿抜による中断 + if(savedata.Read(fileBuffer,rsize) != rsize )//リード + { + //中身のデータが作成サイズに満たない場合に検証エラーとなる対策 + //読めないブロックは置き換える + //検証は512単位でされるので読めてるとこまで置き換えないよう + //リードサイズは512にしておく + if(nn::fs::ResultVerificationFailed::Includes(savedata.LastNnResult)) + { + for (int i = 0; i < rsize; i++) + { + fileBuffer[i] = 0;//0埋め + } + }else{ + res = RESULT_FAIL_READ; + break; + } + } + if(CheckInsExit())break;//挿抜による中断 + if(exsave.Write(fileBuffer,rsize) != rsize )//ライト + { + res = RESULT_FAIL_WRITE; + if(exsave.LastNnResult.IsSuccess()){//容量不足でオープンすると書けるとこまで書いてエラーとならない + if (exsave.GetFreeSize(&free_size)){ + if (free_size == 0 ) res = RESULT_DEVICE_FULL;//空き無し + } + } + break; + } + } + savedata.Close(); + exsave.CloseW(); + if(isInsEject != InEx_None )break;//挿抜による中断 + ct++; + } + savedata.Close(); + exsave.CloseW(); + } + savedata.Unmount(); + exsave.Unmount(); + +//結果 + scr_CountPerMax(ct,arcInfo.FileCount); + scr_CountPerMax2(0,0,-1); + if(isInsEject != InEx_None ) + {//挿抜による中断 + if(TryDeleteDir())return INSEXIT; + return ERROR;//デリート失敗表示 + }else{ + if (res == RESULT_OK) + { + if (ct == arcInfo.FileCount)//ファイル数一致? + { + if(exsave.WriteSys(&arcInfo))//フォーマット情報 + { + //成功 + strcpy(sts,"output folder [ "); + strcat(sts,exsave.DirName);//保存先 + strcat(sts," ]"); + scr_Status(sts,COLOR_WHITE); + + scr_CountPerMax(ct,arcInfo.FileCount);//ファイル数 + scr_CountPerMax2(0,0,total);//総サイズ + return SUCCESS; + } + res = RESULT_FAIL_WRITE; + if(exsave.LastNnResult.IsSuccess()){//容量不足でオープンすると書けるとこまで書いてエラーとならない + if (exsave.GetFreeSize(&free_size)){ + if (free_size == 0 ) res = RESULT_DEVICE_FULL;//空き無し + } + } + }else{ + NN_LOG("file count error\n"); + res = RESULT_FAIL; + } + } + //失敗 + if (res == RESULT_DEVICE_FULL)PutError(ERC_DEV_OUT,ERC_WRITE_NS); + else if ((res == RESULT_FAIL_WRITE) || (res== RESULT_FAIL_OPENW)) PutError(ERC_DEV_OUT); + else if ((res == RESULT_FAIL_READ) || (res== RESULT_FAIL_OPEN)) PutError(ERC_DEV_CARD); + else if (res == RESULT_FAIL_VERIFI) PutError(ERC_DEV_OUT,ERC_VERIFI); + else PutError(ERC_DEV_OTHER); + TryDeleteDir();//ディレクトリごと削除 + } + return ERROR; + +} + + +//--------------------------------------------------------------- セーブデータの情報取得 +//呼ぶ前に tmerr のクリアを忘れない事 +void CheckSaveDataState() +{ + myResult myres; + + Formatted = false; + Active = false; + + if (savedata.GetPrdCode()) + { + Active = true;//カード + myres = savedata.IsExist();//セーブマウント + //NN_LOG("%d",savedata.LastNnResult.GetDescription()); + if (myres == RESULT_OK) + { + Formatted=true; + }else{ + tmerr |= SDATA_ERRPUT_MEDIA; + } + } + scr_PrdCode(savedata.PrdCode); +} + +//エクスポート先の状態確認 +void CheckExSaveState() +{ + exActive = nn::fs::IsSdmcInserted() && nn::fs::IsSdmcWritable(); +} + +//------------------------------------------------------------ 挿抜チェック +bool CheckInsExit() +{ + + if (ejectEvnt.TryWait()){ + //CARD抜け + CheckSaveDataState(); + isInsEject = InEx_EjcCard; + return true; + } + if (insEvnt.TryWait()){ + //CARD挿入 + CheckSaveDataState(); + isInsEject = InEx_InsCard; + return true; + } + if (ejectEvntSd.TryWait()){ + //SD抜け + CheckExSaveState(); + isInsEject = InEx_EjcSd; + return true; + } + if (insEvntSd.TryWait()){ + //SD挿入 + CheckExSaveState(); + isInsEject = InEx_InsSd; + return true; + } + return false; +} + + +//---------------------------------------------------------------- 入力待ち +void WaitUI() +{ + tmerr = 0; + scr_Draw();//画面更新 + scr_evnt = EVNT_NONE; + while(scr_evnt == EVNT_NONE) + { + nn::os::Thread::Yield();//スレッド実行 + //scr_GetEvnt();//入力イベント + + CheckSysBreak();//中断処理 + + //挿抜を検知したら中断して抜ける + //トップ以外ではトップメニューへ戻るようする + if (CheckInsExit())return; + } + ScrClr();//画面消去 + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(500));//チャタ対策 +} + + +//---------------------- main loop -------------------------- +void nnMain() +{ + + RetCode retc; + isInsEject = InEx_None; + + //NN_LOG("Start\n"); + nn::os::Initialize(); + nn::fs::Initialize(); + + //DEA-SUPにて推奨のフリーズ暫定対策:無線デーモンを停止 (2011.3.1 現在) + //スリープ中は止まらないので、本体スイッチ切るのが確実 + //SDK2.2以降で対策不要となったが、点滅が鬱陶しいので残しとく + nn::ndm::Initialize(); + nn::ndm::SuspendScheduler(); + + //中断処理の準備 + InitSysBreak((uptr)endfunc); + // グラフィックスライブラリの初期化は、以降で行わなければならない + // 他、アプリケーションの初期化処理 + + nn::applet::DisableSleep();//スリープ非対応 + + //Heap + appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), + nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + const u32 GxHeapSize = 0x800000; + heapForGx = reinterpret_cast(appHeap.Allocate(GxHeapSize)); + //画面初期化 + if (ScrInitialize(heapForGx,GxHeapSize) == false)failstop(); + ejectEvnt.ClearSignal(); + insEvnt.ClearSignal(); + nn::fs::RegisterCardEjectedEvent(&ejectEvnt); + nn::fs::RegisterCardInsertedEvent(&insEvnt); + ejectEvntSd.ClearSignal(); + insEvntSd.ClearSignal(); + nn::fs::RegisterSdmcEjectedEvent(&ejectEvntSd); + nn::fs::RegisterSdmcInsertedEvent(&insEvntSd); + + // スリープ要求に対する返答を有効にする + // また、蓋の状態チェックを行い蓋が閉じられているならスリープ要求が発生する + //nn::applet::EnableSleep(true); + + extern u8 scr_evnt; + while(1) + { + tmerr = 0; + CheckSaveDataState(); //セーブデータの状態取得 + CheckExSaveState(); //SD挿入状態 + scr_TopMenu(Formatted,Active,exActive,tmerr); + + WaitUI();//入力待ち + if (isInsEject != InEx_None){ + ScrClr();//画面消去 + isInsEject= InEx_None; + }else + switch(scr_evnt) + { + case EVNT_SEL_READ://リード + NN_LOG("select read\n"); + retc = Card2Sd(); + switch (retc) + { + case SUCCESS: + //CheckExSaveState(); //状態の更新 + scr_ResultQuit("Success",COLOR_GREEN);//成功とQuitボタン + break; + case INSEXIT: + //scr_InsExitQuit();//挿抜検知表示 & Quit + ScrClr();//画面消去 + scr_Backup(); + if (isInsEject == InEx_EjcCard)PutError(ERC_DEV_CARD,ERC_DEVICE); + else if (isInsEject == InEx_EjcSd)PutError(ERC_DEV_OUT,ERC_DEVICE); + else PutError(ERC_DEV_OTHER); + scr_ResultQuit("Break",COLOR_RED);//エラーとQuitボタン + break; + case CANCEL:break; + default://errors + 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_PUSH_LEFT_X:// ------------------------------------- LEFT + X + //バックアップ削除 + scr_DelConf();//実行確認 + WaitUI(); + if (scr_evnt != EVNT_YES)break; + exsave.DeleteAll();//全削除 + //CheckExSaveState(); //状態更新 + break; + + } + }//while() + +} + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ + diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/source/screen/screen.cpp b/branches/1stNUP_7/CardSaveData/ToSD/body/source/screen/screen.cpp new file mode 100644 index 0000000..3d277d3 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/body/source/screen/screen.cpp @@ -0,0 +1,765 @@ +#include +#include +#include "screen.h" +#include "../../../../common/my_defs.h" +#include "../../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 +}; + + +//ʏAR|[lgfBZ[u +void ScrClr() +{ + gui.ButtonMask(0); + gui.DisableAll(); + gui.Draw(); +} + +nn::os::Tick holdTck; +u32 holdVal; +//---------------------------------CxgR[obN +//----------------PAD{^ +void pushButton(u32 sts) +{ + //NN_LOG("button > %4x\n",button); + u32 trg = sts & 0x0ffff; + u32 hld = sts >> 16; +/* + if (holdVal)//P\ + { + if (nn::fnd::TimeSpan::FromMilliSeconds(100) > (nn::os::Tick::GetSystemCurrent()-holdTck)){ + holdVal |= trg; + if (holdVal == nn::hid::BUTTON_LEFT | holdVal & nn::hid::BUTTON_X ){ + holdVal = 0; + scr_evnt = EVNT_PUSH_LEFT_X; + } + }else holdVal = 0; + }else if( (holdVal = trg & (nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X ))>0) + {//莞Ԃǂ̃{^ێ + holdTck = nn::os::Tick::GetSystemCurrent(); + } +*/ + + if( holdVal )// + { + if (hld != holdVal) + { + holdVal = 0; + }else + if (nn::fnd::TimeSpan::FromMilliSeconds(4000) < (nn::os::Tick::GetSystemCurrent()-holdTck)) + { + holdVal = 0; + scr_evnt = EVNT_PUSH_LEFT_X; + } + }else if (hld == ( nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X )) + { + holdVal = hld; + holdTck = nn::os::Tick::GetSystemCurrent(); + } + + + else if (trg & nn::hid::BUTTON_B)scr_evnt = EVNT_PUSH_B; +} + +//-----------------pl^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 + +// -------------------------------------------------- R|[lg݌v +// + +//Top Menu +const tPanel panel_Read = {(uptr)touchRead,"Export",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}; + +// +//foOp +//G[\ +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}; + +//smF +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}; + +//gbvj[ +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 -> SD",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}; + +//O\ +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}; + + +//ʏ펞 +//^Cg +#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) +//TOPj[ +//\̓OƔr +#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 = {"[Export] Write to SD",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 = {"SD 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}; + +//폜mF +//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 data on SD",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; + holdVal = 0; + holdTck = nn::fnd::TimeSpan(0); + + if (gui.Initialize(heap,size,&stopEvnt)==false)return false; + + gui.ButtonCallback((uptr)pushButton); + //R|[lgo^ + 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(); +} + + +//gbvj[ +//:J[h +void scr_TopMenuDbg(bool formatted,bool insertted)//fobOp +{ + NN_UNUSED_VAR(insertted); + + scr_evnt = EVNT_NONE; + gui.ButtonMask(nn::hid::BUTTON_A | nn::hid::BUTTON_R | nn::hid::BUTTON_L); + + if (formatted) + {//[h”\ + gui.MessSet(&mess_topmenu_help_read); + gui.PanelEffective(PANEL_READ); + }else{//[hs + gui.MessSet(&mess_topmenu_help_notread); + gui.PanelEffective(PANEL_READ,false); + } +// if (insertted) +// {//݉ +// gui.MessSet(&mess_topmenu_help_write); +// gui.PanelEffective(PANEL_WRITE); +// }else{//ݕs +// 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(); +} + +//ʏ펞 + +//v_NgR[h +//:J[hAgZ[uɋL^ꂽ +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); +} +*/ + +//폜̎smF +void scr_DelConf() +{ + scr_evnt = EVNT_NONE; + gui.PanelEffective(PANEL_DELCONF); + YesNo(); +} + + +//Top menu +//:foCX +//arg : v_NgR[hv +void scr_TopMenu(bool formatted,bool inserted,bool sdins,int err) +{ + + int i; + scr_evnt = EVNT_NONE; + + u32 mask = 0; + mask |= (nn::hid::BUTTON_LEFT | nn::hid::BUTTON_X);//LEFT+X = Delete L + + gui.MessStr(MESSAGE_TITLE," < CTR Card Savedata Exporter >"); + + gui.MessEffective(MESSAGE_MENU_ERROR,false,false); + gui.MessEffective(MESSAGE_MENU_CAUTION,false,false); + gui.MessEffective(MESSAGE_MENU_OPERATE,false,false); + + if (formatted && sdins) + {//obNAbv”\ + gui.MessEffective(MESSAGE_MENU_OPERATE); + gui.PanelEffective(PANEL_READ); + }else + { + gui.PanelEffective(PANEL_READ,false,false); + + if (inserted == false) + { + strcpy(scr_err,"Please Insert Card"); + gui.MessEffective(MESSAGE_MENU_CAUTION); + + }else + if (sdins == false) + { + strcpy(scr_err,"SD protected or not Insert"); + gui.MessEffective(MESSAGE_MENU_CAUTION); + + }else{ + if (err & SDATA_ERRPUT_MEDIA) i = ERC_MEDIA + ERC_DEV_CARD;//obNAbvȂ + else i = ERC_DEV_OTHER;//s + 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(); +} + +//fobOpA{^҂ +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Ɠplg + 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(); +} + +// JEg/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(); +} + +//Q[Wtotal +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_MessOnCount(char *str) +{ +// gui.MessCol(MESSAGE_COUNT2,COLOR_YELLO); + gui.MessStr(MESSAGE_COUNT,str); + gui.MessEffective(MESSAGE_COUNT); + gui.Draw(); +} + + + +//smF +void scr_ConfirmDbg(char *str) +{ + scr_evnt = EVNT_NONE; + gui.MessStr(MESSAGE_CONFIRM_TITLE,str); + gui.PanelEffective(PANEL_CONFIRM); + YesNo(); +} + + +//G[\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(); +} + + +//fobOO +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/1stNUP_7/CardSaveData/ToSD/body/source/screen/screen.h b/branches/1stNUP_7/CardSaveData/ToSD/body/source/screen/screen.h new file mode 100644 index 0000000..1e8f7dc --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/body/source/screen/screen.h @@ -0,0 +1,116 @@ +#ifndef SCREEN_H_ +#define SCREEN_H_ + +#include +#include +#include "../../../../common/gui/gui.h" + +//plID +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)){ //I[o[[h΍ + 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; + } +}; + + +//Topj[ł̃G[\p̃tO +//bit`FbN +#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 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_MessOnCount(char *str); +void scr_Draw(); +void scr_GetEvnt(); + +#endif + diff --git a/branches/1stNUP_7/CardSaveData/ToSD/body/ver.h b/branches/1stNUP_7/CardSaveData/ToSD/body/ver.h new file mode 100644 index 0000000..75c8563 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/body/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 0.01 + + +#endif diff --git a/branches/1stNUP_7/CardSaveData/ToSD/release.txt b/branches/1stNUP_7/CardSaveData/ToSD/release.txt new file mode 100644 index 0000000..dd5a30b --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/ToSD/release.txt @@ -0,0 +1,36 @@ +//////////////////////////////////////////////////////////////// +J[h̃Z[uf[^SDփ_CNgo + +{c[ uNintendo for 3DSvѐpJ[hpł +s͈ȊO̎gp͋ւ܂ + +oe +CTR_SDK\tools\TargetTools\CTR-TS\Release\NandFiler +ŊJJ[h̃TuJ[hփCgł܂ +eʂ^Cg̃`FbN͂܂̂Ŏgp҂ŒӉ +//////////////////////////////////////////////////////////////// + +NANDC|[gĂAAvl̎菇ŋN +{̏̃o[W 2.0.0 (1stNup)ȍ~̃t@[œ삷 + +(C|[g菇) +EfobK̓C^"cci"J[hɏ +E{̃VA܂ރXgƏSD +EHomej[J[hNj[Inports +Ej[ImportI +EId{^Z ->"d؂"^b` + + +(NAND폜) +N܂ł̓C|[gƓl +Ej[Deletes +I̓j[ɖ߂܂ + + +c[{̂̑͑}jAQ + +F +2011.6.8 ver0.01(}X^o[W1.0.0) + + +[Histry] diff --git a/branches/1stNUP_7/CardSaveData/common/common.cpp b/branches/1stNUP_7/CardSaveData/common/common.cpp new file mode 100644 index 0000000..c9f509a --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/common.cpp @@ -0,0 +1,226 @@ +#include +#include +#include "common.h" +#include "sleep.h" +#include "demo.h" +#include +#include +#include + + +extern demo::RenderSystemDrawing s_RenderSystem; +extern nn::fnd::ExpHeap appHeap; +extern uptr heapForGx; + + +//G[\p񐶐 +void GetErrorStr(ErcDev dev,nn::Result res,int cd,char* s) +{ + int desc=0,code; + + if ((cd ==0 ) && (dev != ERC_DEV_OTHER)) + { + desc = res.GetDescription(); + if (desc < 100 ) code = ERC_UNKNOWN;//L[ .. 肦Ȃ + else if (desc < 180 ) code = ERC_READ;//t@C‚Ȃs + else if (desc < 200 ) code = ERC_WRITE_OW;//t@C .. 폜s? + 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;//ANZXG[ + else if (desc < 390 ) code = ERC_FORMAT;//tH[}bgG[ + else if (desc < 400 ) code = ERC_SDK_VERIFI;// + else if (desc < 580 ) code = ERC_ROM;//ROMG[ + else if (desc < 590 ) code = ERC_RETRY;//gCv + else if (desc < 600 ) code = ERC_UNKNOWN;//CCI,CXIs .. 肦Ȃ + else if (desc < 900 ) code = ERC_EXEC;//sG[A\tgoO + else code = ERC_FATAL;//{̂ɖ̉”\ + }else code = cd; + //if (desc>=600){ + // sprintf(s,"ERROR %d, desc %d",dev+code,desc); + //}else{ + sprintf(s,"ERROR %d",dev+code); + // } +} + + + +bool prohibitHome = false;// HOME {^֎~ +// t@CVXeƑJڂX[vƂ̔rɗp +//nn::os::CriticalSection g_SleepCS; +// HOME {^Jڂƃt@CVXe̔rɗpi蓮Zbgj +nn::os::LightEvent g_TransitionEvent; +// X[vƃt@CVXe̔rɗpi蓮Zbgj +nn::os::LightEvent g_AwakeEvent; + +void restoreGraphicSetting() +{ + // GPU WX^ݒ̕A + // AL DMPGL API gpĐݒ肵Ԃ̕ + // WX^ݒR}h͑SčĔsׂ + 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); + + // N͏ Signal ԂɂĂ + g_AwakeEvent.Signal(); + g_TransitionEvent.Signal(); + + // AvbgCuɊւ@\Lɂ + nn::applet::Enable(false); + // gx, snd, dsp eCu Initialize ֐ applet::Enable() ̌ɌĂ΂Ȃ΂ȂȂ + // ɁAgx ̏ł nngxInitialize ֐́AEnable() ̏Ǐɍsׂ + + // S\ɓd{^ꂽȂǁAɏIĂꍇAŃAvI + if ( nn::applet::IsExpectedToCloseApplication() ) + { + SleepHandler::Finalize(); + nn::Result result = nn::applet::PrepareToCloseApplication(); + NN_UTIL_PANIC_IF_FAILED( result ); + nn::applet::CloseApplication(); + } + // OtBbNXCȕ́Aȍ~ōsȂ΂ȂȂ + // AAvP[V̏ + +} + + +//I +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(){ + // X[v̋ŃA1t[̕`抮҂Ă LCD Lɂ + if ( SleepHandler::s_IsAfterWakeUp ) { + nn::gx::StartLcdDisplay(); + SleepHandler::s_IsAfterWakeUp = false; + } + + // GPU ̃WX^ݒ̐lꍇA + // eJځAX[vvւ̕ԓ͕`Iɍsׂ + + // {̃X[v + if ( SleepHandler::IsSleepRequested() ) + { + SleepHandler::SleepSystem(); + } + + // Iv`FbN + if ( nn::applet::IsExpectedToCloseApplication() ) + { + finish(); + } + + // AvP[V̑Jڏs + + // HOME{^iOtBbNXCuς݂łȂ΂ȂȂj + if ( nn::applet::IsExpectedToProcessHomeButton() ) + { + if (prohibitHome){ // HOME {^֎~ + nn::applet::ClearHomeButtonState();//HOME {^tO폜 + }else + { + g_TransitionEvent.ClearSignal(); + + // t@CVXe͑Jڂ҂ + //if ( g_SleepCS.TryEnter() ) + { + // X[vv 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 j[̒fobe[s̗vɂ + // AvIƔfꂽꍇAAṽC[v𔲂ďI + if ( nn::applet::IsExpectedToCloseApplication() ) + { + // `挠͓nĂȂ + finish(); + } + + nn::applet::EnableSleep(true); + + // OtBbN̐ݒ߂ + restoreGraphicSetting(); + } + } + + } + + + // d{^iOtBbNXCuς݂łȂ΂ȂȂj + if ( nn::applet::IsExpectedToProcessPowerButton() ) + { + g_TransitionEvent.ClearSignal(); + + // t@CVXe͑Jڂ҂ + //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(); + + // AvIƔfꂽꍇAAṽC[v𔲂ďI + if ( nn::applet::IsExpectedToCloseApplication() ) + { + // `挠͓nĂȂ + finish(); + } + + nn::applet::EnableSleep(true); + + // OtBbN̐ݒ߂ + restoreGraphicSetting(); + } + + } + + + + +} diff --git a/branches/1stNUP_7/CardSaveData/common/common.h b/branches/1stNUP_7/CardSaveData/common/common.h new file mode 100644 index 0000000..b2a8566 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/common.h @@ -0,0 +1,14 @@ +#ifndef COMMON_H_ +#define COMMON_H_ + +#include "my_defs.h" + +typedef void (*FUNCP)(); + +void finish(); +void CheckSysBreak(); +void InitSysBreak(uptr adrs); +void GetErrorStr(ErcDev dev,nn::Result res,int cd,char* s); + + +#endif diff --git a/branches/1stNUP_7/CardSaveData/common/gui/gui.cpp b/branches/1stNUP_7/CardSaveData/common/gui/gui.cpp new file mode 100644 index 0000000..c39d534 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/gui/gui.cpp @@ -0,0 +1,654 @@ +/*---------------------------------------------------------------------------* + 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配列数以下であること + u32 parent;//親コンポーネントID +public: + cmMemo(); + bool setline(char *p,u16 ln); + char* line(u16 ln); + void clr(){ + for (int i=0;i 80 ) + { + if (x < 160) return -10; + else if (x <230) return -30; + else return -50; + } + return 0; +} + +//PANEL上の座標かチェック +bool onPanel(u16 x,u16 y,cmPanel *p) +{ + int px = pos2tpx(p->pos.x); + int pw = pos2tpx(p->size.x); + int py = 20; + + if (x <= (p->pos.x + px))return false; + if (x >= (p->pos.x + p->size.x + pw))return false; + if (y <= p->pos.y + py )return false; + if (y >= (p->pos.y + p->size.y))return false; + return true; +} + + +#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) | ((padStatus.hold & s_Button.mask) << 16); + 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) + { + NN_LOG("x =%d , y=%d\n",tpStatus.x,tpStatus.y); + 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 割り込みが同時に発生すると + // 画面が暗転したまま止まる不具合を回避するために 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; + u16 id; + u16 scr;//0:up,else down screen +}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/1stNUP_7/CardSaveData/common/my_defs.h b/branches/1stNUP_7/CardSaveData/common/my_defs.h new file mode 100644 index 0000000..4ea84a0 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/my_defs.h @@ -0,0 +1,82 @@ +/*---------------------------------------------------------------------------* + 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_ + + +//エラー表示コード +enum { +ERC_UNKNOWN = 0, //不明 +ERC_DEVICE, //デバイスが見つからない(カード抜け) +ERC_PRODCODE,//プロダクトコード不一致 +ERC_VERIFI,//ベリファイエラー +ERC_PATH,//パスが長すぎ +ERC_DIRDEPTH,//ディレクトリ深すぎ +ERC_MEDIA, //メディアが見つからない(サブ基盤外れなど) +//ERC_PULLOUT,//抜け検出 +ERC_READ = 10, //ファイルが見つからない +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_FAIL_VERIFI, + 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_DEVICE_FULL, + RESULT_MAX +}myResult; + + + +#endif diff --git a/branches/1stNUP_7/CardSaveData/common/null_banner/banner_null.bsf b/branches/1stNUP_7/CardSaveData/common/null_banner/banner_null.bsf new file mode 100644 index 0000000..e52a641 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/common/null_banner/banner_null.bsf differ diff --git a/branches/1stNUP_7/CardSaveData/common/null_banner/model.cbmd b/branches/1stNUP_7/CardSaveData/common/null_banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/common/null_banner/model.cbmd differ diff --git a/branches/1stNUP_7/CardSaveData/common/null_banner/sound.cbsd b/branches/1stNUP_7/CardSaveData/common/null_banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/CardSaveData/common/null_banner/sound.cbsd differ diff --git a/branches/1stNUP_7/CardSaveData/common/null_banner/unknown24x24.ctpk b/branches/1stNUP_7/CardSaveData/common/null_banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/null_banner/unknown24x24.ctpk @@ -0,0 +1 @@ +888yyYyYyyyYyyYyyyyYyYy8 \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/common/null_banner/unknown48x48.ctpk b/branches/1stNUP_7/CardSaveData/common/null_banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/null_banner/unknown48x48.ctpk @@ -0,0 +1 @@ +Y8888ƺ8888YYyyYYޚ޺yY8YyYYޚyY8ޚ8 \ No newline at end of file diff --git a/branches/1stNUP_7/CardSaveData/common/savefile/exsave.cpp b/branches/1stNUP_7/CardSaveData/common/savefile/exsave.cpp new file mode 100644 index 0000000..6cf769a --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/exsave.cpp @@ -0,0 +1,299 @@ +#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";//暫定 +wchar_t expath_w[PATHLENGTH_MAX];//パス名 +wchar_t expathu_w[100][PATHLENGTH_MAX];//上層パス名 +wchar_t expathw_w[PATHLENGTH_MAX];//パス名ワーク +static nn::fs::DirectoryEntry exdcEntry[MAX_LEVEL]; +static nn::fs::Directory exdc[MAX_LEVEL]; + + +//拡張セーブデータ +//存在確認 +bool ExSave::IsExist() +{ + LastNnResult = nn::fs::MountExtSaveData(exsaveName,OWN_UID); + nn::fs::Unmount(exsaveName); + return LastNnResult.IsSuccess(); +} + +//パス検索位置のリセット +void ExSave::ResetPath() +{ + s_lv=0; + s_serch = false; + wcscpy(expath_w,exsaveRoot_w); + //wcscpy(expathu_w,expath_w); +} + + +myResult ExSave::GetPath(wchar_t *path) +{ + int n; + while(1){ + if (s_serch==false){ + LastNnResult = exdc[s_lv].TryInitialize(expath_w);//Open + if (LastNnResult.IsFailure()){ + return RESULT_FAIL; + } + } + while(1){ + n = (exdc[s_lv].Read(&exdcEntry[s_lv],1)); + if ( n==0 )//終端 + { + exdc[s_lv].Finalize(); + if (s_lv == 0){path[0]=0;return RESULT_OK;}// ---- rootなら終了 + s_lv--;//上の層に戻る + wcscpy(expath_w,expathu_w[s_lv]);//パス戻す + }else{ + if(exdcEntry[s_lv].attributes.isDirectory){//ディレクトリ + //m_info.DirCount++; + wcscpy(expathu_w[s_lv],expath_w);//パス保存 + wcscat(expath_w,exdcEntry[s_lv].entryName);//次のディレクトリパス + wcscat(expath_w,L"/"); + if (++s_lv == MAX_LEVEL)return RESULT_DIR_LEVEL_OVER; + s_serch = false; + break; + }else{//ファイル + //m_info.FileCount++; + s_serch = true; + wcscpy(path,pPathTop); + wcscat(path,exdcEntry[s_lv].entryName); + return RESULT_OK; + } + } + } + } + +} + + +//削除 +bool ExSave::Delete() +{ + LastNnResult = nn::fs::DeleteExtSaveData(OWN_UID); + //if (nn::fs::ResultNotFound().Includes(LastNnResult))return RESULT_NOT_FOUND; + return LastNnResult.IsSuccess(); +} + +//セーブ作成、成功時はマウント状態 +myResult ExSave::Create(const void* icon,size_t iconSize,u32 entryDir,u32 entryFile) +{ + if ( IsMounted )return RESULT_ALREADY_MOUNT; + LastNnResult = nn::fs::CreateExtSaveData(OWN_UID,icon,iconSize,entryDir,entryFile); + if (LastNnResult.IsFailure())return RESULT_FAIL_CREATE; + LastNnResult = nn::fs::MountExtSaveData(exsaveName,OWN_UID); + if (LastNnResult.IsFailure())return RESULT_FAIL_MOUNT; + LastNnResult = nn::fs::TryCreateDirectory(exsaveRoot_w); + if (LastNnResult.IsFailure()){ + nn::fs::Unmount(exsaveName); + return RESULT_FAIL_MOUNT; + } + IsMounted = true; + return RESULT_OK; +} +//マウント +myResult ExSave::Mount() +{ + if ( IsMounted )return RESULT_ALREADY_MOUNT; + LastNnResult = nn::fs::MountExtSaveData(exsaveName,OWN_UID); + if (LastNnResult.IsFailure()){ + return RESULT_FAIL_MOUNT; + } + IsMounted = true; + return RESULT_OK; +} +void ExSave::Unmount() +{ + IsMounted = false; + nn::fs::Unmount(exsaveName); +} +//ライト属性ファイルを閉じる +void ExSave::CloseW() +{ + writer.Finalize(); +} + +//ファイルライト +s32 ExSave::Write(char *buffer,size_t size) +{ + s32 ct; + LastNnResult = writer.TryWrite(&ct,(void*)buffer,size); + if(LastNnResult.IsFailure())ct=0; + return ct; +} + + +//管理用ファイル +//ライト属性で開く +bool ExSave::OpenSysW() +{ + LastNnResult = nn::fs::TryCreateFile(exsaveSys_w,sizeof(tArcInfo)); + LastNnResult = writerSys.TryInitialize(exsaveSys_w,false); + return LastNnResult.IsSuccess(); +} +//ライト属性ファイルを閉じる +void ExSave::CloseSysW() +{ + writerSys.Finalize(); +} +//システムファイルライト +bool ExSave::WriteSys(tArcInfo *pinfo) +{ + s32 ct; + pinfo->Ver = INFO_VERSION; + LastNnResult = writerSys.TryWrite(&ct,(void*)pinfo,sizeof(tArcInfo)); + return LastNnResult.IsSuccess(); +} +//リード属性で開く +bool ExSave::OpenSysR() +{ + LastNnResult = readerSys.TryInitialize(exsaveSys_w); + return LastNnResult.IsSuccess(); +} +//ライト属性ファイルを閉じる +void ExSave::CloseSysR() +{ + readerSys.Finalize(); +} +//ファイルリード +bool ExSave::ReadSys(tArcInfo *pinfo) +{ + s32 ct; + LastNnResult = readerSys.TryRead(&ct,(void*)pinfo,sizeof(tArcInfo)); + return LastNnResult.IsSuccess(); +} + + + + +//ライト属性ファイルを開く +bool ExSave::OpenW(wchar_t *path,s64 size) +{ + int pos,pos2; + + wcscpy(expath_w,exsaveRoot_w); + wcscat(expath_w,path); + while(1){ + LastNnResult = nn::fs::TryCreateFile(expath_w,size); + if(LastNnResult.IsSuccess())break; + //ディレクトリがなければディレクトリを作成 + pos = GetPosDelmLast(expath_w,ROOTLENGTH_EX);//ファイルが存在するディレクトリ + if (pos <= 0)return false;//rootかパスが不正 + //while (1){ + wcscpy(expathw_w,expath_w);//ワークにコピー + while (LastNnResult.IsFailure()){//ディレクトリ作成できるまで遡る + if(LastNnResult.GetDescription()!=nn::fs::DESCRIPTION_DBM_DIRECTORY_NOT_FOUND)return false; + pos2 = GetPosDelmLast(expathw_w,ROOTLENGTH_EX);//境界位置を探す + if (pos2 == 0)return false;//root到達 + expathw_w[pos2] = 0;//境界まで削除 (例) dir1/dir2/file -> dir1/dir2 -> dir1 + LastNnResult = nn::fs::TryCreateDirectory(expathw_w); + } + //if (pos2 == pos)break;//配置ディレクトリなら抜ける + //todo:ディレクトリが深いとき時間がかかるなら、無駄なTryCreateを省く + //案)直上から最初の成功までのデリミタ位置を記録 + //先に全ディレクトリ作っておくのがよさげ + //} + } + LastNnResult = writer.TryInitialize(expath_w,false); + return LastNnResult.IsSuccess(); +} + +//ファイルリード +s32 ExSave::Read(char *buffer,size_t size) +{ +// if (IsMounted==false)return 0; + s32 ct; + LastNnResult = reader.TryRead(&ct,(void*)buffer,size); + if(LastNnResult.IsFailure())ct=0; + return ct; +} + + +void ExSave::Close() +{ + reader.Finalize(); +} + + +//ファイルを開く +//パス指定はルート以降 +//(ex)data:/dir/file -> dir/file +bool ExSave::Open(wchar_t *path) +{ + wcscpy(expathw_w,exsaveRoot_w); + wcscat(expathw_w,path); + LastNnResult = reader.TryInitialize(expathw_w); + if (LastNnResult.IsSuccess()) + { + LastNnResult = reader.TryGetSize(&FileSize); + if (LastNnResult.IsSuccess())return true; + else Close(); + } + return false; +} + +//アーカイブ情報の取得 +bool ExSave::GetInfo(tArcInfo *pinfo) +{ + if(Mount()==RESULT_FAIL_MOUNT)return false; + //システムデータからフォーマット情報 + if (OpenSysR()) + { + if(ReadSys(pinfo) == false){ + pinfo->Pcode[0]=0; + CloseSysR();//クローズ + Unmount(); + return false; + } + }else{ + Unmount(); + return false; + } + CloseSysR();//クローズ +// Unmount(); +//#ifdef INFO_API_USE +//API情報と比較 +// LastNnResult = nn::fs::GetExtSaveDataFormatInfo(OWN_UID,&m_info.FileEntry,&m_info.DirEntry); +// if (m_info.FileEntry != pinfo->FileEntry)return false; +// if (m_info.DirEntry != pinfo->DirEntry)return false; +// //if (m_info.Dup != pinfo->Dup)return false; //ExSaveには無い +//#endif + return true; +} + + +//コンストラクタ +ExSave::ExSave() +{ + IsMounted = false; + s_lv=0; + m_info.DirCount = 0; + m_info.FileCount = 0; + m_info.DirEntry = 0; + m_info.FileEntry = 0; + wcscpy(expath_w,exsaveRoot_w); + //wcscpy(expathu_w,expath_w); + pPathTop = (wchar_t*)((u32)&expath_w+strlen(exsaveRoot)*2); +} + +void ExSave::Finalize() +{ + Close(); + Unmount(); +} +//デストラクタ +ExSave::~ExSave() +{ + Finalize(); +} + diff --git a/branches/1stNUP_7/CardSaveData/common/savefile/exsave.h b/branches/1stNUP_7/CardSaveData/common/savefile/exsave.h new file mode 100644 index 0000000..0806d88 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/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/1stNUP_7/CardSaveData/common/savefile/membak.cpp b/branches/1stNUP_7/CardSaveData/common/savefile/membak.cpp new file mode 100644 index 0000000..a8e17a8 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/membak.cpp @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include "membak.h" + +using namespace nn; + +namespace +{ + const size_t BUFFER_SIZE = MEM_BKUP_SIZE; + bit8 s_Buffer[BUFFER_SIZE] NN_ATTRIBUTE_ALIGN(4096); +} + +bool info_alive; + +//-------------------------------------------------------------------- +// + + +//RXgN^ +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() +{ +} +//fXgN^ +MemBak::~MemBak() +{ +} + + + + + +//-------------------------------------------------------------------- +// mount, unmount, create, delete + +//݊mF +bool MemBak::IsExist() +{ + return m_Exists; +} + +//Z[u쐬A̓}Eg +myResult MemBak::Create(u32 entryDir,u32 entryFile) +{ + 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; +} + +//}Eg +myResult MemBak::Mount() +{ + if ( m_IsMounted ) + { + return RESULT_ALREADY_MOUNT; + } + + m_IsMounted = true; + return RESULT_OK; +} +void MemBak::Unmount() +{ + m_IsMounted = false; +} + + + + +//-------------------------------------------------------------------- +// SetInfo, GetInfo + +//A[JCu̎擾 +bool MemBak::GetInfo(tArcInfo *pinfo) +{ + if (info_alive==false)return false; + *pinfo = m_ArcInfo; + return true; +} + + +//Ǘpt@C +//CgŊJ +bool MemBak::OpenSysW() +{ + return true; +} +//Cgt@C‚ +void MemBak::CloseSysW() +{ +} + + +//VXet@CCg +bool MemBak::WriteSys(tArcInfo *pinfo) +{ + info_alive = true; + pinfo->Ver = INFO_VERSION; + m_ArcInfo = *pinfo; + return true; +} + + + + +//-------------------------------------------------------------------- +// Traverse + +//pXʒũZbg +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 + +//Cgt@C‚ +void MemBak::CloseW() +{ +} + +//t@CCg +s32 MemBak::Write(char *buffer,size_t size) +{ + return m_ForWrite.Write(buffer, size); +} + + + +//Cgt@CJ +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 + +//t@C[h +s32 MemBak::Read(char *buffer,size_t size) +{ + return m_ForRead.Read(buffer, size); +} + + +void MemBak::Close() +{ +} + + +//t@CJ +//pXw̓[gȍ~ +//(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/1stNUP_7/CardSaveData/common/savefile/membak.h b/branches/1stNUP_7/CardSaveData/common/savefile/membak.h new file mode 100644 index 0000000..08c54e4 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/membak.h @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------------* + 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 + +//̉zobNAbve +//SDKXVŃAv̈悪”\̂ŖȂ +#define MEM_BKUP_SIZE 10*1024*1024 + +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(u32 entryDir,u32 entryFile); +// myResult CreateSys(); + myResult Mount(); +// myResult MountSys(); + bool IsExist(); + void Unmount(); + bool Delete(); + void CloseW(); + bool OpenW(wchar_t *path,s64 size); + bool OpenSysW();//b + void CloseSysW();//b +// bool OpenSysR();//b +// void CloseSysR();//b + 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/1stNUP_7/CardSaveData/common/savefile/savedata.cpp b/branches/1stNUP_7/CardSaveData/common/savefile/savedata.cpp new file mode 100644 index 0000000..2e4e010 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/savedata.cpp @@ -0,0 +1,79 @@ +#include +#include +#include +#include "savedata.h" +#include +#include +#include +#include + +//プロダクトコード +//結果は PrdCord に格納 +bool SaveData::GetPrdCode() +{ + PrdCode[0] = 0;//clear + s32 numPrograms; + nn::ProgramId programId; + + LastNnResult = nn::am::InitializeForLocalImporter(); + if (LastNnResult.IsFailure()){ + nn::am::FinalizeForLocalImporter(); + return false; + } + LastNnResult = nn::am::GetProgramList(&numPrograms, &programId, 1, nn::fs::MEDIA_TYPE_CTRCARD); + if (LastNnResult.IsFailure()){ + nn::am::FinalizeForLocalImporter(); + return false; + } + LastNnResult = nn::am::GetProductCode( (nn::ProductCode*)&PrdCode,nn::fs::MEDIA_TYPE_CTRCARD,programId); + nn::am::FinalizeForLocalImporter(); + PrdCode[sizeof(nn::ProductCode)] = 0;//表示時のオーバラン対策 + return LastNnResult.IsSuccess(); +} + +//セーブ作成、成功時はマウント状態 +myResult SaveData::Format(tArcInfo *pinfo) +{ + if ( IsMounted )return RESULT_ALREADY_MOUNT; + LastNnResult = nn::fs::FormatCtrCardSaveData(pinfo->FileEntry,pinfo->DirEntry,pinfo->Dup); + if (LastNnResult.IsFailure())return RESULT_FAIL_FORMAT; + if ( Mount() != RESULT_OK )return RESULT_FAIL_MOUNT; + IsMounted = true; + return RESULT_OK; +} + + +//コミット +bool SaveData::Commit() +{ + LastNnResult=nn::fs::CommitSaveData(devName); + return LastNnResult.IsSuccess(); +} + + +//マウント +bool SaveData::MountCore() +{ + //リストア先の場合、コール元でチェック(エラーによってはフォーマットすれば使える) + LastNnResult = nn::fs::MountCtrCardSaveDataForCheck(devName); + return LastNnResult.IsSuccess(); +} + +//フォーマット情報 +void SaveData::GetFormatInfoCore(tArcInfo *ifo) +{ + LastNnResult = nn::fs::GetCtrCardSaveDataFormatInfo(&ifo->FileEntry,&ifo->DirEntry,&ifo->Dup); +} + + +//コンストラクタ +SaveData::SaveData() +{ + PrdCode[0] = 0; + strcpy(devName,"data:"); + SetRootPath(L"data:"); + +} + + + diff --git a/branches/1stNUP_7/CardSaveData/common/savefile/savedata.h b/branches/1stNUP_7/CardSaveData/common/savefile/savedata.h new file mode 100644 index 0000000..0b247ea --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/savedata.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------* + 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 "../my_defs.h" +#include "savefile.h" + +class SaveData: public SaveFileRead,public SaveFileWrite +{ +public: + char PrdCode[20]; +private: + void GetFormatInfoCore(tArcInfo *ifo); +public: + bool MountCore(); + myResult Format(tArcInfo *pinfo); + void Finalize(){Close();}; + bool GetPrdCode(); + bool Commit(); + SaveData(); + ~SaveData(){Finalize();}; +}; + + +#endif diff --git a/branches/1stNUP_7/CardSaveData/common/savefile/savefile.cpp b/branches/1stNUP_7/CardSaveData/common/savefile/savefile.cpp new file mode 100644 index 0000000..eedd2ba --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/savefile.cpp @@ -0,0 +1,301 @@ +//ʊ֐ + +#include "savefile.h" + +//I[OŌ‚E("/"=0x2f)ʒuԂ +//top :͈͂̐擪w +int GetPosDelmLast(wchar_t *s,int top) +{ + size_t i = wcslen(s); + if (i <= top)return 0; + i--; + while(i > top-1){ + if (s[i]==L'/')return i; + i--; + } + return 0; +} + +//pX +void ChainPath(wchar_t *p1,wchar_t *p2) +{ + int n=wcslen(p1); + if ((p1[n-1] == L'/') && (p2[0] == L'/')) p1[n-1] = 0; + if ((p1[wcslen(p1)-1] != L'/') && (p2[0] != L'/')) wcscat(p1,L"/"); + wcscat(p1,p2); +} + + +//pX`FbN for SD +//fs֐ňG[(INVALID_ARGUMENT)ɂȂȂ̂`FbN +bool CheckPath(wchar_t *s) +{ + int i; + size_t n = wcslen(s); + + if ((n > 253) || (n==0))return false; + if (n>251) + {//fBNgI[v251܂ + if ((s[251]==L'/') || (s[252]==L'/'))return false; + } + + for (i =0;i< n-1;i++) + { + if ((s[i-1] == ' ')||(s[i+1] == ' '))return false;//ɂ̓XbVOƍŌ + if ((s[i-1] == 0x5c) ||(s[i+1] == 0x5c))return false;//0x5c = ~}[N + } + return true; + +} + +//-------------- Class SaveFileWrite +//fBNg쐬̃I[v +bool SaveFileWrite::OpenC(wchar_t *path,s64 size,bool *mkdir) +{ + int pos,pos2; + + wcscpy(pathw_w,root_w); + ChainPath(pathw_w,path); + + *mkdir = false; + LastNnResult = nn::fs::TryCreateFile(pathw_w,size); + if(LastNnResult.IsSuccess()) + { + LastNnResult = writer.TryInitialize(pathw_w,false); + return LastNnResult.IsSuccess(); + } + //fBNgȂ΃fBNg쐬 + pos = GetPosDelmLast(pathw_w,RootLength);//t@C݂fBNg + if (pos <= 0)return false;//rootpXs + wcscpy(pathw_w2,pathw_w);//[NɃRs[ + while (LastNnResult.IsFailure()){//fBNg쐬ł܂ők + if(nn::fs::ResultNotFound::Includes(LastNnResult)==false)return false; + pos2 = GetPosDelmLast(pathw_w2,RootLength);//EʒuT + if (pos2 == 0)return false;//rootB + pathw_w2[pos2] = 0;//E܂ō폜 () dir1/dir2/file -> dir1/dir2 -> dir1 + LastNnResult = nn::fs::TryCreateDirectory(pathw_w2); + } + + //쐬fBNgƉʎ~܂̂ŁA쐬Ƃɔ + *mkdir = true; // AlFfalse mkdir=true ȂfBNg쐬̂ + return false; +} + +//fBNg쐬ȂI[vA݂ꍇ͒NjL +bool SaveFileWrite::OpenAdd(wchar_t *path) +{ + wcscpy(pathw_w,root_w); + ChainPath(pathw_w,path); + LastNnResult = writer.TryInitialize(pathw_w,false); + if (LastNnResult.IsSuccess()){ + LastNnResult = writer.TrySeek(0,nn::fs::POSITION_BASE_END);//NjL + }else LastNnResult = writer.TryInitialize(pathw_w,true);//VK + if (LastNnResult.IsFailure()) + { + writer.Finalize(); + return false; + } + return true; +} + + +//fBNg쐬ȂI[v +bool SaveFileWrite::OpenW(const wchar_t *path) +{ + wcscpy(pathw_w,root_w); + ChainPath(pathw_w,(wchar_t*)path); + LastNnResult = writer.TryInitialize(pathw_w,true); + return LastNnResult.IsSuccess(); +} + + + +//N[Y +void SaveFileWrite::CloseW() +{ + writer.Finalize(); +} + +s32 SaveFileWrite::Write(char *buffer,size_t size) +{ + s32 ct; + LastNnResult = writer.TryWrite(&ct,(void*)buffer,size); + if(LastNnResult.IsFailure()){NN_LOG("write fail\n");ct=0;} + return ct; +} + + +//fBNg쐬 +bool SaveFileWrite::CreateDir(const wchar_t *dir) +{ + LastNnResult = nn::fs::TryCreateDirectory(dir); + if(LastNnResult.IsSuccess())return true; + return nn::fs::ResultAlreadyExists::Includes(LastNnResult); +} + +//폜 +bool SaveFileWrite::DeleteDir(const wchar_t *dir) +{ + LastNnResult = nn::fs::TryDeleteDirectoryRecursively(dir); + return LastNnResult.IsSuccess(); +} + + +//------------------------------------------------------ Class SaveFileRead +bool SaveFileRead::Open(const wchar_t *path) +{ + wcscpy(pathw_w,root_w); + ChainPath(pathw_w,(wchar_t*)path); + LastNnResult = reader.TryInitialize(pathw_w); + if (LastNnResult.IsSuccess()) + { + LastNnResult = reader.TryGetSize(&FileSize); + if (LastNnResult.IsSuccess())return true; + else Close(); + } + return false; + +} + +void SaveFileRead::Close() +{ + reader.Finalize(); +} + + +//t@C[h +s32 SaveFileRead::Read(char *buffer,size_t size) +{ + s32 ct; + LastNnResult = reader.TryRead(&ct,(void*)buffer,size); + if(LastNnResult.IsFailure())ct=0; + return ct; +} + +//݃`FbN +myResult SaveFileRead::IsExist(){ + myResult res; + res = Mount(); + Unmount(); + return res; +} + + +void SaveFileRead::ResetPath() +{ + s_lv=0; + s_serch = false; + wcscpy(path_w,root_w); + wcscat(path_w,L"/"); + for (int n = 0;nMAX_PATH_LENGTH - 1)return RESULT_PATH_LENGTH_OVER; + wcscat(path,dcEntryl.entryName); + return RESULT_OK; + } + } + } + +} + + +//A[JCu̎擾 +bool SaveFileRead::GetInfo(tArcInfo *pinfo,size_t clsz) +{ +static nn::fs::DirectoryEntry dcEntryl; +static nn::fs::Directory dcl; + + if(IsMounted==false){NN_LOG("GetInfo: Not Mounted\n");return false;}; + + s_lv=0; + m_info.DirCount = 0; + m_info.FileCount = 0; + m_info.DirEntry = 0; + m_info.FileEntry = 0; + m_info.total = 0; + m_info.Dup = false; + wcscpy(pathw_w,root_w); + wcscat(pathw_w,L"/"); + + int n; + int lv = 0; + for (n = 0;n0)m_info.total +=clsz;//SD..fBNgŃNX^ + wcscpy(pathu_w[lv],pathw_w);//pXۑ + wcscat(pathw_w,dcEntryl.entryName);//̃fBNgpX + wcscat(pathw_w,L"/"); + if (++lv == MAX_LEVEL)return false; + break; + }else{//t@C + m_info.FileCount++; + if (clsz==0){ + m_info.total += dcEntryl.entrySize; + }else{//NX^TCYŒ .. SDLe + sn = dcEntryl.entrySize / clsz; + if ((dcEntryl.entrySize % clsz) > 0 )sn++; + m_info.total += sn*clsz; + } + } + } + } + dcl.Finalize(); + } + for (n = 0;n +#include +#include +#include "../my_defs.h" +#include +#include + + +//******************************** defines ********** +//pX :SDK̓A[JCu253 +//A[JCuSDi[fBNg̗]T݂Ƃ +#define MAX_PATH_LENGTH 512 +//pXKw +//t@CɎgpA"/"+1ŒZȂ̂128ŏ\ +#define MAX_LEVEL 128 + +//******************************** functions ********** +//pX`FbN +//FATᔽ̔pXy[X邩`FbN +//A\񖼁ApXAPIG[(INVALID_ARGUMENT)Ŕ +bool CheckPath(wchar_t *s); + +//f~^("/")ʒuԂ +int GetPosDelmLast(wchar_t *s,int top); + +//pX +void ChainPath(wchar_t *p1,wchar_t *p2); + + +//******************************** Types ********** +//Z[uɊւ +#define INFO_VERSION 0 +struct tArcInfo{ + s64 total;//t@CTCYv + u32 DirEntry,FileEntry;//tH[}bg + u32 DirCount,FileCount;//Dir,t@C + char Pcode[20];//product code SDK̃TCYȂ + bool Dup;//2d + u8 Ver; + u8 yobi;//pfBO +}; + +//******************************** Class *************** +class SaveFileBase +{ +public: + nn::Result LastNnResult; +protected: + wchar_t root_w[MAX_PATH_LENGTH];//pX(foCX) + wchar_t path_w[MAX_PATH_LENGTH];//pX + wchar_t pathw_w[MAX_PATH_LENGTH];//[N + wchar_t pathw_w2[MAX_PATH_LENGTH]; + s32 RootLength; + wchar_t *pPathTop; + char devName[16]; + bool IsMounted; +public: + //pXݒ + void SetRootPath(wchar_t *path) + {// Ō"/"͂‚Ȃ ) "data:" + wcscpy(root_w,path); + RootLength = wcslen(path); + pPathTop = (wchar_t*)((u32)&path_w+RootLength*2); + } + void GetRootPath(wchar_t *path) + { + wcscpy(path,root_w); + + } + virtual bool MountCore() =0; + myResult Mount(){ + if ( IsMounted )return RESULT_ALREADY_MOUNT; + if (MountCore()){ + IsMounted = true; + return RESULT_OK; + } + return RESULT_FAIL_MOUNT; + }; + void Unmount(){ + if(IsMounted){ + IsMounted = false; + nn::fs::Unmount(devName); + } + }; + SaveFileBase(){IsMounted = false;root_w[0]=0;RootLength=0;}; + ~SaveFileBase(){Unmount();}; +}; + +//Cg +class SaveFileWrite :public virtual SaveFileBase +{ +private: + nn::fs::FileWriter writer; +public: + SaveFileWrite(){RootLength=0;}; + ~SaveFileWrite(){}; + bool DeleteDir(const wchar_t *dir); + bool OpenW(const wchar_t *path); + bool OpenC(wchar_t *path,s64 size,bool *mkdir); + bool OpenAdd(wchar_t *path); + void CloseW(); + s32 Write(char *buffer,size_t size); + bool CreateDir(const wchar_t *dir); +}; + +//[h +class SaveFileRead :public virtual SaveFileBase +{ +public: + s64 FileSize; +private: + virtual void GetFormatInfoCore(tArcInfo *ifo) = 0; + int dc_readed[MAX_LEVEL];//[hς݃Gg + wchar_t pathu_w[MAX_LEVEL][MAX_PATH_LENGTH];//pX + nn::fs::FileReader reader; + int s_lv; + tArcInfo m_info; + bool s_serch; +public: + myResult IsExist(); + bool Open(const wchar_t *path); + void Close(); + myResult GetPath(wchar_t *path); + void ResetPath(); + bool GetInfo(tArcInfo *pinfo,size_t clsz = 0); + s32 Read(char *buffer,size_t size); + SaveFileRead(){ + s_lv=0; + m_info.DirCount = 0; + m_info.FileCount = 0; + m_info.DirEntry = 0; + m_info.FileEntry = 0; + }; + ~SaveFileRead(){}; +}; + + +#endif diff --git a/branches/1stNUP_7/CardSaveData/common/savefile/sdmc.cpp b/branches/1stNUP_7/CardSaveData/common/savefile/sdmc.cpp new file mode 100644 index 0000000..7e5ef4b --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/sdmc.cpp @@ -0,0 +1,458 @@ +/* + + Horizon/tools/SaveDataFiler で読めるファイルを作成 + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +//#include <../fs/fs_ResultPrivate.h> +#include "sdmc.h" + +const char *sdmcName = "sdmc:"; +#define PATHLENGTH_MAX_SD 512 + +wchar_t sdmcRoot_w[MAX_PATH_LENGTH];//sdmc:/filer/UserSaveData/YearMtDtHrMtSc/00000000 +#define ROOTLENGTH_SD 49 +wchar_t fp_path[MAX_PATH_LENGTH]; +wchar_t ti_path[MAX_PATH_LENGTH]; +wchar_t expath_w[MAX_PATH_LENGTH];//パス名 +//wchar_t expathu_w[100][PATHLENGTH_MAX_SD];//上層パス名 +wchar_t expathw_w[MAX_PATH_LENGTH];//パス名ワーク +wchar_t latestPath_w[MAX_PATH_LENGTH];//sdmc:/filer/UserSaveData/YearMtDtHrMtSc +bool created; +bool IsMounted; + +//SDKツールのSaveFilerのフォーマットに合わせる +//------------ sources\tools\NandFiler\nandf_Dialog.h 参照 +const wchar_t SDMC_ROOT_DIR_NAME[] = L"sdmc:/filer"; + +struct FormatParameters +{ + size_t m_LimitSize; + size_t m_MaxDir; + size_t m_MaxFile; + s32 m_IconSize; + bit8 *m_pIconData; + bool m_Duplicate; + + FormatParameters() + : m_LimitSize(0),m_IconSize(0), m_pIconData(0) {} + //オリジナルはLinitSize不定 +}; + +struct AdditionalInfo +{ + bit64 m_Version; + bit64 m_Id; + bit64 m_Reserved[128];//オリジナルは乱数埋 + AdditionalInfo() + : m_Version(0), m_Id(0) {} +}; +//--------------------------- nandf_util.cpp 参照 +std::wstring Sdmc::GetDateName() +{ + nn::fnd::DateTime tm = nn::fnd::DateTime::GetNow(); + + std::wostringstream name; + name << std::setw(4) << std::setfill(L'0') << tm.GetYear() + << std::setw(2) << std::setfill(L'0') << tm.GetMonth() + << std::setw(2) << std::setfill(L'0') << tm.GetDay() + << std::setw(2) << std::setfill(L'0') << tm.GetHour() + << std::setw(2) << std::setfill(L'0') << tm.GetMinute() + << std::setw(2) << std::setfill(L'0') << tm.GetSecond(); + + + //char型 :表示で使う + wcstombs(DirName, name.str().c_str(), 14); + DirName[14] = 0; + return name.str(); +} + +nn::Result CreateDirIfNotExists(const wchar_t *dirName) +{ + nn::fs::Directory dir; + nn::Result result = dir.TryInitialize(dirName); + NN_LOG("%d",result.GetDescription()); + if (!nn::fs::ResultAlreadyExists::Includes(result) && result.IsFailure()) + { + result = nn::fs::TryCreateDirectory(dirName); + } + dir.Finalize(); + return result; +} + +bit64 ChangeId(bit64 id, bit64 key) +{ + return id ^ key ^ 0xce8a4d52f7105339; +} + +//----------------------------- + + +//SDMCにライト専用アーカイブ +//ディレクトリもファイルも読めない + +//直前のCreateで作成したDateTimeフォルダ削除 +bool Sdmc::Delete() +{ + if (created==false)return true; + if (Mount() == RESULT_FAIL_MOUNT)return false; + LastNnResult = nn::fs::TryDeleteDirectoryRecursively(latestPath_w); + Unmount(); + return LastNnResult.IsSuccess(); +} + +//全削除 +bool Sdmc::DeleteAll() +{ + if (Mount() == RESULT_FAIL_MOUNT)return false; + LastNnResult = nn::fs::TryDeleteDirectoryRecursively(SDMC_ROOT_DIR_NAME); + Unmount(); + return LastNnResult.IsSuccess(); +} + + +//保存先のディレクトリ作成 +//成功時はマウント状態 +bool Sdmc::Create() +{ + std::wostringstream woss; + created = false; + if (Mount() == RESULT_FAIL_MOUNT)return false; + + LastNnResult = CreateDirIfNotExists(SDMC_ROOT_DIR_NAME);//sdmc:/filer + if (LastNnResult.IsSuccess()) + { + woss << SDMC_ROOT_DIR_NAME << L"/" << L"UserSaveData";//sdmc:/filer/UserSaveData + LastNnResult = CreateDirIfNotExists(woss.str().c_str()); + if (LastNnResult.IsSuccess()) + { + DateDirName = GetDateName(); + woss << L"/" << DateDirName;//sdmc:/filer/UserSaveData/YearMtDtHrMtSc + LastNnResult = nn::fs::TryCreateDirectory(woss.str().c_str()); + if (LastNnResult.IsSuccess()) + { + wcscpy(latestPath_w,woss.str().c_str()); + created = true;//日時ディレクトリ作成フラグ + //コピー先ルート + woss << L"/" << "00000000";//sdmc:/filer/UserSaveData/YearMtDtHrMtSc/00000000 + LastNnResult = nn::fs::TryCreateDirectory(woss.str().c_str()); + if (LastNnResult.IsSuccess()) + { + woss << L"/";//sdmc:/filer/UserSaveData/YearMtDtHrMtSc/00000000/ + wcscpy(sdmcRoot_w,woss.str().c_str()); + return true; + } + } + } + } + Unmount(); + return false; +} + +//格納先パスの取得 +//先にCreateしとくこと +void Sdmc::GetRootPath(wchar_t *path) +{ + wcscpy(path,sdmcRoot_w); +} + + +//マウント +myResult Sdmc::Mount() +{ + if ( IsMounted )return RESULT_ALREADY_MOUNT; + LastNnResult = nn::fs::MountSdmc(sdmcName); + if (LastNnResult.IsFailure()){ + return RESULT_FAIL_MOUNT; + } + IsMounted = true; + return RESULT_OK; +} +void Sdmc::Unmount() +{ + IsMounted = false; + nn::fs::Unmount(sdmcName); +} +//ライト属性ファイルを閉じる +void Sdmc::CloseW() +{ + writer.Finalize(); +} + +//ファイルライト +s32 Sdmc::Write(char *buffer,size_t size) +{ + s32 ct; + LastNnResult = writer.TryWrite(&ct,(void*)buffer,size); + if(LastNnResult.IsFailure())ct=0; + return ct; +} + + +/* +//ライト属性ファイルを開く +bool Sdmc::OpenW(wchar_t *path,s64 size) +{ + int pos,pos2; + wcscpy(expath_w,sdmcRoot_w); + wcscat(expath_w,path); + + while(1){ + LastNnResult = nn::fs::TryCreateFile(expath_w,size); + if(LastNnResult.IsSuccess())break; + if(nn::fs::ResultNotFound::Includes(LastNnResult)==false)return false; + NN_LOG("%d\n",LastNnResult.GetDescription()); + //ディレクトリがなければディレクトリを作成 + pos = GetPosDelmLast(expath_w,ROOTLENGTH_SD);//ファイルが存在するディレクトリ + if (pos <= 0)return false;//rootかパスが不正 + wcscpy(expathw_w,expath_w);//ワークにコピー + while (LastNnResult.IsFailure()) + {//ディレクトリ作成できるまで遡る + if(nn::fs::ResultNotFound::Includes(LastNnResult)==false)return false; + pos2 = GetPosDelmLast(expathw_w,ROOTLENGTH_SD);//境界位置を探す + if (pos2 == 0)return false;//root到達 + expathw_w[pos2] = 0;//境界まで削除 (例) dir1/dir2/file -> dir1/dir2 -> dir1 + LastNnResult = nn::fs::TryCreateDirectory(expathw_w); + } + } + + LastNnResult = writer.TryInitialize(expath_w,false); + return LastNnResult.IsSuccess(); +} +*/ + +bool Sdmc::OpenW(wchar_t *path,s64 size,bool *mkdir) +{ + int pos,pos2; + + wcscpy(expath_w,sdmcRoot_w); + wcscat(expath_w,path); + *mkdir = false; + LastNnResult = nn::fs::TryCreateFile(expath_w,size); + if(LastNnResult.IsSuccess()) + { + LastNnResult = writer.TryInitialize(expath_w,false); + return LastNnResult.IsSuccess(); + } + //ディレクトリがなければディレクトリを作成 + pos = GetPosDelmLast(expath_w,ROOTLENGTH_SD);//ファイルが存在するディレクトリ + if (pos <= 0)return false;//rootかパスが不正 + wcscpy(expathw_w,expath_w);//ワークにコピー + while (LastNnResult.IsFailure()){//ディレクトリ作成できるまで遡る + //if(LastNnResult.GetDescription()!=nn::fs::DESCRIPTION_DBM_DIRECTORY_NOT_FOUND)return false; + if(nn::fs::ResultNotFound::Includes(LastNnResult)==false)return false; + pos2 = GetPosDelmLast(expathw_w,ROOTLENGTH_SD);//境界位置を探す + if (pos2 == 0)return false;//root到達 + expathw_w[pos2] = 0;//境界まで削除 (例) dir1/dir2/file -> dir1/dir2 -> dir1 + LastNnResult = nn::fs::TryCreateDirectory(expathw_w); + } + //作成ディレクトリ多いと画面止まるので、作成ごとに抜ける + *mkdir = true; // 帰値:false で mkdir=true ならディレクトリ作成のみ + return false; +} + + +//パス名エラーで作成できない場合の退避先 +//例:FAT規約違反、"/ test"->"/test"、SD格納先ディレクトリでパス長オーバー +bool Sdmc::OpenVnfW(wchar_t *path,s64 size) +{ + s32 sz; + tVnf vnf; + //パス名&オフセット用ファイル + wcscpy(expath_w,latestPath_w); + wcscat(expath_w,L"/00000000.vnf"); + if(reader.TryInitialize(expath_w).IsSuccess()) + { + Close(); + LastNnResult = writer.TryInitialize(expath_w,false); + if (LastNnResult.IsSuccess()) + LastNnResult = writer.TrySeek(0,nn::fs::POSITION_BASE_END);//追記 + }else LastNnResult = writer.TryInitialize(expath_w,true);//新規 + if (LastNnResult.IsSuccess()) + { + wcscpy(vnf.path,path); + vnf.size = size; + LastNnResult = writer.TryWrite(&sz,&vnf,sizeof(tVnf));//ヘッダ格納 + } + if (LastNnResult.IsFailure()) + { + writer.Finalize(); + return false; + } + return true; + +} + +//退避ファイルをリード用に開く +//成功時はパス名のデータ先頭位置にシーク +bool Sdmc::OpenVnf(wchar_t *path) +{ + s32 sz; + tVnf vnf; + wcscpy(expath_w,latestPath_w); + wcscat(expath_w,L"/00000000.vnf"); + if(reader.TryInitialize(expath_w).IsSuccess()) + { + while(1) + { + LastNnResult = reader.TryRead(&sz, &vnf, sizeof(vnf));//ヘッダ + if (LastNnResult.IsSuccess() && (sz == sizeof(tVnf))) + { + vnf.path[MAX_PATH_LENGTH-1] = 0;//念の為、終端 + if(wcscmp(vnf.path,path) ==0)return true;//パス名一致 + LastNnResult = reader.TrySeek(vnf.size,nn::fs::POSITION_BASE_CURRENT);//次 + if (LastNnResult.IsFailure())return false; + }else return false; + } + } + return false; +} + + + +//情報ファイル +// +bool Sdmc::WriteSys(tArcInfo *ifo) +{//SaveFilerで読むためのファイル + std::wostringstream woss; + if (Mount() == RESULT_FAIL_MOUNT)return false; + woss << latestPath_w << L"/00000000"; + // FormatParameter を保存 + LastNnResult = writer.TryInitialize( (woss.str() + L".dat").c_str(), true); + if (LastNnResult.IsFailure()){Unmount();return false;} + s32 size; + FormatParameters Fparam; + Fparam.m_MaxDir = ifo->DirEntry; + Fparam.m_MaxFile = ifo->FileEntry; + Fparam.m_Duplicate = ifo->Dup; + LastNnResult = writer.TryWrite(&size, &Fparam, sizeof(FormatParameters)); + if (LastNnResult.IsFailure()){Unmount();return false;} + LastNnResult = writer.TryFlush(); + if (LastNnResult.IsFailure()){Unmount();return false;} + writer.Finalize(); + //AdditionalInfoを保存 + AdditionalInfo Ainfo; + LastNnResult = writer.TryInitialize((woss.str() + L"_.dat").c_str(), true); + if (LastNnResult.IsFailure()){ Unmount();return false;} + Ainfo.m_Version = 0; + Ainfo.m_Id = ChangeId(Ainfo.m_Id, static_cast(std::wcstoll(DateDirName.c_str(), NULL, 10))); + LastNnResult = writer.TryWrite(&size, &Ainfo, sizeof(AdditionalInfo)); + if (LastNnResult.IsFailure()){ Unmount();return false;} + LastNnResult = writer.TryFlush(); + if (LastNnResult.IsFailure()){ Unmount();return false;} + writer.Finalize(); +//ツールが使うファイル + std::wostringstream woss2; + woss2 << latestPath_w << L"/toolinfo.dat"; + LastNnResult = writer.TryInitialize(woss2.str().c_str(), true); + if (LastNnResult.IsFailure()){ Unmount();return false;} + LastNnResult = writer.TryWrite(&size, ifo, sizeof(tArcInfo)); + if (LastNnResult.IsFailure()){ Unmount();return false;} + LastNnResult = writer.TryFlush(); + if (LastNnResult.IsFailure()){ Unmount();return false;} + writer.Finalize(); + Unmount(); + + woss << L".dat"; + wcscpy(fp_path,woss.str().c_str()); + wcscpy(ti_path,woss2.str().c_str()); + + return true; +} + + +//アーカイブ情報の取得 +bool Sdmc::GetInfo(tArcInfo *pinfo) +{ + s32 size; + + if (Mount() == RESULT_FAIL_MOUNT)return false; + + // FormatParameter .. SaveFiler用ファイル + // FormatParameter を保存 + LastNnResult = reader.TryInitialize( fp_path); + if (LastNnResult.IsFailure()){Unmount();return false;} + FormatParameters Fparam; + LastNnResult = reader.TryRead(&size, &Fparam, sizeof(FormatParameters)); + if (LastNnResult.IsFailure()){Unmount();return false;} + reader.Finalize(); + + //ツール情報 + LastNnResult = reader.TryInitialize( ti_path); + if (LastNnResult.IsFailure()){ Unmount();return false;} + LastNnResult = reader.TryRead(&size, &m_info, sizeof(tArcInfo)); + if (LastNnResult.IsFailure()){ Unmount();return false;} + reader.Finalize(); + + //両ファイル共通パラメータのチェック + if((Fparam.m_MaxDir != m_info.DirEntry) || + (Fparam.m_MaxFile != m_info.FileEntry) || + (Fparam.m_Duplicate != m_info.Dup))return false; + + *pinfo = m_info; + return true; + +} + + +//ファイルを開く +//パス指定はルート以降 +//(ex)data:/dir/file -> dir/file +bool Sdmc::Open(wchar_t *path) +{ + wcscpy(expathw_w,sdmcRoot_w); + wcscat(expathw_w,path); + LastNnResult = reader.TryInitialize(expathw_w); + if (LastNnResult.IsSuccess()) + { + LastNnResult = reader.TryGetSize(&FileSize); + if (LastNnResult.IsSuccess())return true; + else Close(); + } + NN_LOG("sdmc:Open %d",LastNnResult.GetDescription()); + return false; +} + + +void Sdmc::Close() +{ + reader.Finalize(); +} + +//ファイルリード +s32 Sdmc::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; +} + + +//コンストラクタ +Sdmc::Sdmc() +{ + IsMounted = false; +} + +void Sdmc::Finalize() +{ + CloseW(); + Close(); + Unmount(); +} +//デストラクタ +Sdmc::~Sdmc() +{ + Finalize(); +} + diff --git a/branches/1stNUP_7/CardSaveData/common/savefile/sdmc.h b/branches/1stNUP_7/CardSaveData/common/savefile/sdmc.h new file mode 100644 index 0000000..406bd09 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/sdmc.h @@ -0,0 +1,85 @@ +/*---------------------------------------------------------------------------* + 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 sdmc_H_ +#define sdmc_H_ + +#include +#include +#include +#include "../my_defs.h" +#include "savefile.h" + +class Sdmc +{ +public: + s64 FileSize; + nn::Result LastNnResult; + //std::wstring DateDirName; + char DirName[16]; +private: + std::wstring GetDateName(); + std::wstring DateDirName; + nn::fs::FileReader reader; + nn::fs::FileWriter writer; + //wchar_t *pPathTop; + tArcInfo m_info; + //int s_lv; + int exrootlen; + //bool s_serch; +public: + bool MountCore() + { + LastNnResult = nn::fs::MountSdmcWriteOnly(devName); + return LastNnResult.IsSuccess(); + } + Sdmc(); + ~Sdmc(); + void Finalize(); + bool Create(); + myResult MountSys(); + void Unmount(); + bool Delete(); + bool DeleteAll(); + void CloseW(); + //bool OpenW(wchar_t *path,s64 size); + bool OpenW(wchar_t *path,s64 size,bool *mkdir); + bool OpenVnfW(wchar_t *path,s64 size); + bool OpenVnf(wchar_t *path); + void GetRootPath(wchar_t *path); +// bool OpenSysW();//暫定 +// void CloseSysW();//暫定 +// bool OpenSysR();//暫定 +// void CloseSysR();//暫定 + s32 Write(char *buffer,size_t size); + bool WriteSys(tArcInfo *ifo); +// 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); +}; + +//Fat違反パス格納データのヘッダ +//直後にデータ配置 +//Header+Data,、Header+Data ... と連続して追記してゆく +typedef struct{ + wchar_t path[MAX_PATH_LENGTH]; + s64 size; +}tVnf; + +#endif diff --git a/branches/1stNUP_7/CardSaveData/common/savefile/sdmcwo.cpp b/branches/1stNUP_7/CardSaveData/common/savefile/sdmcwo.cpp new file mode 100644 index 0000000..6660dd0 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/sdmcwo.cpp @@ -0,0 +1,177 @@ +/* + + Horizon/tools/SaveDataFiler で読めるファイルを作成 + + ライトのみアーカイブ使用 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sdmcwo.h" + +const wchar_t *SDMC_ROOT_DIR_NAME = L"/filer"; + +//保存先:日時をディレクトリ名 +//-------- nandf_util.cpp 参照 +std::wstring Sdmcwo::GetDateName() +{ + nn::fnd::DateTime tm = nn::fnd::DateTime::GetNow(); + + std::wostringstream name; + name << std::setw(4) << std::setfill(L'0') << tm.GetYear() + << std::setw(2) << std::setfill(L'0') << tm.GetMonth() + << std::setw(2) << std::setfill(L'0') << tm.GetDay() + << std::setw(2) << std::setfill(L'0') << tm.GetHour() + << std::setw(2) << std::setfill(L'0') << tm.GetMinute() + << std::setw(2) << std::setfill(L'0') << tm.GetSecond(); + + + //char型 :表示で使う + wcstombs(DirName, name.str().c_str(), 14); + DirName[14] = 0; + return name.str(); +} + + +bit64 ChangeId(bit64 id, bit64 key) +{ + return id ^ key ^ 0xce8a4d52f7105339; +} + +//---------------------------------------------------------- + + +bool Sdmcwo::DelDir(const wchar_t *dir) +{ + //if (created==false)return true;//未作成ならなにもしない + if (Mount() == RESULT_FAIL_MOUNT)return false; + bool res = DeleteDir(dir); + Unmount(); + return res; +} + +//直前に作成したDateTimeフォルダ削除 +bool Sdmcwo::Delete() +{ + return DelDir(latestPath_w); +} + +//全削除 +bool Sdmcwo::DeleteAll() +{ + std::wostringstream woss; + woss << devName << SDMC_ROOT_DIR_NAME;//sdmc:/filer + bool res = DelDir(woss.str().c_str()); + if(res)created=false; + else NN_LOG("Deldir fail %d\n",LastNnResult.GetDescription()); + return res; +} + + +//保存先のディレクトリ作成 +//成功時はマウント状態、クラスタサイズを設定 +bool Sdmcwo::Create() +{ + s64 size,size2; + std::wostringstream woss; + created = false; + if (Mount() == RESULT_FAIL_MOUNT)return false; + + woss << devName << SDMC_ROOT_DIR_NAME;//sdmc:/filer + if (CreateDir(woss.str().c_str())) + { + woss << L"/" << L"UserSaveData";//sdmc:/filer/UserSaveData + if ( CreateDir(woss.str().c_str()) ) + { + DateDirName = GetDateName(); + woss << L"/" << DateDirName;//sdmc:/filer/UserSaveData/YearMtDtHrMtSc + if ( CreateDir(woss.str().c_str()) ) + { + wcscpy(latestPath_w,woss.str().c_str()); + created = true;//日時ディレクトリ存在フラグ + //コピー先ルート + woss << L"/" << "00000000";//sdmc:/filer/UserSaveData/YearMtDtHrMtSc/00000000 + if (nn::fs::ResultAlreadyExists::Includes(LastNnResult)) + {//既にあれば混じらないよう削除(時計合ってれば起こらないはず) + nn::fs::TryDeleteDirectoryRecursively(woss.str().c_str());//保存先ディレクトリ + wcscpy(pathw_w,woss.str().c_str()); + wcscat(pathw_w,L".vnf"); + nn::fs::TryDeleteFile(pathw_w);//追記型ファイル + } + GetFreeSize(&size); + if ( CreateDir(woss.str().c_str()) ) + { + GetFreeSize(&size2); + FreeSize = size2; + if ((size-size2)<0) ClasterSize = 0; + else ClasterSize = size-size2;//クラスタサイズ + wcscpy(rootPath_w,woss.str().c_str());//格納先パス保存 + SetRootPath(rootPath_w); + return true; + } + } + } + } + Unmount(); + return false; +} + + +//パス名エラーで作成できない場合の格納先 +bool Sdmcwo::OpenVnfW(wchar_t *path,s64 size) +{ + tVnf vnf; + bool res=false; + //パス名&オフセット用ファイル + SetRootPath(latestPath_w);//基底パスを変更 + if (OpenAdd(L"/00000000.vnf"))//追記で開く + { + wcscpy(vnf.path,path);//ヘッダ格納 + vnf.size = size; + res = (Write((char*)&vnf,sizeof(tVnf)) == sizeof(tVnf)); + } + SetRootPath(rootPath_w);//基底パスを戻す + return res; +} + + +char buff[32768*2]; +//情報ファイル +// +bool Sdmcwo::WriteSys(tArcInfo *ifo) +{//SaveFilerで読むためのファイル + if (Mount() == RESULT_FAIL_MOUNT)return false; + bool res = false; + SetRootPath(latestPath_w);//基底パスを変更 + // FormatParameter を保存 + if(OpenW( L"/00000000.dat" )) + { + FormatParameters Fparam; + Fparam.m_MaxDir = ifo->DirEntry; + Fparam.m_MaxFile = ifo->FileEntry; + Fparam.m_Duplicate = ifo->Dup; + if ( Write((char*)&Fparam, sizeof(FormatParameters)) == sizeof(FormatParameters)) + { //AdditionalInfoを保存 + CloseW(); + if(OpenW( L"/00000000_.dat")) + { + AdditionalInfo Ainfo; + Ainfo.m_Version = 0; + Ainfo.m_Id = ChangeId(Ainfo.m_Id, static_cast(std::wcstoll(DateDirName.c_str(), NULL, 10))); + res = Write((char*)&Ainfo, sizeof(AdditionalInfo)) == sizeof(AdditionalInfo); + } + } + } + CloseW(); + Unmount(); + SetRootPath(rootPath_w);//基底パスを戻す + return res; +} + + diff --git a/branches/1stNUP_7/CardSaveData/common/savefile/sdmcwo.h b/branches/1stNUP_7/CardSaveData/common/savefile/sdmcwo.h new file mode 100644 index 0000000..63cb155 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/savefile/sdmcwo.h @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + + Copyright (C)2009 Nintendo Co., Ltd. All rights reserved. + + These coded instructions, statements, and computer programs contain + proprietary information of Nintendo of America Inc. and/or Nintendo + Company Ltd., and are protected by Federal copyright law. They may + not be disclosed to third parties or copied or duplicated in any form, + in whole or in part, without the prior written consent of Nintendo. + + *---------------------------------------------------------------------------*/ + +//SDKツールのSaveFilerで読める形式でsdmcダイレクトで書き出す +//リードはしない + +#ifndef sdmcwo_H_ +#define sdmcwo_H_ + +#include +#include +#include +#include "../my_defs.h" +#include "savefile.h" + + +//SDKツールのSaveFiler用の情報ファイル +//-------ources\tools\NandFiler\nandf_Dialog.h 参照 + +struct FormatParameters +{ + size_t m_LimitSize; + size_t m_MaxDir; + size_t m_MaxFile; + s32 m_IconSize; + bit8 *m_pIconData; + bool m_Duplicate; + + FormatParameters() + : m_LimitSize(0),m_IconSize(0), m_pIconData(0) {} + //オリジナルはLimitSize不定 +}; + +struct AdditionalInfo +{ + bit64 m_Version; + bit64 m_Id; + bit64 m_Reserved[128];//オリジナルは乱数埋 + AdditionalInfo() + : m_Version(0), m_Id(0) {} +}; + +class Sdmcwo: public SaveFileWrite +{ +public: + char DirName[16]; + size_t ClasterSize;//SDクラスタサイズ .. Create後有効 + size_t FreeSize;//Create直後の空き..Create後有効 +private: + bool DelDir(const wchar_t *dir); + std::wstring GetDateName(); + std::wstring DateDirName; + wchar_t latestPath_w[MAX_PATH_LENGTH];//dev:filer/UserSaveData/YearMtDtHrMtSc + wchar_t rootPath_w[MAX_PATH_LENGTH];//dev:/filer/UserSaveData/YearMtDtHrMtSc/00000000/ + bool created; +public: + bool MountCore() + { + LastNnResult = nn::fs::MountSdmcWriteOnly(devName); + return LastNnResult.IsSuccess(); + } + bool GetFreeSize(s64 *size) + { + s64 sz; + LastNnResult = nn::fs::GetSdmcSize(&sz,size); + return LastNnResult.IsSuccess(); + } + void Finalize(){CloseW();}; + bool Create(); + bool Delete(); + bool DeleteAll(); + bool OpenVnfW(wchar_t *path,s64 size); + bool WriteSys(tArcInfo *ifo); + Sdmcwo(){ + strcpy(devName,"sdmcwo:"); + ClasterSize = 0; + FreeSize = 0; + DirName[0] = 0; + }; + ~Sdmcwo(){Finalize();}; +}; + +//Fat違反パス格納データのヘッダ +//直後にデータ配置 +//Header+Data,、Header+Data ... と連続して追記してゆく +typedef struct{ + wchar_t path[MAX_PATH_LENGTH]; + s64 size; +}tVnf; + +#endif diff --git a/branches/1stNUP_7/CardSaveData/common/shfnt.cpp b/branches/1stNUP_7/CardSaveData/common/shfnt.cpp new file mode 100644 index 0000000..65ca877 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/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 シェーダの初期化を行います。 +//! +//! @param[in,out] pResource 描画用リソースを管理するオブジェクトへのポインタ。 +//--------------------------------------------------------------------------- +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 グラフィックスの初期設定を行います。 + *---------------------------------------------------------------------------*/ +void +InitGX() +{ + glClearColor(0.3f, 0.3f, 0.3f, 1.0f); +} + + +//--------------------------------------------------------------------------- +//! @brief 描画の初期設定を行います。 +//! +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +InitDraw( + int width, + int height +) +{ + // カラーバッファ情報 + // LCDの向きに合わせて、幅と高さを入れ替えています。 + 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 ), + + // ステンシルテストを無効 + NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(), + + // デプステストを無効 + // カラーバッファの全ての成分を書き込み可 + NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK( + false, // isDepthTestEnabled + 0, // depthFunc + true, // depthMask + true, // red + true, // green + true, // blue + true), // alpha + + // アーリーデプステストを無効 + 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 破棄するフォントへのポインタ。 +//--------------------------------------------------------------------------- +void +CleanupFont(nn::font::ResFont* pFont) +{ + // 描画用バッファの無効化 + // 描画用バッファがセットされているなら 構築時に SetDrawBuffer に渡したバッファへの + // ポインタが返ってきます。 + void *const drawBuffer = pFont->SetDrawBuffer(NULL); + if (drawBuffer != NULL) + { + appHeap.Free(drawBuffer); + } +} + +//--------------------------------------------------------------------------- +//! @brief 表示文字列用バッファを確保します。 +//! +//! @param[in] charMax 表示する文字列の最大文字数。 +//! +//! @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 文字列表示用にモデルビュー行列と射影行列を設定します。 +//! +//! @param[in] pDrawer RectDrawerオブジェクトへのポインタ。 +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +SetupTextCamera( + nn::font::RectDrawer* pDrawer, + int width, + int height +) +{ + // 射影行列を正射影に設定 + { + // 左上原点とし、Y軸とZ軸の向きが逆になるように設定します。 + 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); + } + + // モデルビュー行列を単位行列に設定 + { + 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文字列を描画します。 +//--------------------------------------------------------------------------- +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確保、RenderSystem.Inititの後に呼ぶ +void SharedFontInit() +{ + + InitGX(); + + // 共有フォントの初期化 + NN_UTIL_PANIC_IF_FAILED(nn::pl::InitializeSharedFont()); + + // 共有フォントのロードが完了するまで待機 + 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)); + } + + // 共有フォントの種類を取得 + //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/1stNUP_7/CardSaveData/common/shfnt.h b/branches/1stNUP_7/CardSaveData/common/shfnt.h new file mode 100644 index 0000000..e168087 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/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/1stNUP_7/CardSaveData/common/sleep.cpp b/branches/1stNUP_7/CardSaveData/common/sleep.cpp new file mode 100644 index 0000000..67d32cc --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/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(); +} + +/*------------------------------------------------------------------------* + システムスリープの指示が来ているかどうかを返します。 + *------------------------------------------------------------------------*/ +bool SleepHandler::IsSleepRequested( void ) +{ + if ( nn::applet::IsExpectedToReplySleepQuery() ) + return true; + + return false; +} + +/*------------------------------------------------------------------------* + 本体スリープ状態に移行させるための処理を行います。 + グラフィックスなどの処理がスリープに入っても問題ない + 適切なタイミングで呼び出す必要があります。 + *------------------------------------------------------------------------*/ +void SleepHandler::SleepSystem( void ) +{ + // SleepHandler::IsSleepRequested() == true における呼び出しが前提 + + // 何らかの理由で SleepQuery に対して REJECT を返す場合は、ここで判定して + // REJECT を返し、この関数を抜ける + + // ファイルシステム処理中はスリープをしない + //if ( g_SleepCS.TryEnter() ) + { + // スリープ前処理 + + nn::applet::ReplySleepQuery(nn::applet::REPLY_ACCEPT); + + g_AwakeEvent.Wait(); + + // スリープ復帰時の処理 + + // g_SleepCS.Leave(); + } +} + +/*------------------------------------------------------------------------* + スリープ問い合わせ時に呼ばれるコールバック + *------------------------------------------------------------------------*/ +AppletQueryReply SleepHandler::SleepQueryCallback( uptr arg ) +{ + NN_UNUSED_VAR(arg); + g_AwakeEvent.ClearSignal(); + + if ( !nn::applet::IsActive() ) + { + // Inactive なとき、メインスレッドは applet::WaitForStarting() で停止状態であり、 + // 他のスレッドも停止状態になっているはず(アプリケーション側の実装依存) + return nn::applet::REPLY_ACCEPT; + } + else + { + return nn::applet::REPLY_LATER; + } +} + +/*------------------------------------------------------------------------* + スリープ復帰時に呼ばれるコールバック + *------------------------------------------------------------------------*/ +void SleepHandler::AwakeCallback( uptr arg ) +{ + NN_UNUSED_VAR(arg); + g_AwakeEvent.Signal(); + + s_IsAfterWakeUp = true; +} diff --git a/branches/1stNUP_7/CardSaveData/common/sleep.h b/branches/1stNUP_7/CardSaveData/common/sleep.h new file mode 100644 index 0000000..15a14f1 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/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_ + +/*------------------------------------------------------------------------* + 本体スリープに関連する処理 + *------------------------------------------------------------------------*/ + 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フレーム分描画を待ってから LCD を有効にするためのフラグ + 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/1stNUP_7/CardSaveData/common/test_data.cpp b/branches/1stNUP_7/CardSaveData/common/test_data.cpp new file mode 100644 index 0000000..fd73e36 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/test_data.cpp @@ -0,0 +1,1140 @@ +/*---------------------------------------------------------------------------* + 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; + int *buff; + buff = (int*)&src_buff[0]; + for (i=0;i= 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()) + { + //NN_LOG("%d\n",res.GetDescription()); + 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; +} + +const char kinsi[] = {0x22,'<','>','?','*','|',0x5c,':',' ',0};//0x22 = "",0x5c = 円マーク +// スラッシュはセーブ時に重ね("//")ても"/"になり,末尾だとエラーとなる +const char *kinsi2[] = { "CON","PRN","NUL","AUX","LPT1","LPT2","LPT3","LPT4","COM1","COM2","COM3","COM4" +,"con","prn","nul","aux","lpt1","lpt2","lpt3","lpt4","com1","com2","com3","com4",""}; + + +//FAT違反の名前 +bool Test6_W() +{ + + res = nn::fs::FormatSaveData(100,100,true); + if (res.IsFailure()){ + drawText(8,100,"format Fail"); + return false; + } + res =nn::fs::MountSaveData(); + if (res.IsFailure()){ + drawText(8,100,"Mount Fail"); + return false; + } + + + +//禁止文字 + char *base = "test6"; + char dname[128],fname[128]; + int ofst=0; + + //頭に付ける + strcpy(dname,"data:/"); + int pos = strlen(dname); + strcat(dname,"_"); + strcat(dname,base);//data:/_base + int pos2 = strlen(dname)+1; + strcpy(fname,dname); + strcat(fname,"/_"); + strcat(fname,base); + strcat(fname,".bin");//data:/_base/_base.bin + + int i =0; + char c; + while(kinsi[i] != 0) + { + c = kinsi[i]; + dname[pos] = c; + res = nn::fs::TryCreateDirectory(dname); + if (res.IsFailure()){ + drawText(8,100,"Dir fail"); + nn::fs::Unmount("data:"); + return false; + } + fname[pos] = c; + fname[pos2] = c; + res = fout.TryInitialize(fname,true); + if (res.IsFailure()){ + drawText(8,100,"open fail"); + nn::fs::Unmount("data:"); + return false; + } + res = fout.TryWrite( &size,&src_buff[ofst],512); + if (res.IsFailure()){ + drawText(8,100,"write fail"); + nn::fs::Unmount("data:"); + return false; + } + fout.Finalize(); + i++; + ofst+=512; + } + + //末尾 + strcpy(dname,"data:/"); + strcat(dname,base);//data:/base + pos = strlen(dname); + strcat(dname,"_");//data:/base_ + strcpy(fname,dname); + strcat(fname,"/"); + strcat(fname,base);//data:/base_/base + pos2 = strlen(fname); + strcat(fname,"_.bin");//data:/base_/base_.bin + + i =0; + while(kinsi[i] != 0) + { + c = kinsi[i]; + dname[pos] = c; + res = nn::fs::TryCreateDirectory(dname); + if (res.IsFailure()){ + drawText(8,100,"dir fail"); + nn::fs::Unmount("data:"); + return false; + } + fname[pos] = c; + fname[pos2] = c; + res = fout.TryInitialize(fname,true); + if (res.IsFailure()){ + drawText(8,100,"open fail"); + nn::fs::Unmount("data:"); + return false; + } + res = fout.TryWrite( &size,&src_buff[ofst],512); + if (res.IsFailure()){ + drawText(8,100,"write fail"); + nn::fs::Unmount("data:"); + return false; + } + fout.Finalize(); + i++; + ofst+=512; + } + + +//禁止名 + i=0; + while(kinsi2[i][0] != 0) + { + strcpy(dname,"data:/"); + strcat(dname,kinsi2[i]); + res = nn::fs::TryCreateDirectory(dname); + if (res.IsFailure()){ + drawText(8,100,"dir fail"); + nn::fs::Unmount("data:"); + return false; + } + strcpy(fname,dname); + strcat(fname,"/"); + strcat(fname,kinsi2[i]); + res = fout.TryInitialize(fname,true); + if (res.IsFailure()){ + drawText(8,100,"open fail"); + nn::fs::Unmount("data:"); + return false; + } + res = fout.TryWrite( &size,&src_buff[ofst],512); + if (res.IsFailure()){ + drawText(8,100,"write fail"); + nn::fs::Unmount("data:"); + return false; + } + fout.Finalize(); + i++; + ofst+=512; + } + + nn::fs::CommitSaveData(); + nn::fs::Unmount("data:"); + + drawText(10,100,"end"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + return true; +} + + +bool Test6_V() +{ + +//禁止文字 + char *base = "test6"; + char fname[128]; + int ofst=0; + + //頭に付ける + strcpy(fname,"data:/"); + int pos = strlen(fname); + strcat(fname,"_"); + strcat(fname,base);//data:/_base + int pos2 = strlen(fname)+1; + strcat(fname,"/_"); + strcat(fname,base); + strcat(fname,".bin");//data:/_base/_base.bin + + int i =0; + int j; + char c; + while(kinsi[i] != 0) + { + c = kinsi[i]; + fname[pos] = c; + fname[pos2] = c; + res = fin.TryInitialize(fname); + if (res.IsFailure()){ + drawText(8,100,"open fail"); + nn::fs::Unmount("data:"); + return false; + } + res = fin.TryRead( &size,&get_buff[ofst],512); + if (res.IsFailure()){ + drawText(8,100,"read fail"); + nn::fs::Unmount("data:"); + return false; + } + fin.Finalize(); + + for(j=0;j<512;j++)if(src_buff[ofst+i] != get_buff[ofst+i]){ + drawText(8,100,"verifi fail"); + nn::fs::Unmount("data:"); + return false; + } + + i++; + ofst+=512; + } + + //末尾 + strcpy(fname,"data:/"); + strcat(fname,base);//data:/base + pos = strlen(fname); + strcat(fname,"_/");//data:/base_/ + strcat(fname,base);//data:/base_/base + pos2 = strlen(fname); + strcat(fname,"_.bin");//data:/base_/base_.bin + + i =0; + while(kinsi[i] != 0)//末尾スラッシュは名無しでエラー + { + c = kinsi[i]; + fname[pos] = c; + fname[pos2] = c; + res = fin.TryInitialize(fname); + if (res.IsFailure()){ + drawText(8,100,"open fail"); + nn::fs::Unmount("data:"); + return false; + } + res = fin.TryRead( &size,&get_buff[ofst],512); + if (res.IsFailure()){ + drawText(8,100,"write fail"); + nn::fs::Unmount("data:"); + return false; + } + fout.Finalize(); + + for(j=0;j<512;j++)if(src_buff[ofst+i] != get_buff[ofst+i]){ + drawText(8,100,"verifi fail"); + nn::fs::Unmount("data:"); + return false; + } + + i++; + ofst+=512; + } + + +//禁止名 + i=0; + while(kinsi2[i][0] != 0) + { + strcpy(fname,"data:/"); + strcat(fname,kinsi2[i]); + strcat(fname,"/"); + strcat(fname,kinsi2[i]); + res = fin.TryInitialize(fname); + if (res.IsFailure()){ + drawText(8,100,"open fail"); + nn::fs::Unmount("data:"); + return false; + } + res = fin.TryRead( &size,&get_buff[ofst],512); + if (res.IsFailure()){ + drawText(8,100,"read fail"); + nn::fs::Unmount("data:"); + return false; + } + fin.Finalize(); + + for(j=0;j<512;j++)if(src_buff[ofst+i] != get_buff[ofst+i]){ + drawText(8,100,"verifi fail"); + nn::fs::Unmount("data:"); + return false; + } + i++; + ofst+=512; + } + + fin.Finalize(); + nn::fs::Unmount("data:"); + drawText(10,100,"end"); + s_RenderSystem.SwapBuffers(); + nngxWaitVSync(NN_GX_DISPLAY0); + return true; +} + +#define menu_ct 7 +#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","fat error name"}; + +#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 = Test0_W(5);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; + case 6:sccs = Test6_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 = Test0_V(5);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; + case 6:sccs = Test6_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){ + fin.Finalize(); + fout.Finalize(); + res =nn::fs::Unmount("data:"); + 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/1stNUP_7/CardSaveData/common/test_data.h b/branches/1stNUP_7/CardSaveData/common/test_data.h new file mode 100644 index 0000000..3525aa4 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/common/test_data.h @@ -0,0 +1,6 @@ +#ifndef TEST_DATA_H_ +#define TEST_DATA_H_ + +void TestMain(); + +#endif diff --git a/branches/1stNUP_7/CardSaveData/docs/Error_code.txt b/branches/1stNUP_7/CardSaveData/docs/Error_code.txt new file mode 100644 index 0000000..0920809 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/docs/Error_code.txt @@ -0,0 +1,37 @@ + +//エラー表示コードの下位2桁 +0, //不明 +1, //デバイスが見つからない +2,//プロダクトコード不一致 +3,//ベリファイエラー +4,//パスが長すぎ +5,//ディレクトリ深すぎ +6, //メディアが見つからない(サブ基盤外れなど) +10, //ファイルが見つからない +20, //既に存在 +21, //空き容量がない +22, //書込み禁止 +30, //アクセスエラー +50, //フォーマットエラー +60, //検証に失敗、改竄 +70, //ROM情報エラー +80, //リトライ要求 +90, //実行時エラー +99 //深刻なエラー + + +//上位 +CARD = 100, +BKUP DEVICE = 200, +OTHER = 300 + + +これらの合成で表示される +例えば、カードが刺さっていない場合は 101 となる + + +通常時に発生しやすいと思われるもの + +302 .. プロダクトコードが一致しない +101 .. カードが見つからない + diff --git a/branches/1stNUP_7/CardSaveData/docs/HowToビルド.txt b/branches/1stNUP_7/CardSaveData/docs/HowToビルド.txt new file mode 100644 index 0000000..ecbe1c6 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/docs/HowToビルド.txt @@ -0,0 +1,60 @@ +mF‹F +ARM RVC_Nintendo 4.1 +omake 0.9.8.5 +CTR SDK2.3.4 + PrivateKit(SystemProgramKit,RepairTool,SystemMenu) + +vF1stNup(SDK 2.3x)ȍ~̃VXe{ + +) +Sampledemos common,gxrhĂ +omakeroot̂fBNgɂomaket@C +SAMPLED_DEMOS_COMMON_INCLUDE_DIR Ɂ@ +sampledemos/common/includëʒuw肵Ă +Jpubkeyimp/omakeŎw + +rh) +omakeroot̂fBNgomakes +bodyŃrhocia AImpomake(SRC_IMPORTEE_PATH)Ŏw +(ʎY@Ŏgɂ́A}X^Ociaw) +rhNANDC|[gpccił + + +C|[g: +ciaSDC|[g -> SD .. DevMenugp,DevMenufullȂnandɂ +J[hNC|[g -> NAND + +ʎY@ł̎sɂ̓}X^OK{ +bodyō쐬cia OLStŃ}X^O +ciagč쐬cci}X^O + +}X^O̗F +Ebody/imagesɏocia}X^OOLSt +EciaImpomakeŎwA͎wꏊɒu +ibodỹrhŏ㏑Ȃ悤ꏊt@CςقSj +Eimp/omakesAcci쐬 +Ecci}X^O +EfobKC^ŊJJ[hɏĂA +fobKł̓[hTARGET ERRORƕ\邪CɂĂ +C^͎gƖł͂.. + +OLSƃ}X^o[WXVKv +common/ver.h͕\o[WAύXĂ_ +body/omekẽRgQl + +NANDC|[gŎsꍇcia`FbN +SDC|[g +J@œ- }X^OĂȂ +ʎY@œ- OLStĂȂ +(1stNupȍ~̗ʎY@̓}X^OSDAvtOK{) + +C|[g̖{̂VAԍŐĂ܂ +"imp/imp_lis/"ɃXgƏTv +OpenSSL0.9.6k,r 1.0.0d œmF +imp/imp_list ɃR}hCc[(win32)pob` +gcygwinł +[UɂomakewpubkeyƑgprivatekeyōn + + +{c[J̃}X^O͐iG()Ɉ˗ +}X^OςDevMenu(full) +CUP쐬͔ѓɕ diff --git a/branches/1stNUP_7/CardSaveData/docs/csm_inf_sample.txt b/branches/1stNUP_7/CardSaveData/docs/csm_inf_sample.txt new file mode 100644 index 0000000..7c50204 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/docs/csm_inf_sample.txt @@ -0,0 +1,8 @@ +#TvłAgp +#csm_inf.txt ɉĉ + +#{̃VA\ +-p + +#eXgj[L +-t diff --git a/branches/1stNUP_7/CardSaveData/docs/import.txt b/branches/1stNUP_7/CardSaveData/docs/import.txt new file mode 100644 index 0000000..e94a4f3 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/docs/import.txt @@ -0,0 +1,27 @@ + +ړIF‚{̂̂݃C|[g + +JROMǂݍ + +SCj@c[p{̂̃VA[ȂǂRED֘A +RED)@Xg(csm_list)Ə(csm_sign)쐬 + + +C|[g菇 +E@XgASDCTRɍ +E@C|[gpAvJ[hN +E@LȖ{̂ȂC|[gj[\ + + +Openeelō쐬 +ɎSD[gɒu + +Xg̏ +C|[gƒVAeLXgŗ +--- +aaaaaaaa +bbbbbbbb +---- +{̗VAI[digit(lpg̐)͏Ȃ +digitmFꍇ̓Xg쐬ɂƂ +t@CTCY64K܂(VÂ݋LڂŁA悻4000) diff --git a/branches/1stNUP_7/CardSaveData/docs/option.txt b/branches/1stNUP_7/CardSaveData/docs/option.txt new file mode 100644 index 0000000..64a334f --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/docs/option.txt @@ -0,0 +1,10 @@ +C|[^̃IvVL + +cms_inf.txt̖OŃt@C쐬 +ȉ̋LqŃIvVLɂȂ + +-t: eXgj[ +@@@J[h̃Z[uɃeXgp^[݁xt@C + +-p: {̃VA\ + diff --git a/branches/1stNUP_7/CardSaveData/docs/マスタリング.txt b/branches/1stNUP_7/CardSaveData/docs/マスタリング.txt new file mode 100644 index 0000000..3009e14 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/docs/マスタリング.txt @@ -0,0 +1,10 @@ +ʎY@ł̓ɂ̓}X^OKv + +cia̓T[oF؁iOLSjK{ +OLS͑O擾烊}X^o[WグKv(2011/2) +(Ⴆ΁AO 1.0.0 Ȃ@1.0.1 ) +W[rsfŎw(Remasterversion) +}Ciƃ}CNOmakefile +MAKECIAFLAGS = -minor 0 -micro 1 +̏ꍇ *.0.1 (*rsfRemasterversion) + diff --git a/branches/1stNUP_7/CardSaveData/docs/操作説明.txt b/branches/1stNUP_7/CardSaveData/docs/操作説明.txt new file mode 100644 index 0000000..603c6ed --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/docs/操作説明.txt @@ -0,0 +1,21 @@ + +c[{(bodyfBNg) +삪oԂ̂ƂʂɃ{^\ +\ɂă^b`Őis܂ + +(obNAbvf[g) +擪ʂ L[ LEFT + X + + + + +SDɈȉL^čĂ +cms(cts)_list.txt .. {̃VA +cms(cts)_sign.dat .. +/imp/imp_list ɃTv + +Nɖ{̃VA`FbN +–{̂ł΃j[\A\ɂă{^ + +̓rhɎw肵ƃyǍg + diff --git a/branches/1stNUP_7/CardSaveData/docs/署名に関する覚え書.txt b/branches/1stNUP_7/CardSaveData/docs/署名に関する覚え書.txt new file mode 100644 index 0000000..484e487 --- /dev/null +++ b/branches/1stNUP_7/CardSaveData/docs/署名に関する覚え書.txt @@ -0,0 +1,34 @@ + +rhɑgݍ񂾌J̃yAƂȂvCx[ggďs + +o[WŌʂ +ύX̏ꍇło[Wς邱 + +Openssl.exe : cygwiñCXgAWinł +RSAArbg͂QOSŴ +SHA256̃_CWFXgɏ +Openssl0.9.6.k(r),1.0.0d쐬̏œmF + +(쐬) +openssl genrsa -out private_key.pem 2048 +openssl enc -d -base64 -in private_key.pem -out private_key.der +openssl rsa -pubout -inform DER -outform DER -in private_key.der -out public_key.der + +(1.0.0̏ꍇ) +openssl genpkey -out private_key.der -outform DER -algorithm rsa -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 +openssl rsa -pubout -inform DER -outform DER -in private_key.der -out public_key.der + +() +openssl dgst -sha256 -binary -keyform DER -sign private_key.der -out csm_sign.dat csm_list.txt + +vCx[g̃oCisvȂ +openssl genrsa -out private_key.pem 2048 +openssl rsa -pubout -outform DER -in private_key.pem -out public_key.der + +openssl dgst -sha256 -binary -sign private_key.pem -out csm_sign.dat csm_list.txt + +쐬pubC|[gAvomakeŎw +OBJECTS[] = + $`(ObjectFromBinary $(TARGET), ./Imp_list/Public_Key.der) + +XgvCx[gŏ쐬AXgƏC|[gSDǂ diff --git a/branches/1stNUP_7/ConsoleDataMigration/documents/CTR修理フロー_1stNUP.vsd b/branches/1stNUP_7/ConsoleDataMigration/documents/CTR修理フロー_1stNUP.vsd new file mode 100644 index 0000000..a3d6b89 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/documents/CTR修理フロー_1stNUP.vsd differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/documents/CTR本体データ移行ツール説明.doc b/branches/1stNUP_7/ConsoleDataMigration/documents/CTR本体データ移行ツール説明.doc new file mode 100644 index 0000000..9d1eb70 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/documents/CTR本体データ移行ツール説明.doc differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/documents/CTR用本体データ移行ツール仕様_20101221.ppt b/branches/1stNUP_7/ConsoleDataMigration/documents/CTR用本体データ移行ツール仕様_20101221.ppt new file mode 100644 index 0000000..e16207e Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/documents/CTR用本体データ移行ツール仕様_20101221.ppt differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/documents/Readme.txt b/branches/1stNUP_7/ConsoleDataMigration/documents/Readme.txt new file mode 100644 index 0000000..e325280 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/documents/Readme.txt @@ -0,0 +1,15 @@ +yrh‹z + +ESDK +Horizon 2_3 branch r38025 + +Ecygwin +Esubversion + +yrh̒Ӂz +J@EʎY@AESς邽߁A}X^Oprh +sources\common\Aes_define.h + +#define USE_PROD_KEY +Lɂ邱ƁB + diff --git a/branches/1stNUP_7/ConsoleDataMigration/documents/データ移行ツール1stNUPテスト.xls b/branches/1stNUP_7/ConsoleDataMigration/documents/データ移行ツール1stNUPテスト.xls new file mode 100644 index 0000000..ea70cbd Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/documents/データ移行ツール1stNUPテスト.xls differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/ConsoleBackup.bsf b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/ConsoleBackup.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/ConsoleBackup.bsf differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/ConsoleBackup.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/ConsoleBackup.cpp new file mode 100644 index 0000000..7f2b917 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/ConsoleBackup.cpp @@ -0,0 +1,293 @@ +/*---------------------------------------------------------------------------* + 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 "demo.h" + +#include +#include + +#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 "common_Types.h" +#include "VersionDetect.h" +#include "Util.h" +#include "ResFont.h" +#include "HardwareStateManager.h" + +// svnリビジョン埋め込み用 +#include "../../generated/ConsoleBackup/version.h" +#ifndef BACKUP_VERSION_NUM +#define BACKUP_VERSION_NUM 0 +#endif + +namespace { + +// グラフィックスに割り当てるメモリ +const size_t s_GxHeapSize = 0x800000; + +common::Util s_HwUtility; + +} // namespace + +extern "C" void nninitSetupDaemons(void) +{ +} + +namespace ConsoleBackup{ + + +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(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // cfg の初期化 + nn::cfg::CTR::init::Initialize(); + nn::cfg::CTR::system::Initialize(); + + // 時計設定用ptm初期化 + nn::ptm::CTR::InitializeForSystemMenu(); + + // ps の初期化 + nn::ps::Initialize(); + + // amの初期化 + nn::am::InitializeForSystemMenu(); + + // ヒープの確保 + common::InitializeHeap(); + + // RenderSystem の準備 + common::HeapManager gxHeapManager(s_GxHeapSize); + uptr heapForGx = reinterpret_cast(gxHeapManager.GetAddr()); + demo::RenderSystemDrawing renderSystem; + renderSystem.Initialize(heapForGx, s_GxHeapSize); + + // ResFontの初期化 + common::InitializeResFont(); + + // サウンドスレッドの起動 + common::InitializeSimplePlayer(); + + // ログ描画の初期化 + common::Logger::GetLoggerInstance()->Initialize(common::CONSOLE_WIDTH, common::CONSOLE_HEIGHT, + common::CONSOLE_MAX_LINE, &renderSystem); + + // RenderSystemを作ってからログが出せる + common::Logger::InitializeEjectThread(); + common::Logger::SetEjectHandler(OnSdEjected); + // 起動時に削除 + common::Logger::GetLoggerInstance()->ClearSdLog(); + + COMMON_LOGGER("\n"); + COMMON_LOGGER("CTR Console Backup start\n"); + + // ボタン入力 + nn::hid::PadReader s_PadReader; + nn::hid::PadStatus padStatus; + + // データの準備 + s_HwUtility.InitializeForBackup(); + common::HardwareStateManager manager(s_HwUtility); + + // 情報出力 + COMMON_LOGGER("CTR Console Backup %s Rev.%s\n", __DATE__, BACKUP_VERSION_NUM); + COMMON_LOGGER("System Ver. %d.%d.%d-%d\n", + s_HwUtility.GetCupMajorVersion(), + s_HwUtility.GetCupMinorVersion(), + s_HwUtility.GetCupMicroVersion(), + s_HwUtility.GetNupVersion()); + COMMON_LOGGER("System Region %s\n", s_HwUtility.GetRegionCodeA3()); + COMMON_LOGGER("Serial Number %s\n", s_HwUtility.GetSerialNumber()); + COMMON_LOGGER("Device ID %llu\n", s_HwUtility.GetInfraDeviceId()); + COMMON_LOGGER("MAC Address %s\n", s_HwUtility.GetMacAddress()); + + 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(); + } + + + // 情報更新 + // ACアダプタ + std::string adapterState; + if(manager.IsAdapterConnected()) + { + adapterState += ::std::string("Connected"); + } + else + { + adapterState += ::std::string("Not Connected"); + } + + // 操作用メッセージ + // 進捗確認メッセージを兼ねる? + ::std::vector operationMessage; + + ControlState(manager, operationMessage, nextStep, continueBackup); + + nn::util::FloatColor titleColor; + + titleColor.r = 0.3f; + titleColor.g = 0.f; + titleColor.b = 0.2f; + + // 上画面表示 + common::DrawSystemState("CTR Console Backup", + renderSystem, + titleColor, + flip, + adapterState, + BACKUP_VERSION_NUM, + s_HwUtility.GetCupMajorVersion(), + s_HwUtility.GetCupMinorVersion(), + s_HwUtility.GetCupMicroVersion(), + s_HwUtility.GetNupVersion(), + s_HwUtility.GetBatteryRemain(), + s_HwUtility.GetInfraDeviceId(), + s_HwUtility.GetFriendcode(), + GetProgress(), + IsBackupFailed(), + IsBackupSucceeded(), + s_HwUtility.GetMacAddress(), + operationMessage, + s_HwUtility.GetRegion(), + s_HwUtility.GetSerialNumber(), + s_HwUtility.HasReadFriendCode() + ); + + renderSystem.SwapBuffers(); + + // デフォルトで下画面に描画するもの + renderSystem.SetRenderTarget(common::GetRenderTarget(NN_GX_DISPLAY1, flip)); + if(IsBackupSucceeded()) + { + renderSystem.SetClearColor(common::GetRenderTarget(NN_GX_DISPLAY1, flip), SUCCESS_COLOR); + } + if(IsBackupFailed()) + { + renderSystem.SetClearColor(common::GetRenderTarget(NN_GX_DISPLAY1, flip), FAIL_COLOR); + } + renderSystem.Clear(); + renderSystem.SetColor(1.f, 1.f, 1.f); + + common::Logger::GetLoggerInstance()->DrawConsole(); + renderSystem.SwapBuffers(); + + + 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); + renderSystem.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/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/ConsoleBackup.rsf b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/ConsoleBackup.rsf new file mode 100644 index 0000000..2ab5f97 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/ConsoleBackup.rsf @@ -0,0 +1,44 @@ +BasicInfo: + Title : ConsoleBackup + ProductCode: CTR-P-22TA + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xf8021 + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 0x4000 + Dependency : + - codec + - hid + - gsp + - nwm + +AccessControlInfo: + Priority : 16 + DisableDebug : true + + FileSystemAccess: + - DirectSdmc + - Debug + - Core + - CategoryFileSystemTool + + IoAccessControl: + - FsMountCardSpi + - FsMountNand + - FsMountTwln + +Option: + FreeProductCode: true + +CardInfo: + CardDevice: None + +Rom: + # ROM に含めるファイルシステムのルートパスを指定します。 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Controller.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Controller.cpp new file mode 100644 index 0000000..9622df4 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Controller.cpp @@ -0,0 +1,384 @@ +/*---------------------------------------------------------------------------* + 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 "Exporter.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" + +#include + +namespace ConsoleBackup +{ + +namespace +{ + +typedef enum BackupState +{ + STARTUP, // 初期値 + EXPORT_TWL_NAND, // TWLセーブデータ領域の吸出し中 + EXPORT_TWL_SOUND, // TWLサウンド領域の吸出し中 + EXPORT_TWL_PHOTO, // TWL写真領域の吸出し中 + EXPORT_CTR_NAND, // 吸出し中 + DELETE_NIM, // nimのシステムセーブデータ削除 + DONE, // 吸出し完了 + FINISHED, // SDカード抜き完了 + FAIL // 失敗 +} BackupState; + + +// APSettingの書式が無い警告サウンドを鳴らしたかどうか +bool s_ExistAPSettingAnnotation = false; +// SDに書き込みできない警告サウンドを鳴らしたかどうか +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 NeedsAcAdapter(common::HardwareStateManager& manager) +{ + return manager.IsBatteryLower() && !manager.IsAdapterConnected(); +} + +void ControlState(common::HardwareStateManager& manager, ::std::vector& operationMessage, bool& nextStep, + bool& continueBackup) +{ + // 状態遷移Controller + switch (s_BackupState) + { + + // 起動時 + case STARTUP: + { + bool error = false; + // 完全性検証SEEDを読めるか? + if (manager.CanReadIvs()) + { + // SDカードが挿入されているか? + if (nn::fs::IsSdmcInserted()) + { + // SDカードに書き込みできるか? + 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) + { + // シリアルナンバーを読み取れるか? + if (!manager.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 SDCI!!")); + } + + // ACアダプタが必要か? + if (NeedsAcAdapter(manager)) + { + error = true; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // エラーが無ければ進行用メッセージ表示 + 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_NAND; + } + } + break; + + + // TWLセーブデータ領域の吸出し中 + case EXPORT_TWL_NAND: + { + static bool init = true; + if(init) + { + // コンテキストを初期化する + InitializeFileListContext(); + + // データを書き込む + if(ExportTwlSaveData().IsFailure()) + { + s_BackupState = FAIL; + break; + } + init = false; + } + + // 処理が完了した + if (IsExportThreadFinished()) + { + FinalizeExportThread(); + if(IsExportSucceeded()) + { + s_BackupState = EXPORT_TWL_SOUND; + } + else + { + s_BackupState = FAIL; + } + + } + } + break; + + // TWLサウンド領域の吸出し中 + case EXPORT_TWL_SOUND: + { + static bool init = true; + if(init) + { + // データを書き込む + ExportTwlSoundData(); + init = false; + } + + // 処理が完了した + if (IsExportThreadFinished()) + { + FinalizeExportThread(); + if(IsExportSucceeded()) + { + s_BackupState = EXPORT_TWL_PHOTO; + } + else + { + s_BackupState = FAIL; + } + } + } + break; + + // TWL写真領域の吸出し中 + case EXPORT_TWL_PHOTO: + { + static bool init = true; + if(init) + { + // データを書き込む + ExportTwlPhotoData(); + init = false; + } + + // 処理が完了した + if (IsExportThreadFinished()) + { + FinalizeExportThread(); + if(IsExportSucceeded()) + { + s_BackupState = EXPORT_CTR_NAND; + } + else + { + s_BackupState = FAIL; + } + } + } + break; + + // 吸出し中 + case EXPORT_CTR_NAND: + { + continueBackup = true; + + // ACアダプタが必要か? + if (NeedsAcAdapter(manager)) + { + continueBackup = false; + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // データを書き込む + if (!ExportData(manager)) + { + s_BackupState = FAIL; + } + else + { + // 処理が完了した + if (continueBackup && IsExportThreadFinished()) + { + FinalizeExportThread(); + if (IsExportSucceeded()) + { + COMMON_LOGGER("Export NAND Data Finished.\n"); + + if (GetProgress() > 99) + { + s_BackupState = DELETE_NIM; + } + else + { + s_BackupState = FAIL; + } + } + else + { + s_BackupState = FAIL; + } + } + + } + } + break; + + // nimのシステムセーブデータ削除 + case DELETE_NIM: + { + if(DeleteNimSaveData()) + { + s_BackupState = DONE; + } + else + { + s_BackupState = FAIL; + } + + } + 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 if(s_BackupState != FAIL) + { + 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/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Controller.h b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Controller.h new file mode 100644 index 0000000..b60d065 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Controller.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------* + 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 "HardwareStateManager.h" + +namespace ConsoleBackup +{ + +// 状態遷移を管理する +// manager ハードウェア情報を取得するためのラッパ +// operationMessage 操作情報として表示したい文字列 +// nextStep 次の状態に遷移してもよいかどうか +// continueBackup 処理を続けてもよいかどうか +void ControlState(common::HardwareStateManager& manager, ::std::vector& operationMessage, bool& nextStep, + bool& continueBackup); + +// バックアップ処理中かどうか +bool InProgress(); + +// バックアップが完了したかどうか +bool IsBackupSucceeded(); + +// バックアップが失敗したかどうか +bool IsBackupFailed(); + +// SDカードが抜き出されたときに実行したい関数 +void OnSdEjected(); + +// 状態を初期化する +void InitializeState(); + +} + +#endif /* CONTOROLLER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Exporter.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Exporter.cpp new file mode 100644 index 0000000..6d0834e --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Exporter.cpp @@ -0,0 +1,987 @@ +/*---------------------------------------------------------------------------* + 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 +#include // cfg:norの初期化に必要 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Exporter.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "HeapManager.h" +#include "SdReaderWriter.h" +#include "FileName.h" +#include "FileTransfer.h" +#include "common_Types.h" +#include "Aes_define.h" +#include "VersionDetect.h" +#include "Util.h" + +namespace ConsoleBackup +{ + +namespace +{ + +common::NtrNorData s_NtrNorData; +common::CfgCountryLanguage s_CountryLanguage; + +const size_t EXPORT_THREAD_STACK_SIZE = 0x4000; +nn::os::Thread s_ExportThread; +nn::os::StackBuffer s_ExportThreadStack; +bool s_IsExportSucceeded; + +wchar_t s_RootName[256]; + +nn::crypto::Sha256Context s_FileListContext; + +} + +void AddCmac(nn::fs::FileOutputStream* file, nn::crypto::Sha256Context* context); + +nn::Result 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; + + result = common::SdMountManager::Mount(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = dir.TryInitialize(currentDirectory.c_str()); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + nn::fs::DirectoryEntry entry; + s32 numEntry; + for (;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + if (numEntry == 0) + { + // ルートディレクトリを閉じる + dir.Finalize(); + + // ルートディレクトリの子を開く + for (entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++) + { + // ディレクトリなら削除する + 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_RETURN_RESULT_IF_FAILED(result); + + } + // ファイルならログとAP設定以外は削除する + 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_RETURN_RESULT_IF_FAILED(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); + } + } + } + + result = common::SdMountManager::Unmount(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + return nn::ResultSuccess(); +} + +nn::Result WriteTwlTitleList(std::vector& programIdList) +{ + nn::Result result; + COMMON_LOGGER("Export TwlTitle List.\n"); + + size_t heapSize = common::GetAllocatableSize(); + common::HeapManager manager(heapSize); + char* titleListBuf = reinterpret_cast (manager.GetAddr()); + + size_t writeSize = 0; + if (titleListBuf != NULL) + { + for (std::vector::iterator it = programIdList.begin(); it != programIdList.end(); it++) + { + nn::nstd::TSNPrintf(titleListBuf + writeSize, heapSize - writeSize, "%s\n", common::GetCharStr(it->c_str())); + NN_LOG("%ls\n", it->c_str()); + writeSize += it->size() + sizeof('\n'); + } + + common::SdReaderWriter sdWriter; + return sdWriter.WriteBufWithCmac(common::TWL_TITLELIST_PATHNAME, titleListBuf, writeSize); + } + else + { + return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } +} + + +nn::Result WriteRegionData() +{ + COMMON_LOGGER("Export Region Data.\n"); + + nn::cfg::CTR::CfgRegionCode region; + region = nn::cfg::CTR::GetRegion(); + + common::SdReaderWriter sdWriter; + return sdWriter.WriteBufWithCmac(common::REGION_DATA_PATHNAME, ®ion, sizeof(nn::cfg::CTR::CfgRegionCode)); +} + +nn::Result 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(); + + common::SdReaderWriter sdWriter; + return sdWriter.WriteBufWithCmac(common::COUNTRY_SETTING_PATHNAME, &s_CountryLanguage, sizeof(s_CountryLanguage)); + } + + return nn::ResultSuccess(); +} + +nn::Result 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_RETURN_RESULT_IF_FAILED(result); + + // TWL WiFi設定 + result = nn::cfg::nor::CTR::ReadTwlWifiSetting(0, s_NtrNorData.TwlWiFiSetting, common::TWL_WIFI_SETTING_SIZE); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + // NTR WiFi設定 + result = nn::cfg::nor::CTR::ReadNtrWifiSetting(0, s_NtrNorData.NtrWiFiSetting, common::NTR_WIFI_SETTING_SIZE); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + common::SdReaderWriter sdWriter; + return sdWriter.WriteBufWithCmac(common::NOR_PATHNAME, &s_NtrNorData, sizeof(common::NtrNorData)); +} + +nn::Result WriteSerialNumber(common::HardwareStateManager& manager) +{ + COMMON_LOGGER("Export Serial Number.\n"); + + u8* serial; + size_t size; + manager.GetSerialNumber(&serial, &size); + + common::SdReaderWriter sdWriter; + return sdWriter.WriteBufWithCmac(common::SERIAL_PATHNAME, serial, size); +} + +nn::Result WriteDeviceId(common::HardwareStateManager& manager) +{ + COMMON_LOGGER("Export Device ID.\n"); + + bit32 deviceId = manager.GetDeviceId(); + + common::SdReaderWriter sdWriter; + return sdWriter.WriteBufWithCmac(common::DEVICE_ID_PATHNAME, &deviceId, sizeof(deviceId)); +} + +nn::Result WriteIvs(common::HardwareStateManager& manager) +{ + COMMON_LOGGER("Export SDCI.\n"); + + void* ivs; + size_t size; + manager.GetIvs(&ivs, &size); + + void* enc; + nn::Result result; + common::HeapManager ivsHeap(size); + enc = ivsHeap.GetAddr(); + 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); + + common::SdReaderWriter sdWriter; + return sdWriter.WriteBufWithCmac(common::IVS_PATHNAME, enc, size); + } + else + { + return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } +} + +void CreateTwlDirectory(enum common::TWL_PATH_INDEX path) +{ + NN_ASSERT(path < common::TWL_PATHNAME_MAX); + + common::SdReaderWriter sdWriter; + sdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + + std::wstring(common::SD_TWL_ROOTNAME_TABLE[path])).c_str()); +} + +bool ListTwlSaveData(std::wstring currentDirectory, std::vector* list) +{ + nn::fs::Directory dir; + nn::fs::DirectoryEntry entry; + s32 numEntry; + + nn::Result result = dir.TryInitialize(currentDirectory.c_str()); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + for (;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + if (numEntry == 0) + { + break; + } + else + { + common::SavePathInfo pathInfo; + pathInfo.name = currentDirectory + std::wstring(L"/") + std::wstring(entry.entryName); + pathInfo.isDirectory = false; + list->push_back(pathInfo); + } + } + + return true; +} + +void AddCurrentProgramIdPath(std::vector* programIdList, std::wstring currentDir) +{ + std::wstring currentPath(currentDir); + std::wstring token(common::NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH); + + std::wstring::size_type pos; + pos = currentPath.find(token); + if(pos != std::wstring::npos) + { + std::wstring subStr = currentPath.substr(token.size()); + + std::wstring slash(L"/"); + pos = subStr.find(slash); + while(pos != std::wstring::npos) + { + subStr.erase(pos, slash.size()); + pos = subStr.find(slash); + } + + std::wstring ctrProgramIdHi(L"00048"); + subStr.replace(0, ctrProgramIdHi.size(), ctrProgramIdHi); + + programIdList->push_back(subStr); + } + else + { + NN_LOG("Can't find %ls\n", common::NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH); + } + +} + +void AddCurrentDirectory(std::vector* list, std::wstring currentDir, wchar_t* currentEntry) +{ + common::SavePathInfo pathInfo; + + pathInfo.name = currentDir + std::wstring(L"/") + std::wstring(currentEntry) + std::wstring(L"/"); + pathInfo.isDirectory = true; + list->push_back(pathInfo); +} + +// TWLセーブデータが存在するディレクトリの一覧をlistに追加する +// return: dataディレクトリが存在するかどうか +bool ListTwlSaveDataDirectory(std::wstring currentDirectory, u32 level, std::vector* list, + std::vector* programIdList) +{ + nn::fs::FileInputStream fis; + nn::fs::Directory dir; + nn::Result result; + std::vector entryList; //カレントディレクトリのエントリ一覧を格納 + std::vector::iterator entryIndex; + + // level 0 1 2 + // twln:/title/00030005/484e4441/data/ + const u8 TWL_SAVEDATA_DIRECTORY_LEVEL = 2; // data ディレクトリまでの階層 + const wchar_t* const TWL_SAVEDATA_DIRECTORY_NAME = L"data"; + + result = dir.TryInitialize(currentDirectory.c_str()); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + nn::fs::DirectoryEntry entry; + s32 numEntry; + for (;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + if (numEntry == 0) + { + dir.Finalize(); + + bool hasDataDirectory = false; + for (entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++) + { + // レベル2未満のディレクトリなら再帰的に開く + if (level < TWL_SAVEDATA_DIRECTORY_LEVEL) + { + if (entryIndex->attributes.isDirectory) + { + if (!ListTwlSaveDataDirectory( + currentDirectory + std::wstring(L"/") + std::wstring(entryIndex->entryName), level + 1, + list, programIdList)) + { + hasDataDirectory |= false; + } + else + { + NN_LOG("%ls/%ls has data directory.\n", currentDirectory.c_str(), entryIndex->entryName); + AddCurrentDirectory(list, currentDirectory, entryIndex->entryName); + hasDataDirectory |= true; + } + } + } + // レベル2のディレクトリなら data かどうかチェック + else if (level == TWL_SAVEDATA_DIRECTORY_LEVEL && entryIndex->attributes.isDirectory) + { + if (std::wcscmp(entryIndex->entryName, TWL_SAVEDATA_DIRECTORY_NAME) == 0) + { + // ファイル一覧を取得する + if (!ListTwlSaveData( + currentDirectory + std::wstring(L"/") + std::wstring(entryIndex->entryName), list)) + { + hasDataDirectory |= false; + } + + NN_LOG("%ls/%ls has data directory.\n", currentDirectory.c_str(), entryIndex->entryName); + AddCurrentDirectory(list, currentDirectory, entryIndex->entryName); + AddCurrentProgramIdPath(programIdList, currentDirectory); + hasDataDirectory |= true; + } + } + else + { + return false; + } + } + + return hasDataDirectory; + } + else + { + // vectorに保存する + entryList.push_back(entry); + } + } +} + + +void WriteTwlData(enum common::TWL_PATH_INDEX path) +{ + NN_ASSERT(path < common::TWL_PATHNAME_MAX); + + nn::Result result; + s_IsExportSucceeded = true; + + result = nn::fs::MountSpecialArchive(common::TWL_ARCHIVE_NAME_TABLE[path], common::TWL_FS_ARCHIVE_KIND[path]); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + result = common::SdMountManager::Mount(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + u32 fileNum = 0; + s64 fileSize = 0; + result = common::CalculateFileNum(::std::wstring(common::NAND_TWL_ROOT_PATHNAME_WITH_SLASH_TABLE[path]), fileNum, fileSize); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + NN_LOG("File Number = %d\n", fileNum); + NN_LOG("File Size = %d\n", fileSize); + // 進捗表示用 + common::InitializeTransferProgress(fileSize); + + size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2); + NN_LOG("AllocatableSize = %d\n", bufSize); + + common::HeapManager writeHeap(bufSize, AES_BLOCK_SIZE * 2); + void* buf = writeHeap.GetAddr(); + if (buf != NULL) + { + nn::fs::FileOutputStream list; + result = list.TryInitialize(common::FILE_LIST_PATHNAME, true); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if (result.IsSuccess()) + { + result = list.TryGetSize(&fileSize); + if (result.IsSuccess()) + { + // 末尾に移動 + result = list.TrySetPosition(fileSize); + if (result.IsSuccess()) + { + wchar_t archiveName[nn::fs::MAX_FILE_PATH_LENGTH]; + ::std::mbstowcs(archiveName, common::TWL_ARCHIVE_NAME_TABLE[path], + std::strlen(common::TWL_ARCHIVE_NAME_TABLE[path]) + 1); + std::wstring archiveString(archiveName); + if(!common::CopyDirectory( + NULL, + (archiveString + ::std::wstring(L"/")).c_str(), + (common::SDMC_ROOT_DIRECTORY_PATH + ::std::wstring(common::SD_TWL_ROOTNAME_TABLE[path])).c_str(), + buf, bufSize, true, &list, &s_FileListContext)) + { + s_IsExportSucceeded = false; + return; + } + } + + list.TryFlush(); + list.Finalize(); + } + } + else + { + s_IsExportSucceeded = false; + } + } + + common::SdMountManager::Unmount(); + nn::fs::Unmount(common::TWL_ARCHIVE_NAME_TABLE[path]); +} + +nn::Result CalculateTwlSaveData(std::vector* fileList, s64* fileSize) +{ + NN_NULL_ASSERT(fileList); + NN_NULL_ASSERT(fileSize); + + *fileSize = 0; + nn::Result result = nn::ResultSuccess(); + + for (std::vector::iterator it = fileList->begin(); it != fileList->end(); it++) + { + if(!it->isDirectory) + { + nn::fs::FileInputStream file; + result = file.TryInitialize(it->name.c_str()); + if(result.IsSuccess()) + { + s64 size; + result = file.TryGetSize(&size); + if(result.IsSuccess()) + { + *fileSize += size; + } + } + } + } + + return result; + +} + +void WriteTwlSaveData() +{ + nn::Result result; + s_IsExportSucceeded = true; + std::vector fileList; + std::vector programIdList; + + COMMON_LOGGER("Export Twl Save Data.\n"); + + // ディレクトリ作成 + common::SdReaderWriter sdWriter; + result = sdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + + std::wstring(common::SD_SAVEDATA_TWL_ROOT_NAME)).c_str()); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + // セーブデータを含むディレクトリ一覧を生成 + result = nn::fs::MountSpecialArchive(common::NAND_TWL_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_TWL_NAND); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + if(!ListTwlSaveDataDirectory(std::wstring(common::NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH), 0, &fileList, & programIdList)) + { + NN_LOG("No Twl Savedata\n"); + s_IsExportSucceeded = true; + return; + } + + NN_LOG("listup Twl Savedata Directory\n"); + for (std::vector::reverse_iterator it = fileList.rbegin(); it != fileList.rend(); it++) + { + NN_LOG("%ls\n", it->name.c_str()); + } + + result = WriteTwlTitleList(programIdList); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + // 合計サイズ取得 + s64 fileSize; + result = CalculateTwlSaveData(&fileList, &fileSize); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + common::InitializeTransferProgress(fileSize); + + NN_LOG("\n"); + // SDに書き出し + result = common::SdMountManager::Mount(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2); + NN_LOG("AllocatableSize = %d\n", bufSize); + + common::HeapManager writeHeap(bufSize, AES_BLOCK_SIZE * 2); + void* buf = writeHeap.GetAddr(); + if (buf != NULL) + { + nn::fs::FileOutputStream list; + result = list.TryInitialize(common::FILE_LIST_PATHNAME, true); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + result = list.TryGetSize(&fileSize); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + // 末尾に移動 + result = list.TrySetPosition(fileSize); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + + wchar_t archiveName[nn::fs::MAX_FILE_PATH_LENGTH]; + ::std::mbstowcs(archiveName, common::NAND_TWL_ARCHIVE_NAME, std::strlen(common::NAND_TWL_ARCHIVE_NAME) + 1); + std::wstring archiveString(archiveName); + + for (std::vector::reverse_iterator it = fileList.rbegin(); it != fileList.rend(); it++) + { + // twln:/title/をsdmc:/CTR_Console_Repair/TWLBackup/に置換 + std::wstring toPath(it->name.c_str()); + toPath.replace(0, std::wcslen(common::NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH) + 1, + std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + std::wstring(common::SD_SAVEDATA_TWL_ROOT_NAME)); + + if (it->isDirectory) + { + if(!common::ExportTwlSaveDirectory(toPath.c_str(), &list, &s_FileListContext)) + { + s_IsExportSucceeded = false; + return; + } + } + else + { + if(!common::ExportTwlSaveFile(it->name.c_str(), toPath.c_str(), buf, bufSize, &list, &s_FileListContext)) + { + s_IsExportSucceeded = false; + return; + } + } + } + result = list.TryFlush(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + list.Finalize(); + } + + result = common::SdMountManager::Unmount(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); + result = nn::fs::Unmount(common::NAND_TWL_ARCHIVE_NAME); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsExportSucceeded); +} + +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 InitializeFileListContext() +{ + nn::crypto::Initialize(); + s_FileListContext.Initialize(); +} + +nn::Result ExportTwlSaveData() +{ + // 不要なデータを削除する + COMMON_LOGGER_RETURN_RESULT_IF_FAILED( + DeleteTrash((std::wstring(common::LOG_ROOT_DIRECTORY_PATH) + std::wstring(L"/")).c_str())); + + s_ExportThread.Start(WriteTwlSaveData, s_ExportThreadStack); + + return nn::ResultSuccess(); +} + +void ExportTwlPhotoData() +{ + s_ExportThread.Start(WriteTwlPhotoData, s_ExportThreadStack); +} + +void ExportTwlSoundData() +{ + s_ExportThread.Start(WriteTwlSoundData, s_ExportThreadStack); +} + + +nn::Result WriteMcuRtcData(common::HardwareStateManager& manager) +{ + COMMON_LOGGER("Export RTC Data.\n"); + nn::Result result; + nn::Handle handle = manager.GetMcuHandle(); + + if(handle.IsValid()) + { + nn::mcu::CTR::HwCheck mcu(handle); + + nn::mcu::CTR::RtcData rtc; + const u8 RETRY = 10; + for (u8 i = 0; i < RETRY; i++) + { + result = mcu.GetRtcAll(&rtc); + if (result.IsSuccess()) + { + 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::SdReaderWriter sdWriter; + return sdWriter.WriteBufWithCmac(common::MCU_RTC_PATHNAME, &rtc, sizeof(rtc)); + } + nn::os::Thread::Sleep( + nn::fnd::TimeSpan::FromMilliSeconds( + nn::os::Tick::GetSystemCurrent().ToTimeSpan().GetMilliSeconds() % 100)); + } + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + } + else + { + NN_LOG("invalid handle\n"); + return nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_INVALID_STATE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_INVALID_HANDLE); + } + + return nn::ResultSuccess(); +} + +void ExportThreadFunc() +{ + nn::Result result; + s_IsExportSucceeded = true; + + 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::GetAllocatableSize(AES_BLOCK_SIZE * 2); + NN_LOG("AllocatableSize = %d\n", bufSize); + + common::HeapManager writeHeap(bufSize, AES_BLOCK_SIZE * 2); + void* buf = writeHeap.GetAddr(); + if (buf != NULL) + { + nn::fs::FileOutputStream list; + result = list.TryInitialize(common::FILE_LIST_PATHNAME, true); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if (result.IsSuccess()) + { + s64 fileSize; + result = list.TryGetSize(&fileSize); + if (result.IsSuccess()) + { + // 末尾に移動 + result = list.TrySetPosition(fileSize); + if (result.IsSuccess()) + { + if(!common::CopyDirectory( + NULL, + ::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH).c_str(), + (std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_SAVEDATA_ROOT_NAME)).c_str(), buf, bufSize, true, &list, + &s_FileListContext)) + { + s_IsExportSucceeded = false; + return; + } + + AddCmac(&list, &s_FileListContext); + list.TryFlush(); + list.Finalize(); + } + } + } + } + + common::SdMountManager::Unmount(); + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + NN_LOG("Export Thread Finalize\n"); +} + +nn::Result WriteSaveData(::std::string& sysSaveRoot) +{ + // NANDからSDカードに書き出し + nn::Result result; + + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + u32 fileNum = 0; + s64 fileSize = 0; + result = common::CalculateFileNum(::std::wstring(common::NAND_DATA_ROOT_PATHNAME_WITH_SLASH), fileNum, fileSize); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + NN_LOG("File Number = %d\n", fileNum); + NN_LOG("File Size = %d\n", fileSize); + // 進捗表示用 + common::InitializeTransferProgress(fileSize); + + ::std::mbstowcs(s_RootName, sysSaveRoot.c_str(), 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()); + + // セーブデータディレクトリ以下のデータをSDカードにコピー + // コピー用ディレクトリ作成 + common::SdReaderWriter sdWriter; + result = sdWriter.CreateDirectory((::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_SAVEDATA_ROOT_NAME)).c_str()); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + COMMON_LOGGER("Export NAND Data Start...\n"); + + // SDにコピーするためのスレッドの作成 + s_ExportThread.Start(ExportThreadFunc, s_ExportThreadStack); + + return result; +} + +void FinalizeExportThread() +{ + s_ExportThread.Join(); + s_ExportThread.Finalize(); +} + +nn::Result WriteVersionData(common::HardwareStateManager& manager) +{ + COMMON_LOGGER("Export Version Data.\n"); + + common::VerDef versionData; + manager.GetVersionData(&versionData); + + common::SdReaderWriter sdWriter; + return sdWriter.WriteBufWithCmac(common::VERSION_DATA_PATHNAME, &versionData, sizeof(common::VerDef)); +} + +bool 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); + + result = common::SdMountManager::Mount(); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + NN_LOG("%ls\n", nimSaveDataPath.c_str()); + result = nn::fs::TryDeleteDirectoryRecursively(nimSaveDataPath.c_str()); + if (result.IsFailure() && !nn::fs::ResultNotFound::Includes(result)) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + return false; + } + + result = common::SdMountManager::Unmount(); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + return true; +} + +void AddShutDownPtmEvent() +{ + nn::pl::CTR::NotifyPlayEvent(nn::pl::CTR::EVENTTYPE_TERMINATE, nn::CTR::INVALID_PROGRAM_ID, + nn::fnd::DateTime::GetNow()); +} + +bool ExportData(common::HardwareStateManager& manager) +{ + static bool init = true; + + if (init) + { + nn::Result result; + + // リージョンデータをSDに書き込む + result = WriteRegionData(); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // 国データと言語データをSDに書き込む + result = WriteCountryLanguageData(); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // NORデータをSDカードに書き込む + result = WriteNorData(); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // シリアルナンバーをSDカードに書き込む + result = WriteSerialNumber(manager); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // デバイスIDをSDカードに書き込む + result = WriteDeviceId(manager); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // 完全性検証SEEDをSDカードに書き込む + result = WriteIvs(manager); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // 電源断の履歴をptmに追加する + AddShutDownPtmEvent(); + + // RTCをSDに書き出す + result = WriteMcuRtcData(manager); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // バージョン情報をSDに書き出す + result = WriteVersionData(manager); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + ::std::string systemSaveRoot; + void* ivs; + size_t size; + manager.GetIvs(&ivs, &size); + // IVSからセーブデータディレクトリ名を計算 + common::Util::GetSaveDataDirectoryRoot(systemSaveRoot, ivs, size); + + // NANDのセーブデータをSDに書き出す + result = WriteSaveData(systemSaveRoot); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + init = false; + } + + return true; +} + +u32 GetProgress() +{ + return common::GetProgress(); +} + +bool IsExportThreadFinished() +{ + return s_ExportThread.IsValid() && !s_ExportThread.IsAlive(); +} + +bool IsExportSucceeded() +{ + return s_IsExportSucceeded; +} + +//!@ brief ファイルにSHA256から計算したAES-CMACを付加します +//!@ param[in] file CMACを付加したいInitialize済みのファイル +//!@ param[in] context CMAC計算元のSHA256コンテキスト +void AddCmac(nn::fs::FileOutputStream* file, nn::crypto::Sha256Context* context) +{ + nn::Result result; + + 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); + + s32 writeSize; + result = file->TryWrite(&writeSize, cmac, sizeof(cmac), false); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Exporter.h b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Exporter.h new file mode 100644 index 0000000..8f2149d --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/Exporter.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------------* + 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 +#include "HardwareStateManager.h" + +namespace ConsoleBackup +{ + +// 出力ファイルリストのコンテキストを初期化する。出力ファイルリストを +// 生成する前に必ず呼び出す必要がある +void InitializeFileListContext(); + +// 新たにスレッドを起動して、DSiWareのセーブデータをSDカードに出力する +nn::Result ExportTwlSaveData(); + +// 新たにスレッドを起動して、TWL写真領域のデータをSDカードに出力する +void ExportTwlPhotoData(); + +// 新たにスレッドを起動して、TWLサウンド領域のデータをSDカードに出力する +void ExportTwlSoundData(); + +// 本体固有情報をSDカードに出力する +// 新たにスレッドを起動して、CTR領域のセーブデータをSDカードに出力する +bool ExportData(common::HardwareStateManager& manager); + +// NIMのセーブデータをSDカードから削除する +bool DeleteNimSaveData(); + +// 出力スレッドの進捗を返す +u32 GetProgress(); + +// 出力スレッドが終了したかどうか +bool IsExportThreadFinished(); + +// 出力スレッドを終了する +void FinalizeExportThread(); + +// 出力が成功したかどうか +bool IsExportSucceeded(); + +} + +#endif /* EXPORTER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/OMakefile new file mode 100644 index 0000000..88cdf18 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/OMakefile @@ -0,0 +1,79 @@ +#!/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.* +CTR_APPTYPE = CARD + +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/Util.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/VersionDetect.cpp + ../common/ResFont.cpp + ../common/HardwareStateManager.cpp + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = ../common/romfiles + +SHADER_BIN = nnfont_RectDrawerShader.shbin +SHADER_PATH = $(ROMFS_ROOT)/$(SHADER_BIN) + +ROMFS_DEPENDENCIES = $(SHADER_PATH) + +LIBS += libnn_cfg \ + libnn_crypto \ + libnn_mcu \ + libnn_i2c \ + libnn_ps \ + lib_demo \ + libnn_nwm \ + libnn_friends \ + libnn_nim \ + libnn_am \ + +INSTALL_SDK_TOOL = true + +ROM_SPEC_FILE = $(TARGET_PROGRAM).rsf +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/RepairTool.desc + +include $(ROOT_OMAKE)/modulerules + +VERSION_H = $(file ../../generated/$(TARGET_PROGRAM)/version.h) + +$(VERSION_H): $(SOURCES) + section + bash genversion.sh + +RequireSetup($(VERSION_H)) +build: $(VERSION_H) $(DEFAULT_TARGETS) diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/model.cbmd b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/model.cbmd differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/sound.cbsd b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/sound.cbsd differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/unknown24x24.ctpk b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +888yyYyYyyyYyyYyyyyYyYy8 \ No newline at end of file diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/unknown48x48.ctpk b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +Y8888ƺ8888YYyyYYޚ޺yY8YyYYޚyY8ޚ8 \ No newline at end of file diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/genversion.sh b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleBackup/genversion.sh new file mode 100755 index 0000000..74e3c79 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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'`\"" > ../generated/ConsoleBackup/version.h diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/ConsoleRestore.bsf b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/ConsoleRestore.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/ConsoleRestore.bsf differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/ConsoleRestore.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/ConsoleRestore.cpp new file mode 100644 index 0000000..6b4d2cc --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/ConsoleRestore.cpp @@ -0,0 +1,356 @@ +/*---------------------------------------------------------------------------* + 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 "demo.h" + +#include +#include + +#include "DrawSystemState.h" +#include "Controller.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "HeapManager.h" +#include "VersionDetect.h" +#include "Util.h" +#include "ResFont.h" +#include "HardwareStateManager.h" + +// svnリビジョン埋め込み用 +#include "../../generated/ConsoleRestore/version.h" +#ifndef RESTORE_VERSION_NUM +#define RESOTRE_VERSION_NUM 0 +#endif + +namespace { + +// グラフィックスに割り当てるメモリ +const size_t s_GxHeapSize = 0x800000; + +common::Util s_HwUtility; + +demo::RenderSystemDrawing s_RenderSystem; + +} // namespace + +namespace ConsoleRestore{ + +void FinalizeAll() +{ + common::Logger::GetLoggerInstance()->Finalize(); + // アンマウント + nn::fs::Unmount("nand:"); + nn::fs::Unmount("sdmc:"); + s_RenderSystem.Finalize(); + + s_HwUtility.FinalizeForRestore(); + 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(); +} + +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); + + // デーモンの自律動作を停止 + 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(); + + // amの初期化 + nn::am::InitializeForSystemMenu(); + + // ヒープの確保 + common::InitializeHeap(); + + // RenderSystem の準備 + common::HeapManager gxHeap(s_GxHeapSize); + uptr heapForGx = reinterpret_cast(gxHeap.GetAddr()); + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + + // ResFontの初期化 + common::InitializeResFont(); + + // サウンドスレッドの起動 + common::InitializeSimplePlayer(); + + // ログ描画の初期化 + common::Logger::GetLoggerInstance()->Initialize(common::CONSOLE_WIDTH, common::CONSOLE_HEIGHT, + common::CONSOLE_MAX_LINE, &s_RenderSystem); + + // RenderSystemを作ってからログが出せる + common::Logger::InitializeEjectThread(); + common::Logger::SetEjectHandler(OnSdEjected); + common::Logger::SetInsertHandler(OnSdInserted); + COMMON_LOGGER("\n"); + COMMON_LOGGER("CTR Console Restore start\n"); + + // ボタン入力 + nn::hid::PadReader s_PadReader; + nn::hid::PadStatus padStatus; + + // データの準備 + s_HwUtility.InitializeForRestore(); + common::HardwareStateManager manager(s_HwUtility); + + // 情報出力 + COMMON_LOGGER("CTR Console Restore %s Rev.%s\n", __DATE__, RESTORE_VERSION_NUM); + COMMON_LOGGER("System Ver. %d.%d.%d-%d\n", s_HwUtility.GetCupMajorVersion(), + s_HwUtility.GetCupMinorVersion(), + s_HwUtility.GetCupMicroVersion(), + s_HwUtility.GetNupVersion()); + COMMON_LOGGER("System Region %s\n", s_HwUtility.GetRegionCodeA3()); + COMMON_LOGGER("Serial Number %s\n", s_HwUtility.GetSerialNumber()); + COMMON_LOGGER("Device ID %llu\n", s_HwUtility.GetInfraDeviceId()); + COMMON_LOGGER("MAC Address %s\n", s_HwUtility.GetMacAddress()); + COMMON_LOGGER("Friend Code %04u-%04u-%04u\n", + static_cast(s_HwUtility.GetFriendcode() / 100000000ULL % 10000ULL), + static_cast(s_HwUtility.GetFriendcode() / 10000ULL % 10000ULL), + static_cast(s_HwUtility.GetFriendcode() % 10000ULL) ); + + + bool flip = false; + InitializeState(); + + 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(); + } + + // 情報更新 + // ACアダプタ + std::string adapterState; + if(manager.IsAdapterConnected()) + { + adapterState += ::std::string("Connected"); + } + else + { + adapterState += ::std::string("Not Connected"); + } + + // 操作用メッセージ + // 進捗確認メッセージを兼ねる? + ::std::vector operationMessage; + + ControlState(manager, operationMessage, nextStep); + + 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; + } + else if(GetRestoreMode() == RESTORE_MODE_GET_IVS) + { + titleColor.r = 1.0f; + titleColor.g = 0.2f; + titleColor.b = 0.2f; + } + else if(GetRestoreMode() == RESTORE_MODE_CHECK_SD) + { + titleColor.r = 0.2f; + titleColor.g = 0.2f; + titleColor.b = 1.2f; + } + + // 上画面表示 + common::DrawSystemState("CTR Console Restore", + s_RenderSystem, + titleColor, + flip, + adapterState, + RESTORE_VERSION_NUM, + s_HwUtility.GetCupMajorVersion(), + s_HwUtility.GetCupMinorVersion(), + s_HwUtility.GetCupMicroVersion(), + s_HwUtility.GetNupVersion(), + s_HwUtility.GetBatteryRemain(), + s_HwUtility.GetInfraDeviceId(), + s_HwUtility.GetFriendcode(), + GetProgress(), + IsRestoreFailed(), + IsRestoreSucceeded(), + s_HwUtility.GetMacAddress(), + operationMessage, + s_HwUtility.GetRegion(), + s_HwUtility.GetSerialNumber(), + s_HwUtility.HasReadFriendCode() + ); + + if (GetRestoreMode() != RESTORE_MODE_RESTORE) + { + const u8 spaceSize = 10; + const u8 lineBottom = 23; + const u32 screenWidth = 400; + + s_RenderSystem.SetColor(1.f, 1.f, 1.f); + + if (GetRestoreMode() == RESTORE_MODE_NUP_ONLY) + { + s_RenderSystem.DrawText(0, lineBottom * spaceSize, "NUP-Only Mode"); + } + else if (GetRestoreMode() == RESTORE_MODE_GET_IVS) + { + s_RenderSystem.DrawText(0, lineBottom * spaceSize, "GET-SDCI Mode"); + } + else if (GetRestoreMode() == RESTORE_MODE_CHECK_SD) + { + s_RenderSystem.DrawText(0, lineBottom * spaceSize, "CHECK-SD 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(); + + // デフォルトで下画面に描画するもの + 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/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/ConsoleRestore.rsf b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/ConsoleRestore.rsf new file mode 100644 index 0000000..fdbf1fd --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/ConsoleRestore.rsf @@ -0,0 +1,47 @@ +BasicInfo: + Title : ConsoleRestore + ProductCode: CTR-P-22UA + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xf8022 + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 0x4000 + Dependency : + - codec + - hid + - gsp + - friends + - nim + - ac + - ndm + +AccessControlInfo: + Priority : 16 + DisableDebug : true + + FileSystemAccess: + - DirectSdmc + - Debug + - Core + - CategoryFileSystemTool + + IoAccessControl: + - FsMountCardSpi + - FsMountNand + - FsMountTwln + +Option: + FreeProductCode: true + +CardInfo: + CardDevice: None + +Rom: + # ROM に含めるファイルシステムのルートパスを指定します。 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Controller.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Controller.cpp new file mode 100644 index 0000000..62b0d87 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Controller.cpp @@ -0,0 +1,1688 @@ +/*---------------------------------------------------------------------------* + 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 + +#include "Controller.h" +#include "FileChecker.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" +#include "Importer.h" +#include "Updater.h" +#include "NtpClient.h" +#include "TitleDownloader.h" +#include "Shop.h" +#include "Util.h" + +namespace ConsoleRestore +{ + +namespace +{ + +// ネットワーク設定ファイルを読んだかどうか +bool s_ReadSettingDone = false; +// インターネット設定を読んだ結果 +bool s_ReadSettingIsSuccess = false; +// NUP専用モードかどうか +bool s_NupOnlyMode = false; +// IVS取得専用モードかどうか +bool s_GetIvsOnlyMode = false; +// SDカード確認専用モード +bool s_CheckSdOnlyMode = false; +// NUPスキップモードかどうか +bool s_SkipNupMode = false; + +// APSettingの書式が無い警告サウンドを鳴らしたかどうか +bool s_ExistAPSettingAnnotation = false; +// APSettingの書式が違っている警告サウンドを鳴らしたかどうか +bool s_APSettingAnnotation = false; +// シリアルナンバーがない警告サウンドを鳴らしたかどうか +bool s_SerialNumberAnnotation = false; +// 失敗サウンドを鳴らしたかどうか +bool s_PlayedFailSound = false; +// 操作開始サウンドを鳴らしたかどうか +bool s_PlayedStartCursor = false; +// リブート開始前サウンドを鳴らしたかどうか +bool s_PlayedRebootCursor = false; +// SD抜き出し前サウンドを鳴らしたかどうか +bool s_PlayedSdPullOutCursor = false; +// SDに書き込みできない警告サウンドを鳴らしたかどうか +bool s_SdWriteProetctAnnotation = false; +// WiFiがOFFである警告サウンドを鳴らしたかどうか +bool s_WifiStatusOffAnnotation = false; + +// ネットワークアップデートを開始したかどうか +bool s_ExecuteFgNup = false; +// FGNUPを何回リトライしたか +u32 s_FgNupRetryCount = 0; +// 時計同期モードかどうか +bool s_IsSyncClock = false; +// TWLタイトルのダウンロードを開始したかどうか +bool s_ExecuteTitleDownload = false; +// TWLタイトルのダウンロードを何回リトライしたか +u32 s_TitleDownloadRetryCount = 0; + +// ショップ処理を開始したかどうか +bool s_ShopOperationExecuted[SHOP_OPERATION_NUM_MAX]; +// ショップ処理を何回リトライしたか +u32 s_ShopOperationRetryCount[SHOP_OPERATION_NUM_MAX]; + +void PutAliveMessage(::std::vector& operationMessage, const char* str); +bool CheckAndReadAPSetting(::std::vector& operationMessage); + +bool NeedsAcAdater(common::HardwareStateManager& manager) +{ + return manager.IsBatteryLower() && !manager.IsAdapterConnected(); +} + +bool HasValidRtcData() +{ + return !s_CheckSdOnlyMode && !s_NupOnlyMode && !s_GetIvsOnlyMode; +} + +typedef enum RestoreState +{ + STARTUP, // 初期値 + INITIALIZE_CONSOLE, // セーブデータ領域のNAND初期化を行う + SERIAL_IS_NOT_IN_SD, // シリアルナンバーファイルがSDカードにないことを表示 + WAIT_START_UPDATE, // アップデート開始入力待ち + WAIT_START_IMPORT, // 書き込み開始入力待ち + WAIT_START_SYNC_CLOCK, // 時計合わせ開始入力待ち + IMPORT_RTC, // RTC同期 + UPDATE_IN_PROGRESS, // アップデート中 + UPDATE_DONE, // アップデート完了 + NUP_ONLY_WAIT_SD_EJECT, // NUP_ONLYモードでSDカード抜き待ち + NUP_ONLY_WAIT_NEXT, // NUP_ONLYモードでキー入力待ち + WAIT_START_TRANSFER_ACCOUNT, // アカウント転送開始入力まち + TRANSFER_ACCOUNT, // アカウント転送を完了させる + TRANSFER_ACCOUNT_DONE, // アカウント転送完了 + DOWNLOAD_IVS, // インフラからIVSを取得する + DOWNLOAD_IVS_DONE, // インフラからIVSを取得完了 + DOWNLOAD_IVS_WAIT_NEXT, // IVS取得モードでキー入力待ち + CHECK_IVS, // IVSとSDカードのセーブデータディレクトリの一致を確認 + CHECK_SD_DIRECTORY, // SDカードのIVS依存ディレクトリを探す + CHECK_SD_DIRECTORY_SUCCESS, // SDカードのIVS依存ディレクトリチェック完了 + CHECK_SD_DIRECTORY_FAIL, // SDカードのIVS依存ディレクトリが見つからなかった + WAIT_START_DELETE_ACCOUNT, // ショップアカウント削除開始入力待ち, + DELETE_ACCOUNT, // ショップアカウントを削除する + DELETE_ACCOUNT_DONE, // ショップアカウント削除完了 + SYNC_TICKET, // eTicketを同期する + READ_FILELIST, // ファイル一覧の読み込み + RESTORE_TWL_NAND, // TWL NANDの書き込み中 + RESTORE_TWL_SOUND, // TWLサウンドの書き込み中 + RESTORE_TWL_PHOTO, // TWL写真の書き込み中 + RESTORE_IN_PROGRESS, // 書き込み中 + POST_RESTORE, // 書き込み後の処理 + RESTORE_DONE, // 書き込み完了 + REBOOTING, // 再起動を行う + ERASE, // 削除処理を行う + RESTORE_CAL, // cfgの一部をcal値で上書きする + TIME_ADJUST, // 時計あわせを行う + DOWNLOAD_TWL, // TWLアプリ本体をダウンロードする + WAIT_SD_EJECT, // SDカードぬき待ち + ALL_DONE, // すべて完了 + INITIALIZE_AND_SHUTDOWN, // 本体初期化後にシャットダウン中 + FAIL // 失敗 +} RestoreState; + + + +// Restore状態管理 +RestoreState s_RestoreState = STARTUP; +// Restoreモード管理 +RestoreMode s_RestoreMode = RESTORE_MODE_RESTORE; + +void CheckSdInserted(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckAcAdapter(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckSdWritable(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckApSetting(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckNupExecuted(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckDownloadIvs(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckAccountDeleted(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckAccountTransfered(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckWriteFinished(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckReadIvs(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckConsoleInitialized(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckExistsSerialNumber(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckIvsinSd(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); +void CheckRegioinSd(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep); + +// SDカード挿入チェック +void CheckSdInserted(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + if (nn::fs::IsSdmcInserted()) + { + CheckAcAdapter(manager, message, goNextStep); + } + else + { + message.push_back(::std::string("Insert SD Card!!")); + s_RestoreState = STARTUP; + } +} + +// ACアダプタが必要かどうかチェック +void CheckAcAdapter(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + // ACアダプタが必要か? + if (NeedsAcAdater(manager)) + { + message.push_back(::std::string("Connect AC Adapter!!")); + s_RestoreState = STARTUP; + } + else + { + CheckSdWritable(manager, message, goNextStep); + } +} + +// SDカード書き込みチェック +void CheckSdWritable(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + // SDカードに書き込みできるか? + if (nn::fs::IsSdmcWritable()) + { + CheckApSetting(manager, message, goNextStep); + } + else + { + if (!s_SdWriteProetctAnnotation) + { + s_SdWriteProetctAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + message.push_back(::std::string("Can't Write SD Card!!\n")); + s_RestoreState = STARTUP; + } +} + + +// 設定ファイル書式チェック +void CheckApSetting(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + NN_UNUSED_VAR(manager); + NN_UNUSED_VAR(goNextStep); + + if (CheckAndReadAPSetting(message)) + { + s_RestoreState = IMPORT_RTC; + } + else + { + s_RestoreState = STARTUP; + } +} + +// NUP済みかどうかチェック +void CheckNupExecuted(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + if (common::ExistsUpdateCheckedFile()) + { + if (s_NupOnlyMode) + { + s_RestoreState = WAIT_START_DELETE_ACCOUNT; + } + else + { + CheckAccountDeleted(manager, message, goNextStep); + } + } + else + { + // NUPを実行 + if (CheckAndReadAPSetting(message)) + { + if (nn::nwm::CTR::IsWifiOn()) + { + // ネットワークアップデートを行う + s_RestoreState = WAIT_START_UPDATE; + } + else + { + if (!s_WifiStatusOffAnnotation) + { + s_WifiStatusOffAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + + message.push_back(::std::string("Wireless is Off\n")); + s_RestoreState = STARTUP; + } + } + } +} + +// インフラからIVS取得済みかチェック +void CheckDownloadIvs(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + NN_UNUSED_VAR(message); + NN_UNUSED_VAR(goNextStep); + + // IVS取得確認ファイルがあるか? + if (common::ExistsDownloadIvsCheckedFile()) + { + if(s_GetIvsOnlyMode) + { + s_RestoreState = DOWNLOAD_IVS_WAIT_NEXT; + } + else + { + CheckWriteFinished(manager, message, goNextStep); + } + } + else + { + COMMON_LOGGER("Download SDCI\n"); + s_RestoreState = DOWNLOAD_IVS; + } + +} + +// アカウント削除済みかチェック +void CheckAccountDeleted(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + // アカウント削除確認ファイルがあるか? + if (common::ExistsDeleteAccountChecked()) + { + CheckAccountTransfered(manager, message, goNextStep); + } + else + { + // 同一本体下記書き戻しの場合はアカウント削除しない + if(EqualsDeviceIdFileandDeviceId(manager).IsSuccess()) + { + // IVS専用モードならばIVSを取得させる + if(s_GetIvsOnlyMode) + { + CheckDownloadIvs(manager, message, goNextStep); + } + else + { + CheckAccountTransfered(manager, message, goNextStep); + } + } + else + { + s_RestoreState = WAIT_START_DELETE_ACCOUNT; + } + } +} + +// アカウント移行済みかチェック +void CheckAccountTransfered(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + // アカウント移行確認ファイルがあるか? + if (common::ExistsTransferAccountChecked()) + { + CheckDownloadIvs(manager, message, goNextStep); + } + else + { + s_RestoreState = WAIT_START_TRANSFER_ACCOUNT; + } +} + +// 書き込み完了かどうかチェック +void CheckWriteFinished(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + NN_UNUSED_VAR(goNextStep); + + // SDカードに書き込み完了ファイルがあるか? + if (common::ExistsWriteFinishedFile()) + { + if (CheckAndReadAPSetting(message)) + { + if (nn::nwm::CTR::IsWifiOn()) + { + // 削除処理を行う + s_RestoreState = WAIT_START_SYNC_CLOCK; + } + else + { + if (!s_WifiStatusOffAnnotation) + { + s_WifiStatusOffAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + message.push_back(::std::string("Wireless is Off\n")); + } + } + } + else + { + CheckReadIvs(manager, message, goNextStep); + } +} + +// IVSを読めるかどうかチェック +void CheckReadIvs(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + // IVSを読めるか? + if (manager.CanReadIvs()) + { + CheckConsoleInitialized(manager, message, goNextStep); + } + else + { + s_RestoreState = FAIL; + COMMON_LOGGER("Can't Read SDCI!!"); + } +} + +// 本体初期化済みかどうかチェック +void CheckConsoleInitialized(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + // 本体初期化完了ファイルがあるか? + if (common::ExistsConsoleInitializedFile()) + { + CheckRegioinSd(manager, message, goNextStep); + } + else + { + CheckIvsinSd(manager, message, goNextStep); + } +} + +// シリアルナンバーがあるかどうかチェック +void CheckExistsSerialNumber(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + NN_UNUSED_VAR(manager); + NN_UNUSED_VAR(message); + NN_UNUSED_VAR(goNextStep); + + + // SDカードにシリアルナンバーがあるか? + if (common::ExistsSerialNumberFile()) + { + u8 serial[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + nn::Result result = ReadSerialNumber(serial); + if (result.IsSuccess()) + { + s_RestoreState = WAIT_START_IMPORT; + } + else + { + s_RestoreState = FAIL; + } + } + else + { + COMMON_LOGGER("Can't Read Serial Number in SD Card!!\n"); + s_RestoreState = SERIAL_IS_NOT_IN_SD; + } +} + +// SDカードにIVSがあるかどうかチェック +void CheckIvsinSd(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + NN_UNUSED_VAR(manager); + NN_UNUSED_VAR(message); + NN_UNUSED_VAR(goNextStep); + + if (common::ExistsIVSFile()) + { + s_RestoreState = INITIALIZE_CONSOLE; + } + else + { + // 移行不能なのでFAIL + COMMON_LOGGER("Can't Read SDCI in SD Card!!\n"); + s_RestoreState = FAIL; + } +} + +// SDカードにリージョンデータがあるかどうかチェック +void CheckRegioinSd(common::HardwareStateManager& manager, ::std::vector& message, bool& goNextStep) +{ + NN_UNUSED_VAR(message); + NN_UNUSED_VAR(goNextStep); + + // SDカードにリージョンデータがあるか? + if (common::ExistsRegionData()) + { + // リージョンデータは一致しているか? + if (EqualsRegionDataandRegion().IsFailure()) + { + COMMON_LOGGER("Current Region and Region in SD differ!!\n"); + s_RestoreState = FAIL; + } + else + { + CheckExistsSerialNumber(manager, message, goNextStep); + } + + } + else + { + // 移行不能なのでFAIL + COMMON_LOGGER("Can't Read Region in SD Card!!\n"); + s_RestoreState = FAIL; + } +} + +void ShopOperationSuccess(ShopOperation op, const char* logMessage, RestoreState nextState) +{ + COMMON_LOGGER("%s", logMessage); + if (op == SHOP_OPERATION_UNREGISTER || op == SHOP_OPERATION_FORCE_UNREGISTER) + { + CreateDeleteAccountFinishedFile(); + } + else if (op == SHOP_OPERATION_GET_IVS) + { + CreateDownloadIvsFinishedFile(); + } + + s_RestoreState = nextState; + +} + +void ShopOperationSingleTemplate( + common::HardwareStateManager& manager, + std::vector& message, + ShopOperation op, + const char* aliveMessage, + const char* logMessage, + const char* retryLogMessage, + RestoreState nextState + ) +{ + // ACアダプタが必要か? + if (NeedsAcAdater(manager)) + { + message.push_back(::std::string("Connect AC Adapter!!")); + } + + // アップデートを行う + if (!s_ShopOperationExecuted[op]) + { + if (ImportCountryLanguageData().IsSuccess()) + { + StartShopOperationSingle(op); + s_ShopOperationExecuted[op] = true; + } + else + { + s_RestoreState = FAIL; + } + } + + // 動いていることを表示 + { + PutAliveMessage(message, aliveMessage); + } + + if (IsShopOperationSingleFinished()) + { + FinalizeShopOperationSingle(); + // エラーがあったら表示する + if (GetShopOperationSingleResult().IsSuccess()) + { + ShopOperationSuccess(op, logMessage, nextState); + } + // IVSがアップロードされていない場合もあるため + // IVSを取得できない状況も成功として扱う + // IVSサイズが違う場合も成功として扱う + else if(op == SHOP_OPERATION_GET_IVS && ( GetShopOperationSingleResult() == nn::nim::ResultCannotGetIvs() || + GetShopOperationSingleResult() == nn::nim::ResultInvalidData() + )) + { + ShopOperationSuccess(op, logMessage, nextState); + } + else if(op == SHOP_OPERATION_CONNECT && nextState == TRANSFER_ACCOUNT_DONE && + GetShopOperationSingleResult() == nn::nim::ResultNeedGetIvs()) + + { + NN_LOG("ResultNeedGetIvs\n"); + ShopOperationSuccess(op, logMessage, nextState); + } + else + { + if (GetShopOperationSingleResult().IsFailure()) + { + if (GetShopOperationSingleResult() == nn::ac::ResultFailedConnectAp()) + { + COMMON_LOGGER("Failed Connect AccesPoint."); + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromSeconds(5)); + } + + + // APが見つからない + if (GetUpdateResult() == nn::ac::ResultNotFoundAccessPoint()) + { + COMMON_LOGGER("No Access Point Found!"); + } + } + + if (s_ShopOperationRetryCount[op]++ < RETRY_MAX) + { + // エラーのためやり直す + COMMON_LOGGER_RESULT_IF_FAILED(GetShopOperationSingleResult()); + COMMON_LOGGER("%s %d\n", retryLogMessage, s_ShopOperationRetryCount[op]); + + // スレッドを作るとこからやり直し + s_ShopOperationExecuted[op] = false; + } + else + { + s_RestoreState = FAIL; + } + } + + } +} + +void UpdateOperation(common::HardwareStateManager& manager, ::std::vector& message, RestoreState nextState) +{ + // ACアダプタが必要か? + if (NeedsAcAdater(manager)) + { + message.push_back(::std::string("Connect AC Adapter!!")); + } + + // アップデートを行う + if (!s_ExecuteFgNup) + { + if (ImportCountryLanguageData().IsSuccess()) + { + StartFGNetworkUpdate(); + s_ExecuteFgNup = true; + } + else + { + s_RestoreState = FAIL; + } + } + + // 動いていることを表示 + { + PutAliveMessage(message, "Updating"); + } + + if (IsNetworkUpdateFinished()) + { + FinishFGNetworkUpdate(); + // エラーがあったら表示する + if (GetUpdateResult().IsFailure()) + { + // APが見つからない + if (GetUpdateResult() == nn::ac::ResultNotFoundAccessPoint()) + { + COMMON_LOGGER("No Access Point Found!"); + } + } + + if (GetUpdateResult().IsSuccess()) + { + COMMON_LOGGER("Network Update Finished.\n"); + if(nextState == UPDATE_DONE) + { + // アップデート完了ファイルを作成 + CreateUpdateFinishedFile(); + } + + s_RestoreState = nextState; + } + else + { + if (s_FgNupRetryCount++ < RETRY_MAX) + { + // エラーのためやり直す + COMMON_LOGGER_RESULT_IF_FAILED(GetUpdateResult()); + COMMON_LOGGER("Network Update Failed. Retrying... %d\n", s_FgNupRetryCount); + + // FGNUP用のスレッドを作るとこからやり直し + s_ExecuteFgNup = false; + } + else + { + s_RestoreState = FAIL; + } + } + + } +} + +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; + } + + // 設定ファイルからAP設定を読み込む + if (!s_ReadSettingDone) + { + s_ReadSettingDone = true; + s_ReadSettingIsSuccess = ReadSetting(&s_NupOnlyMode, &s_GetIvsOnlyMode, &s_CheckSdOnlyMode, &s_SkipNupMode); + } + + if (s_NupOnlyMode && s_GetIvsOnlyMode + || s_GetIvsOnlyMode && s_CheckSdOnlyMode + || s_CheckSdOnlyMode && s_NupOnlyMode) + { + operationMessage.push_back("Only one special mode setting is valid!!"); + s_ReadSettingIsSuccess = false; + } + else if(s_NupOnlyMode && s_SkipNupMode) + { + operationMessage.push_back("Both NUP_ONLY and SKIP_NUP are described!!"); + s_ReadSettingIsSuccess = false; + } + else + { + if (s_NupOnlyMode) + { + s_RestoreMode = RESTORE_MODE_NUP_ONLY; + } + + if (s_GetIvsOnlyMode) + { + s_RestoreMode = RESTORE_MODE_GET_IVS; + } + + if(s_CheckSdOnlyMode) + { + s_RestoreMode = RESTORE_MODE_CHECK_SD; + } + } + + if (!s_ReadSettingIsSuccess) + { + operationMessage.push_back(::std::string("Invalid Accsess_Point_Setting format!")); + if(!s_APSettingAnnotation) + { + s_APSettingAnnotation = true; + common::PlaySound(common::SOUND_ANNOTATION); + } + } + + return s_ReadSettingIsSuccess; +} + +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(common::HardwareStateManager& manager) +{ + nn::Result result = nn::ResultSuccess(); + if(!common::ExistsRtcSyncFinishedFile()) + { + result = ImportMcuRtc(manager); + if(result.IsSuccess()) + { + // RTCを同期完了ファイルを作る + CreateRtcSyncFinishedFile(); + } + } + + return result; +} + +} // namespace + +void ControlState(common::HardwareStateManager& manager, ::std::vector& operationMessage, bool& nextStep) +{ + using namespace common; + nn::Result result; + + // 状態遷移Controller + switch (s_RestoreState) + { + // 起動時 + case STARTUP: + { + CheckSdInserted(manager, operationMessage, nextStep); + } + break; + + + case INITIALIZE_CONSOLE: + { + COMMON_LOGGER("Initialize Console\n"); + + // 本体初期化完了ファイルを作る + CreateConsoleInitializedFile(); + + // ファイルシステムの初期化を行う + if(InitializeFileSystem()) + { + s_RestoreState = REBOOTING; + } + else + { + s_RestoreState = FAIL; + } + + } + break; + + case WAIT_START_UPDATE: + { + operationMessage.push_back(::std::string("Push A or START Button")); + operationMessage.push_back(::std::string("Network Update Mode")); + if (!s_PlayedStartCursor) + { + PlaySound(SOUND_CURSOR); + s_PlayedStartCursor = true; + } + + if (nextStep) + { + COMMON_LOGGER("Start Network Update\n"); + s_RestoreState = UPDATE_IN_PROGRESS; + } + } + break; + + case WAIT_START_IMPORT: + { + 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 + { + s_RestoreState = FAIL; + } + + operationMessage.push_back(::std::string("Push A or START Button")); + operationMessage.push_back(::std::string("Import Data Mode")); + if (!s_PlayedStartCursor) + { + PlaySound(SOUND_CURSOR); + s_PlayedStartCursor = true; + } + + if (nextStep) + { + s_RestoreState = READ_FILELIST; + } + } + break; + + case WAIT_START_SYNC_CLOCK: + { + operationMessage.push_back(::std::string("Push A or START Button")); + operationMessage.push_back(::std::string("DownLoad Twl Title and Clock Sync Mode")); + if (!s_PlayedStartCursor) + { + PlaySound(SOUND_CURSOR); + s_PlayedStartCursor = true; + } + + if (nextStep) + { + COMMON_LOGGER("Erase Trash\n"); + s_RestoreState = ERASE; + } + } + break; + + case IMPORT_RTC: + { + result = nn::ResultSuccess(); + if (HasValidRtcData()) + { + result = ExecSyncMcuRtc(manager); + if (result <= nn::fs::ResultVerificationFailed()) + { + s_RestoreState = FAIL; + } + else + { + if (s_SkipNupMode) + { + CheckAccountTransfered(manager, operationMessage, nextStep); + } + else + { + CheckNupExecuted(manager, operationMessage, nextStep); + } + } + } + else + { + if (s_CheckSdOnlyMode) + { + s_RestoreState = CHECK_IVS; + } + else + { + CheckNupExecuted(manager, operationMessage, nextStep); + } + } + } + break; + + // シリアルナンバーがSDカードにないこと警告 + 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 = READ_FILELIST; + } + } + break; + + // アップデート中 + case UPDATE_IN_PROGRESS: + { + UpdateOperation(manager, operationMessage, UPDATE_DONE); + } + 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; + + case DOWNLOAD_IVS: + { + ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_GET_IVS, "Get SDCI", + "Get SDCI Finished.\n", "Get SDCI Failed. Retrying...", DOWNLOAD_IVS_DONE); + } + break; + + + case DOWNLOAD_IVS_DONE: + { + operationMessage.push_back(::std::string("Get SDCI 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 CHECK_IVS: + { + operationMessage.push_back(::std::string("Insert User's SD Card")); + } + break; + + case CHECK_SD_DIRECTORY: + { + if (nn::fs::IsSdmcInserted()) + { + NN_LOG("Check User's SD Card\n"); + // ユーザのSDカードにはAP設定ファイルは無いはず + if (ExistsAPSetting()) + { + NN_LOG("AP Setting Exists. Retry\n"); + s_RestoreState = CHECK_IVS; + } + else + { + NN_LOG("Read User's SD Card\n"); + void* ivs; + size_t size; + manager.GetIvs(&ivs, &size); + std::string sysSaveRoot; + + common::Util::GetSaveDataDirectoryRoot(sysSaveRoot, ivs, size); + if (ExistsIvsDirectory(sysSaveRoot)) + { + s_RestoreState = CHECK_SD_DIRECTORY_SUCCESS; + } + else + { + s_RestoreState = CHECK_SD_DIRECTORY_FAIL; + } + } + } + } + break; + + case CHECK_SD_DIRECTORY_SUCCESS: + { + operationMessage.push_back(::std::string("Check User's SD Card Succeeded.")); + operationMessage.push_back(::std::string("Pull Out SD Card")); + } + break; + + case CHECK_SD_DIRECTORY_FAIL: + { + operationMessage.push_back(::std::string("Check User's SD Card Failed.")); + operationMessage.push_back(::std::string("Pull Out SD Card")); + } + break; + + case WAIT_START_TRANSFER_ACCOUNT: + { + if(s_SkipNupMode) + { + operationMessage.push_back(::std::string("After Operating BMS Account Transfer,")); + } + + operationMessage.push_back(::std::string("Push A or START Button")); + operationMessage.push_back(::std::string("Transfer Account Mode")); + if (!s_PlayedStartCursor) + { + PlaySound(SOUND_CURSOR); + s_PlayedStartCursor = true; + } + + if (nextStep) + { + COMMON_LOGGER("Transfer Account\n"); + s_RestoreState = TRANSFER_ACCOUNT; + } + } + break; + + case TRANSFER_ACCOUNT: + { + ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_CONNECT, "Transfer Account", + "Transfer Account Finished.\n", "Transfer Account Failed. Retrying...", TRANSFER_ACCOUNT_DONE); + } + break; + + case TRANSFER_ACCOUNT_DONE: + { + CreateTransferAccountFinishedFile(); + s_RestoreState = STARTUP; + } + break; + + case WAIT_START_DELETE_ACCOUNT: + { + operationMessage.push_back(::std::string("Push A or START Button")); + operationMessage.push_back(::std::string("Delete Account Mode")); + if (!s_PlayedStartCursor) + { + PlaySound(SOUND_CURSOR); + s_PlayedStartCursor = true; + } + + if (nextStep) + { + COMMON_LOGGER("Delete Account\n"); + s_RestoreState = DELETE_ACCOUNT; + } + } + break; + + case DELETE_ACCOUNT: + { + if(s_NupOnlyMode) + { + ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_FORCE_UNREGISTER, "Deleting Account", + "Delete Account Finished.\n", "Delete Account Failed. Retrying...", DELETE_ACCOUNT_DONE); + + } + else + { + ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_UNREGISTER, "Deleting Account", + "Delete Account Finished.\n", "Delete Account Failed. Retrying...", DELETE_ACCOUNT_DONE); + } + } + break; + + case DELETE_ACCOUNT_DONE: + { + if(s_NupOnlyMode) + { + s_RestoreState = NUP_ONLY_WAIT_SD_EJECT; + + // リストア状態チェックファイルをすべて削除 + DeleteAllCheckFiles(); + } + else + { + operationMessage.push_back(::std::string("Delete Account Done.")); + operationMessage.push_back(::std::string("Operate BMS.")); + operationMessage.push_back(::std::string("")); + operationMessage.push_back(::std::string("Press A or START Button to Continue")); + + if (!s_PlayedRebootCursor) + { + PlaySound(SOUND_CURSOR); + s_PlayedRebootCursor = true; + } + + if (nextStep) + { + s_RestoreState = STARTUP; + } + } + } + break; + + case READ_FILELIST: + { + result = SetupFileList(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + if (result.IsSuccess()) + { + if (s_IsSyncClock) + { + s_RestoreState = RESTORE_TWL_NAND; + } + else + { + s_RestoreState = RESTORE_TWL_SOUND; + } + + } + else + { + s_RestoreState = FAIL; + } + } + break; + + // TWLサウンド領域の書き込み中 + case RESTORE_TWL_SOUND: + { + static bool init = true; + if (init) + { + // データを書き込む + ImportTwlSoundData(); + init = false; + } + + PutAliveMessage(operationMessage, "Importing TWL Sound Data"); + + // 処理が完了した + if (IsImportThreadFinished()) + { + FinalizeImportThread(); + if(IsImportSucceeded()) + { + s_RestoreState = RESTORE_TWL_PHOTO; + } + else + { + s_RestoreState = FAIL; + } + + } + } + break; + + // TWL写真領域の書き込み + case RESTORE_TWL_PHOTO: + { + static bool init = true; + if (init) + { + // データを書き込む + ImportTwlPhotoData(); + init = false; + } + + PutAliveMessage(operationMessage, "Importing TWL Photo Data"); + + // 処理が完了した + if (IsImportThreadFinished()) + { + FinalizeImportThread(); + if(IsImportSucceeded()) + { + s_RestoreState = RESTORE_IN_PROGRESS; + } + else + { + s_RestoreState = FAIL; + } + + } + } + break; + + // 書き込み中 + case RESTORE_IN_PROGRESS: + { + // ACアダプタが必要か? + if (NeedsAcAdater(manager)) + { + operationMessage.push_back(::std::string("Connect AC Adapter!!")); + } + + // データを読み込む + if (ImportData().IsFailure()) + { + s_RestoreState = FAIL; + } + else + { + PutAliveMessage(operationMessage, "Importing Nand Data"); + + // 処理が完了した + if (!NeedsAcAdater(manager) && IsImportThreadFinished()) + { + if (IsImportSucceeded()) + { + + COMMON_LOGGER("Import NAND Data Finished.\n"); + + if (GetProgress() > 99) + { + s_RestoreState = POST_RESTORE; + } + else + { + s_RestoreState = FAIL; + } + } + else + { + s_RestoreState = FAIL; + } + } + } + } + break; + + // リブート中 + case REBOOTING: + { + static bool init = true; + + if (init) + { + // ErrDispから引用 + 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: リブートは非同期のため処理は継続 + } + init = false; + } + } + break; + + // 書き込み後の処理 + case POST_RESTORE: + { + operationMessage.push_back(::std::string("Post Process...")); + + // SDカードのIVSファイルを書き込む + if(ImportIvsData()) + { + // 書き込み完了ファイルを作成 + CreateWriteFinishedFile(); + + s_RestoreState = RESTORE_DONE; + } + else + { + s_RestoreState = FAIL; + } + } + 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 = RESTORE_CAL; + } + break; + + // 削除処理 + case RESTORE_CAL: + { + // ptmのセーブデータ移行後に時計を無効化する + nn::ptm::CTR::InvalidateSystemTime(); + + // cfgの本体固有値をcal値で初期化する + result = InitializeHardwareDependentSetting(); + if (result.IsFailure()) + { + s_RestoreState = FAIL; + } + + COMMON_LOGGER("Sync eTicket\n"); + s_RestoreState = SYNC_TICKET; + } + break; + + case SYNC_TICKET: + { + if(s_GetIvsOnlyMode) + { + ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_CONNECT, "Shop Connect", + "Shop Connect Finished.\n", "Shop Connect Failed. Retrying...", WAIT_SD_EJECT); + } + else + { + ShopOperationSingleTemplate(manager, operationMessage, SHOP_OPERATION_CONNECT, "Shop Connect", + "Shop Connect Finished.\n", "Shop Connect Failed. Retrying...", DOWNLOAD_TWL); + } + } + break; + + case DOWNLOAD_TWL: + { + // ファイルリストがなければ次へ + if( !ExistsTwlTitleListFile()) + { + s_IsSyncClock = true; + s_RestoreState = READ_FILELIST; + } + else + { + if (!s_ExecuteTitleDownload) + { + COMMON_LOGGER("Download Twl Title\n"); + s_ExecuteTitleDownload = true; + StartTitleDownload(); + } + + // 動いていることを表示 + { + PutAliveMessage(operationMessage, "Download Twl Title"); + } + + if (IsDownloadTitleFinished()) + { + FinalizeTitleDownload(); + if (DownloadTitleSucceeded()) + { + s_IsSyncClock = true; + s_RestoreState = READ_FILELIST; + } + else + { + if (s_TitleDownloadRetryCount++ < RETRY_MAX) + { + // エラーのためやり直す + COMMON_LOGGER_RESULT_IF_FAILED(GetShopOperationSingleResult()); + COMMON_LOGGER("Download Twl Title Failed. Retrying... %d\n", s_TitleDownloadRetryCount); + + s_ExecuteTitleDownload = false; + } + else + { + s_RestoreState = FAIL; + } + } + } + } + } + break; + + // TWL NAND領域の書き込み中 + case RESTORE_TWL_NAND: + { + static bool init = true; + if (init) + { + // データを書き込む + ImportTwlSaveData(); + init = false; + } + + PutAliveMessage(operationMessage, "Importing TWL SaveData"); + + // 処理が完了した + if (IsImportThreadFinished()) + { + FinalizeImportThread(); + s_RestoreState = TIME_ADJUST; + } + } + break; + + // 時計あわせ + 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カード抜けのみで次の状態に遷移する + + 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カード抜けのみで次の状態に遷移する + if (!s_PlayedSdPullOutCursor) + { + common::PlaySound(common::SOUND_CURSOR); + s_PlayedSdPullOutCursor = true; + } + } + break; + + case DOWNLOAD_IVS_WAIT_NEXT: + { + operationMessage.push_back(::std::string("Press A or START Button to Continue.")); + if(nextStep) + { + s_RestoreState = SYNC_TICKET; + DeleteAllCheckFiles(); + } + } + break; + + case NUP_ONLY_WAIT_NEXT: + { + operationMessage.push_back(::std::string("Press A or START Button to Shutdown.")); + + if (nextStep) + { + s_RestoreState = INITIALIZE_AND_SHUTDOWN; + } + } + break; + + case INITIALIZE_AND_SHUTDOWN: + { + // 本体初期化を行う + if(!InitializeFileSystem()) + { + s_RestoreState = FAIL; + } + + // シャットダウンする + 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 == CHECK_SD_DIRECTORY_SUCCESS) + { + 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; + } + // ユーザのSDが抜かれてからFAILにする + else if (s_RestoreState == CHECK_SD_DIRECTORY_FAIL) + { + s_RestoreState = FAIL; + } + // FAILのときは一旦電源を切らないと動かないようにしておく + // IVSチェック時はユーザのSDカードを挿入してもらうため + else if (s_RestoreState != FAIL && s_RestoreState != CHECK_IVS) + { + InitializeState(); + ClearFileReadResult(); + } +} + +void OnSdInserted() +{ + if(s_RestoreState == CHECK_IVS) + { + // SDカードが変わるのでファイルチェックは初期化する + common::InitializeFileCheck(); + s_RestoreState = CHECK_SD_DIRECTORY; + } +} + +void InitializeState() +{ + s_RestoreState = STARTUP; + s_RestoreMode = RESTORE_MODE_RESTORE; + + for(u32 i = 0; i < SHOP_OPERATION_NUM_MAX; i++) + { + s_ShopOperationExecuted[i] = false; + s_ShopOperationRetryCount[i] = 0; + } + + common::InitializeFileCheck(); + + s_ExistAPSettingAnnotation = false; + s_ReadSettingDone = false; + s_ReadSettingIsSuccess = 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_GetIvsOnlyMode = false; + s_SdWriteProetctAnnotation = false; + s_WifiStatusOffAnnotation = false; + s_CheckSdOnlyMode = false; + s_SkipNupMode = false; +} + +u32 GetProgress() +{ + if(s_RestoreState == RESTORE_TWL_SOUND || + s_RestoreState == RESTORE_TWL_PHOTO || + s_RestoreState == RESTORE_TWL_NAND || + 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 if(s_RestoreState == DOWNLOAD_TWL) + { + return GetTitleDownloadProgress(); + } + else + { + return 0; + } + +} + +RestoreMode GetRestoreMode() +{ + return s_RestoreMode; +} + +} // namespace ConsoleRestore diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Controller.h b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Controller.h new file mode 100644 index 0000000..bc8400b --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Controller.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------------* + 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 +#include "HardwareStateManager.h" + +namespace ConsoleRestore +{ + +typedef enum RestoreMode +{ + RESTORE_MODE_RESTORE, + RESTORE_MODE_NUP_ONLY, + RESTORE_MODE_GET_IVS, + RESTORE_MODE_CHECK_SD + +} RestoreMode; + +// ネットワーク処理のリトライ回数の最大値 +const u32 RETRY_MAX = 3; + +// 状態遷移を管理する +// manager ハードウェア情報を取得するためのラッパ +// operationMessage 操作情報として表示したい文字列 +// nextStep 次の状態に遷移してもよいかどうか +// continueBackup 処理を続けてもよいかどうか +void ControlState(common::HardwareStateManager& manager, ::std::vector& operationMessage, bool& nextStep); + +// リストア処理中かどうか +bool InProgress(); + +// リストアが完了したかどうか +bool IsRestoreSucceeded(); + +// リストアが失敗したかどうか +bool IsRestoreFailed(); + +// 書き込みスレッドの進捗を返す +u32 GetProgress(); + + +// SDカードが抜き出されたときに実行したい関数 +void OnSdEjected(); + +// SDカードが挿入されたときに実行したい関数 +void OnSdInserted(); + +// 状態を初期化する +void InitializeState(); + +// リストア状態を取得する +RestoreMode GetRestoreMode(); + +} + +#endif /* CONTOROLLER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Importer.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Importer.cpp new file mode 100644 index 0000000..4f7c6a7 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Importer.cpp @@ -0,0 +1,1891 @@ +/*---------------------------------------------------------------------------* + 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 + +#include "FileName.h" +#include "Importer.h" +#include "SdMountManager.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 "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; +bool s_IsImportSucceeded; + +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; + +struct SdFileSize +{ + s64 totalFileSize; + s64 twlFileSize; + s64 twlSoundFileSize; + s64 twlPhotoFileSize; + s64 ctrFileSize; +}; + +SdFileSize s_SdFileSize; + +// シリアルナンバー +u8 s_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + +// 空のファイルを作成する +bool CreateEmptyFile(const wchar_t* path); +// SDからNANDにセーブデータをコピーする +void ImportSaveData(); +// SDからNORにNORデータをコピーする +nn::Result ImportNorData(); + +// SDカードに保存してあるバージョン情報 +common::VerDef s_SDVersionData; + +// SDカードから読み込んだファイル一覧 +common::ImportDataList s_FileLists; + +} + +// SDからファイル一覧を読み込む +nn::Result ReadFileList(SdFileSize* sdFileSize, common::ImportDataList* fileList); + +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 = 1024; + common::HeapManager readHeap(bufSize); + void* buf = readHeap.GetAddr(); + 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; + } + } + 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(common::HardwareStateManager& manager) +{ + 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; + size_t bufSize = 1024; + common::HeapManager heap(bufSize); + void* buf = heap.GetAddr(); + if (buf != NULL) + { + result = sdReader.ReadBufWithCmac(common::DEVICE_ID_PATHNAME, buf, bufSize, &totalSize); + if (result.IsSuccess()) + { + s_CheckedEqualsDeviceIdFileandDeviceId = true; + std::memcpy(&sdDeviceId, buf, sizeof(sdDeviceId)); + + if (manager.GetDeviceId() == sdDeviceId) + { + 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); + } + } + } + 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 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 = 1024; + common::HeapManager heap(bufSize); + void* buf = heap.GetAddr(); + 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); + } + } + } + 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 = 1024; + common::HeapManager heap(bufSize); + void* buf = heap.GetAddr(); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::COUNTRY_SETTING_PATHNAME, buf, bufSize, &readSize); + if (result.IsSuccess()) + { + // SDから読み出し成功 + SetCountry(reinterpret_cast (buf)->country); + + SetLanguage(reinterpret_cast (buf)->language); + } + + NN_UTIL_RETURN_IF_FAILED(result); + } + } + else + { + // リージョンから適当な国を指定する + 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::HardwareStateManager& manager) +{ + COMMON_LOGGER("Import RTC Data.\n"); + nn::Result result = nn::ResultSuccess(); + nn::Handle handle = manager.GetMcuHandle(); + + if(handle.IsValid()) + { + if (common::CheckFileExists(common::MCU_RTC_PATHNAME)) + { + size_t bufSize = 1024; + NN_LOG("AllocatableSize = %d\n", bufSize); + + common::HeapManager heap(bufSize); + void* buf = heap.GetAddr(); + 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]); + } + + const u8 RETRY = 10; + for (u8 i = 0; i < RETRY; i++) + { + result = mcu.WriteBySend(nn::drivers::mcu::CTR::MCU_RTC_SEC_ADDR, bcd, RTC_PARAM_SIZE); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + if(result.IsSuccess()) + { + break; + } + nn::os::Thread::Sleep( + nn::fnd::TimeSpan::FromMilliSeconds( + nn::os::Tick::GetSystemCurrent().ToTimeSpan().GetMilliSeconds() % 100)); + + } + } + + 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; +} + +bool 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_RETURN_FALSE_IF_FAILED(result); + + 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()); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + nn::fs::DirectoryEntry entry; + s32 numEntry; + for (;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + if (numEntry == 0) + { + // ルートディレクトリを閉じる + dir.Finalize(); + + // ルートディレクトリの子を開く + for (entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++) + { + // ディレクトリなら削除する + 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_RETURN_FALSE_IF_FAILED(result); + + } + // ファイルなら削除する + 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_RETURN_FALSE_IF_FAILED(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); + } + } + } + + result = nn::fs::Unmount(common::TWL_ARCHIVE_NAME_TABLE[i]); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + } + + result = nn::am::DeleteAllTwlUserPrograms(); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + nn::fs::InitializeCtrFileSystem(); + return true; +} + +nn::Result ImportIvs() +{ + nn::Result result = nn::ResultSuccess(); + nn::fs::FileOutputStream fos; + + size_t bufSize = 1024; + common::HeapManager encHeap(bufSize); + void* enc = encHeap.GetAddr(); + if (enc != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::IVS_PATHNAME, enc, bufSize, &readSize); + if(result.IsSuccess()) + { + // SDから読み出し成功 + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if (result.IsSuccess()) + { + common::HeapManager decHeap(bufSize); + void *dec = decHeap.GetAddr(); + 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 SDCI.\n"); + } + } + } + } + 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); + } + 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 ImportIvsData() +{ + return ImportIvs().IsSuccess(); +} + +void ImportThreadFunc() +{ + nn::Result result; + s_IsImportSucceeded = true; + + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + + result = common::SdMountManager::Mount(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + + size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2); + NN_LOG("AllocatableSize = %d\n", bufSize); + + common::HeapManager heap(bufSize, AES_BLOCK_SIZE * 2); + void* buf = heap.GetAddr(); + if (buf != NULL) + { + if(!common::CopyDirectory( + &s_FileLists, + (::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, NULL, NULL)) + { + s_IsImportSucceeded = false; + return; + } + } + + common::SdMountManager::Unmount(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + + NN_LOG("Import Thread Finalize\n"); +} + +namespace +{ + +void ImportSaveData() +{ + // SDカードからNANDに読み込み + nn::Result result; + + // ファイルサイズ設定 + common::InitializeTransferProgress(s_SdFileSize.ctrFileSize); + + // SDカードにあるセーブデータディレクトリ以下のデータをNANDにコピー + 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::GetAllocatableSize() / 2; + NN_LOG("AllocatableSize = %d\n", bufSize); + + common::HeapManager heap(bufSize); + void* buf = heap.GetAddr(); + 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_RETURN_RESULT_IF_FAILED(result); + + // WiFiコネクションIDが仮の値であればWiFi設定は移行しない + // TWL修理に準拠している + u64 attestedUserId1 = 0; + u64 attestedUserId2 = 0; + const u32 WIFI_CONNECTION_USERID_OFFSET1 = 0xf0; + const u32 WIFI_CONNECTION_USERID_OFFSET2 = 0x1f0; + const u32 USERID_SIZE = 6; + const bit64 USERID_MASK = 0x7FFFFFFFFFF; // 43bit + + + void* NtrWifiSettingAddr = &reinterpret_cast(buf)->NtrWiFiSetting; + std::memcpy(&attestedUserId1, + &reinterpret_cast(NtrWifiSettingAddr)[WIFI_CONNECTION_USERID_OFFSET1], + USERID_SIZE); + attestedUserId1 &= USERID_MASK; + + std::memcpy(&attestedUserId2, + &reinterpret_cast(NtrWifiSettingAddr)[WIFI_CONNECTION_USERID_OFFSET2], + USERID_SIZE); + attestedUserId2 &= USERID_MASK; + + if (attestedUserId1 == attestedUserId2 && attestedUserId1 != 0) + { + // TWL WiFi設定 + result = nn::cfg::nor::CTR::WriteTwlWifiSetting(0, + reinterpret_cast (buf)->TwlWiFiSetting, common::TWL_WIFI_SETTING_SIZE); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + // NTR WiFi設定 + result = nn::cfg::nor::CTR::WriteNtrWifiSetting(0, + reinterpret_cast (buf)->NtrWiFiSetting, common::NTR_WIFI_SETTING_SIZE); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + } + else + { + // クリアしておく + result = nn::cfg::nor::CTR::ClearTwlWifiSetting(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::cfg::nor::CTR::ClearNtrWifiSetting(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + } + } + + COMMON_LOGGER_RETURN_RESULT_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::GetAllocatableSize() / 2; + NN_LOG("AllocatableSize = %d\n", bufSize); + + common::HeapManager heap(bufSize); + void* buf = heap.GetAddr(); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::VERSION_DATA_PATHNAME, buf, bufSize, &readSize); + if(result.IsSuccess()) + { + // バージョン情報を保持する + 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_RETURN_RESULT_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 ExistsIvsDirectory(std::string& ivsRoot) +{ + nn::Result result; + nn::fs::Directory dir; + + common::SdMountManager::Mount(); + + result = dir.TryInitialize(common::SD_NINTENDO_3DS_ROOT_PATH); + if(result.IsFailure()) + { + NN_DBG_PRINT_RESULT(result); + common::SdMountManager::Unmount(); + return false; + } + + wchar_t ivs[34]; + std::mbstowcs(ivs, ivsRoot.c_str(), ivsRoot.size() + 1); + + nn::fs::DirectoryEntry entry; + s32 numEntry; + for (;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + if (result.IsFailure()) + { + dir.Finalize(); + common::SdMountManager::Unmount(); + return false; + } + if (numEntry == 0) + { + dir.Finalize(); + common::SdMountManager::Unmount(); + return false; + } + else + { + // 比較する + if (entry.attributes.isDirectory) + { + NN_LOG("%ls\n", entry.entryName); + if(std::wcscmp(ivs, entry.entryName) == 0) + { + common::SdMountManager::Unmount(); + return true; + } + } + } + } +} + +nn::Result 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"); + return nn::am::DoCleanup(nn::fs::MEDIA_TYPE_NAND); + } + } + + return 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 IsImportThreadFinished() +{ + return s_ImportThread.IsValid() && !s_ImportThread.IsAlive(); +} + +void CreateWriteFinishedFile() +{ + CreateEmptyFile(common::FILENAME_TABLE[common::EXISTS_WRITE_FINISHED]); + common::ClearFileCheck(common::EXISTS_WRITE_FINISHED); +} + +void CreateConsoleInitializedFile() +{ + CreateEmptyFile(common::FILENAME_TABLE[common::EXISTS_CONSOLE_INTIALIZED]); + common::ClearFileCheck(common::EXISTS_CONSOLE_INTIALIZED); +} + +void CreateUpdateFinishedFile() +{ + CreateEmptyFile(common::FILENAME_TABLE[common::EXISTS_UPDATE_FINISHED]); + common::ClearFileCheck(common::EXISTS_UPDATE_FINISHED); +} + +void CreateRtcSyncFinishedFile() +{ + CreateEmptyFile(common::FILENAME_TABLE[common::EXISTS_RTC_SYNC_FINISHED]); + common::ClearFileCheck(common::EXISTS_RTC_SYNC_FINISHED); +} + +void CreateDownloadIvsFinishedFile() +{ + CreateEmptyFile(common::FILENAME_TABLE[common::EXISTS_DOWNLOAD_IVS]); + common::ClearFileCheck(common::EXISTS_DOWNLOAD_IVS); +} + +void CreateDeleteAccountFinishedFile() +{ + CreateEmptyFile(common::FILENAME_TABLE[common::EXISTS_DELETE_ACCOUNT]); + common::ClearFileCheck(common::EXISTS_DELETE_ACCOUNT); + +} + +void CreateTransferAccountFinishedFile() +{ + CreateEmptyFile(common::FILENAME_TABLE[common::EXISTS_TRANSFER_ACCOUNT]); + common::ClearFileCheck(common::EXISTS_TRANSFER_ACCOUNT); +} + +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 + { + //特に入力させる必要のない自動で設定する項目 + 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, bool* getIvs, bool* checkSd, bool* skipNup) +{ + nn::Result result; + bool retval = true; + common::ConfigFileLoader configfileLoader; + + common::SdMountManager::Mount(); + size_t size = 10240; + common::HeapManager heap(size); + void* heapAddr = heap.GetAddr(); + + 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); + } + + } + + { + const wchar_t* const NUP_ONLY_STR = L"NUP_ONLY"; + NN_NULL_ASSERT(nupOnly); + if (configfileLoader.ReadAsChar(NUP_ONLY_STR) != NULL) + { + s32 num = configfileLoader.ReadAsInteger(NUP_ONLY_STR); + if (num == 1) + { + *nupOnly = true; + COMMON_LOGGER("NUP Only Mode.\n"); + } + } + } + + { + const wchar_t* const GET_IVS_STR = L"GET_SDCI"; + NN_NULL_ASSERT(getIvs); + if (configfileLoader.ReadAsChar(GET_IVS_STR) != NULL) + { + s32 num = configfileLoader.ReadAsInteger(GET_IVS_STR); + if (num == 1) + { + *getIvs = true; + COMMON_LOGGER("GET SDCI Mode.\n"); + } + } + } + + { + const wchar_t* const CHECK_SD_STR = L"CHECK_SD"; + NN_NULL_ASSERT(checkSd); + if (configfileLoader.ReadAsChar(CHECK_SD_STR) != NULL) + { + s32 num = configfileLoader.ReadAsInteger(CHECK_SD_STR); + if (num == 1) + { + *checkSd = true; + COMMON_LOGGER("CHECK SD Mode.\n"); + } + } + } + + { + const wchar_t* const SKIP_NUP_STR = L"SKIP_NUP"; + NN_NULL_ASSERT(skipNup); + if (configfileLoader.ReadAsChar(SKIP_NUP_STR) != NULL) + { + s32 num = configfileLoader.ReadAsInteger(SKIP_NUP_STR); + if (num == 1) + { + *skipNup = true; + COMMON_LOGGER("Skip NUP Mode.\n"); + } + } + } + + configfileLoader.Finalize(); + + // 書き込み完了しなければfalse + if(!UpdateNetworkSetting(networkSetting)) + { + retval = false; + } + + } + else + { + NN_LOG("configfileLoader Initialize Failed\n"); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + retval = false; + } + } + 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, s64 fileSize) +{ + NN_ASSERT(path < common::TWL_PATHNAME_MAX); + + nn::Result result; + s_IsImportSucceeded = true; + + result = nn::fs::MountSpecialArchive(common::TWL_ARCHIVE_NAME_TABLE[path], common::TWL_FS_ARCHIVE_KIND[path]); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + + result = common::SdMountManager::Mount(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + + size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2); + NN_LOG("AllocatableSize = %d\n", bufSize); + + // ファイルサイズ設定 + common::InitializeTransferProgress(fileSize); + + common::HeapManager heap(bufSize, AES_BLOCK_SIZE * 2); + void* buf = heap.GetAddr(); + if (buf != NULL) + { + wchar_t archiveName[nn::fs::MAX_FILE_PATH_LENGTH]; + ::std::mbstowcs(archiveName, common::TWL_ARCHIVE_NAME_TABLE[path], std::strlen(common::TWL_ARCHIVE_NAME_TABLE[path]) + 1); + std::wstring archiveString(archiveName); + if(!common::CopyDirectory( + &s_FileLists, + (::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, NULL, NULL)) + { + s_IsImportSucceeded = false; + return; + } + } + + common::SdMountManager::Unmount(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + nn::fs::Unmount(common::TWL_ARCHIVE_NAME_TABLE[path]); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); +} + +void ImportTwlTitleSaveData(s64 fileSize) +{ + nn::Result result; + s_IsImportSucceeded = true; + + result = nn::fs::MountSpecialArchive(common::NAND_TWL_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_TWL_NAND); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + + result = common::SdMountManager::Mount(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + + size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2); + NN_LOG("AllocatableSize = %d\n", bufSize); + + // ファイルサイズ設定 + common::InitializeTransferProgress(fileSize); + + common::HeapManager heap(bufSize, AES_BLOCK_SIZE * 2); + void* buf = heap.GetAddr(); + if (buf != NULL) + { + if(!common::CopyDirectory( + &s_FileLists, + (::std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_TWL_ROOT_NAME)).c_str(), + (std::wstring(common::NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH) + ::std::wstring(L"/")).c_str(), + buf, bufSize, false, NULL, NULL)) + { + s_IsImportSucceeded = false; + return; + } + } + + common::SdMountManager::Unmount(); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); + nn::fs::Unmount(common::NAND_TWL_ARCHIVE_NAME); + COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, s_IsImportSucceeded); +} + +void ImportTwlPhotoDataFunc() +{ + COMMON_LOGGER("Import Twl Photo Data.\n"); + ImportTwlData(common::TWL_PHOTO, s_SdFileSize.twlPhotoFileSize); +} + +void ImportTwlSoundDataFunc() +{ + COMMON_LOGGER("Import Twl Sound Data.\n"); + ImportTwlData(common::TWL_SOUND, s_SdFileSize.twlSoundFileSize); +} + +void ImportTwlSaveDataFunc() +{ + COMMON_LOGGER("Import Twl Save Data.\n"); + ImportTwlTitleSaveData(s_SdFileSize.twlFileSize); +} + +void ImportTwlPhotoData() +{ + s_ImportThread.Start(ImportTwlPhotoDataFunc, s_ImportThreadStack); +} + +void ImportTwlSoundData() +{ + s_ImportThread.Start(ImportTwlSoundDataFunc, s_ImportThreadStack); +} + +void ImportTwlSaveData() +{ + s_ImportThread.Start(ImportTwlSaveDataFunc, s_ImportThreadStack); +} + + +void ClearFileReadResult() +{ + s_CheckedEqualsDeviceIdFileandDeviceId = false; + s_CheckedEqualsRegionDataandRegion = false; + s_ReadSerialNumber = false; +} + +nn::Result ExportCalData() +{ + using namespace nn::cfg::CTR::detail; + + nn::Result result; + common::CfgCalData cfgCalData; + common::SdReaderWriter sdWriter; + + COMMON_LOGGER("Export CalData\n"); + + result = common::SdMountManager::Mount(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.touchPanelCfgData, sizeof(TouchPanelCfgData), + GET_CFG_KEY(NN_CFG_HID, NN_CFG_HID_CAL_TOUCHPANEL)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.lcdFlickerCfgData, sizeof(LcdFlickerCfgData), + GET_CFG_KEY(NN_CFG_LCD, NN_CFG_LCD_CAL_FLICKER)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.fcramCfgData, sizeof(FcramCfgData), + GET_CFG_KEY(NN_CFG_FCRAM, NN_CFG_FCRAM_CAL_DELAY)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.rtcCfgData, sizeof(RtcCfgData), + GET_CFG_KEY(NN_CFG_RTC, NN_CFG_RTC_CAL_COMPENSATION)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.gyroscopeCfgData, sizeof(GyroscopeCfgData), + GET_CFG_KEY(NN_CFG_HID, NN_CFG_HID_CAL_GYROSCOPE)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.accelCfgData, sizeof(AccelCfgData), + GET_CFG_KEY(NN_CFG_HID, NN_CFG_HID_CAL_ACCELEROMETER)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.codecCfgData, sizeof(CodecCfgData), + GET_CFG_KEY(NN_CFG_CODEC, NN_CFG_CODEC_CAL)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = nn::cfg::CTR::init::GetConfig(&cfgCalData.mcuSlideVolumeRangeCfgData, sizeof(McuSlideVolumeRangeCfgData), + GET_CFG_KEY(NN_CFG_MCU, NN_CFG_MCU_SLIDE_VOLUME)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = sdWriter.WriteBufWithCmac(common::CFG_CALIBRATION_PATHNAME, &cfgCalData, sizeof(cfgCalData)); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = common::SdMountManager::Unmount(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + return nn::ResultSuccess(); +} + +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::GetAllocatableSize() / 2; + common::HeapManager heap(bufSize); + void* buf = heap.GetAddr(); + if (buf != NULL) + { + common::SdReaderWriter sdReader; + + size_t readSize; + result = sdReader.ReadBufWithCmac(common::CFG_CALIBRATION_PATHNAME, buf, bufSize, &readSize); + if(result.IsSuccess()) + { + // SDから読み出し成功 + std::memcpy(data, buf, readSize); + } + COMMON_LOGGER_RETURN_RESULT_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 SetupFileList() +{ + std::memset(&s_SdFileSize, 0, sizeof(s_SdFileSize)); + + // ファイル一覧を読み込む + nn::Result result = ReadFileList(&s_SdFileSize, &s_FileLists); + NN_UTIL_RETURN_IF_FAILED(result); + + return result; +} + +nn::Result ReadFileList(SdFileSize* sdFiles, common::ImportDataList* fileList) +{ + nn::Result result = nn::ResultSuccess(); + + COMMON_LOGGER("Read File List\n"); + + size_t readSize; + common::SdReaderWriter sdReader; + s64 fileSize; + { + nn::fs::FileInputStream file; + + // サイズ取得のため一時的に開く + result = file.TryInitialize(common::FILE_LIST_PATHNAME); + NN_UTIL_RETURN_IF_FAILED(result); + + result = file.TryGetSize(&fileSize); + if (result.IsFailure()) + { + file.Finalize(); + return result; + } + file.Finalize(); + } + + common::HeapManager heap(fileSize); + void* buf = heap.GetAddr(); + if(buf != NULL) + { + result = sdReader.ReadBufWithCmac(common::FILE_LIST_PATHNAME, buf, fileSize, &readSize); + if(result.IsSuccess()) + { + // ファイル一覧 + const char comma[] = ","; + const char newLine[] = "\n"; + char *token = NULL; + token = std::strtok(reinterpret_cast(buf), comma); + bool parseFileName = false; + common::ImportDataEntry entry; + + entry.fileName = std::string(token); + while( token != NULL) + { + if(parseFileName) + { + token = std::strtok(NULL, comma); + if(token != NULL) + { + entry.fileName = std::string(token); + } + } + else + { + token = std::strtok(NULL, newLine); + if(token != NULL) + { + s64 size = std::atoll(token); + if(size != -1) + { + entry.isDirectory = false; + sdFiles->totalFileSize += size; + + wchar_t wcToken[nn::fs::MAX_FILE_PATH_LENGTH]; + if(std::mbstowcs(wcToken, entry.fileName.c_str(), entry.fileName.size()) != entry.fileName.size() - 1) + { + if(std::wcsstr(wcToken, common::SD_SAVEDATA_ROOT_NAME) != NULL) + { + sdFiles->ctrFileSize += size; + } + else if(std::wcsstr(wcToken, common::SD_SAVEDATA_TWL_PHOTO_ROOT_NAME) != NULL) + { + sdFiles->twlPhotoFileSize += size; + } + else if(std::wcsstr(wcToken, common::SD_SAVEDATA_TWL_SOUND_ROOT_NAME) != NULL) + { + sdFiles->twlSoundFileSize += size; + } + else if(std::wcsstr(wcToken, common::SD_SAVEDATA_TWL_ROOT_NAME) != NULL) + { + sdFiles->twlFileSize += size; + } + } + } + else + { + entry.isDirectory = true; + } + + fileList->push_back(entry); + } + } + parseFileName = !parseFileName; + + } + + } + } + 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; + +} + +bool IsImportSucceeded() +{ + return s_IsImportSucceeded; +} + +nn::Result ImportData() +{ + static nn::Result result = nn::ResultSuccess(); + static bool init = true; + if(init) + { + init = false; + + // インポート前にACを止める + result = nn::ndm::SuspendScheduler(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + // NANDのごみを削除する + result = Cleanup(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + // NORデータを書き込む + result = ImportNorData(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + // 固体固有calLデータをSDカードに出力する + // 本体初期化後はcal値が設定されている + result = ExportCalData(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + // SDカードのセーブデータをNANDに書き込む + ImportSaveData(); + } + + return result; +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Importer.h b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Importer.h new file mode 100644 index 0000000..e2c49b1 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Importer.h @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------------* + 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 +#include +#include "HardwareStateManager.h" + +namespace ConsoleRestore +{ + +// SDカードのデバイスIDファイルと本体のデバイスIDが一致しているかどうか +nn::Result EqualsDeviceIdFileandDeviceId(common::HardwareStateManager& manager); + +// SDカードのリージョンと本体のリージョンが一致しているかどうか +nn::Result EqualsRegionDataandRegion(); + +// シリアルナンバーを取得する +nn::Result ReadSerialNumber(u8* serial); + +// 出力ファイル一覧を読み込む +nn::Result SetupFileList(); + +// インポート用のスレッドを終了する +void FinalizeImportThread(); + +// インポート用のスレッドが終了したかどうか +bool IsImportThreadFinished(); + +// 新たにスレッドを立て、TWLサウンド領域をインポートする +void ImportTwlSoundData(); + +// 新たにスレッドを立て、TWL-NAND領域をインポートする +void ImportTwlSaveData(); + +// 新たにスレッドを立て、TWL写真領域をインポートする +void ImportTwlPhotoData(); + +// 本体固有データを読み込む +// 新たにスレッドを立て、CTRセーブデータ領域をインポートする +nn::Result ImportData(); + +// インポート完了ファイルを作る +void CreateWriteFinishedFile(); + +// ネットワークアップデート完了ファイルを作る +void CreateUpdateFinishedFile(); + +// 本体初期化完了ファイルを作る +void CreateConsoleInitializedFile(); + +// RTC書き込み完了ファイルを作る +void CreateRtcSyncFinishedFile(); + +// IVSダウンロード完了ファイルを作る +void CreateDownloadIvsFinishedFile(); + +// アカウント削除完了ファイルを作る +void CreateDeleteAccountFinishedFile(); + +// アカウント移行完了ファイルを作る +void CreateTransferAccountFinishedFile(); + +// インポートスレッドの進捗を取得する +u32 GetImportProgress(); + +// NANDのごみを削除する +nn::Result 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, + common::DOWNLOAD_IVS_CHECK_PATHNAME, + common::DELETE_ACCOUNT_CHECK_PATHNAME, + common::TRANSFER_ACCOUNT_CHECK_PATHNAME +}; + +// ファイル存在確認をクリアする +void DeleteAllCheckFiles(); + +struct TimeZone +{ + u32 hour; + u32 minutes; + bool isMinus; + NN_PADDING3; +}; + +// ネットワーク設定ファイルを読み込む +bool ReadSetting(bool* nupOnly, bool* getIvs, bool* checkSd, bool* skipNup); + +// ネットワーク設定ファイルからNTPサーバの名前を取得する +// 先にReadSettingが成功している必要がある +char* GetNtpServerName(); + +// ネットワーク設定ファイルからタイムゾーンを取得する +// 先にReadSettingが成功している必要がある +TimeZone GetTimeZone(); + +struct CheckedNetworkSetting +{ + nn::ac::CTR::NetworkSetting setting; + bool isValid; + NN_PADDING3; +}; + +// SDカードから読み込んだネットワーク設定ファイルから生成した +// インターネット設定へのポインタを取得する +// インターネット設定は内部のバッファに読み込む +CheckedNetworkSetting* GetTempNetworkSetting(); + +// 国設定を読み込む +nn::Result ImportCountryLanguageData(); + +// RTCを読み込む +nn::Result ImportMcuRtc(common::HardwareStateManager& manager); + +// TWL写真領域を初期化してから本体初期化を行う +bool InitializeFileSystem(); + +// SDカードのファイルと本体情報の比較結果をクリアする +void ClearFileReadResult(); + +// プレイ履歴を読み込みます。ptmのセーブデータ移行後に呼び出す必要があります +void ImportPlayHistory(); + +// cfgのハードウェア固有領域をcal値で初期化します +nn::Result InitializeHardwareDependentSetting(); + +// SDカード上のバージョン情報を読みます +nn::Result ReadVersionData(); + +// SDカードのNintendo 3DS以下ににIVSと一致するディレクトリがあるかどうか +bool ExistsIvsDirectory(std::string& ivsRoot); + +// SDカードのIVSデータを書き込む +bool ImportIvsData(); + +// 書き込みが成功したかどうか +bool IsImportSucceeded(); + +} + +#endif /* IMPORTER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/NtpClient.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/NtpClient.cpp new file mode 100644 index 0000000..f2a5114 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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; // 送信するNTPパケット +NTP_Packet s_NTPRecvPacket; // 受信するNTPパケット +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; + } + + // デバッグ用に接続テストを無効化 + nn::ac::DebugSetNetworkArea(&config, nn::ac::NETWORK_AREA_LAN); + + // 接続要求を発行 + 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"); + + // 本体に書き込まれているネットワーク設定を使ってネットワーク接続を初期化 + result = InitializeNetwork(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + { + NN_LOG("Initializing socket..\n"); + + // 一つのスレッドからソケット API を利用する + const s32 sessionCount = 1; + // ソケットの送受信バッファとして 64 KB を割り当て + const size_t bufferSizeForSockets = 65536; + // ソケットライブラリに必要なワークサイズを求める + const size_t workSizeForLibrary = nn::socket::GetRequiredMemorySize(bufferSizeForSockets, sessionCount); + + // ワークメモリを確保して 4KB にアラインにする + 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パケットを生成して送る + // ******************************************************************************** + + // サーバアドレスの設定 + 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 + { + // サーバのホスト情報からIPアドレスをコピー + 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パケットをSNTP用に初期化する + 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; + + // サーバを指定してNTPパケットを送信する + 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; + } + + // サーバから時刻情報を受信する + // サーバを指定して受信を行う + // 受信するまで待たされる + 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サーバから取得した時刻を現地時間に変換する + *ntpTime = nn::socket::NtoHl(s_NTPRecvPacket.transmitTimestampSeconds) - 2208988800; /* 1970/01/01 からの秒数に変換 */ + 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に変換する + 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; + } + + // インターネット設定を元に戻す + 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/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/NtpClient.h b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/NtpClient.h new file mode 100644 index 0000000..0e9514e --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/NtpClient.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------* + 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 +{ + +// 新たにスレッドを立て、NTPサーバと同期する +u32 AdjustTime(); + +// NTPサーバとの同期が終了したかどうか +bool IsTimeAdjustFinished(); + +// NTPサーバとの同期が完了したかどうか +bool IsTimeAdjustSuccessed(); + +} + +#endif /* NTPCLIENT_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/OMakefile new file mode 100644 index 0000000..a09ecd0 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/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.* +CTR_APPTYPE = CARD + +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 + TitleDownloader.cpp + Shop.cpp + ../common/Util.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/VersionDetect.cpp + ../common/ResFont.cpp + ../common/HardwareStateManager.cpp + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = ../common/romfiles + +SHADER_BIN = nnfont_RectDrawerShader.shbin +SHADER_PATH = $(ROMFS_ROOT)/$(SHADER_BIN) + +ROMFS_DEPENDENCIES = $(SHADER_PATH) + +LIBS += libnn_cfg \ + libnn_crypto \ + libnn_mcu \ + libnn_ps \ + 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/RepairTool.desc + +include $(ROOT_OMAKE)/modulerules + +VERSION_H = $(file ../../generated/$(TARGET_PROGRAM)/version.h) + +$(VERSION_H): $(SOURCES) + section + bash genversion.sh + +RequireSetup($(VERSION_H)) +build: $(VERSION_H) $(DEFAULT_TARGETS) diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Shop.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Shop.cpp new file mode 100644 index 0000000..3a1b0bd --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Shop.cpp @@ -0,0 +1,560 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Shop.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 "Shop.h" +#include "CommonLogger.h" + +using namespace ES_NAMESPACE; +using namespace EC_NAMESPACE; + +#define NIM_SHOP_RESULT_CHECK(result) \ +do { \ + if (result.IsFailure()) \ + { \ + ECCustomerSupportCode csc; \ + nn::nim::Shop::GetCustomerSupportCode(&csc); \ + COMMON_LOGGER("CSCode: %d\n", csc); \ + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); \ + NN_DBG_PRINT_RESULT(result); \ + COMMON_LOGGER_DETAIL("Result = %08X\n", result.GetPrintableBits()); \ + s_ShopResult = result; \ + return; \ + } \ +} while(0) +namespace +{ + +nn::Result s_ShopResult = nn::ResultSuccess(); + +const size_t SHOP_OPERATION_THREAD_STACK_SIZE = 0x1000; +nn::os::Thread s_ShopOperationThread; +nn::os::StackBuffer s_ShopOperationThreadStack; + +const size_t EC_BUFFER_SIZE = 128 * 1024; +u8 s_EcBufffer[EC_BUFFER_SIZE]; +bool s_IsNimShopInitialized = false; + +struct ShopThreadParam +{ + ConsoleRestore::ShopOperation op; + nn::nim::TitleConfig config; +}; + +// TitleProgress の ==, != を定義 +bool operator==( + nn::nim::TitleProgress& lhs, + nn::nim::TitleProgress& rhs) +{ + return (lhs.state == rhs.state && + lhs.lastResult == rhs.lastResult && + lhs.downloadedSize == rhs.downloadedSize && + lhs.totalSize == rhs.totalSize); +} + +bool operator!=( + nn::nim::TitleProgress& lhs, + nn::nim::TitleProgress& rhs) +{ + return (! (lhs == rhs)); +} + +// TitleState の文字列を取得 +#ifdef COMMON_LOGGER_DETAIL_ENABLE +const char* GetTitleStateString(nn::nim::TitleState state) +{ + switch (state) + { + case nn::nim::TITLE_STATE_NOT_INITIALIZED: + return "NOT_INITIALIZED"; + case nn::nim::TITLE_STATE_INITIALIZED: + return "INITIALIZED"; + case nn::nim::TITLE_STATE_DOWNLOAD_TMD: + return "DOWNLOAD_TMD"; + case nn::nim::TITLE_STATE_PREPARE_SAVE_DATA: + return "PREPARE_SAVE_DATA"; + case nn::nim::TITLE_STATE_DOWNLOAD_CONTENTS: + return "DOWNLOAD_CONTENTS"; + case nn::nim::TITLE_STATE_WAIT_COMMIT: + return "WAIT_COMMIT"; + case nn::nim::TITLE_STATE_COMMITTING: + return "COMMITTING"; + case nn::nim::TITLE_STATE_FINISHED: + return "FINISHED"; + case nn::nim::TITLE_STATE_VERSION_MISMATCH: + return "VERSION_MISMATCH"; + default: + return "UNKNOWN"; + } +} +#endif + + +// 空文字列と NULL ポインタをそれぞれ と NULL として返す +#ifdef COMMON_LOGGER_DETAIL_ENABLE +const char* Cstr(const char* p) +{ + return p ? (p[0] ? p : "") : "NULL"; +} +#endif + +// ECTicketVersions を出力 +void PrintECTicketVersions(const ECTicketVersions& ticketVersions) +{ + if (ticketVersions.nTicketVersions == 0) + { + COMMON_LOGGER_DETAIL("No TicketVersions\n"); + return; + } + + COMMON_LOGGER_DETAIL("----- ECTicketVersions -----\n"); + for (u32 i = 0; i < ticketVersions.nTicketVersions; i++) + { +#ifdef COMMON_LOGGER_DETAIL_ENABLE + ECTicketVersion version = ticketVersions.ticketVersions[i]; +#endif + COMMON_LOGGER_DETAIL("%03d: 0x%016llx v%d\n", i, version.ticketId, version.version); + } + COMMON_LOGGER_DETAIL("---------------------------\n"); +} + +// ECAccountInfo の情報を出力 +void PrintECAccountInfo(const ECAccountInfo& accountInfo) +{ + COMMON_LOGGER_DETAIL("========== ECAccountInfo ==========\n"); + + COMMON_LOGGER_DETAIL("accountId\n %s\n", Cstr(accountInfo.accountId)); + + COMMON_LOGGER_DETAIL("accountStatus\n %s\n", Cstr(accountInfo.accountStatus)); + + if (accountInfo.accountBalance == NULL) + { + COMMON_LOGGER_DETAIL("accountBalance\n NULL\n"); + } + else + { + COMMON_LOGGER_DETAIL("accountBalance->amount\n %s\n", + Cstr(accountInfo.accountBalance->amount)); + COMMON_LOGGER_DETAIL("accountBalance->currency\n %s\n", + Cstr(accountInfo.accountBalance->currency)); + } + + if (accountInfo.agreedEULAVersion == NULL) + { + COMMON_LOGGER_DETAIL("agreedEULAVersion\n NULL\n"); + } + else + { + COMMON_LOGGER_DETAIL("agreedEULAVersion\n %lld\n", + *accountInfo.agreedEULAVersion); + } + + if (accountInfo.latestEULAVersion == NULL) + { + COMMON_LOGGER_DETAIL("latestEULAVersion\n NULL\n"); + } + else + { + COMMON_LOGGER_DETAIL("latestEULAVersion\n %lld\n", + *accountInfo.latestEULAVersion); + } + + COMMON_LOGGER_DETAIL("country\n %s\n", Cstr(accountInfo.country)); + + COMMON_LOGGER_DETAIL("extAccountId\n %s\n", Cstr(accountInfo.extAccountId)); + + COMMON_LOGGER_DETAIL("deviceToken\n %s\n", Cstr(accountInfo.deviceToken)); + + COMMON_LOGGER_DETAIL("weakToken\n %s\n", Cstr(accountInfo.weakToken)); + + COMMON_LOGGER_DETAIL("isStandbyMode\n %d\n", accountInfo.isStandbyMode); + + if (accountInfo.owned == NULL) + { + COMMON_LOGGER_DETAIL("owned\n NULL\n"); + } + else + { + PrintECTicketVersions(*(accountInfo.owned)); + } +} + +nn::Result PrintNetworkSetting() +{ + nn::Result result; + nn::ac::NetworkSetting networkSetting; + result = 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 result; +} + + +nn::Result ConnectNetwork() +{ + nn::Result result; + nn::ac::Config config; + + result = nn::ac::CreateDefaultConfig(&config); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + NN_UTIL_RETURN_IF_FAILED(result); + + result = nn::ac::ConnectWithoutEula(config); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + NN_UTIL_RETURN_IF_FAILED(result); + + COMMON_LOGGER_DETAIL("Success nn::ac::ConnectWithoutEula\n"); + + result = PrintNetworkSetting(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + NN_UTIL_RETURN_IF_FAILED(result); + + return result; +} + +nn::Result InitializeInternal() +{ + nn::Result result; + + result = nn::ac::InitializeInternal(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + NN_UTIL_RETURN_IF_FAILED(result); + + result = ConnectNetwork(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + NN_UTIL_RETURN_IF_FAILED(result); + + return result; +} + +nn::Result FinalizeInternal() +{ + nn::Result result = nn::ResultSuccess(); + + nn::ac::CloseAll(); + + result = nn::ac::FinalizeInternal(); + NN_UTIL_RETURN_IF_FAILED(result); + + return result; +} + +} + + +namespace ConsoleRestore{ + +nn::Result ShopOperationConnect(); +nn::Result ShopOperationFinalize(); + + +nn::Result CheckStandbyMode(s32 isStandbyMode) +{ + if(isStandbyMode) + { + COMMON_LOGGER("Shop is Standby Mode\n"); + return nn::MakePermanentResult(nn::Result::SUMMARY_INVALID_STATE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_NOT_AUTHORIZED); + } + else + { + return nn::ResultSuccess(); + } +} + +nn::Result ShopOperationConnect(ECAccountInfo** pAccountInfo) +{ + nn::Result result = nn::ResultSuccess(); + + /* ------------------------------------------------------------------- + Connect + -------------------------------------------------------------------- */ + COMMON_LOGGER_DETAIL("nim::Shop::Connect\n"); + result = nn::nim::Shop::Connect(pAccountInfo, s_EcBufffer, EC_BUFFER_SIZE); + NN_UTIL_RETURN_IF_FAILED(result); + result = CheckStandbyMode((*pAccountInfo)->isStandbyMode); + NN_UTIL_RETURN_IF_FAILED(result); + + PrintECAccountInfo(**pAccountInfo); + COMMON_LOGGER_DETAIL("\n"); + + return result; +} + +nn::Result ShopOperationInitialize() +{ + nn::Result result = nn::ResultSuccess(); + + /* ------------------------------------------------------------------- + Initialize + -------------------------------------------------------------------- */ + if (!s_IsNimShopInitialized) + { + COMMON_LOGGER_DETAIL("nim::InitializeForShop\n"); + result = nn::nim::InitializeForShop(); + NN_UTIL_RETURN_IF_FAILED(result); + s_IsNimShopInitialized = true; + } + + /* ------------------------------------------------------------------- + SetParameter + -------------------------------------------------------------------- */ + COMMON_LOGGER_DETAIL("nim::Shop::SetApplication Id\n"); + + nn::nim::Shop::SetApplicationId(); + NN_UTIL_RETURN_IF_FAILED(result); + + COMMON_LOGGER_DETAIL("nim::Shop::SetTIN\n"); + result = nn::nim::Shop::SetTin(CONSOLE_RESTORE_TIN); + NN_UTIL_RETURN_IF_FAILED(result); + + return result; +} + +nn::Result ShopOperationConnect() +{ + nn::Result result; + result = ShopOperationInitialize(); + NN_UTIL_RETURN_IF_FAILED(result); + + /* ------------------------------------------------------------------- + Connect + -------------------------------------------------------------------- */ + ECAccountInfo* pAccountInfo; + result = ShopOperationConnect(&pAccountInfo); + NN_UTIL_RETURN_IF_FAILED(result); + + return result; +} + +nn::Result ShopOperationFinalize() +{ + nn::Result result = nn::ResultSuccess(); + + /* ------------------------------------------------------------------- + Finalize + -------------------------------------------------------------------- */ + COMMON_LOGGER_DETAIL("nim::FinalizeForShop\n"); + result = nn::nim::FinalizeForShop(); + NN_UTIL_RETURN_IF_FAILED(result); + s_IsNimShopInitialized = false; + + COMMON_LOGGER_DETAIL("util::ac::Finalize\n"); + result = FinalizeInternal(); + NN_UTIL_RETURN_IF_FAILED(result); + + return result; +} + +namespace +{ + +void ShopOperationUnregisterCore(bool force) +{ + nn::Result result; + result = ShopOperationInitialize(); + NIM_SHOP_RESULT_CHECK(result); + ECAccountInfo* pAccountInfo; + result = ShopOperationConnect(&pAccountInfo); + NIM_SHOP_RESULT_CHECK(result); + if (force) + { + if (pAccountInfo->accountStatus && (pAccountInfo->accountStatus[0] == 'R' || pAccountInfo->accountStatus[0] + == 'T')) + { + COMMON_LOGGER_DETAIL("nim::Shop::Unregister\n"); + result = nn::nim::Shop::Unregister(); + NIM_SHOP_RESULT_CHECK(result); + } + } + else + { + if (pAccountInfo->accountStatus && (pAccountInfo->accountStatus[0] == 'R')) + { + COMMON_LOGGER_DETAIL("nim::Shop::Unregister\n"); + result = nn::nim::Shop::Unregister(); + NIM_SHOP_RESULT_CHECK(result); + } + else + { + COMMON_LOGGER_DETAIL("Not registered.\n"); + } + } +} + +// メイン関数 +void ShopOperationSingleThreadFunc(ShopThreadParam param) +{ + nn::Result result; + + s_ShopResult = nn::ResultSuccess(); + + COMMON_LOGGER_DETAIL("util::ac::Initialize\n"); + result = InitializeInternal(); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + NIM_SHOP_RESULT_CHECK(result); + + switch(param.op) + { + case SHOP_OPERATION_CONNECT: + { + result = ShopOperationConnect(); + NIM_SHOP_RESULT_CHECK(result); + } + break; + + case SHOP_OPERATION_GET_IVS: + { + result = ShopOperationInitialize(); + NIM_SHOP_RESULT_CHECK(result); + // IVSを取得する + result = nn::nim::Shop::ImportIvsFromInfrastructure(); + NIM_SHOP_RESULT_CHECK(result); + } + break; + + case SHOP_OPERATION_UNREGISTER: + { + ShopOperationUnregisterCore(false); + } + break; + + case SHOP_OPERATION_FORCE_UNREGISTER: + { + ShopOperationUnregisterCore(true); + } + break; + + case SHOP_OPERATION_CONNECT_WITHOUT_CLOSE: + { + result = ShopOperationConnect(); + NIM_SHOP_RESULT_CHECK(result); + return; + } + + + { + case SHOP_OPERATION_DOWNLOAD_TITLE: + COMMON_LOGGER_DETAIL("Try Download %016llx\n", param.config.titleId); + result = nn::nim::Shop::StartDownload(param.config); + + if (result == nn::nim::ResultBusy() || result == nn::nim::ResultAlreadyDone()) + { + COMMON_LOGGER("Download Content -> Nim is busy\n"); + } + else if (result == nn::nim::ResultInvalidTitle()) + { + COMMON_LOGGER("Download Content -> Invalid Title\n"); + } + else if (result.IsFailure()) + { + COMMON_LOGGER("Download Content -> Failure %x\n", result.GetPrintableBits()); + } + + /* ------------------------------------------------------------------- + GetProgress + -------------------------------------------------------------------- */ + + COMMON_LOGGER_DETAIL("nim::Shop::GetProgress()\n"); + nn::nim::TitleProgress before; + nn::nim::TitleProgress latest; + while (true) + { + result = nn::nim::Shop::GetProgress(&latest); + + NIM_SHOP_RESULT_CHECK(result); + NIM_SHOP_RESULT_CHECK(latest.lastResult); + + // Print progress + if (latest != before) + { + COMMON_LOGGER_DETAIL("%8lld / %8lld (%d:%s)\n", + latest.downloadedSize, + latest.totalSize, + latest.state.Get(), + GetTitleStateString(latest.state)); + + if (latest.state == nn::nim::TITLE_STATE_FINISHED) + { + COMMON_LOGGER_DETAIL("Finished Download\n"); + break; + } + + before = latest; + } + + // あまりにも頻繁に GetProgress を呼ぶと、ダウンロード処理の速度に + // 影響が出てしまいます。少なくとも数フレーム以上の間隔をあけて + // GetProgress することを推奨します。 + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(100)); + } + } + break; + } + + result = ShopOperationFinalize(); + NIM_SHOP_RESULT_CHECK(result); +} + +} + +void StartShopOperationSingle(ShopOperation op, nn::nim::TitleConfig config) +{ + COMMON_LOGGER_DETAIL("Start ShopOperationSingle, %s\n", SHOP_OPERATION_STR[op]); + + ShopThreadParam param; + param.op = op; + param.config = config; + s_ShopOperationThread.Start(ShopOperationSingleThreadFunc, param, s_ShopOperationThreadStack); +} + +void StartShopOperationSingle(ShopOperation op) +{ + ShopThreadParam param; + param.op = op; + + COMMON_LOGGER_DETAIL("Start ShopOperationSingle, %s\n", SHOP_OPERATION_STR[op]); + s_ShopOperationThread.Start(ShopOperationSingleThreadFunc, param, s_ShopOperationThreadStack); +} + +void FinalizeShopOperationSingle() +{ + COMMON_LOGGER_DETAIL("Finalize ShopOperationSingle\n"); + s_ShopOperationThread.Join(); + s_ShopOperationThread.Finalize(); +} + +bool IsShopOperationSingleFinished() +{ + return s_ShopOperationThread.IsValid() && !s_ShopOperationThread.IsAlive(); +} + +nn::Result GetShopOperationSingleResult() +{ + return s_ShopResult; +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Shop.h b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Shop.h new file mode 100644 index 0000000..1cf5eac --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Shop.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Shop.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 SHOP_H_ +#define SHOP_H_ + +#include +#include + +namespace ConsoleRestore +{ + +// ショップサーバにConsoleResotoreが接続するためのTINコード +const char* const CONSOLE_RESTORE_TIN = "987654321"; + +typedef enum SHOP_OPERATION +{ + SHOP_OPERATION_CONNECT, // Shop::ConnectしてCloseするだけ + SHOP_OPERATION_GET_IVS, // Shop::ImportIvsFromInfrastructureを実行 + SHOP_OPERATION_UNREGISTER, // Shop::Unregisterを実行 + SHOP_OPERATION_FORCE_UNREGISTER, // アカウント移行後でもUnregisterを実行 + SHOP_OPERATION_CONNECT_WITHOUT_CLOSE, // Shop::ConnectしてCloseしない + SHOP_OPERATION_DOWNLOAD_TITLE, // Titleをダウンロードする + SHOP_OPERATION_NUM_MAX + +} ShopOperation; + +// ショップ操作のモード表示用文字列(デバッグ用) +const char* const SHOP_OPERATION_STR[] = +{ + "Connect", + "Get SDCI", + "Unregister", + "Force Unregister", + "Connect Without Close", + "Download Title" +}; + +// 新たにスレッドを立て、ショップ操作を開始する +void StartShopOperationSingle(ShopOperation op, nn::nim::TitleConfig config); + +// 新たにスレッドを立て、ショップ操作を開始する +void StartShopOperationSingle(ShopOperation op); + +// ショップ操作スレッドを終了する +void FinalizeShopOperationSingle(); + +// ショップ操作スレッドが終了したかどうか +bool IsShopOperationSingleFinished(); + +// ショップ操作のResultを取得する +nn::Result GetShopOperationSingleResult(); + +} + +#endif /* SHOP_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/TitleDownloader.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/TitleDownloader.cpp new file mode 100644 index 0000000..469fae3 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/TitleDownloader.cpp @@ -0,0 +1,261 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: TitleDownloader.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 "FileName.h" +#include "CommonLogger.h" +#include "HeapManager.h" +#include "TitleDownloader.h" +#include "Shop.h" +#include "SdReaderWriter.h" + + +namespace +{ + +bit8 s_buffer1[400 * 1024]; + +const size_t TITLE_DOWNLOADER_STACK_SIZE = 0x1000; +nn::os::Thread s_TitleDownloaderThread; +nn::os::StackBuffer s_TitleDownloaderThreadStack; +u64 s_Progress; + +nn::fs::MediaType GetMediaType(const ES_NAMESPACE::ESTitleId titleId) +{ + return (nn::CTR::IsTwlApp(titleId)) ? + nn::fs::MEDIA_TYPE_NAND : nn::fs::MEDIA_TYPE_SDMC; +} + +const char *GetAttribute(EC_NAMESPACE::ECNameValuePair *attributes, u32 nAttributes, const char *attributeName) +{ + for(int i=0; inEntries == 1) + { + *entry = &(titleCatalog->entries[0]); + } + else + { + return nn::MakeStatusResult(nn::Result::SUMMARY_NOT_FOUND, nn::Result::MODULE_COMMON, nn::Result::DESCRIPTION_NOT_FOUND); + } + + } + return result; +} + +nn::Result GetTitleConfig(const ES_NAMESPACE::ESTitleId titleId, nn::nim::TitleConfig *titleConfig) +{ + EC_NAMESPACE::ECTitleCatalogEntry *entry; + NN_UTIL_RETURN_IF_FAILED(GetEntry(titleId, &entry)); + + titleConfig->titleId=titleId; + titleConfig->version=std::strtoull(GetAttribute(entry->attributes, entry->nAttributes, "Version"), NULL, 10); + titleConfig->ratingAge=0; + titleConfig->media=GetMediaType(titleId); + + COMMON_LOGGER_DETAIL("titleId : 0x%016llx\n", titleConfig->titleId); + COMMON_LOGGER_DETAIL("version : %lld\n" , titleConfig->version); + COMMON_LOGGER_DETAIL("ratingAge : %d\n" , titleConfig->ratingAge); + COMMON_LOGGER_DETAIL("media : %d\n" , titleConfig->media); + + + return nn::ResultSuccess(); +} + + +} // namespace + +namespace ConsoleRestore +{ + +nn::Result TitleDownloader::m_Result = nn::ResultSuccess(); + +void TitleDownloaderThreadFunc() +{ + TitleDownloader TwlTitleDownloader; + + s_Progress = 0; + TwlTitleDownloader.Start(); +} + +void StartTitleDownload() +{ + s_TitleDownloaderThread.Start(TitleDownloaderThreadFunc, s_TitleDownloaderThreadStack); +} + +bool IsDownloadTitleFinished() +{ + return s_TitleDownloaderThread.IsValid() && !s_TitleDownloaderThread.IsAlive(); +} + +void FinalizeTitleDownload() +{ + s_TitleDownloaderThread.Join(); + s_TitleDownloaderThread.Finalize(); +} + +bool DownloadTitleSucceeded() +{ + return TitleDownloader::m_Result.IsSuccess() && GetShopOperationSingleResult().IsSuccess(); +} + +u32 GetTitleDownloadProgress() +{ + return s_Progress; +} + + +TitleDownloader::TitleDownloader() : m_TwlTiteNum(0) +{ + for(u32 i = 0; i < TWL_IMPORTABLE_TITLE_MAX; i++) + { + m_ProgramIdList[i] = 0; + } + +} + +TitleDownloader::~TitleDownloader() +{ + +} + + +nn::Result WaitCancelled() +{ + nn::nim::TitleProgress progress; + while(true) + { + // キャンセルがResultとして返ってくる / ダウンロード終了まで待つ + NN_UTIL_RETURN_IF_FAILED(nn::nim::Shop::GetProgress(&progress)); + if(progress.lastResult==nn::nim::ResultCancelRequested() || progress.state==nn::nim::TITLE_STATE_FINISHED) + { + break; + } + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(100)); + } + return nn::ResultSuccess(); +} + +void WaitShopOperationAndFinalize() +{ + while (!IsShopOperationSingleFinished()) + { + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(100)); + } + + FinalizeShopOperationSingle(); +} + +void TitleDownloader::Start() +{ + m_Result = ListUp(); + if(m_Result.IsFailure()) + { + return; + } + + for(u8 i = 0; i < m_TwlTiteNum; i++) + { + s_Progress = i * 100 / m_TwlTiteNum; + StartShopOperationSingle(SHOP_OPERATION_CONNECT_WITHOUT_CLOSE); + WaitShopOperationAndFinalize(); + + nn::nim::TitleConfig config; + m_Result = GetTitleConfig(m_ProgramIdList[i], &config); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(m_Result); + if (m_Result.IsSuccess()) + { + StartShopOperationSingle(SHOP_OPERATION_DOWNLOAD_TITLE, config); + WaitShopOperationAndFinalize(); + } + } +} + +nn::Result TitleDownloader::ListUp() +{ + COMMON_LOGGER("Read TwlTitle List.\n"); + + size_t heapSize = common::GetAllocatableSize(); + common::HeapManager heap(heapSize); + char* titleListBuf = reinterpret_cast (heap.GetAddr()); + + size_t readSize = 0; + if (titleListBuf != NULL) + { + common::SdReaderWriter sdReader; + m_Result = sdReader.ReadBufWithCmac(common::TWL_TITLELIST_PATHNAME, titleListBuf, heapSize, &readSize); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(m_Result); + if (m_Result.IsSuccess()) + { + u32 listHead = 0; + for (u32 i = 0; i < readSize; i++) + { + if (titleListBuf[i] == '\n') + { + char ProgramIdStr[32]; + char *error; + std::memcpy(ProgramIdStr, &titleListBuf[listHead], i - listHead); + m_ProgramIdList[m_TwlTiteNum] = std::strtoull(ProgramIdStr, &error, 16); + m_TwlTiteNum++; + COMMON_LOGGER_DETAIL("%016llx\n", m_ProgramIdList[m_TwlTiteNum - 1]); + + listHead = i + 1; + } + } + } + COMMON_LOGGER("%d Title(s) found.\n", m_TwlTiteNum); + } + else + { + m_Result = nn::Result(nn::Result::LEVEL_FATAL, nn::Result::SUMMARY_OUT_OF_RESOURCE, nn::Result::MODULE_COMMON, + nn::Result::DESCRIPTION_OUT_OF_MEMORY); + } + + return m_Result; +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/TitleDownloader.h b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/TitleDownloader.h new file mode 100644 index 0000000..cd1818e --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/TitleDownloader.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: TitleDownloader.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 TITLEDOWNLOADER_H_ +#define TITLEDOWNLOADER_H_ + +#include + +namespace ConsoleRestore +{ + +// 新たにスレッドを立て、タイトルのダウンロードを開始する +void StartTitleDownload(); + +// タイトルのダウンロードスレッドが終了したかどうか +bool IsDownloadTitleFinished(); + +// タイトルのダウンロードスレッドが成功したかどうか +bool DownloadTitleSucceeded(); + +// タイトルのダウンロードスレッドを終了する +void FinalizeTitleDownload(); + +// タイトルダウンロードの進捗を取得する +u32 GetTitleDownloadProgress(); + +// ショップからタイトルをダウンロードするためのクラス +class TitleDownloader +{ +public: + TitleDownloader(); + virtual ~TitleDownloader(); + + // タイトルのダウンロードを開始する + void Start(); + + NN_PADDING4; + static nn::Result m_Result; + +private: + nn::Result ListUp(); + + static const size_t TWL_IMPORTABLE_TITLE_MAX = 30; + + nn::ProgramID m_ProgramIdList[TWL_IMPORTABLE_TITLE_MAX]; + u32 m_TwlTiteNum; + + +}; + +} + +#endif /* TITLEDOWNLOADER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Updater.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Updater.cpp new file mode 100644 index 0000000..55addb4 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Updater.cpp @@ -0,0 +1,251 @@ +/*---------------------------------------------------------------------------* + 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); \ + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); \ + NN_DBG_PRINT_RESULT(result); \ + COMMON_LOGGER_DETAIL("Result = %08X\n", result.GetPrintableBits()); \ + 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); + + COMMON_LOGGER_DETAIL("Success nn::ac::ConnectWithoutEula\n"); + + NN_UTIL_RETURN_IF_FAILED(PrintNetworkSetting()); + + return result; +} + +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 result; +} + +nn::Result FinalizeInternal() +{ + nn::Result result = nn::ResultSuccess(); + + nn::ac::CloseAll(); + + result = nn::ac::FinalizeInternal(); + NN_UTIL_RETURN_IF_FAILED(result); + + return result; +} + +} + +void UpdateThreadFunc() +{ + nn::Result result; + + COMMON_LOGGER_DETAIL("********************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 + -------------------------------------------------------------------- */ + COMMON_LOGGER_DETAIL("[Updater] nn::nim::InitializeForUpdater\n"); + result = nn::nim::InitializeForUpdater(); + NIM_UPDATER_RESULT_CHECK(result); + + COMMON_LOGGER_DETAIL("[Updater] InitializeInternal\n"); + result = InitializeInternal(); + NIM_UPDATER_RESULT_CHECK(result); + + + /* ------------------------------------------------------------------- + StartNetworkUpdate + -------------------------------------------------------------------- */ + COMMON_LOGGER_DETAIL("[Updater] nn::nim::Updater::StartNetworkUpdate()\n"); + result = nn::nim::Updater::StartNetworkUpdate(); + NIM_UPDATER_RESULT_CHECK(result); + + /* ------------------------------------------------------------------- + GetProgress + -------------------------------------------------------------------- */ + COMMON_LOGGER_DETAIL("[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); + COMMON_LOGGER_DETAIL("\x1b[1A\x1b[K"); + COMMON_LOGGER_DETAIL("Downloading %2lld/%2lld %8lld/%8lld (%d)\n", + progress.downloadedTitleNum, + progress.totalTitleNum, + progress.currentDownloadedSize, + progress.currentTotalSize, + static_cast(progress.state)); + + // ゼロ除算を防ぐ + 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 + -------------------------------------------------------------------- */ + COMMON_LOGGER_DETAIL("[Updater] nn::nim::FinalizeForUpdater\n"); + result = nn::nim::FinalizeForUpdater(); + NIM_UPDATER_RESULT_CHECK(result); + + result = FinalizeInternal(); + NIM_UPDATER_RESULT_CHECK(result); + + COMMON_LOGGER_DETAIL("[Updater] Finish nim Updater demo.\n"); + +} + +void StartFGNetworkUpdate() +{ + COMMON_LOGGER_DETAIL("Start FGNetworkUpdate\n"); + s_Result = nn::ResultSuccess(); + s_UpdaterThread.Start(UpdateThreadFunc, s_UpdaterThreadStack); +} + +void FinishFGNetworkUpdate() +{ + COMMON_LOGGER_DETAIL("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/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Updater.h b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Updater.h new file mode 100644 index 0000000..7802590 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/Updater.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------------* + 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(); + +// ネットワークアップデートのResultを取得する +nn::Result GetUpdateResult(); + +} + +#endif /* UPDATER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/model.cbmd b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/model.cbmd differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/sound.cbsd b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/sound.cbsd differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/unknown24x24.ctpk b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +888yyYyYyyyYyyYyyyyYyYy8 \ No newline at end of file diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/unknown48x48.ctpk b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +Y8888ƺ8888YYyyYYޚ޺yY8YyYYޚyY8ޚ8 \ No newline at end of file diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/genversion.sh b/branches/1stNUP_7/ConsoleDataMigration/sources/ConsoleRestore/genversion.sh new file mode 100755 index 0000000..a774086 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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'`\"" > ../generated/ConsoleRestore/version.h diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/OMakefile new file mode 100644 index 0000000..0ebeff4 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/OMakefile @@ -0,0 +1,27 @@ +#!/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: $(exist-dirs \ + common \ + ConsoleBackup \ + ConsoleRestore \ + tools \ + ) + +if $(IsTestBuild) + .SUBDIRS: $(exist-dirs tests) + +DefineDefaultRules() diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/OMakeroot b/branches/1stNUP_7/ConsoleDataMigration/sources/OMakeroot new file mode 100644 index 0000000..7ee1cb5 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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:$ +#---------------------------------------------------------------------------- + +# fBNgCAEgɂ‚Ă̐ +# +# a) \[XR[h[gfBNgɔzuꍇ +# : +# /OMakeroot +# /foo/bar/OMakefile +# +# : +# OMakefile ƓfBNgȉ objects images ܂B +# +# /foo/bar/objects/... +# /foo/bar/images/.. +# +# +# b) \[XR[h sources ȉɔzuꍇ +# : +# /OMakeroot +# /sources/foo/bar/OMakefile +# +# : +# [gfBNgȉ objects images ܂B +# +# /objects/foo/bar/... +# /images/foo/bar/... +# +# + +# [g‹ϐ̎擾 +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 v܂BpXݒ肷邩Aǂ炩`ĉB) + 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/1stNUP_7/ConsoleDataMigration/sources/common/Aes_define.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/Aes_define.h new file mode 100644 index 0000000..68a4cc6 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/Aes_define.h @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------------* + 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_ + +//マスタリング用ビルド時に有効にする +//#define USE_PROD_KEY + +#ifdef NN_BUILD_RELEASE +#ifndef USE_PROD_KEY +#warning !! Using Development Key on Release Build !! +#endif +#endif + +#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/1stNUP_7/ConsoleDataMigration/sources/common/CommonLogger.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/CommonLogger.cpp new file mode 100644 index 0000000..373230e --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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() +{ + + +} + +CommonLogger::~CommonLogger() +{ + +} + +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 sdLock(m_CriticalSection); + va_list vlist; + + va_start(vlist, fmt); + + NN_LOGV(fmt, vlist); + GetSdInstance()->Print(fmt, vlist); + GetConsoleInstance()->AddText(fmt, vlist); + + va_end(vlist); +} + +void CommonLogger::PrintResultSdLog(const char* fmt, ...) +{ + nn::os::CriticalSection::ScopedLock sdLock(m_CriticalSection); + va_list vlist; + + va_start(vlist, fmt); + + GetSdInstance()->Print(fmt, vlist); + + va_end(vlist); +} + +void CommonLogger::ClearSdLog() +{ + nn::os::CriticalSection::ScopedLock sdLock(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/1stNUP_7/ConsoleDataMigration/sources/common/CommonLogger.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/CommonLogger.h new file mode 100644 index 0000000..4c0ae93 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/CommonLogger.h @@ -0,0 +1,149 @@ +/*---------------------------------------------------------------------------* + 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" + +#define COMMON_LOGGER( ... ) (void)common::Logger::GetLoggerInstance()->Print(__VA_ARGS__) +#define COMMON_LOGGER_RESULT(result, func) \ + NN_DBG_PRINT_RESULT(result); \ + (void)common::Logger::GetLoggerInstance()->PrintResultSdLog("Func = %s\n", func); \ + (void)common::Logger::GetLoggerInstance()->PrintResultSdLog("Result = %X\n", result.GetPrintableBits()); \ + +#ifndef NN_SWITCH_DISABLE_DEBUG_PRINT +#define COMMON_LOGGER_DEBUG( ... ) COMMON_LOGGER(__VA_ARGS__) +#else // ifndef NN_SWITCH_DISABLE_DEBUG_PRINT +#define COMMON_LOGGER_DEBUG( ... ) ((void)0) +#endif // ifndef NN_SWITCH_DISABLE_DEBUG_PRINT else + +#ifndef NN_SWITCH_DISABLE_DEBUG_PRINT +#ifdef COMMON_LOGGER_DETAIL_ENABLE +#define COMMON_LOGGER_DETAIL(...) COMMON_LOGGER(__VA_ARGS__) +#else +#define COMMON_LOGGER_DETAIL( ... ) ((void)0) +#endif +#else +#define COMMON_LOGGER_DETAIL( ... ) ((void)0) +#endif + + +#define COMMON_LOGGER_RESULT_WITH_LINE(result, line, func) \ + NN_LOG("%s\n", func); \ + NN_LOG("%d\n", line); \ + NN_DBG_PRINT_RESULT(result); \ + (void)common::Logger::GetLoggerInstance()->PrintResultSdLog("Func = %s\n", func); \ + (void)common::Logger::GetLoggerInstance()->PrintResultSdLog("line = %d\n", line); \ + (void)common::Logger::GetLoggerInstance()->PrintResultSdLog("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__); \ + } \ + +#define COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result) \ + if(result.IsFailure()) \ + { \ + COMMON_LOGGER_RESULT_WITH_LINE(result, __LINE__, __func__); \ + return result; \ + } \ + +#define COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result) \ + if(result.IsFailure()) \ + { \ + COMMON_LOGGER_RESULT_WITH_LINE(result, __LINE__, __func__); \ + return false; \ + } \ + +#define COMMON_LOGGER_RETURN_VOID_IF_FAILED(result) \ + if(result.IsFailure()) \ + { \ + COMMON_LOGGER_RESULT_WITH_LINE(result, __LINE__, __func__); \ + return; \ + } \ + +#define COMMON_LOGGER_RETURN_VOID_SET_BOOL_IF_FAILED(result, setbool) \ + if(result.IsFailure()) \ + { \ + COMMON_LOGGER_RESULT_WITH_LINE(result, __LINE__, __func__); \ + setbool = false; \ + return; \ + } \ + +#define COMMON_LOGGER_RETURN_FALSE(result) \ + COMMON_LOGGER_RESULT_WITH_LINE(result, __LINE__, __func__); \ + return false; \ + +namespace common +{ + +namespace Logger +{ + +// SDカードのログと下画面ログを同時に扱うためのクラス +class CommonLogger +{ +public: + CommonLogger(); + ~CommonLogger(); + + void Initialize(u32 width, u32 height, u32 maxLine, demo::RenderSystemDrawing* renderSystem); + void Finalize(); + + // SDログに書き込み、下画面ログ出力のためのバッファに溜め込む + void Print(const char* fmt, ...); + + // SDログのみにResult値を出力する + void PrintResultSdLog(const char* fmt, ...); + + // SDカードのログファイルを消去する + void ClearSdLog(); + + // 下画面ログを上スクロールする + 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/1stNUP_7/ConsoleDataMigration/sources/common/DrawSystemState.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/DrawSystemState.cpp new file mode 100644 index 0000000..68c8b3e --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/DrawSystemState.cpp @@ -0,0 +1,202 @@ +/*---------------------------------------------------------------------------* + 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" +#include "ResFont.h" + +#include + +const u16 PROGRESS_MAX_LINES = 129; + +namespace common +{ + +namespace +{ +u8 s_CupMajor; +u8 s_CupMinor; +u8 s_CupMicro; +u8 s_NupMajor; +nn::cfg::CTR::CfgRegionCode s_Region; +u8 s_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN + 1]; +bit64 s_DeviceId; +char8 s_MacAddress[nn::nwm::Mac::MAC_STRING_SIZE]; +u64 s_FriendCode; +u8 s_BatteryRemain; +std::string s_AdapterState; +u8 s_Progress; +::std::vector* s_OperationMessage; +bool s_ReadFriendCode; + +} + +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 SetTextWriterCore() +{ + GetTextWriter()->Print("\n"); + + GetTextWriter()->Printf("System Ver. %d.%d.%d-%d\n", s_CupMajor, s_CupMinor, s_CupMicro, s_NupMajor); + GetTextWriter()->Printf("System Region %s\n", nn::cfg::CTR::GetRegionCodeA3(s_Region)); + GetTextWriter()->Printf("Serial No. %s\n", s_SerialNo); + GetTextWriter()->Printf("Device ID %llu\n", s_DeviceId); + GetTextWriter()->Printf("MAC Address %s\n", s_MacAddress); + if (s_ReadFriendCode) + { + GetTextWriter()->Printf("Friend Code %04u-%04u-%04u\n", + static_cast(s_FriendCode / 100000000ULL % 10000ULL), static_cast (s_FriendCode / 10000ULL % 10000ULL), + static_cast (s_FriendCode % 10000ULL)); + } + + GetTextWriter()->Printf("Battery %d%%\n", s_BatteryRemain); + GetTextWriter()->Printf("AC Adapter %s\n", s_AdapterState.c_str()); + GetTextWriter()->Printf("Progress %02d%%\n", s_Progress); + GetTextWriter()->Print("\n"); + + ::std::vector::iterator it; + for (it = s_OperationMessage->begin(); it != s_OperationMessage->end(); it++) + { + GetTextWriter()->Printf("%s\n", it->c_str()); + } + + +} + +void DrawSystemState +( + const char* toolName, + demo::RenderSystemDrawing& renderSystem, + nn::util::FloatColor titleColor, + bool flip, + std::string& adapterState, + const char* toolVersion, + u8 cupMajorVersion, + u8 cupMinorVersion, + u8 cupMicroVersion, + u8 nupVersion, + u8 batteryRemain, + u64 deviceId, + u64 friendCode, + u32 progress, + bool isBackupFailed, + bool isBackupSucceeded, + char8* macAddress, + ::std::vector& operationMessage, + nn::cfg::CTR::CfgRegionCode region, + u8* serialNo, + bool readFriendCode + +) +{ + // パラメータ保存 + s_AdapterState = adapterState; + s_CupMajor = cupMajorVersion; + s_CupMinor = cupMinorVersion; + s_CupMicro = cupMicroVersion; + s_NupMajor = nupVersion; + s_BatteryRemain = batteryRemain; + s_DeviceId = deviceId; + s_FriendCode = friendCode; + s_Progress = progress; + std::memcpy(s_MacAddress, macAddress, sizeof(s_MacAddress)); + s_Region = region; + std::memcpy(s_SerialNo, serialNo, sizeof(s_SerialNo)); + s_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN] = '\0'; + s_OperationMessage = &operationMessage; + s_ReadFriendCode = readFriendCode; + + + // デフォルトで上画面に描画するもの + renderSystem.SetRenderTarget(GetRenderTarget(NN_GX_DISPLAY0, flip)); + if (isBackupSucceeded) + { + renderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY0, flip), SUCCESS_COLOR); + } + else if (isBackupFailed) + { + renderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY0, flip), FAIL_COLOR); + } + else + { + renderSystem.SetClearColor(GetRenderTarget(NN_GX_DISPLAY0, flip), NORMAL_COLOR); + } + + + renderSystem.Clear(); + renderSystem.SetColor(1.f, 1.f, 1.f); + u32 line = 0; + + size_t fontwidth = 8; + size_t fontheight = fontwidth + 2; + + SetDrawTextHandler(SetTextWriterCore); + DrawResFont(GetRenderTarget(NN_GX_DISPLAY0, flip)); + + renderSystem.SetFontSize(fontwidth); + + // ツール名、ハイライト + renderSystem.DrawText(0, line++ * fontheight, "%s %s Rev.%s", toolName, __DATE__, toolVersion); + renderSystem.SetColor(titleColor.r, titleColor.g, titleColor.b); + renderSystem.FillRectangle(0, (line - 1) * fontheight, 400, fontheight); + renderSystem.SetColor(1.f, 1.f, 1.f); + renderSystem.DrawText(0, line++ * fontheight, ""); + + // プログレスバー + fontwidth = 8; + fontheight = 14; + if(readFriendCode) + { + line += 9; + } + else + { + line += 8; + } + + const u8 offset = 19; + const u8 diff = 4; + renderSystem.SetColor(0.f, 0.2f, 0.f); + renderSystem.DrawLine(offset * fontwidth, (line - 1) * fontheight - diff, offset * fontwidth + PROGRESS_MAX_LINES, (line - 1) + * fontheight - diff); + renderSystem.DrawLine(offset * fontwidth, (line - 1) * fontheight - diff, offset * fontwidth, (line) * fontheight - diff); + renderSystem.DrawLine(offset * fontwidth, (line) * fontheight - diff, offset * fontwidth + PROGRESS_MAX_LINES, (line) * fontheight - diff); + renderSystem.DrawLine(offset * fontwidth + PROGRESS_MAX_LINES, (line - 1) * fontheight - diff, offset * fontwidth + + PROGRESS_MAX_LINES, (line) * fontheight + 1 - diff); + renderSystem.SetColor(0.f, 0.5f, 0.f); + renderSystem.FillRectangle(offset * fontwidth, (line - 1) * fontheight - diff, progress * PROGRESS_MAX_LINES / 100 + 1, + fontheight); + + renderSystem.SetColor(1.f, 1.f, 1.f); + renderSystem.DrawText(0, line++ * fontheight, ""); +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/DrawSystemState.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/DrawSystemState.h new file mode 100644 index 0000000..448d086 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/DrawSystemState.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------------* + 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 +{ + +// 現在の描画先ディスプレイを返す +// target NN_GX_DISPLAY0 または NN_GX_DISPLAY1 +// flip 上下画面を入れ替えているかどうか +u32 GetRenderTarget(u32 target, bool flip = false); + +// システム状態を描画する +// InitializeResFont()、demo::RenderSystemDrawing.Initializeが呼び出されている必要がある +void DrawSystemState +( + const char* toolName, + demo::RenderSystemDrawing& renderSystem, + nn::util::FloatColor titleColor, + bool flip, + std::string& adapterState, + const char* toolVersion, + u8 cupMajorVersion, + u8 cupMinorVersion, + u8 cupMicroVersion, + u8 nupVersion, + u8 batteryRemain, + u64 deviceId, + u64 friendCode, + u32 progress, + bool isBackupFailed, + bool isBackupSucceeded, + char8* macAddress, + ::std::vector& operationMessage, + nn::cfg::CTR::CfgRegionCode region, + u8* s_SerialNo, + bool readFriendCode +); + +} + + +#endif /* DRAWSYSTEMSTATE_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileChecker.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileChecker.cpp new file mode 100644 index 0000000..80893ed --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileChecker.cpp @@ -0,0 +1,153 @@ +/*---------------------------------------------------------------------------* + 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]; +} + +void ClearFileCheck(FileExistsCheck index) +{ + if(index > EXISTS_MAX) + { + NN_LOG("Invalid File index!!\n"); + return; + } + + s_FileExistsChecked[index] = false; +} + +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 ExistsRegionData() +{ + return ExistsFile(EXISTS_REGION_DATA); +} + +bool ExistsDeleteAccountChecked() +{ + return ExistsFile(EXISTS_DELETE_ACCOUNT); +} + +bool ExistsTransferAccountChecked() +{ + return ExistsFile(EXISTS_TRANSFER_ACCOUNT); +} + +bool ExistsDownloadIvsCheckedFile() +{ + return ExistsFile(EXISTS_DOWNLOAD_IVS); +} + +bool ExistsTwlTitleListFile() +{ + return ExistsFile(EXISTS_TWL_TITLELIST); +} + +void InitializeFileCheck() +{ + for(u32 i = 0; i < EXISTS_MAX; i++) + { + s_FileExistsChecked[i] = false; + } +} + + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileChecker.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileChecker.h new file mode 100644 index 0000000..2172ec1 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileChecker.h @@ -0,0 +1,88 @@ +/*---------------------------------------------------------------------------* + 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, // IVS + EXISTS_CONSOLE_INTIALIZED, // 本体初期化完了 + EXISTS_WRITE_FINISHED, // 書き込み完了 + EXISTS_AP_SETTING, // 無線設定ファイル + EXISTS_RTC_SYNC_FINISHED, // RTC書き込み完了 + EXISTS_COUNTRY_LANGUAGE, // 国設定書き込み完了 + EXISTS_REGION_DATA, // リージョン + EXISTS_DELETE_ACCOUNT, // アカウント削除完了 + EXISTS_TRANSFER_ACCOUNT, // アカウント移行完了 + EXISTS_DOWNLOAD_IVS, // IVSダウロード完了 + EXISTS_TWL_TITLELIST, // TWLタイトルリストファイル + 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::REGION_DATA_PATHNAME, + common::DELETE_ACCOUNT_CHECK_PATHNAME, + common::TRANSFER_ACCOUNT_CHECK_PATHNAME, + common::DOWNLOAD_IVS_CHECK_PATHNAME, + common::TWL_TITLELIST_PATHNAME +}; + +// ファイルが存在するかどうか +bool CheckFileExists(const wchar_t* path); + +bool ExistsUpdateCheckedFile(); +bool ExistsSerialNumberFile(); +bool ExistsIVSFile(); +bool ExistsConsoleInitializedFile(); +bool ExistsWriteFinishedFile(); +bool ExistsAPSetting(); +bool ExistsRtcSyncFinishedFile(); +bool ExistsCountryLanguageFile(); +bool ExistsRegionData(); +bool ExistsDeleteAccountChecked(); +bool ExistsTransferAccountChecked(); +bool ExistsDownloadIvsCheckedFile(); +bool ExistsTwlTitleListFile(); + +// ファイルチェックの結果を初期化する +// 一度チェックするとその結果を保持するため +// ファイルを作成したり削除した時に呼ぶ必要がある +void ClearFileCheck(FileExistsCheck index); + +// 全てのファイルチェックの結果を初期化する +void InitializeFileCheck(); + +} + +#endif /* FILECHECKER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileName.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileName.h new file mode 100644 index 0000000..0d45e9c --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileName.h @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------------* + 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 char* const NAND_TWL_ARCHIVE_NAME = "twln:"; + +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 SD_SAVEDATA_TWL_ROOT_NAME = L"CTR_Console_Repair/TWLBackup/"; +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 NAND_TWL_DATA_ROOT_PATHNAME_WITHOUT_SLASH = L"twln:/title"; +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 DELETE_ACCOUNT_CHECK_PATHNAME = L"sdmc:/CTR_Console_Repair/AccountDeletedChecked"; +const wchar_t* const TRANSFER_ACCOUNT_CHECK_PATHNAME = L"sdmc:/CTR_Console_Repair/AccountTransferedChecked"; +const wchar_t* const DOWNLOAD_IVS_CHECK_PATHNAME = L"sdmc:/CTR_Console_Repair/DownloadSDCIFinished"; +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"; +const wchar_t* const FILE_LIST_PATHNAME = L"sdmc:/CTR_Console_Repair/FileList.txt"; +const wchar_t* const TWL_TITLELIST_PATHNAME = L"sdmc:/CTR_Console_Repair/TwlTitleList.txt"; +const wchar_t* const SD_NINTENDO_3DS_ROOT_PATH = L"sdmc:/Nintendo 3DS/"; + +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/1stNUP_7/ConsoleDataMigration/sources/common/FileTransfer.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileTransfer.cpp new file mode 100644 index 0000000..cc76f83 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileTransfer.cpp @@ -0,0 +1,771 @@ +/*---------------------------------------------------------------------------* + 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 + +#include "Aes_define.h" +#include "FileTransfer.h" +#include "CommonLogger.h" +#include "common_Types.h" +#include "FileName.h" + +namespace common +{ + +namespace +{ + +u64 s_TotalFileSize; +u64 s_FinishedFileSize = 0; +u64 s_Progress = 0; + +} + +bool VerifyMac(nn::fs::FileInputStream* sdFile, nn::fs::FileStream* nandFile, s64 sdFileSize, s64 nandFileSize, + const wchar_t* nandPath, void* buf, size_t bufSize); +bool ConfirmFile(nn::fs::FileInputStream* from_file, nn::fs::FileStream* to_file, s64 sdFileSize, s64 nandFileSize, + void* buf, size_t bufSize, const wchar_t* sdPath, const wchar_t* tmpPath, const wchar_t* truePath); +void AddPkcsPadding(u8* paddingSize, void* buf, size_t bufSize, s32* readSize); +bool AddPathNameAndUpdateContext(nn::fs::FileOutputStream* file, const wchar_t *str, s64 fileSize, + nn::crypto::Sha256Context* context); + +const char* GetCharStr(const wchar_t* path) +{ + static char filename[nn::fs::MAX_FILE_PATH_LENGTH]; + 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, s64& fileSize) +{ + nn::fs::Directory dir; + nn::Result result; + std::vector entryList; //カレントディレクトリのエントリ一覧を格納 + std::vector::iterator entryIndex; + + result = dir.TryInitialize(currentDirectory.c_str()); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + nn::fs::DirectoryEntry entry; + s32 numEntry; + for (;;) + { + result = dir.TryRead(&numEntry, &entry, 1); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + if (numEntry == 0) + { + // カレントディレクトリを閉じる + dir.Finalize(); + + // カレントディレクトリの子を開く + for (entryIndex = entryList.begin(); entryIndex != entryList.end(); entryIndex++) + { + if (entryIndex->attributes.isDirectory) + { + result = CalculateFileNum(currentDirectory + std::wstring(entryIndex->entryName) + std::wstring(L"/"), + fileNum, fileSize); + } + } + + return result; + } + + entryList.push_back(entry); + fileNum++; + fileSize += entry.entrySize; + } +} + +bool ExistsInList(ImportDataList* fileList, const wchar_t* path, bool isDirectory) +{ + std::wstring sdPath(path); + if(isDirectory) + { + sdPath += std::wstring(L"/"); + } + + char str[nn::fs::MAX_FILE_PATH_LENGTH]; + std::strlcpy(str, GetCharStr(sdPath.c_str()), sizeof(str)); + + bool returnValue = false; + for(ImportDataList::iterator it = fileList->begin(); it != fileList->end(); it++) + { + if(std::strcmp(str, it->fileName.c_str()) == 0) + { + returnValue = true; + NN_LOG("%s exists in FileList.txt\n", str); + break; + } + } + + return returnValue; +} + +bool ExportTwlSaveDirectory(const wchar_t* dirPath, nn::fs::FileOutputStream* list, + nn::crypto::Sha256Context* listContext) +{ + NN_LOG("Create Directory %ls\n", dirPath); + + nn::Result result = nn::fs::TryCreateDirectory(dirPath); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + return AddPathNameAndUpdateContext(list, dirPath, -1, listContext); +} + +bool ExportTwlSaveFile(const wchar_t* from_path, const wchar_t* to_path, void* buf, const size_t bufSize, + nn::fs::FileOutputStream* list, nn::crypto::Sha256Context* listContext) +{ + NN_LOG("from = %ls\n", from_path); + NN_LOG("to = %ls\n", to_path); + + nn::Result result; + + // ファイル作成 + nn::fs::FileInputStream from_file; + nn::fs::FileStream to_file; + s64 filesize; + s32 readsize; + s32 writesize; + + NN_LOG("Copy File %ls\n", from_path); + + // 読み込み対象ファイル開く + result = from_file.TryInitialize(from_path); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // 読み込み対象ファイルのサイズ取得 + result = from_file.TryGetSize(&filesize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + if (!AddPathNameAndUpdateContext(list, to_path, filesize, listContext)) + { + return false; + } + + nn::crypto::SwAesCtrContext swAesCtrContext; + swAesCtrContext.Initialize(iv, common::key, sizeof(key)); + + size_t totalReadSize = 0; + nn::crypto::Sha256Context context; + context.Initialize(); + + // ファイルサイズをヘッダに書いておく + // 書き込み対象ファイル作成 + result = nn::fs::TryCreateFile(to_path, filesize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + result = to_file.TryInitialize(to_path, + nn::fs::OPEN_MODE_READ | nn::fs::OPEN_MODE_WRITE | nn::fs::OPEN_MODE_CREATE); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // フルパスをハッシュに含める + context.Update(from_path, std::wcslen(from_path) * sizeof(wchar_t)); + + BackupDataHeader header; + BackupDataHeader enc; + std::memset(&header, 0, sizeof(header)); + std::memset(&enc, 0, sizeof(enc)); + header.size = filesize; + result = swAesCtrContext.Encrypt(&enc, &header, sizeof(header)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context.Update(&enc, sizeof(enc)); + s32 writeSize; + result = to_file.TryWrite(&writeSize, &enc, sizeof(enc), false); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + while (1) + { + // バッファの後半半分を暗号・復号用に使う + result = from_file.TryRead(&readsize, buf, bufSize / 2); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + totalReadSize += readsize; + + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + if (readsize == 0) + { + NN_LOG("Add CMAC %ls\n", from_path); + // SHA256を計算してCMACを付加する + 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_RETURN_FALSE_IF_FAILED(result); + + result = to_file.TryWrite(&writesize, cmac, sizeof(cmac)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + result = to_file.TryFlush(); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + break; + } + else + { + NN_LOG("EncryptSize = %d\n", readsize); + + u8 paddingSize = 0; + AddPkcsPadding(&paddingSize, reinterpret_cast(buf), bufSize / 2, &readsize); + + // 暗号化後SHA256を計算しつつ書き込み + result = swAesCtrContext.Encrypt(reinterpret_cast(buf) + bufSize / 2, buf, readsize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context.Update(reinterpret_cast(buf) + bufSize / 2, readsize); + + result = to_file.TryWrite(&writesize, reinterpret_cast(buf) + bufSize / 2, readsize, false); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // 事前計算したファイルサイズに一致させるためパディング分減算 + 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); + } + } + to_file.Finalize(); + + from_file.Finalize(); + + return true; +} + + +bool CopyDirectory(ImportDataList* fileList, const wchar_t * from_path, const wchar_t * to_path, void* buf, + const size_t bufSize, bool encode, nn::fs::FileOutputStream* list, nn::crypto::Sha256Context* listContext) +{ + nn::fs::Directory from_dir; + nn::fs::DirectoryEntry entry; + s32 numread = 0; + std::wostringstream target_from; + std::wostringstream target_to; + + nn::Result result = from_dir.TryInitialize(from_path); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + while (1) + { + result = from_dir.TryRead(&numread, &entry, 1); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + if(numread == 0) + { + 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; + + // NAND書き込みの場合はリストに存在するかチェックする + if (!encode) + { + if (!ExistsInList(fileList, target_from.str().c_str(), entry.attributes.isDirectory)) + { + NN_LOG("============No such file %ls in FileList.txt. Skip=============\n", target_from.str().c_str()); + continue; + } + } + + // ディレクトリの場合 + 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.IsSuccess() || result.IsFailure() && result <= nn::fs::ResultAlreadyExists()) + { + target_from << L"/"; + target_to << L"/"; + if(encode) + { + if(!AddPathNameAndUpdateContext(list, target_to.str().c_str(), -1, listContext)) + { + return false; + } + } + + // 再帰処理 + if (!CopyDirectory(fileList, target_from.str().c_str(), target_to.str().c_str(), buf, bufSize, encode, list, listContext)) + { + return false; + } + } + else + { + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + } + } + // ファイルの場合 + else + { + std::wostringstream target_tmp; + target_tmp.str(L""); + target_tmp.clear(std::stringstream::goodbit); + + if(!encode) + { + target_tmp << to_path << L"_" << entry.entryName; + } + else + { + target_tmp << target_to.str(); + } + + // ファイル作成 + nn::fs::FileInputStream from_file; + nn::fs::FileStream 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()); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // 読み込み対象ファイルのサイズ取得 + result = from_file.TryGetSize(&filesize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + if (encode) + { + if (!AddPathNameAndUpdateContext(list, target_to.str().c_str(), filesize, listContext)) + { + return false; + } + } + + 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_tmp.str().c_str(), filesize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + result = to_file.TryInitialize(target_tmp.str().c_str(), + nn::fs::OPEN_MODE_READ | nn::fs::OPEN_MODE_WRITE | nn::fs::OPEN_MODE_CREATE); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // フルパスをハッシュに含める + context.Update(target_from.str().c_str(), target_from.str().size() * sizeof(wchar_t)); + + BackupDataHeader header; + BackupDataHeader enc; + std::memset(&header, 0, sizeof(header)); + std::memset(&enc, 0, sizeof(enc)); + header.size = filesize; + result = swAesCtrContext.Encrypt(&enc, &header, sizeof(header)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context.Update(&enc, sizeof(enc)); + s32 writeSize; + result = to_file.TryWrite(&writeSize, &enc, sizeof(enc), false); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + } + else + { + // ヘッダを読む + // ハッシュの計算は終わっているので復号化のみ + BackupDataHeader header; + BackupDataHeader dec; + std::memset(&header, 0, sizeof(header)); + std::memset(&dec, 0, sizeof(dec)); + s32 readSize; + result = from_file.TryRead(&readSize, &header, sizeof(header)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + swAesCtrContext.Decrypt(&dec, &header, sizeof(header)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + fileSizeWithoutHeaderAndFooter = dec.size; + + // 書き込み対象ファイル作成 + result = nn::fs::TryCreateFile(target_tmp.str().c_str(), fileSizeWithoutHeaderAndFooter); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + result = to_file.TryInitialize(target_tmp.str().c_str(), + nn::fs::OPEN_MODE_READ | nn::fs::OPEN_MODE_WRITE | nn::fs::OPEN_MODE_CREATE); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + } + + while (1) + { + // バッファの後半半分を暗号・復号用に使う + result = from_file.TryRead(&readsize, buf, bufSize / 2); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + totalReadSize += readsize; + + if (readsize == 0) + { + if (encode) + { + NN_LOG("Add CMAC %ls\n", target_from.str().c_str()); + // SHA256を計算してCMACを付加する + 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_RETURN_FALSE_IF_FAILED(result); + + result = to_file.TryWrite(&writesize, cmac, sizeof(cmac)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + } + + result = to_file.TryFlush(); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // 復号済みなら検証する + if (!encode) + { + if (!ConfirmFile(&from_file, &to_file, filesize, fileSizeWithoutHeaderAndFooter, buf, bufSize, + target_from.str().c_str(), target_tmp.str().c_str(), target_to.str().c_str())) + { + return false; + } + } + + break; + } + else + { + if (encode) + { + NN_LOG("EncryptSize = %d\n", readsize); + + u8 paddingSize = 0; + AddPkcsPadding(&paddingSize, reinterpret_cast(buf), bufSize / 2, &readsize); + + // 暗号化後SHA256を計算しつつ書き込み + result = swAesCtrContext.Encrypt(reinterpret_cast(buf) + bufSize / 2, buf, readsize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context.Update(reinterpret_cast(buf) + bufSize / 2, readsize); + + result = to_file.TryWrite(&writesize, reinterpret_cast(buf) + bufSize / 2, readsize, + false); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // 事前計算したファイルサイズに一致させるためパディング分減算 + 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 + { + // ハッシュ検証は通っているので復号化しつつ書き込み + // パディング以降は書き込まないよう書き込みサイズを変更する + + NN_LOG("DecryptSize = %d\n", readsize); + result = swAesCtrContext.Decrypt(reinterpret_cast(buf) + bufSize / 2, buf, readsize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + // パディングまで読んだかどうか + bool readDone = false; + // パディングまで読んでいたら書き込みサイズを減らす + if (fileSizeWithoutHeaderAndFooter < totalReadSize) + { + readsize -= totalReadSize - fileSizeWithoutHeaderAndFooter; + readDone = true; + } + + result = to_file.TryWrite(&writesize, reinterpret_cast(buf) + bufSize / 2, readsize, + false); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + 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(); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + if (!ConfirmFile(&from_file, &to_file, filesize, fileSizeWithoutHeaderAndFooter, buf, + bufSize, target_from.str().c_str(), target_tmp.str().c_str(), + target_to.str().c_str())) + { + return false; + } + break; + } + } + + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + } + } + to_file.Finalize(); + + from_file.Finalize(); + } + } + + from_dir.Finalize(); + return true; +} + +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); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + return std::memcmp(cmac, sdCmac, sizeof(cmac)) == 0; +} + + +bool VerifyMac(nn::fs::FileInputStream* sdFile, nn::fs::FileStream* nandFile, s64 sdFileSize, s64 nandFileSize, + const wchar_t* nandPath, void* buf, size_t bufSize) +{ + nn::Result result; + bit8 sdCmac[nn::crypto::AES_CMAC_MAC_SIZE]; + + // ハッシュが付加されていないとエラー + if(sdFileSize < nn::crypto::AES_CMAC_MAC_SIZE) + { + return false; + } + + s32 readSize; + // ハッシュを取得する + nn::crypto::Initialize(); + result = sdFile->TrySetPosition(sdFileSize - nn::crypto::AES_CMAC_MAC_SIZE); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + result = sdFile->TryRead(&readSize, sdCmac, sizeof(sdCmac)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + + sdFile->Finalize(); + + nandFile->SetPosition(0); + + // ハッシュを計算する + nn::crypto::SwAesCtrContext swAesCtrContext; + swAesCtrContext.Initialize(iv, common::key, sizeof(key)); + + nn::crypto::Sha256Context context; + context.Initialize(); + + // NAND上のフルパスをハッシュに含めている + context.Update(nandPath, std::wcslen(nandPath) * sizeof(wchar_t)); + + BackupDataHeader header; + BackupDataHeader enc; + std::memset(&header, 0, sizeof(header)); + std::memset(&enc, 0, sizeof(enc)); + header.size = nandFileSize; + result = swAesCtrContext.Encrypt(&enc, &header, sizeof(header)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context.Update(&enc, sizeof(enc)); + + bool retValue = false; + + size_t totalReadSize = 0; + while (1) + { + result = nandFile->TryRead(&readSize, buf, bufSize / 2); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + retValue = false; + break; + } + else + { + totalReadSize += readSize; + + if (readSize == 0) + { + retValue = CalculateAndCompareCmac(&context, sdCmac); + break; + } + else + { + u8 paddingSize = 0; + AddPkcsPadding(&paddingSize, reinterpret_cast(buf), bufSize / 2, &readSize); + result = swAesCtrContext.Encrypt(reinterpret_cast(buf) + bufSize / 2, buf, readSize); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context.Update(reinterpret_cast(buf) + bufSize / 2 , readSize); + + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + retValue = false; + break; + } + } + } + } + nn::crypto::Finalize(); + nandFile->Finalize(); + + return retValue; +} + +bool ConfirmFile(nn::fs::FileInputStream* from_file, nn::fs::FileStream* to_file, s64 sdFileSize, s64 nandFileSize, + void* buf, size_t bufSize, const wchar_t* sdPath, const wchar_t* tmpPath, const wchar_t* truePath) +{ + nn::Result result; + + NN_LOG("Verify CMAC %ls\n", sdPath); + if (!VerifyMac(from_file, to_file, sdFileSize, nandFileSize, truePath, buf, bufSize)) + { + // 検証に失敗したので削除する + s_FinishedFileSize -= nandFileSize; + COMMON_LOGGER("**********Verification Failed %s, Delete**********\n", GetCharStr(sdPath)); + result = nn::fs::TryDeleteFile(tmpPath); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + return false; + } + else + { + NN_LOG("Verification Success %s, Rename\n", GetCharStr(sdPath)); + // 書き込み先を削除する + result = nn::fs::TryDeleteFile(truePath); + if (result.IsFailure() && !nn::fs::ResultNotFound::Includes(result)) + { + COMMON_LOGGER("**********Verification Failed %s, Delete**********\n", GetCharStr(sdPath)); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + } + + // 正しいファイル名にリネームする + result = nn::fs::TryRenameFile(tmpPath, truePath); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if (result.IsFailure()) + { + COMMON_LOGGER("**********Verification Failed %s, Delete**********\n", GetCharStr(sdPath)); + s_FinishedFileSize -= nandFileSize; + return false; + } + } + + return true; +} + +//! @brief 入力データの末尾16バイトをPKCS5で必要バイト数パディングする +//! @param[out] paddingSize パディングしたバイト数 +//! @param[in] buf 入力データの入ったバッファ +//! @param[in] bufSize バッファサイズ +//! @param[inout] readSize バッファに読み込んだバイト数。書き込み時に参照するためパディングしたら増加させる +void AddPkcsPadding(u8* paddingSize, void* buf, size_t bufSize, s32* readSize) +{ + if (*readSize < bufSize) + { + if ((*readSize % AES_BLOCK_SIZE) != 0) + { + *paddingSize = AES_BLOCK_SIZE - *readSize % AES_BLOCK_SIZE; + std::memset(reinterpret_cast(buf) + *readSize, *paddingSize, *paddingSize); + *readSize += *paddingSize; + } + } +} + +//! @brief パスにnimのセーブデータディレクトリが含まれているかどうかを返します +//! @param[in] str パス +//! @return パスにnimのセーブデータディレクトリが含まれているか +bool ContainsNimSaveDataDir(const wchar_t* str) +{ + return std::wcsstr(str, common::NIM_SAVEDATA_DIRECTORY_NAME) != NULL; +} + +//! @brief ファイルに文字列とサイズをカンマ区切り、改行付きで追加します +//! @param[in] file 文字列を出力したいファイル +//! @param[in] str 入力文字列 +//! @param[in] fileSize サイズ +//! @param[in] context SHA-256計算用コンテキスト +bool AddPathNameAndUpdateContext(nn::fs::FileOutputStream* file, const wchar_t *str, s64 fileSize, + nn::crypto::Sha256Context* context) +{ + nn::Result result; + s32 writeSize; + + if(ContainsNimSaveDataDir(str)) + { + return true; + } + + std::string output(GetCharStr(str)); + result = file->TryWrite(&writeSize, output.c_str(), output.size(), true); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context->Update(output.c_str(), output.size()); + + char comma = ','; + result = file->TryWrite(&writeSize, &comma, sizeof(comma), true); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context->Update(&comma, sizeof(comma)); + + char sizeStr[10]; + std::memset(sizeStr, 0, sizeof(sizeStr)); + s32 sizeStrSize = std::snprintf(sizeStr, sizeof(sizeStr), "%lld", fileSize); + result = file->TryWrite(&writeSize, sizeStr, sizeStrSize, true); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context->Update(sizeStr, sizeStrSize); + + char newLine = '\n'; + result = file->TryWrite(&writeSize, &newLine, sizeof(newLine), true); + COMMON_LOGGER_RETURN_FALSE_IF_FAILED(result); + context->Update(&newLine, sizeof(newLine)); + + return true; +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileTransfer.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileTransfer.h new file mode 100644 index 0000000..e55f3bf --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/FileTransfer.h @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------------* + 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 +#include "common_Types.h" + +namespace common +{ + +// currentDirectory以下のファイル数、ファイルサイズを再帰的に計算する +nn::Result CalculateFileNum(std::wstring currentDirectory, u32& fileNum, s64& fileSize); + +// 単一のディレクトリを作成する +// アーカイブはマウント済みにしておく +bool ExportTwlSaveDirectory(const wchar_t* dirPath, nn::fs::FileOutputStream* list, + nn::crypto::Sha256Context* listContext); + +// 単一のファイルをコピーする +// アーカイブはマウント済みにしておく +bool ExportTwlSaveFile(const wchar_t* from_path, const wchar_t* to_path, void* buf, const size_t bufSize, + nn::fs::FileOutputStream* list, nn::crypto::Sha256Context* listContext); + +// ディレクトリ間のコピー +// アーカイブ越しのコピーが可能 +// アーカイブにマウントした状態で呼び出す必要あり +// 書き込み先のディレクトリはあらかじめ消去しておくこと。 +// 引数はスラッシュ付き +// TODO:分割して短くする +bool CopyDirectory(ImportDataList* fileList, const wchar_t * from_path, const wchar_t * to_path, void* buf, + const size_t bufSize, bool encode, nn::fs::FileOutputStream* list, nn::crypto::Sha256Context* listContext); + +// ファイル転送の進捗を取得する +// InitializeTransferProgress で設定した値を100とする割合が返される +u32 GetProgress(); + +// ファイル転送の目標値を設定する +void InitializeTransferProgress(u64 totalSize); + +// wchar_t* を char* に変換する。 +// 内部のバッファを使用するためスレッドアンセーフ +const char* GetCharStr(const wchar_t* path); + +} + +#endif /* FILETRANSFER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/HardwareStateManager.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/HardwareStateManager.cpp new file mode 100644 index 0000000..0f5fa76 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/HardwareStateManager.cpp @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: HardwareStateManager.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 "HardwareStateManager.h" + +namespace common +{ + +HardwareStateManager::HardwareStateManager(Util& hwUtility) +{ + m_pUtil = &hwUtility; +} + +HardwareStateManager::~HardwareStateManager() +{ + +} + +bool HardwareStateManager::CanReadIvs() +{ + return m_pUtil->CanReadIVS(); +} + +bool HardwareStateManager::CanReadSerialNumber() +{ + return m_pUtil->CanReadSerialNumber(); +} + +bool HardwareStateManager::IsBatteryLower() +{ + return m_pUtil->IsBatteryLower(); +} + +bool HardwareStateManager::IsAdapterConnected() +{ + return m_pUtil->IsAdapterConnected(); +} + +bit32 HardwareStateManager::GetDeviceId() +{ + return m_pUtil->GetDeviceId(); +} + +void HardwareStateManager::GetIvs(void** ivs, size_t* size) +{ + return m_pUtil->GetIvs(ivs, size); +} + +nn::Handle HardwareStateManager::GetMcuHandle() +{ + return m_pUtil->GetMcuHandle(); +} + +void HardwareStateManager::GetSerialNumber(u8** serial, size_t* size) +{ + return m_pUtil->GetSerialNumber(serial, size); +} + +void HardwareStateManager::GetVersionData(common::VerDef* version) +{ + return m_pUtil->GetVersionData(version); +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/HardwareStateManager.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/HardwareStateManager.h new file mode 100644 index 0000000..1483dff --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/HardwareStateManager.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: HardwareStateManager.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 HARDWARESTATEMANAGER_H_ +#define HARDWARESTATEMANAGER_H_ + +#include "Util.h" + + +namespace common +{ + +// ハードウェア状態に依存するAPIをクッション +class HardwareStateManager +{ +public: + explicit HardwareStateManager(Util& hwUtility); + virtual ~HardwareStateManager(); + + bool CanReadIvs(); + bool CanReadSerialNumber(); + bool IsBatteryLower(); + bool IsAdapterConnected(); + bit32 GetDeviceId(); + void GetIvs(void** ivs, size_t* size); + nn::Handle GetMcuHandle(); + void GetSerialNumber(u8** serial, size_t* size); + void GetVersionData(common::VerDef* version); + +private: + NN_PADDING4; + Util* m_pUtil; +}; + +} + +#endif /* HARDWARESTATEMANAGER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/HeapManager.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/HeapManager.cpp new file mode 100644 index 0000000..1930fc2 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/HeapManager.cpp @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------------* + 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 s_AppHeap; + + +HeapManager::HeapManager(size_t byteSize, s32 alignment, bit8 groupId, nn::fnd::ExpHeapBase::AllocationMode mode, bool reuse) +{ + m_Ptr = s_AppHeap.Allocate(byteSize, alignment, groupId, mode, reuse); +} + +HeapManager::~HeapManager() +{ + if(m_Ptr != NULL) + { + s_AppHeap.Free(m_Ptr); + } +} +void* HeapManager::GetAddr() +{ + return m_Ptr; +} + +void InitializeHeap() +{ + s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); +} + +size_t GetAllocatableSize(s32 alignment) +{ + return s_AppHeap.GetAllocatableSize(alignment); +} + +void* ForceAllocate(size_t byteSize, s32 alignment, bit8 groupId, nn::fnd::ExpHeapBase::AllocationMode mode, bool reuse) +{ + return s_AppHeap.Allocate(byteSize, alignment, groupId, mode, reuse); +} + +void ForceFree(void* ptr) +{ + if(ptr != NULL) + { + s_AppHeap.Free(ptr); + } +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/HeapManager.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/HeapManager.h new file mode 100644 index 0000000..eb8da76 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/HeapManager.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------* + 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 +#include + +namespace common +{ + +class HeapManager +{ +public: + explicit HeapManager(size_t byteSize, s32 alignment = nn::fnd::ExpHeapBase::DEFAULT_ALIGNMENT, bit8 groupId = 0, + nn::fnd::ExpHeapBase::AllocationMode mode = nn::fnd::ExpHeapBase::ALLOCATION_MODE_FIRST_FIT, bool reuse = false); + virtual ~HeapManager(); + + void* GetAddr(); + +private: + void* m_Ptr; + +}; + +void InitializeHeap(); +size_t GetAllocatableSize(s32 alignment = nn::fnd::ExpHeapBase::DEFAULT_ALIGNMENT); + +// HeapManagerを使わず確保する場合のみ +void* ForceAllocate(size_t byteSize, s32 alignment = nn::fnd::ExpHeapBase::DEFAULT_ALIGNMENT, bit8 groupId = 0, + nn::fnd::ExpHeapBase::AllocationMode mode = nn::fnd::ExpHeapBase::ALLOCATION_MODE_FIRST_FIT, bool reuse = false); + +// HeapManagerを使わず解放する場合のみ +void ForceFree(void* ptr); + +} // namespace common + +#endif /* HEAPMANAGER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/LogConsole.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/LogConsole.cpp new file mode 100644 index 0000000..0af3ee8 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/LogConsole.cpp @@ -0,0 +1,172 @@ +/*---------------------------------------------------------------------------* + 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) + { + // 満杯なので先頭を削除する + ::std::vector::iterator it; + it = m_Log.begin(); + m_Log.erase(it); + m_LineNum--; + } + + // 部分文字列を追加 + AddWrapedText(str.substr(addedText, m_Width).c_str()); + m_LineNum++; + + // 画面領域の末尾を描画中 かつ + // 画面領域以上追加したら末尾にスクロールする + if(m_CurrentViewLine == (m_LineNum - m_Height - 1) && 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/1stNUP_7/ConsoleDataMigration/sources/common/LogConsole.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/LogConsole.h new file mode 100644 index 0000000..9b120bc --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/LogConsole.h @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------------* + 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(); + + // AddTextで追加された文字列を描画する + 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 描画のためのRenderSystemDrawingへのポインタ + demo::RenderSystemDrawing* m_RenderSystem; + //! @brief 追加したログの行数 + u32 m_LineNum; + //! @brief 表示を開始するログの行数 + u32 m_CurrentViewLine; + + +}; + +} + +#endif /* LOGCONSOLE_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/LogConsole_Private.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/LogConsole_Private.h new file mode 100644 index 0000000..8fbdd42 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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/1stNUP_7/ConsoleDataMigration/sources/common/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/common/OMakefile new file mode 100644 index 0000000..e874cbc --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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/1stNUP_7/ConsoleDataMigration/sources/common/ProgramId.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/ProgramId.h new file mode 100644 index 0000000..c565f11 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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/1stNUP_7/ConsoleDataMigration/sources/common/ResFont.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/ResFont.cpp new file mode 100644 index 0000000..a9a8a79 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/ResFont.cpp @@ -0,0 +1,415 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ResFont.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$ + *---------------------------------------------------------------------------*/ + +//------------------------------------------------------------------ +// デモ: ResFont +// +// 概要 +// nn::font::ResFont の構築と破棄のサンプルです。 +// +// 操作 +// なし。 +// +//------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "ResFont.h" +#include "demo.h" +#include "HeapManager.h" + +namespace common +{ + +namespace +{ +const char s_ShaderBinaryFilePath[] = "rom:/nnfont_RectDrawerShader.shbin"; +const char s_FontFilePath[] = "rom:/lc.bcfnt"; + +const u8 s_Color = 255; + +nn::font::RectDrawer s_Drawer; +void* s_DrawerBuf; +nn::font::ResFont s_Font; +nn::font::DispStringBuffer *s_pDrawStringBuf0; +nn::font::TextWriter s_TextWriter; +void (*s_DrawTextFunc)() = NULL; + +//--------------------------------------------------------------------------- +//! @brief シェーダの初期化を行います。 +//! +//! @param[in,out] pResource 描画用リソースを管理するオブジェクトへのポインタ。 +//--------------------------------------------------------------------------- +void* +InitShaders(nn::font::RectDrawer* pDrawer) +{ + nn::fs::FileReader shaderReader(s_ShaderBinaryFilePath); + + const u32 fileSize = (u32)shaderReader.GetSize(); + + void* shaderBinary = ForceAllocate(fileSize); + NN_NULL_ASSERT(shaderBinary); + +#ifndef NN_BUILD_RELEASE + s32 read = +#endif // NN_BUILD_RELEASE + shaderReader.Read(shaderBinary, fileSize); + NN_ASSERT(read == fileSize); + + const u32 vtxBufCmdBufSize = + nn::font::RectDrawer::GetVertexBufferCommandBufferSize(shaderBinary, fileSize); + void *const vtxBufCmdBuf = ForceAllocate(vtxBufCmdBufSize); + NN_NULL_ASSERT(vtxBufCmdBuf); + pDrawer->Initialize(vtxBufCmdBuf, shaderBinary, fileSize); + + return vtxBufCmdBuf; + +} + +//--------------------------------------------------------------------------- +//! @brief 描画の初期設定を行います。 +//! +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +InitDraw( + s32 width, + s32 height +) +{ + // カラーバッファ情報 + // LCDの向きに合わせて、幅と高さを入れ替えています。 + 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 ), + + // ステンシルテストを無効 + NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(), + + // デプステストを無効 + // カラーバッファの全ての成分を書き込み可 + NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK( + false, // isDepthTestEnabled + 0, // depthFunc + true, // depthMask + true, // red + true, // green + true, // blue + true), // alpha + + // アーリーデプステストを無効 + 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, + const char* filePath +) +{ + // フォントリソースをロードします + nn::fs::FileReader fontReader(filePath); + + s32 fileSize = (s32)fontReader.GetSize(); + if ( fileSize <= 0 ) + { + return false; + } + + void* buffer = common::ForceAllocate(fileSize, nn::font::GlyphDataAlignment); + if (buffer == NULL) + { + return false; + } + + s32 readSize = fontReader.Read(buffer, fileSize); + if (readSize != fileSize) + { + common::ForceFree(buffer); + return false; + } + + // フォントリソースをセットします + bool bSuccess = pFont->SetResource(buffer); + NN_ASSERT(bSuccess); + + //--- 既にリソースをセット済みであるか,ロード済みであるか、リソースが不正な場合に失敗します。 + if (! bSuccess) + { + common::ForceFree(buffer); + } + + // 描画用バッファを設定します。 + const u32 drawBufferSize = nn::font::ResFont::GetDrawBufferSize(buffer); + void* drawBuffer = common::ForceAllocate(drawBufferSize, 4); + NN_NULL_ASSERT(drawBuffer); + pFont->SetDrawBuffer(drawBuffer); + + return bSuccess; +} + +//--------------------------------------------------------------------------- +//! @brief ResFontを破棄します。 +//! +//! @param[in] pFont 破棄するフォントへのポインタ。 +//--------------------------------------------------------------------------- +void +CleanupFont(nn::font::ResFont* pFont) +{ + // 描画用バッファの無効化 + // 描画用バッファがセットされているなら 構築時に SetDrawBuffer に渡したバッファへの + // ポインタが返ってきます。 + void *const drawBuffer = pFont->SetDrawBuffer(NULL); + if (drawBuffer != NULL) + { + ForceFree(drawBuffer); + } + + // フォントがセットされているなら SetResource 時に渡したリソースへの + // ポインタが返ってきます。 + void *const resource = pFont->RemoveResource(); + if (resource != NULL) + { + ForceFree(resource); + } + + // RemoveResource 後は再度 SetResource するまでフォントとして使用できません。 +} + +//--------------------------------------------------------------------------- +//! @brief 表示文字列用バッファを確保します。 +//! +//! @param[in] charMax 表示する文字列の最大文字数。 +//! +//! @return 確保した表示文字列用バッファへのポインタを返します。 +//--------------------------------------------------------------------------- +nn::font::DispStringBuffer* +AllocDispStringBuffer(s32 charMax) +{ + const u32 DrawBufferSize = nn::font::CharWriter::GetDispStringBufferSize(charMax); + void *const bufMem = ForceAllocate(DrawBufferSize); + NN_NULL_ASSERT(bufMem); + + return nn::font::CharWriter::InitDispStringBuffer(bufMem, charMax); +} + +//--------------------------------------------------------------------------- +//! @brief 文字列表示用にモデルビュー行列と射影行列を設定します。 +//! +//! @param[in] pDrawer RectDrawerオブジェクトへのポインタ。 +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +SetupTextCamera( + nn::font::RectDrawer* pDrawer, + s32 width, + s32 height +) +{ + // 射影行列を正射影に設定 + { + // 左上原点とし、Y軸とZ軸の向きが逆になるように設定します。 + 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); + } + + // モデルビュー行列を単位行列に設定 + { + nn::math::MTX34 mv; + nn::math::MTX34Identity(&mv); + pDrawer->SetViewMtxForText(mv); + } +} + +//--------------------------------------------------------------------------- +//! @brief ASCII文字列を描画します。 +//! +//! @param[in] pDrawer RectDrawerオブジェクトへのポインタ。 +//! @param[in] pDrawStringBuf DispStringBufferオブジェクトへのポインタ。 +//! @param[in] pFont フォントへのポインタ。 +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +DrawAscii( + nn::font::RectDrawer* pDrawer, + nn::font::DispStringBuffer* pDrawStringBuf, + nn::font::ResFont* pFont, + s32 width, + s32 height +) +{ + s_TextWriter.SetDispStringBuffer(pDrawStringBuf); + s_TextWriter.SetFont(pFont); + + s_TextWriter.SetCursor(0, 0, 1.f); + + s_TextWriter.StartPrint(); + if(s_DrawTextFunc != NULL) + { + s_DrawTextFunc(); + } + + s_TextWriter.EndPrint(); + pDrawer->BuildTextCommand(&s_TextWriter); + + + // 文字の色は、文字列の描画コマンドを再作成しなくても変更できます。 + s_TextWriter.SetTextColor(nn::util::Color8(s_Color, s_Color, s_Color, s_Color)); + + pDrawer->DrawBegin(); + + SetupTextCamera(pDrawer, width, height); + s_TextWriter.UseCommandBuffer(); + + pDrawer->DrawEnd(); +} + +} // namespace + +void SetDrawTextHandler(void (*func)()) +{ + s_DrawTextFunc = func; +} + + +//--------------------------------------------------------------------------- +//! @brief サンプルのメイン関数です。 +//--------------------------------------------------------------------------- +void +InitializeResFont() +{ + 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)); + + // フォントの構築 + { +#ifndef NN_BUILD_RELEASE + bool bSuccess = +#endif // NN_BUILD_RELEASE + InitFont(&s_Font, s_FontFilePath); + NN_ASSERTMSG(bSuccess, "Fail to load ResFont."); + } + + // 描画リソースの構築 + s_DrawerBuf = InitShaders(&s_Drawer); + + // 描画文字列用バッファの確保 + s_pDrawStringBuf0 = AllocDispStringBuffer(512); + + nn::fs::Unmount("rom:"); + +} + +void DrawResFont(s32 display) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if(display == NN_GX_DISPLAY0) + { + InitDraw(NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + + DrawAscii(&s_Drawer, s_pDrawStringBuf0, &s_Font, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + } + else if(display == NN_GX_DISPLAY1) + { + InitDraw(NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT); + + DrawAscii(&s_Drawer, s_pDrawStringBuf0, &s_Font, NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT); + } + + nngxUpdateState(NN_GX_STATE_ALL); +} + +void FinalizeResFont() +{ + s_Drawer.Finalize(); + + // 描画リソースの破棄 + ForceFree(s_DrawerBuf); + + // フォントの破棄 + CleanupFont(&s_Font); + + // 描画文字列用バッファの解放 + ForceFree(s_pDrawStringBuf0); +} + +nn::font::TextWriter* GetTextWriter() +{ + return &s_TextWriter; +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/ResFont.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/ResFont.h new file mode 100644 index 0000000..379a0bb --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/ResFont.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ResFont.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 RESFONT_H_ +#define RESFONT_H_ + +#include + +namespace common +{ + +// ResFontを初期化する。 +void InitializeResFont(); + +// 文字列の描画時に実行したいハンドラを設定する +void SetDrawTextHandler(void (*func)()); + +// SetDrawTextHandler で設定した関数を使って文字列を描画する +void DrawResFont(s32 display); + +// 内部で保持しているTextWriterへのポインタを返す +nn::font::TextWriter* GetTextWriter(); + + +} + + +#endif /* RESFONT_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdLogger.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdLogger.cpp new file mode 100644 index 0000000..9851395 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdLogger.cpp @@ -0,0 +1,268 @@ +/*---------------------------------------------------------------------------* + 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_PRINT_RESULT(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(); + s_SdLogger.Inactivate(); + } +} + +void InitializeEjectThread() +{ + s_SdEjectedEvent.Initialize(true); + s_SdInsertedEvent.Initialize(true); + nn::fs::RegisterSdmcEjectedEvent(&s_SdEjectedEvent); + nn::fs::RegisterSdmcInsertedEvent(&s_SdInsertedEvent); + + // SDカード抜けを検知するためのスレッド作成 + s_SdmcEjectedEventThread.Start(SdmcEjectedEventThreadFunc, s_SdmcEjectedEventThreadStack); + + // SDカード挿入を検知するためのスレッド作成 + 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; + + // ディレクトリが無ければ作る + 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_PRINT_RESULT(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/1stNUP_7/ConsoleDataMigration/sources/common/SdLogger.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdLogger.h new file mode 100644 index 0000000..6d543f2 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdLogger.h @@ -0,0 +1,67 @@ +/*---------------------------------------------------------------------------* + 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() {}; + + // SDログに文字列を出力する + void Print(const char* fmt, ::std::va_list arg); + + // SDログを削除する + void Clear(); + + // 内部状態を初期化する。SDカード挿抜時に呼ばれることを期待 + void Inactivate(); + +private: + void Activate(); + + nn::fs::FileOutputStream sd; + bool m_TryActivate; + bool m_Permitted; + NN_PADDING2; + +}; + +// SDカード挿抜用のスレッドを初期化する +void InitializeEjectThread(); + +// SDカードが抜けた時に呼ばれるコールバック +void SetEjectHandler(void (*func)()); + +// SDカードが挿入された時に呼ばれるコールバック +void SetInsertHandler(void (*func)()); + +// 内部で保持しているインスタンスへのポインタを返す +SdLogger* GetSdInstance(); + +} // namespace Logger +} // namespace ConsoleBackup + +#endif /* SDLOGGER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdMountManager.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdMountManager.cpp new file mode 100644 index 0000000..4895529 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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() +{ + + +} + +SdMountManager::~SdMountManager() +{ + +} + +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/1stNUP_7/ConsoleDataMigration/sources/common/SdMountManager.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdMountManager.h new file mode 100644 index 0000000..c4db65b --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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状態を管理するためのクラスです +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/1stNUP_7/ConsoleDataMigration/sources/common/SdReaderWriter.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdReaderWriter.cpp new file mode 100644 index 0000000..9ce75c6 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdReaderWriter.cpp @@ -0,0 +1,245 @@ +/*---------------------------------------------------------------------------* + 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; + + // 初期化済みなら何もしない + 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(nn::fs::FileStream& file, const wchar_t* path, void* buf, size_t size) +{ + NN_ASSERT(path != NULL); + NN_ASSERT(size > 0); + + nn::Result result = Initialize(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(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()) + { + // 何もしない + } + else + { + NN_LOG("SD TryWrite failed\n"); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + } + } + else + { + NN_LOG("SD TryInitialize failed\n"); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + } + + return result; +} + +nn::Result SdReaderWriter::WriteBuf(nn::fs::FileStream& file, const wchar_t* path, void* buf, size_t size) +{ + nn::Result result; + + result = WriteBufCore(file, path, buf, size); + NN_UTIL_RETURN_IF_FAILED(result); + + result = file.TryFlush(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + file.Finalize(); + + result = Finalize(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + return result; +} + +nn::Result SdReaderWriter::WriteBufWithCmac(const wchar_t* path, void* buf, size_t size) +{ + nn::Result result; + nn::fs::FileStream file; + + result = WriteBufCore(file, 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_RETURN_RESULT_IF_FAILED(result); + + s32 writeSize; + result = file.TryWrite(&writeSize, cmac, sizeof(cmac), false); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + result = file.TryFlush(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + file.Finalize(); + + result = Finalize(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + return result; + +} + +nn::Result SdReaderWriter::ReadBufCore(nn::fs::FileStream& file, 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); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + s32 readSize; + result = file.TryRead(&readSize, buf, size); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + // TODO バッファを超えるサイズのファイル読み込み + *totalSize = readSize; + + return result; +} + +nn::Result SdReaderWriter::ReadBuf(nn::fs::FileStream& file, const wchar_t* path, void* buf, size_t size, + size_t* totalSize) +{ + nn::Result result; + + result = ReadBufCore(file, 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::fs::FileStream file; + + NN_ASSERT(size > nn::crypto::AES_CMAC_MAC_SIZE); + + result = ReadBufCore(file, path, buf, size, totalSize); + NN_UTIL_RETURN_IF_FAILED(result); + + file.Finalize(); + // ハッシュが付加されていない + 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_RETURN_RESULT_IF_FAILED(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(); + } + + // CMACを0埋め + std::memset(reinterpret_cast(buf) + *totalSize, 0, sizeof(cmac)); + + return result; +} + +nn::Result 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_RETURN_RESULT_IF_FAILED(result); + + result = Finalize(); + COMMON_LOGGER_RETURN_RESULT_IF_FAILED(result); + + return nn::ResultSuccess(); +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdReaderWriter.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdReaderWriter.h new file mode 100644 index 0000000..392ba0d --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SdReaderWriter.h @@ -0,0 +1,78 @@ +/*---------------------------------------------------------------------------* + 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カードに書き込むためのクラスです。 +class SdReaderWriter +{ +public : + SdReaderWriter() : m_IsInitialized(false) {}; + ~SdReaderWriter() {}; + + //! @brief 渡されたバッファからsizeバイト指定されたパス名で書きこみます。CMACが付加されます。 + //! @param[in] path sdmc:で始まる出力パス名。予めディレクトリを作っておく必要があります。 + //! @param[in] buf 入力データへのポインタ + //! @param[in] size 入力データのサイズ + nn::Result WriteBufWithCmac(const wchar_t* path, void* buf, size_t size); + + //! @brief 渡されたバッファへ(size - CMAC)バイト指定されたパス名から読み込みます + //! @param[in] path sdmc:で始まるCMAC付きの入力パス名 + //! @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 渡されたディレクトリ名のディレクトリを作成します + nn::Result CreateDirectory(const wchar_t* path); + +private: + //! @brief 渡されたバッファからサイズ分指定されたパス名で書きこみます + //! @param[in] path sdmc:で始まる出力パス名。予めディレクトリを作っておく必要があります。 + //! @param[in] buf 入力データへのポインタ + //! @param[in] size 入力データのサイズ + nn::Result WriteBuf(nn::fs::FileStream& file, const wchar_t* path, void* buf, size_t size); + + nn::Result WriteBufCore(nn::fs::FileStream& file, const wchar_t*path, void* buf, size_t size); + + //! @brief 渡されたバッファへサイズ分指定されたパス名から読み込みます + //! @param[in] path sdmc:で始まる入力パス名 + //! @param[in] buf 出力バッファへのポインタ + //! @param[in] size バッファサイズ + //! @param[out] totalSize 読み込んだデータのサイズ + nn::Result ReadBuf(nn::fs::FileStream& file, const wchar_t* path, void* buf, size_t size, size_t* totalSize); + + nn::Result ReadBufCore(nn::fs::FileStream& file, const wchar_t* path, void* buf, size_t size, size_t* totalSize); + + //! @brief 初期化します。 + nn::Result Initialize(); + + //! @brief 終了します。 + nn::Result Finalize(); + + NN_PADDING3; + bool m_IsInitialized; + +}; + +} + +#endif /* SDWRITER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/SimplePlayer.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SimplePlayer.cpp new file mode 100644 index 0000000..921eff9 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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; // 使用できる 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() + { + // サウンド出力をステレオに + 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(ForceAllocate(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 からのデータ受信を待つ。 + + + 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(); + + // サウンドスレッドを起動(DSP 割り込みイベント待ち) + threadSound.Start(SoundThreadFunc, s_SoundThreadStack); +} + +void PlaySound(SoundEffect index) +{ + NN_ASSERT(index < SOUND_MAX); + + 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/1stNUP_7/ConsoleDataMigration/sources/common/SimplePlayer.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SimplePlayer.h new file mode 100644 index 0000000..2f73c78 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/SimplePlayer.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------------------------* + 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 +{ + +typedef enum SoundEffect +{ + SOUND_OK, + SOUND_NG, + SOUND_CURSOR, + SOUND_ANNOTATION, + SOUND_MAX + +} SoundEffect; + +// サウンドを鳴らすための初期化を行う +void InitializeSimplePlayer(); + +// 終了処理を行う +void FinalizeSimplePlayer(); + +// サウンドを鳴らす +void PlaySound(SoundEffect index); + +} // namespace common + + +#endif /* SIMPLEPLAYER_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/Util.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/Util.cpp new file mode 100644 index 0000000..bb52b06 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/Util.cpp @@ -0,0 +1,360 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Util.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 +#include +#include +#include + +#include "Util.h" +#include "FileName.h" +#include "CommonLogger.h" +#include "HeapManager.h" + + +namespace common +{ + +Util::Util() : + m_FriendCode(0), m_BatteryRemain(100), m_CanReadSerialNumber(false), m_CanReadIvs(false), m_HasReadFriendCode(false) +{ + +} + +Util::~Util() +{ + +} + +void Util::InitializeForBackup() +{ + Initialize(); +} + +void Util::InitializeForRestore() +{ + Initialize(); + + // friendsの初期化 + nn::Result result = nn::friends::detail::Initialize(); + + // フレンドコードの取得 + nn::friends::CTR::FriendKey friendKey; + result = nn::friends::CTR::GetMyFriendKey(&friendKey); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + m_FriendCode = nn::friends::CTR::FriendKeyToFriendCode(friendKey); + + m_HasReadFriendCode = true; +} + +void Util::Initialize() +{ + nn::Result result; + + // mcuの初期化 + nn::mcu::CTR::InitializeHwCheck(&m_McuSession); + mp_Mcu = new nn::mcu::CTR::HwCheck(m_McuSession); + + // 完全性検証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 = ForceAllocate(fileSize); + if (addr != NULL) + { + mp_Ivs = addr; + m_SizeofIvs = fileSize; + result = fis.TryRead(&ret, addr, fileSize); + if (result.IsSuccess()) + { + m_CanReadIvs = true; + } + // 後でIVSを参照するのでFreeしない + } + } + fis.Finalize(); + } + // 一旦アンマウントしておく + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + + + // シリアルナンバーの取得 + std::memset(m_SerialNo, '\0', + nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN); + result = nn::cfg::CTR::system::GetSerialNo(m_SerialNo); + if(result.IsSuccess()) + { + m_CanReadSerialNumber = true; + } + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + AddCheckDigit(reinterpret_cast(m_SerialNo)); + + + // デバイスIDの取得 + result = nn::ps::CTR::GetDeviceId(&m_DeviceId); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + + // リージョンの取得 + m_Region = nn::cfg::CTR::GetRegion(); + + // バージョンの取得 + common::GetSystemVersion(&m_VerData, m_Region); + + // MACアドレスの取得 + nn::nwm::Mac mac; + + result = nn::nwm::GetMacAddress(mac); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + mac.GetString(m_MacAddress); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); +} + +void Util::FinalizeForBackup() +{ + Finalize(); +} + +void Util::FinalizeForRestore() +{ + nn::friends::detail::Finalize(); +} + +void Util::Finalize() +{ + nn::mcu::CTR::FinalizeHwCheck(&m_McuSession); +} + +// NULL終端されたシリアルナンバーを受け取る +// NULL終端された場所にチェックデジットを付加して新たにNULL終端する +void Util::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'; +} + +// IVSからセーブデータディレクトリ名を生成する +void Util::GetSaveDataDirectoryRoot(::std::string& sysSaveRoot, void* ivs, size_t size) +{ + 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]; + + // 最後の16バイトのハッシュを使う + nn::crypto::CalculateSha256(hash, &reinterpret_cast (ivs)[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]; + } + } + + // 得られたハッシュから文字列を生成 + 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'; + + // セーブデータディレクトリ名を保存する + sysSaveRoot = ::std::string(rootStr); + + NN_LOG("%s\n", sysSaveRoot.c_str()); +} + +bool Util::IsAdapterConnected() +{ + static nn::os::Tick last(0); + static bool lastResult = false; + const u8 UPDATE_INTERVAL = 100; + + nn::os::Tick now = nn::os::Tick::GetSystemCurrent(); + if(last == 0 || (now - last).ToTimeSpan().GetMilliSeconds() > UPDATE_INTERVAL) + { + u8 buf; + nn::Result result = mp_Mcu->ReadByReceive(nn::drivers::mcu::CTR::MCU_PERIPHERAL_STATUS_ADDR, &buf, sizeof(buf)); + if(result.IsSuccess()) + { + last = now; + lastResult = buf & nn::drivers::mcu::CTR::MCU_STATUS_ADAPTER_MASK; + } + } + return lastResult; + +} + +bool Util::IsBatteryLower() +{ + m_BatteryRemain = GetBatteryRemain(); + return m_BatteryRemain <= 10; +} + +bool Util::CanReadIVS() +{ + return m_CanReadIvs; +} + +bool Util::CanReadSerialNumber() +{ + return m_CanReadSerialNumber; +} + +void Util::GetSerialNumber(u8** serial, size_t* size) +{ + *serial = m_SerialNo; + *size = nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN; +} + +u8* Util::GetSerialNumber() +{ + return m_SerialNo; +} + + +void Util::GetIvs(void** ivs, size_t* size) +{ + *ivs = mp_Ivs; + *size = m_SizeofIvs; +} + +bit32 Util::GetDeviceId() +{ + return m_DeviceId; +} + +u8 Util::GetCupMajorVersion() +{ + return m_VerData.cup.majorVersion; +} + +u8 Util::GetCupMinorVersion() +{ + return m_VerData.cup.minorVersion; +} + +u8 Util::GetCupMicroVersion() +{ + return m_VerData.cup.microVersion; +} + +u8 Util::GetNupVersion() +{ + return m_VerData.nup.majorVersion; +} + +nn::Handle Util::GetMcuHandle() +{ + return m_McuSession; +} + +u32 Util::GetBatteryRemain() +{ + u8 remain; + mp_Mcu->GetBatteryRemain(&remain); + return remain; +} + +u64 Util::GetInfraDeviceId() +{ + bit64 infraDeviceId; + infraDeviceId = m_DeviceId + common::INFRA_DEVICE_ID_OFFSET; + return infraDeviceId; +} + +u64 Util::GetFriendcode() +{ + return m_FriendCode; +} + +char8* Util::GetMacAddress() +{ + return m_MacAddress; +} + +nn::cfg::CTR::CfgRegionCode Util::GetRegion() +{ + return m_Region; +} + +const char* Util::GetRegionCodeA3() +{ + return nn::cfg::GetRegionCodeA3(m_Region); +} + +void Util::GetVersionData(common::VerDef* version) +{ + *version = m_VerData; +} + +bool Util::HasReadFriendCode() +{ + return m_HasReadFriendCode; +} + +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/Util.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/Util.h new file mode 100644 index 0000000..ebcf875 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/Util.h @@ -0,0 +1,166 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: Util.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 UTIL_H_ +#define UTIL_H_ + +#include +#include +#include +#include +#include + +#include "VersionDetect.h" + +namespace common +{ + +class Util +{ +public: + Util(); + virtual ~Util(); + + void InitializeForBackup(); + void InitializeForRestore(); + + void FinalizeForBackup(); + void FinalizeForRestore(); + + // シリアルナンバーにモジュラス10 ウェイト3・1(M10W31)でチェックデジットを付加する + static void AddCheckDigit(char* serial); + + // IVSから計算されるセーブデータディレクトリ名を取得する + static void GetSaveDataDirectoryRoot(::std::string& sysSaveRoot, void* ivs, size_t size); + + // ACアダプタが接続されているかどうか + bool IsAdapterConnected(); + + // バッテリ残量が10%未満かどうか + bool IsBatteryLower(); + + // IVSを読み取れるかどうか + bool CanReadIVS(); + + // シリアルナンバーを読み取れるかどうか + bool CanReadSerialNumber(); + + // シリアルナンバーを取得する + void GetSerialNumber(u8** serial, size_t* size); + + // シリアルナンバーを返す + u8* GetSerialNumber(); + + // IVSを取得する + void GetIvs(void** ivs, size_t* size); + + // 32bitデバイスIDを返す + bit32 GetDeviceId(); + + // CUPメジャーバージョンを返す + u8 GetCupMajorVersion(); + + // CUPマイナーバージョンを返す + u8 GetCupMinorVersion(); + + // CUPマイクロバージョンを返す + u8 GetCupMicroVersion(); + + // NUPバージョンを返す + u8 GetNupVersion(); + + // MCUプロセスに接続するためのハンドルを返す + nn::Handle GetMcuHandle(); + + // バッテリ残量を0~100で返す + u32 GetBatteryRemain(); + + // 64bitインフラデバイスIDを返す + u64 GetInfraDeviceId(); + + // フレンドコードを返す + u64 GetFriendcode(); + + // MACアドレスを返す + char8* GetMacAddress(); + + // リージョンコードを返す + nn::cfg::CTR::CfgRegionCode GetRegion(); + + // リージョンコードを3文字のアルファベットに置き換えた文字列を返す + const char* GetRegionCodeA3(); + + // バージョン情報を取得する + void GetVersionData(common::VerDef* version); + + // フレンドコードを取得済みかどうか + bool HasReadFriendCode(); + +private: + void Initialize(); + void Finalize(); + + NN_PADDING4; + // フレンドコード + u64 m_FriendCode; + + // バージョン情報 + common::VerDef m_VerData; + + // mcu接続のためのハンドル + nn::Handle m_McuSession; + + // デバイスID + bit32 m_DeviceId; + + // IVSへのポインタ + void* mp_Ivs; + + // IVSのサイズ + size_t m_SizeofIvs; + NN_PADDING4; + + // MCUへのポインタ + nn::mcu::CTR::HwCheck* mp_Mcu; + + // リージョン + nn::cfg::CTR::CfgRegionCode m_Region; + + // バッテリ残量 + u8 m_BatteryRemain; + + // シリアルナンバーが読めるかどうか + bool m_CanReadSerialNumber; + + // IVSが読めるかどうか + bool m_CanReadIvs; + + // シリアルナンバー + u8 m_SerialNo[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + + // MACアドレス + char8 m_MacAddress[nn::nwm::Mac::MAC_STRING_SIZE]; + NN_PADDING3; + + // FriendCodeを読んだかどうか + bool m_HasReadFriendCode; + NN_PADDING3; + NN_PADDING4; + +}; + +} + +#endif /* UTIL_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/VersionDetect.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/VersionDetect.cpp new file mode 100644 index 0000000..09977cd --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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; + common::HeapManager heap(fileSize); + addr = heap.GetAddr(); + 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)); + } + } + } + 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; + common::HeapManager heap(fileSize); + addr = heap.GetAddr(); + 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)); + } + } + } + + 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/1stNUP_7/ConsoleDataMigration/sources/common/VersionDetect.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/VersionDetect.h new file mode 100644 index 0000000..9b41b56 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/VersionDetect.h @@ -0,0 +1,31 @@ +/*---------------------------------------------------------------------------* + 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/1stNUP_7/ConsoleDataMigration/sources/common/common_Types.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/common_Types.h new file mode 100644 index 0000000..fd76dad --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/common/common_Types.h @@ -0,0 +1,129 @@ +/*---------------------------------------------------------------------------* + 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 + +#include +#include + +namespace common +{ + +const u32 CONSOLE_WIDTH = 38; +const u32 CONSOLE_HEIGHT = 24; +const u32 CONSOLE_MAX_LINE = 1000; + + +const u32 NTR_WIFI_SETTING_SIZE = 0x400; // NTR Wifi 設定のサイズ +const u32 TWL_WIFI_SETTING_SIZE = 0x600; // TWL Wifi 設定のサイズ + +const u64 INFRA_DEVICE_ID_OFFSET = 0x400000000; + +// NOR領域のみにある設定データ用構造体 +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; +}; + +// CALに依存するCFGパラメータ +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, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_EU, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_CN, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_KR, + nn::pl::CTR::SHAREDDATA_TITLEID_CUP_VERSION_TW, +}; + +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, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_EU, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_CN, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_KR, + nn::pl::CTR::SHAREDDATA_TITLEID_NUP_VERSION_TW, +}; + +// SDに出力するデータのヘッダ +struct BackupDataHeader +{ + s64 size; // パディングを含まないファイルサイズ + NN_PADDING4; + NN_PADDING4; +}; + +// SDから読み込むファイルリストのエントリ +struct ImportDataEntry +{ + std::string fileName; + NN_PADDING3; + bool isDirectory; +}; + +typedef std::vector ImportDataList; + +// TWLセーブデータリストのエントリ +struct SavePathInfo +{ + std::wstring name; + NN_PADDING3; + bool isDirectory; +}; + +} + +#endif /* COMMON_TYPES_H_ */ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/configLoader.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/configLoader.cpp new file mode 100644 index 0000000..b262ba9 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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終端ぶん読めるサイズを減らす + 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終端しておく + + // ダブルクウォート中なら : も文字として読み取る + bool inEscape = false; + // # で行末までコメント + bool inComment = false; + // : で行頭から:までがkey、:から行末までがvalue + 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終端する + 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/1stNUP_7/ConsoleDataMigration/sources/common/configLoader.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/configLoader.h new file mode 100644 index 0000000..67e1edf --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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 を初期化します. + + 使用するファイルが存在するアーカイブは,あらかじめマウントしておく必要があります. + 読み込みに使用するバッファを確保し,引数 buffer に与える必要があります. + Finalize を呼ぶまでこのバッファは開放しないでください. + + 読み込ませることのできるフォーマット + ・エンコーディング:UTF-16 + ・バイトオーダ  :リトルエンディアン + ・改行記号    :不問 + + 半角コロンを含む行のみパラメータ記述行として読み込み,含まない行は無視します. + 半角コロンより前の文字はすべてパラメータ名として取得し, + 半角コロンより後の文字はすべてパラメータの値として取得します. + ParameterName : ParameterValue; + と記述すると + パラメータ名は 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); + + // スレッドセーフではありません. + 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/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/annotation.wav b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/annotation.wav new file mode 100644 index 0000000..b64f77b Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/annotation.wav differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/cursor.wav b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/cursor.wav new file mode 100644 index 0000000..85765b3 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/cursor.wav differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/lc.bcfnt b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/lc.bcfnt new file mode 100644 index 0000000..28d1db0 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/lc.bcfnt differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/ng.wav b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/ng.wav new file mode 100644 index 0000000..dc2f3ef Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/ng.wav differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/nnfont_RectDrawerShader.shbin b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/nnfont_RectDrawerShader.shbin new file mode 100644 index 0000000..4290c2c Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/nnfont_RectDrawerShader.shbin differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/ok.wav b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/ok.wav new file mode 100644 index 0000000..bf5149f Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/common/romfiles/ok.wav differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/common/wave.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/common/wave.cpp new file mode 100644 index 0000000..a897109 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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"); + } + + // ファイルサイズより大きくなるまで読み込む + 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; + } + // それ以外 + else + { + readbyte += chunk.size; + if (readbyte == fsize) break; + + // 読み飛ばす + reader.Seek(chunk.size, nn::fs::POSITION_BASE_CURRENT); + } + } +} + +#ifndef NN_BUILD_RELEASE // Release ビルドでは HostIO は使えません。 +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/1stNUP_7/ConsoleDataMigration/sources/common/wave.h b/branches/1stNUP_7/ConsoleDataMigration/sources/common/wave.h new file mode 100644 index 0000000..cbaf2f3 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/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 は使えません。 +#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 は使えません。 +void WriteWaveHeader(nn::hio::CTR::HostFile& hostFile, WaveFmt* fmt, s32 size); +#endif // NN_BUILD_RELEASE + +#endif // __WAVE_HEADER__ + +/*---------------------------------------------------------------------------*/ +/* end of file */ +/*---------------------------------------------------------------------------*/ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleBackup/Exporter/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleBackup/Exporter/OMakefile new file mode 100644 index 0000000..ef5f9f7 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleBackup/Exporter/OMakefile @@ -0,0 +1,63 @@ +#!/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-*.Process.MPCore.* + +include $(makePlatformDefsPath tests) + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + ../../../common \ + ../../../ConsoleBackup \ + + + +TEST_COMMON_SOURCES[] = + ../../../ConsoleBackup/Exporter.cpp + ../../../common/Util.cpp + ../../../common/HeapManager.cpp + ../../../common/SdLogger.cpp + ../../../common/LogConsole.cpp + ../../../common/CommonLogger.cpp + ../../../common/SdMountManager.cpp + ../../../common/PlayHistoryManager.cpp + ../../../common/VersionDetect.cpp + ../../../common/HardwareStateManager.cpp + ../../../common/FileTransfer.cpp + ../../../common/SdReaderWriter.cpp + + +SOURCES_TEST[] = test_Exporter.cpp + +ROMFS_ROOT = ../../../common/romfiles + +TEST_ENVIRONMENT_PROCESSLIST = true +TEST_ENVIRONMENT_EMUMEM = true + +LIBS += libnn_test \ + libnn_mcu \ + libnn_ps \ + libnn_am \ + lib_demo \ + + +ROM_SPEC_FILE = ../../../ConsoleBackup/ConsoleBackup.rsf +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/_private/RepairTool.desc + + +include $(makePlatformDefsPath build.tests) + + +tests: $(TEST_TARGETS) diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleBackup/Exporter/test_Exporter.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleBackup/Exporter/test_Exporter.cpp new file mode 100644 index 0000000..486e320 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleBackup/Exporter/test_Exporter.cpp @@ -0,0 +1,113 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: test_Util.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 "demo.h" + +#include "CommonLogger.h" +#include "HeapManager.h" +#include "Exporter.h" + +using namespace nn::test; + +class ExporterTest : public Suite { +public: + virtual bool InitializeSuite(); + virtual void FinalizeSuite(); + + ExporterTest() { + SUITE_NAME("TestUtil"); + TEST_ADD(ExporterTest::ExportTwlSaveData); + } +private: + void ExportTwlSaveData(); +}; + +namespace +{ + +const size_t s_GxHeapSize = 0x800000; + +} + +//------------------------------------------------------------------ +// Initialize/Finalize +//------------------------------------------------------------------ + +bool ExporterTest::InitializeSuite() +{ + // os の初期化 + nn::os::Initialize(); + + nn::fs::Initialize(); + + // amの初期化 + nn::am::InitializeForSystemMenu(); + + // ヒープの確保 + common::HeapManager::GetHeap()->Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + // RenderSystem の準備 + uptr heapForGx = reinterpret_cast(common::HeapManager::GetHeap()->Allocate(s_GxHeapSize)); + demo::RenderSystemDrawing renderSystem; + renderSystem.Initialize(heapForGx, s_GxHeapSize); + + // ログ描画の初期化 + common::Logger::GetLoggerInstance()->Initialize(common::CONSOLE_WIDTH, common::CONSOLE_HEIGHT, + common::CONSOLE_MAX_LINE, &renderSystem); + + return true; + +} + +void ExporterTest::FinalizeSuite() +{ +} + +//------------------------------------------------------------------ +// Test Util +//------------------------------------------------------------------ + + +//------------------------------------------------------------------ +// Test Functions +//------------------------------------------------------------------ + +void ExporterTest::ExportTwlSaveData() +{ + NN_LOG("WriteTwlTitleData\n"); + ConsoleBackup::ExportTwlSaveData(); + + while (!ConsoleBackup::IsExportThreadFinished()) + { + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(10)); + } + ConsoleBackup::FinalizeExportThread(); + +} + +NN_TEST_DEFINE_MAIN(ExporterTest) + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleBackup/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleBackup/OMakefile new file mode 100644 index 0000000..0b7f26b --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleBackup/OMakefile @@ -0,0 +1,20 @@ +#!/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$ +#---------------------------------------------------------------------------- + +if $(IsTestBuild) + .SUBDIRS: Exporter + +DefineDefaultRules() diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleRestore/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleRestore/OMakefile new file mode 100644 index 0000000..19fef5c --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleRestore/OMakefile @@ -0,0 +1,20 @@ +#!/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$ +#---------------------------------------------------------------------------- + +if $(IsTestBuild) + .SUBDIRS: TitleDownloader + +DefineDefaultRules() diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleRestore/TitleDownloader/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleRestore/TitleDownloader/OMakefile new file mode 100644 index 0000000..30f3b2d --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleRestore/TitleDownloader/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$ +#---------------------------------------------------------------------------- +SUPPORTED_TARGETS = CTR-*.Process.MPCore.* + +include $(makePlatformDefsPath tests) + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + ../../../common \ + ../../../ConsoleRestore \ + + + +TEST_COMMON_SOURCES[] = + ../../../ConsoleRestore/TitleDownloader.cpp + ../../../ConsoleRestore/Shop.cpp + ../../../common/Util.cpp + ../../../common/HeapManager.cpp + ../../../common/SdLogger.cpp + ../../../common/LogConsole.cpp + ../../../common/CommonLogger.cpp + ../../../common/SdMountManager.cpp + ../../../common/PlayHistoryManager.cpp + ../../../common/VersionDetect.cpp + ../../../common/HardwareStateManager.cpp + ../../../common/FileTransfer.cpp + ../../../common/SdReaderWriter.cpp + + +SOURCES_TEST[] = test_TitleDownloader.cpp + +ROMFS_ROOT = ../../../common/romfiles + +TEST_ENVIRONMENT_PROCESSLIST = true +TEST_ENVIRONMENT_EMUMEM = true + +LIBS += libnn_test \ + libnn_mcu \ + libnn_ps \ + libnn_am \ + lib_demo \ + libnn_nim \ + + +ROM_SPEC_FILE = ../../../ConsoleRestore/ConsoleRestore.rsf +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/_private/RepairTool.desc + + +include $(makePlatformDefsPath build.tests) + + +tests: $(TEST_TARGETS) diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleRestore/TitleDownloader/test_TitleDownloader.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleRestore/TitleDownloader/test_TitleDownloader.cpp new file mode 100644 index 0000000..97adbe2 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/ConsoleRestore/TitleDownloader/test_TitleDownloader.cpp @@ -0,0 +1,109 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: test_Util.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 "demo.h" + +#include "common_Types.h" +#include "CommonLogger.h" +#include "HeapManager.h" +#include "TitleDownloader.h" + +using namespace nn::test; + +class TitleDownloaderTest : public Suite { +public: + virtual bool InitializeSuite(); + virtual void FinalizeSuite(); + + TitleDownloaderTest() { + SUITE_NAME("TestUtil"); + TEST_ADD(TitleDownloaderTest::ListUp); + } +private: + void ListUp(); +}; + +namespace +{ + +const size_t s_GxHeapSize = 0x800000; + +} + +//------------------------------------------------------------------ +// Initialize/Finalize +//------------------------------------------------------------------ + +bool TitleDownloaderTest::InitializeSuite() +{ + // os の初期化 + nn::os::Initialize(); + + nn::fs::Initialize(); + + // amの初期化 + nn::am::InitializeForSystemMenu(); + + // ヒープの確保 + common::HeapManager::GetHeap()->Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + // RenderSystem の準備 + uptr heapForGx = reinterpret_cast(common::HeapManager::GetHeap()->Allocate(s_GxHeapSize)); + demo::RenderSystemDrawing renderSystem; + renderSystem.Initialize(heapForGx, s_GxHeapSize); + + // ログ描画の初期化 + common::Logger::GetLoggerInstance()->Initialize(common::CONSOLE_WIDTH, common::CONSOLE_HEIGHT, + common::CONSOLE_MAX_LINE, &renderSystem); + + return true; + +} + +void TitleDownloaderTest::FinalizeSuite() +{ +} + +//------------------------------------------------------------------ +// Test Util +//------------------------------------------------------------------ + + +//------------------------------------------------------------------ +// Test Functions +//------------------------------------------------------------------ + +void TitleDownloaderTest::ListUp() +{ + NN_LOG("WriteTwlTitleData\n"); + ConsoleRestore::TitleDownloader dl; + + dl.Start(); +} + +NN_TEST_DEFINE_MAIN(TitleDownloaderTest) + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/OMakefile new file mode 100644 index 0000000..970e68a --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/OMakefile @@ -0,0 +1,20 @@ +#!/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$ +#---------------------------------------------------------------------------- + +if $(IsTestBuild) + .SUBDIRS: common ConsoleBackup ConsoleRestore + +DefineDefaultRules() diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/common/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/common/OMakefile new file mode 100644 index 0000000..10686fc --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/common/OMakefile @@ -0,0 +1,20 @@ +#!/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$ +#---------------------------------------------------------------------------- + +if $(IsTestBuild) + .SUBDIRS: util + +DefineDefaultRules() diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/common/util/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/common/util/OMakefile new file mode 100644 index 0000000..825ae74 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/common/util/OMakefile @@ -0,0 +1,55 @@ +#!/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-*.Process.MPCore.* + +include $(makePlatformDefsPath tests) + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + ../../../common \ + + + +TEST_COMMON_SOURCES[] = + ../../../common/Util.cpp + ../../../common/HeapManager.cpp + ../../../common/SdLogger.cpp + ../../../common/LogConsole.cpp + ../../../common/CommonLogger.cpp + ../../../common/SdMountManager.cpp + ../../../common/VersionDetect.cpp + + +SOURCES_TEST[] = test_Util.cpp + +ROMFS_ROOT = ../../../common/romfiles + +TEST_ENVIRONMENT_PROCESSLIST = true +TEST_ENVIRONMENT_EMUMEM = true + +LIBS += libnn_test \ + libnn_mcu \ + libnn_ps \ + + +ROM_SPEC_FILE = ../../../ConsoleRestore/ConsoleRestore.rsf +DESCRIPTOR = $(HORIZON_ROOT)/resources/specfiles/_private/RepairTool.desc + + +include $(makePlatformDefsPath build.tests) + + +tests: $(TEST_TARGETS) diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tests/common/util/test_Util.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/common/util/test_Util.cpp new file mode 100644 index 0000000..9910ec5 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tests/common/util/test_Util.cpp @@ -0,0 +1,174 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: test_Util.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 "Util.h" + +using namespace nn::test; + +class UtilTest : public Suite { +public: + virtual bool InitializeSuite(); + virtual void FinalizeSuite(); + + UtilTest() { + SUITE_NAME("TestUtil"); + TEST_ADD(UtilTest::AddCheckDigit); + TEST_ADD(UtilTest::GetSaveDataDirectoryRoot); + } +private: + void AddCheckDigit(); + void GetSaveDataDirectoryRoot(); +}; + +//------------------------------------------------------------------ +// Initialize/Finalize +//------------------------------------------------------------------ + +bool UtilTest::InitializeSuite() +{ + nn::fs::Initialize(); + + return true; +} + +void UtilTest::FinalizeSuite() +{ +} + +//------------------------------------------------------------------ +// Test Util +//------------------------------------------------------------------ + + +//------------------------------------------------------------------ +// Test Functions +//------------------------------------------------------------------ + +void UtilTest::AddCheckDigit() +{ + + // 通常チェックデジット + { + const char serialBase[] = "EJF10000445"; + const char serialWithCheckDigit[] = "EJF100004458"; + char serial[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + std::memcpy(serial, serialBase, sizeof(serialBase)); + common::Util::AddCheckDigit(serial); + + NN_TEST_ASSERT_EQUAL(std::strcmp(serial, serialWithCheckDigit), 0); + } + + // チェックデジットが0になる場合 + { + const char serialBase[] = "CJF10004638"; + const char serialWithCheckDigit[] = "CJF100046380"; + char serial[nn::cfg::CTR::CFG_SECURE_INFO_SERIAL_NO_LEN]; + std::memcpy(serial, serialBase, sizeof(serialBase)); + common::Util::AddCheckDigit(serial); + + NN_TEST_ASSERT_EQUAL(std::strcmp(serial, serialWithCheckDigit), 0); + } +} + +void UtilTest::GetSaveDataDirectoryRoot() +{ + bit8 ivs[512]; + s64 ivsSize; + // 完全性検証SEEDの取得 + nn::Result 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()) + { + ivsSize = fis.GetSize(); + s32 readSize; + result = fis.TryRead(&readSize, ivs, ivsSize); + if (result.IsFailure()) + { + NN_DBG_PRINT_RESULT(result); + NN_TEST_FAIL("Can't Read SDCI"); + } + } + else + { + NN_TEST_FAIL("Can't Initialize File"); + } + fis.Finalize(); + } + else + { + NN_TEST_FAIL("Can't Mount nand:"); + } + + wchar_t saveDataRootWStr[nn::fs::MAX_FILE_PATH_LENGTH]; + nn::fs::Directory dir; + result = dir.TryInitialize("nand:/data/"); + if(result.IsSuccess()) + { + nn::fs::DirectoryEntry entry; + s32 num; + result = dir.TryRead(&num, &entry, 1); + if(result.IsSuccess()) + { + if(num == 1) + { + std::memset(saveDataRootWStr, 0, sizeof(saveDataRootWStr)); + std::wcscpy(saveDataRootWStr, entry.entryName); + } + else + { + NN_TEST_FAIL("Unknown Directory exists"); + } + } + else + { + NN_TEST_FAIL("Can't Read nand:/data/"); + } + } + else + { + NN_TEST_FAIL("Can't Initialize nand:/data/"); + } + + // 一旦アンマウントしておく + nn::fs::Unmount("nand:"); + + std::wstring tmp(saveDataRootWStr); + char saveDataRootStr[nn::fs::MAX_FILE_PATH_LENGTH]; + std::wcstombs(saveDataRootStr, tmp.c_str(), tmp.size()); + + std::string sysSaveRoot; + common::Util::GetSaveDataDirectoryRoot(sysSaveRoot, &ivs, ivsSize); + + NN_TEST_ASSERT_EQUAL(std::strcmp(sysSaveRoot.c_str(), saveDataRootStr), 0); +} + + +NN_TEST_DEFINE_MAIN(UtilTest) + +/*---------------------------------------------------------------------------* + End of file + *---------------------------------------------------------------------------*/ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/ExportedDataVerifier.bsf b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/ExportedDataVerifier.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/ExportedDataVerifier.bsf differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/ExportedDataVerifier.rsf b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/ExportedDataVerifier.rsf new file mode 100644 index 0000000..4fefd93 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/ExportedDataVerifier.rsf @@ -0,0 +1,50 @@ +BasicInfo: + Title : ExportedDataVeri + ProductCode: ExportedDataVeri + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xf8023 + Version: 0 + +SystemControlInfo: + AppType : Application + StackSize : 0xF000 + Dependency : + - gpio + - pdn + - spi + - i2c + - mcu + - ptm + - codec + - cfg + - hid + - gsp + +AccessControlInfo: + Priority : 16 + DisableDebug : true + + FileSystemAccess: + - DirectSdmc + - Debug + - Core + - CategoryFileSystemTool + + IoAccessControl: + - FsMountCardSpi + - FsMountNand + - FsMountTwln + +Option: + FreeProductCode: true + +CardInfo: + CardDevice: None + +Rom: + # ROM に含めるファイルシステムのルートパスを指定します。 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/OMakefile new file mode 100644 index 0000000..3eec50d --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/OMakefile @@ -0,0 +1,64 @@ +#!/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.* +CTR_APPTYPE = BOTH +CTR_MAKE_DEVELOPMENT_IMAGE = true + +TARGET_PROGRAM = ExportedDataVerifier + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + ../../common + +SOURCES[] = + main.cpp + ../../common/Util.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/VersionDetect.cpp + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = ../../common/romfiles + +LIBS += libnn_cfg \ + libnn_crypto \ + libnn_mcu \ + libnn_ps \ + 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/RepairTool.desc + +include $(ROOT_OMAKE)/modulerules + +build: $(DEFAULT_TARGETS) diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/model.cbmd b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/model.cbmd differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/sound.cbsd b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/sound.cbsd differ diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/unknown24x24.ctpk b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +888yyYyYyyyYyyYyyyyYyYy8 \ No newline at end of file diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/unknown48x48.ctpk b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +Y8888ƺ8888YYyyYYޚ޺yY8YyYYޚyY8ޚ8 \ No newline at end of file diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/main.cpp b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/main.cpp new file mode 100644 index 0000000..d72d44e --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/ExportedDataVerifier/main.cpp @@ -0,0 +1,495 @@ +/*---------------------------------------------------------------------------* + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "Aes_define.h" +#include "FileTransfer.h" +#include "CommonLogger.h" + +#include "demo.h" + +#include +#include + +#include "DrawSystemState.h" +#include "FileName.h" +#include "SimplePlayer.h" +#include "CommonLogger.h" +#include "SDMountManager.h" +#include "HeapManager.h" +#include "common_Types.h" +#include "VersionDetect.h" +#include "Util.h" +#include "CommonLogger.h" + +namespace +{ + +// グラフィックスに割り当てるメモリ +const size_t s_GxHeapSize = 0x800000; + +const u32 CONSOLE_WIDTH = 38; +const u32 CONSOLE_HEIGHT = 24; +const u32 CONSOLE_MAX_LINE = 1000; + +const size_t VERIFY_THREAD_STACK_SIZE = 0x4000; +nn::os::Thread s_VerifyThread; +nn::os::StackBuffer s_VerifyThreadStack; + +u32 s_VerifySuccess = 0; +u32 s_VerifyFail = 0; + +} + +void GenerateNandPath(wchar_t* toPath, const wchar_t* fromPath) +{ + // 切り詰める + std::string tmp(common::GetCharStr(fromPath)); + std::string twlPhotoRoot(common::GetCharStr(common::SD_SAVEDATA_TWL_PHOTO_ROOT_NAME)); + std::string twlSoundRoot(common::GetCharStr(common::SD_SAVEDATA_TWL_SOUND_ROOT_NAME)); + std::string ctrRoot(common::GetCharStr(common::SD_SAVEDATA_ROOT_NAME)); + + std::string output; + + std::string::size_type size; + size = tmp.find(twlPhotoRoot.c_str()); + if(size == std::string::npos) + { + size = tmp.find(twlSoundRoot.c_str()); + if(size == std::string::npos) + { + size = tmp.find(ctrRoot.c_str()); + if(size == std::string::npos) + { + // 想定外のパスへの出力のためreturn + return; + } + else + { + output += std::string("nand:/data/"); + output += tmp.substr(size + ctrRoot.size()); + } + } + else + { + output += std::string("twls:/"); + output += tmp.substr(size + twlSoundRoot.size()); + } + } + else + { + output += std::string("twlp:/"); + output += tmp.substr(size + twlPhotoRoot.size()); + } + + s32 length = std::mbstowcs(toPath, output.c_str(), nn::fs::MAX_FILE_PATH_LENGTH); + if(length == -1) + { + NN_PANIC("failed mbstowcs"); + } +} + +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; +} + +// ディレクトリ間のコピー +// アーカイブ越しのコピーが可能 +// アーカイブにマウントした状態で呼び出す必要あり +// 書き込み先のディレクトリはあらかじめ消去しておくこと。 +// 引数はスラッシュ付き +// TODO:分割して短くする +bool VerifyDirectory(const wchar_t * from_path, void* buf, + const size_t bufSize) +{ + using namespace common; + + nn::fs::Directory from_dir; + nn::fs::DirectoryEntry entry; + s32 numread = 0; + std::wostringstream target_from; + bool ret_value = true; + + nn::Result result = from_dir.TryInitialize(from_path); + + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(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; + + // ディレクトリの場合 + if (entry.attributes.isDirectory) + { + { + target_from << L"/"; + + + // 再帰処理 + if (!VerifyDirectory(target_from.str().c_str(), buf, bufSize)) + { + ret_value = false; + } + } + } + // ファイルの場合 + // SDカード上のファイルのCMACを検証する + else + { + nn::fs::FileInputStream sdFile; + s64 sdFileSize; + + result = sdFile.TryInitialize(target_from.str().c_str()); + if(result.IsFailure()) + { + ret_value = false; + break; + } + + result = sdFile.TryGetSize(&sdFileSize); + if (result.IsFailure()) + { + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + ret_value = false; + break; + } + else + { + + bit8 sdCmac[nn::crypto::AES_CMAC_MAC_SIZE]; + + // ハッシュが付加されていないとエラー + if (sdFileSize < nn::crypto::AES_CMAC_MAC_SIZE) + { + return false; + } + + s32 readSize; + // ハッシュを取得する + nn::crypto::Initialize(); + result = sdFile.TrySetPosition(sdFileSize - nn::crypto::AES_CMAC_MAC_SIZE); + if (result.IsSuccess()) + { + result = sdFile.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; + } + + sdFile.SetPosition(0); + + + // 復号化しながらハッシュを計算する + nn::crypto::SwAesCtrContext swAesCtrContext; + swAesCtrContext.Initialize(iv, common::key, sizeof(key)); + + nn::crypto::Sha256Context context; + context.Initialize(); + + wchar_t nandPath[nn::fs::MAX_FILE_PATH_LENGTH]; + // sdパスからnandパスを生成する + GenerateNandPath(nandPath, target_from.str().c_str()); + + // NAND上のフルパスをハッシュに含めている + context.Update(nandPath, std::wcslen(nandPath) * sizeof(wchar_t)); + + BackupDataHeader enc; + BackupDataHeader dec; + std::memset(&enc, 0, sizeof(enc)); + std::memset(&dec, 0, sizeof(dec)); + sdFile.TryRead(&readSize, &enc, sizeof(enc)); + COMMON_LOGGER_RESULT_IF_FAILED_WITH_LINE(result); + if(result.IsFailure()) + { + ret_value = false; + break; + } + context.Update(&enc, sizeof(enc)); + swAesCtrContext.Decrypt(&dec, &enc, sizeof(enc)); + + size_t totalReadSize = 0; + while (1) + { + result = sdFile.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); + if(!ret_value) + { + COMMON_LOGGER("********** Verification Failed **********\n %s\n", common::GetCharStr(target_from.str().c_str())); + s_VerifyFail++; + } + else + { + COMMON_LOGGER("Success %s\n", common::GetCharStr(target_from.str().c_str())); + s_VerifySuccess++; + } + break; + } + else + { + bool readDone = false;; + // CMACまで読んだかどうか + if (sdFileSize - (sizeof(BackupDataHeader) + nn::crypto::AES_CMAC_MAC_SIZE) < totalReadSize) + { + readSize -= totalReadSize - (sdFileSize - (sizeof(BackupDataHeader) + nn::crypto::AES_CMAC_MAC_SIZE)); + readDone = true; + } + context.Update(buf, readSize); + + if(readDone) + { + ret_value = CalculateAndCompareCmac(&context, sdCmac); + if(!ret_value) + { + COMMON_LOGGER("********** Verification Failed **********\n %s\n", common::GetCharStr(target_from.str().c_str())); + s_VerifyFail++; + } + else + { + COMMON_LOGGER("Success %s\n", common::GetCharStr(target_from.str().c_str())); + s_VerifySuccess++; + } + break; + } + } + } + } + nn::crypto::Finalize(); + sdFile.Finalize(); + } + } + } + from_dir.Finalize(); + return ret_value; +} + + +void VerifyThreadFunc() +{ + nn::Result result; + + COMMON_LOGGER("VerifyThreadFunc Start\n"); + s_VerifyFail = 0; + s_VerifySuccess = 0; + + result = common::SdMountManager::Mount(); + + size_t bufSize = common::GetAllocatableSize(AES_BLOCK_SIZE * 2); + + common::HeapManager heap(bufSize, AES_BLOCK_SIZE * 2); + void* buf = heap.GetAddr(); + if (buf != NULL) + { + u32 i = 0; + result = nn::fs::MountSpecialArchive(common::TWL_ARCHIVE_NAME_TABLE[i], common::TWL_FS_ARCHIVE_KIND[i]); + if (result.IsSuccess()) + { + VerifyDirectory( + (std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_SAVEDATA_TWL_SOUND_ROOT_NAME)).c_str(), buf, bufSize); + + } + nn::fs::Unmount(common::TWL_ARCHIVE_NAME_TABLE[i]); + + i++; + + result = nn::fs::MountSpecialArchive(common::TWL_ARCHIVE_NAME_TABLE[i], common::TWL_FS_ARCHIVE_KIND[i]); + if (result.IsSuccess()) + { + VerifyDirectory( + (std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring( + common::SD_SAVEDATA_TWL_PHOTO_ROOT_NAME)).c_str(), buf, bufSize); + } + nn::fs::Unmount(common::TWL_ARCHIVE_NAME_TABLE[i]); + + result = nn::fs::MountSpecialArchive(common::NAND_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_CTR_NAND); + if(result.IsSuccess()) + { + VerifyDirectory( + (std::wstring(common::SDMC_ROOT_DIRECTORY_PATH) + ::std::wstring(common::SD_SAVEDATA_ROOT_NAME)).c_str(), + buf, bufSize); + } + nn::fs::Unmount(common::NAND_ARCHIVE_NAME); + } + + common::SdMountManager::Unmount(); + + COMMON_LOGGER("Verify Thread Finalize\n"); + + COMMON_LOGGER("\n\n"); + COMMON_LOGGER("Verify Finished, success = %d, fail = %d\n", s_VerifySuccess, s_VerifyFail); +} + +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); + + // ヒープの確保 + common::InitializeHeap(); + + // RenderSystem の準備 + common::HeapManager gxHeap(s_GxHeapSize); + uptr heapForGx = reinterpret_cast(gxHeap.GetAddr()); + demo::RenderSystemDrawing s_RenderSystem; + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + + // ログ描画の初期化 + common::Logger::GetLoggerInstance()->Initialize(CONSOLE_WIDTH, CONSOLE_HEIGHT, CONSOLE_MAX_LINE, &s_RenderSystem); + + // RenderSystemを作ってからログが出せる + common::Logger::InitializeEjectThread(); + + COMMON_LOGGER("Verify Start\n"); + + // ボタン入力 + nn::hid::PadReader s_PadReader; + nn::hid::PadStatus padStatus; + + for(;;) + { + s_PadReader.ReadLatest(&padStatus); + + if(padStatus.trigger & nn::hid::BUTTON_A) + { + // SDにコピーするためのスレッドの作成 + if(s_VerifyThread.IsValid() && !s_VerifyThread.IsAlive()) + { + s_VerifyThread.Join(); + s_VerifyThread.Finalize(); + } + s_VerifyThread.Start(VerifyThreadFunc, s_VerifyThreadStack); + } + + // コンソールスクロール + 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(); + } + + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); + 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); + } +} diff --git a/branches/1stNUP_7/ConsoleDataMigration/sources/tools/OMakefile b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/OMakefile new file mode 100644 index 0000000..2d83e1f --- /dev/null +++ b/branches/1stNUP_7/ConsoleDataMigration/sources/tools/OMakefile @@ -0,0 +1,16 @@ +#!/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, *) diff --git a/branches/1stNUP_7/KENJEraser/DSiWareDeleteTool.desc b/branches/1stNUP_7/KENJEraser/DSiWareDeleteTool.desc new file mode 100644 index 0000000..68d8a82 --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/DSiWareDeleteTool.desc @@ -0,0 +1,229 @@ +AccessControlDescriptor: + AffinityMask: 1 + AutoGen: true + CoreVersion: 2 + DescVersion: 2 + Descriptor: | + AP///wAABAACAAAAAAAFGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIEAAAAAAABBUFQ6VQAAACRo + aW9GSU8AJGhvc3RpbzAkaG9zdGlvMWFjOnUAAAAAYm9zczpVAABjZmc6dQAA + AGRzcDo6RFNQZnJkOnUAAABmczpVU0VSAGdzcDo6R3B1aGlkOlVTRVJodHRw + OkMAAG5kbTp1AAAAbndtOjpVRFNwdG06dQAAAHB4aTpkZXYAc29jOlUAAABz + c2w6QwAAAGxkcjpybwAAYW06c3lzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAD+//vw/7//8ec/APIA8JH/APaR/1D/gf9Y/4H/cP+B/3j/gf8B + AQD/AAIA/v////////////////////////////////////////////////// + ////////////////////////////////////////AAAAAAAAAAAAAAAAAAAA + AAQDAAAAAAAAAAAAAAAAAAI= + DisableDebug: false + EnableInterruptNumbers: [] + EnableSystemCalls: + ArbitrateAddress: 34 + Break: 60 + CancelTimer: 28 + ClearEvent: 25 + ClearTimer: 29 + CloseHandle: 35 + ConnectToPort: 45 + ControlMemory: 1 + CreateAddressArbiter: 33 + CreateEvent: 23 + CreateMemoryBlock: 30 + CreateMutex: 19 + CreateSemaphore: 21 + CreateThread: 8 + CreateTimer: 26 + DuplicateHandle: 39 + ExitProcess: 3 + ExitThread: 9 + GetCurrentProcessorNumber: 17 + GetHandleInfo: 41 + GetProcessAffinityMask: 4 + GetProcessId: 53 + GetProcessIdOfThread: 54 + GetProcessIdealProcessor: 6 + GetProcessInfo: 43 + GetResourceLimit: 56 + GetResourceLimitCurrentValues: 58 + GetResourceLimitLimitValues: 57 + GetSystemInfo: 42 + GetSystemTick: 40 + GetThreadAffinityMask: 13 + GetThreadContext: 59 + GetThreadId: 55 + GetThreadIdealProcessor: 15 + GetThreadInfo: 44 + GetThreadPriority: 11 + MapMemoryBlock: 31 + OutputDebugString: 61 + QueryMemory: 2 + ReleaseMutex: 20 + ReleaseSemaphore: 22 + SendSyncRequest1: 46 + SendSyncRequest2: 47 + SendSyncRequest3: 48 + SendSyncRequest4: 49 + SendSyncRequest: 50 + SetProcessAffinityMask: 5 + SetProcessIdealProcessor: 7 + SetThreadAffinityMask: 14 + SetThreadIdealProcessor: 16 + SetThreadPriority: 12 + SetTimer: 27 + SignalEvent: 24 + SleepThread: 10 + UnmapMemoryBlock: 32 + WaitSynchronization1: 36 + WaitSynchronizationN: 37 + FileSystemAccess: + - Debug + - DirectSdmc + - DirectSdmcWrite + - Core + HandleTableSize: 512 + IORegisterMapping: + - 1ff50000-1ff57fff + - 1ff70000-1ff77fff + IdealProcessor: 1 + IoAccessControl: + - UseDirectSdmc + - SdApplication + - FsMountTwln + MemoryMapping: + - 1f000000-1f5fffff:r + MemoryType: Application + Priority: 24 + ProgramId: 0x00040000ffffff00L + ServiceAccessControl: + - APT:U + - $hioFIO + - $hostio0 + - $hostio1 + - ac:u + - boss:U + - cfg:u + - dsp::DSP + - frd:u + - fs:USER + - gsp::Gpu + - hid:USER + - http:C + - ndm:u + - nwm::UDS + - ptm:u + - pxi:dev + - soc:U + - ssl:C + - ldr:ro + - am:sys + Signature: | + df8WcNTaVgoVquQ9BkEsZoF3PpbJVmH6XIv6V9KHR/rJNpR/QcT2k/psvUNf + tlgvSy+ZtRIUE+xM0qelRXXZ/kpUUtPuYF0//cdetGKJIXVzV/0CLsChV1LQ + ZKDZasONA2of0sBQmyh82GWbIvwKuaQjkTcEpZ0xSO8qMRIFsE9T1itpZI3y + 39KZSBz5FNGizpA2UoFKCART2VDvx1owquaB6FaUjUEljRYF2B5xfzImsWtR + CMkbV7rSfKjCl1f2VLIPxc7GbOkY4/nYShaZgp9tvCFlBtUPLoec9TEr6Nn+ + +r6Kh9BvXqPdd3rpDtHXim9CSWgXmZsNtIdoJ5rS7g== + StorageId: + - 0 +CommonHeaderKey: + D: | + 2dZqKOrq81unaSIjE7BboKKaCHaNsjpoZcjSnwX3x8NMSHC2ovTPP3iR+6Qz + Rq15iPQg2NV/4WbMMmKFNfVIrsNEAbpOFpQCXdriiwsXHMziM1wO7Td4qzYN + z/s6ZNxhTxpdKtISUDmkyLGVFBCGNV4EPJkEM+GWqn5yKw1uX0lt2x/iICGR + WE8f02khCCpAD1/CrrSaUHBrodE9lXX0lGT8rYEB7avrl99FNFcxa8NUslqN + 0lcP9yzzssJNQitYiZv5VLkJgAt4RCadsZd5sWblqGTFK/zEd7wN4BXs87tR + RLDWMAeJ3L/e4ZRpenon/vit1o9UmSgSGKb9klejAQ== + DP: | + xRNzBAhcOLE51pbYrWt4xBMokTuY/NhJN6IoN+r8dg3jIwBq4H9PtlV+gyqU + 4mTptKZiNyZa8uvUt0TlB/BgFiwc7MWkFTcJ+TBB1orXC38bTTBLGP1J7B/S + MEPveiQjjUHRaBFjS+5BMfcXeOcQ9/FOt1FiuHcvDKWKD85tgYE= + DQ: | + euNxPVbXvF/a9HPArd3Fd8BUcm4Fb0Q18W0SYqHdDD4mP7lWjTKHGADix1OX + UtqNPyv6NbJ5WnwKg4oqB9zl4Dxu6JyrifBiZ2VxngrLLA0xRKYjxNxMIAgx + 7PbgQcZ5x45fgNa1QFA31oQnaa2Mvr4PgHqMlK6VIFqEg+ZA/+c= + Exponent: | + AQAB + InverseQ: | + 5WZLcyBu4+Mq8aTpVybYh1boPuVyMSvBeCvkedKssUvG8PFhx5Z5vMkvjgpo + ckM/etwsOwSLGuDzzUhMFflM1koSi+dwyR0FpRAkTnXeY12xgwbVaiMJot0v + e37qFGCMYiDQXu4wjbiR2IJ6YRmSSy3RyBHiMw++y/6vKKQ1jPI= + Modulus: | + 5OQ4q7/KRkL+yc/QrOysdG0wKlwgzj0VlwfdnvEBfBSjG6bAALQkqWVzUXkk + JaHcun6evvaHq7Tc9Aa6xNMgA7oBsfGVpneGMFrjvJzDqi9gjZQUdirfyIDR + Hp+F/A4DXQ3CUufnUTv2F+W5ACNOpe8QR9UOBjrJGYzmFS1VvF2wNqy5cNhg + CH4lK6fmetKCJn60EWzPahvLPRJbWITvtmky21GQ0JOU87I8n4r288JTVKEW + FDtku26iWW67erVUpn21KQvimhWjiuKAjAWEzt97np0GdxNs8fSWq57jTwuT + eyEZayHXbHsjp8hNU11aML7mM5IYgRRZGFV3OU+ufw== + P: | + /B+LD7VSdc2FL61myP2m92eBsOdxzMtb7egh3zGnnRDbUxKE7o97imkL+gx5 + MtdXvWWZSKnB9dbmkcSxpaLuV6cvHmBPxUmn2W6nlRT025c2F4Zti+fJrUEE + GSMKH/Xp+qE5o03+geWPYffFjUugxGJMrmKYpVGxYdRWYSY5xKE= + Q: | + 6Gk6mKRG6huUf7xPHhuFYNdzigZO1Z15XfRmcrNaHwlVhkPofzEQDpj8mI4g + RaJIVi1a147vK8B5gcgeGNQ2Ukyhw9j+tjDN9nB9b7mAnZ97+9Q9R5A/rtQF + kGFga2AwkNsT2/cXX9HYBi0IqhFoe+URHvJc8ba23O3EQLSlfx8= +DefaultSpec: + AccessControlInfo: + AffinityMask: 1 + FirmwareVersion: 2 + HandleTableSize: 512 + IORegisterMapping: + - 1ff50000-1ff57fff + - 1ff70000-1ff77fff + IdealProcessor: 0 + MemoryMapping: + - 1f000000-1f5fffff:r + Priority: 16 + BasicInfo: + CompanyCode: "00" + Logo: Nintendo + Title: default + ExeFs: + ReadOnly: + - RO + ReadWrite: + - RW + Text: + - STUP_ENTRY + Media: + MediaType: Card + PlainRegion: + - .module_id + Rom: + DefaultReject: + - .* + File: + - "*" + SystemControlInfo: + Dependency: + ac: 0x0004013000002402L + am: 0x0004013000001502L + boss: 0x0004013000003402L + camera: 0x0004013000001602L + cecd: 0x0004013000002602L + cfg: 0x0004013000001702L + codec: 0x0004013000001802L + csnd: 0x0004013000002702L + dlp: 0x0004013000002802L + dsp: 0x0004013000001a02L + friends: 0x0004013000003202L + gpio: 0x0004013000001b02L + gsp: 0x0004013000001c02L + hid: 0x0004013000001d02L + http: 0x0004013000002902L + i2c: 0x0004013000001e02L + mcu: 0x0004013000001f02L + mic: 0x0004013000002002L + ndm: 0x0004013000002b02L + news: 0x0004013000003502L + nim: 0x0004013000002c02L + nwm: 0x0004013000002d02L + pdn: 0x0004013000002102L + ps: 0x0004013000003102L + ptm: 0x0004013000002202L + ro: 0x0004013000003702L + socket: 0x0004013000002e02L + spi: 0x0004013000002302L + ssl: 0x0004013000002f02L + StackSize: 16384 diff --git a/branches/1stNUP_7/KENJEraser/HeapManager.cpp b/branches/1stNUP_7/KENJEraser/HeapManager.cpp new file mode 100644 index 0000000..29f4367 --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/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/1stNUP_7/KENJEraser/HeapManager.h b/branches/1stNUP_7/KENJEraser/HeapManager.h new file mode 100644 index 0000000..b9fc469 --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/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/1stNUP_7/KENJEraser/KENJEraser.bsf b/branches/1stNUP_7/KENJEraser/KENJEraser.bsf new file mode 100644 index 0000000..104a94d Binary files /dev/null and b/branches/1stNUP_7/KENJEraser/KENJEraser.bsf differ diff --git a/branches/1stNUP_7/KENJEraser/KENJEraser.rsf b/branches/1stNUP_7/KENJEraser/KENJEraser.rsf new file mode 100644 index 0000000..d52e186 --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/KENJEraser.rsf @@ -0,0 +1,47 @@ +BasicInfo: + Title : KENJEraser + ProductCode: CTR-P-24HA + BackupMemoryType: None + +TitleInfo: + Use: Evaluation + Category: Application + UniqueId: 0xF8037 + 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: + - Core + + IoAccessControl: + - FsMountTwln + +Option: + FreeProductCode: true + + +Rom: + # ROM に含めるファイルシステムのルートパスを指定します。 + HostRoot: "$(ROMFS_ROOT)" \ No newline at end of file diff --git a/branches/1stNUP_7/KENJEraser/OMakefile b/branches/1stNUP_7/KENJEraser/OMakefile new file mode 100644 index 0000000..f615b21 --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/OMakefile @@ -0,0 +1,68 @@ +#!/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.* +CTR_APPTYPE = BOTH +CTR_MAKE_DEVELOPMENT_IMAGE = true + +TARGET_PROGRAM = KENJEraser + +SAMPLED_DEMOS_COMMON_INCLUDE_DIR = $(dir $(HORIZON_ROOT)/../CTR/SampleDemos/common/include) +INCLUDES += $(SAMPLED_DEMOS_COMMON_INCLUDE_DIR) \ + +SOURCES[] = + main.cpp + ResFont.cpp + HeapManager.cpp + +CTR_BANNER_SPEC = $(TARGET_PROGRAM).bsf + +ROMFS_ROOT = romfiles + +SHADER_BIN = nnfont_RectDrawerShader.shbin +SHADER_PATH = $(ROMFS_ROOT)/$(SHADER_BIN) + +ROMFS_DEPENDENCIES = $(SHADER_PATH) + +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 \ + +INSTALL_SDK_TOOL = true + +ROM_SPEC_FILE = $(TARGET_PROGRAM).rsf +DESCRIPTOR = DSiWareDeleteTool.desc + +include $(ROOT_OMAKE)/modulerules + +VERSION_H = $(file version.h) + +build: $(DEFAULT_TARGETS) diff --git a/branches/1stNUP_7/KENJEraser/OMakeroot b/branches/1stNUP_7/KENJEraser/OMakeroot new file mode 100644 index 0000000..875e083 --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/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$ +#---------------------------------------------------------------------------- + +# fBNgCAEgɂ‚Ă̐ +# +# a) \[XR[h[gfBNgɔzuꍇ +# : +# /OMakeroot +# /foo/bar/OMakefile +# +# : +# OMakefile ƓfBNgȉ objects images ܂B +# +# /foo/bar/objects/... +# /foo/bar/images/.. +# +# +# b) \[XR[h sources ȉɔzuꍇ +# : +# /OMakeroot +# /sources/foo/bar/OMakefile +# +# : +# [gfBNgȉ objects images ܂B +# +# /objects/foo/bar/... +# /images/foo/bar/... +# +# + +# [g‹ϐ̎擾 +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 v܂BpXݒ肷邩Aǂ炩`ĉB) + 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/1stNUP_7/KENJEraser/ResFont.cpp b/branches/1stNUP_7/KENJEraser/ResFont.cpp new file mode 100644 index 0000000..b0183df --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/ResFont.cpp @@ -0,0 +1,417 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ResFont.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$ + *---------------------------------------------------------------------------*/ + +//------------------------------------------------------------------ +// デモ: ResFont +// +// 概要 +// nn::font::ResFont の構築と破棄のサンプルです。 +// +// 操作 +// なし。 +// +//------------------------------------------------------------------ + +#include +#include +#include +#include +#include + +#include "ResFont.h" +#include "demo.h" +#include "HeapManager.h" + +namespace common +{ + +namespace +{ +const char s_ShaderBinaryFilePath[] = "rom:/nnfont_RectDrawerShader.shbin"; +const char s_FontFilePath[] = "rom:/lc.bcfnt"; + +const u8 s_Color = 255; + +nn::font::RectDrawer s_Drawer; +void* s_DrawerBuf; +nn::font::ResFont s_Font; +nn::font::DispStringBuffer *s_pDrawStringBuf0; +nn::font::TextWriter s_TextWriter; +void (*s_DrawTextFunc)() = NULL; + +//--------------------------------------------------------------------------- +//! @brief シェーダの初期化を行います。 +//! +//! @param[in,out] pResource 描画用リソースを管理するオブジェクトへのポインタ。 +//--------------------------------------------------------------------------- +void* +InitShaders(nn::font::RectDrawer* pDrawer) +{ + nn::fs::FileReader shaderReader(s_ShaderBinaryFilePath); + + const u32 fileSize = (u32)shaderReader.GetSize(); + + void* shaderBinary = HeapManager::GetHeap()->Allocate(fileSize); + NN_NULL_ASSERT(shaderBinary); + +#ifndef NN_BUILD_RELEASE + s32 read = +#endif // NN_BUILD_RELEASE + shaderReader.Read(shaderBinary, fileSize); + NN_ASSERT(read == fileSize); + + const u32 vtxBufCmdBufSize = + nn::font::RectDrawer::GetVertexBufferCommandBufferSize(shaderBinary, fileSize); + void *const vtxBufCmdBuf = HeapManager::GetHeap()->Allocate(vtxBufCmdBufSize); + NN_NULL_ASSERT(vtxBufCmdBuf); + pDrawer->Initialize(vtxBufCmdBuf, shaderBinary, fileSize); + + HeapManager::GetHeap()->Free(shaderBinary); + + return vtxBufCmdBuf; + +} + +//--------------------------------------------------------------------------- +//! @brief 描画の初期設定を行います。 +//! +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +InitDraw( + s32 width, + s32 height +) +{ + // カラーバッファ情報 + // LCDの向きに合わせて、幅と高さを入れ替えています。 + 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 ), + + // ステンシルテストを無効 + NN_FONT_CMD_SET_DISABLE_STENCIL_TEST(), + + // デプステストを無効 + // カラーバッファの全ての成分を書き込み可 + NN_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK( + false, // isDepthTestEnabled + 0, // depthFunc + true, // depthMask + true, // red + true, // green + true, // blue + true), // alpha + + // アーリーデプステストを無効 + 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, + const char* filePath +) +{ + // フォントリソースをロードします + nn::fs::FileReader fontReader(filePath); + + s32 fileSize = (s32)fontReader.GetSize(); + if ( fileSize <= 0 ) + { + return false; + } + + void* buffer = HeapManager::GetHeap()->Allocate(fileSize, nn::font::GlyphDataAlignment); + if (buffer == NULL) + { + return false; + } + + s32 readSize = fontReader.Read(buffer, fileSize); + if (readSize != fileSize) + { + HeapManager::GetHeap()->Free(buffer); + return false; + } + + // フォントリソースをセットします + bool bSuccess = pFont->SetResource(buffer); + NN_ASSERT(bSuccess); + + //--- 既にリソースをセット済みであるか,ロード済みであるか、リソースが不正な場合に失敗します。 + if (! bSuccess) + { + HeapManager::GetHeap()->Free(buffer); + } + + // 描画用バッファを設定します。 + const u32 drawBufferSize = nn::font::ResFont::GetDrawBufferSize(buffer); + void* drawBuffer = HeapManager::GetHeap()->Allocate(drawBufferSize, 4); + NN_NULL_ASSERT(drawBuffer); + pFont->SetDrawBuffer(drawBuffer); + + return bSuccess; +} + +//--------------------------------------------------------------------------- +//! @brief ResFontを破棄します。 +//! +//! @param[in] pFont 破棄するフォントへのポインタ。 +//--------------------------------------------------------------------------- +void +CleanupFont(nn::font::ResFont* pFont) +{ + // 描画用バッファの無効化 + // 描画用バッファがセットされているなら 構築時に SetDrawBuffer に渡したバッファへの + // ポインタが返ってきます。 + void *const drawBuffer = pFont->SetDrawBuffer(NULL); + if (drawBuffer != NULL) + { + HeapManager::GetHeap()->Free(drawBuffer); + } + + // フォントがセットされているなら SetResource 時に渡したリソースへの + // ポインタが返ってきます。 + void *const resource = pFont->RemoveResource(); + if (resource != NULL) + { + HeapManager::GetHeap()->Free(resource); + } + + // RemoveResource 後は再度 SetResource するまでフォントとして使用できません。 +} + +//--------------------------------------------------------------------------- +//! @brief 表示文字列用バッファを確保します。 +//! +//! @param[in] charMax 表示する文字列の最大文字数。 +//! +//! @return 確保した表示文字列用バッファへのポインタを返します。 +//--------------------------------------------------------------------------- +nn::font::DispStringBuffer* +AllocDispStringBuffer(s32 charMax) +{ + const u32 DrawBufferSize = nn::font::CharWriter::GetDispStringBufferSize(charMax); + void *const bufMem = HeapManager::GetHeap()->Allocate(DrawBufferSize); + NN_NULL_ASSERT(bufMem); + + return nn::font::CharWriter::InitDispStringBuffer(bufMem, charMax); +} + +//--------------------------------------------------------------------------- +//! @brief 文字列表示用にモデルビュー行列と射影行列を設定します。 +//! +//! @param[in] pDrawer RectDrawerオブジェクトへのポインタ。 +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +SetupTextCamera( + nn::font::RectDrawer* pDrawer, + s32 width, + s32 height +) +{ + // 射影行列を正射影に設定 + { + // 左上原点とし、Y軸とZ軸の向きが逆になるように設定します。 + 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); + } + + // モデルビュー行列を単位行列に設定 + { + nn::math::MTX34 mv; + nn::math::MTX34Identity(&mv); + pDrawer->SetViewMtxForText(mv); + } +} + +//--------------------------------------------------------------------------- +//! @brief ASCII文字列を描画します。 +//! +//! @param[in] pDrawer RectDrawerオブジェクトへのポインタ。 +//! @param[in] pDrawStringBuf DispStringBufferオブジェクトへのポインタ。 +//! @param[in] pFont フォントへのポインタ。 +//! @param[in] width 画面の幅。 +//! @param[in] height 画面の高さ。 +//--------------------------------------------------------------------------- +void +DrawAscii( + nn::font::RectDrawer* pDrawer, + nn::font::DispStringBuffer* pDrawStringBuf, + nn::font::ResFont* pFont, + s32 width, + s32 height +) +{ + s_TextWriter.SetDispStringBuffer(pDrawStringBuf); + s_TextWriter.SetFont(pFont); + + s_TextWriter.SetCursor(0, 0, 1.f); + + s_TextWriter.StartPrint(); + if(s_DrawTextFunc != NULL) + { + s_DrawTextFunc(); + } + + s_TextWriter.EndPrint(); + pDrawer->BuildTextCommand(&s_TextWriter); + + + // 文字の色は、文字列の描画コマンドを再作成しなくても変更できます。 + s_TextWriter.SetTextColor(nn::util::Color8(s_Color, s_Color, s_Color, s_Color)); + + pDrawer->DrawBegin(); + + SetupTextCamera(pDrawer, width, height); + s_TextWriter.UseCommandBuffer(); + + pDrawer->DrawEnd(); +} + +} // namespace + +void SetDrawTextHandler(void (*func)()) +{ + s_DrawTextFunc = func; +} + + +//--------------------------------------------------------------------------- +//! @brief サンプルのメイン関数です。 +//--------------------------------------------------------------------------- +void +InitializeResFont() +{ + 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)); + + // フォントの構築 + { +#ifndef NN_BUILD_RELEASE + bool bSuccess = +#endif // NN_BUILD_RELEASE + InitFont(&s_Font, s_FontFilePath); + NN_ASSERTMSG(bSuccess, "Fail to load ResFont."); + } + + // 描画リソースの構築 + s_DrawerBuf = InitShaders(&s_Drawer); + + // 描画文字列用バッファの確保 + s_pDrawStringBuf0 = AllocDispStringBuffer(512); + + nn::fs::Unmount("rom:"); + +} + +void DrawResFont(s32 display) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + if(display == NN_GX_DISPLAY0) + { + InitDraw(NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + + DrawAscii(&s_Drawer, s_pDrawStringBuf0, &s_Font, NN_GX_DISPLAY0_WIDTH, NN_GX_DISPLAY0_HEIGHT); + } + else if(display == NN_GX_DISPLAY1) + { + InitDraw(NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT); + + DrawAscii(&s_Drawer, s_pDrawStringBuf0, &s_Font, NN_GX_DISPLAY1_WIDTH, NN_GX_DISPLAY1_HEIGHT); + } + + nngxUpdateState(NN_GX_STATE_ALL); +} + +void FinalizeResFont() +{ + s_Drawer.Finalize(); + + // 描画リソースの破棄 + HeapManager::GetHeap()->Free(s_DrawerBuf); + + // フォントの破棄 + CleanupFont(&s_Font); + + // 描画文字列用バッファの解放 + HeapManager::GetHeap()->Free(s_pDrawStringBuf0); +} + +nn::font::TextWriter* GetTextWriter() +{ + return &s_TextWriter; +} + +} diff --git a/branches/1stNUP_7/KENJEraser/ResFont.h b/branches/1stNUP_7/KENJEraser/ResFont.h new file mode 100644 index 0000000..ca53420 --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/ResFont.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: ResFont.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 RESFONT_H_ +#define RESFONT_H_ + +#include + +namespace common +{ + +void InitializeResFont(); +void DrawResFont(s32 display); +void SetDrawTextHandler(void (*func)()); +nn::font::TextWriter* GetTextWriter(); + + +} + + +#endif /* RESFONT_H_ */ diff --git a/branches/1stNUP_7/KENJEraser/banner/model.cbmd b/branches/1stNUP_7/KENJEraser/banner/model.cbmd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/KENJEraser/banner/model.cbmd differ diff --git a/branches/1stNUP_7/KENJEraser/banner/sound.cbsd b/branches/1stNUP_7/KENJEraser/banner/sound.cbsd new file mode 100644 index 0000000..f1c7b62 Binary files /dev/null and b/branches/1stNUP_7/KENJEraser/banner/sound.cbsd differ diff --git a/branches/1stNUP_7/KENJEraser/banner/unknown24x24.ctpk b/branches/1stNUP_7/KENJEraser/banner/unknown24x24.ctpk new file mode 100644 index 0000000..794b136 --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/banner/unknown24x24.ctpk @@ -0,0 +1 @@ +888yyYyYyyyYyyYyyyyYyYy8 \ No newline at end of file diff --git a/branches/1stNUP_7/KENJEraser/banner/unknown48x48.ctpk b/branches/1stNUP_7/KENJEraser/banner/unknown48x48.ctpk new file mode 100644 index 0000000..8c7da16 --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/banner/unknown48x48.ctpk @@ -0,0 +1 @@ +Y8888ƺ8888YYyyYYޚ޺yY8YyYYޚyY8ޚ8 \ No newline at end of file diff --git a/branches/1stNUP_7/KENJEraser/main.cpp b/branches/1stNUP_7/KENJEraser/main.cpp new file mode 100644 index 0000000..8a9c8aa --- /dev/null +++ b/branches/1stNUP_7/KENJEraser/main.cpp @@ -0,0 +1,391 @@ +/*---------------------------------------------------------------------------* + Project: Horizon + File: main.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 + +#include +#include + +#include "demo.h" +#include "ResFont.h" +#include "HeapManager.h" + +#define UTIL_RETURN_IF_NOT_AM_NOT_FOUND(result) \ + if(result.IsFailure()) \ + { \ + if(result != nn::am::ResultNotFound()) \ + { \ + return result; \ + } \ + nn::dbg::PrintResult(result); \ +} \ + +#define RED 1.0f, 0.0f, 0.0f +#define GREEN 0.0f, 1.0f, 0.0f +#define YELLOW 1.0f, 1.0f, 0.0f +#define WHITE 1.0f, 1.0f, 1.0f +#define BLACK 0.0f, 0.0f, 0.0f + +namespace { + const char* const NAND_TWL_ARCHIVE_NAME = "twln:"; + const char* const NAND_TWL_KENJ_DIR_PATHNAME = "twln:/title/00030004/4b454e4a"; + const char* const NAND_TWL_KENJ_SAVE_DATA_PATHNAME = "twln:/title/00030004/4b454e4a/data/Public.sav"; + const nn::ProgramId NAND_TWL_KENJ_PROGRAM_ID = 0x000480044b454e4aULL; + + // 乱数生成クラス + // 線形合同法を用いて乱数を生成する。 + class Random + { + private: + nn::util::Int64 m_x; //!< 乱数値 + nn::util::Int64 m_mul; //!< 乗数 + nn::util::Int64 m_add; //!< 加算する数 + + public: + Random(u64 seed = 0) + { + SetSeed(seed); + } + + void SetSeed(u64 seed) + { + m_x = seed; + m_mul = (1566083941LL << 32) + 1812433253LL; + m_add = 2531011; + } + + u32 Get32(u32 max = 0xFFFFFFFFU) + { + m_x = m_mul * m_x + m_add; + + if (max != 0) + { + return (u32)(((m_x >> 32) * max) >> 32); + } + return 0; + } + }; + + nn::Result DeleteKENJ(void); + + const size_t ERASE_THREAD_STACK_SIZE = 0x1000; + nn::os::Thread s_EraseThread; + nn::os::StackBuffer s_EraseThreadStack; + + demo::RenderSystemDrawing s_RenderSystem; + + bool s_IsAppExist = false; + bool s_IsFinish = false; + bool s_IsSaveDataCleanSuccess = false; + bool s_IsAppDeleteSuccess = false; + nn::Result s_result; + + // グラフィックスに割り当てるメモリ + const size_t s_GxHeapSize = 0x800000; + + + void EraseThreadFunc(void) + { + // ほぼ日健康手帳を消去する + s_result = DeleteKENJ(); + + s_IsFinish = true; + } + + nn::Result FillRandamDataToKENJSaveData(void) + { + nn::Result result; + nn::fs::FileStream file; + s64 file_size; + + // セーブデータオープン + result = file.TryInitialize( NAND_TWL_KENJ_SAVE_DATA_PATHNAME, nn::fs::OPEN_MODE_WRITE ); + if( result.IsFailure() ) + { + return result; + } + + // セーブデータファイルのサイズを読む + result = file.TryGetSize( &file_size ); + if( result.IsFailure() ) + { + file.Finalize(); + return result; + } + + nn::fnd::DateTime tm; + nn::os::Tick tick; + Random rand; + u64 seed; + s32 sizeResult = 0; + + // バッファの確保 + void *buf = std::malloc( file_size ); + NN_TPANIC_IF_NULL_( buf ); + + // 乱数のシードを設定 + nn::fnd::DateTimeParameters param = tm.GetNow().GetParameters(); + seed = tm.DateToDays( param.year, param.month, param.day ); + seed = (u64)(seed * 86400 + param.hour * 3600 + param.minute * 60 + param.second); + seed = (u64)(seed ^ tick.GetSystemCurrent()); + rand.SetSeed( seed ); + + // バッファを乱数で埋める + u8 *p = (u8 *)buf; + for (s32 loopSizeFile = 0; loopSizeFile < file_size; loopSizeFile++) + { + p[loopSizeFile] = (u8)rand.Get32(0xff); + } + + // 書き込み + result = file.TryWrite(&sizeResult, buf, file_size); + + file.Finalize(); + + return result; + } + + + nn::Result DeleteKENJ(void) + { + nn::Result result; + + // TWl領域をマウントする + result = nn::fs::MountSpecialArchive( NAND_TWL_ARCHIVE_NAME, nn::fs::CTR::ARCHIVE_TYPE_TWL_NAND ); + if( result.IsFailure() ) + { + NN_LOG("Twl NAND Mount Failed...\n"); + return result; + } + + // アプリが存在するかどうか確かめる + nn::fs::Directory dir; + if( dir.TryInitialize(NAND_TWL_KENJ_DIR_PATHNAME).IsFailure() ) + { + dir.Finalize(); + } + else + { + // アプリ存在フラグを上げる + s_IsAppExist = true; + + // ここでfinalizeしておかないと、DeleteProgramでフェータルになる。 + dir.Finalize(); + + // ほぼ日健康手帳のセーブデータを乱数で埋める + result = FillRandamDataToKENJSaveData(); + if( result.IsFailure() ) + { + nn::fs::Unmount( "twln:" ); + return result; + } + else + { + s_IsSaveDataCleanSuccess = true; + } + + // ほぼ日健康手帳を消す + result = nn::am::DeleteUserProgram(nn::fs::MEDIA_TYPE_NAND, NAND_TWL_KENJ_PROGRAM_ID); + if( result.IsSuccess() ) + { + s_IsAppDeleteSuccess = true; + } + + UTIL_RETURN_IF_NOT_AM_NOT_FOUND(result); + } + + nn::fs::Unmount( "twln:" ); + + return result; + } + + + void DrawResultText() + { + s_RenderSystem.SetFontSize(8.0f); + s_RenderSystem.SetColor( YELLOW ); + s_RenderSystem.DrawText(10.0f, 20.0f, "SaveData Cleaner"); + + s_RenderSystem.SetColor( WHITE ); + s_RenderSystem.DrawText(10.0f, 60.0f, "Initialcode : KENJ"); + + if( s_result.IsSuccess() ) + { + if( s_IsAppExist ) + { + s_RenderSystem.SetColor( GREEN ); + s_RenderSystem.DrawText(10.0f, 75.0f, "application found"); + + s_RenderSystem.SetColor( WHITE ); + s_RenderSystem.DrawText(10.0f, 120.0f, "Private Save :"); + s_RenderSystem.DrawText(10.0f, 135.0f, "Public Save :"); + s_RenderSystem.DrawText(10.0f, 150.0f, "application :"); + + s_RenderSystem.SetColor( YELLOW ); + s_RenderSystem.DrawText(130.0f, 120.0f, "not existed"); + + s_RenderSystem.SetColor( GREEN ); + s_RenderSystem.DrawText(130.0f, 135.0f, "cleanup succeeded"); + s_RenderSystem.DrawText(130.0f, 150.0f, "cleanup succeeded"); + } + else + { + s_RenderSystem.SetColor( YELLOW ); + s_RenderSystem.DrawText(10.0f, 70.0f, "application not found"); + } + } + else + { + s_RenderSystem.SetColor( WHITE ); + s_RenderSystem.DrawText(10.0f, 120.0f, "Private Save :"); + s_RenderSystem.DrawText(10.0f, 135.0f, "Public Save :"); + s_RenderSystem.DrawText(10.0f, 150.0f, "application :"); + + s_RenderSystem.SetColor( YELLOW ); + s_RenderSystem.DrawText(130.0f, 120.0f, "not existed"); + + // アプリある? + if( s_IsAppExist ) + { + s_RenderSystem.SetColor( GREEN ); + s_RenderSystem.DrawText(10.0f, 75.0f, "application found"); + } + else + { + s_RenderSystem.SetColor( RED ); + s_RenderSystem.DrawText(10.0f, 75.0f, "application not found"); + } + + // セーブデータの乱数埋めでエラー? + if( s_IsSaveDataCleanSuccess ) + { + s_RenderSystem.SetColor( GREEN ); + s_RenderSystem.DrawText(130.0f, 135.0f, "cleanup succeeded"); + } + else + { + s_RenderSystem.SetColor( RED ); + s_RenderSystem.DrawText(130.0f, 135.0f, "cleanup failed"); + } + + // アプリ削除でエラー? + if( s_IsAppDeleteSuccess ) + { + s_RenderSystem.SetColor( GREEN ); + s_RenderSystem.DrawText(130.0f, 150.0f, "cleanup failed"); + } + else + { + s_RenderSystem.SetColor( RED ); + s_RenderSystem.DrawText(130.0f, 150.0f, "cleanup failed"); + } + } + } +} + +extern "C" void nnMain(void) +{ + // os の初期化 + nn::os::Initialize(); + + // fs の初期化 + nn::fs::Initialize(); + + // appletの初期化 + nn::applet::Enable( false ); + + // hid の初期化 + nn::Result result = nn::hid::Initialize(); + NN_UTIL_PANIC_IF_FAILED(result); + + // cfg の初期化 + nn::cfg::CTR::Initialize(); + + // am の初期化 + nn::am::InitializeForSystemMenu(); + + // ヒープの確保 + common::HeapManager::GetHeap()->Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(), nn::os::ALLOCATE_OPTION_LINEAR); + + // RenderSystem の準備 + uptr heapForGx = reinterpret_cast(common::HeapManager::GetHeap()->Allocate(s_GxHeapSize)); + s_RenderSystem.Initialize(heapForGx, s_GxHeapSize); + + // ResFontの初期化 + common::InitializeResFont(); + + s_EraseThread.Start(EraseThreadFunc, s_EraseThreadStack); + + s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, BLACK, 0); + s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, BLACK, 0); + + for(;;) + { + if( s_IsFinish ) + { + // 初期化 + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); + s_RenderSystem.Clear(); + + // 上画面の色変更 + if( s_result.IsSuccess() ) + { + if( !s_IsAppExist ) + { + s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, YELLOW, 0); + } + else + { + s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, GREEN, 0); + } + } + else + { + s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, RED, 0); + } + + // バッファへ + s_RenderSystem.SwapBuffers(); + + // 初期化 + s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); + s_RenderSystem.Clear(); + + // 変更 + DrawResultText(); + common::DrawResFont(NN_GX_DISPLAY1); + + // バッファへ + s_RenderSystem.SwapBuffers(); + } + + nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(10)); + + if ( nn::applet::IsExpectedToCloseApplication() ) + { + nn::applet::PrepareToCloseApplication(); + nn::applet::CloseApplication(); + } + } +} diff --git a/branches/1stNUP_7/KENJEraser/romfiles/lc.bcfnt b/branches/1stNUP_7/KENJEraser/romfiles/lc.bcfnt new file mode 100644 index 0000000..28d1db0 Binary files /dev/null and b/branches/1stNUP_7/KENJEraser/romfiles/lc.bcfnt differ diff --git a/branches/1stNUP_7/KENJEraser/romfiles/nnfont_RectDrawerShader.shbin b/branches/1stNUP_7/KENJEraser/romfiles/nnfont_RectDrawerShader.shbin new file mode 100644 index 0000000..4290c2c Binary files /dev/null and b/branches/1stNUP_7/KENJEraser/romfiles/nnfont_RectDrawerShader.shbin differ