1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     FakeClient.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 <nn/nstd/nstd_String.h>
21 #include "demo.h"
22 #include "dlpDemo.h"
23 #include <nn/dlp/CTR/dlp_FakeClient.h>
24 #include "../Child_0/Child.h"
25 #include "nn/dlp/CTR/dlp_FakeClientWithName.h"
26 
27 #include <string.h>
28 #include <wchar.h>
29 #include <stdlib.h>
30 
31 namespace
32 {
33     static bool                 s_IsSessionDone = false;
34     static nn::os::Event        s_DlpClientEvent;
35     static void*                s_pWorkBuffer;
36     static void*                s_pAlignedWorkBuffer;
37     size_t                      s_DlpClientWorkBufferSize;
38     static int                  s_TitleNum = 0;
39     static int                  s_Selected = 0;
40     static nn::dlp::ServerInfo  s_ServerInfo;
41     static GLuint               s_IconTextureId = 0;
42     static u8                   s_ServerMac[6];
43     static char                 s_Passphrase[nn::dlp::MAX_CHILD_UDS_PASSPHRASE_LENGTH];
44     static nn::cfg::UserName    s_UserName;
45 
46     static nn::os::LightEvent s_AwakeEvent;         // Wake events
47 
mySleepQueryCallback(uptr arg)48     nn::applet::AppletQueryReply mySleepQueryCallback( uptr arg )
49     {
50         NN_UNUSED_VAR(arg);
51         DLP_DEBUG_POINT;
52         return nn::applet::CTR::REPLY_LATER;
53     }
54 
myAwakeCallback(uptr arg)55     void myAwakeCallback( uptr arg )
56     {
57         NN_UNUSED_VAR(arg);
58         DLP_DEBUG_POINT;
59         s_AwakeEvent.Signal();
60     }
61 }
62 
63 /*!--------------------------------------------------------------------------*
64   Display Cube
65  *---------------------------------------------------------------------------*/
DisplayCube(demo::RenderSystemDrawing * pRenderSystem,u16 x,u16 y)66 void DisplayCube(demo::RenderSystemDrawing* pRenderSystem, u16 x, u16 y)
67 {
68     struct Position
69     {
70         u16 x;
71         u16 y;
72     };
73     const Position cubePos[8] = { {0, 0}, {5, 0}, {10, 0}, {10, 5}, {10, 10}, {5, 10}, {0, 10}, {0, 5} };
74 
75     static u16 startPos = 0;
76     static u16 count = 0;
77 
78     if(count == 4)
79     {
80         startPos = (startPos + 1) % 8;
81         count = 0;
82     }
83 
84     for(int i = 0; i < 5; i++)
85     {
86         u16 curPos = (startPos + i) % 8;
87         pRenderSystem->FillRectangle(x + cubePos[curPos].x, y + cubePos[curPos].y, 4, 4);
88     }
89     pRenderSystem->FillRectangle(x + 5, y + 5, 4, 4);
90 
91     count++;
92 }
93 
94 
95 /*!--------------------------------------------------------------------------*
96   Display child device program list
97  *---------------------------------------------------------------------------*/
DisplayTitleList(const nn::dlp::TitleInfo titleList[],int titleNum,int selected,demo::RenderSystemDrawing * pRenderSystem)98 void DisplayTitleList(const nn::dlp::TitleInfo titleList[], int titleNum, int selected, demo::RenderSystemDrawing* pRenderSystem)
99 {
100     u16 x = 1;
101     u16 y = 2;
102     char buffer[29];
103 
104     // Specify white in font color
105     pRenderSystem->SetColor(WHITE_COLOR);
106     pRenderSystem->DrawText(FONT_SIZE * (x +  3), FONT_SIZE * y, "TITLE NAME");
107     pRenderSystem->DrawText(FONT_SIZE * (x + 33), FONT_SIZE * y, "SERVER NAME");
108     y += 2;
109 
110     // Display child device program list
111     for(int i = 0; i < titleNum; i++)
112     {
113         if(i == selected)
114         {
115             // Specify green in font color
116             pRenderSystem->SetColor(GREEN_COLOR);
117         }
118         else
119         {
120             // Specify white in font color
121             pRenderSystem->SetColor(WHITE_COLOR);
122         }
123 
124         pRenderSystem->DrawText(FONT_SIZE * x       , FONT_SIZE * y, "%02d", i + 1);
125         wcstombs(buffer, titleList[i].shortTitleName, 28);
126         pRenderSystem->DrawText(FONT_SIZE * (x +  3), FONT_SIZE * y, "%s", buffer);
127         buffer[28] = NULL;
128 
129         // Get server information
130         nn::dlp::ServerInfo serverInfo;
131         nn::dlp::FakeClient::GetServerInfo(&serverInfo, titleList[i].mac);
132         wcstombs(buffer, serverInfo.nodeInfo[0].userName.userName, 11);
133         pRenderSystem->DrawText(FONT_SIZE * (x + 33), FONT_SIZE * y, "%s", buffer);
134         y++;
135     }
136 
137     // Use --- to fill in blanks where there is no child device program
138     for(int i = titleNum; i < SCAN_NUM; i++)
139     {
140         if(i == selected)
141         {
142             // Specify green in font color
143             pRenderSystem->SetColor(GREEN_COLOR);
144         }
145         else
146         {
147             // Specify white in font color
148             pRenderSystem->SetColor(WHITE_COLOR);
149         }
150         pRenderSystem->DrawText(FONT_SIZE * x       , FONT_SIZE * y, "%02d", i + 1);
151         pRenderSystem->DrawText(FONT_SIZE * (x +  3), FONT_SIZE * y, "----------------------------");
152         pRenderSystem->DrawText(FONT_SIZE * (x + 33), FONT_SIZE * y, "----------");
153         y++;
154     }
155 }
156 
157 /*!--------------------------------------------------------------------------*
158   Display icon
159  *---------------------------------------------------------------------------*/
DeleteIconTexture(GLuint * pIconTextureId,demo::RenderSystemDrawing * pRenderSystem)160 void DeleteIconTexture(GLuint* pIconTextureId, demo::RenderSystemDrawing* pRenderSystem)
161 {
162     if ( *pIconTextureId != 0 )
163     {
164         bool flag = pRenderSystem->DeleteTexture(*pIconTextureId);
165         if ( flag )
166         {
167             *pIconTextureId = 0;
168         }
169     }
170 }
171 
CreateIconTexture(GLuint * pIconTextureId,const bit16 * iconImage,demo::RenderSystemDrawing * pRenderSystem)172 void CreateIconTexture(GLuint* pIconTextureId, const bit16* iconImage, demo::RenderSystemDrawing* pRenderSystem)
173 {
174     if ( *pIconTextureId != 0 )
175     {
176         DeleteIconTexture(pIconTextureId, pRenderSystem);
177     }
178     const u16 BLOCK_WIDTH          = 8;
179     const u16 BLOCK_HEIGHT         = 8;
180     const u16 BLOCK_LENGTH         = BLOCK_WIDTH * BLOCK_HEIGHT;
181     const u16 BLOCK_SIZE           = BLOCK_LENGTH * sizeof(u16);
182     const u16 ICON_BLOCK_WIDTH     = 6;
183     const u16 ICON_BLOCK_HEIGHT    = 6;
184     const u16 TEXTURE_BLOCK_WIDTH  = 8;
185     const u16 TEXTURE_BLOCK_HEIGHT = 8;
186     static bit16 textureBuffer[TEXTURE_BLOCK_WIDTH * BLOCK_WIDTH * TEXTURE_BLOCK_HEIGHT * BLOCK_HEIGHT];
187 
188     GLenum target = GL_TEXTURE_2D;
189     GLenum internalFormat = GL_RGB_NATIVE_DMP;
190     GLenum format = GL_RGB_NATIVE_DMP;
191     GLenum type = GL_UNSIGNED_SHORT_5_6_5;
192     GLuint textureId = 0;
193 
194     memset(textureBuffer, 0xff, sizeof(textureBuffer));
195     // Convert to texture format; native format has an reverse field y
196     for (size_t i = 0; i < ICON_BLOCK_HEIGHT; i++)
197     {
198         nn::nstd::MemCpy(
199                 &textureBuffer[(i + TEXTURE_BLOCK_HEIGHT - ICON_BLOCK_HEIGHT)* BLOCK_LENGTH * TEXTURE_BLOCK_WIDTH],
200                 &iconImage[i * BLOCK_LENGTH * ICON_BLOCK_WIDTH],
201                 BLOCK_SIZE * ICON_BLOCK_WIDTH);
202     }
203 
204     pRenderSystem->GenerateTexture(target, internalFormat, TEXTURE_BLOCK_WIDTH * BLOCK_WIDTH, TEXTURE_BLOCK_HEIGHT * BLOCK_HEIGHT,
205         format, type, textureBuffer, textureId);
206 
207     if ( textureId != 0 )
208     {
209         *pIconTextureId = textureId;
210     }
211 }
212 
DisplayIcon(const nn::dlp::IconInfo icon,f32 x,f32 y,bool update,demo::RenderSystemDrawing * pRenderSystem)213 void DisplayIcon(const nn::dlp::IconInfo icon, f32 x, f32 y, bool update, demo::RenderSystemDrawing* pRenderSystem)
214 {
215     const u16 TEXTURE_WIDTH = 64;
216     const u16 TEXTURE_HEIGHT = 64;
217 
218     if(update)
219     {
220         CreateIconTexture(&s_IconTextureId, icon.image, pRenderSystem);
221     }
222 
223     if(s_IconTextureId != 0)
224     {
225         pRenderSystem->FillTexturedRectangle(s_IconTextureId, x, y,
226                                                     nn::dlp::ICON_WIDTH_PIXEL, nn::dlp::ICON_HEIGHT_PIXEL,
227                                                     nn::dlp::ICON_WIDTH_PIXEL, nn::dlp::ICON_HEIGHT_PIXEL,
228                                                     TEXTURE_WIDTH, TEXTURE_HEIGHT);
229     }
230 }
231 
232 /*!--------------------------------------------------------------------------*
233   Display child device program information
234  *---------------------------------------------------------------------------*/
DisplayTitleInfo(const nn::dlp::TitleInfo titleInfo,demo::RenderSystemDrawing * pRenderSystem)235 void DisplayTitleInfo(const nn::dlp::TitleInfo titleInfo, demo::RenderSystemDrawing* pRenderSystem)
236 {
237     u16 x = 8;
238     u16 y = 2;
239     char buffer[128];
240 
241     // Update selection
242     bool update = true;
243 
244     // Display icon
245     DisplayIcon(titleInfo.icon, FONT_SIZE, 2 * FONT_SIZE, update, pRenderSystem);
246     // Specify white in font color
247     pRenderSystem->SetColor(WHITE_COLOR);
248     // Display child device program information
249     pRenderSystem->DrawText(0, 0, "TITLE INFO");
250     wcstombs(buffer, titleInfo.shortTitleName, 64);
251     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "SHORT TITLE NAME : %s", buffer);
252     wcstombs(buffer, titleInfo.longTitleName, 128);
253     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "LONG TITLE NAME  : %s", buffer);
254     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "SIZE    : %d BYTES", titleInfo.importSize);
255     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "ID/IDX/Ver : %05x/%d/%04x", titleInfo.uniqueId, titleInfo.childIndex, titleInfo.programVersion);
256     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "REGION  : %08x", titleInfo.region.Get());
257     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "RATING  : %02x%02x%02x%02x%02x%02x%02x%02x", titleInfo.ratingInfo[0],titleInfo.ratingInfo[1],titleInfo.ratingInfo[2],titleInfo.ratingInfo[3],
258                                                                                                      titleInfo.ratingInfo[4],titleInfo.ratingInfo[5],titleInfo.ratingInfo[6],titleInfo.ratingInfo[7]);
259     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "          %02x%02x%02x%02x%02x%02x%02x%02x", titleInfo.ratingInfo[8],titleInfo.ratingInfo[9],titleInfo.ratingInfo[10],titleInfo.ratingInfo[11],
260                                                                                                      titleInfo.ratingInfo[12],titleInfo.ratingInfo[13],titleInfo.ratingInfo[14],titleInfo.ratingInfo[15]);
261 
262 }
263 
264 /*!--------------------------------------------------------------------------*
265   Display server information
266  *---------------------------------------------------------------------------*/
DisplayServerInfo(const nn::dlp::ServerInfo serverInfo,demo::RenderSystemDrawing * pRenderSystem)267 void DisplayServerInfo(const nn::dlp::ServerInfo serverInfo, demo::RenderSystemDrawing* pRenderSystem)
268 {
269     u16 x = 1;
270     u16 y = 9;
271 
272     // Display server information
273     pRenderSystem->DrawText(0, FONT_SIZE * y++, "[ SERVER INFO ]");
274     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "MAC : %02X:%02X:%02X:%02X:%02X:%02X", serverInfo.mac[0],
275                                     serverInfo.mac[1], serverInfo.mac[2], serverInfo.mac[3], serverInfo.mac[4], serverInfo.mac[5]);
276     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "CH : %2d, LEVEL : %d, NODE : %2d/%2d", serverInfo.channel, serverInfo.linkLevel.Get(), serverInfo.nodeNum, serverInfo.maxNodeNum);
277 }
278 
279 /*!--------------------------------------------------------------------------*
280   Display node information
281  *---------------------------------------------------------------------------*/
DisplayNodeInfo(const nn::dlp::NodeInfo nodeInfo[],int nodeNum,demo::RenderSystemDrawing * pRenderSystem)282 void DisplayNodeInfo(const nn::dlp::NodeInfo nodeInfo[], int nodeNum, demo::RenderSystemDrawing* pRenderSystem)
283 {
284     u16 x = 1;
285     u16 y = 13;
286     char buffer[16];
287 
288     // Display node information
289     pRenderSystem->DrawText(0, FONT_SIZE * y++, "[ NODE INFO ]");
290     for(int i = 0; i < nodeNum; i++)
291     {
292         wcstombs(buffer, nodeInfo[i].userName.userName, 11);
293         pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y, "%02d", i + 1);
294         pRenderSystem->DrawText(FONT_SIZE * (x + 3), FONT_SIZE * y++, "%s", buffer);
295     }
296 }
297 
298 /*!--------------------------------------------------------------------------*
299   Display download information
300  *---------------------------------------------------------------------------*/
DisplayDownloadInfo(nn::dlp::ClientStatus status,demo::RenderSystemDrawing * pRenderSystem)301 void DisplayDownloadInfo(nn::dlp::ClientStatus status, demo::RenderSystemDrawing* pRenderSystem)
302 {
303     u16 x = 1;
304     u16 y = 2;
305 
306     // Specify white in font color
307     pRenderSystem->SetColor(WHITE_COLOR);
308 
309     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y  , "DOWNLOADING...");
310     y++;
311     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "NODE ID           : %d\n", status.nodeId);
312     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "STATE             : %d\n", status.state.Get());
313 }
314 
315 /*!--------------------------------------------------------------------------*
316   Display server dynamic information after connecting to server
317  *---------------------------------------------------------------------------*/
UpdateVariableServerInfo(nn::dlp::ServerInfo * pServerInfo)318 void UpdateVariableServerInfo(nn::dlp::ServerInfo* pServerInfo)
319 {
320     u16 nodeIds[nn::dlp::MAX_NODE_NUM];
321 
322     pServerInfo->linkLevel = nn::uds::LINK_LEVEL_0;
323     pServerInfo->nodeNum = 0;
324 
325     nn::uds::LinkLevel linkLevel;
326     nn::dlp::FakeClient::GetLinkLevel(&linkLevel);
327     pServerInfo->linkLevel = static_cast< nn::util::SizedEnum1<nn::uds::LinkLevel> >(linkLevel);
328     nn::dlp::FakeClient::GetConnectingNodes(&pServerInfo->nodeNum, nodeIds, nn::dlp::MAX_NODE_NUM);
329     for (size_t i = 0; i < pServerInfo->nodeNum; i++)
330     {
331         nn::dlp::FakeClient::GetNodeInfo(&pServerInfo->nodeInfo[i], nodeIds[i]);
332     }
333 }
334 
335 /*!--------------------------------------------------------------------------*
336   Initialization state
337  *---------------------------------------------------------------------------*/
DisplayInitialize(demo::RenderSystemDrawing * pRenderSystem)338 void DisplayInitialize(demo::RenderSystemDrawing* pRenderSystem)
339 {
340     u16 x = 1;
341     u16 y = 2;
342 
343     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY0);
344     pRenderSystem->Clear();
345     pRenderSystem->SetColor(WHITE_COLOR);
346     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "FAKE CLIENT SAMPLE");
347     y++;
348     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "NOW INITIALIZING...");
349     pRenderSystem->SwapBuffers();
350     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY1);
351     pRenderSystem->Clear();
352     pRenderSystem->SwapBuffers();
353 }
354 
355 /*!--------------------------------------------------------------------------*
356   Start state
357  *---------------------------------------------------------------------------*/
UpdateStart(int * pTitleNum,int * pSelected,const nn::hid::PadStatus padStatus)358 void UpdateStart(int* pTitleNum, int* pSelected, const nn::hid::PadStatus padStatus)
359 {
360     if(padStatus.trigger & nn::hid::BUTTON_A)
361     {
362         DLP_DEBUG_POINT;
363         // Start scan
364         nn::dlp::FakeClient::StartScan();
365         (*pTitleNum) = 0;
366         (*pSelected) = 0;
367     }
368     else if(padStatus.trigger & nn::hid::BUTTON_Y)
369     {
370         // Initialize using the user name specified with the code
371         std::memcpy( s_UserName.userName, L"FAKE", sizeof(L"FAKE"));
372         nn::dlp::FakeClient::Finalize();
373         nn::dlp::FakeClientWithName::Initialize(SCAN_NUM, s_DlpClientEvent.GetHandle(), s_pAlignedWorkBuffer, s_DlpClientWorkBufferSize, &s_UserName );
374 
375         // Start scan
376         nn::dlp::FakeClient::StartScan();
377         (*pTitleNum) = 0;
378         (*pSelected) = 0;
379     }
380 }
381 
DisplayStart(demo::RenderSystemDrawing * pRenderSystem)382 void DisplayStart(demo::RenderSystemDrawing* pRenderSystem)
383 {
384     u16 x = 1;
385     u16 y = 2;
386 
387     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY0);
388     pRenderSystem->Clear();
389     pRenderSystem->SetColor(WHITE_COLOR);
390     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "FAKE CLIENT SAMPLE");
391     y++;
392     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "PRESS A TO START");
393     pRenderSystem->SwapBuffers();
394     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY1);
395     pRenderSystem->Clear();
396     pRenderSystem->SwapBuffers();
397 }
398 
399 /*!--------------------------------------------------------------------------*
400   Scan state
401  *---------------------------------------------------------------------------*/
UpdateScan(nn::dlp::TitleInfo * titleList,int * pTitleNum,int * pSelected,const nn::hid::PadStatus padStatus)402 void UpdateScan(nn::dlp::TitleInfo* titleList, int* pTitleNum, int* pSelected, const nn::hid::PadStatus padStatus)
403 {
404     nn::Result result;
405 
406     if(padStatus.trigger & nn::hid::BUTTON_A)
407     {
408         DLP_DEBUG_POINT;
409         if(*pSelected < *pTitleNum)
410         {
411             DLP_DEBUG_POINT;
412             // Stop scanning
413             nn::dlp::FakeClient::StopScan();
414             // Start session participation
415             result = nn::dlp::FakeClient::StartFakeSession(titleList[*pSelected].mac, titleList[*pSelected].uniqueId, titleList[*pSelected].childIndex);
416             memcpy(s_ServerMac, titleList[*pSelected].mac, sizeof(s_ServerMac));
417 
418             if(result.IsFailure())
419             {
420                 DLP_DEBUG_PRINT("failed to StartFakeSession\n");
421                 NN_DBG_PRINT_RESULT(result);
422             }
423         }
424     }
425     else if(padStatus.trigger & nn::hid::BUTTON_B)
426     {
427         DLP_DEBUG_POINT;
428         // Stop scanning
429         nn::dlp::FakeClient::StopScan();
430         return;
431     }
432     else if(padStatus.trigger & nn::hid::BUTTON_UP)
433     {
434         DLP_DEBUG_POINT;
435         // Move the selection
436         (*pSelected) = ((*pSelected) - 1 + SCAN_NUM) % SCAN_NUM;
437     }
438     else if(padStatus.trigger & nn::hid::BUTTON_DOWN)
439     {
440         DLP_DEBUG_POINT;
441         // Move the selection
442         (*pSelected) = ((*pSelected) + 1) % SCAN_NUM;
443     }
444 
445     // Update child device program list
446     if(*pTitleNum < SCAN_NUM)
447     {
448         if(nn::dlp::FakeClient::GetTitleInfo(&titleList[*pTitleNum], false).IsSuccess())
449         {
450             NN_LOG("Get new title : %s:%d\n", __FILE__, __LINE__);
451             (*pTitleNum) += 1;
452         }
453     }
454 }
455 
456 
DisplayScan(const nn::dlp::TitleInfo * titleList,int titleNum,int selected,demo::RenderSystemDrawing * pRenderSystem)457 void DisplayScan(const nn::dlp::TitleInfo* titleList, int titleNum, int selected, demo::RenderSystemDrawing* pRenderSystem)
458 {
459 
460     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY0);
461     pRenderSystem->Clear(); DLP_DEBUG_POINT;
462 
463     // Display child device program list
464     DisplayTitleList(titleList, titleNum, selected, pRenderSystem);
465 
466     // Display Cube
467     DisplayCube(pRenderSystem, 385, 225);
468     pRenderSystem->SwapBuffers();
469 
470     // Display child device program details
471     if(0 != titleNum && selected < titleNum)
472     {
473         pRenderSystem->SetRenderTarget(NN_GX_DISPLAY1);
474         pRenderSystem->Clear();
475 
476         DisplayTitleInfo(titleList[selected], pRenderSystem);
477 
478         // Get server information
479         nn::dlp::FakeClient::GetServerInfo(&s_ServerInfo, titleList[selected].mac);
480         // Display server information
481         DisplayServerInfo(s_ServerInfo, pRenderSystem);
482 
483         // Display node information
484         DisplayNodeInfo(s_ServerInfo.nodeInfo, s_ServerInfo.nodeNum, pRenderSystem);
485         pRenderSystem->SwapBuffers();
486     }
487     else
488     {
489         pRenderSystem->SetRenderTarget(NN_GX_DISPLAY1);
490         pRenderSystem->Clear();
491         pRenderSystem->SwapBuffers();
492     }
493 }
494 
495 /*!--------------------------------------------------------------------------*
496   Waiting for connection state
497  *---------------------------------------------------------------------------*/
DisplayWaitingConnect(demo::RenderSystemDrawing * pRenderSystem)498 void DisplayWaitingConnect(demo::RenderSystemDrawing* pRenderSystem)
499 {
500     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY0);
501     pRenderSystem->Clear(); DLP_DEBUG_POINT;
502 
503     u16 x = 1;
504     u16 y = 2;
505 
506     pRenderSystem->SetColor(WHITE_COLOR);
507     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "WAITING CONNECT...");
508     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "PRESS B TO CANCEL");
509 
510     pRenderSystem->SwapBuffers();
511 }
512 
UpdateWaitingConnect(const nn::hid::PadStatus padStatus)513 void UpdateWaitingConnect(const nn::hid::PadStatus padStatus)
514 {
515     if(padStatus.trigger & nn::hid::BUTTON_B)
516     {
517         DLP_DEBUG_POINT;
518         nn::Result result;
519         // Cancel download
520         nn::dlp::FakeClient::StopFakeSession();
521     }
522 }
523 
524 
525 /*!--------------------------------------------------------------------------*
526   Waiting for download state
527  *---------------------------------------------------------------------------*/
UpdateWaitingDownload(const nn::hid::PadStatus padStatus)528 void UpdateWaitingDownload(const nn::hid::PadStatus padStatus)
529 {
530     if(padStatus.trigger & nn::hid::BUTTON_B)
531     {
532         DLP_DEBUG_POINT;
533         nn::Result result;
534         // Cancel download
535         nn::dlp::FakeClient::StopFakeSession();
536     }
537 }
538 
DisplayWaitingDownload(const nn::dlp::TitleInfo & titleInfo,demo::RenderSystemDrawing * pRenderSystem)539 void DisplayWaitingDownload(const nn::dlp::TitleInfo& titleInfo, demo::RenderSystemDrawing* pRenderSystem)
540 {
541     u16 x = 1;
542     u16 y = 2;
543 
544     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY0);
545     pRenderSystem->Clear();
546 
547     pRenderSystem->SetColor(WHITE_COLOR);
548     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "WAITING DOWNLOAD...");
549     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "PRESS B TO CANCEL");
550     pRenderSystem->SwapBuffers();
551 
552     // Display child device program details
553     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY1);
554     pRenderSystem->Clear();
555 
556     DisplayTitleInfo(titleInfo, pRenderSystem);
557 
558     // Display server information
559     UpdateVariableServerInfo(&s_ServerInfo);
560     DisplayServerInfo(s_ServerInfo, pRenderSystem);
561 
562     // Display node information
563     DisplayNodeInfo(s_ServerInfo.nodeInfo, s_ServerInfo.nodeNum, pRenderSystem);
564     pRenderSystem->SwapBuffers();
565 }
566 
567 /*!--------------------------------------------------------------------------*
568   Download state
569  *---------------------------------------------------------------------------*/
UpdateDownload(const nn::hid::PadStatus padStatus)570 void UpdateDownload(const nn::hid::PadStatus padStatus)
571 {
572     if(padStatus.trigger & nn::hid::BUTTON_B)
573     {
574         DLP_DEBUG_POINT;
575         // Cancel download
576         nn::dlp::FakeClient::StopFakeSession();
577     }
578 }
579 
DisplayDownload(nn::dlp::ClientStatus & status,const nn::dlp::TitleInfo & titleInfo,demo::RenderSystemDrawing * pRenderSystem)580 void DisplayDownload(nn::dlp::ClientStatus& status, const nn::dlp::TitleInfo& titleInfo, demo::RenderSystemDrawing* pRenderSystem)
581 {
582     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY0);
583     pRenderSystem->Clear();
584 
585     // Download information display
586     DisplayDownloadInfo(status, pRenderSystem);
587 
588     // Display Cube
589     DisplayCube(pRenderSystem, 385, 225);
590     pRenderSystem->SwapBuffers();
591 
592     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY1);
593     pRenderSystem->Clear();
594 
595     // Display child device program details
596     DisplayTitleInfo(titleInfo, pRenderSystem);
597 
598     // Display server information
599     UpdateVariableServerInfo(&s_ServerInfo);
600     DisplayServerInfo(s_ServerInfo, pRenderSystem);
601 
602     // Display node information
603     DisplayNodeInfo(s_ServerInfo.nodeInfo, s_ServerInfo.nodeNum, pRenderSystem);
604     pRenderSystem->SwapBuffers();
605 }
606 
607 /*!--------------------------------------------------------------------------*
608   Reboot state
609  *---------------------------------------------------------------------------*/
UpdateReboot()610 void UpdateReboot()
611 {
612     DLP_DEBUG_POINT;
613     // Stop download
614     NN_UTIL_PANIC_IF_FAILED(nn::dlp::FakeClient::GetPassphrase(s_Passphrase));
615     DLP_DEBUG_PRINT("PASSPHRASE : %s\n", s_Passphrase);
616     nn::dlp::FakeClient::Finalize();
617     s_IsSessionDone = true;
618 }
619 
DisplayReboot(demo::RenderSystemDrawing * pRenderSystem)620 void DisplayReboot(demo::RenderSystemDrawing* pRenderSystem)
621 {
622     u16 x = 1;
623     u16 y = 2;
624 
625     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY0);
626     pRenderSystem->Clear();
627     pRenderSystem->SetColor(WHITE_COLOR);
628     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "STARTING FAKE CHILD");
629     pRenderSystem->SwapBuffers();
630 
631     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY1);
632     pRenderSystem->Clear();
633     pRenderSystem->SwapBuffers();
634 }
635 
636 
637 /*!--------------------------------------------------------------------------*
638   Error state
639  *---------------------------------------------------------------------------*/
UpdateError(const nn::hid::PadStatus padStatus)640 void UpdateError(const nn::hid::PadStatus padStatus)
641 {
642     nn::dlp::FakeClient::Finalize();
643     if(padStatus.trigger & nn::hid::BUTTON_A)
644     {
645         DLP_DEBUG_POINT;
646         // Restart
647         nn::dlp::FakeClient::Initialize(SCAN_NUM, s_DlpClientEvent.GetHandle(), s_pAlignedWorkBuffer, s_DlpClientWorkBufferSize);
648         s_TitleNum = 0;
649         s_Selected = 0;
650     }
651 }
652 
DisplayError(demo::RenderSystemDrawing * pRenderSystem)653 void DisplayError(demo::RenderSystemDrawing* pRenderSystem)
654 {
655     u16 x = 1;
656     u16 y = 2;
657 
658     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY0);
659     pRenderSystem->Clear();
660     pRenderSystem->SetColor(WHITE_COLOR);
661 
662     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "ERROR");
663 
664     y++;
665     pRenderSystem->DrawText(FONT_SIZE * x, FONT_SIZE * y++, "PRESS A TO RESTART");
666     pRenderSystem->SwapBuffers();
667 
668     pRenderSystem->SetRenderTarget(NN_GX_DISPLAY1);
669     pRenderSystem->Clear();
670     pRenderSystem->SwapBuffers();
671 }
672 
673 
DisplayBlackBack(demo::RenderSystemDrawing & renderSystem)674 void DisplayBlackBack(demo::RenderSystemDrawing& renderSystem)
675 {
676     renderSystem.SetRenderTarget(NN_GX_DISPLAY0);
677     renderSystem.Clear();
678     renderSystem.SwapBuffers();
679     renderSystem.SetRenderTarget(NN_GX_DISPLAY1);
680     renderSystem.Clear();
681     renderSystem.SwapBuffers();
682 }
683 
684 /*!--------------------------------------------------------------------------*
685   Update/display state functions
686  *---------------------------------------------------------------------------*/
Update(nn::dlp::ClientStatus clientStatus,nn::dlp::TitleInfo * titleList,int * pTitleNum,int * pSelected,const nn::hid::PadStatus padStatus)687 void Update(nn::dlp::ClientStatus clientStatus, nn::dlp::TitleInfo* titleList, int* pTitleNum, int* pSelected, const nn::hid::PadStatus padStatus)
688 {
689     switch(clientStatus.state)
690     {
691 
692     case nn::dlp::CLIENT_STATE_DISCONNECTED_NETWORK:
693         UpdateStart(pTitleNum, pSelected, padStatus);
694         break;
695     case nn::dlp::CLIENT_STATE_SCANNING:
696         UpdateScan(titleList, pTitleNum, pSelected, padStatus);
697         break;
698     case nn::dlp::CLIENT_STATE_WAITING_CONNECT:
699         UpdateWaitingConnect(padStatus);
700         break;
701     case nn::dlp::CLIENT_STATE_WAITING_INVITE:
702     case nn::dlp::CLIENT_STATE_JOINED_SESSION:
703         UpdateWaitingDownload(padStatus);
704         break;
705     case nn::dlp::CLIENT_STATE_DOWNLOADING:
706         UpdateDownload(padStatus);
707         break;
708     case nn::dlp::CLIENT_STATE_REBOOTING:
709         UpdateReboot();
710         break;
711     case nn::dlp::CLIENT_STATE_ERROR:
712     case nn::dlp::CLIENT_STATE_INVALID:
713         UpdateError(padStatus);
714         break;
715     default:
716         break;
717     }
718 }
719 
Display(nn::dlp::ClientStatus clientStatus,const nn::dlp::TitleInfo * titleList,int titleNum,int selected,demo::RenderSystemDrawing * pRenderSystem)720 void Display(nn::dlp::ClientStatus clientStatus, const nn::dlp::TitleInfo* titleList, int titleNum, int selected, demo::RenderSystemDrawing* pRenderSystem)
721 {
722     switch(clientStatus.state)
723     {
724     case nn::dlp::CLIENT_STATE_DISCONNECTED_NETWORK:
725         DisplayStart(pRenderSystem);
726         break;
727     case nn::dlp::CLIENT_STATE_SCANNING:
728         DisplayScan(titleList, titleNum, selected, pRenderSystem);
729         break;
730     case nn::dlp::CLIENT_STATE_WAITING_CONNECT:
731         DisplayWaitingConnect(pRenderSystem);
732         break;
733     case nn::dlp::CLIENT_STATE_WAITING_INVITE:
734     case nn::dlp::CLIENT_STATE_JOINED_SESSION:
735         DisplayWaitingDownload(titleList[selected], pRenderSystem);
736         break;
737     case nn::dlp::CLIENT_STATE_DOWNLOADING:
738     case nn::dlp::CLIENT_STATE_DOWNLOAD_COMPLETE:
739         DisplayDownload(clientStatus, titleList[selected], pRenderSystem);
740         break;
741     case nn::dlp::CLIENT_STATE_RECONNECTING_NETWORK:
742         break;
743     case nn::dlp::CLIENT_STATE_REBOOTING:
744         DisplayReboot(pRenderSystem);
745         break;
746     case nn::dlp::CLIENT_STATE_ERROR:
747     case nn::dlp::CLIENT_STATE_INVALID:
748         DisplayError(pRenderSystem);
749         break;
750     default:
751         break;
752     }
753 }
754 
755 /*!--------------------------------------------------------------------------*
756   Main function
757  *---------------------------------------------------------------------------*/
nnMain(void)758 extern "C" void nnMain(void)
759 {
760     //Set sleep callback, sleep recovery callback
761     nn::applet::SetSleepQueryCallback( mySleepQueryCallback, 0 );
762     nn::applet::SetAwakeCallback( myAwakeCallback, 0 );
763     nn::applet::Enable();
764     s_AwakeEvent.Initialize(false);
765 
766     // Initialize hid
767     NN_UTIL_PANIC_IF_FAILED(nn::hid::Initialize());
768 
769     // Prepare pad input
770     nn::hid::PadReader padReader;
771     nn::hid::PadStatus padStatus;
772 
773     // Allocate heap
774     nn::fnd::ExpHeap appHeap;
775     appHeap.Initialize(
776                 nn::os::GetDeviceMemoryAddress(),
777                 nn::os::GetDeviceMemorySize() );
778 
779     // Prepare RenderSystem
780     uptr heapForGx = reinterpret_cast<uptr>(appHeap.Allocate(0x800000));
781     demo::RenderSystemDrawing renderSystem;
782     renderSystem.Initialize(heapForGx, 0x800000);
783     renderSystem.SetClearColor(NN_GX_DISPLAY_BOTH, 0.f, 0.f, 0.f, 0.f);
784     renderSystem.SetFontSize(FONT_SIZE);
785     renderSystem.SetLineWidth(LINE_WIDTH);
786 
787     // Initialize event used by DLP client
788     s_DlpClientEvent.Initialize(false);
789 
790     // Get work buffer size necessary to initialize DLP client
791     s_DlpClientWorkBufferSize = nn::dlp::FakeClient::GetBufferSize(SCAN_NUM);
792     DLP_DEBUG_PRINT("dlpClientWorkBufferSize %d\n", s_DlpClientWorkBufferSize);
793 
794     // Get DLP client work buffer
795     s_pWorkBuffer = new u8[s_DlpClientWorkBufferSize + 4096];
796     s_pAlignedWorkBuffer = reinterpret_cast<void*>(DLP_ROUNDUP(reinterpret_cast<u32>(s_pWorkBuffer), 4096UL));
797 
798 
799     DisplayInitialize(&renderSystem);
800 
801     // Initialize DLP client
802     nn::dlp::FakeClient::Initialize(SCAN_NUM, s_DlpClientEvent.GetHandle(), s_pAlignedWorkBuffer, s_DlpClientWorkBufferSize);
803 
804     // Child device program list
805     nn::dlp::TitleInfo* titleList = reinterpret_cast<nn::dlp::TitleInfo*>(appHeap.Allocate(sizeof(nn::dlp::TitleInfo) * SCAN_NUM));
806     NN_NULL_ASSERT(titleList);
807 
808     s_TitleNum = 0;
809     s_Selected = 0;
810 
811     nn::dlp::ClientStatus clientStatus;
812 
813     // Main loop
814     while(!s_IsSessionDone)
815     {
816         // Get pad input
817         padReader.ReadLatest(&padStatus);
818 
819         // Get DLP client state
820         nn::dlp::FakeClient::GetMyStatus(&clientStatus);
821 
822         // Render
823         Display(clientStatus, titleList, s_TitleNum, s_Selected, &renderSystem);
824 
825         // Update
826         Update(clientStatus, titleList, &s_TitleNum, &s_Selected, padStatus);
827 
828         //Sleep support
829         if ( nn::applet::IsExpectedToReplySleepQuery() )
830         {
831             DLP_DEBUG_POINT;
832             nn::dlp::FakeClient::Finalize();    // Finalize before sleep.
833             nn::applet::ReplySleepQuery( nn::applet::REPLY_ACCEPT ); DLP_DEBUG_POINT;
834             s_AwakeEvent.Wait(); DLP_DEBUG_POINT;
835 
836             // Processing after restart
837             nn::gx::StartLcdDisplay(); DLP_DEBUG_POINT;
838         }
839 
840         //HOME Button support
841         if (nn::applet::IsExpectedToProcessHomeButton())
842         {
843             DLP_DEBUG_POINT;
844             nn::dlp::FakeClient::Finalize();
845             nn::applet::ProcessHomeButton();
846             nn::applet::WaitForStarting(); DLP_DEBUG_POINT;
847 
848             // Recover the GPU register settings
849             nngxUpdateState(NN_GX_STATE_ALL);
850             nngxValidateState(NN_GX_STATE_ALL,GL_TRUE);
851 
852             if ( nn::applet::IsExpectedToCloseApplication() )
853             {
854                 DLP_DEBUG_POINT;
855                 break;
856             }
857         }
858 
859         //POWER Button support
860         if ( nn::applet::IsExpectedToProcessPowerButton() )
861         {
862             DLP_DEBUG_POINT;
863             nn::dlp::FakeClient::Finalize();
864             nn::applet::ProcessPowerButton();
865             nn::applet::WaitForStarting(); DLP_DEBUG_POINT;
866 
867             // Recover the GPU register settings
868             nngxUpdateState(NN_GX_STATE_ALL);
869             nngxValidateState(NN_GX_STATE_ALL,GL_TRUE);
870 
871             if ( nn::applet::IsExpectedToCloseApplication() )
872             {
873                 DLP_DEBUG_POINT;
874                 break;
875             }
876         }
877 
878         // Support for termination request
879         if (nn::applet::IsExpectedToCloseApplication())
880         {
881             DLP_DEBUG_POINT;
882             DisplayBlackBack(renderSystem);
883             break;
884         }
885     }
886 
887     // Discard child device program list
888     appHeap.Free(titleList);
889 
890     nn::dlp::FakeClient::Finalize();
891     delete[] s_pWorkBuffer;
892     s_DlpClientEvent.Finalize();
893     renderSystem.Finalize();
894     appHeap.Free(reinterpret_cast<void*>(heapForGx));
895     appHeap.Finalize();
896     nn::hid::Finalize();
897     nn::applet::SetSleepQueryCallback(NULL, 0);
898     nn::applet::SetAwakeCallback(NULL, 0);
899     s_AwakeEvent.Finalize();
900 
901     if (s_IsSessionDone)
902     {
903         DLP_DEBUG_POINT;
904         // Because this is a provisional implementation, the SLEEP, HOME, and POWER Buttons do not work after this
905         DoChild(s_ServerMac, s_Passphrase);
906     }
907 
908     // Discard events used by DLP client
909     s_DlpClientEvent.Finalize();
910 
911     // Discard work buffer used by the DLP client
912     delete s_pWorkBuffer;
913 
914     while(1)
915     {
916         nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromSeconds(60));
917     }
918 }
919 
920