1 /*---------------------------------------------------------------------------*
2 Project: Dolphin/Revolution cx demo
3 File: cx_uncompress_stream.c
4
5 Copyright 2006 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 /*---------------------------------------------------------------------------*
14 cx_uncompress
15 data uncompress demo
16 *---------------------------------------------------------------------------*/
17
18 #include <demo.h>
19 #include <revolution/cx.h>
20
21 // for camera
22 typedef struct
23 {
24 Vec location;
25 Vec up;
26 Vec target;
27 f32 left;
28 f32 top;
29 f32 znear;
30 f32 zfar;
31 } CameraConfig;
32
33 typedef struct
34 {
35 CameraConfig cfg;
36 Mtx view;
37 Mtx44 proj;
38 } MyCameraObj;
39
40 // for entire scene control
41 typedef struct
42 {
43 MyCameraObj cam;
44 u32 texNum[ 4 ];
45 } MySceneCtrlObj;
46
47
48 void main ( void );
49 static void DrawInit ( MySceneCtrlObj* sc );
50 static void DrawTick ( MySceneCtrlObj* sc );
51 static void AnimTick ( MySceneCtrlObj* sc );
52 static void SetCamera ( MyCameraObj* cam );
53 static void PrintIntro( void );
54 static void DrawRect ( void );
55
56 static void* LoadTexData ( const char* path );
57 static void* LoadTexDataLZ ( const char* path );
58 static void* LoadTexDataRL ( const char* path );
59 static void* LoadTexDataHuff( const char* path );
60
61
62 /*---------------------------------------------------------------------------*
63 Camera configuration
64 *---------------------------------------------------------------------------*/
65 static CameraConfig DEFAULT_CAMERA =
66 {
67 { 0.0F, 0.0F, 100.0F }, // location
68 { 0.0F, 1.0F, 0.0F }, // up :
69 { 0.0F, 0.0F, 0.0F }, // target
70 -320.0F, // left
71 -224.0F, // top (note: was 240, now adjusted for over scan)
72 0.1F, // near
73 2000.0F // far
74 };
75
76
77 /*---------------------------------------------------------------------------*
78 Data for views and parameters
79 *---------------------------------------------------------------------------*/
80
81 /*---------------------------------------------------------------------------*
82 Global variables
83 *---------------------------------------------------------------------------*/
84 static TPLPalettePtr sMyTplObj[ 4 ] = { NULL, NULL, NULL, NULL }; // A pointer to the texture/palette data.
85
86 /* double buffer used for streaming decompression (to load and decompress in parallel)*/
87 #define BUF_SIZE 0x4000
88 static u8 sReadBuf[ 2 ][ BUF_SIZE ] ATTRIBUTE_ALIGN(32);
89
90
91 /*---------------------------------------------------------------------------*
92 Application main loop
93 *---------------------------------------------------------------------------*/
main(void)94 void main( void )
95 {
96 MySceneCtrlObj sceneCtrl;
97
98 DEMOInit( NULL ); // OS, Pad, GX and VI initialization
99
100 PrintIntro();
101
102 DrawInit( &sceneCtrl ); // camera initialization and loading of texture pattern from DVD
103 // compressed data is loaded as streaming decompression takes place
104
105 while ( !(DEMOPadGetButton( 0 ) & PAD_BUTTON_MENU) )
106 {
107 DEMOBeforeRender();
108 DrawTick( &sceneCtrl ); // render process for each frame
109 DEMODoneRender();
110 DEMOPadRead();
111 AnimTick( &sceneCtrl ); // pad input process for each frame
112 }
113
114 OSHalt("End of demo");
115 }
116
117
118 /*---------------------------------------------------------------------------*
119 Name: SetCamera
120
121 Description: Calculates and sets the view and projection matrices.
122
123 Arguments: cam : a pointer to MyCameraObj
124
125 Returns: None.
126 *---------------------------------------------------------------------------*/
SetCamera(MyCameraObj * cam)127 static void SetCamera( MyCameraObj* cam )
128 {
129 MTXLookAt( cam->view,
130 &cam->cfg.location,
131 &cam->cfg.up,
132 &cam->cfg.target );
133
134 MTXOrtho( cam->proj,
135 cam->cfg.top,
136 -(cam->cfg.top),
137 cam->cfg.left,
138 -(cam->cfg.left),
139 cam->cfg.znear,
140 cam->cfg.zfar );
141
142 GXSetProjection( cam->proj, GX_ORTHOGRAPHIC );
143 }
144
145
146 /*---------------------------------------------------------------------------*
147 Name: LoadTexData
148
149 Description: loads non-compressed texture/palette data from the DVD
150
151 Arguments: path: the path to the texture/palette file on the DVD
152
153 Returns: Returns the pointer to the loaded data.
154 *---------------------------------------------------------------------------*/
LoadTexData(const char * path)155 static void* LoadTexData( const char* path )
156 {
157 DVDFileInfo fileInfo;
158 void* buf;
159
160 DVDOpen( path, &fileInfo );
161
162 buf = MEMAllocFromAllocator( &DemoAllocator1, OSRoundUp32B( fileInfo.length ) );
163 DVDRead( &fileInfo, buf, (s32)OSRoundUp32B( fileInfo.length ), 0 );
164 DVDClose( &fileInfo );
165
166 return buf;
167 }
168
169
170 /*---------------------------------------------------------------------------*
171 Name: LoadTexDataRL
172
173 Description: loads run-length compressed texture/palette data from the DVD and performs streaming decompression
174
175 Data is decompressed as it is asynchronously read from the DVD, using a double buffer.
176
177
178 Arguments: path: the path to the texture/palette file on the DVD
179
180 Returns: Returns the pointer to the decompressed data.
181 *---------------------------------------------------------------------------*/
LoadTexDataRL(const char * path)182 static void* LoadTexDataRL( const char* path )
183 {
184 void* uncompBuf; // decompression buffer
185 u32 uncompSize; // Data size after expansion
186 DVDFileInfo fileInfo; // DVD file context
187 u32 len[ 2 ]; // size of read data in the temporary buffer
188 s32 currIdx = 0; // index to control double buffer
189 s32 nextIdx = 1; // index to control double buffer
190 s32 offset = 0; // DVD offset
191 CXUncompContextRL context; // streaming decompression context
192
193 DVDOpen( path, &fileInfo );
194 DVDRead( &fileInfo, sReadBuf[ currIdx ], 32, 0 );
195 len[ currIdx ] = 32;
196 offset += 32;
197
198 // Loads at least the first four bytes of data and then allocates memory for the decompressed data size.
199 uncompSize = CXGetUncompressedSize ( sReadBuf[ currIdx ] );
200 uncompBuf = MEMAllocFromAllocator ( &DemoAllocator1, uncompSize );
201 // Initializes the context for streaming decompression.
202 CXInitUncompContextRL( &context, uncompBuf );
203
204 // Data is decompressed in order until the file decompression is complete.
205 while ( ! CXIsFinishedUncompRL( &context ) )
206 {
207 while ( DVDGetFileInfoStatus( &fileInfo ) != DVD_FILEINFO_READY ) {}
208
209 len[ nextIdx ] = OSRoundUp32B( fileInfo.length - offset );
210 if ( len[ nextIdx ] > BUF_SIZE )
211 {
212 len[ nextIdx ] = BUF_SIZE;
213 }
214
215 if ( len[ nextIdx ] > 0 )
216 {
217 DVDReadAsync( &fileInfo, sReadBuf[ nextIdx ], (s32)len[ nextIdx ], offset, NULL );
218 offset += len[ nextIdx ];
219 }
220
221 // only the loaded data is passed in order to the CX functions
222 ASSERT( len[ currIdx ] != 0 );
223 CXReadUncompRL( &context, sReadBuf[ currIdx ], len[ currIdx ] );
224
225 // double buffer swap
226 currIdx = (currIdx == 0)? 1 : 0;
227 nextIdx = (nextIdx == 0)? 1 : 0;
228 }
229
230 DCFlushRange( uncompBuf, uncompSize );
231 DVDClose( &fileInfo );
232
233 return uncompBuf;
234 }
235
236
237 /*---------------------------------------------------------------------------*
238 Name: LoadTexDataLZ
239
240 Description: loads LZ77 compressed texture/palette data from the DVD and performs streaming decompression
241
242 Data is decompressed as it is asynchronously read from the DVD, using a double buffer.
243
244
245 Arguments: path: the path to the texture/palette file on the DVD
246
247 Returns: Returns the pointer to the decompressed data.
248 *---------------------------------------------------------------------------*/
LoadTexDataLZ(const char * path)249 static void* LoadTexDataLZ( const char* path )
250 {
251 void* uncompBuf; // decompression buffer
252 u32 uncompSize; // Data size after expansion
253 DVDFileInfo fileInfo; // DVD file context
254 u32 len[ 2 ]; // size of read data in the temporary buffer
255 s32 currIdx = 0; // index to control double buffer
256 s32 nextIdx = 1; // index to control double buffer
257 s32 offset = 0; // DVD offset
258 CXUncompContextLZ context; // streaming decompression context
259
260 DVDOpen( path, &fileInfo );
261 DVDRead( &fileInfo, sReadBuf[ currIdx ], 32, 0 );
262 len[ currIdx ] = 32;
263 offset += 32;
264
265 // loads at least the first four bytes of data and then allocates memory for the decompressed data size.
266 uncompSize = CXGetUncompressedSize ( sReadBuf[ currIdx ] );
267 uncompBuf = MEMAllocFromAllocator ( &DemoAllocator1, uncompSize );
268 // Initializes the context for streaming decompression.
269 CXInitUncompContextLZ( &context, uncompBuf );
270
271 // Data is decompressed in order until the file decompression is complete.
272 while ( ! CXIsFinishedUncompLZ( &context ) )
273 {
274 while ( DVDGetFileInfoStatus( &fileInfo ) != DVD_FILEINFO_READY ) {}
275
276 len[ nextIdx ] = OSRoundUp32B( fileInfo.length - offset );
277 if ( len[ nextIdx ] > BUF_SIZE )
278 {
279 len[ nextIdx ] = BUF_SIZE;
280 }
281
282 if ( len[ nextIdx ] > 0 )
283 {
284 DVDReadAsync( &fileInfo, sReadBuf[ nextIdx ], (s32)len[ nextIdx ], offset, NULL );
285 offset += len[ nextIdx ];
286 }
287
288 // only the loaded data is passed in order to the CX functions
289 ASSERT( len[ currIdx ] != 0 );
290 CXReadUncompLZ( &context, sReadBuf[ currIdx ], len[ currIdx ] );
291
292 // double buffer swap
293 currIdx = (currIdx == 0)? 1 : 0;
294 nextIdx = (nextIdx == 0)? 1 : 0;
295 }
296
297 DCFlushRange( uncompBuf, uncompSize );
298 DVDClose( &fileInfo );
299
300 return uncompBuf;
301 }
302
303
304 /*---------------------------------------------------------------------------*
305 Name: LoadTexDataHuff
306
307 Description: loads Huffman compressed texture/palette data from the DVD and performs streaming decompression
308
309 Data is decompressed as it is asynchronously read from the DVD, using a double buffer.
310
311
312 Arguments: path: the path to the texture/palette file on the DVD
313
314 Returns: Returns the pointer to the decompressed data.
315 *---------------------------------------------------------------------------*/
LoadTexDataHuff(const char * path)316 static void* LoadTexDataHuff( const char* path )
317 {
318 void* uncompBuf; // decompression buffer
319 u32 uncompSize; // Data size after expansion
320 DVDFileInfo fileInfo; // DVD file context
321 u32 len[ 2 ]; // size of read data in the temporary buffer
322 s32 currIdx = 0; // index to control double buffer
323 s32 nextIdx = 1; // index to control double buffer
324 s32 offset = 0; // DVD offset
325 CXUncompContextHuffman context; // streaming decompression context
326
327 DVDOpen( path, &fileInfo );
328 DVDRead( &fileInfo, sReadBuf[ currIdx ], 32, 0 );
329 len[ currIdx ] = 32;
330 offset += 32;
331
332 // loads at least the first four bytes of data and then allocates memory for the decompressed data size.
333 uncompSize = CXGetUncompressedSize ( sReadBuf[ currIdx ] );
334 uncompBuf = MEMAllocFromAllocator ( &DemoAllocator1, uncompSize );
335 // Initializes the context for streaming decompression.
336 CXInitUncompContextHuffman( &context, uncompBuf );
337
338 // Data is decompressed in order until the file decompression is complete.
339 while ( ! CXIsFinishedUncompHuffman( &context ) )
340 {
341 while ( DVDGetFileInfoStatus( &fileInfo ) != DVD_FILEINFO_READY ) {}
342
343 len[ nextIdx ] = OSRoundUp32B( fileInfo.length - offset );
344 if ( len[ nextIdx ] > BUF_SIZE )
345 {
346 len[ nextIdx ] = BUF_SIZE;
347 }
348
349 if ( len[ nextIdx ] > 0 )
350 {
351 DVDReadAsync( &fileInfo, sReadBuf[ nextIdx ], (s32)len[ nextIdx ], offset, NULL );
352 offset += len[ nextIdx ];
353 }
354
355 // only the loaded data is passed in order to the CX functions
356 ASSERT( len[ currIdx ] != 0 );
357 CXReadUncompHuffman( &context, sReadBuf[ currIdx ], len[ currIdx ] );
358
359 // double buffer swap
360 currIdx = (currIdx == 0)? 1 : 0;
361 nextIdx = (nextIdx == 0)? 1 : 0;
362 }
363
364 DCFlushRange( uncompBuf, uncompSize );
365 DVDClose( &fileInfo );
366
367 return uncompBuf;
368 }
369
370
371 /*---------------------------------------------------------------------------*
372 Functions
373 *---------------------------------------------------------------------------*/
374
375 /*---------------------------------------------------------------------------*
376 Name: DrawInit
377
378 Description: camera initialization and loading and decompressing of texture and palette data from the DVD
379
380
381 Arguments: sc : a pointer to the scene parameter
382
383 Returns: None.
384 *---------------------------------------------------------------------------*/
DrawInit(MySceneCtrlObj * sc)385 static void DrawInit( MySceneCtrlObj* sc )
386 {
387 u32 i;
388
389 for ( i = 0; i < 4; i++ )
390 {
391 sc->texNum[ i ] = 0;
392 }
393
394 // Loads from the DVD while performing streaming decompression of the TPL file.
395 sMyTplObj[ 0 ] = (TPLPalettePtr)LoadTexData ( "/cxdemo/tex-01.tpl" );
396 sMyTplObj[ 1 ] = (TPLPalettePtr)LoadTexDataRL ( "/cxdemo/tex-01_RL.bin" );
397 sMyTplObj[ 2 ] = (TPLPalettePtr)LoadTexDataLZ ( "/cxdemo/tex-01_LZ.bin" );
398 sMyTplObj[ 3 ] = (TPLPalettePtr)LoadTexDataHuff( "/cxdemo/tex-01_Huff.bin" );
399
400 // bind the TPL object
401 TPLBind( sMyTplObj[ 0 ] );
402 TPLBind( sMyTplObj[ 1 ] );
403 TPLBind( sMyTplObj[ 2 ] );
404 TPLBind( sMyTplObj[ 3 ] );
405
406 // camera initialization
407 sc->cam.cfg = DEFAULT_CAMERA;
408 SetCamera( &sc->cam );
409
410 // Sets the view matrix.
411 GXLoadPosMtxImm( sc->cam.view, GX_PNMTX0 );
412 }
413
414
415 /*---------------------------------------------------------------------------*
416 Name: DrawTick
417
418 Description: render process for each frame
419
420 Arguments: sc : a pointer to the scene parameter
421
422 Returns: None.
423 *---------------------------------------------------------------------------*/
DrawTick(MySceneCtrlObj * sc)424 static void DrawTick( MySceneCtrlObj* sc )
425 {
426 TPLDescriptorPtr tdp;
427 GXTexObj texObj;
428 s32 i;
429
430 SetCamera( &sc->cam );
431 GXLoadPosMtxImm( sc->cam.view, GX_PNMTX0 );
432
433 for ( i = 0; i < 4; i++ )
434 {
435 {
436 // sets the texture index specified from the TPL object
437 tdp = TPLGet( sMyTplObj[ i ], sc->texNum[ i ] );
438
439 GXInitTexObj(
440 &texObj,
441 tdp->textureHeader->data,
442 tdp->textureHeader->width,
443 tdp->textureHeader->height,
444 (GXTexFmt)tdp->textureHeader->format,
445 tdp->textureHeader->wrapS,
446 tdp->textureHeader->wrapT,
447 GX_FALSE );
448
449 // Tev, TexGen and Zmode
450 GXSetTevOp ( GX_TEVSTAGE0, GX_REPLACE );
451 GXSetTevOrder ( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL );
452 GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY );
453 GXSetZMode ( GX_ENABLE, GX_LEQUAL, GX_ENABLE );
454 GXSetNumTexGens( 1 );
455
456 GXSetCurrentMtx( GX_PNMTX0 );
457 GXLoadTexObj( &texObj, GX_TEXMAP0 );
458 }
459
460 {
461 // renders after applying Scale and Trans
462 Mtx mv;
463 Mtx m;
464
465 f32 transX = (i % 2)? -112 : 112;
466 f32 transY = (i / 2)? -112 : 112;
467
468 MTXScale( m, 0.5f, 0.5f, 0.5f );
469 MTXConcat( m, sc->cam.view, mv );
470 MTXTrans( m, transX, transY, 0 );
471 MTXConcat( m, mv, mv );
472
473 GXLoadPosMtxImm( mv, GX_PNMTX0 );
474 DrawRect();
475 }
476 }
477
478
479 DEMOInitCaption(
480 DM_FT_OPQ,
481 320,
482 224 );
483
484 DEMOPrintf(48, 0, 0, "Raw");
485 DEMOPrintf(160, 0, 0, "RunLength");
486 DEMOPrintf(48, 112, 0, "LZ77");
487 DEMOPrintf(160, 112, 0, "Huffman");
488
489 }
490
491
492
493 /*---------------------------------------------------------------------------*
494 Name: AnimTick
495
496 Description: pad process for each frame
497
498 Arguments: sc : a pointer to the scene parameter
499
500 Returns: none
501 *---------------------------------------------------------------------------*/
AnimTick(MySceneCtrlObj * sc)502 static void AnimTick ( MySceneCtrlObj* sc )
503 {
504 if ( DEMOPadGetButtonDown( 0 ) & PAD_BUTTON_A )
505 {
506 s32 i;
507 for ( i = 0; i < 4; i++ )
508 {
509 if ( ++sc->texNum[ i ] >= sMyTplObj[ i ]->numDescriptors )
510 {
511 sc->texNum[ i ] = 0;
512 }
513 }
514 }
515 }
516
517
518 /*---------------------------------------------------------------------------*
519 Name: DrawRect
520
521 Description: Renders a textured rectangle.
522
523 Arguments: none
524
525 Returns: none
526 *---------------------------------------------------------------------------*/
DrawRect(void)527 static void DrawRect( void )
528 {
529 const s16 VERTEX_POS = 224;
530
531 // Vertex Attribute
532 // Vertex Attribute ( VTXFMT0 is used by DEMOPuts lib.)
533 GXSetVtxAttrFmt( GX_VTXFMT1, GX_VA_POS, GX_POS_XY, GX_S16, 0 );
534 GXSetVtxAttrFmt( GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_S16, 0 );
535
536 // Array Pointers and Strides
537 GXInvalidateVtxCache();
538
539 // set vertex descriptor
540 GXClearVtxDesc();
541 GXSetVtxDesc( GX_VA_POS, GX_DIRECT );
542 GXSetVtxDesc( GX_VA_TEX0, GX_DIRECT );
543
544 // draw a cube
545 GXBegin( GX_QUADS, GX_VTXFMT1, 4 );
546
547 GXPosition2s16( -VERTEX_POS, -VERTEX_POS );
548 GXTexCoord2s16( 0, 0 );
549
550 GXPosition2s16( VERTEX_POS, -VERTEX_POS );
551 GXTexCoord2s16( 1, 0 );
552
553 GXPosition2s16( VERTEX_POS, VERTEX_POS );
554 GXTexCoord2s16( 1, 1 );
555
556 GXPosition2s16( -VERTEX_POS, VERTEX_POS );
557 GXTexCoord2s16( 0, 1 );
558
559 GXEnd();
560 }
561
562
563 /*---------------------------------------------------------------------------*
564 Name: PrintIntro
565
566 Description: Prints the directions on how to use this demo.
567
568 Arguments: none
569
570 Returns: none
571 *---------------------------------------------------------------------------*/
PrintIntro(void)572 static void PrintIntro( void )
573 {
574 OSReport("\n\n");
575 OSReport("************************************************\n");
576 OSReport("cx_uncompress_stream: Streaming Uncompression demo\n");
577 OSReport("************************************************\n");
578 OSReport("to quit hit the start button\n");
579 OSReport("\n");
580 OSReport("A button : change texture index to next\n");
581 OSReport("************************************************\n\n");
582 }
583
584 /*============================================================================*/
585