Rev 8645 | Rev 8647 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8645 | turbocat | 1 | // |
2 | // ID Engine |
||
3 | // ID_SD.c - Sound Manager for Wolfenstein 3D |
||
4 | // v1.2 |
||
5 | // By Jason Blochowiak |
||
6 | // |
||
7 | |||
8 | // |
||
9 | // This module handles dealing with generating sound on the appropriate |
||
10 | // hardware |
||
11 | // |
||
12 | // Depends on: User Mgr (for parm checking) |
||
13 | // |
||
14 | // Globals: |
||
15 | // For User Mgr: |
||
16 | // SoundBlasterPresent - SoundBlaster card present? |
||
17 | // AdLibPresent - AdLib card present? |
||
18 | // SoundMode - What device is used for sound effects |
||
19 | // (Use SM_SetSoundMode() to set) |
||
20 | // MusicMode - What device is used for music |
||
21 | // (Use SM_SetMusicMode() to set) |
||
22 | // DigiMode - What device is used for digitized sound effects |
||
23 | // (Use SM_SetDigiDevice() to set) |
||
24 | // |
||
25 | // For Cache Mgr: |
||
26 | // NeedsDigitized - load digitized sounds? |
||
27 | // NeedsMusic - load music? |
||
28 | // |
||
29 | |||
30 | #include "wl_def.h" |
||
31 | #include "SDL_mixer/SDL_mixer.h" |
||
32 | #if defined(GP2X_940) |
||
33 | #include "gp2x/fmopl.h" |
||
34 | #else |
||
35 | #include "mame/fmopl.h" |
||
36 | #endif |
||
37 | |||
38 | #pragma hdrstop |
||
39 | |||
40 | #define ORIGSAMPLERATE 7042 |
||
41 | |||
42 | typedef struct |
||
43 | { |
||
44 | char RIFF[4]; |
||
45 | longword filelenminus8; |
||
46 | char WAVE[4]; |
||
47 | char fmt_[4]; |
||
48 | longword formatlen; |
||
49 | word val0x0001; |
||
50 | word channels; |
||
51 | longword samplerate; |
||
52 | longword bytespersec; |
||
53 | word bytespersample; |
||
54 | word bitspersample; |
||
55 | } headchunk; |
||
56 | |||
57 | typedef struct |
||
58 | { |
||
59 | char chunkid[4]; |
||
60 | longword chunklength; |
||
61 | } wavechunk; |
||
62 | |||
63 | typedef struct |
||
64 | { |
||
65 | uint32_t startpage; |
||
66 | uint32_t length; |
||
67 | } digiinfo; |
||
68 | |||
69 | static Mix_Chunk *SoundChunks[ STARTMUSIC - STARTDIGISOUNDS]; |
||
70 | static byte *SoundBuffers[STARTMUSIC - STARTDIGISOUNDS]; |
||
71 | |||
72 | globalsoundpos channelSoundPos[MIX_CHANNELS]; |
||
73 | |||
74 | // Global variables |
||
75 | boolean AdLibPresent, |
||
76 | SoundBlasterPresent,SBProPresent, |
||
77 | SoundPositioned; |
||
78 | SDMode SoundMode; |
||
79 | SMMode MusicMode; |
||
80 | SDSMode DigiMode; |
||
81 | static byte **SoundTable; |
||
82 | int DigiMap[LASTSOUND]; |
||
83 | int DigiChannel[STARTMUSIC - STARTDIGISOUNDS]; |
||
84 | |||
85 | // Internal variables |
||
86 | static boolean SD_Started; |
||
87 | static boolean nextsoundpos; |
||
88 | static soundnames SoundNumber; |
||
89 | static soundnames DigiNumber; |
||
90 | static word SoundPriority; |
||
91 | static word DigiPriority; |
||
92 | static int LeftPosition; |
||
93 | static int RightPosition; |
||
94 | |||
95 | word NumDigi; |
||
96 | static digiinfo *DigiList; |
||
97 | static boolean DigiPlaying; |
||
98 | |||
99 | // PC Sound variables |
||
100 | static volatile byte pcLastSample; |
||
101 | static byte * volatile pcSound; |
||
102 | static longword pcLengthLeft; |
||
103 | |||
104 | // AdLib variables |
||
105 | static byte * volatile alSound; |
||
106 | static byte alBlock; |
||
107 | static longword alLengthLeft; |
||
108 | static longword alTimeCount; |
||
109 | static Instrument alZeroInst; |
||
110 | |||
111 | // Sequencer variables |
||
112 | static volatile boolean sqActive; |
||
113 | static word *sqHack; |
||
114 | static word *sqHackPtr; |
||
115 | static int sqHackLen; |
||
116 | static int sqHackSeqLen; |
||
117 | static longword sqHackTime; |
||
118 | |||
119 | |||
120 | static void SDL_SoundFinished(void) |
||
121 | { |
||
122 | SoundNumber = (soundnames)0; |
||
123 | SoundPriority = 0; |
||
124 | } |
||
125 | |||
126 | |||
127 | #ifdef NOTYET |
||
128 | |||
129 | void SDL_turnOnPCSpeaker(word timerval); |
||
130 | #pragma aux SDL_turnOnPCSpeaker = \ |
||
131 | "mov al,0b6h" \ |
||
132 | "out 43h,al" \ |
||
133 | "mov al,bl" \ |
||
134 | "out 42h,al" \ |
||
135 | "mov al,bh" \ |
||
136 | "out 42h,al" \ |
||
137 | "in al,61h" \ |
||
138 | "or al,3" \ |
||
139 | "out 61h,al" \ |
||
140 | parm [bx] \ |
||
141 | modify exact [al] |
||
142 | |||
143 | void SDL_turnOffPCSpeaker(); |
||
144 | #pragma aux SDL_turnOffPCSpeaker = \ |
||
145 | "in al,61h" \ |
||
146 | "and al,0fch" \ |
||
147 | "out 61h,al" \ |
||
148 | modify exact [al] |
||
149 | |||
150 | void SDL_setPCSpeaker(byte val); |
||
151 | #pragma aux SDL_setPCSpeaker = \ |
||
152 | "in al,61h" \ |
||
153 | "and al,0fch" \ |
||
154 | "or al,ah" \ |
||
155 | "out 61h,al" \ |
||
156 | parm [ah] \ |
||
157 | modify exact [al] |
||
158 | |||
159 | void inline SDL_DoFX() |
||
160 | { |
||
161 | if(pcSound) |
||
162 | { |
||
163 | if(*pcSound!=pcLastSample) |
||
164 | { |
||
165 | pcLastSample=*pcSound; |
||
166 | |||
167 | if(pcLastSample) |
||
168 | SDL_turnOnPCSpeaker(pcLastSample*60); |
||
169 | else |
||
170 | SDL_turnOffPCSpeaker(); |
||
171 | } |
||
172 | pcSound++; |
||
173 | pcLengthLeft--; |
||
174 | if(!pcLengthLeft) |
||
175 | { |
||
176 | pcSound=0; |
||
177 | SoundNumber=(soundnames)0; |
||
178 | SoundPriority=0; |
||
179 | SDL_turnOffPCSpeaker(); |
||
180 | } |
||
181 | } |
||
182 | |||
183 | // [adlib sound stuff removed...] |
||
184 | } |
||
185 | |||
186 | static void SDL_DigitizedDoneInIRQ(void); |
||
187 | |||
188 | void inline SDL_DoFast() |
||
189 | { |
||
190 | count_fx++; |
||
191 | if(count_fx>=5) |
||
192 | { |
||
193 | count_fx=0; |
||
194 | |||
195 | SDL_DoFX(); |
||
196 | |||
197 | count_time++; |
||
198 | if(count_time>=2) |
||
199 | { |
||
200 | TimeCount++; |
||
201 | count_time=0; |
||
202 | } |
||
203 | } |
||
204 | |||
205 | // [adlib music and soundsource stuff removed...] |
||
206 | |||
207 | TimerCount+=TimerDivisor; |
||
208 | if(*((word *)&TimerCount+1)) |
||
209 | { |
||
210 | *((word *)&TimerCount+1)=0; |
||
211 | t0OldService(); |
||
212 | } |
||
213 | else |
||
214 | { |
||
215 | outp(0x20,0x20); |
||
216 | } |
||
217 | } |
||
218 | |||
219 | // Timer 0 ISR for 7000Hz interrupts |
||
220 | void __interrupt SDL_t0ExtremeAsmService(void) |
||
221 | { |
||
222 | if(pcindicate) |
||
223 | { |
||
224 | if(pcSound) |
||
225 | { |
||
226 | SDL_setPCSpeaker(((*pcSound++)&0x80)>>6); |
||
227 | pcLengthLeft--; |
||
228 | if(!pcLengthLeft) |
||
229 | { |
||
230 | pcSound=0; |
||
231 | SDL_turnOffPCSpeaker(); |
||
232 | SDL_DigitizedDoneInIRQ(); |
||
233 | } |
||
234 | } |
||
235 | } |
||
236 | extreme++; |
||
237 | if(extreme>=10) |
||
238 | { |
||
239 | extreme=0; |
||
240 | SDL_DoFast(); |
||
241 | } |
||
242 | else |
||
243 | outp(0x20,0x20); |
||
244 | } |
||
245 | |||
246 | // Timer 0 ISR for 700Hz interrupts |
||
247 | void __interrupt SDL_t0FastAsmService(void) |
||
248 | { |
||
249 | SDL_DoFast(); |
||
250 | } |
||
251 | |||
252 | // Timer 0 ISR for 140Hz interrupts |
||
253 | void __interrupt SDL_t0SlowAsmService(void) |
||
254 | { |
||
255 | count_time++; |
||
256 | if(count_time>=2) |
||
257 | { |
||
258 | TimeCount++; |
||
259 | count_time=0; |
||
260 | } |
||
261 | |||
262 | SDL_DoFX(); |
||
263 | |||
264 | TimerCount+=TimerDivisor; |
||
265 | if(*((word *)&TimerCount+1)) |
||
266 | { |
||
267 | *((word *)&TimerCount+1)=0; |
||
268 | t0OldService(); |
||
269 | } |
||
270 | else |
||
271 | outp(0x20,0x20); |
||
272 | } |
||
273 | |||
274 | void SDL_IndicatePC(boolean ind) |
||
275 | { |
||
276 | pcindicate=ind; |
||
277 | } |
||
278 | |||
279 | /////////////////////////////////////////////////////////////////////////// |
||
280 | // |
||
281 | // SDL_SetTimer0() - Sets system timer 0 to the specified speed |
||
282 | // |
||
283 | /////////////////////////////////////////////////////////////////////////// |
||
284 | static void |
||
285 | SDL_SetTimer0(word speed) |
||
286 | { |
||
287 | #ifndef TPROF // If using Borland's profiling, don't screw with the timer |
||
288 | // _asm pushfd |
||
289 | _asm cli |
||
290 | |||
291 | outp(0x43,0x36); // Change timer 0 |
||
292 | outp(0x40,(byte)speed); |
||
293 | outp(0x40,speed >> 8); |
||
294 | // Kludge to handle special case for digitized PC sounds |
||
295 | if (TimerDivisor == (1192030 / (TickBase * 100))) |
||
296 | TimerDivisor = (1192030 / (TickBase * 10)); |
||
297 | else |
||
298 | TimerDivisor = speed; |
||
299 | |||
300 | // _asm popfd |
||
301 | _asm sti |
||
302 | #else |
||
303 | TimerDivisor = 0x10000; |
||
304 | #endif |
||
305 | } |
||
306 | |||
307 | /////////////////////////////////////////////////////////////////////////// |
||
308 | // |
||
309 | // SDL_SetIntsPerSec() - Uses SDL_SetTimer0() to set the number of |
||
310 | // interrupts generated by system timer 0 per second |
||
311 | // |
||
312 | /////////////////////////////////////////////////////////////////////////// |
||
313 | static void |
||
314 | SDL_SetIntsPerSec(word ints) |
||
315 | { |
||
316 | TimerRate = ints; |
||
317 | SDL_SetTimer0(1192030 / ints); |
||
318 | } |
||
319 | |||
320 | static void |
||
321 | SDL_SetTimerSpeed(void) |
||
322 | { |
||
323 | word rate; |
||
324 | void (_interrupt *isr)(void); |
||
325 | |||
326 | if ((DigiMode == sds_PC) && DigiPlaying) |
||
327 | { |
||
328 | rate = TickBase * 100; |
||
329 | isr = SDL_t0ExtremeAsmService; |
||
330 | } |
||
331 | else if ((MusicMode == smm_AdLib) || ((DigiMode == sds_SoundSource) && DigiPlaying) ) |
||
332 | { |
||
333 | rate = TickBase * 10; |
||
334 | isr = SDL_t0FastAsmService; |
||
335 | } |
||
336 | else |
||
337 | { |
||
338 | rate = TickBase * 2; |
||
339 | isr = SDL_t0SlowAsmService; |
||
340 | } |
||
341 | |||
342 | if (rate != TimerRate) |
||
343 | { |
||
344 | _dos_setvect(8,isr); |
||
345 | SDL_SetIntsPerSec(rate); |
||
346 | TimerRate = rate; |
||
347 | } |
||
348 | } |
||
349 | |||
350 | // |
||
351 | // PC Sound code |
||
352 | // |
||
353 | |||
354 | /////////////////////////////////////////////////////////////////////////// |
||
355 | // |
||
356 | // SDL_PCPlaySample() - Plays the specified sample on the PC speaker |
||
357 | // |
||
358 | /////////////////////////////////////////////////////////////////////////// |
||
359 | #ifdef _MUSE_ |
||
360 | void |
||
361 | #else |
||
362 | static void |
||
363 | #endif |
||
364 | SDL_PCPlaySample(byte *data,longword len,boolean inIRQ) |
||
365 | { |
||
366 | if(!inIRQ) |
||
367 | { |
||
368 | // _asm pushfd |
||
369 | _asm cli |
||
370 | } |
||
371 | |||
372 | SDL_IndicatePC(true); |
||
373 | |||
374 | pcLengthLeft = len; |
||
375 | pcSound = (volatile byte *)data; |
||
376 | |||
377 | if(!inIRQ) |
||
378 | { |
||
379 | // _asm popfd |
||
380 | _asm sti |
||
381 | } |
||
382 | } |
||
383 | |||
384 | /////////////////////////////////////////////////////////////////////////// |
||
385 | // |
||
386 | // SDL_PCStopSample() - Stops a sample playing on the PC speaker |
||
387 | // |
||
388 | /////////////////////////////////////////////////////////////////////////// |
||
389 | #ifdef _MUSE_ |
||
390 | void |
||
391 | #else |
||
392 | static void |
||
393 | #endif |
||
394 | SDL_PCStopSampleInIRQ(void) |
||
395 | { |
||
396 | pcSound = 0; |
||
397 | |||
398 | SDL_IndicatePC(false); |
||
399 | |||
400 | _asm in al,0x61 // Turn the speaker off |
||
401 | _asm and al,0xfd // ~2 |
||
402 | _asm out 0x61,al |
||
403 | } |
||
404 | |||
405 | /////////////////////////////////////////////////////////////////////////// |
||
406 | // |
||
407 | // SDL_PCPlaySound() - Plays the specified sound on the PC speaker |
||
408 | // |
||
409 | /////////////////////////////////////////////////////////////////////////// |
||
410 | #ifdef _MUSE_ |
||
411 | void |
||
412 | #else |
||
413 | static void |
||
414 | #endif |
||
415 | SDL_PCPlaySound(PCSound *sound) |
||
416 | { |
||
417 | // _asm pushfd |
||
418 | _asm cli |
||
419 | |||
420 | pcLastSample = -1; |
||
421 | pcLengthLeft = sound->common.length; |
||
422 | pcSound = sound->data; |
||
423 | |||
424 | // _asm popfd |
||
425 | _asm sti |
||
426 | } |
||
427 | |||
428 | /////////////////////////////////////////////////////////////////////////// |
||
429 | // |
||
430 | // SDL_PCStopSound() - Stops the current sound playing on the PC Speaker |
||
431 | // |
||
432 | /////////////////////////////////////////////////////////////////////////// |
||
433 | #ifdef _MUSE_ |
||
434 | void |
||
435 | #else |
||
436 | static void |
||
437 | #endif |
||
438 | SDL_PCStopSound(void) |
||
439 | { |
||
440 | // _asm pushfd |
||
441 | _asm cli |
||
442 | |||
443 | pcSound = 0; |
||
444 | |||
445 | _asm in al,0x61 // Turn the speaker off |
||
446 | _asm and al,0xfd // ~2 |
||
447 | _asm out 0x61,al |
||
448 | |||
449 | // _asm popfd |
||
450 | _asm sti |
||
451 | } |
||
452 | |||
453 | /////////////////////////////////////////////////////////////////////////// |
||
454 | // |
||
455 | // SDL_ShutPC() - Turns off the pc speaker |
||
456 | // |
||
457 | /////////////////////////////////////////////////////////////////////////// |
||
458 | static void |
||
459 | SDL_ShutPC(void) |
||
460 | { |
||
461 | // _asm pushfd |
||
462 | _asm cli |
||
463 | |||
464 | pcSound = 0; |
||
465 | |||
466 | _asm in al,0x61 // Turn the speaker & gate off |
||
467 | _asm and al,0xfc // ~3 |
||
468 | _asm out 0x61,al |
||
469 | |||
470 | // _asm popfd |
||
471 | _asm sti |
||
472 | } |
||
473 | |||
474 | #endif |
||
475 | |||
476 | void |
||
477 | SD_StopDigitized(void) |
||
478 | { |
||
479 | DigiPlaying = false; |
||
480 | DigiNumber = (soundnames) 0; |
||
481 | DigiPriority = 0; |
||
482 | SoundPositioned = false; |
||
483 | if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) |
||
484 | SDL_SoundFinished(); |
||
485 | |||
486 | switch (DigiMode) |
||
487 | { |
||
488 | case sds_PC: |
||
489 | // SDL_PCStopSampleInIRQ(); |
||
490 | break; |
||
491 | case sds_SoundBlaster: |
||
492 | // SDL_SBStopSampleInIRQ(); |
||
493 | Mix_HaltChannel(-1); |
||
494 | break; |
||
495 | } |
||
496 | } |
||
497 | |||
498 | int SD_GetChannelForDigi(int which) |
||
499 | { |
||
500 | if(DigiChannel[which] != -1) return DigiChannel[which]; |
||
501 | |||
502 | int channel = Mix_GroupAvailable(1); |
||
503 | if(channel == -1) channel = Mix_GroupOldest(1); |
||
504 | if(channel == -1) // All sounds stopped in the meantime? |
||
505 | return Mix_GroupAvailable(1); |
||
506 | return channel; |
||
507 | } |
||
508 | |||
509 | void SD_SetPosition(int channel, int leftpos, int rightpos) |
||
510 | { |
||
511 | if((leftpos < 0) || (leftpos > 15) || (rightpos < 0) || (rightpos > 15) |
||
512 | || ((leftpos == 15) && (rightpos == 15))) |
||
513 | Quit("SD_SetPosition: Illegal position"); |
||
514 | |||
515 | switch (DigiMode) |
||
516 | { |
||
517 | case sds_SoundBlaster: |
||
518 | // SDL_PositionSBP(leftpos,rightpos); |
||
519 | Mix_SetPanning(channel, ((15 - leftpos) << 4) + 15, |
||
520 | ((15 - rightpos) << 4) + 15); |
||
521 | break; |
||
522 | } |
||
523 | } |
||
524 | |||
525 | Sint16 GetSample(float csample, byte *samples, int size) |
||
526 | { |
||
527 | float s0=0, s1=0, s2=0; |
||
528 | int cursample = (int) csample; |
||
529 | float sf = csample - (float) cursample; |
||
530 | |||
531 | if(cursample-1 >= 0) s0 = (float) (samples[cursample-1] - 128); |
||
532 | s1 = (float) (samples[cursample] - 128); |
||
533 | if(cursample+1 < size) s2 = (float) (samples[cursample+1] - 128); |
||
534 | |||
535 | float val = s0*sf*(sf-1)/2 - s1*(sf*sf-1) + s2*(sf+1)*sf/2; |
||
536 | int32_t intval = (int32_t) (val * 256); |
||
537 | if(intval < -32768) intval = -32768; |
||
538 | else if(intval > 32767) intval = 32767; |
||
539 | return (Sint16) intval; |
||
540 | } |
||
541 | |||
542 | void SD_PrepareSound(int which) |
||
543 | { |
||
544 | if(DigiList == NULL) |
||
545 | Quit("SD_PrepareSound(%i): DigiList not initialized!\n", which); |
||
546 | |||
547 | int page = DigiList[which].startpage; |
||
548 | int size = DigiList[which].length; |
||
549 | |||
550 | byte *origsamples = PM_GetSound(page); |
||
551 | if(origsamples + size >= PM_GetEnd()) |
||
552 | Quit("SD_PrepareSound(%i): Sound reaches out of page file!\n", which); |
||
553 | |||
554 | int destsamples = (int) ((float) size * (float) param_samplerate |
||
555 | / (float) ORIGSAMPLERATE); |
||
556 | |||
557 | byte *wavebuffer = (byte *) malloc(sizeof(headchunk) + sizeof(wavechunk) |
||
558 | + destsamples * 2); // dest are 16-bit samples |
||
559 | if(wavebuffer == NULL) |
||
560 | Quit("Unable to allocate wave buffer for sound %i!\n", which); |
||
561 | |||
562 | headchunk head = {{'R','I','F','F'}, 0, {'W','A','V','E'}, |
||
563 | {'f','m','t',' '}, 0x10, 0x0001, 1, param_samplerate, param_samplerate*2, 2, 16}; |
||
564 | wavechunk dhead = {{'d', 'a', 't', 'a'}, destsamples*2}; |
||
565 | head.filelenminus8 = sizeof(head) + destsamples*2; // (sizeof(dhead)-8 = 0) |
||
566 | memcpy(wavebuffer, &head, sizeof(head)); |
||
567 | memcpy(wavebuffer+sizeof(head), &dhead, sizeof(dhead)); |
||
568 | |||
569 | // alignment is correct, as wavebuffer comes from malloc |
||
570 | // and sizeof(headchunk) % 4 == 0 and sizeof(wavechunk) % 4 == 0 |
||
571 | Sint16 *newsamples = (Sint16 *)(void *) (wavebuffer + sizeof(headchunk) |
||
572 | + sizeof(wavechunk)); |
||
573 | float cursample = 0.F; |
||
574 | float samplestep = (float) ORIGSAMPLERATE / (float) param_samplerate; |
||
575 | for(int i=0; i |
||
576 | { |
||
577 | newsamples[i] = GetSample((float)size * (float)i / (float)destsamples, |
||
578 | origsamples, size); |
||
579 | } |
||
580 | SoundBuffers[which] = wavebuffer; |
||
581 | |||
582 | SoundChunks[which] = Mix_LoadWAV_RW(SDL_RWFromMem(wavebuffer, |
||
583 | sizeof(headchunk) + sizeof(wavechunk) + destsamples * 2), 1); |
||
584 | } |
||
585 | |||
586 | int SD_PlayDigitized(word which,int leftpos,int rightpos) |
||
587 | { |
||
588 | if (!DigiMode) |
||
589 | return 0; |
||
590 | |||
591 | if (which >= NumDigi) |
||
592 | Quit("SD_PlayDigitized: bad sound number %i", which); |
||
593 | |||
594 | int channel = SD_GetChannelForDigi(which); |
||
595 | SD_SetPosition(channel, leftpos,rightpos); |
||
596 | |||
597 | DigiPlaying = true; |
||
598 | |||
599 | Mix_Chunk *sample = SoundChunks[which]; |
||
600 | if(sample == NULL) |
||
601 | { |
||
602 | printf("SoundChunks[%i] is NULL!\n", which); |
||
603 | return 0; |
||
604 | } |
||
605 | |||
606 | if(Mix_PlayChannel(channel, sample, 0) == -1) |
||
607 | { |
||
608 | printf("Unable to play sound: %s\n", Mix_GetError()); |
||
609 | return 0; |
||
610 | } |
||
611 | |||
612 | return channel; |
||
613 | } |
||
614 | |||
615 | void SD_ChannelFinished(int channel) |
||
616 | { |
||
617 | channelSoundPos[channel].valid = 0; |
||
618 | } |
||
619 | |||
620 | void |
||
621 | SD_SetDigiDevice(SDSMode mode) |
||
622 | { |
||
623 | boolean devicenotpresent; |
||
624 | |||
625 | if (mode == DigiMode) |
||
626 | return; |
||
627 | |||
628 | SD_StopDigitized(); |
||
629 | |||
630 | devicenotpresent = false; |
||
631 | switch (mode) |
||
632 | { |
||
633 | case sds_SoundBlaster: |
||
634 | if (!SoundBlasterPresent) |
||
635 | devicenotpresent = true; |
||
636 | break; |
||
637 | } |
||
638 | |||
639 | if (!devicenotpresent) |
||
640 | { |
||
641 | DigiMode = mode; |
||
642 | |||
643 | #ifdef NOTYET |
||
644 | SDL_SetTimerSpeed(); |
||
645 | #endif |
||
646 | } |
||
647 | } |
||
648 | |||
649 | void |
||
650 | SDL_SetupDigi(void) |
||
651 | { |
||
652 | // Correct padding enforced by PM_Startup() |
||
653 | word *soundInfoPage = (word *) (void *) PM_GetPage(ChunksInFile-1); |
||
654 | NumDigi = (word) PM_GetPageSize(ChunksInFile - 1) / 4; |
||
655 | |||
656 | DigiList = (digiinfo *) malloc(NumDigi * sizeof(digiinfo)); |
||
657 | int i; |
||
658 | for(i = 0; i < NumDigi; i++) |
||
659 | { |
||
660 | // Calculate the size of the digi from the sizes of the pages between |
||
661 | // the start page and the start page of the next sound |
||
662 | |||
663 | DigiList[i].startpage = soundInfoPage[i * 2]; |
||
664 | if((int) DigiList[i].startpage >= ChunksInFile - 1) |
||
665 | { |
||
666 | NumDigi = i; |
||
667 | break; |
||
668 | } |
||
669 | |||
670 | int lastPage; |
||
671 | if(i < NumDigi - 1) |
||
672 | { |
||
673 | lastPage = soundInfoPage[i * 2 + 2]; |
||
674 | if(lastPage == 0 || lastPage + PMSoundStart > ChunksInFile - 1) lastPage = ChunksInFile - 1; |
||
675 | else lastPage += PMSoundStart; |
||
676 | } |
||
677 | else lastPage = ChunksInFile - 1; |
||
678 | |||
679 | int size = 0; |
||
680 | for(int page = PMSoundStart + DigiList[i].startpage; page < lastPage; page++) |
||
681 | size += PM_GetPageSize(page); |
||
682 | |||
683 | // Don't include padding of sound info page, if padding was added |
||
684 | if(lastPage == ChunksInFile - 1 && PMSoundInfoPagePadded) size--; |
||
685 | |||
686 | // Patch lower 16-bit of size with size from sound info page. |
||
687 | // The original VSWAP contains padding which is included in the page size, |
||
688 | // but not included in the 16-bit size. So we use the more precise value. |
||
689 | if((size & 0xffff0000) != 0 && (size & 0xffff) < soundInfoPage[i * 2 + 1]) |
||
690 | size -= 0x10000; |
||
691 | size = (size & 0xffff0000) | soundInfoPage[i * 2 + 1]; |
||
692 | |||
693 | DigiList[i].length = size; |
||
694 | } |
||
695 | |||
696 | for(i = 0; i < LASTSOUND; i++) |
||
697 | { |
||
698 | DigiMap[i] = -1; |
||
699 | DigiChannel[i] = -1; |
||
700 | } |
||
701 | } |
||
702 | |||
703 | // AdLib Code |
||
704 | |||
705 | /////////////////////////////////////////////////////////////////////////// |
||
706 | // |
||
707 | // SDL_ALStopSound() - Turns off any sound effects playing through the |
||
708 | // AdLib card |
||
709 | // |
||
710 | /////////////////////////////////////////////////////////////////////////// |
||
711 | static void |
||
712 | SDL_ALStopSound(void) |
||
713 | { |
||
714 | alSound = 0; |
||
715 | alOut(alFreqH + 0, 0); |
||
716 | } |
||
717 | |||
718 | static void |
||
719 | SDL_AlSetFXInst(Instrument *inst) |
||
720 | { |
||
721 | byte c,m; |
||
722 | |||
723 | m = 0; // modulator cell for channel 0 |
||
724 | c = 3; // carrier cell for channel 0 |
||
725 | alOut(m + alChar,inst->mChar); |
||
726 | alOut(m + alScale,inst->mScale); |
||
727 | alOut(m + alAttack,inst->mAttack); |
||
728 | alOut(m + alSus,inst->mSus); |
||
729 | alOut(m + alWave,inst->mWave); |
||
730 | alOut(c + alChar,inst->cChar); |
||
731 | alOut(c + alScale,inst->cScale); |
||
732 | alOut(c + alAttack,inst->cAttack); |
||
733 | alOut(c + alSus,inst->cSus); |
||
734 | alOut(c + alWave,inst->cWave); |
||
735 | |||
736 | // Note: Switch commenting on these lines for old MUSE compatibility |
||
737 | // alOutInIRQ(alFeedCon,inst->nConn); |
||
738 | alOut(alFeedCon,0); |
||
739 | } |
||
740 | |||
741 | /////////////////////////////////////////////////////////////////////////// |
||
742 | // |
||
743 | // SDL_ALPlaySound() - Plays the specified sound on the AdLib card |
||
744 | // |
||
745 | /////////////////////////////////////////////////////////////////////////// |
||
746 | static void |
||
747 | SDL_ALPlaySound(AdLibSound *sound) |
||
748 | { |
||
749 | Instrument *inst; |
||
750 | byte *data; |
||
751 | |||
752 | SDL_ALStopSound(); |
||
753 | |||
754 | alLengthLeft = sound->common.length; |
||
755 | data = sound->data; |
||
756 | alBlock = ((sound->block & 7) << 2) | 0x20; |
||
757 | inst = &sound->inst; |
||
758 | |||
759 | if (!(inst->mSus | inst->cSus)) |
||
760 | { |
||
761 | Quit("SDL_ALPlaySound() - Bad instrument"); |
||
762 | } |
||
763 | |||
764 | SDL_AlSetFXInst(inst); |
||
765 | alSound = (byte *)data; |
||
766 | } |
||
767 | |||
768 | /////////////////////////////////////////////////////////////////////////// |
||
769 | // |
||
770 | // SDL_ShutAL() - Shuts down the AdLib card for sound effects |
||
771 | // |
||
772 | /////////////////////////////////////////////////////////////////////////// |
||
773 | static void |
||
774 | SDL_ShutAL(void) |
||
775 | { |
||
776 | alSound = 0; |
||
777 | alOut(alEffects,0); |
||
778 | alOut(alFreqH + 0,0); |
||
779 | SDL_AlSetFXInst(&alZeroInst); |
||
780 | } |
||
781 | |||
782 | /////////////////////////////////////////////////////////////////////////// |
||
783 | // |
||
784 | // SDL_CleanAL() - Totally shuts down the AdLib card |
||
785 | // |
||
786 | /////////////////////////////////////////////////////////////////////////// |
||
787 | static void |
||
788 | SDL_CleanAL(void) |
||
789 | { |
||
790 | int i; |
||
791 | |||
792 | alOut(alEffects,0); |
||
793 | for (i = 1; i < 0xf5; i++) |
||
794 | alOut(i, 0); |
||
795 | } |
||
796 | |||
797 | /////////////////////////////////////////////////////////////////////////// |
||
798 | // |
||
799 | // SDL_StartAL() - Starts up the AdLib card for sound effects |
||
800 | // |
||
801 | /////////////////////////////////////////////////////////////////////////// |
||
802 | static void |
||
803 | SDL_StartAL(void) |
||
804 | { |
||
805 | alOut(alEffects, 0); |
||
806 | SDL_AlSetFXInst(&alZeroInst); |
||
807 | } |
||
808 | |||
809 | /////////////////////////////////////////////////////////////////////////// |
||
810 | // |
||
811 | // SDL_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster |
||
812 | // emulating an AdLib) present |
||
813 | // |
||
814 | /////////////////////////////////////////////////////////////////////////// |
||
815 | static boolean |
||
816 | SDL_DetectAdLib(void) |
||
817 | { |
||
818 | for (int i = 1; i <= 0xf5; i++) // Zero all the registers |
||
819 | alOut(i, 0); |
||
820 | |||
821 | alOut(1, 0x20); // Set WSE=1 |
||
822 | // alOut(8, 0); // Set CSM=0 & SEL=0 |
||
823 | |||
824 | return true; |
||
825 | } |
||
826 | |||
827 | //////////////////////////////////////////////////////////////////////////// |
||
828 | // |
||
829 | // SDL_ShutDevice() - turns off whatever device was being used for sound fx |
||
830 | // |
||
831 | //////////////////////////////////////////////////////////////////////////// |
||
832 | static void |
||
833 | SDL_ShutDevice(void) |
||
834 | { |
||
835 | switch (SoundMode) |
||
836 | { |
||
837 | case sdm_PC: |
||
838 | // SDL_ShutPC(); |
||
839 | break; |
||
840 | case sdm_AdLib: |
||
841 | SDL_ShutAL(); |
||
842 | break; |
||
843 | } |
||
844 | SoundMode = sdm_Off; |
||
845 | } |
||
846 | |||
847 | /////////////////////////////////////////////////////////////////////////// |
||
848 | // |
||
849 | // SDL_CleanDevice() - totally shuts down all sound devices |
||
850 | // |
||
851 | /////////////////////////////////////////////////////////////////////////// |
||
852 | static void |
||
853 | SDL_CleanDevice(void) |
||
854 | { |
||
855 | if ((SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib)) |
||
856 | SDL_CleanAL(); |
||
857 | } |
||
858 | |||
859 | /////////////////////////////////////////////////////////////////////////// |
||
860 | // |
||
861 | // SDL_StartDevice() - turns on whatever device is to be used for sound fx |
||
862 | // |
||
863 | /////////////////////////////////////////////////////////////////////////// |
||
864 | static void |
||
865 | SDL_StartDevice(void) |
||
866 | { |
||
867 | switch (SoundMode) |
||
868 | { |
||
869 | case sdm_AdLib: |
||
870 | SDL_StartAL(); |
||
871 | break; |
||
872 | } |
||
873 | SoundNumber = (soundnames) 0; |
||
874 | SoundPriority = 0; |
||
875 | } |
||
876 | |||
877 | // Public routines |
||
878 | |||
879 | /////////////////////////////////////////////////////////////////////////// |
||
880 | // |
||
881 | // SD_SetSoundMode() - Sets which sound hardware to use for sound effects |
||
882 | // |
||
883 | /////////////////////////////////////////////////////////////////////////// |
||
884 | boolean |
||
885 | SD_SetSoundMode(SDMode mode) |
||
886 | { |
||
887 | boolean result = false; |
||
888 | word tableoffset; |
||
889 | |||
890 | SD_StopSound(); |
||
891 | |||
892 | if ((mode == sdm_AdLib) && !AdLibPresent) |
||
893 | mode = sdm_PC; |
||
894 | |||
895 | switch (mode) |
||
896 | { |
||
897 | case sdm_Off: |
||
898 | tableoffset = STARTADLIBSOUNDS; |
||
899 | result = true; |
||
900 | break; |
||
901 | case sdm_PC: |
||
902 | tableoffset = STARTPCSOUNDS; |
||
903 | result = true; |
||
904 | break; |
||
905 | case sdm_AdLib: |
||
906 | tableoffset = STARTADLIBSOUNDS; |
||
907 | if (AdLibPresent) |
||
908 | result = true; |
||
909 | break; |
||
910 | default: |
||
911 | Quit("SD_SetSoundMode: Invalid sound mode %i", mode); |
||
912 | return false; |
||
913 | } |
||
914 | SoundTable = &audiosegs[tableoffset]; |
||
915 | |||
916 | if (result && (mode != SoundMode)) |
||
917 | { |
||
918 | SDL_ShutDevice(); |
||
919 | SoundMode = mode; |
||
920 | SDL_StartDevice(); |
||
921 | } |
||
922 | |||
923 | return(result); |
||
924 | } |
||
925 | |||
926 | /////////////////////////////////////////////////////////////////////////// |
||
927 | // |
||
928 | // SD_SetMusicMode() - sets the device to use for background music |
||
929 | // |
||
930 | /////////////////////////////////////////////////////////////////////////// |
||
931 | boolean |
||
932 | SD_SetMusicMode(SMMode mode) |
||
933 | { |
||
934 | boolean result = false; |
||
935 | |||
936 | SD_FadeOutMusic(); |
||
937 | while (SD_MusicPlaying()) |
||
938 | SDL_Delay(5); |
||
939 | |||
940 | switch (mode) |
||
941 | { |
||
942 | case smm_Off: |
||
943 | result = true; |
||
944 | break; |
||
945 | case smm_AdLib: |
||
946 | if (AdLibPresent) |
||
947 | result = true; |
||
948 | break; |
||
949 | } |
||
950 | |||
951 | if (result) |
||
952 | MusicMode = mode; |
||
953 | |||
954 | // SDL_SetTimerSpeed(); |
||
955 | |||
956 | return(result); |
||
957 | } |
||
958 | |||
959 | int numreadysamples = 0; |
||
960 | byte *curAlSound = 0; |
||
961 | byte *curAlSoundPtr = 0; |
||
962 | longword curAlLengthLeft = 0; |
||
963 | int soundTimeCounter = 5; |
||
964 | int samplesPerMusicTick; |
||
965 | |||
966 | void SDL_IMFMusicPlayer(void *udata, Uint8 *stream, int len) |
||
967 | { |
||
968 | int stereolen = len>>1; |
||
969 | int sampleslen = stereolen>>1; |
||
970 | INT16 *stream16 = (INT16 *) (void *) stream; // expect correct alignment |
||
971 | |||
972 | while(1) |
||
973 | { |
||
974 | if(numreadysamples) |
||
975 | { |
||
976 | if(numreadysamples |
||
977 | { |
||
978 | YM3812UpdateOne(0, stream16, numreadysamples); |
||
979 | stream16 += numreadysamples*2; |
||
980 | sampleslen -= numreadysamples; |
||
981 | } |
||
982 | else |
||
983 | { |
||
984 | YM3812UpdateOne(0, stream16, sampleslen); |
||
985 | numreadysamples -= sampleslen; |
||
986 | return; |
||
987 | } |
||
988 | } |
||
989 | soundTimeCounter--; |
||
990 | if(!soundTimeCounter) |
||
991 | { |
||
992 | soundTimeCounter = 5; |
||
993 | if(curAlSound != alSound) |
||
994 | { |
||
995 | curAlSound = curAlSoundPtr = alSound; |
||
996 | curAlLengthLeft = alLengthLeft; |
||
997 | } |
||
998 | if(curAlSound) |
||
999 | { |
||
1000 | if(*curAlSoundPtr) |
||
1001 | { |
||
1002 | alOut(alFreqL, *curAlSoundPtr); |
||
1003 | alOut(alFreqH, alBlock); |
||
1004 | } |
||
1005 | else alOut(alFreqH, 0); |
||
1006 | curAlSoundPtr++; |
||
1007 | curAlLengthLeft--; |
||
1008 | if(!curAlLengthLeft) |
||
1009 | { |
||
1010 | curAlSound = alSound = 0; |
||
1011 | SoundNumber = (soundnames) 0; |
||
1012 | SoundPriority = 0; |
||
1013 | alOut(alFreqH, 0); |
||
1014 | } |
||
1015 | } |
||
1016 | } |
||
1017 | if(sqActive) |
||
1018 | { |
||
1019 | do |
||
1020 | { |
||
1021 | if(sqHackTime > alTimeCount) break; |
||
1022 | sqHackTime = alTimeCount + *(sqHackPtr+1); |
||
1023 | alOut(*(byte *) sqHackPtr, *(((byte *) sqHackPtr)+1)); |
||
1024 | sqHackPtr += 2; |
||
1025 | sqHackLen -= 4; |
||
1026 | } |
||
1027 | while(sqHackLen>0); |
||
1028 | alTimeCount++; |
||
1029 | if(!sqHackLen) |
||
1030 | { |
||
1031 | sqHackPtr = sqHack; |
||
1032 | sqHackLen = sqHackSeqLen; |
||
1033 | sqHackTime = 0; |
||
1034 | alTimeCount = 0; |
||
1035 | } |
||
1036 | } |
||
1037 | numreadysamples = samplesPerMusicTick; |
||
1038 | } |
||
1039 | } |
||
1040 | |||
1041 | /////////////////////////////////////////////////////////////////////////// |
||
1042 | // |
||
1043 | // SD_Startup() - starts up the Sound Mgr |
||
1044 | // Detects all additional sound hardware and installs my ISR |
||
1045 | // |
||
1046 | /////////////////////////////////////////////////////////////////////////// |
||
1047 | void |
||
1048 | SD_Startup(void) |
||
1049 | { |
||
1050 | int i; |
||
1051 | |||
1052 | if (SD_Started) |
||
1053 | return; |
||
1054 | |||
1055 | if(Mix_OpenAudio(param_samplerate, AUDIO_S16, 2, param_audiobuffer)) |
||
1056 | { |
||
1057 | printf("Unable to open audio: %s\n", Mix_GetError()); |
||
1058 | return; |
||
1059 | } |
||
1060 | |||
1061 | Mix_ReserveChannels(2); // reserve player and boss weapon channels |
||
1062 | Mix_GroupChannels(2, MIX_CHANNELS-1, 1); // group remaining channels |
||
1063 | |||
1064 | // Init music |
||
1065 | |||
1066 | samplesPerMusicTick = param_samplerate / 700; // SDL_t0FastAsmService played at 700Hz |
||
1067 | |||
1068 | if(YM3812Init(1,3579545,param_samplerate)) |
||
1069 | { |
||
1070 | printf("Unable to create virtual OPL!!\n"); |
||
1071 | } |
||
1072 | |||
1073 | for(i=1;i<0xf6;i++) |
||
1074 | YM3812Write(0,i,0); |
||
1075 | |||
1076 | YM3812Write(0,1,0x20); // Set WSE=1 |
||
1077 | // YM3812Write(0,8,0); // Set CSM=0 & SEL=0 // already set in for statement |
||
1078 | |||
1079 | Mix_HookMusic(SDL_IMFMusicPlayer, 0); |
||
1080 | Mix_ChannelFinished(SD_ChannelFinished); |
||
1081 | AdLibPresent = true; |
||
1082 | SoundBlasterPresent = true; |
||
1083 | |||
1084 | alTimeCount = 0; |
||
1085 | |||
1086 | SD_SetSoundMode(sdm_Off); |
||
1087 | SD_SetMusicMode(smm_Off); |
||
1088 | |||
1089 | SDL_SetupDigi(); |
||
1090 | |||
1091 | SD_Started = true; |
||
1092 | } |
||
1093 | |||
1094 | /////////////////////////////////////////////////////////////////////////// |
||
1095 | // |
||
1096 | // SD_Shutdown() - shuts down the Sound Mgr |
||
1097 | // Removes sound ISR and turns off whatever sound hardware was active |
||
1098 | // |
||
1099 | /////////////////////////////////////////////////////////////////////////// |
||
1100 | void |
||
1101 | SD_Shutdown(void) |
||
1102 | { |
||
1103 | if (!SD_Started) |
||
1104 | return; |
||
1105 | |||
1106 | SD_MusicOff(); |
||
1107 | SD_StopSound(); |
||
1108 | |||
1109 | for(int i = 0; i < STARTMUSIC - STARTDIGISOUNDS; i++) |
||
1110 | { |
||
1111 | if(SoundChunks[i]) Mix_FreeChunk(SoundChunks[i]); |
||
1112 | if(SoundBuffers[i]) free(SoundBuffers[i]); |
||
1113 | } |
||
1114 | |||
1115 | free(DigiList); |
||
1116 | |||
1117 | SD_Started = false; |
||
8646 | turbocat | 1118 | Mix_CloseAudio(); |
8645 | turbocat | 1119 | } |
1120 | |||
1121 | /////////////////////////////////////////////////////////////////////////// |
||
1122 | // |
||
1123 | // SD_PositionSound() - Sets up a stereo imaging location for the next |
||
1124 | // sound to be played. Each channel ranges from 0 to 15. |
||
1125 | // |
||
1126 | /////////////////////////////////////////////////////////////////////////// |
||
1127 | void |
||
1128 | SD_PositionSound(int leftvol,int rightvol) |
||
1129 | { |
||
1130 | LeftPosition = leftvol; |
||
1131 | RightPosition = rightvol; |
||
1132 | nextsoundpos = true; |
||
1133 | } |
||
1134 | |||
1135 | /////////////////////////////////////////////////////////////////////////// |
||
1136 | // |
||
1137 | // SD_PlaySound() - plays the specified sound on the appropriate hardware |
||
1138 | // |
||
1139 | /////////////////////////////////////////////////////////////////////////// |
||
1140 | boolean |
||
1141 | SD_PlaySound(soundnames sound) |
||
1142 | { |
||
1143 | boolean ispos; |
||
1144 | SoundCommon *s; |
||
1145 | int lp,rp; |
||
1146 | |||
1147 | lp = LeftPosition; |
||
1148 | rp = RightPosition; |
||
1149 | LeftPosition = 0; |
||
1150 | RightPosition = 0; |
||
1151 | |||
1152 | ispos = nextsoundpos; |
||
1153 | nextsoundpos = false; |
||
1154 | |||
1155 | if (sound == -1 || (DigiMode == sds_Off && SoundMode == sdm_Off)) |
||
1156 | return 0; |
||
1157 | |||
1158 | s = (SoundCommon *) SoundTable[sound]; |
||
1159 | |||
1160 | if ((SoundMode != sdm_Off) && !s) |
||
1161 | Quit("SD_PlaySound() - Uncached sound"); |
||
1162 | |||
1163 | if ((DigiMode != sds_Off) && (DigiMap[sound] != -1)) |
||
1164 | { |
||
1165 | if ((DigiMode == sds_PC) && (SoundMode == sdm_PC)) |
||
1166 | { |
||
1167 | #ifdef NOTYET |
||
1168 | if (s->priority < SoundPriority) |
||
1169 | return 0; |
||
1170 | |||
1171 | SDL_PCStopSound(); |
||
1172 | |||
1173 | SD_PlayDigitized(DigiMap[sound],lp,rp); |
||
1174 | SoundPositioned = ispos; |
||
1175 | SoundNumber = sound; |
||
1176 | SoundPriority = s->priority; |
||
1177 | #else |
||
1178 | return 0; |
||
1179 | #endif |
||
1180 | } |
||
1181 | else |
||
1182 | { |
||
1183 | #ifdef NOTYET |
||
1184 | if (s->priority < DigiPriority) |
||
1185 | return(false); |
||
1186 | #endif |
||
1187 | |||
1188 | int channel = SD_PlayDigitized(DigiMap[sound], lp, rp); |
||
1189 | SoundPositioned = ispos; |
||
1190 | DigiNumber = sound; |
||
1191 | DigiPriority = s->priority; |
||
1192 | return channel + 1; |
||
1193 | } |
||
1194 | |||
1195 | return(true); |
||
1196 | } |
||
1197 | |||
1198 | if (SoundMode == sdm_Off) |
||
1199 | return 0; |
||
1200 | |||
1201 | if (!s->length) |
||
1202 | Quit("SD_PlaySound() - Zero length sound"); |
||
1203 | if (s->priority < SoundPriority) |
||
1204 | return 0; |
||
1205 | |||
1206 | switch (SoundMode) |
||
1207 | { |
||
1208 | case sdm_PC: |
||
1209 | // SDL_PCPlaySound((PCSound *)s); |
||
1210 | break; |
||
1211 | case sdm_AdLib: |
||
1212 | SDL_ALPlaySound((AdLibSound *)s); |
||
1213 | break; |
||
1214 | } |
||
1215 | |||
1216 | SoundNumber = sound; |
||
1217 | SoundPriority = s->priority; |
||
1218 | |||
1219 | return 0; |
||
1220 | } |
||
1221 | |||
1222 | /////////////////////////////////////////////////////////////////////////// |
||
1223 | // |
||
1224 | // SD_SoundPlaying() - returns the sound number that's playing, or 0 if |
||
1225 | // no sound is playing |
||
1226 | // |
||
1227 | /////////////////////////////////////////////////////////////////////////// |
||
1228 | |||
1229 | word |
||
1230 | SD_SoundPlaying(void) |
||
1231 | { |
||
1232 | boolean result = false; |
||
1233 | |||
1234 | switch (SoundMode) |
||
1235 | { |
||
1236 | case sdm_PC: |
||
1237 | result = pcSound? true : false; |
||
1238 | break; |
||
1239 | case sdm_AdLib: |
||
1240 | result = alSound? true : false; |
||
1241 | break; |
||
1242 | } |
||
1243 | |||
1244 | if (result) |
||
1245 | return(SoundNumber); |
||
1246 | else |
||
1247 | return(false); |
||
1248 | } |
||
1249 | |||
1250 | /////////////////////////////////////////////////////////////////////////// |
||
1251 | // |
||
1252 | // SD_StopSound() - if a sound is playing, stops it |
||
1253 | // |
||
1254 | /////////////////////////////////////////////////////////////////////////// |
||
1255 | void |
||
1256 | SD_StopSound(void) |
||
1257 | { |
||
1258 | if (DigiPlaying) |
||
1259 | SD_StopDigitized(); |
||
1260 | |||
1261 | switch (SoundMode) |
||
1262 | { |
||
1263 | case sdm_PC: |
||
1264 | // SDL_PCStopSound(); |
||
1265 | break; |
||
1266 | case sdm_AdLib: |
||
1267 | SDL_ALStopSound(); |
||
1268 | break; |
||
1269 | } |
||
1270 | |||
1271 | SoundPositioned = false; |
||
1272 | |||
1273 | SDL_SoundFinished(); |
||
1274 | } |
||
1275 | |||
1276 | /////////////////////////////////////////////////////////////////////////// |
||
1277 | // |
||
1278 | // SD_WaitSoundDone() - waits until the current sound is done playing |
||
1279 | // |
||
1280 | /////////////////////////////////////////////////////////////////////////// |
||
1281 | void |
||
1282 | SD_WaitSoundDone(void) |
||
1283 | { |
||
1284 | while (SD_SoundPlaying()) |
||
1285 | SDL_Delay(5); |
||
1286 | } |
||
1287 | |||
1288 | /////////////////////////////////////////////////////////////////////////// |
||
1289 | // |
||
1290 | // SD_MusicOn() - turns on the sequencer |
||
1291 | // |
||
1292 | /////////////////////////////////////////////////////////////////////////// |
||
1293 | void |
||
1294 | SD_MusicOn(void) |
||
1295 | { |
||
1296 | sqActive = true; |
||
1297 | } |
||
1298 | |||
1299 | /////////////////////////////////////////////////////////////////////////// |
||
1300 | // |
||
1301 | // SD_MusicOff() - turns off the sequencer and any playing notes |
||
1302 | // returns the last music offset for music continue |
||
1303 | // |
||
1304 | /////////////////////////////////////////////////////////////////////////// |
||
1305 | int |
||
1306 | SD_MusicOff(void) |
||
1307 | { |
||
1308 | word i; |
||
1309 | |||
1310 | sqActive = false; |
||
1311 | switch (MusicMode) |
||
1312 | { |
||
1313 | case smm_AdLib: |
||
1314 | alOut(alEffects, 0); |
||
1315 | for (i = 0;i < sqMaxTracks;i++) |
||
1316 | alOut(alFreqH + i + 1, 0); |
||
1317 | break; |
||
1318 | } |
||
1319 | |||
1320 | return (int) (sqHackPtr-sqHack); |
||
1321 | } |
||
1322 | |||
1323 | /////////////////////////////////////////////////////////////////////////// |
||
1324 | // |
||
1325 | // SD_StartMusic() - starts playing the music pointed to |
||
1326 | // |
||
1327 | /////////////////////////////////////////////////////////////////////////// |
||
1328 | void |
||
1329 | SD_StartMusic(int chunk) |
||
1330 | { |
||
1331 | SD_MusicOff(); |
||
1332 | |||
1333 | if (MusicMode == smm_AdLib) |
||
1334 | { |
||
1335 | int32_t chunkLen = CA_CacheAudioChunk(chunk); |
||
1336 | sqHack = (word *)(void *) audiosegs[chunk]; // alignment is correct |
||
1337 | if(*sqHack == 0) sqHackLen = sqHackSeqLen = chunkLen; |
||
1338 | else sqHackLen = sqHackSeqLen = *sqHack++; |
||
1339 | sqHackPtr = sqHack; |
||
1340 | sqHackTime = 0; |
||
1341 | alTimeCount = 0; |
||
1342 | SD_MusicOn(); |
||
1343 | } |
||
1344 | } |
||
1345 | |||
1346 | void |
||
1347 | SD_ContinueMusic(int chunk, int startoffs) |
||
1348 | { |
||
1349 | SD_MusicOff(); |
||
1350 | |||
1351 | if (MusicMode == smm_AdLib) |
||
1352 | { |
||
1353 | int32_t chunkLen = CA_CacheAudioChunk(chunk); |
||
1354 | sqHack = (word *)(void *) audiosegs[chunk]; // alignment is correct |
||
1355 | if(*sqHack == 0) sqHackLen = sqHackSeqLen = chunkLen; |
||
1356 | else sqHackLen = sqHackSeqLen = *sqHack++; |
||
1357 | sqHackPtr = sqHack; |
||
1358 | |||
1359 | if(startoffs >= sqHackLen) |
||
1360 | { |
||
1361 | Quit("SD_StartMusic: Illegal startoffs provided!"); |
||
1362 | } |
||
1363 | |||
1364 | // fast forward to correct position |
||
1365 | // (needed to reconstruct the instruments) |
||
1366 | |||
1367 | for(int i = 0; i < startoffs; i += 2) |
||
1368 | { |
||
1369 | byte reg = *(byte *)sqHackPtr; |
||
1370 | byte val = *(((byte *)sqHackPtr) + 1); |
||
1371 | if(reg >= 0xb1 && reg <= 0xb8) val &= 0xdf; // disable play note flag |
||
1372 | else if(reg == 0xbd) val &= 0xe0; // disable drum flags |
||
1373 | |||
1374 | alOut(reg,val); |
||
1375 | sqHackPtr += 2; |
||
1376 | sqHackLen -= 4; |
||
1377 | } |
||
1378 | sqHackTime = 0; |
||
1379 | alTimeCount = 0; |
||
1380 | |||
1381 | SD_MusicOn(); |
||
1382 | } |
||
1383 | } |
||
1384 | |||
1385 | /////////////////////////////////////////////////////////////////////////// |
||
1386 | // |
||
1387 | // SD_FadeOutMusic() - starts fading out the music. Call SD_MusicPlaying() |
||
1388 | // to see if the fadeout is complete |
||
1389 | // |
||
1390 | /////////////////////////////////////////////////////////////////////////// |
||
1391 | void |
||
1392 | SD_FadeOutMusic(void) |
||
1393 | { |
||
1394 | switch (MusicMode) |
||
1395 | { |
||
1396 | case smm_AdLib: |
||
1397 | // DEBUG - quick hack to turn the music off |
||
1398 | SD_MusicOff(); |
||
1399 | break; |
||
1400 | } |
||
1401 | } |
||
1402 | |||
1403 | /////////////////////////////////////////////////////////////////////////// |
||
1404 | // |
||
1405 | // SD_MusicPlaying() - returns true if music is currently playing, false if |
||
1406 | // not |
||
1407 | // |
||
1408 | /////////////////////////////////////////////////////////////////////////// |
||
1409 | boolean |
||
1410 | SD_MusicPlaying(void) |
||
1411 | { |
||
1412 | boolean result; |
||
1413 | |||
1414 | switch (MusicMode) |
||
1415 | { |
||
1416 | case smm_AdLib: |
||
1417 | result = sqActive; |
||
1418 | break; |
||
1419 | default: |
||
1420 | result = false; |
||
1421 | break; |
||
1422 | } |
||
1423 | |||
1424 | return(result); |
||
1425 | }=>>>>>>>0xf6;i++) |