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