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