/*---------------------------------------------------------------------------* Project: TwlSDK - tcl - demos.TWL - tcl-1 File: main.c Copyright 2008-2009 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2009-06-04#$ $Rev: 10698 $ $Author: okubata_ryoma $ *---------------------------------------------------------------------------*/ #include #include #include #include #include "DEMO.h" #include "screen.h" /*---------------------------------------------------------------------------* Constant Definitions *---------------------------------------------------------------------------*/ #define WIDTH 256 // Image width #define HEIGHT 192 // Image height /*---------------------------------------------------------------------------* Internal Functions and Definitions *---------------------------------------------------------------------------*/ void VBlankIntr(void); void Print(void); void DownSampling( const u16* org_img, int org_wdt, int org_hgt, u16* new_img, int new_wdt, int new_hgt ); int GetR ( u16 color ); int GetG ( u16 color ); int GetB ( u16 color ); /*---------------------------------------------------------------------------* Internal Variable Definitions *---------------------------------------------------------------------------*/ // Buffer storing images static u16 draw_buffer[ WIDTH * HEIGHT ] ATTRIBUTE_ALIGN(32); int condition_id = 0; int search = 0; int num_pict = 0; int draw_id = 0; // Get the color value (from 0 to 31) int GetR ( u16 color ) { return (color & GX_RGB_R_MASK) >> GX_RGB_R_SHIFT; } int GetG ( u16 color ) { return (color & GX_RGB_G_MASK) >> GX_RGB_G_SHIFT; } int GetB ( u16 color ) { return (color & GX_RGB_B_MASK) >> GX_RGB_B_SHIFT; } /*---------------------------------------------------------------------------* Name: VBlankIntr Description: V-Blank interrupt handler. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void VBlankIntr(void) { OS_SetIrqCheckFlag( OS_IE_V_BLANK ); } /*---------------------------------------------------------------------------* Name: Print Description: Renders debug information. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void Print(void) { const char* condition_name[] = { "All Picture", "Favorite1", "Favorite2", "Favorite3", "FavoriteAll" }; ClearScreen(); PutScreen(0, 0, 0xff, "TCL-1 Search Picture Demo"); PutScreen(2, 4, 0xff, "TCL Condition : %s", condition_name[condition_id] ); PutScreen(2, 5, 0xff, "Draw Index : %d", draw_id ); PutScreen(2, 7, 0xff, "Num Pictures : %d", num_pict ); PutScreen(1, 12, 0xff, "A Button > Draw Picture" ); PutScreen(1, 13, 0xff, "B Button > Draw Thumbnail" ); PutScreen(1, 14, 0xff, "X Button > Select Condition" ); PutScreen(1, 15, 0xff, "Y Button > Change Search Method" ); PutScreen(1, 16, 0xff, "R Button > Delete Picture" ); if( search ) { PutScreen(1, 2, 0xff, "Iterate Search" ); } else { PutScreen(1, 2, 0xff, "Random Search" ); PutScreen(1, 17, 0xff, "Left Key > Select Draw Index" ); PutScreen(1, 18, 0xff, "Right Key > Select Draw Index" ); } } /*---------------------------------------------------------------------------* Name: DownSampling Description: Size reduction. Arguments: org_img: Original image org_wdt: Original image width org_hgt: Original image height new_img: New image new_wdt: New image width new_hgt: New image height Returns: None. *---------------------------------------------------------------------------*/ void DownSampling( const u16* org_img, int org_wdt, int org_hgt, u16* new_img, int new_wdt, int new_hgt ) { int h, w, i = 0; if( org_wdt == TCL_JPEG_WIDTH ) { // Normal photograph for ( h = 0; h < new_hgt; ++h ) { for ( w = 0; w < new_wdt; ++w ) { new_img[ h * new_wdt + w ] = org_img[ ( h * org_hgt / new_hgt ) * org_wdt + w * org_wdt / new_wdt ]; } } } else { // Thumbnail u16* thumb_img = &new_img[ ( HEIGHT - SSP_JPEG_THUMBNAIL_HEIGHT ) / 2 * WIDTH + ( WIDTH - SSP_JPEG_THUMBNAIL_WIDTH ) / 2 ]; for ( h = 0; h < org_hgt; ++h ) { for ( w = 0; w < org_wdt; ++w ) { thumb_img[ h * new_wdt + w ] = org_img[ i ]; ++i; } } } } /*---------------------------------------------------------------------------* Name: TwlMain Description: Main. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void TwlMain(void) { OSHeapHandle handle; char pict_path[TCL_PATH_LEN]; void* nstart; void* pTableBuf; void* pWorkBuf; FSResult fs_result; TCLResult result; // TCL accessor TCLAccessor accessor; // Search condition object TCLSearchObject search_obj; TCLSortType sort_type = TCL_SORT_TYPE_DATE; // Initialization process DEMOInitCommon(); DEMOInitVRAM(); FS_Init( FS_DMA_NOT_USE ); InitScreen(); ClearScreen(); // GX-related settings GX_SetBankForBG( GX_VRAM_BG_128_A ); GX_SetGraphicsMode( GX_DISPMODE_GRAPHICS, GX_BGMODE_3, GX_BG0_AS_2D ); GX_SetVisiblePlane( GX_PLANEMASK_BG3 ); G2_SetBG3Priority( 0 ); G2_BG3Mosaic( FALSE ); G2_SetBG3ControlDCBmp( GX_BG_SCRSIZE_DCBMP_256x256, GX_BG_AREAOVER_XLU, GX_BG_BMPSCRBASE_0x00000 ); MI_CpuClearFast( draw_buffer, WIDTH * HEIGHT * sizeof(u16) ); GX_LoadBG3Bmp( draw_buffer, 0, WIDTH * HEIGHT * sizeof(u16) ); // Create heap nstart = OS_InitAlloc( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi(), 1 ); OS_SetMainArenaLo( nstart ); handle = OS_CreateHeap( OS_ARENA_MAIN, OS_GetMainArenaLo(), OS_GetMainArenaHi() ); if (handle < 0) { OS_Panic("ARM9: Fail to create heap...\n"); } handle = OS_SetCurrentHeap( OS_ARENA_MAIN, handle ); // TCL initialization // 32-byte alignment necessary pTableBuf = OS_Alloc( TCL_GetTableBufferSize() ); pWorkBuf = OS_Alloc( TCL_GetWorkBufferSize() ); if( pTableBuf == NULL || pWorkBuf == NULL ) { OS_Panic("Cannot allocate memory!"); } result = TCL_LoadTable( &accessor, pTableBuf, TCL_GetTableBufferSize(), pWorkBuf, TCL_GetWorkBufferSize(), &fs_result ); #if 1 // End the following processes when loading of the management file fails switch ( result ) { case TCL_RESULT_SUCCESS: break; // Success case TCL_RESULT_ERROR_EXIST_OTHER_FILE: case TCL_RESULT_ERROR_ALREADY_MANAGED: // Error indicating no obstacle to getting a photo OS_TPrintf("failed TCL_LoadTable : %d\n", result ); break; default: // For other errors, prompt Nintendo DSi camera startup and end the process //OS_TPrintf ("appropriate text here") OS_Panic("failed TCL_LoadTable : %d\n", result ); break; } #else // Try recovering if loading of the management file failed switch( result ) { case TCL_RESULT_SUCCESS: break; // Success case TCL_RESULT_ERROR_EXIST_OTHER_FILE: case TCL_RESULT_ERROR_ALREADY_MANAGED: // Error indicating no obstacle to getting a photo OS_TPrintf("failed TCL_LoadTable : %d\n", result ); break; default: OS_TPrintf("failed TCL_LoadTable : %d\n", result ); // The management file is recreated because read processing cannot be carried out result = TCL_CreateTable( &accessor, pTableBuf, TCL_GetTableBufferSize(), pWorkBuf, TCL_GetWorkBufferSize(), &fs_result ); if( result != TCL_RESULT_SUCCESS ) { OS_Panic("failed TCL_CreateTable : %d\n", result ); } break; } #endif // Initialize SearchObject TCL_InitSearchObject( &search_obj, TCL_SEARCH_CONDITION_PICTURE ); // How many photos in all? num_pict = TCL_GetNumPictures( &accessor, &search_obj ); // Sort the table as conditions indicate TCL_SortTable( &accessor, sort_type ); Print(); DEMOStartDisplay(); // Updates text display UpdateScreen(); while (1) { // Reading pad information and controls DEMOReadKey(); if( num_pict != 0 && DEMO_IS_TRIG( PAD_BUTTON_A | PAD_BUTTON_B | PAD_BUTTON_R ) ) { BOOL success_flag = FALSE; // Display thumbnails when the B Button is pressed BOOL thumbnail_flag = DEMO_IS_TRIG( PAD_BUTTON_B ); BOOL delete_flag = DEMO_IS_TRIG( PAD_BUTTON_R ); const TCLPictureInfo* pPicInfo = NULL; const TCLMakerNote* pMakerNote = NULL; MI_CpuClear( pict_path, TCL_PATH_LEN ); if( search ) { do { draw_id = search_obj.startIdx; // Get photo information result = TCL_SearchNextPictureInfo( &accessor, &pPicInfo, &search_obj ); if( result == TCL_RESULT_ERROR_NO_FIND_PICTURE ) { // Initialize SearchObject as one full search has been completed TCL_InitSearchObject( &search_obj, search_obj.condition ); OS_TPrintf("finished TCL_SearchNextPicturePath\n" ); } } while( result == TCL_RESULT_ERROR_NO_FIND_PICTURE ); } else { result = TCL_SearchPictureInfoByIndex( &accessor, &pPicInfo, &search_obj, draw_id ); } if( result != TCL_RESULT_SUCCESS ) { OS_TPrintf("failed TCL_Search* : %d\n", result ); } else if( delete_flag ) { TCLPictureInfo* pGetPicInfo = NULL; FSResult result; // For the test, get the picture's path and then get TCLPictureInfo again. ( void ) TCL_PrintPicturePath( pict_path, TCL_PATH_LEN, pPicInfo ); if(TCL_GetPictureInfoFromPath( &accessor, &pGetPicInfo, (const char*)pict_path, (u32)STD_StrLen(pict_path) ) == FALSE) { OS_TPrintf("failed TCL_PrintPictureInfo\n"); } else { // Allow picture data to be deleted only if it was created by one of your game titles. // You may also restrict this to only items created by this application. if(TCL_DeletePicture(&accessor, pGetPicInfo, &result) != TCL_RESULT_SUCCESS) OS_TPrintf("failed TCL_DeletePicture\n"); search_obj.condition = TCL_SEARCH_CONDITION_PICTURE; sort_type = TCL_SORT_TYPE_DATE; switch( condition_id ) { case 0: break; case 1: search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_1; sort_type = TCL_SORT_TYPE_FAVORITE_1; break; case 2: search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_2; sort_type = TCL_SORT_TYPE_FAVORITE_2; break; case 3: search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_3; sort_type = TCL_SORT_TYPE_FAVORITE_3; break; case 4: search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_ALL; sort_type = TCL_SORT_TYPE_FAVORITE_ALL; break; } if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition ); num_pict = TCL_GetNumPictures( &accessor, &search_obj ); TCL_SortTable( &accessor, sort_type ); draw_id = 0; Print(); } } else { FSFile file; u32 size; s32 read_size; s16 width, height; TCLResult decodeResult; u32 decodeOptiion; // JPEG buffer u8* pJpegBuf = NULL; u16* pDecodeTmpBuf = NULL; if( thumbnail_flag ) { width = SSP_JPEG_THUMBNAIL_WIDTH; height = SSP_JPEG_THUMBNAIL_HEIGHT; decodeOptiion = SSP_JPEG_THUMBNAIL | SSP_JPEG_RGB555; } else { width = TCL_JPEG_WIDTH; height = TCL_JPEG_HEIGHT; decodeOptiion = SSP_JPEG_RGB555; } // Get the photo path ( void ) TCL_PrintPicturePath( pict_path, TCL_PATH_LEN, pPicInfo ); // Get photo FS_InitFile( &file ); if( FS_OpenFileEx( &file, pict_path, FS_FILEMODE_R ) ) { pJpegBuf = (u8*)OS_Alloc( TCL_MAX_JPEG_SIZE ); // Allocate the necessary memory for whether it is a normal photograph or a thumbnail pDecodeTmpBuf = (u16*)OS_Alloc( width * height * sizeof(u16) ); if( pJpegBuf == NULL || pDecodeTmpBuf == NULL ) { OS_Panic("Cannot allocate memory!"); } size = FS_GetFileLength( &file ); read_size = FS_ReadFile( &file, pJpegBuf, (s32)size ); if( read_size > 0 ) { // JPEG decoding decodeResult = TCL_DecodePicture( pJpegBuf, size, (u8*)pDecodeTmpBuf, width, height, decodeOptiion ); if( decodeResult == TCL_RESULT_SUCCESS ) { // Get manufacturer's notes pMakerNote = ( TCLMakerNote* ) SSP_GetJpegDecoderMakerNoteAddrEx( SSP_MAKERNOTE_PHOTO ); // Display if image type is same if( TCL_IsSameImageType( pPicInfo, pMakerNote ) != FALSE ) { MI_CpuClearFast( draw_buffer, WIDTH * HEIGHT * sizeof(u16) ); // Shrink to image size DownSampling( pDecodeTmpBuf, width, height, draw_buffer, WIDTH, HEIGHT ); success_flag = TRUE; } else OS_TPrintf("Not Same Image Type\n"); } else OS_TPrintf("failed JPEG Decode %d\n", decodeResult); } else OS_TPrintf("failed FS_ReadFile\n"); ( void ) FS_CloseFile( &file ); OS_Free( pJpegBuf ); OS_Free( pDecodeTmpBuf ); } else OS_TPrintf("failed FS_Open\n"); } if( !success_flag ) MI_CpuClearFast( draw_buffer, WIDTH * HEIGHT * sizeof(u16) ); DC_FlushRange( draw_buffer, WIDTH * HEIGHT * sizeof(u16) ); Print(); } else if( DEMO_IS_TRIG( PAD_BUTTON_X ) ) { // Modify search conditions if( ++condition_id > 4 ) condition_id = 0; search_obj.condition = TCL_SEARCH_CONDITION_PICTURE; sort_type = TCL_SORT_TYPE_DATE; switch( condition_id ) { case 0: break; case 1: search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_1; sort_type = TCL_SORT_TYPE_FAVORITE_1; break; case 2: search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_2; sort_type = TCL_SORT_TYPE_FAVORITE_2; break; case 3: search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_3; sort_type = TCL_SORT_TYPE_FAVORITE_3; break; case 4: search_obj.condition |= TCL_SEARCH_CONDITION_FAVORITE_ALL; sort_type = TCL_SORT_TYPE_FAVORITE_ALL; break; } if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition ); num_pict = TCL_GetNumPictures( &accessor, &search_obj ); TCL_SortTable( &accessor, sort_type ); draw_id = 0; Print(); } else if( DEMO_IS_TRIG( PAD_BUTTON_Y ) ) { // Modify search method search ^= 1; draw_id = 0; if( search ) TCL_InitSearchObject( &search_obj, search_obj.condition ); Print(); } else if( num_pict != 0 && !search ) { // Modify ID of displayed photo if( DEMO_IS_TRIG( PAD_KEY_RIGHT ) ) { if( ++draw_id >= num_pict ) draw_id = 0; Print(); } else if( DEMO_IS_TRIG( PAD_KEY_LEFT ) ) { if( --draw_id < 0 ) draw_id = num_pict - 1; Print(); } } OS_WaitVBlankIntr(); // Updates text display UpdateScreen(); GX_LoadBG3Bmp( draw_buffer, 0, WIDTH * HEIGHT * sizeof(u16) ); } OS_Free( pTableBuf ); OS_Free( pWorkBuf ); OS_Terminate(); }