1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - tcl - demos.TWL - tcl-1
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/jpegdec.h>
20 #include <twl/ssp/ARM9/exifdec.h>
21
22 #include "DEMO.h"
23 #include "screen.h"
24
25 /*---------------------------------------------------------------------------*
26 Constant Definitions
27 *---------------------------------------------------------------------------*/
28 #define WIDTH 256 // Image width
29 #define HEIGHT 192 // Image height
30
31 /*---------------------------------------------------------------------------*
32 Internal Functions and Definitions
33 *---------------------------------------------------------------------------*/
34 void VBlankIntr(void);
35 void Print(void);
36 void DownSampling( const u16* org_img, int org_wdt, int org_hgt,
37 u16* new_img, int new_wdt, int new_hgt );
38 int GetR ( u16 color );
39 int GetG ( u16 color );
40 int GetB ( u16 color );
41
42 /*---------------------------------------------------------------------------*
43 Internal Variable Definitions
44 *---------------------------------------------------------------------------*/
45 // Buffer storing images
46 static u16 draw_buffer[ WIDTH * HEIGHT ] ATTRIBUTE_ALIGN(32);
47
48 int condition_id = 0;
49 int search = 0;
50 int num_pict = 0;
51 int draw_id = 0;
52
53 // Get the color value (from 0 to 31)
GetR(u16 color)54 int GetR ( u16 color ) { return (color & GX_RGB_R_MASK) >> GX_RGB_R_SHIFT; }
GetG(u16 color)55 int GetG ( u16 color ) { return (color & GX_RGB_G_MASK) >> GX_RGB_G_SHIFT; }
GetB(u16 color)56 int GetB ( u16 color ) { return (color & GX_RGB_B_MASK) >> GX_RGB_B_SHIFT; }
57
58 /*---------------------------------------------------------------------------*
59 Name: VBlankIntr
60
61 Description: V-Blank interrupt handler.
62
63 Arguments: None.
64
65 Returns: None.
66 *---------------------------------------------------------------------------*/
VBlankIntr(void)67 void VBlankIntr(void)
68 {
69 OS_SetIrqCheckFlag( OS_IE_V_BLANK );
70 }
71
72 /*---------------------------------------------------------------------------*
73 Name: Print
74
75 Description: Renders debug information.
76
77 Arguments: None.
78
79 Returns: None.
80 *---------------------------------------------------------------------------*/
Print(void)81 void Print(void)
82 {
83 const char* condition_name[] = { "All Picture", "Favorite1", "Favorite2", "Favorite3", "FavoriteAll" };
84
85 ClearScreen();
86
87 PutScreen(0, 0, 0xff, "TCL-1 Search Picture Demo");
88
89 PutScreen(2, 4, 0xff, "TCL Condition : %s", condition_name[condition_id] );
90 PutScreen(2, 5, 0xff, "Draw Index : %d", draw_id );
91
92 PutScreen(2, 7, 0xff, "Num Pictures : %d", num_pict );
93
94 PutScreen(1, 12, 0xff, "A Button > Draw Picture" );
95 PutScreen(1, 13, 0xff, "B Button > Draw Thumbnail" );
96 PutScreen(1, 14, 0xff, "X Button > Select Condition" );
97 PutScreen(1, 15, 0xff, "Y Button > Change Search Method" );
98 PutScreen(1, 16, 0xff, "R Button > Delete Picture" );
99
100 if( search )
101 {
102 PutScreen(1, 2, 0xff, "Iterate Search" );
103 }
104 else
105 {
106 PutScreen(1, 2, 0xff, "Random Search" );
107 PutScreen(1, 17, 0xff, "Left Key > Select Draw Index" );
108 PutScreen(1, 18, 0xff, "Right Key > Select Draw Index" );
109 }
110 }
111
112 /*---------------------------------------------------------------------------*
113 Name: DownSampling
114
115 Description: Size reduction.
116
117 Arguments: org_img: Original image
118 org_wdt: Original image width
119 org_hgt: Original image height
120 new_img: New image
121 new_wdt: New image width
122 new_hgt: New image height
123
124 Returns: None.
125 *---------------------------------------------------------------------------*/
DownSampling(const u16 * org_img,int org_wdt,int org_hgt,u16 * new_img,int new_wdt,int new_hgt)126 void DownSampling( const u16* org_img, int org_wdt, int org_hgt,
127 u16* new_img, int new_wdt, int new_hgt )
128 {
129 int h, w, i = 0;
130
131 if( org_wdt == TCL_JPEG_WIDTH )
132 {
133 // Normal photograph
134 for ( h = 0; h < new_hgt; ++h )
135 {
136 for ( w = 0; w < new_wdt; ++w )
137 {
138 new_img[ h * new_wdt + w ] = org_img[ ( h * org_hgt / new_hgt ) * org_wdt +
139 w * org_wdt / new_wdt ];
140 }
141 }
142 }
143 else
144 {
145 // Thumbnail
146 u16* thumb_img = &new_img[ ( HEIGHT - SSP_JPEG_THUMBNAIL_HEIGHT ) / 2 * WIDTH +
147 ( WIDTH - SSP_JPEG_THUMBNAIL_WIDTH ) / 2 ];
148
149 for ( h = 0; h < org_hgt; ++h )
150 {
151 for ( w = 0; w < org_wdt; ++w )
152 {
153 thumb_img[ h * new_wdt + w ] = org_img[ i ];
154 ++i;
155 }
156 }
157 }
158 }
159
160 /*---------------------------------------------------------------------------*
161 Name: TwlMain
162
163 Description: Main.
164
165 Arguments: None.
166
167 Returns: None.
168 *---------------------------------------------------------------------------*/
TwlMain(void)169 void TwlMain(void)
170 {
171 OSHeapHandle handle;
172 char pict_path[TCL_PATH_LEN];
173 void* nstart;
174
175 void* pTableBuf;
176 void* pWorkBuf;
177
178 FSResult fs_result;
179 TCLResult result;
180
181 // TCL accessor
182 TCLAccessor accessor;
183
184 // Search condition object
185 TCLSearchObject search_obj;
186 TCLSortType sort_type = TCL_SORT_TYPE_DATE;
187
188 // Initialization process
189 DEMOInitCommon();
190 DEMOInitVRAM();
191
192 FS_Init( FS_DMA_NOT_USE );
193
194 InitScreen();
195 ClearScreen();
196
197 // GX-related settings
198 GX_SetBankForBG( GX_VRAM_BG_128_A );
199
200 GX_SetGraphicsMode( GX_DISPMODE_GRAPHICS, GX_BGMODE_3, GX_BG0_AS_2D );
201
202 GX_SetVisiblePlane( GX_PLANEMASK_BG3 );
203 G2_SetBG3Priority( 0 );
204 G2_BG3Mosaic( FALSE );
205
206 G2_SetBG3ControlDCBmp( GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000 );
207
208 MI_CpuClearFast( draw_buffer, WIDTH * HEIGHT * sizeof(u16) );
209 GX_LoadBG3Bmp( draw_buffer, 0, WIDTH * HEIGHT * sizeof(u16) );
210
211 // Create heap
212 nstart = OS_InitAlloc( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1 );
213 OS_SetMainArenaLo( nstart );
214
215 handle = OS_CreateHeap( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi() );
216 if (handle < 0)
217 {
218 OS_Panic("ARM9: Fail to create heap...\n");
219 }
220 handle = OS_SetCurrentHeap( OS_ARENA_MAIN, handle );
221
222 // TCL initialization
223 // 32-byte alignment necessary
224 pTableBuf = OS_Alloc( TCL_GetTableBufferSize() );
225 pWorkBuf = OS_Alloc( TCL_GetWorkBufferSize() );
226 if( pTableBuf == NULL || pWorkBuf == NULL )
227 {
228 OS_Panic("Cannot allocate memory!");
229 }
230
231 result = TCL_LoadTable( &accessor,
232 pTableBuf,
233 TCL_GetTableBufferSize(),
234 pWorkBuf,
235 TCL_GetWorkBufferSize(),
236 &fs_result );
237
238 #if 1
239
240 // End the following processes when loading of the management file fails
241
242 switch ( result )
243 {
244 case TCL_RESULT_SUCCESS: break; // Success
245 case TCL_RESULT_ERROR_EXIST_OTHER_FILE:
246 case TCL_RESULT_ERROR_ALREADY_MANAGED:
247 // Error indicating no obstacle to getting a photo
248 OS_TPrintf("failed TCL_LoadTable : %d\n", result );
249 break;
250 default:
251 // For other errors, prompt Nintendo DSi camera startup and end the process
252 //OS_TPrintf ("appropriate text here")
253
254 OS_Panic("failed TCL_LoadTable : %d\n", result );
255 break;
256 }
257
258 #else
259
260 // Try recovering if loading of the management file failed
261
262 switch( result )
263 {
264 case TCL_RESULT_SUCCESS: break; // Success
265 case TCL_RESULT_ERROR_EXIST_OTHER_FILE:
266 case TCL_RESULT_ERROR_ALREADY_MANAGED:
267 // Error indicating no obstacle to getting a photo
268 OS_TPrintf("failed TCL_LoadTable : %d\n", result );
269 break;
270 default:
271 OS_TPrintf("failed TCL_LoadTable : %d\n", result );
272
273 // The management file is recreated because read processing cannot be carried out
274 result = TCL_CreateTable( &accessor,
275 pTableBuf,
276 TCL_GetTableBufferSize(),
277 pWorkBuf,
278 TCL_GetWorkBufferSize(),
279 &fs_result );
280
281 if( result != TCL_RESULT_SUCCESS )
282 {
283 OS_Panic("failed TCL_CreateTable : %d\n", result );
284 }
285 break;
286 }
287
288 #endif
289
290 // Initialize SearchObject
291 TCL_InitSearchObject( &search_obj, TCL_SEARCH_CONDITION_PICTURE );
292
293 // How many photos in all?
294 num_pict = TCL_GetNumPictures( &accessor, &search_obj );
295
296 // Sort the table as conditions indicate
297 TCL_SortTable( &accessor, sort_type );
298
299 Print();
300
301 DEMOStartDisplay();
302
303 // Updates text display
304 UpdateScreen();
305
306 while (1)
307 {
308 // Reading pad information and controls
309 DEMOReadKey();
310
311 if( num_pict != 0 && DEMO_IS_TRIG( PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_R ) )
312 {
313 BOOL success_flag = FALSE;
314
315 // Display thumbnails when the B Button is pressed
316 BOOL thumbnail_flag = DEMO_IS_TRIG( PAD_BUTTON_B );
317
318 BOOL delete_flag = DEMO_IS_TRIG( PAD_BUTTON_R );
319
320 const TCLPictureInfo* pPicInfo = NULL;
321 const TCLMakerNote* pMakerNote = NULL;
322
323 MI_CpuClear( pict_path, TCL_PATH_LEN );
324
325 if( search )
326 {
327 do
328 {
329 draw_id = search_obj.startIdx;
330
331 // Get photo information
332 result = TCL_SearchNextPictureInfo( &accessor,
333 &pPicInfo,
334 &search_obj );
335
336 if( result == TCL_RESULT_ERROR_NO_FIND_PICTURE )
337 {
338 // Initialize SearchObject as one full search has been completed
339 TCL_InitSearchObject( &search_obj, search_obj.condition );
340 OS_TPrintf("finished TCL_SearchNextPicturePath\n" );
341 }
342 } while( result == TCL_RESULT_ERROR_NO_FIND_PICTURE );
343 }
344 else
345 {
346 result = TCL_SearchPictureInfoByIndex( &accessor,
347 &pPicInfo,
348 &search_obj,
349 draw_id );
350 }
351
352 if( result != TCL_RESULT_SUCCESS )
353 {
354 OS_TPrintf("failed TCL_Search* : %d\n", result );
355 }
356 else if( delete_flag )
357 {
358 TCLPictureInfo* pGetPicInfo = NULL;
359 FSResult result;
360
361 // For the test, get the picture's path and then get TCLPictureInfo again.
362 ( void ) TCL_PrintPicturePath( pict_path, TCL_PATH_LEN, pPicInfo );
363 if(TCL_GetPictureInfoFromPath( &accessor, &pGetPicInfo, (const char*)pict_path, (u32)STD_StrLen(pict_path) ) == FALSE)
364 {
365 OS_TPrintf("failed TCL_PrintPictureInfo\n");
366 }
367 else
368 {
369 // Allow picture data to be deleted only if it was created by one of your game titles.
370 // You may also restrict this to only items created by this application.
371 if(TCL_DeletePicture(&accessor, pGetPicInfo, &result) != TCL_RESULT_SUCCESS)
372 OS_TPrintf("failed TCL_DeletePicture\n");
373
374 search_obj.condition = TCL_SEARCH_CONDITION_PICTURE;
375 sort_type = TCL_SORT_TYPE_DATE;
376
377 switch( condition_id )
378 {
379 case 0: break;
380 case 1:
381 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_1;
382 sort_type = TCL_SORT_TYPE_FAVORITE_1;
383 break;
384 case 2:
385 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_2;
386 sort_type = TCL_SORT_TYPE_FAVORITE_2;
387 break;
388 case 3:
389 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_3;
390 sort_type = TCL_SORT_TYPE_FAVORITE_3;
391 break;
392 case 4:
393 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_ALL;
394 sort_type = TCL_SORT_TYPE_FAVORITE_ALL;
395 break;
396 }
397
398 if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition );
399 num_pict = TCL_GetNumPictures( &accessor, &search_obj );
400 TCL_SortTable( &accessor, sort_type );
401 draw_id = 0;
402
403 Print();
404 }
405 }
406 else
407 {
408 FSFile file;
409 u32 size;
410 s32 read_size;
411 s16 width, height;
412 TCLResult decodeResult;
413 u32 decodeOptiion;
414
415 // JPEG buffer
416 u8* pJpegBuf = NULL;
417 u16* pDecodeTmpBuf = NULL;
418
419 if( thumbnail_flag )
420 {
421 width = SSP_JPEG_THUMBNAIL_WIDTH;
422 height = SSP_JPEG_THUMBNAIL_HEIGHT;
423 decodeOptiion = SSP_JPEG_THUMBNAIL | SSP_JPEG_RGB555;
424 }
425 else
426 {
427 width = TCL_JPEG_WIDTH;
428 height = TCL_JPEG_HEIGHT;
429 decodeOptiion = SSP_JPEG_RGB555;
430 }
431
432 // Get the photo path
433 ( void ) TCL_PrintPicturePath( pict_path, TCL_PATH_LEN, pPicInfo );
434
435 // Get photo
436 FS_InitFile( &file );
437 if( FS_OpenFileEx( &file, pict_path, FS_FILEMODE_R ) )
438 {
439 pJpegBuf = (u8*)OS_Alloc( TCL_MAX_JPEG_SIZE );
440
441 // Allocate the necessary memory for whether it is a normal photograph or a thumbnail
442 pDecodeTmpBuf = (u16*)OS_Alloc( width * height * sizeof(u16) );
443
444 if( pJpegBuf == NULL || pDecodeTmpBuf == NULL )
445 {
446 OS_Panic("Cannot allocate memory!");
447 }
448
449 size = FS_GetFileLength( &file );
450 read_size = FS_ReadFile( &file, pJpegBuf, (s32)size );
451
452 if( read_size > 0 )
453 {
454 // JPEG decoding
455 decodeResult = TCL_DecodePicture( pJpegBuf,
456 size,
457 (u8*)pDecodeTmpBuf,
458 width, height,
459 decodeOptiion );
460
461 if( decodeResult == TCL_RESULT_SUCCESS )
462 {
463 // Get manufacturer's notes
464 pMakerNote = ( TCLMakerNote* ) SSP_GetJpegDecoderMakerNoteAddrEx( SSP_MAKERNOTE_PHOTO );
465
466 // Display if image type is same
467 if( TCL_IsSameImageType( pPicInfo, pMakerNote ) != FALSE )
468 {
469 MI_CpuClearFast( draw_buffer, WIDTH * HEIGHT * sizeof(u16) );
470
471 // Shrink to image size
472 DownSampling( pDecodeTmpBuf, width, height,
473 draw_buffer, WIDTH, HEIGHT );
474
475 success_flag = TRUE;
476 }
477 else OS_TPrintf("Not Same Image Type\n");
478 }
479 else OS_TPrintf("failed JPEG Decode %d\n", decodeResult);
480 }
481 else OS_TPrintf("failed FS_ReadFile\n");
482
483 ( void ) FS_CloseFile( &file );
484
485 OS_Free( pJpegBuf );
486 OS_Free( pDecodeTmpBuf );
487 }
488 else OS_TPrintf("failed FS_Open\n");
489 }
490
491 if( !success_flag ) MI_CpuClearFast( draw_buffer, WIDTH * HEIGHT * sizeof(u16) );
492 DC_FlushRange( draw_buffer, WIDTH * HEIGHT * sizeof(u16) );
493
494 Print();
495 }
496 else if( DEMO_IS_TRIG( PAD_BUTTON_X ) )
497 {
498 // Modify search conditions
499 if( ++condition_id > 4 ) condition_id = 0;
500
501 search_obj.condition = TCL_SEARCH_CONDITION_PICTURE;
502 sort_type = TCL_SORT_TYPE_DATE;
503
504 switch( condition_id )
505 {
506 case 0: break;
507 case 1:
508 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_1;
509 sort_type = TCL_SORT_TYPE_FAVORITE_1;
510 break;
511 case 2:
512 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_2;
513 sort_type = TCL_SORT_TYPE_FAVORITE_2;
514 break;
515 case 3:
516 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_3;
517 sort_type = TCL_SORT_TYPE_FAVORITE_3;
518 break;
519 case 4:
520 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_ALL;
521 sort_type = TCL_SORT_TYPE_FAVORITE_ALL;
522 break;
523 }
524
525 if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition );
526 num_pict = TCL_GetNumPictures( &accessor, &search_obj );
527 TCL_SortTable( &accessor, sort_type );
528 draw_id = 0;
529
530 Print();
531 }
532 else if( DEMO_IS_TRIG( PAD_BUTTON_Y ) )
533 {
534 // Modify search method
535 search ^= 1;
536 draw_id = 0;
537
538 if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition );
539 Print();
540 }
541 else if( num_pict != 0 && !search )
542 {
543 // Modify ID of displayed photo
544 if( DEMO_IS_TRIG( PAD_KEY_RIGHT ) )
545 {
546 if( ++draw_id >= num_pict ) draw_id = 0;
547 Print();
548 }
549 else if( DEMO_IS_TRIG( PAD_KEY_LEFT ) )
550 {
551 if( --draw_id < 0 ) draw_id = num_pict - 1;
552 Print();
553 }
554 }
555
556 OS_WaitVBlankIntr();
557
558 // Updates text display
559 UpdateScreen();
560
561 GX_LoadBG3Bmp( draw_buffer, 0, WIDTH * HEIGHT * sizeof(u16) );
562 }
563
564 OS_Free( pTableBuf );
565 OS_Free( pWorkBuf );
566
567 OS_Terminate();
568 }
569