1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     FsSampleSecureSaveFrame.cpp
4 
5   Copyright (C)2009-2012 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 47440 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn.h>
17 #include "demo.h"
18 
19 #include "../Common/FsSampleCommon.h"
20 #include "FsSampleSecureSave.h"
21 
22 using namespace nn;
23 
24 namespace sample { namespace fs { namespace securesave {
25 
26 namespace
27 {
28     enum ENUM_TASK
29     {
30         TASK_NONE,
31         TASK_SAVE,
32         TASK_LOAD,
33         TASK_RENEW,
34 
35         ENUM_TASK_NUM
36     } s_Task;
37 
38     enum ENUM_STATE
39     {
40         STATE_NONE,
41         STATE_DATA_FORMATTED,
42         STATE_SAVE,
43         STATE_SAVE_DONE,
44         STATE_LOAD,
45         STATE_LOAD_SUCCEEDED,
46         STATE_LOAD_FAILED,
47         STATE_RENEW_SUCCEEDED,
48 
49         ENUM_STATE_NUM
50     } s_State;
51 
52     enum ENUM_OPERATION
53     {
54         OPERATION_FILEINDEX,
55         OPERATION_DATA,
56 
57         ENUM_OPERATION_NUM
58     } s_Operation;
59 
60     struct DisplayParameter
61     {
62         bit64 versionValueOnMemory;
63     } s_DisplayParam;
64 
65     SaveData s_SaveData;
66     u32 s_FileIndex;
67 
68     bool s_IsWorkerThreadAlive;
69     nn::os::Event s_WorkerEvent;
70     nn::os::Thread s_WorkerThread;
71 } // namespace
72 
ProceedDisplay(demo::RenderSystemDrawing & renderSystem)73 void ProceedDisplay(demo::RenderSystemDrawing &renderSystem)
74 {
75     renderSystem.SetRenderTarget(NN_GX_DISPLAY0);
76     renderSystem.Clear();
77     renderSystem.SetColor(1.0f, 1.0f, 1.0f);
78 
79     switch (s_State)
80     {
81     case STATE_DATA_FORMATTED:
82         renderSystem.DrawText(0, LINE_HEIGHT *  0, "SaveData was formatted");
83         break;
84     case STATE_SAVE:
85         renderSystem.DrawText(0, LINE_HEIGHT *  0, "Saving file index %d...", s_FileIndex);
86         break;
87     case STATE_SAVE_DONE:
88         renderSystem.DrawText(0, LINE_HEIGHT *  0, "Saving Succeeded");
89         break;
90     case STATE_LOAD:
91         renderSystem.DrawText(0, LINE_HEIGHT *  0, "Loading file index %d...", s_FileIndex);
92         break;
93     case STATE_LOAD_SUCCEEDED:
94         renderSystem.DrawText(0, LINE_HEIGHT *  0, "Loading Succeeded");
95         break;
96     case STATE_LOAD_FAILED:
97         renderSystem.DrawText(0, LINE_HEIGHT *  0, "Loading Failed");
98         break;
99     case STATE_RENEW_SUCCEEDED:
100         renderSystem.DrawText(0, LINE_HEIGHT *  0, "Renewal Succeeded");
101         break;
102     default:
103         break;
104     }
105 
106     renderSystem.DrawText(0, LINE_HEIGHT *  3 * (1 + s_Operation), ">");
107     renderSystem.DrawText(FONT_SIZE * 1, LINE_HEIGHT *  3, "File index          %c %d %c"
108             , (s_Operation == 0) ? '<' : ' '
109             , s_FileIndex
110             , (s_Operation == 0) ? '>' : ' '
111             );
112     renderSystem.DrawText(FONT_SIZE * 1, LINE_HEIGHT *  6, "Data on memory      %c %c %c"
113             , (s_Operation == 1) ? '<' : ' '
114             , 'A' + ((s_SaveData.userData.data1 % 26) + 26) % 26
115             , (s_Operation == 1) ? '>' : ' '
116             );
117     renderSystem.DrawText(FONT_SIZE * 1, LINE_HEIGHT *  9, "VersionValue on memory %llu", s_DisplayParam.versionValueOnMemory);
118 
119     renderSystem.SwapBuffers();
120 
121 
122     renderSystem.SetRenderTarget(NN_GX_DISPLAY1);
123     renderSystem.Clear();
124     renderSystem.SetColor(1.0f, 1.0f, 1.0f);
125 
126     renderSystem.DrawText(8, LINE_HEIGHT *  1, "PlusPad: Change Data");
127     renderSystem.DrawText(8, LINE_HEIGHT *  4, "A: Save");
128     renderSystem.DrawText(8, LINE_HEIGHT *  5, "Y: Load & Check Version");
129     renderSystem.DrawText(8, LINE_HEIGHT *  6, "X: Renew");
130 
131     renderSystem.SwapBuffers();
132 }
133 
WorkerThread()134 void WorkerThread()
135 {
136     while (s_IsWorkerThreadAlive)
137     {
138         s_WorkerEvent.Wait();
139         switch (s_Task)
140         {
141         case TASK_SAVE:
142             s_State = STATE_SAVE;
143             Save(s_SaveData, s_FileIndex);
144             s_State = STATE_SAVE_DONE;
145             break;
146         case TASK_LOAD:
147             s_State = STATE_LOAD;
148             s_State = (Load(s_SaveData, s_FileIndex)) ? STATE_LOAD_SUCCEEDED : STATE_LOAD_FAILED;
149             break;
150         case TASK_RENEW:
151             s_State = STATE_RENEW_SUCCEEDED;
152             s_SaveData.Reset();
153             break;
154         default:
155             s_State = STATE_NONE;
156             break;
157         }
158 
159         s_DisplayParam.versionValueOnMemory = s_SaveData.version;
160         s_Task = TASK_NONE;
161     }
162 }
163 
ProceedHid()164 void ProceedHid()
165 {
166     static nn::hid::PadReader padReader;
167     static nn::hid::PadStatus padStatus;
168 
169     if (!padReader.ReadLatest(&padStatus))
170     {
171         nn::dbg::detail::TPrintf("Getting pad status failed.\n");
172     }
173 
174     if ((padStatus.trigger & nn::hid::BUTTON_A) && s_Task == TASK_NONE)
175     {
176         s_Task = TASK_SAVE;
177         s_WorkerEvent.Signal();
178     }
179     else if ((padStatus.trigger & nn::hid::BUTTON_Y) && s_Task == TASK_NONE)
180     {
181         s_Task = TASK_LOAD;
182         s_WorkerEvent.Signal();
183     }
184     else if ((padStatus.trigger & nn::hid::BUTTON_X) && s_Task == TASK_NONE)
185     {
186         s_Task = TASK_RENEW;
187         s_WorkerEvent.Signal();
188     }
189     else if (padStatus.trigger & nn::hid::BUTTON_UP)
190     {
191         s_Operation = static_cast<ENUM_OPERATION>((s_Operation - 1 + ENUM_OPERATION_NUM) % ENUM_OPERATION_NUM);
192     }
193     else if (padStatus.trigger & nn::hid::BUTTON_DOWN)
194     {
195         s_Operation = static_cast<ENUM_OPERATION>((s_Operation + 1) % ENUM_OPERATION_NUM);
196     }
197     else if (padStatus.trigger & nn::hid::BUTTON_LEFT)
198     {
199         switch (s_Operation)
200         {
201         case OPERATION_FILEINDEX:
202             s_FileIndex = (s_FileIndex - 1 + DATA_FILE_NUM) % DATA_FILE_NUM;
203             break;
204         case OPERATION_DATA:
205             s_SaveData.userData.data1--;
206             break;
207         }
208     }
209     else if (padStatus.trigger & nn::hid::BUTTON_RIGHT)
210     {
211         switch (s_Operation)
212         {
213         case OPERATION_FILEINDEX:
214             s_FileIndex = (s_FileIndex + 1) % DATA_FILE_NUM;
215             break;
216         case OPERATION_DATA:
217             s_SaveData.userData.data1++;
218             break;
219         }
220     }
221 }
222 
223 } // namespace securesave
224 
225 using namespace securesave;
226 
MainLoop(demo::RenderSystemDrawing & renderSystem)227 void MainLoop(demo::RenderSystemDrawing &renderSystem)
228 {
229     ProceedHid();
230     ProceedDisplay(renderSystem);
231 
232     nngxWaitVSync(NN_GX_DISPLAY_BOTH);
233 }
234 
Initialize(demo::RenderSystemDrawing &)235 void Initialize(demo::RenderSystemDrawing&)
236 {
237     nn::fs::Initialize();
238     if (InitializeSaveData())
239     {
240         s_State = STATE_DATA_FORMATTED;
241     }
242     else
243     {
244         s_State = STATE_NONE;
245     }
246 
247     s_SaveData.Reset();
248     s_FileIndex = 0;
249     s_DisplayParam.versionValueOnMemory = s_SaveData.version;
250 
251     s_WorkerEvent.Initialize(false);
252     s_IsWorkerThreadAlive = true;
253     NN_ERR_THROW_FATAL_ALL(s_WorkerThread.TryStartUsingAutoStack(&WorkerThread, 4 * 1024, nn::os::Thread::GetCurrentPriority() + 1));
254 }
255 
Finalize()256 void Finalize()
257 {
258     s_IsWorkerThreadAlive = false;
259     s_WorkerEvent.Signal();
260     s_WorkerThread.Join();
261 }
262 
263 }} // namespace sample::fs
264