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-10-15#$
14 $Rev: 11095 $
15 $Author: kitase_hirotake $
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 PutScreen(1, 17, 0xff, "L Button > Change FavoriteType" );
100
101 if( search )
102 {
103 PutScreen(1, 2, 0xff, "Iterate Search" );
104 }
105 else
106 {
107 PutScreen(1, 2, 0xff, "Random Search" );
108 PutScreen(1, 18, 0xff, "Left Key > Select Draw Index" );
109 PutScreen(1, 19, 0xff, "Right Key > Select Draw Index" );
110 }
111 }
112
113 /*---------------------------------------------------------------------------*
114 Name: DownSampling
115
116 Description: Size reduction.
117
118 Arguments: org_img: Original image
119 org_wdt: Original image width
120 org_hgt: Original image height
121 new_img: New image
122 new_wdt: New image width
123 new_hgt: New image height
124
125 Returns: None.
126 *---------------------------------------------------------------------------*/
DownSampling(const u16 * org_img,int org_wdt,int org_hgt,u16 * new_img,int new_wdt,int new_hgt)127 void DownSampling( const u16* org_img, int org_wdt, int org_hgt,
128 u16* new_img, int new_wdt, int new_hgt )
129 {
130 int h, w, i = 0;
131
132 if( org_wdt == TCL_JPEG_WIDTH )
133 {
134 // Normal photograph
135 for ( h = 0; h < new_hgt; ++h )
136 {
137 for ( w = 0; w < new_wdt; ++w )
138 {
139 new_img[ h * new_wdt + w ] = org_img[ ( h * org_hgt / new_hgt ) * org_wdt +
140 w * org_wdt / new_wdt ];
141 }
142 }
143 }
144 else
145 {
146 // Thumbnail
147 u16* thumb_img = &new_img[ ( HEIGHT - SSP_JPEG_THUMBNAIL_HEIGHT ) / 2 * WIDTH +
148 ( WIDTH - SSP_JPEG_THUMBNAIL_WIDTH ) / 2 ];
149
150 for ( h = 0; h < org_hgt; ++h )
151 {
152 for ( w = 0; w < org_wdt; ++w )
153 {
154 thumb_img[ h * new_wdt + w ] = org_img[ i ];
155 ++i;
156 }
157 }
158 }
159 }
160
161 /*---------------------------------------------------------------------------*
162 Name: TwlMain
163
164 Description: Main.
165
166 Arguments: None.
167
168 Returns: None.
169 *---------------------------------------------------------------------------*/
TwlMain(void)170 void TwlMain(void)
171 {
172 OSHeapHandle handle;
173 char pict_path[TCL_PATH_LEN];
174 void* nstart;
175
176 void* pTableBuf;
177 void* pWorkBuf;
178
179 FSResult fs_result;
180 TCLResult result;
181
182 // TCL accessor
183 TCLAccessor accessor;
184
185 // Search condition object
186 TCLSearchObject search_obj;
187 TCLSortType sort_type = TCL_SORT_TYPE_DATE;
188
189 // Initialization process
190 DEMOInitCommon();
191 DEMOInitVRAM();
192
193 FS_Init( FS_DMA_NOT_USE );
194
195 InitScreen();
196 ClearScreen();
197
198 // GX-related settings
199 GX_SetBankForBG( GX_VRAM_BG_128_A );
200
201 GX_SetGraphicsMode( GX_DISPMODE_GRAPHICS, GX_BGMODE_3, GX_BG0_AS_2D );
202
203 GX_SetVisiblePlane( GX_PLANEMASK_BG3 );
204 G2_SetBG3Priority( 0 );
205 G2_BG3Mosaic( FALSE );
206
207 G2_SetBG3ControlDCBmp( GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000 );
208
209 MI_CpuClearFast( draw_buffer, WIDTH * HEIGHT * sizeof(u16) );
210 GX_LoadBG3Bmp( draw_buffer, 0, WIDTH * HEIGHT * sizeof(u16) );
211
212 // Create heap
213 nstart = OS_InitAlloc( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1 );
214 OS_SetMainArenaLo( nstart );
215
216 handle = OS_CreateHeap( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi() );
217 if (handle < 0)
218 {
219 OS_Panic("ARM9: Fail to create heap...\n");
220 }
221 handle = OS_SetCurrentHeap( OS_ARENA_MAIN, handle );
222
223 // TCL initialization
224 // 32-byte alignment necessary
225 pTableBuf = OS_Alloc( TCL_GetTableBufferSize() );
226 pWorkBuf = OS_Alloc( TCL_GetWorkBufferSize() );
227 if( pTableBuf == NULL || pWorkBuf == NULL )
228 {
229 OS_Panic("Cannot allocate memory!");
230 }
231
232 result = TCL_LoadTable( &accessor,
233 pTableBuf,
234 TCL_GetTableBufferSize(),
235 pWorkBuf,
236 TCL_GetWorkBufferSize(),
237 &fs_result );
238
239 #if 1
240
241 // End the following processes when loading of the management file fails
242
243 switch ( result )
244 {
245 case TCL_RESULT_SUCCESS: break; // Success
246 case TCL_RESULT_ERROR_EXIST_OTHER_FILE:
247 case TCL_RESULT_ERROR_ALREADY_MANAGED:
248 // Error indicating no obstacle to getting a photo
249 OS_TPrintf("failed TCL_LoadTable : %d\n", result );
250 break;
251 default:
252 // For other errors, prompt Nintendo DSi camera startup and end the process
253 //OS_TPrintf ("appropriate text here")
254
255 OS_Panic("failed TCL_LoadTable : %d\n", result );
256 break;
257 }
258
259 #else
260
261 // Try recovering if loading of the management file failed
262
263 switch( result )
264 {
265 case TCL_RESULT_SUCCESS: break; // Success
266 case TCL_RESULT_ERROR_EXIST_OTHER_FILE:
267 case TCL_RESULT_ERROR_ALREADY_MANAGED:
268 // Error indicating no obstacle to getting a photo
269 OS_TPrintf("failed TCL_LoadTable : %d\n", result );
270 break;
271 default:
272 OS_TPrintf("failed TCL_LoadTable : %d\n", result );
273
274 // The management file is recreated because read processing cannot be carried out
275 result = TCL_CreateTable( &accessor,
276 pTableBuf,
277 TCL_GetTableBufferSize(),
278 pWorkBuf,
279 TCL_GetWorkBufferSize(),
280 &fs_result );
281
282 if( result != TCL_RESULT_SUCCESS )
283 {
284 OS_Panic("failed TCL_CreateTable : %d\n", result );
285 }
286 break;
287 }
288
289 #endif
290
291 // Initialize SearchObject
292 TCL_InitSearchObject( &search_obj, TCL_SEARCH_CONDITION_PICTURE );
293
294 // How many photos in all?
295 num_pict = TCL_GetNumPictures( &accessor, &search_obj );
296
297 // Sort the table as conditions indicate
298 TCL_SortTable( &accessor, sort_type );
299
300 Print();
301
302 DEMOStartDisplay();
303
304 // Updates text display
305 UpdateScreen();
306
307 while (1)
308 {
309 // Reading pad information and controls
310 DEMOReadKey();
311
312 if( num_pict != 0 && DEMO_IS_TRIG( PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_R | PAD_BUTTON_L ) )
313 {
314 BOOL success_flag = FALSE;
315
316 // Display thumbnails when the B Button is pressed
317 BOOL thumbnail_flag = DEMO_IS_TRIG( PAD_BUTTON_B );
318
319 BOOL delete_flag = DEMO_IS_TRIG( PAD_BUTTON_R );
320
321 BOOL favorite_flag = DEMO_IS_TRIG( PAD_BUTTON_L );
322
323 const TCLPictureInfo* pPicInfo = NULL;
324 const TCLMakerNote* pMakerNote = NULL;
325
326 MI_CpuClear( pict_path, TCL_PATH_LEN );
327
328 if( search )
329 {
330 do
331 {
332 draw_id = search_obj.startIdx;
333
334 // Get photo information
335 result = TCL_SearchNextPictureInfo( &accessor,
336 &pPicInfo,
337 &search_obj );
338
339 if( result == TCL_RESULT_ERROR_NO_FIND_PICTURE )
340 {
341 // Initialize SearchObject as one full search has been completed
342 TCL_InitSearchObject( &search_obj, search_obj.condition );
343 OS_TPrintf("finished TCL_SearchNextPicturePath\n" );
344 }
345 } while( result == TCL_RESULT_ERROR_NO_FIND_PICTURE );
346 }
347 else
348 {
349 result = TCL_SearchPictureInfoByIndex( &accessor,
350 &pPicInfo,
351 &search_obj,
352 draw_id );
353 }
354
355 if( result != TCL_RESULT_SUCCESS )
356 {
357 OS_TPrintf("failed TCL_Search* : %d\n", result );
358 }
359 else if( delete_flag )
360 {
361 TCLPictureInfo* pGetPicInfo = NULL;
362 FSResult result;
363
364 // For the test, get the picture's path and then get TCLPictureInfo again.
365 ( void ) TCL_PrintPicturePath( pict_path, TCL_PATH_LEN, pPicInfo );
366 if(TCL_GetPictureInfoFromPath( &accessor, &pGetPicInfo, (const char*)pict_path, (u32)STD_StrLen(pict_path) ) == FALSE)
367 {
368 OS_TPrintf("failed TCL_PrintPictureInfo\n");
369 }
370 else
371 {
372 // Allow picture data to be deleted only if it was created by one of your game titles.
373 // You may also restrict this to only items created by this application.
374 if(TCL_DeletePicture(&accessor, pGetPicInfo, &result) != TCL_RESULT_SUCCESS)
375 OS_TPrintf("failed TCL_DeletePicture\n");
376
377 search_obj.condition = TCL_SEARCH_CONDITION_PICTURE;
378 sort_type = TCL_SORT_TYPE_DATE;
379
380 switch( condition_id )
381 {
382 case 0: break;
383 case 1:
384 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_1;
385 sort_type = TCL_SORT_TYPE_FAVORITE_1;
386 break;
387 case 2:
388 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_2;
389 sort_type = TCL_SORT_TYPE_FAVORITE_2;
390 break;
391 case 3:
392 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_3;
393 sort_type = TCL_SORT_TYPE_FAVORITE_3;
394 break;
395 case 4:
396 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_ALL;
397 sort_type = TCL_SORT_TYPE_FAVORITE_ALL;
398 break;
399 }
400
401 if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition );
402 num_pict = TCL_GetNumPictures( &accessor, &search_obj );
403 TCL_SortTable( &accessor, sort_type );
404 draw_id = 0;
405
406 Print();
407 }
408 }
409 else if( favorite_flag )
410 {
411 TCLPictureInfo* pChangePicInfo = (TCLPictureInfo*)pPicInfo;
412 TCLFavoriteType nextFavoriteType;
413 FSResult result;
414
415 switch ( pChangePicInfo->favoriteType )
416 {
417 case TCL_FAVORITE_TYPE_NONE:
418 nextFavoriteType = TCL_FAVORITE_TYPE_1;
419 break;
420 case TCL_FAVORITE_TYPE_1:
421 nextFavoriteType = TCL_FAVORITE_TYPE_2;
422 break;
423 case TCL_FAVORITE_TYPE_2:
424 nextFavoriteType = TCL_FAVORITE_TYPE_3;
425 break;
426 case TCL_FAVORITE_TYPE_3:
427 default:
428 nextFavoriteType = TCL_FAVORITE_TYPE_NONE;
429 break;
430 }
431
432 OS_TPrintf("change favoriteType %d -> %d\n", pChangePicInfo->favoriteType, nextFavoriteType);
433
434 if(TCL_ChangePictureFavoriteType(&accessor, pChangePicInfo, nextFavoriteType, &result) != TCL_RESULT_SUCCESS)
435 OS_TPrintf("failed TCL_ChangePictureFavoriteType\n");
436
437 search_obj.condition = TCL_SEARCH_CONDITION_PICTURE;
438 sort_type = TCL_SORT_TYPE_DATE;
439
440 switch( condition_id )
441 {
442 case 0: break;
443 case 1:
444 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_1;
445 sort_type = TCL_SORT_TYPE_FAVORITE_1;
446 break;
447 case 2:
448 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_2;
449 sort_type = TCL_SORT_TYPE_FAVORITE_2;
450 break;
451 case 3:
452 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_3;
453 sort_type = TCL_SORT_TYPE_FAVORITE_3;
454 break;
455 case 4:
456 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_ALL;
457 sort_type = TCL_SORT_TYPE_FAVORITE_ALL;
458 break;
459 }
460
461 if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition );
462 num_pict = TCL_GetNumPictures( &accessor, &search_obj );
463 TCL_SortTable( &accessor, sort_type );
464 draw_id = 0;
465
466 Print();
467 }
468 else
469 {
470 FSFile file;
471 u32 size;
472 s32 read_size;
473 s16 width, height;
474 TCLResult decodeResult;
475 u32 decodeOptiion;
476
477 // JPEG buffer
478 u8* pJpegBuf = NULL;
479 u16* pDecodeTmpBuf = NULL;
480
481 if( thumbnail_flag )
482 {
483 width = SSP_JPEG_THUMBNAIL_WIDTH;
484 height = SSP_JPEG_THUMBNAIL_HEIGHT;
485 decodeOptiion = SSP_JPEG_THUMBNAIL | SSP_JPEG_RGB555;
486 }
487 else
488 {
489 width = TCL_JPEG_WIDTH;
490 height = TCL_JPEG_HEIGHT;
491 decodeOptiion = SSP_JPEG_RGB555;
492 }
493
494 // Get the photo path
495 ( void ) TCL_PrintPicturePath( pict_path, TCL_PATH_LEN, pPicInfo );
496
497 // Get photo
498 FS_InitFile( &file );
499 if( FS_OpenFileEx( &file, pict_path, FS_FILEMODE_R ) )
500 {
501 pJpegBuf = (u8*)OS_Alloc( TCL_MAX_JPEG_SIZE );
502
503 // Allocate the necessary memory for whether it is a normal photograph or a thumbnail
504 pDecodeTmpBuf = (u16*)OS_Alloc( width * height * sizeof(u16) );
505
506 if( pJpegBuf == NULL || pDecodeTmpBuf == NULL )
507 {
508 OS_Panic("Cannot allocate memory!");
509 }
510
511 size = FS_GetFileLength( &file );
512 read_size = FS_ReadFile( &file, pJpegBuf, (s32)size );
513
514 if( read_size > 0 )
515 {
516 // JPEG decoding
517 decodeResult = TCL_DecodePicture( pJpegBuf,
518 size,
519 (u8*)pDecodeTmpBuf,
520 width, height,
521 decodeOptiion );
522
523 if( decodeResult == TCL_RESULT_SUCCESS )
524 {
525 // Get manufacturer's notes
526 pMakerNote = ( TCLMakerNote* ) SSP_GetJpegDecoderMakerNoteAddrEx( SSP_MAKERNOTE_PHOTO );
527
528 // Display if image type is same
529 if( TCL_IsSameImageType( pPicInfo, pMakerNote ) != FALSE )
530 {
531 MI_CpuClearFast( draw_buffer, WIDTH * HEIGHT * sizeof(u16) );
532
533 // Shrink to image size
534 DownSampling( pDecodeTmpBuf, width, height,
535 draw_buffer, WIDTH, HEIGHT );
536
537 success_flag = TRUE;
538 }
539 else OS_TPrintf("Not Same Image Type\n");
540 }
541 else OS_TPrintf("failed JPEG Decode %d\n", decodeResult);
542 }
543 else OS_TPrintf("failed FS_ReadFile\n");
544
545 ( void ) FS_CloseFile( &file );
546
547 OS_Free( pJpegBuf );
548 OS_Free( pDecodeTmpBuf );
549 }
550 else OS_TPrintf("failed FS_Open\n");
551 }
552
553 if( !success_flag ) MI_CpuClearFast( draw_buffer, WIDTH * HEIGHT * sizeof(u16) );
554 DC_FlushRange( draw_buffer, WIDTH * HEIGHT * sizeof(u16) );
555
556 Print();
557 }
558 else if( DEMO_IS_TRIG( PAD_BUTTON_X ) )
559 {
560 // Modify search conditions
561 if( ++condition_id > 4 ) condition_id = 0;
562
563 search_obj.condition = TCL_SEARCH_CONDITION_PICTURE;
564 sort_type = TCL_SORT_TYPE_DATE;
565
566 switch( condition_id )
567 {
568 case 0: break;
569 case 1:
570 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_1;
571 sort_type = TCL_SORT_TYPE_FAVORITE_1;
572 break;
573 case 2:
574 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_2;
575 sort_type = TCL_SORT_TYPE_FAVORITE_2;
576 break;
577 case 3:
578 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_3;
579 sort_type = TCL_SORT_TYPE_FAVORITE_3;
580 break;
581 case 4:
582 search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_ALL;
583 sort_type = TCL_SORT_TYPE_FAVORITE_ALL;
584 break;
585 }
586
587 if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition );
588 num_pict = TCL_GetNumPictures( &accessor, &search_obj );
589 TCL_SortTable( &accessor, sort_type );
590 draw_id = 0;
591
592 Print();
593 }
594 else if( DEMO_IS_TRIG( PAD_BUTTON_Y ) )
595 {
596 // Modify search method
597 search ^= 1;
598 draw_id = 0;
599
600 if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition );
601 Print();
602 }
603 else if( num_pict != 0 && !search )
604 {
605 // Modify ID of displayed photo
606 if( DEMO_IS_TRIG( PAD_KEY_RIGHT ) )
607 {
608 if( ++draw_id >= num_pict ) draw_id = 0;
609 Print();
610 }
611 else if( DEMO_IS_TRIG( PAD_KEY_LEFT ) )
612 {
613 if( --draw_id < 0 ) draw_id = num_pict - 1;
614 Print();
615 }
616 }
617
618 OS_WaitVBlankIntr();
619
620 // Updates text display
621 UpdateScreen();
622
623 GX_LoadBG3Bmp( draw_buffer, 0, WIDTH * HEIGHT * sizeof(u16) );
624 }
625
626 OS_Free( pTableBuf );
627 OS_Free( pWorkBuf );
628
629 OS_Terminate();
630 }
631