1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: SimpleServer.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: 47228 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn.h>
17 #include <nn/applet.h>
18 #include <nn/dlp.h>
19 #include <nn/hid.h>
20 #include "demo.h"
21 #include "SimpleServer.h"
22 #include "dlpDemo.h"
23 #include "Parent.h"
24 #include "nn/dlp/CTR/dlp_ServerWithName.h"
25
26 #include <wchar.h>
27 #include <stdlib.h>
28
29 static size_t s_DlpServerWorkBufferSize;
30 static void* s_pWorkBuffer;
31 static void* s_pAlignedWorkBuffer;
32 static bool s_IsDistributionDone = false;
33 static bool s_IsNoticeNeeded = false;
34 static nn::os::Event s_DlpServerEvent;
35 static u16 s_Selected = 0;
36 static nn::hid::PadStatus s_PadStatus;
37 static nn::os::LightEvent s_AwakeEvent; // Wake events
38 static u16 s_ClientNum;
39 static char s_Passphraase[nn::dlp::MAX_CHILD_UDS_PASSPHRASE_LENGTH];
40 static nn::cfg::UserName s_UserName;
41
mySleepQueryCallback(uptr arg)42 nn::applet::AppletQueryReply mySleepQueryCallback(uptr arg)
43 {
44 NN_UNUSED_VAR(arg);
45 DLP_DEBUG_POINT;
46 return nn::applet::CTR::IsActive()? nn::applet::CTR::REPLY_LATER: nn::applet::CTR::REPLY_ACCEPT;
47 }
48
myAwakeCallback(uptr arg)49 void myAwakeCallback(uptr arg)
50 {
51 NN_UNUSED_VAR(arg);
52 DLP_DEBUG_POINT;
53 s_AwakeEvent.Signal();
54 }
55
56 // Display client status
DisplayClientState(u16 x,u16 y,nn::dlp::ClientState state,demo::RenderSystemDrawing * pRenderSystem)57 void DisplayClientState(u16 x, u16 y, nn::dlp::ClientState state,
58 demo::RenderSystemDrawing* pRenderSystem)
59 {
60 switch (state)
61 {
62 case nn::dlp::CLIENT_STATE_WAITING_INVITE:
63 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y, "WAIT INVITE");
64 break;
65 case nn::dlp::CLIENT_STATE_WAITING_ACCEPT:
66 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y, "WAIT ACCEPT");
67 break;
68 case nn::dlp::CLIENT_STATE_JOINED_SESSION:
69 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y, "JOINED");
70 break;
71 case nn::dlp::CLIENT_STATE_DOWNLOADING:
72 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y, "DOWNLOADING");
73 break;
74 case nn::dlp::CLIENT_STATE_DOWNLOAD_COMPLETE:
75 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y, "COMPLETE");
76 break;
77 default:
78 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y, "INVALID");
79 }
80 }
81
82 // Display a list of clients
DisplayClientList(u16 selected,u16 x,u16 y,demo::RenderSystemDrawing * pRenderSystem)83 u16 DisplayClientList(u16 selected, u16 x, u16 y, demo::RenderSystemDrawing* pRenderSystem)
84 {
85 char buffer[14];
86
87 // Specify white in font color
88 pRenderSystem->SetColor(WHITE_COLOR);
89 pRenderSystem->DrawText(FONT_SIZE * (x + 3), FONT_SIZE * y, "CLIENT NAME");
90 pRenderSystem->DrawText(FONT_SIZE * (x + 15), FONT_SIZE * y, "STATE");
91 pRenderSystem->DrawText(FONT_SIZE * (x + 28), FONT_SIZE * y, "PROGRESS");
92
93 // Get the client list
94 u16 clientNum = 0;
95 u16 clientId[MAX_CLIENT];
96 nn::dlp::Server::GetConnectingClients(&clientNum, clientId, MAX_CLIENT);
97
98 y += 2;
99
100 for (int i = 0; i < clientNum; i++)
101 {
102 if (i == selected)
103 {
104 // Specify green in font color
105 pRenderSystem->SetColor(GREEN_COLOR);
106 }
107 else
108 {
109 // Specify white in font color
110 pRenderSystem->SetColor(WHITE_COLOR);
111 }
112
113 nn::dlp::NodeInfo clientInfo;
114 nn::dlp::ClientState clientState;
115 size_t totalNum;
116 size_t downloadedNum;
117
118 if ( nn::dlp::Server::GetClientInfo(&clientInfo, clientId[i]).IsFailure()
119 || nn::dlp::Server::GetClientState(&clientState, &totalNum, &downloadedNum, clientId[i]).IsFailure())
120 {
121 clientNum = 0;
122 break;
123 }
124
125 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y, "%02d", i + 1);
126 wcstombs(buffer, clientInfo.userName.userName, 11);
127 pRenderSystem->DrawText(FONT_SIZE * (x + 3), FONT_SIZE * y, "%s", buffer);
128 DisplayClientState(x + 15, y, clientState, pRenderSystem);
129 pRenderSystem->DrawText(FONT_SIZE * (x + 28), FONT_SIZE * y, "%5d/%5d",
130 downloadedNum, totalNum);
131 y++;
132 }
133
134 // Use --- to fill in blanks where there is no client
135 for (int i = clientNum; i < MAX_CLIENT; i++)
136 {
137 if (i == selected)
138 {
139 // Specify green in font color
140 pRenderSystem->SetColor(GREEN_COLOR);
141 }
142 else
143 {
144 // Specify white in font color
145 pRenderSystem->SetColor(WHITE_COLOR);
146 }
147
148 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y, "%02d", i + 1);
149 pRenderSystem->DrawText(FONT_SIZE * (x + 3), FONT_SIZE * y, "----------");
150 pRenderSystem->DrawText(FONT_SIZE * (x + 15), FONT_SIZE * y, "------------");
151 pRenderSystem->DrawText(FONT_SIZE * (x + 28), FONT_SIZE * y, "-----------");
152 y++;
153 }
154
155 return y;
156 }
157
158
159 // Display child device program information
DisplayTitleInfo(demo::RenderSystemDrawing * pRenderSystem)160 void DisplayTitleInfo(demo::RenderSystemDrawing* pRenderSystem)
161 {
162 u16 x = 1;
163 u16 y = 2;
164
165 // Specify white in font color
166 pRenderSystem->SetColor(WHITE_COLOR);
167
168 // Display child device program information
169 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "TITLE INFO");
170
171 }
172
173 /*!--------------------------------------------------------------------------*
174 Initialization state
175 *---------------------------------------------------------------------------*/
DisplayInitialize(demo::RenderSystemDrawing * pRenderSystem)176 void DisplayInitialize(demo::RenderSystemDrawing* pRenderSystem)
177 {
178 u16 x = 1;
179 u16 y = 2;
180
181 pRenderSystem->SetColor(WHITE_COLOR);
182 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "SIMPLE SERVER");
183
184 y++;
185 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++,
186 "NOW INITIALIZING...");
187 }
188
189 /*!--------------------------------------------------------------------------*
190 Start state
191 *---------------------------------------------------------------------------*/
UpdateStart(const nn::hid::PadStatus padStatus)192 void UpdateStart(const nn::hid::PadStatus padStatus)
193 {
194 if (padStatus.trigger & nn::hid::BUTTON_A)
195 {
196 // Start download session
197 // Because there is a bug that it difficult to connect with 1 ch
198 DLP_DEBUG_POINT;
199 nn::dlp::Server::OpenSessions(true, 6);
200 }
201 else if (padStatus.trigger & nn::hid::BUTTON_Y)
202 {
203 // Initialize with the user name specified with the code
204 std::memcpy( s_UserName.userName, L"SERVER", sizeof(L"SERVER"));
205 nn::dlp::Server::Finalize();
206 nn::dlp::ServerWithName::Initialize(
207 &s_IsNoticeNeeded,
208 s_DlpServerEvent.GetHandle(),
209 MAX_CLIENT,
210 CHILD_INDEX,
211 s_pAlignedWorkBuffer,
212 s_DlpServerWorkBufferSize,
213 nn::dlp::MIN_NETWORK_BLOCK_BUFFER_SIZE * 2,
214 nn::dlp::MIN_NETWORK_BLOCK_BUFFER_NUM,
215 &s_UserName );
216 // Start download session
217 // Because there is a bug that it difficult to connect with 1 ch
218 DLP_DEBUG_POINT;
219 nn::dlp::Server::OpenSessions(true, 6);
220 }
221
222 }
223
DisplayStart(demo::RenderSystemDrawing * pRenderSystem)224 void DisplayStart(demo::RenderSystemDrawing* pRenderSystem)
225 {
226 u16 x = 1;
227 u16 y = 2;
228
229 pRenderSystem->SetColor(WHITE_COLOR);
230 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "SIMPLE SERVER");
231
232 y++;
233 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "PRESS A TO START");
234 y++;
235 if (s_IsNoticeNeeded)
236 {
237 y++;
238 pRenderSystem->SetColor(RED_COLOR);
239 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "[WARNING]");
240 y++;
241 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "SimpleServer may disconnect clients without");
242 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "a notice. Please update clients via network.");
243 }
244 }
245
246 /*!--------------------------------------------------------------------------*
247 Accept client status
248 *---------------------------------------------------------------------------*/
UpdateAcceptClient(u16 * pSelected,const nn::hid::PadStatus padStatus)249 void UpdateAcceptClient(u16* pSelected, const nn::hid::PadStatus padStatus)
250 {
251 // Get the client list
252 u16 clientNum = 0;
253 u16 clientId[MAX_CLIENT];
254 nn::dlp::Server::GetConnectingClients(&clientNum, clientId, MAX_CLIENT);
255
256 // Checks whether waiting for Accept
257 bool isWaitingAccept = false;
258 if ((*pSelected) < clientNum)
259 {
260 DLP_DEBUG_POINT;
261 // Gets client status
262 nn::dlp::ClientState clientState;
263 nn::dlp::Server::GetClientState(&clientState, clientId[*pSelected]);
264 if (clientState == nn::dlp::CLIENT_STATE_WAITING_ACCEPT)
265 {
266 DLP_DEBUG_POINT;
267 isWaitingAccept = true;
268 }
269 }
270
271 if (padStatus.trigger & nn::hid::BUTTON_A)
272 {
273 DLP_DEBUG_POINT;
274 // ACCEPT
275 if (isWaitingAccept)
276 {
277 DLP_DEBUG_POINT;
278 // Accept
279 nn::dlp::Server::AcceptClient(clientId[*pSelected]);
280 }
281 }
282 else if (padStatus.trigger & nn::hid::BUTTON_B)
283 {
284 DLP_DEBUG_POINT;
285 // REJECT
286 if (isWaitingAccept)
287 {
288 DLP_DEBUG_POINT;
289 // Disconnect
290 nn::dlp::Server::DisconnectClient(clientId[*pSelected]);
291 }
292 }
293 else if (padStatus.trigger & nn::hid::BUTTON_X)
294 {
295 DLP_DEBUG_POINT;
296 // Start distribution
297 nn::dlp::Server::StartDistribute();
298 nn::dlp::Server::GetConnectingClients(&s_ClientNum, clientId, MAX_CLIENT);
299 }
300 else if (padStatus.trigger & nn::hid::BUTTON_UP)
301 {
302 DLP_DEBUG_POINT;
303 // Move the selection
304 (*pSelected) = ((*pSelected) - 1 + MAX_CLIENT) % MAX_CLIENT;
305 }
306 else if (padStatus.trigger & nn::hid::BUTTON_DOWN)
307 {
308 DLP_DEBUG_POINT;
309 // Move the selection
310 (*pSelected) = ((*pSelected) + 1) % MAX_CLIENT;
311 }
312 }
313
DisplayAcceptClient(u16 selected,demo::RenderSystemDrawing * pRenderSystem)314 void DisplayAcceptClient(u16 selected, demo::RenderSystemDrawing* pRenderSystem)
315 {
316 u16 x = 1;
317 u16 y = 2;
318
319 y = DisplayClientList(selected, x, y, pRenderSystem);
320
321 y++;
322 pRenderSystem->SetColor(WHITE_COLOR);
323 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++,
324 "PRESS A TO ACCEPT CLIENT");
325 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++,
326 "PRESS B TO REJECT CLIENT");
327 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++,
328 "(WAIT ACCEPT STATE CLIENT ONLY)");
329 y++;
330 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++,
331 "PRESS X TO START DISTRIBUTE");
332 }
333
334 /*!--------------------------------------------------------------------------*
335 Distribution status
336 *---------------------------------------------------------------------------*/
UpdateDistribute(nn::hid::PadStatus padStatus)337 void UpdateDistribute(nn::hid::PadStatus padStatus)
338 {
339 if (padStatus.trigger & nn::hid::BUTTON_B)
340 {
341 DLP_DEBUG_POINT;
342 nn::dlp::Server::CloseSessions();
343 }
344 }
345
DisplayDistribute(demo::RenderSystemDrawing * pRenderSystem)346 void DisplayDistribute(demo::RenderSystemDrawing* pRenderSystem)
347 {
348 u16 x = 1;
349 u16 y = 2;
350
351 y = DisplayClientList(MAX_CLIENT + 1, x, y, pRenderSystem);
352
353 pRenderSystem->SetColor(WHITE_COLOR);
354 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "PRESS B TO CANCEL");
355 }
356
357 /*!--------------------------------------------------------------------------*
358 Distribution completion status
359 *---------------------------------------------------------------------------*/
UpdateComplete()360 void UpdateComplete()
361 {
362 DLP_DEBUG_POINT;
363
364 u32 random;
365
366 ::std::srand(static_cast<s32>(nn::os::Tick::GetSystemCurrent() >> 1));
367 random = static_cast<u32>(::std::rand());
368
369 nn::nstd::TSNPrintf(s_Passphraase, sizeof(s_Passphraase), "%08x", random);
370 DLP_DEBUG_PRINT("Passphrase : %s \n", s_Passphraase);
371
372 nn::dlp::Server::RebootAllClients(s_Passphraase);
373 }
374
375 /*!--------------------------------------------------------------------------*
376 Waiting for reboot status
377 *---------------------------------------------------------------------------*/
UpdateReboot()378 void UpdateReboot()
379 {
380 // Get the client list
381 u16 clientNum = 0;
382 u16 clientId[MAX_CLIENT];
383 if (nn::dlp::Server::GetConnectingClients(&clientNum, clientId, MAX_CLIENT).IsSuccess())
384 {
385 DLP_DEBUG_POINT;
386 if (clientNum == 0)
387 {
388 DLP_DEBUG_POINT;
389 s_IsDistributionDone = true;
390 }
391 }
392 }
393
DisplayReboot(demo::RenderSystemDrawing * pRenderSystem)394 void DisplayReboot(demo::RenderSystemDrawing* pRenderSystem)
395 {
396 u16 x = 1;
397 u16 y = 2;
398
399 y = DisplayClientList(MAX_CLIENT + 1, x, y, pRenderSystem);
400 }
401
402
403 /*!--------------------------------------------------------------------------*
404 Error state
405 *---------------------------------------------------------------------------*/
UpdateError(nn::hid::PadStatus padStatus)406 void UpdateError(nn::hid::PadStatus padStatus)
407 {
408 nn::dlp::Server::Finalize();
409 if (padStatus.trigger & nn::hid::BUTTON_A)
410 {
411 DLP_DEBUG_POINT;
412 s_Selected = 0;
413 nn::dlp::Server::Initialize(
414 &s_IsNoticeNeeded,
415 s_DlpServerEvent.GetHandle(),
416 MAX_CLIENT,
417 CHILD_INDEX,
418 s_pAlignedWorkBuffer,
419 s_DlpServerWorkBufferSize);
420 }
421 }
422
DisplayError(demo::RenderSystemDrawing * pRenderSystem)423 void DisplayError(demo::RenderSystemDrawing* pRenderSystem)
424 {
425 u16 x = 1;
426 u16 y = 2;
427
428 pRenderSystem->SetColor(WHITE_COLOR);
429 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "+++ ERROR +++");
430
431 y++;
432 pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++,
433 "PRESS A TO RESTART");
434 }
435
436 /*!--------------------------------------------------------------------------*
437 Black background
438 *---------------------------------------------------------------------------*/
DisplayBlackBack(demo::RenderSystemDrawing & renderSystem)439 void DisplayBlackBack(demo::RenderSystemDrawing& renderSystem)
440 {
441 renderSystem.SetRenderTarget(NN_GX_DISPLAY0);
442 renderSystem.Clear();
443 renderSystem.SwapBuffers();
444 renderSystem.SetRenderTarget(NN_GX_DISPLAY1);
445 renderSystem.Clear();
446 renderSystem.SwapBuffers();
447 }
448
449
450 /*!--------------------------------------------------------------------------*
451 Update/display state functions
452 *---------------------------------------------------------------------------*/
Update(nn::dlp::ServerState serverState,u16 * pSelected,const nn::hid::PadStatus padStatus)453 void Update(nn::dlp::ServerState serverState, u16* pSelected,
454 const nn::hid::PadStatus padStatus)
455 {
456 switch (serverState)
457 {
458 case nn::dlp::SERVER_STATE_INITIALIZED:
459 UpdateStart(padStatus);
460 break;
461 case nn::dlp::SERVER_STATE_OPENED_SESSIONS:
462 UpdateAcceptClient(pSelected, padStatus);
463 break;
464 case nn::dlp::SERVER_STATE_DISTRIBUTING:
465 UpdateDistribute(padStatus);
466 break;
467 case nn::dlp::SERVER_STATE_COMPLETE_DISTRIBUTION:
468 UpdateComplete();
469 break;
470 case nn::dlp::SERVER_STATE_REBOOTING_CLIENTS:
471 UpdateReboot();
472 break;
473 case nn::dlp::SERVER_STATE_ERROR:
474 case nn::dlp::SERVER_STATE_INVALID:
475 UpdateError(padStatus);
476 break;
477 }
478 }
Display(nn::dlp::ServerState serverState,u16 selected,demo::RenderSystemDrawing * pRenderSystem)479 void Display(nn::dlp::ServerState serverState, u16 selected,
480 demo::RenderSystemDrawing* pRenderSystem)
481 {
482 // Render on the upper screen
483 pRenderSystem->SetRenderTarget(NN_GX_DISPLAY0);
484 pRenderSystem->Clear();
485
486 switch (serverState)
487 {
488 case nn::dlp::SERVER_STATE_INITIALIZED:
489 DisplayStart(pRenderSystem);
490 break;
491 case nn::dlp::SERVER_STATE_OPENED_SESSIONS:
492 DisplayAcceptClient(selected, pRenderSystem);
493 break;
494 case nn::dlp::SERVER_STATE_DISTRIBUTING:
495 case nn::dlp::SERVER_STATE_COMPLETE_DISTRIBUTION:
496 DisplayDistribute(pRenderSystem);
497 break;
498 case nn::dlp::SERVER_STATE_REBOOTING_CLIENTS:
499 DisplayReboot(pRenderSystem);
500 break;
501 case nn::dlp::SERVER_STATE_ERROR:
502 case nn::dlp::SERVER_STATE_INVALID:
503 DisplayError(pRenderSystem);
504 break;
505 }
506
507 pRenderSystem->SwapBuffers();
508
509 // Render on the lower screen
510 pRenderSystem->SetRenderTarget(NN_GX_DISPLAY1);
511 pRenderSystem->Clear();
512
513 // DisplayTitleInfo(pRenderSystem);
514
515 pRenderSystem->SwapBuffers();
516 }
517
518 /*!--------------------------------------------------------------------------*
519 Main function
520 *---------------------------------------------------------------------------*/
521
nnMain(void)522 void nnMain(void)
523 {
524 nn::Result result;
525
526 //Set sleep callback, sleep recovery callback
527 nn::applet::SetSleepQueryCallback(mySleepQueryCallback, 0);
528 nn::applet::SetAwakeCallback(myAwakeCallback, 0);
529 nn::applet::Enable();
530 s_AwakeEvent.Initialize(false); DLP_DEBUG_POINT;
531
532 // Initialize hid
533 result = nn::hid::Initialize();
534 NN_UTIL_PANIC_IF_FAILED(result);
535
536 // Prepare pad
537 nn::hid::PadReader padReader;
538
539 // Allocate heap
540 nn::fnd::ExpHeap appHeap;
541 appHeap.Initialize(nn::os::GetDeviceMemoryAddress(), 16 * 1024 * 1024 ); // nn::os::GetDeviceMemorySize()
542
543 // Prepare RenderSystem
544 uptr heapForGx = reinterpret_cast<uptr> (appHeap.Allocate(0x800000));
545 demo::RenderSystemDrawing renderSystem;
546 renderSystem.Initialize(heapForGx, 0x800000);
547 renderSystem.SetClearColor(NN_GX_DISPLAY_BOTH, 0.f, 0.f, 0.f, 0.f);
548 renderSystem.SetFontSize(FONT_SIZE);
549 renderSystem.SetLineWidth(LINE_WIDTH);
550
551 // Initialize event used by DLP server
552 s_DlpServerEvent.Initialize(false);
553
554 // Get work buffer size necessary to initialize DLP server
555 s_DlpServerWorkBufferSize = nn::dlp::Server::GetBufferSize(MAX_CLIENT);
556 DLP_DEBUG_PRINT("dlpServerWorkBufferSize %d\n", s_DlpServerWorkBufferSize);
557
558 // Get DLP server work buffer
559 s_pWorkBuffer = new u8[s_DlpServerWorkBufferSize + 4096];
560 DLP_DEBUG_PRINT("dlpServerWorkBuffer allocated address 0x%08x\n", s_pWorkBuffer);
561 s_pAlignedWorkBuffer
562 = reinterpret_cast<void*> (DLP_ROUNDUP(reinterpret_cast<u32>(s_pWorkBuffer), 4096UL));
563 DLP_DEBUG_PRINT("dlpServerWorkBuffer aligned address 0x%08x\n", s_pAlignedWorkBuffer);
564
565 renderSystem.SetRenderTarget(NN_GX_DISPLAY0);
566 renderSystem.Clear();
567 DisplayInitialize(&renderSystem);
568 renderSystem.SwapBuffers();
569
570 // Initialize DLP server
571 nn::dlp::Server::Initialize(
572 &s_IsNoticeNeeded,
573 s_DlpServerEvent.GetHandle(),
574 MAX_CLIENT,
575 CHILD_INDEX,
576 s_pAlignedWorkBuffer,
577 s_DlpServerWorkBufferSize);
578 DLP_DEBUG_POINT;
579
580 nn::dlp::ServerState serverState;
581
582 while (!s_IsDistributionDone)
583 {
584 // Get pad input
585 padReader.ReadLatest(&s_PadStatus);
586 nn::dlp::Server::GetState(&serverState);
587
588 // Update
589 Update(serverState, &s_Selected, s_PadStatus);
590
591 // Render
592 Display(serverState, s_Selected, &renderSystem);
593
594
595 //Sleep support
596 if ( nn::applet::IsExpectedToReplySleepQuery() )
597 {
598 DLP_DEBUG_POINT;
599 nn::dlp::Server::Finalize(); // Finalize before sleep.
600 nn::applet::ReplySleepQuery(nn::applet::REPLY_ACCEPT); DLP_DEBUG_POINT;
601 s_AwakeEvent.Wait(); DLP_DEBUG_POINT;
602
603 // Processing after restart
604 nn::gx::StartLcdDisplay(); DLP_DEBUG_POINT;
605 }
606
607 //HOME Button support
608 if (nn::applet::IsExpectedToProcessHomeButton())
609 {
610 DLP_DEBUG_POINT;
611 nn::dlp::Server::Finalize();
612 nn::applet::ProcessHomeButton();
613 nn::applet::WaitForStarting(); DLP_DEBUG_POINT;
614
615 // Recover the GPU register settings
616 nngxUpdateState(NN_GX_STATE_ALL);
617 nngxValidateState(NN_GX_STATE_ALL,GL_TRUE);
618
619 if (nn::applet::IsExpectedToCloseApplication())
620 {
621 DLP_DEBUG_POINT;
622 break;
623 }
624 }
625
626 //POWER Button support
627 if ( nn::applet::IsExpectedToProcessPowerButton() )
628 {
629 DLP_DEBUG_POINT;
630 nn::dlp::Server::Finalize();
631 nn::applet::ProcessPowerButton();
632 nn::applet::WaitForStarting(); DLP_DEBUG_POINT;
633
634 // Recover the GPU register settings
635 nngxUpdateState(NN_GX_STATE_ALL);
636 nngxValidateState(NN_GX_STATE_ALL,GL_TRUE);
637
638 if ( nn::applet::IsExpectedToCloseApplication() )
639 {
640 DLP_DEBUG_POINT;
641 break;
642 }
643 }
644
645 // Support for termination request
646 if (nn::applet::IsExpectedToCloseApplication())
647 {
648 DLP_DEBUG_POINT;
649 DisplayBlackBack(renderSystem);
650 break;
651 }
652 }
653
654 nn::dlp::Server::Finalize(); DLP_DEBUG_POINT;
655 s_DlpServerEvent.Finalize(); DLP_DEBUG_POINT;
656 delete[] s_pWorkBuffer; DLP_DEBUG_POINT;
657 renderSystem.Finalize();
658 appHeap.Free(reinterpret_cast<void*>(heapForGx));
659 appHeap.Finalize();
660 nn::hid::Finalize();
661 nn::applet::DisableSleep();
662 nn::applet::SetSleepQueryCallback(NULL, 0);
663 nn::applet::SetAwakeCallback(NULL, 0);
664 s_AwakeEvent.Finalize();
665
666 // Communicate with child device as the parent device
667 if (s_IsDistributionDone)
668 {
669 DLP_DEBUG_POINT;
670 // Because this is a provisional implementation, the SLEEP, HOME, and POWER Buttons do not work after this
671 DoParent(s_ClientNum, s_Passphraase);
672 }
673
674 nn::applet::CloseApplication();
675 // Execution does not come here
676 DLP_DEBUG_PRINT("EXIT.\n");
677 }
678