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