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