1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     swkbd_demo.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: 47394 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn.h>
17 
18 #include "demo.h"
19 
20 #include <nn/swkbd.h>
21 
22 #include <string.h>
23 #include <wchar.h>
24 
25 
26 //----------------------------------------------------------------
27 
28 namespace
29 {
30     demo::RenderSystemDrawing df;
31 
32     s32 loopCnt = 0;
33 
SetupRenderSystem()34     void SetupRenderSystem()
35     {
36         demo::RenderBufferDescription colorBufferDesc;
37         {
38             colorBufferDesc.m_Format     = GL_RGBA8_OES;
39             colorBufferDesc.m_Width      = nn::gx::DISPLAY0_WIDTH;
40             colorBufferDesc.m_Height     = nn::gx::DISPLAY0_HEIGHT;
41             colorBufferDesc.m_Area       = NN_GX_MEM_VRAMA;
42             colorBufferDesc.m_Attachment = GL_COLOR_ATTACHMENT0;
43         }
44         demo::RenderBufferDescription depthStencilBufferDesc;
45         {
46             depthStencilBufferDesc.m_Format     = GL_DEPTH24_STENCIL8_EXT;
47             depthStencilBufferDesc.m_Width      = nn::gx::DISPLAY0_WIDTH;
48             depthStencilBufferDesc.m_Height     = nn::gx::DISPLAY0_HEIGHT;
49             depthStencilBufferDesc.m_Area       = NN_GX_MEM_VRAMB;
50             depthStencilBufferDesc.m_Attachment = GL_DEPTH_STENCIL_ATTACHMENT;
51         }
52 
53         demo::FrameBufferDescription frameBufferDesc;
54         {
55             frameBufferDesc.m_RenderBufferDescriptionArray[demo::DEMO_COLOR_BUFFER_INDEX] = colorBufferDesc;
56             frameBufferDesc.m_RenderBufferDescriptionArray[demo::DEMO_DEPTH_STENCIL_BUFFER_INDEX] = depthStencilBufferDesc;
57         }
58 
59         demo::DisplayBuffersDescription display0BuffersDesc;
60         {
61             display0BuffersDesc.m_TargetDisplay    = NN_GX_DISPLAY0;
62             display0BuffersDesc.m_DisplayBufferNum = demo::DEMO_DISPLAY_BUFFER_NUM;
63             display0BuffersDesc.m_Format           = GL_RGB8_OES;
64             display0BuffersDesc.m_Width            = nn::gx::DISPLAY0_WIDTH;
65             display0BuffersDesc.m_Height           = nn::gx::DISPLAY0_HEIGHT;
66             display0BuffersDesc.m_Area             = NN_GX_MEM_FCRAM;
67 //            display0BuffersDesc.m_Area             = NN_GX_MEM_VRAMA;
68         }
69 
70         demo::DisplayBuffersDescription display1BuffersDesc;
71         {
72             display1BuffersDesc.m_TargetDisplay    = NN_GX_DISPLAY1;
73             display1BuffersDesc.m_DisplayBufferNum = demo::DEMO_DISPLAY_BUFFER_NUM;
74             display1BuffersDesc.m_Format           = GL_RGB8_OES;
75             display1BuffersDesc.m_Width            = nn::gx::DISPLAY1_WIDTH;
76             display1BuffersDesc.m_Height           = nn::gx::DISPLAY1_HEIGHT;
77             display1BuffersDesc.m_Area             = NN_GX_MEM_FCRAM;
78 //            display1BuffersDesc.m_Area             = NN_GX_MEM_VRAMB;
79         }
80 
81         df.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize(),
82                                   0x40000, 128, true,
83                                   display0BuffersDesc, display1BuffersDesc,
84                                   frameBufferDesc
85                                   );
86     }
87 
ReleaseRenderSystem()88     void ReleaseRenderSystem()
89     {
90         df.Finalize();
91     }
92 
DrawText()93     void DrawText()
94     {
95         // display 0
96         df.SetRenderTarget(NN_GX_DISPLAY0);
97         df.Clear();
98         {
99             df.SetColor(0.0f, 0.0f, 0.5f);
100             df.FillRectangle( 0, 0, 399, 255 );
101             df.SetColor(0.5f, 0.4f, 0.0f);
102             df.FillRectangle( 0, 0, 399, 40 );
103             df.SetColor(0.5f, 0.0f, 0.4f);
104             df.FillRectangle( 0, 180, 399, 40 );
105             df.SetColor(1.0f, 1.0f, 1.0f);
106             df.DrawText( 100, 50, "** DEMO APPLICATION **" );
107 
108             df.SetColor(1.0f, 1.0f, 1.0f);
109             df.DrawText( 30,  80, "[A]   Launch library applet." );
110 
111             // Count
112             df.DrawText( 340, 50, "%d", loopCnt );
113             df.DrawText( 340, 82, "%d", nngxCheckVSync(NN_GX_DISPLAY0) );
114         }
115         df.SwapBuffers();
116 
117         // display 1
118         df.SetRenderTarget(NN_GX_DISPLAY1);
119         df.Clear();
120         {
121             df.SetColor(0.0f, 0.5f, 0.0f);
122             df.FillRectangle( 0, 0, 399, 255 );
123             df.SetColor(1.0f, 1.0f, 1.0f);
124             df.DrawText( 80, 50, "** DEMO APPLICATION **" );
125         }
126         df.SwapBuffers();
127     }
128 
DrawDisplay()129     void DrawDisplay()
130     {
131         DrawText();
132     }
133 
RestoreGraphics()134     void RestoreGraphics()
135     {
136         // Recover the GPU register settings
137         nngxUpdateState(NN_GX_STATE_ALL);
138         nngxValidateState(NN_GX_STATE_ALL,GL_TRUE);
139     }
140 }
141 
142 //----------------------------------------------------------------
myReceiveSleepQueryNotification(uptr arg)143 AppletQueryReply myReceiveSleepQueryNotification( uptr arg )
144 {
145     NN_UNUSED_VAR( arg );
146     NN_LOG("*** Application-1 sleepQuery \n");
147     return /*applet::IsActive()? applet::REPLY_LATER:*/ nn::applet::REPLY_ACCEPT;
148 }
149 
150 //----------------------------------------------------------------
myReceiveAwakeNotification(uptr arg)151 void myReceiveAwakeNotification( uptr arg )
152 {
153     NN_UNUSED_VAR( arg );
154     NN_LOG("*** Application-1 awake \n");
155     if ( nn::applet::IsActive() )
156     {
157         nngxStartLcdDisplay();
158     }
159 }
160 
161 //----------------------------------------------------------------
nnMain()162 extern "C" void nnMain()
163 {
164     NN_TLOG_("----Application start\n");
165 
166     nn::Result result;
167 
168     // applet declarations
169     nn::applet::SetSleepQueryCallback( myReceiveSleepQueryNotification, 0 );
170     nn::applet::SetAwakeCallback( myReceiveAwakeNotification, 0 );
171     nn::applet::Enable();
172     if(nn::applet::IsExpectedToCloseApplication())
173     {
174         // Quickly end the application
175         nn::applet::PrepareToCloseApplication();
176         nn::applet::CloseApplication();
177 
178         // Never reached
179         return;
180     }
181 
182     // hid
183     result = nn::hid::Initialize();
184     NN_UTIL_PANIC_IF_FAILED(result);
185 
186     // Render class initialization
187     SetupRenderSystem();
188 
189     nn::hid::PadReader padReader;
190     nn::hid::PadStatus ps;
191 
192     while(1)
193     {
194         loopCnt++;
195 
196         padReader.ReadLatest(&ps);
197 
198         // Render
199         DrawDisplay();
200 
201 
202         // Start library applet with A Button
203         if ( ps.trigger & nn::hid::BUTTON_A )
204         {
205             nn::applet::WakeupState wstate;
206             nn::swkbd::Parameter kbd_param; // structure for keyboard configuration and structure containing screen capture information
207 
208             // Initialize structure for keyboard configuration
209             nn::swkbd::InitializeConfig( &kbd_param.config );
210             kbd_param.config.keyboardType = nn::swkbd::KEYBOARD_TYPE_QWERTY;
211             kbd_param.config.upperScreenFlag = nn::swkbd::UPPER_SCREEN_DARK;
212             kbd_param.config.bottomButtonType = nn::swkbd::BOTTOM_BUTTON_TYPE_2BUTTON;
213             kbd_param.config.textLengthMax = 10;
214             kbd_param.config.prediction = false;
215             kbd_param.config.lineFeed = false;
216             kbd_param.config.bottomButtonToFinish[nn::swkbd::BOTTOM_BUTTON_2BUTTON_RIGHT] = true;
217             wcsncpy( kbd_param.config.guideText, L"Please input text.", 19 );
218 
219             /*
220                         The code below modifies the text of the OK and Cancel buttons shown on the bottom of the screen.
221                         Although text appears on the button as specified if modified, the default text for a given system region and language will appear as long as default settings are used.
222 
223                         For example, "Cancel" and "OK" are displayed on buttons if English is selected as the language, but "Annuler" and "OK" appear if French is selected.
224 
225                         Localization of text used for button on the screen is therefore unnecessary at the application level as long as you use default settings.
226 
227              */
228             //wcsncpy( kbd_param.config.bottomButtonText[nn::swkbd::BOTTOM_BUTTON_2BUTTON_LEFT], L"Cancel", 7 );
229             //wcsncpy( kbd_param.config.bottomButtonText[nn::swkbd::BOTTOM_BUTTON_2BUTTON_RIGHT], L"OK", 3 );
230 
231             // Calculate size of shared memory region
232             s32 memSize = nn::swkbd::GetSharedMemorySize( &kbd_param.config, NULL, NULL );
233             // Allocate shared memory
234             const u32 ALIGN = 4096;
235             void* share_buf = std::malloc(memSize + (ALIGN - 1));
236             NN_NULL_ASSERT( share_buf );
237 
238             if( share_buf )
239             {
240                 void* aligned_share_buf = reinterpret_cast<void*>((reinterpret_cast<u32>(share_buf) + (ALIGN - 1)) & ~(ALIGN-1));
241 
242                 // Call keyboard
243                 nn::swkbd::StartKeyboardApplet(
244                     &wstate,
245                     &kbd_param,
246                     aligned_share_buf, // Must be 4096-byte aligned.ipp Device memory cannot be specified.
247                     memSize );         // Must be a multiple of 4096
248                 // Recover the GPU register settings
249                 if(nn::applet::IsExpectedToCloseApplication())
250                 {
251                     std::free(share_buf);
252                     break;
253                 }
254                 RestoreGraphics();
255 
256 
257                 // Get the input string
258                 u8* buf = static_cast<u8*>(aligned_share_buf);
259                 wchar_t text_buf[11];
260                 memset( text_buf, 0, sizeof( text_buf ) );
261 
262                 memcpy( text_buf, &buf[kbd_param.config.inputText], kbd_param.config.inputTextLength * sizeof( wchar_t ) );
263 
264                 for( s32 i = 0; i < 10; ++i )
265                 {
266                     NN_LOG("%d\n", text_buf[i]);
267                 }
268                 std::free(share_buf);
269             }
270         }
271 
272 
273         // Handle HOME Button on keyboard
274         if ( nn::applet::IsExpectedToProcessHomeButton() )
275         {
276             NN_LOG("swkbd HomeBtn.\n");
277             nn::applet::ProcessHomeButtonAndWait();
278 
279             if(nn::applet::IsExpectedToCloseApplication())
280             {
281                 break;
282             }
283 
284             RestoreGraphics();
285 
286         }
287 
288         // Handle POWER Button on keyboard
289         if ( nn::applet::IsExpectedToProcessPowerButton() )
290         {
291             NN_LOG("swkbd PowerBtn.\n");
292             nn::applet::ProcessPowerButtonAndWait();
293 
294             if(nn::applet::IsExpectedToCloseApplication())
295             {
296                 break;
297             }
298 
299             RestoreGraphics();
300 
301         }
302     }
303 
304     NN_TLOG_("----Application is to be end\n");
305 
306     // Free the render class
307     ReleaseRenderSystem();
308 
309     // Finalize hid
310     nn::hid::Finalize();
311 
312     // Exit application
313     nn::applet::PrepareToCloseApplication();
314     nn::applet::CloseApplication();
315 
316     // No need to call Finalize on applet
317     // Execution will probably not reach here.
318     NN_TLOG_("----Application end\n");
319 }
320