1 /*---------------------------------------------------------------------------*
2   Project:  DPL2 Demo application
3   File:     dpl2demo.c
4 
5   Copyright (C)1998-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   $Log: dpl2demo.c,v $
14   Revision 1.9  2006/03/06 09:59:03  kawaset
15   Eliminated warnings.
16 
17   Revision 1.8  02/21/2006 01:04:15  mitu
18   modified am.h path.
19 
20   Revision 1.7  02/20/2006 04:13:07  mitu
21   changed include path from dolphin/ to revolution/.
22 
23   Revision 1.6  02/02/2006 07:26:59  aka
24   Modified using MEM functions instead of OSAlloc()/OSFree().
25 
26   Revision 1.5  02/01/2006 08:07:50  aka
27   Added #ifndef(#ifdef) HOLLYWOOD_REV - #else - #endif.
28 
29   Revision 1.4  2006/01/31 08:07:05  aka
30   Added cast from u32 to u8* in relation to changing API around ARAM.
31 
32   Revision 1.3  2006/01/27 04:54:59  ekwon
33   Corrected "\%" escape sequence warning (replaced with "%%").
34 
35   Revision 1.2  11/08/2005 02:55:02  aka
36   Changed suiting to Revolution's audio spec.
37 
38   Revision 1.1  11/04/2005 05:01:39  aka
39   Imported from dolphin tree.
40 
41     2     4/30/02 4:43p Eugene
42     Fixed pad read contention between UI and application. Requires latest
43     DEMO library!
44 
45     1     1/15/02 3:19p Billyjack
46     created
47 
48   $NoKeywords: $
49  *---------------------------------------------------------------------------*/
50 
51 /*---------------------------------------------------------------------------*
52  * Includes
53  *---------------------------------------------------------------------------*/
54 
55 #include <demo.h>
56 #include <demo/DEMOWin.h>
57 #include <revolution.h>
58 #include <revolution/mix.h>
59 #include <revolution/sp.h>
60 #ifndef HOLLYWOOD_REV
61 #include <dolphin/am.h>
62 #else
63 #include <revolution/mem.h>
64 #include <string.h>
65 #endif
66 
67 #include "noise.h"
68 
69 
70 /*---------------------------------------------------------------------------*
71  * SP data
72  *---------------------------------------------------------------------------*/
73 
74 #define SPT_FILE "/axdemo/dpl2/noise.spt"
75 #define SPD_FILE "/axdemo/dpl2/noise.spd"
76 
77 static SPSoundTable *sp_table;
78 #ifdef HOLLYWOOD_REV
79 static u8           *sp_data;
80 #endif
81 
82 #ifndef HOLLYWOOD_REV
83 /*---------------------------------------------------------------------------*
84 * ARAM initialization
85 *---------------------------------------------------------------------------*/
86 
87 // Use AR allocator to divide ARAM into 3 blocks
88 #define MAX_ARAM_BLOCKS  3
89 
90 // Give a whopping 8MB of ARAM to audio!
91 #define AUDIO_BLOCK_SIZE_BYTES (8*1024*1024)
92 
93 
94 static u32  aramZeroBase;
95 static u32  aramUserBase;
96 static u32  aramMemArray[MAX_ARAM_BLOCKS];
97 
98 
99 // transfer buffer for ARAM audio manager (AM)
100 #define XFER_BUFFER_SIZE_BYTES (16*1024)
101 
102 u8 xfer_buffer[XFER_BUFFER_SIZE_BYTES] ATTRIBUTE_ALIGN(32);
103 
104 #else
105 /*---------------------------------------------------------------------------*
106  * Exp Heap
107  *---------------------------------------------------------------------------*/
108 static MEMHeapHandle hExpHeap;
109 
110 /*---------------------------------------------------------------------------*
111  * Zero Buffer
112  *---------------------------------------------------------------------------*/
113 
114 #define ZEROBUFFER_BYTES 256
115 #endif
116 
117 /*---------------------------------------------------------------------------*
118  * Application-layer voice abstraction
119  *---------------------------------------------------------------------------*/
120 AXVPB           *voice;
121 SPSoundEntry    *sound;
122 int             panX, panY;
123 
124 /*---------------------------------------------------------------------------*
125  * Prototypes
126  *---------------------------------------------------------------------------*/
127 
128 static void         ax_demo_callback        (void);
129 static void         ax_drop_voice_callback  (void *p);
130 
131 // for UI menus
132 static void         MNU_sound               (DEMOWinMenuInfo *menu, u32 item, u32 *result);
133 static void         MNU_position            (DEMOWinMenuInfo *menu, u32 item, u32 *result);
134 
135 
136 /*---------------------------------------------------------------------------*
137  * UI Stuff
138  *---------------------------------------------------------------------------*/
139 
140 DEMOWinInfo *DebugWin;
141 DEMOWinInfo *PositionWin;
142 
143 DEMOWinMenuItem MenuItem[] =
144 {
145     { "",                       DEMOWIN_ITM_SEPARATOR,  NULL,             NULL },
146     { "Sound: None",            DEMOWIN_ITM_NONE,       MNU_sound,        NULL },
147     { "Position: C Stick",      DEMOWIN_ITM_NONE,       MNU_position,     NULL },
148     { "",                       DEMOWIN_ITM_SEPARATOR,  NULL,             NULL },
149     { "",                       DEMOWIN_ITM_TERMINATOR, NULL,             NULL }
150 };
151 
152 DEMOWinMenuInfo Menu =
153 {
154     "AX DPL2 Demo",             // title
155     NULL,                       // window handle
156     MenuItem,                   // list of menu items
157     5,                          // max num of items to display at a time
158     DEMOWIN_MNU_NONE,           // attribute flags
159 
160     // user callbacks
161     NULL,                       // callback for menu open event
162     NULL,                       // callback for cursor move event
163     NULL,                       // callback for item select event
164     NULL,                       // callback for cancel event
165 
166     // private members
167     0, 0, 0, 0, 0
168 };
169 
170 DEMOWinMenuInfo *MenuPtr;
171 
172 /*===========================================================================*
173  *                   F U N C T I O N    D E F I N I T I O N S
174  *===========================================================================*/
stop_voice(void)175 static void stop_voice(void)
176 {
177     if (voice)
178     {
179         DEMOWinLogPrintf(DebugWin, "Free voice.\n");
180         MIXReleaseChannel(voice);
181         AXFreeVoice(voice);
182         voice = NULL;
183     }
184 }
185 
play_sound(u32 sfx)186 static void play_sound(u32 sfx)
187 {
188     DEMOWinLogPrintf(DebugWin, "Acquire voice.\n");
189     voice = AXAcquireVoice(15, ax_drop_voice_callback, 0);
190 
191     if (voice)
192     {
193         sound = SPGetSoundEntry(sp_table, sfx);
194 
195         SPPrepareSound(sound, voice, sound->sampleRate);
196 
197         MIXInitChannel(voice, 0, 0, -960, -960, -960, panX, 127 - panY, 0);
198         DEMOWinLogPrintf(DebugWin, "Start voice.\n");
199         AXSetVoiceState(voice, AX_PB_STATE_RUN);
200     }
201     else
202     {
203         DEMOWinLogPrintf(DebugWin, "AX Voice allocation failed!\n");
204     }
205 }
206 
207 
208 /*---------------------------------------------------------------------------*
209  *---------------------------------------------------------------------------*/
210 static u32 soundIndex = 0;
MNU_sound(DEMOWinMenuInfo * menu,u32 item,u32 * result)211 static void MNU_sound(DEMOWinMenuInfo *menu, u32 item, u32 *result)
212 {
213 #pragma unused(result)
214 
215     soundIndex++;
216     soundIndex %= 3;
217 
218     switch (soundIndex)
219     {
220     case 0: // None
221 
222         stop_voice();
223         menu->items[item].name = "Sound: None";
224 
225         break;
226 
227     case 1: // White Noise
228 
229         stop_voice();
230         play_sound(SOUND_WHITE_NOISE);
231         menu->items[item].name = "Sound: White Noise";
232 
233         break;
234 
235     case 2: // Pink Noise
236 
237         stop_voice();
238         play_sound(SOUND_PINK_NOISE);
239         menu->items[item].name = "Sound: Pink Noise";
240 
241         break;
242     }
243 
244 }
245 
246 
247 /*---------------------------------------------------------------------------*
248  *---------------------------------------------------------------------------*/
249 static u32 positionIndex = 0;
MNU_position(DEMOWinMenuInfo * menu,u32 item,u32 * result)250 static void MNU_position(DEMOWinMenuInfo *menu, u32 item, u32 *result)
251 {
252 #pragma unused(result)
253 
254     positionIndex++;
255     positionIndex %= 7;
256 
257     switch (positionIndex)
258     {
259     case 0:
260 
261         menu->items[item].name = "Position: C Stick";
262 
263         break;
264 
265     case 1:
266 
267         panX = 0;
268         panY = 0;
269         menu->items[item].name = "Position: L";
270 
271         break;
272 
273     case 2:
274 
275         panX = 63;
276         panY = 0;
277         menu->items[item].name = "Position: C";
278 
279         break;
280 
281     case 3:
282 
283         panX = 127;
284         panY = 0;
285         menu->items[item].name = "Position: R";
286 
287         break;
288 
289     case 4:
290 
291         panX = 0;
292         panY = 127;
293         menu->items[item].name = "Position: Ls";
294 
295         break;
296 
297     case 5:
298 
299         panX = 127;
300         panY = 127;
301         menu->items[item].name = "Position: Rs";
302 
303         break;
304 
305     case 6:
306 
307         panX = 63;
308         panY = 127;
309         menu->items[item].name = "Position: Bs";
310 
311         break;
312 
313     }
314 
315 }
316 
317 
318 /*---------------------------------------------------------------------------*
319  * Name        : position_win_update()
320  * Description : refresh callback for position window
321  * Arguments   :
322  * Returns     :
323  *---------------------------------------------------------------------------*/
position_win_update(DEMOWinInfo * window)324 static void position_win_update(DEMOWinInfo *window)
325 {
326 //    DEMOWinPrintfXY(window, 0, 2, "X: %1.2f Y: %1.2f%%", (f32)(panX + 1) / 128, (f32)(panY + 1) / 128);
327     DEMOWinPrintfXY(window, 0, 2, "X: %1.2f Y: %1.2f%%", (f32)panX / 127, (f32)panY / 127);
328 }
329 
330 /*---------------------------------------------------------------------------*
331  * Name        :
332  * Description :
333  * Arguments   : None.
334  * Returns     : None.
335  *---------------------------------------------------------------------------*/
ax_demo_callback(void)336 static void ax_demo_callback(void)
337 {
338 
339     int substickX;
340     int substickY;
341 
342         substickX = (MenuPtr->handle)->pad.pads[0].substickX;
343         substickY = (MenuPtr->handle)->pad.pads[0].substickY;
344 
345         if (positionIndex == 0)
346         {
347             //DEMOPadRead();
348             //panX = (int)DEMOPadGetSubStickX(0) + 63;
349             //panY = ((int)DEMOPadGetSubStickY(0) - 63) * -1;
350 
351             panX = substickX + 63;
352             panY = (substickY - 63) * -1;
353 
354         }
355 
356         if (voice)
357         {
358             MIXSetPan(voice, panX);
359             MIXSetSPan(voice, 127 - panY);
360             MIXUpdateSettings();
361         }
362 
363 
364 } // end ax_demo_callback()
365 
366 
367 /*---------------------------------------------------------------------------*
368  * Name        : ax_drop_voice_callback()
369  * Description : Invoked by AX when a voice has been forciby dropped.
370  *               Must delete references to the voice from our abstraction layer
371  *               and release the associated MIXer channel.
372  * Arguments   : None.
373  * Returns     : None.
374  *---------------------------------------------------------------------------*/
ax_drop_voice_callback(void * p)375 static void ax_drop_voice_callback(void *p)
376 {
377     if (p == voice)
378     {
379         MIXReleaseChannel(voice);
380         voice = NULL;
381     }
382 } // end ax_demo_callback()
383 
384 
385 #ifdef HOLLYWOOD_REV
386 /*---------------------------------------------------------------------------*
387  *---------------------------------------------------------------------------*/
LoadFileIntoRam(char * path)388 static void* LoadFileIntoRam(char *path)
389 {
390     DVDFileInfo handle;
391     u32         round_length;
392     s32         read_length;
393     void        *buffer;
394 
395     // Open File
396     if (!DVDOpen(path, &handle))
397     {
398         OSReport("WARNING! Failed to open %s\n", path);
399         return NULL;
400     }
401 
402     // Make sure file length is not 0
403     if (DVDGetLength(&handle) == 0)
404     {
405         OSReport("WARNING! File length is 0\n");
406         return NULL;
407     }
408 
409     round_length = OSRoundUp32B(DVDGetLength(&handle));
410     buffer       = MEMAllocFromExpHeapEx(hExpHeap, round_length,  32);
411 
412     // Make sure we got a buffer
413     if (buffer == NULL)
414     {
415         OSReport("WARNING! Unable to allocate buffer\n");
416         return NULL;
417     }
418 
419     // Read Files
420     read_length = DVDRead(&handle, buffer, (s32)(round_length), 0);
421 
422     // Make sure we read the file correctly
423     if (read_length <= 0)
424     {
425         OSReport("WARNING! File lenght is wrong\n");
426         return NULL;
427     }
428 
429     return buffer;
430 }
431 #endif
432 
433 /*---------------------------------------------------------------------------*
434  * Name        : main()
435  * Description : Hold on to your seatbelts!
436  * Arguments   : None.
437  * Returns     : None.
438  *---------------------------------------------------------------------------*/
main(void)439 void main(void)
440 {
441 #ifdef HOLLYWOOD_REV
442     void       *arenaMem2Lo;
443     void       *arenaMem2Hi;
444     u8         *zeroBuffer;
445 #endif
446 
447     // initialize system
448     DEMOInit(NULL);
449     DEMOWinInit();
450 
451 #ifndef HOLLYWOOD_REV
452     // initialize ARAM w/ stack allocator
453     ARInit(aramMemArray, MAX_ARAM_BLOCKS);
454     ARQInit();
455 #else
456     arenaMem2Lo = OSGetMEM2ArenaLo();
457     arenaMem2Hi = OSGetMEM2ArenaHi();
458     hExpHeap    = MEMCreateExpHeap(arenaMem2Lo, (u32)arenaMem2Hi - (u32) arenaMem2Lo);
459 #endif
460 
461     // initialize AI subsystem
462     AIInit(NULL);
463 
464     // initialize AX audio system and MIXer application
465     AXInit();
466     MIXInit();
467 
468     AXSetMode(AX_MODE_DPL2);
469     MIXSetSoundMode(MIX_SOUND_MODE_DPL2);
470 
471 #ifndef HOLLYWOOD_REV
472     // -----------------------------------------------------------
473     // Initialize ARAM audio manager (AM)
474     // -----------------------------------------------------------
475 
476     // get a block from the AR ARAM allocator
477     aramUserBase = ARAlloc(AUDIO_BLOCK_SIZE_BYTES);
478 
479     // initialize AM with the block
480     AMInit(aramUserBase, AUDIO_BLOCK_SIZE_BYTES);
481 
482     // retrieve start of zero buffer, as created by AM
483     aramZeroBase = AMGetZeroBuffer();
484 #endif
485 
486     // -----------------------------------------------------------
487     // Load SP data!
488     // -----------------------------------------------------------
489 
490 #ifndef HOLLYWOOD_REV
491     // Retrieve sound table
492     sp_table = (SPSoundTable *)AMLoadFile(SPT_FILE, NULL);
493 
494     // Load sound effects into ARAM
495     aramUserBase = AMPushBuffered(SPD_FILE, (void *)xfer_buffer, XFER_BUFFER_SIZE_BYTES);
496 #else
497     // Load sound table
498     sp_table = LoadFileIntoRam(SPT_FILE);
499 
500     // Load sound effects
501     sp_data  = LoadFileIntoRam(SPD_FILE);
502 #endif
503 
504 #ifdef HOLLYWOOD_REV
505     // -----------------------------------------------------------
506     // Prepare Zero Buffer
507     // -----------------------------------------------------------
508     zeroBuffer = MEMAllocFromExpHeapEx(hExpHeap, ZEROBUFFER_BYTES, 8);
509     memset(zeroBuffer, 0, ZEROBUFFER_BYTES);
510     DCFlushRange(zeroBuffer, ZEROBUFFER_BYTES);
511 #endif
512 
513     // -----------------------------------------------------------
514     // initialize sound table!
515     // -----------------------------------------------------------
516 #ifndef HOLLYWOOD_REV
517     SPInitSoundTable(sp_table, (u8*)aramUserBase, (u8*)aramZeroBase);
518 #else
519     SPInitSoundTable(sp_table, sp_data, zeroBuffer);
520 #endif
521 
522     // -----------------------------------------------------------
523     // Initialize demo voice abstraction layer
524     // -----------------------------------------------------------
525     AXRegisterCallback(ax_demo_callback);
526 
527     // -----------------------------------------------------------
528     // Invoke menu system!
529     // -----------------------------------------------------------
530     MenuPtr     = DEMOWinCreateMenuWindow(
531                         &Menu,
532                         20,
533                         100
534                         );
535 
536     DebugWin    = DEMOWinCreateWindow(
537                         (u16)(MenuPtr->handle->x2+10),
538                         20,
539                         620,
540                         440,
541                         "Debug",
542                         1024,
543                         NULL
544                         );
545 
546     PositionWin = DEMOWinCreateWindow(
547                         (u16)(MenuPtr->handle->x1),
548                         (u16)(MenuPtr->handle->y2+10),
549                         (u16)(MenuPtr->handle->x2),
550                         (u16)(MenuPtr->handle->y2+60),
551                         "Position",
552                         0,
553                         position_win_update
554                         );
555 
556     DEMOWinOpenWindow(DebugWin);
557     DEMOWinOpenWindow(PositionWin);
558 
559     DEMOWinLogPrintf(DebugWin, "-------------------------------\n");
560     DEMOWinLogPrintf(DebugWin, "AX DPL2 Demo!\n");
561     DEMOWinLogPrintf(DebugWin, "-------------------------------\n");
562 
563     while (1)
564     {
565 
566         DEMOWinMenu(MenuPtr);
567 
568     }
569 
570 
571 } // end main()
572 
573