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