/*---------------------------------------------------------------------------* Project: Horizon File: FsSampleSecureSaveFrame.cpp Copyright (C)2009-2012 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: 47440 $ *---------------------------------------------------------------------------*/ #include #include "demo.h" #include "../Common/FsSampleCommon.h" #include "FsSampleSecureSave.h" using namespace nn; namespace sample { namespace fs { namespace securesave { namespace { enum ENUM_TASK { TASK_NONE, TASK_SAVE, TASK_LOAD, TASK_RENEW, ENUM_TASK_NUM } s_Task; enum ENUM_STATE { STATE_NONE, STATE_DATA_FORMATTED, STATE_SAVE, STATE_SAVE_DONE, STATE_LOAD, STATE_LOAD_SUCCEEDED, STATE_LOAD_FAILED, STATE_RENEW_SUCCEEDED, ENUM_STATE_NUM } s_State; enum ENUM_OPERATION { OPERATION_FILEINDEX, OPERATION_DATA, ENUM_OPERATION_NUM } s_Operation; struct DisplayParameter { bit64 versionValueOnMemory; } s_DisplayParam; SaveData s_SaveData; u32 s_FileIndex; bool s_IsWorkerThreadAlive; nn::os::Event s_WorkerEvent; nn::os::Thread s_WorkerThread; } // namespace void ProceedDisplay(demo::RenderSystemDrawing &renderSystem) { renderSystem.SetRenderTarget(NN_GX_DISPLAY0); renderSystem.Clear(); renderSystem.SetColor(1.0f, 1.0f, 1.0f); switch (s_State) { case STATE_DATA_FORMATTED: renderSystem.DrawText(0, LINE_HEIGHT * 0, "SaveData was formatted"); break; case STATE_SAVE: renderSystem.DrawText(0, LINE_HEIGHT * 0, "Saving file index %d...", s_FileIndex); break; case STATE_SAVE_DONE: renderSystem.DrawText(0, LINE_HEIGHT * 0, "Saving Succeeded"); break; case STATE_LOAD: renderSystem.DrawText(0, LINE_HEIGHT * 0, "Loading file index %d...", s_FileIndex); break; case STATE_LOAD_SUCCEEDED: renderSystem.DrawText(0, LINE_HEIGHT * 0, "Loading Succeeded"); break; case STATE_LOAD_FAILED: renderSystem.DrawText(0, LINE_HEIGHT * 0, "Loading Failed"); break; case STATE_RENEW_SUCCEEDED: renderSystem.DrawText(0, LINE_HEIGHT * 0, "Renewal Succeeded"); break; default: break; } renderSystem.DrawText(0, LINE_HEIGHT * 3 * (1 + s_Operation), ">"); renderSystem.DrawText(FONT_SIZE * 1, LINE_HEIGHT * 3, "File index %c %d %c" , (s_Operation == 0) ? '<' : ' ' , s_FileIndex , (s_Operation == 0) ? '>' : ' ' ); renderSystem.DrawText(FONT_SIZE * 1, LINE_HEIGHT * 6, "Data on memory %c %c %c" , (s_Operation == 1) ? '<' : ' ' , 'A' + ((s_SaveData.userData.data1 % 26) + 26) % 26 , (s_Operation == 1) ? '>' : ' ' ); renderSystem.DrawText(FONT_SIZE * 1, LINE_HEIGHT * 9, "VersionValue on memory %llu", s_DisplayParam.versionValueOnMemory); renderSystem.SwapBuffers(); renderSystem.SetRenderTarget(NN_GX_DISPLAY1); renderSystem.Clear(); renderSystem.SetColor(1.0f, 1.0f, 1.0f); renderSystem.DrawText(8, LINE_HEIGHT * 1, "PlusPad: Change Data"); renderSystem.DrawText(8, LINE_HEIGHT * 4, "A: Save"); renderSystem.DrawText(8, LINE_HEIGHT * 5, "Y: Load & Check Version"); renderSystem.DrawText(8, LINE_HEIGHT * 6, "X: Renew"); renderSystem.SwapBuffers(); } void WorkerThread() { while (s_IsWorkerThreadAlive) { s_WorkerEvent.Wait(); switch (s_Task) { case TASK_SAVE: s_State = STATE_SAVE; Save(s_SaveData, s_FileIndex); s_State = STATE_SAVE_DONE; break; case TASK_LOAD: s_State = STATE_LOAD; s_State = (Load(s_SaveData, s_FileIndex)) ? STATE_LOAD_SUCCEEDED : STATE_LOAD_FAILED; break; case TASK_RENEW: s_State = STATE_RENEW_SUCCEEDED; s_SaveData.Reset(); break; default: s_State = STATE_NONE; break; } s_DisplayParam.versionValueOnMemory = s_SaveData.version; s_Task = TASK_NONE; } } void ProceedHid() { static nn::hid::PadReader padReader; static nn::hid::PadStatus padStatus; if (!padReader.ReadLatest(&padStatus)) { nn::dbg::detail::TPrintf("Getting pad status failed.\n"); } if ((padStatus.trigger & nn::hid::BUTTON_A) && s_Task == TASK_NONE) { s_Task = TASK_SAVE; s_WorkerEvent.Signal(); } else if ((padStatus.trigger & nn::hid::BUTTON_Y) && s_Task == TASK_NONE) { s_Task = TASK_LOAD; s_WorkerEvent.Signal(); } else if ((padStatus.trigger & nn::hid::BUTTON_X) && s_Task == TASK_NONE) { s_Task = TASK_RENEW; s_WorkerEvent.Signal(); } else if (padStatus.trigger & nn::hid::BUTTON_UP) { s_Operation = static_cast((s_Operation - 1 + ENUM_OPERATION_NUM) % ENUM_OPERATION_NUM); } else if (padStatus.trigger & nn::hid::BUTTON_DOWN) { s_Operation = static_cast((s_Operation + 1) % ENUM_OPERATION_NUM); } else if (padStatus.trigger & nn::hid::BUTTON_LEFT) { switch (s_Operation) { case OPERATION_FILEINDEX: s_FileIndex = (s_FileIndex - 1 + DATA_FILE_NUM) % DATA_FILE_NUM; break; case OPERATION_DATA: s_SaveData.userData.data1--; break; } } else if (padStatus.trigger & nn::hid::BUTTON_RIGHT) { switch (s_Operation) { case OPERATION_FILEINDEX: s_FileIndex = (s_FileIndex + 1) % DATA_FILE_NUM; break; case OPERATION_DATA: s_SaveData.userData.data1++; break; } } } } // namespace securesave using namespace securesave; void MainLoop(demo::RenderSystemDrawing &renderSystem) { ProceedHid(); ProceedDisplay(renderSystem); nngxWaitVSync(NN_GX_DISPLAY_BOTH); } void Initialize(demo::RenderSystemDrawing&) { nn::fs::Initialize(); if (InitializeSaveData()) { s_State = STATE_DATA_FORMATTED; } else { s_State = STATE_NONE; } s_SaveData.Reset(); s_FileIndex = 0; s_DisplayParam.versionValueOnMemory = s_SaveData.version; s_WorkerEvent.Initialize(false); s_IsWorkerThreadAlive = true; NN_ERR_THROW_FATAL_ALL(s_WorkerThread.TryStartUsingAutoStack(&WorkerThread, 4 * 1024, nn::os::Thread::GetCurrentPriority() + 1)); } void Finalize() { s_IsWorkerThreadAlive = false; s_WorkerEvent.Signal(); s_WorkerThread.Join(); } }} // namespace sample::fs