1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - tcl - demos.TWL - tcl-2
3   File:     main.c
4 
5   Copyright 2008-2009 Nintendo. 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   $Date:: 2009-06-04#$
14   $Rev: 10698 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 #include <twl.h>
18 #include <twl/tcl.h>
19 #include <twl/ssp/ARM9/jpegenc.h>
20 #include <twl/ssp/ARM9/exifenc.h>
21 
22 #include "DEMO.h"
23 #include "screen.h"
24 
25 /*---------------------------------------------------------------------------*
26     Constant Definitions
27  *---------------------------------------------------------------------------*/
28 #define BMP_HEADER_SIZE 54 // Header size for Windows bitmap (BMP) file
29 
30 /*---------------------------------------------------------------------------*
31     Internal Functions and Definitions
32  *---------------------------------------------------------------------------*/
33 void VBlankIntr(void);
34 void Print(void);
35 void BMPToRGB( const u8* p_bmp, u16* p_rgb );
36 
37 /*---------------------------------------------------------------------------*
38     Internal Variable Definitions
39  *---------------------------------------------------------------------------*/
40 int  state = 0;
41 int  num_pict = 0;
42 int  rest_pict = 0;
43 
44 /*---------------------------------------------------------------------------*
45   Name:         VBlankIntr
46 
47   Description:  V-Blank interrupt handler.
48 
49   Arguments:    None.
50 
51   Returns:      None.
52  *---------------------------------------------------------------------------*/
VBlankIntr(void)53 void VBlankIntr(void)
54 {
55     OS_SetIrqCheckFlag( OS_IE_V_BLANK );
56 }
57 
58 /*---------------------------------------------------------------------------*
59   Name:         Print
60 
61   Description:  Renders debug information.
62 
63   Arguments:    None.
64 
65   Returns:      None.
66  *---------------------------------------------------------------------------*/
Print(void)67 void Print(void)
68 {
69     ClearScreen();
70 
71     PutScreen(0, 0, 0xff, "TCL-2 Write Picture Demo");
72 
73     PutScreen(2, 4, 0xff, "Num Pictures       : %d", num_pict );
74     PutScreen(2, 3, 0xff, "Rest Num Pictures  : %d", rest_pict );
75 
76     switch( state )
77     {
78     case 0: PutScreen( 1, 8, 0xff, "A Button > Write Picture" ); break;
79     case 1: PutScreen( 1, 8, 0xff, "Now Writing..." );           break;
80     case 2: PutScreen( 1, 8, 0xff, "Finish!" );                  break;
81     case 3: PutScreen( 1, 8, 0xff, "Not enable Write Picture" ); break;
82     }
83 }
84 
85 /*---------------------------------------------------------------------------*
86   Name:         BMPToRGB
87 
88   Description:  Converts 24-bit BMP to RGB555 format.
89 
90   Arguments:    p_bmp: Original bitmap image
91                 p_rgb: New RGB image
92 
93   Returns:      None.
94  *---------------------------------------------------------------------------*/
BMPToRGB(const u8 * p_bmp,u16 * p_rgb)95 void BMPToRGB( const u8* p_bmp, u16* p_rgb )
96 {
97     int h, w;
98     int b, g, r;
99 
100     for ( h = 0; h < TCL_JPEG_HEIGHT; ++h )
101     {
102         for ( w = 0; w < TCL_JPEG_WIDTH; ++w )
103         {
104             b = ( p_bmp[ 3 * ( h * TCL_JPEG_WIDTH + w ) + 0 ] >> 3 ) & 0x1f;
105             g = ( p_bmp[ 3 * ( h * TCL_JPEG_WIDTH + w ) + 1 ] >> 3 ) & 0x1f;
106             r = ( p_bmp[ 3 * ( h * TCL_JPEG_WIDTH + w ) + 2 ] >> 3 ) & 0x1f;
107 
108             p_rgb[ ( TCL_JPEG_HEIGHT - h - 1 ) * TCL_JPEG_WIDTH + w ] = (u16)( 0x8000 |
109                                                                                ( b << GX_RGBA_B_SHIFT ) |
110                                                                                ( g << GX_RGBA_G_SHIFT ) |
111                                                                                ( r << GX_RGBA_R_SHIFT ) );
112         }
113     }
114 }
115 
116 /*---------------------------------------------------------------------------*
117   Name:         TwlMain
118 
119   Description:  Main.
120 
121   Arguments:    None.
122 
123   Returns:      None.
124  *---------------------------------------------------------------------------*/
TwlMain(void)125 void TwlMain(void)
126 {
127     OSHeapHandle handle;
128     void* nstart;
129 
130     void* pTableBuf;
131     void* pWorkBuf;
132 
133     FSResult fs_result;
134     TCLResult result;
135 
136     // TCL accessor
137     TCLAccessor accessor;
138 
139     // Search condition object
140     TCLSearchObject search_obj;
141 
142     BOOL write_enable = TRUE;
143     int count;
144 
145     // Initialization process
146     DEMOInitCommon();
147     DEMOInitVRAM();
148 
149     OS_InitTick();
150     OS_InitAlarm();
151     RTC_Init();
152     FS_Init( FS_DMA_NOT_USE );
153 
154     InitScreen();
155     ClearScreen();
156 
157     // GX-related settings
158     GX_SetBankForBG( GX_VRAM_BG_128_A );
159 
160     GX_SetGraphicsMode( GX_DISPMODE_GRAPHICS, GX_BGMODE_3, GX_BG0_AS_2D );
161 
162     GX_SetVisiblePlane( GX_PLANEMASK_BG3 );
163     G2_SetBG3Priority( 0 );
164     G2_BG3Mosaic( FALSE );
165 
166     G2_SetBG3ControlDCBmp( GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000 );
167 
168     // Create heap
169     nstart = OS_InitAlloc( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1 );
170     OS_SetMainArenaLo( nstart );
171 
172     handle = OS_CreateHeap( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi() );
173     if (handle < 0)
174     {
175         OS_Panic("ARM9: Fail to create heap...");
176     }
177     handle = OS_SetCurrentHeap( OS_ARENA_MAIN, handle );
178 
179 
180     // TCL initialization
181     // 32-byte alignment necessary
182     pTableBuf = OS_Alloc( TCL_GetTableBufferSize() );
183     pWorkBuf = OS_Alloc( TCL_GetWorkBufferSize() );
184     if( pTableBuf == NULL || pWorkBuf == NULL )
185     {
186         OS_Panic("Cannot allocate memory!");
187     }
188 
189     result = TCL_LoadTable( &accessor,
190                             pTableBuf,
191                             TCL_GetTableBufferSize(),
192                             pWorkBuf,
193                             TCL_GetWorkBufferSize(),
194                             &fs_result );
195 
196 #if 1
197 
198     // End the following processes when loading of the management file fails
199 
200     if ( result != TCL_RESULT_SUCCESS )
201     {
202         // For other errors, prompt Nintendo DSi camera startup and end the process
203         //OS_TPrintf ("appropriate text here")
204 
205         OS_Panic("failed TCL_LoadTable : %d\n", result );
206     }
207 
208 #else
209 
210     // Try recovering if loading of the management file failed
211 
212     switch( result )
213     {
214     case TCL_RESULT_SUCCESS: break; // Success
215     case TCL_RESULT_ERROR_EXIST_OTHER_FILE:
216     case TCL_RESULT_ERROR_ALREADY_MANAGED:
217         OS_TPrintf("failed TCL_LoadTable : %d\n", result );
218 
219         // Recalculate the next save location because no write-out processing can be carried out
220         result = TCL_RepairTable( &accessor, &fs_result );
221 
222         if( result != TCL_RESULT_SUCCESS )
223         {
224             OS_TPrintf("failed TCL_RepairTable : %d\n", result );
225 
226             // Recreate the management file because the state does not allow image write-outs
227             result = TCL_CreateTable( &accessor,
228                                       pTableBuf,
229                                       TCL_GetTableBufferSize(),
230                                       pWorkBuf,
231                                       TCL_GetWorkBufferSize(),
232                                       &fs_result );
233 
234             switch( result )
235             {
236             case TCL_RESULT_SUCCESS:
237                 // Table successfully created
238                 break;
239             case TCL_RESULT_ERROR_OVER_NUM_PICTURES:
240                 // More than 500 photos present, but table successfully created
241                 OS_TPrintf("failed TCL_CreateTable : %d", result );
242                 break;
243             case TCL_RESULT_ERROR_NO_NEXT_INDEX:
244                 // Error indicates no save possible, but continuation possible
245                 write_enable = FALSE;
246                 OS_TPrintf("failed TCL_CreateTable : %d", result );
247                 break;
248             default:
249                 // Continuation impossible error
250                 OS_Panic("failed TCL_CreateTable : %d", result );
251                 break;
252             }
253         }
254         break;
255     default:
256         OS_TPrintf("failed TCL_LoadTable : %d\n", result );
257 
258         // The management file is recreated because read processing cannot be carried out
259         result = TCL_CreateTable( &accessor,
260                                   pTableBuf,
261                                   TCL_GetTableBufferSize(),
262                                   pWorkBuf,
263                                   TCL_GetWorkBufferSize(),
264                                   &fs_result );
265 
266         switch( result )
267         {
268         case TCL_RESULT_SUCCESS: break;
269         case TCL_RESULT_ERROR_OVER_NUM_PICTURES:
270             OS_TPrintf("failed TCL_CreateTable : %d", result );
271             break;
272         case TCL_RESULT_ERROR_NO_NEXT_INDEX:
273             write_enable = FALSE;
274             OS_TPrintf("failed TCL_CreateTable : %d", result );
275             break;
276         default:
277             OS_Panic("failed TCL_CreateTable : %d", result );
278             break;
279         }
280         break;
281     }
282 
283 #endif
284 
285     // How many more photos can be saved?
286     rest_pict = TCL_CalcNumEnableToTakePictures( &accessor );
287 
288     // Initialize SearchObject
289     TCL_InitSearchObject( &search_obj, TCL_SEARCH_CONDITION_PICTURE );
290 
291     // How many photos in all?
292     num_pict = TCL_GetNumPictures( &accessor, &search_obj );
293 
294     Print();
295 
296     DEMOStartDisplay();
297 
298     // Updates text display
299     UpdateScreen();
300 
301     while (1)
302     {
303         // Reading pad information and controls
304         DEMOReadKey();
305 
306         if( DEMO_IS_TRIG( PAD_BUTTON_A ) )
307         {
308             if( rest_pict == 0 || !write_enable )
309             {
310                 // Cannot save more than this
311                 count = 0;
312                 state = 3;
313                 Print();
314             }
315             else if( state == 0 )
316             {
317                 count = 0;
318                 ++state;
319                 Print();
320             }
321         }
322         else if( state == 1 )
323         {
324             // Buffer storing JPEG images
325             u8*  pJpegBuf = NULL;
326             u8*  pData    = NULL;
327             u8*  pTmpBuf  = NULL;
328             u16* pRGBBuf  = NULL;
329             u32  length;
330             FSFile file;
331             const u32 option = SSP_JPEG_THUMBNAIL | SSP_JPEG_RGB555;
332 
333             // Get BMP image
334             FS_InitFile( &file );
335             if( !FS_OpenFileEx( &file, "rom:/demo.bmp", FS_FILEMODE_R ) )
336             {
337                 OS_Panic("failed FS_OpenFileEx : %d ", FS_GetResultCode( &file ) );
338             }
339 
340             length = FS_GetFileLength( &file );
341             pData = OS_Alloc( length );
342             if( pData == NULL )
343             {
344                 OS_Panic("Cannot allocate memory ... pData!");
345             }
346 
347             if( FS_ReadFile( &file, pData, (s32)length ) == -1 )
348             {
349                 OS_Panic("failed FS_ReadFile");
350             }
351             ( void ) FS_CloseFile( &file );
352 
353             pData += BMP_HEADER_SIZE;
354 
355             // Convert BMP image to RGB555 format
356             pRGBBuf = OS_Alloc( TCL_JPEG_WIDTH * TCL_JPEG_HEIGHT * sizeof(u16) );
357             if( pRGBBuf == NULL )
358             {
359                 OS_Panic("Cannot allocate memory ... pRGBBuf!");
360             }
361 
362             BMPToRGB( pData, pRGBBuf );
363             pData -= BMP_HEADER_SIZE;
364 
365             OS_Free( pData );
366 
367             // JPEG encoding
368             length = TCL_GetJpegEncoderBufferSize( option );
369             pTmpBuf = OS_Alloc( length );
370             if( pTmpBuf == NULL )
371             {
372                 OS_Panic("Cannot allocate memory ... pTmpBuf!");
373             }
374             OS_TPrintf("SSP_GetJpegEncoderBufferSize() = %d\n", length );
375 
376             pJpegBuf = OS_Alloc( TCL_MAX_JPEG_SIZE );
377             if( pJpegBuf == NULL )
378             {
379                 OS_Panic("Cannot allocate memory ... pJpegBuf!");
380             }
381 
382             // Encode + Write
383             result = TCL_EncodeAndWritePicture( &accessor,
384                                                 pRGBBuf ,
385                                                 pJpegBuf,
386                                                 TCL_MAX_JPEG_SIZE ,
387                                                 pTmpBuf ,
388                                                 TCL_JPEG_DEFAULT_QUALITY ,
389                                                 option ,
390                                                 &fs_result );
391 
392             if( result != TCL_RESULT_SUCCESS )
393             {
394                 OS_TPrintf("failed TCL_WritePicture : %d\n", result );
395 
396                 // Cannot save more than this
397                 if( result == TCL_RESULT_ERROR_NO_NEXT_INDEX ) write_enable = FALSE;
398             }
399             else
400             {
401                 OS_TPrintf("success TCL_WritePicture! %s\n" , TCL_GetLastWrittenPicturePath() );
402             }
403 
404             OS_Free( pJpegBuf );
405             OS_Free( pTmpBuf );
406             OS_Free( pRGBBuf );
407 
408             // How many more photos can be saved?
409             rest_pict = TCL_CalcNumEnableToTakePictures( &accessor );
410 
411             // How many photos in all?
412             num_pict = TCL_GetNumPictures( &accessor, &search_obj );
413 
414             ++state;
415             Print();
416         }
417         else if( state == 2 || state == 3 )
418         {
419             ++count;
420             if( count > 180 )
421             {
422                 state = 0;
423                 Print();
424             }
425         }
426 
427         OS_WaitVBlankIntr();
428 
429         // Updates text display
430         UpdateScreen();
431     }
432 
433     OS_Free( pWorkBuf );
434     OS_Free( pTableBuf );
435 
436     OS_Terminate();
437 }
438