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