|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * OS specific functions
5: *
6: * Copyright 1995, 1996, 1997 Bernd Schmidt
7: * Copyright 1996 Marcus Sundberg
8: * Copyright 1996 Manfred Thole
9: */
10:
11: #include "sysconfig.h"
12: #include "sysdeps.h"
13:
14: #include "config.h"
15: #include "options.h"
16: #include "memory.h"
17: #include "custom.h"
1.1.1.7 root 18: #include "newcpu.h"
19: #include "autoconf.h"
1.1 root 20: #include "gensound.h"
21: #include "sounddep/sound.h"
22: #include "events.h"
23: #include "audio.h"
1.1.1.8 root 24: #include "savestate.h"
1.1 root 25:
1.1.1.7 root 26: struct audio_channel_data audio_channel[6];
1.1.1.2 root 27: int sound_available = 0;
1.1 root 28: int sound_table[64][256];
1.1.1.2 root 29: void (*sample_handler) (void);
1.1.1.7 root 30:
31: /* Zero if we want to produce Paula output, nonzero if we want to produce
32: AHI output. */
33: static int ahi_enabled;
34:
35: /* Bit 0 is set if the right channel raised an interrupt, bit 1 is set if the
36: left channel raised an interrupt. */
37: static int ahi_interrupt_state;
38:
39: unsigned long sample_evtime, scaled_sample_evtime;
40: int scaled_sample_evtime_ok;
41:
1.1.1.2 root 42: static unsigned long last_cycles, next_sample_evtime;
1.1 root 43:
1.1.1.2 root 44: void init_sound_table16 (void)
1.1 root 45: {
46: int i,j;
47:
48: for (i = 0; i < 256; i++)
49: for (j = 0; j < 64; j++)
50: sound_table[j][i] = j * (uae_s8)i * (currprefs.stereo ? 2 : 1);
51: }
52:
53: void init_sound_table8 (void)
54: {
55: int i,j;
56:
57: for (i = 0; i < 256; i++)
58: for (j = 0; j < 64; j++)
59: sound_table[j][i] = (j * (uae_s8)i * (currprefs.stereo ? 2 : 1)) / 256;
60: }
61:
62: #define MULTIPLICATION_PROFITABLE
63:
64: #ifdef MULTIPLICATION_PROFITABLE
65: typedef uae_s8 sample8_t;
66: #define DO_CHANNEL_1(v, c) do { (v) *= audio_channel[c].vol; } while (0)
67: #define SBASEVAL8(logn) ((logn) == 1 ? SOUND8_BASE_VAL << 7 : SOUND8_BASE_VAL << 8)
68: #define SBASEVAL16(logn) ((logn) == 1 ? SOUND16_BASE_VAL >> 1 : SOUND16_BASE_VAL)
1.1.1.7 root 69: #define FINISH_DATA(data,b,logn) do { if (14 - (b) + (logn) > 0) (data) >>= 14 - (b) + (logn); else (data) <<= (b) - 14 - (logn); } while (0);
1.1 root 70: #else
71: typedef uae_u8 sample8_t;
72: #define DO_CHANNEL_1(v, c) do { (v) = audio_channel[c].voltbl[(v)]; } while (0)
73: #define SBASEVAL8(logn) SOUND8_BASE_VAL
74: #define SBASEVAL16(logn) SOUND16_BASE_VAL
75: #define FINISH_DATA(b,logn)
76: #endif
77:
1.1.1.7 root 78: /* Always put the right word before the left word. */
79: #define DELAY_BUFFER 32
80: static uae_u32 right_word_saved[DELAY_BUFFER];
81: static uae_u32 left_word_saved[DELAY_BUFFER];
82: static int saved_ptr;
1.1 root 83:
1.1.1.7 root 84: STATIC_INLINE void put_sound_word_right (uae_u32 w)
1.1 root 85: {
1.1.1.7 root 86: if (currprefs.mixed_stereo) {
87: right_word_saved[saved_ptr] = w;
88: return;
1.1 root 89: }
90:
1.1.1.7 root 91: PUT_SOUND_WORD_RIGHT (w);
1.1 root 92: }
93:
1.1.1.7 root 94: STATIC_INLINE void put_sound_word_left (uae_u32 w)
1.1.1.5 root 95: {
1.1.1.7 root 96: if (currprefs.mixed_stereo) {
97: uae_u32 rold, lold, rnew, lnew, tmp;
1.1.1.5 root 98:
1.1.1.7 root 99: left_word_saved[saved_ptr] = w;
100: lnew = w - SOUND16_BASE_VAL;
101: rnew = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
1.1.1.5 root 102:
1.1.1.7 root 103: saved_ptr = (saved_ptr + 1) & (DELAY_BUFFER - 1);
104: lold = left_word_saved[saved_ptr] - SOUND16_BASE_VAL;
105: tmp = (rnew * 5 + lold * 3) >> 3;
106: tmp += SOUND16_BASE_VAL;
107: PUT_SOUND_WORD_RIGHT (tmp);
1.1.1.5 root 108:
1.1.1.7 root 109: rold = right_word_saved[saved_ptr] - SOUND16_BASE_VAL;
110: w = (lnew * 5 + rold * 3) >> 3;
111: }
112: PUT_SOUND_WORD_LEFT (w);
113: }
1.1.1.5 root 114:
1.1.1.7 root 115: #define DO_CHANNEL(v, c) do { (v) &= audio_channel[c].adk_mask; data += v; } while (0);
1.1.1.5 root 116:
1.1.1.7 root 117: void sample16_handler (void)
118: {
119: if (ahi_enabled) {
120: uae_u16 word = audio_channel[4].current_sample + audio_channel[5].current_sample;
121: word >>= 1;
122: word += SOUND16_BASE_VAL;
123: PUT_SOUND_WORD (word);
124: } else {
125: uae_u32 data0 = audio_channel[0].current_sample;
126: uae_u32 data1 = audio_channel[1].current_sample;
127: uae_u32 data2 = audio_channel[2].current_sample;
128: uae_u32 data3 = audio_channel[3].current_sample;
129: DO_CHANNEL_1 (data0, 0);
130: DO_CHANNEL_1 (data1, 1);
131: DO_CHANNEL_1 (data2, 2);
132: DO_CHANNEL_1 (data3, 3);
133: data0 &= audio_channel[0].adk_mask;
134: data1 &= audio_channel[1].adk_mask;
135: data2 &= audio_channel[2].adk_mask;
136: data3 &= audio_channel[3].adk_mask;
137: data0 += data1;
138: data0 += data2;
139: data0 += data3;
140: {
141: uae_u32 data = SBASEVAL16(2) + data0;
142: FINISH_DATA (data, 16, 2);
143: PUT_SOUND_WORD (data);
144: }
1.1.1.5 root 145: }
146: check_sound_buffers ();
147: }
148:
1.1.1.7 root 149: void sample16i_rh_handler (void)
1.1.1.6 root 150: {
1.1.1.7 root 151: if (ahi_enabled) {
152: uae_u16 word = audio_channel[4].current_sample + audio_channel[5].current_sample;
153: word >>= 1;
154: word += SOUND16_BASE_VAL;
155: PUT_SOUND_WORD (word);
156: } else {
157: unsigned long delta, ratio;
1.1.1.6 root 158:
1.1.1.7 root 159: uae_u32 data0 = audio_channel[0].current_sample;
160: uae_u32 data1 = audio_channel[1].current_sample;
161: uae_u32 data2 = audio_channel[2].current_sample;
162: uae_u32 data3 = audio_channel[3].current_sample;
163: uae_u32 data0p = audio_channel[0].last_sample;
164: uae_u32 data1p = audio_channel[1].last_sample;
165: uae_u32 data2p = audio_channel[2].last_sample;
166: uae_u32 data3p = audio_channel[3].last_sample;
167: DO_CHANNEL_1 (data0, 0);
168: DO_CHANNEL_1 (data1, 1);
169: DO_CHANNEL_1 (data2, 2);
170: DO_CHANNEL_1 (data3, 3);
171: DO_CHANNEL_1 (data0p, 0);
172: DO_CHANNEL_1 (data1p, 1);
173: DO_CHANNEL_1 (data2p, 2);
174: DO_CHANNEL_1 (data3p, 3);
175:
176: data0 &= audio_channel[0].adk_mask;
177: data0p &= audio_channel[0].adk_mask;
178: data1 &= audio_channel[1].adk_mask;
179: data1p &= audio_channel[1].adk_mask;
180: data2 &= audio_channel[2].adk_mask;
181: data2p &= audio_channel[2].adk_mask;
182: data3 &= audio_channel[3].adk_mask;
183: data3p &= audio_channel[3].adk_mask;
184:
185: /* linear interpolation and summing up... */
186: delta = audio_channel[0].per;
187: ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
188: data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
189: delta = audio_channel[1].per;
190: ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
191: data0 += (data1 * (256 - ratio) + data1p * ratio) >> 8;
192: delta = audio_channel[2].per;
193: ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
194: data0 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
195: delta = audio_channel[3].per;
196: ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
197: data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
1.1.1.6 root 198:
1.1.1.7 root 199: {
200: uae_u32 data = SBASEVAL16(2) + data0;
201: FINISH_DATA (data, 16, 2);
202: PUT_SOUND_WORD (data);
203: }
1.1.1.6 root 204:
1.1.1.7 root 205: check_sound_buffers ();
1.1.1.6 root 206: }
1.1.1.7 root 207: }
1.1.1.6 root 208:
1.1.1.7 root 209: void sample16i_crux_handler (void)
210: {
211: if (ahi_enabled) {
212: uae_u16 word = audio_channel[4].current_sample + audio_channel[5].current_sample;
213: word >>= 1;
214: word += SOUND16_BASE_VAL;
215: PUT_SOUND_WORD (word);
216: } else {
217: uae_u32 data0 = audio_channel[0].current_sample;
218: uae_u32 data1 = audio_channel[1].current_sample;
219: uae_u32 data2 = audio_channel[2].current_sample;
220: uae_u32 data3 = audio_channel[3].current_sample;
221: uae_u32 data0p = audio_channel[0].last_sample;
222: uae_u32 data1p = audio_channel[1].last_sample;
223: uae_u32 data2p = audio_channel[2].last_sample;
224: uae_u32 data3p = audio_channel[3].last_sample;
225: DO_CHANNEL_1 (data0, 0);
226: DO_CHANNEL_1 (data1, 1);
227: DO_CHANNEL_1 (data2, 2);
228: DO_CHANNEL_1 (data3, 3);
229: DO_CHANNEL_1 (data0p, 0);
230: DO_CHANNEL_1 (data1p, 1);
231: DO_CHANNEL_1 (data2p, 2);
232: DO_CHANNEL_1 (data3p, 3);
233:
234: data0 &= audio_channel[0].adk_mask;
235: data0p &= audio_channel[0].adk_mask;
236: data1 &= audio_channel[1].adk_mask;
237: data1p &= audio_channel[1].adk_mask;
238: data2 &= audio_channel[2].adk_mask;
239: data2p &= audio_channel[2].adk_mask;
240: data3 &= audio_channel[3].adk_mask;
241: data3p &= audio_channel[3].adk_mask;
242:
243: {
244: struct audio_channel_data *cdp;
245: unsigned long ratio, ratio1;
246: #define INTERVAL (scaled_sample_evtime * 3)
247: cdp = audio_channel + 0;
248: ratio1 = cdp->per - cdp->evtime;
249: ratio = (ratio1 << 12) / INTERVAL;
250: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
251: ratio = 4096;
252: data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
253:
254: cdp = audio_channel + 1;
255: ratio1 = cdp->per - cdp->evtime;
256: ratio = (ratio1 << 12) / INTERVAL;
257: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
258: ratio = 4096;
259: data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
260:
261: cdp = audio_channel + 2;
262: ratio1 = cdp->per - cdp->evtime;
263: ratio = (ratio1 << 12) / INTERVAL;
264: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
265: ratio = 4096;
266: data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
267:
268: cdp = audio_channel + 3;
269: ratio1 = cdp->per - cdp->evtime;
270: ratio = (ratio1 << 12) / INTERVAL;
271: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
272: ratio = 4096;
273: data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
274: }
275: data1 += data2;
276: data0 += data3;
277: data0 += data1;
278: {
279: uae_u32 data = SBASEVAL16(2) + data0;
280: FINISH_DATA (data, 16, 2);
281: PUT_SOUND_WORD (data);
282: }
283: }
1.1.1.6 root 284: check_sound_buffers ();
285: }
286:
1.1.1.2 root 287: void sample8_handler (void)
1.1 root 288: {
289: uae_u32 data0 = audio_channel[0].current_sample;
290: uae_u32 data1 = audio_channel[1].current_sample;
291: uae_u32 data2 = audio_channel[2].current_sample;
292: uae_u32 data3 = audio_channel[3].current_sample;
293: DO_CHANNEL_1 (data0, 0);
294: DO_CHANNEL_1 (data1, 1);
295: DO_CHANNEL_1 (data2, 2);
296: DO_CHANNEL_1 (data3, 3);
297: data0 &= audio_channel[0].adk_mask;
298: data1 &= audio_channel[1].adk_mask;
299: data2 &= audio_channel[2].adk_mask;
300: data3 &= audio_channel[3].adk_mask;
301: data0 += data1;
302: data0 += data2;
303: data0 += data3;
304: {
305: uae_u32 data = SBASEVAL8(2) + data0;
1.1.1.7 root 306: FINISH_DATA (data, 8, 2);
1.1 root 307: PUT_SOUND_BYTE (data);
308: }
309:
310: check_sound_buffers ();
311: }
312:
313: #ifdef HAVE_STEREO_SUPPORT
1.1.1.2 root 314: void sample16s_handler (void)
1.1 root 315: {
1.1.1.7 root 316: if (ahi_enabled) {
317: PUT_SOUND_WORD_RIGHT (audio_channel[4].dat);
318: PUT_SOUND_WORD_LEFT (audio_channel[5].dat);
319: } else {
320: uae_u32 data0 = audio_channel[0].current_sample;
321: uae_u32 data1 = audio_channel[1].current_sample;
322: uae_u32 data2 = audio_channel[2].current_sample;
323: uae_u32 data3 = audio_channel[3].current_sample;
324: DO_CHANNEL_1 (data0, 0);
325: DO_CHANNEL_1 (data1, 1);
326: DO_CHANNEL_1 (data2, 2);
327: DO_CHANNEL_1 (data3, 3);
328:
329: data0 &= audio_channel[0].adk_mask;
330: data1 &= audio_channel[1].adk_mask;
331: data2 &= audio_channel[2].adk_mask;
332: data3 &= audio_channel[3].adk_mask;
1.1 root 333:
1.1.1.7 root 334: data0 += data3;
335: {
336: uae_u32 data = SBASEVAL16(1) + data0;
337: FINISH_DATA (data, 16, 1);
338: put_sound_word_right (data);
339: }
1.1 root 340:
1.1.1.7 root 341: data1 += data2;
342: {
343: uae_u32 data = SBASEVAL16(1) + data1;
344: FINISH_DATA (data, 16, 1);
345: put_sound_word_left (data);
346: }
1.1 root 347: }
1.1.1.7 root 348:
1.1 root 349: check_sound_buffers ();
350: }
351:
1.1.1.6 root 352: void sample16si_crux_handler (void)
1.1.1.5 root 353: {
1.1.1.7 root 354: if (ahi_enabled) {
355: PUT_SOUND_WORD_RIGHT (audio_channel[4].dat);
356: PUT_SOUND_WORD_LEFT (audio_channel[5].dat);
357: } else {
358: unsigned long delta, ratio;
1.1.1.5 root 359:
1.1.1.7 root 360: uae_u32 data0 = audio_channel[0].current_sample;
361: uae_u32 data1 = audio_channel[1].current_sample;
362: uae_u32 data2 = audio_channel[2].current_sample;
363: uae_u32 data3 = audio_channel[3].current_sample;
364: uae_u32 data0p = audio_channel[0].last_sample;
365: uae_u32 data1p = audio_channel[1].last_sample;
366: uae_u32 data2p = audio_channel[2].last_sample;
367: uae_u32 data3p = audio_channel[3].last_sample;
368:
369: DO_CHANNEL_1 (data0, 0);
370: DO_CHANNEL_1 (data1, 1);
371: DO_CHANNEL_1 (data2, 2);
372: DO_CHANNEL_1 (data3, 3);
373: DO_CHANNEL_1 (data0p, 0);
374: DO_CHANNEL_1 (data1p, 1);
375: DO_CHANNEL_1 (data2p, 2);
376: DO_CHANNEL_1 (data3p, 3);
377:
378: data0 &= audio_channel[0].adk_mask;
379: data0p &= audio_channel[0].adk_mask;
380: data1 &= audio_channel[1].adk_mask;
381: data1p &= audio_channel[1].adk_mask;
382: data2 &= audio_channel[2].adk_mask;
383: data2p &= audio_channel[2].adk_mask;
384: data3 &= audio_channel[3].adk_mask;
385: data3p &= audio_channel[3].adk_mask;
386:
387: {
388: struct audio_channel_data *cdp;
389: unsigned long ratio, ratio1;
390: #define INTERVAL (scaled_sample_evtime * 3)
391: cdp = audio_channel + 0;
392: ratio1 = cdp->per - cdp->evtime;
393: ratio = (ratio1 << 12) / INTERVAL;
394: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
395: ratio = 4096;
396: data0 = (data0 * ratio + data0p * (4096 - ratio)) >> 12;
397:
398: cdp = audio_channel + 1;
399: ratio1 = cdp->per - cdp->evtime;
400: ratio = (ratio1 << 12) / INTERVAL;
401: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
402: ratio = 4096;
403: data1 = (data1 * ratio + data1p * (4096 - ratio)) >> 12;
404:
405: cdp = audio_channel + 2;
406: ratio1 = cdp->per - cdp->evtime;
407: ratio = (ratio1 << 12) / INTERVAL;
408: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
409: ratio = 4096;
410: data2 = (data2 * ratio + data2p * (4096 - ratio)) >> 12;
411:
412: cdp = audio_channel + 3;
413: ratio1 = cdp->per - cdp->evtime;
414: ratio = (ratio1 << 12) / INTERVAL;
415: if (cdp->evtime < scaled_sample_evtime || ratio1 >= INTERVAL)
416: ratio = 4096;
417: data3 = (data3 * ratio + data3p * (4096 - ratio)) >> 12;
418: }
419: data1 += data2;
420: data0 += data3;
421: {
422: uae_u32 data = SBASEVAL16 (1) + data0;
423: FINISH_DATA (data, 16, 1);
424: put_sound_word_right (data);
425: }
1.1.1.6 root 426:
1.1.1.7 root 427: {
428: uae_u32 data = SBASEVAL16 (1) + data1;
429: FINISH_DATA (data, 16, 1);
430: put_sound_word_left (data);
431: }
432: }
1.1.1.6 root 433: check_sound_buffers ();
434: }
435:
436: void sample16si_rh_handler (void)
437: {
1.1.1.7 root 438: if (ahi_enabled) {
439: PUT_SOUND_WORD_RIGHT (audio_channel[4].dat);
440: PUT_SOUND_WORD_LEFT (audio_channel[5].dat);
441: } else {
442: unsigned long delta, ratio;
1.1.1.6 root 443:
1.1.1.7 root 444: uae_u32 data0 = audio_channel[0].current_sample;
445: uae_u32 data1 = audio_channel[1].current_sample;
446: uae_u32 data2 = audio_channel[2].current_sample;
447: uae_u32 data3 = audio_channel[3].current_sample;
448: uae_u32 data0p = audio_channel[0].last_sample;
449: uae_u32 data1p = audio_channel[1].last_sample;
450: uae_u32 data2p = audio_channel[2].last_sample;
451: uae_u32 data3p = audio_channel[3].last_sample;
452:
453: DO_CHANNEL_1 (data0, 0);
454: DO_CHANNEL_1 (data1, 1);
455: DO_CHANNEL_1 (data2, 2);
456: DO_CHANNEL_1 (data3, 3);
457: DO_CHANNEL_1 (data0p, 0);
458: DO_CHANNEL_1 (data1p, 1);
459: DO_CHANNEL_1 (data2p, 2);
460: DO_CHANNEL_1 (data3p, 3);
461:
462: data0 &= audio_channel[0].adk_mask;
463: data0p &= audio_channel[0].adk_mask;
464: data1 &= audio_channel[1].adk_mask;
465: data1p &= audio_channel[1].adk_mask;
466: data2 &= audio_channel[2].adk_mask;
467: data2p &= audio_channel[2].adk_mask;
468: data3 &= audio_channel[3].adk_mask;
469: data3p &= audio_channel[3].adk_mask;
470:
471: /* linear interpolation and summing up... */
472: delta = audio_channel[0].per;
473: ratio = ((audio_channel[0].evtime % delta) << 8) / delta;
474: data0 = (data0 * (256 - ratio) + data0p * ratio) >> 8;
475: delta = audio_channel[1].per;
476: ratio = ((audio_channel[1].evtime % delta) << 8) / delta;
477: data1 = (data1 * (256 - ratio) + data1p * ratio) >> 8;
478: delta = audio_channel[2].per;
479: ratio = ((audio_channel[2].evtime % delta) << 8) / delta;
480: data1 += (data2 * (256 - ratio) + data2p * ratio) >> 8;
481: delta = audio_channel[3].per;
482: ratio = ((audio_channel[3].evtime % delta) << 8) / delta;
483: data0 += (data3 * (256 - ratio) + data3p * ratio) >> 8;
484: {
485: uae_u32 data = SBASEVAL16 (1) + data0;
486: FINISH_DATA (data, 16, 1);
487: put_sound_word_right (data);
488: }
1.1.1.5 root 489:
1.1.1.7 root 490: {
491: uae_u32 data = SBASEVAL16 (1) + data1;
492: FINISH_DATA (data, 16, 1);
493: put_sound_word_left (data);
494: }
495: }
1.1.1.5 root 496: check_sound_buffers ();
497: }
498:
1.1.1.2 root 499: void sample8s_handler (void)
1.1 root 500: {
501: uae_u32 data0 = audio_channel[0].current_sample;
502: uae_u32 data1 = audio_channel[1].current_sample;
503: uae_u32 data2 = audio_channel[2].current_sample;
504: uae_u32 data3 = audio_channel[3].current_sample;
505: DO_CHANNEL_1 (data0, 0);
506: DO_CHANNEL_1 (data1, 1);
507: DO_CHANNEL_1 (data2, 2);
508: DO_CHANNEL_1 (data3, 3);
509:
510: data0 &= audio_channel[0].adk_mask;
511: data1 &= audio_channel[1].adk_mask;
512: data2 &= audio_channel[2].adk_mask;
513: data3 &= audio_channel[3].adk_mask;
514:
515: data0 += data3;
516: {
517: uae_u32 data = SBASEVAL8(1) + data0;
1.1.1.7 root 518: FINISH_DATA (data, 8, 1);
1.1 root 519: PUT_SOUND_BYTE_RIGHT (data);
520: }
521: data1 += data2;
522: {
523: uae_u32 data = SBASEVAL8(1) + data1;
1.1.1.7 root 524: FINISH_DATA (data, 8, 1);
1.1 root 525: PUT_SOUND_BYTE_LEFT (data);
526: }
527:
528: check_sound_buffers ();
529: }
530: #else
1.1.1.2 root 531: void sample8s_handler (void)
1.1 root 532: {
533: sample8_handler();
534: }
1.1.1.2 root 535: void sample16s_handler (void)
1.1 root 536: {
537: sample16_handler();
538: }
1.1.1.6 root 539: void sample16si_crux_handler (void)
540: {
541: sample16i_crux_handler();
542: }
543: void sample16si_rh_handler (void)
544: {
545: sample16i_rh_handler();
546: }
1.1 root 547: #endif
548:
1.1.1.2 root 549: static uae_u8 int2ulaw (int ch)
1.1 root 550: {
551: int mask;
552:
553: if (ch < 0) {
554: ch = -ch;
555: mask = 0x7f;
556: }
557: else {
558: mask = 0xff;
559: }
560:
561: if (ch < 32) {
562: ch = 0xF0 | ( 15 - (ch/2) );
563: } else if (ch < 96) {
564: ch = 0xE0 | ( 15 - (ch-32)/4 );
565: } else if (ch < 224) {
566: ch = 0xD0 | ( 15 - (ch-96)/8 );
567: } else if (ch < 480) {
568: ch = 0xC0 | ( 15 - (ch-224)/16 );
569: } else if (ch < 992 ) {
570: ch = 0xB0 | ( 15 - (ch-480)/32 );
571: } else if (ch < 2016) {
572: ch = 0xA0 | ( 15 - (ch-992)/64 );
573: } else if (ch < 4064) {
574: ch = 0x90 | ( 15 - (ch-2016)/128 );
575: } else if (ch < 8160) {
576: ch = 0x80 | ( 15 - (ch-4064)/256 );
577: } else {
578: ch = 0x80;
579: }
580: return (uae_u8)(mask & ch);
581: }
582:
583: void sample_ulaw_handler (void)
584: {
585: int nr;
586: uae_u32 data = 0;
587:
588: for (nr = 0; nr < 4; nr++) {
589: if (!(adkcon & (0x11 << nr))) {
590: uae_u32 d = audio_channel[nr].current_sample;
591: DO_CHANNEL_1 (d, nr);
592: data += d;
593: }
594: }
595: PUT_SOUND_BYTE (int2ulaw (data));
596: check_sound_buffers ();
597: }
598:
1.1.1.7 root 599: void schedule_audio (void)
600: {
601: unsigned long best = ~0ul;
602: int i;
603:
604: eventtab[ev_audio].active = 0;
605: eventtab[ev_audio].oldcycles = get_cycles ();
606: for (i = 0; i < 6; i++) {
607: struct audio_channel_data *cdp = audio_channel + i;
608:
609: if (cdp->state != 0) {
610: if (best > cdp->evtime) {
611: best = cdp->evtime;
612: eventtab[ev_audio].active = 1;
613: }
614: }
615: }
616: eventtab[ev_audio].evtime = get_cycles () + best;
617: }
618:
1.1 root 619: static void audio_handler (int nr)
620: {
621: struct audio_channel_data *cdp = audio_channel + nr;
622:
623: switch (cdp->state) {
624: case 0:
1.1.1.11 root 625: write_log ("Bug in sound code\n");
1.1 root 626: break;
627:
628: case 1:
629: /* We come here at the first hsync after DMA was turned on. */
1.1.1.7 root 630: cdp->evtime = maxhpos * CYCLE_UNIT;
1.1 root 631:
632: cdp->state = 5;
633: INTREQ(0x8000 | (0x80 << nr));
634: if (cdp->wlen != 1)
1.1.1.9 root 635: cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.10 root 636: cdp->nextdat = chipmem_wget (cdp->pt);
1.1 root 637:
638: cdp->pt += 2;
639: break;
640:
641: case 5:
642: /* We come here at the second hsync after DMA was turned on. */
643: if (currprefs.produce_sound == 0)
1.1.1.7 root 644: cdp->per = PERIOD_MAX;
1.1 root 645:
1.1.1.2 root 646: cdp->evtime = cdp->per;
1.1 root 647: cdp->dat = cdp->nextdat;
1.1.1.5 root 648: cdp->last_sample = cdp->current_sample;
1.1 root 649: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
650:
651: cdp->state = 2;
652: {
653: int audav = adkcon & (1 << nr);
654: int audap = adkcon & (16 << nr);
655: int napnav = (!audav && !audap) || audav;
656: if (napnav)
657: cdp->data_written = 2;
658: }
659: break;
660:
661: case 2:
662: /* We come here when a 2->3 transition occurs */
663: if (currprefs.produce_sound == 0)
1.1.1.7 root 664: cdp->per = PERIOD_MAX;
1.1 root 665:
1.1.1.5 root 666: cdp->last_sample = cdp->current_sample;
1.1 root 667: cdp->current_sample = (sample8_t)(cdp->dat & 0xFF);
1.1.1.2 root 668: cdp->evtime = cdp->per;
1.1 root 669:
670: cdp->state = 3;
671:
672: /* Period attachment? */
673: if (adkcon & (0x10 << nr)) {
674: if (cdp->intreq2 && cdp->dmaen)
1.1.1.9 root 675: INTREQ (0x8000 | (0x80 << nr));
1.1 root 676: cdp->intreq2 = 0;
677:
678: cdp->dat = cdp->nextdat;
679: if (cdp->dmaen)
680: cdp->data_written = 2;
681: if (nr < 3) {
682: if (cdp->dat == 0)
1.1.1.7 root 683: (cdp+1)->per = PERIOD_MAX;
684: else if (cdp->dat < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
685: (cdp+1)->per = maxhpos * CYCLE_UNIT / 2;
1.1 root 686: else
1.1.1.7 root 687: (cdp+1)->per = cdp->dat * CYCLE_UNIT;
1.1 root 688: }
689: }
690: break;
691:
692: case 3:
693: /* We come here when a 3->2 transition occurs */
694: if (currprefs.produce_sound == 0)
1.1.1.7 root 695: cdp->per = PERIOD_MAX;
1.1 root 696:
1.1.1.2 root 697: cdp->evtime = cdp->per;
1.1 root 698:
699: if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
700: cdp->state = 0;
1.1.1.5 root 701: cdp->last_sample = 0;
1.1 root 702: cdp->current_sample = 0;
703: break;
704: } else {
705: int audav = adkcon & (1 << nr);
706: int audap = adkcon & (16 << nr);
707: int napnav = (!audav && !audap) || audav;
708: cdp->state = 2;
709:
710: if ((cdp->intreq2 && cdp->dmaen && napnav)
711: || (napnav && !cdp->dmaen))
712: INTREQ(0x8000 | (0x80 << nr));
713: cdp->intreq2 = 0;
714:
715: cdp->dat = cdp->nextdat;
1.1.1.5 root 716: cdp->last_sample = cdp->current_sample;
1.1 root 717: cdp->current_sample = (sample8_t)(cdp->dat >> 8);
718:
719: if (cdp->dmaen && napnav)
720: cdp->data_written = 2;
721:
722: /* Volume attachment? */
723: if (audav) {
724: if (nr < 3) {
725: (cdp+1)->vol = cdp->dat;
726: #ifndef MULTIPLICATION_PROFITABLE
727: (cdp+1)->voltbl = sound_table[cdp->dat];
728: #endif
729: }
730: }
731: }
732: break;
733:
734: default:
735: cdp->state = 0;
736: break;
737: }
738: }
739:
1.1.1.7 root 740: static void ahi_handler (int nr)
741: {
742: struct audio_channel_data *cdp = audio_channel + nr;
743:
744: switch (cdp->state) {
1.1.1.10 root 745: case 0:
1.1.1.11 root 746: write_log ("Bug in sound code\n");
1.1.1.7 root 747: break;
748:
1.1.1.10 root 749: case 1:
750: cdp->evtime = cdp->per;
751: cdp->intreq2 = 0;
1.1.1.7 root 752:
1.1.1.10 root 753: cdp->state = 2;
1.1.1.7 root 754: if (cdp->wlen != 1)
1.1.1.9 root 755: cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.10 root 756: cdp->dat = chipmem_wget (cdp->pt);
1.1.1.7 root 757:
758: cdp->pt += 2;
759: break;
760:
1.1.1.10 root 761: case 2:
1.1.1.7 root 762: if (currprefs.produce_sound == 0)
763: cdp->per = PERIOD_MAX;
764:
1.1.1.10 root 765: /* Only do interrupts for one of the AHI channels. */
766: if (nr == 4 && cdp->intreq2)
767: /* Reuse AUD0 interrupt for AHI purposes. This is easier than
768: fixing the driver source to use AddIntServer instead of SetIntVector
769: for the EXTER interrupt. */
770: INTREQ (0x8080);
1.1.1.7 root 771: cdp->intreq2 = 0;
1.1.1.10 root 772: cdp->evtime = cdp->per;
1.1.1.7 root 773:
1.1.1.10 root 774: cdp->dat = chipmem_wget (cdp->pt);
775: cdp->pt += 2;
776: if (cdp->wlen == 1) {
777: cdp->pt = cdp->lc;
778: cdp->wlen = cdp->len;
779: cdp->intreq2 = 1;
780: } else
781: cdp->wlen = (cdp->wlen - 1) & 0xFFFF;
1.1.1.7 root 782: break;
783:
1.1.1.10 root 784: default:
1.1.1.7 root 785: cdp->state = 0;
786: break;
787: }
788: }
789:
1.1 root 790: void aud0_handler (void)
791: {
792: audio_handler (0);
793: }
794: void aud1_handler (void)
795: {
796: audio_handler (1);
797: }
798: void aud2_handler (void)
799: {
800: audio_handler (2);
801: }
802: void aud3_handler (void)
803: {
804: audio_handler (3);
805: }
806:
1.1.1.10 root 807: void audio_channel_enable_dma (struct audio_channel_data *cdp)
808: {
809: if (cdp->state == 0) {
810: cdp->state = 1;
811: cdp->pt = cdp->lc;
812: cdp->wper = cdp->per;
813: cdp->wlen = cdp->len;
814: cdp->data_written = 2;
815: cdp->evtime = eventtab[ev_hsync].evtime - get_cycles ();
816: }
817: }
818:
819: void audio_channel_disable_dma (struct audio_channel_data *cdp)
820: {
821: if (cdp->state == 1 || cdp->state == 5) {
822: cdp->state = 0;
823: cdp->last_sample = 0;
824: cdp->current_sample = 0;
825: }
826: }
827:
1.1 root 828: void audio_reset (void)
829: {
1.1.1.8 root 830: int i;
831: if (savestate_state != STATE_RESTORE) {
832: memset (audio_channel, 0, 4 * sizeof *audio_channel);
833: audio_channel[0].per = PERIOD_MAX;
834: audio_channel[1].per = PERIOD_MAX;
835: audio_channel[2].per = PERIOD_MAX;
836: audio_channel[3].per = PERIOD_MAX;
837: audio_channel[0].voltbl = sound_table[0];
838: audio_channel[1].voltbl = sound_table[0];
839: audio_channel[2].voltbl = sound_table[0];
840: audio_channel[3].voltbl = sound_table[0];
841: } else
842: for (i = 0; i < 4; i++)
843: audio_channel[i].dmaen = (dmacon & 0x200) && (dmacon & (1 << i));
844:
845:
846: memset (audio_channel + 4, 0, 2 * sizeof *audio_channel);
1.1.1.7 root 847: audio_channel[4].per = PERIOD_MAX;
848: audio_channel[5].per = PERIOD_MAX;
1.1.1.8 root 849:
850: #ifndef MULTIPLICATION_PROFITABLE
851: for (i = 0; i < 6; i++)
852: audio_channel[nr].voltbl = sound_table[audio_channel[nr].vol];
853: #endif
1.1.1.2 root 854:
855: last_cycles = 0;
1.1.1.7 root 856: ahi_enabled = 0;
857: ahi_interrupt_state = 0;
858: next_sample_evtime = scaled_sample_evtime;
1.1.1.8 root 859:
860: schedule_audio ();
1.1.1.2 root 861: }
862:
1.1.1.6 root 863: STATIC_INLINE int sound_prefs_changed (void)
1.1.1.2 root 864: {
865: return (changed_prefs.produce_sound != currprefs.produce_sound
866: || changed_prefs.stereo != currprefs.stereo
1.1.1.7 root 867: || changed_prefs.mixed_stereo != currprefs.mixed_stereo
1.1.1.9 root 868: || changed_prefs.sound_maxbsiz != currprefs.sound_maxbsiz
1.1.1.4 root 869: || changed_prefs.sound_freq != currprefs.sound_freq
1.1.1.2 root 870: || changed_prefs.sound_bits != currprefs.sound_bits);
871: }
872:
873: void check_prefs_changed_audio (void)
874: {
1.1.1.6 root 875: if (sound_available && sound_prefs_changed ()) {
876: close_sound ();
1.1.1.2 root 877:
1.1.1.6 root 878: currprefs.produce_sound = changed_prefs.produce_sound;
879: currprefs.stereo = changed_prefs.stereo;
1.1.1.7 root 880: currprefs.mixed_stereo = changed_prefs.mixed_stereo;
1.1.1.6 root 881: currprefs.sound_bits = changed_prefs.sound_bits;
882: currprefs.sound_freq = changed_prefs.sound_freq;
1.1.1.9 root 883: currprefs.sound_maxbsiz = changed_prefs.sound_maxbsiz;
1.1.1.6 root 884: if (currprefs.produce_sound >= 2) {
1.1.1.7 root 885: if (init_audio ()) {
886: last_cycles = get_cycles () - 1;
887: next_sample_evtime = scaled_sample_evtime;
1.1.1.6 root 888: } else
889: if (! sound_available) {
1.1.1.11 root 890: write_log ("Sound is not supported.\n");
1.1.1.6 root 891: } else {
1.1.1.11 root 892: write_log ("Sorry, can't initialize sound.\n");
1.1.1.6 root 893: currprefs.produce_sound = 0;
894: /* So we don't do this every frame */
895: changed_prefs.produce_sound = 0;
896: }
897: }
1.1.1.12! root 898: compute_vsynctime ();
1.1.1.2 root 899: }
1.1.1.6 root 900: /* Select the right interpolation method. */
901: if (sample_handler == sample16_handler
902: || sample_handler == sample16i_crux_handler
903: || sample_handler == sample16i_rh_handler)
904: sample_handler = (currprefs.sound_interpol == 0 ? sample16_handler
905: : currprefs.sound_interpol == 1 ? sample16i_rh_handler
906: : sample16i_crux_handler);
907: else if (sample_handler == sample16s_handler
908: || sample_handler == sample16si_crux_handler
909: || sample_handler == sample16si_rh_handler)
910: sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler
911: : currprefs.sound_interpol == 1 ? sample16si_rh_handler
912: : sample16si_crux_handler);
1.1.1.7 root 913: if (currprefs.produce_sound == 0) {
914: eventtab[ev_audio].active = 0;
915: events_schedule ();
916: }
1.1.1.2 root 917: }
918:
919: void update_audio (void)
920: {
921: unsigned long int n_cycles;
922:
1.1.1.8 root 923: if (currprefs.produce_sound == 0 || savestate_state == STATE_RESTORE)
1.1.1.2 root 924: return;
925:
1.1.1.7 root 926: n_cycles = get_cycles () - last_cycles;
1.1.1.2 root 927: for (;;) {
928: unsigned long int best_evtime = n_cycles + 1;
929: if (audio_channel[0].state != 0 && best_evtime > audio_channel[0].evtime)
1.1.1.10 root 930: best_evtime = audio_channel[0].evtime;
1.1.1.2 root 931: if (audio_channel[1].state != 0 && best_evtime > audio_channel[1].evtime)
1.1.1.10 root 932: best_evtime = audio_channel[1].evtime;
1.1.1.2 root 933: if (audio_channel[2].state != 0 && best_evtime > audio_channel[2].evtime)
1.1.1.10 root 934: best_evtime = audio_channel[2].evtime;
1.1.1.2 root 935: if (audio_channel[3].state != 0 && best_evtime > audio_channel[3].evtime)
1.1.1.10 root 936: best_evtime = audio_channel[3].evtime;
1.1.1.7 root 937: if (audio_channel[4].state != 0 && best_evtime > audio_channel[4].evtime)
1.1.1.10 root 938: best_evtime = audio_channel[4].evtime;
1.1.1.7 root 939: if (audio_channel[5].state != 0 && best_evtime > audio_channel[5].evtime)
1.1.1.10 root 940: best_evtime = audio_channel[5].evtime;
1.1.1.7 root 941: if (currprefs.produce_sound > 1 && best_evtime > next_sample_evtime)
1.1.1.2 root 942: best_evtime = next_sample_evtime;
943:
944: if (best_evtime > n_cycles)
945: break;
946:
947: next_sample_evtime -= best_evtime;
948: audio_channel[0].evtime -= best_evtime;
949: audio_channel[1].evtime -= best_evtime;
950: audio_channel[2].evtime -= best_evtime;
951: audio_channel[3].evtime -= best_evtime;
1.1.1.7 root 952: audio_channel[4].evtime -= best_evtime;
953: audio_channel[5].evtime -= best_evtime;
1.1.1.2 root 954: n_cycles -= best_evtime;
1.1.1.3 root 955: if (next_sample_evtime == 0 && currprefs.produce_sound > 1) {
1.1.1.7 root 956: next_sample_evtime = scaled_sample_evtime;
1.1.1.2 root 957: (*sample_handler) ();
958: }
959: if (audio_channel[0].evtime == 0 && audio_channel[0].state != 0)
960: audio_handler (0);
961: if (audio_channel[1].evtime == 0 && audio_channel[1].state != 0)
962: audio_handler (1);
963: if (audio_channel[2].evtime == 0 && audio_channel[2].state != 0)
964: audio_handler (2);
965: if (audio_channel[3].evtime == 0 && audio_channel[3].state != 0)
966: audio_handler (3);
1.1.1.7 root 967: if (audio_channel[4].evtime == 0 && audio_channel[4].state != 0)
968: ahi_handler (4);
969: if (audio_channel[5].evtime == 0 && audio_channel[5].state != 0)
970: ahi_handler (5);
1.1.1.2 root 971: }
1.1.1.7 root 972: last_cycles = get_cycles () - n_cycles;
973: }
974:
975: void audio_evhandler (void)
976: {
977: if (currprefs.produce_sound == 0)
978: abort ();
979:
980: update_audio ();
981: schedule_audio ();
1.1.1.2 root 982: }
983:
984: void AUDxDAT (int nr, uae_u16 v)
985: {
986: struct audio_channel_data *cdp = audio_channel + nr;
987:
1.1.1.7 root 988: if (currprefs.produce_sound == 0)
989: return;
990:
1.1.1.2 root 991: update_audio ();
992:
993: cdp->dat = v;
994: if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
995: cdp->state = 2;
996: INTREQ(0x8000 | (0x80 << nr));
997: /* data_written = 2 ???? */
998: cdp->evtime = cdp->per;
1.1.1.7 root 999: schedule_audio ();
1000: events_schedule ();
1.1.1.2 root 1001: }
1002: }
1003:
1004: void AUDxLCH (int nr, uae_u16 v)
1005: {
1006: update_audio ();
1007:
1008: audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
1009: }
1010:
1011: void AUDxLCL (int nr, uae_u16 v)
1012: {
1013: update_audio ();
1014:
1015: audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
1016: }
1017:
1018: void AUDxPER (int nr, uae_u16 v)
1019: {
1.1.1.7 root 1020: unsigned long per = v * CYCLE_UNIT;
1.1.1.2 root 1021: update_audio ();
1022:
1.1.1.7 root 1023: if (per == 0)
1024: per = PERIOD_MAX;
1.1.1.2 root 1025:
1.1.1.7 root 1026: if (per < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
1027: per = maxhpos * CYCLE_UNIT / 2;
1.1.1.2 root 1028:
1.1.1.8 root 1029: if (audio_channel[nr].per == PERIOD_MAX
1030: && per != PERIOD_MAX)
1031: {
1032: audio_channel[nr].evtime = CYCLE_UNIT;
1.1.1.9 root 1033: if (currprefs.produce_sound > 0) {
1034: schedule_audio ();
1035: events_schedule ();
1036: }
1.1.1.8 root 1037: }
1.1.1.7 root 1038: audio_channel[nr].per = per;
1.1.1.2 root 1039: }
1040:
1041: void AUDxLEN (int nr, uae_u16 v)
1042: {
1043: update_audio ();
1044: audio_channel[nr].len = v;
1045: }
1046:
1047: void AUDxVOL (int nr, uae_u16 v)
1048: {
1049: int v2 = v & 64 ? 63 : v & 63;
1050:
1051: update_audio ();
1052:
1053: audio_channel[nr].vol = v2;
1054: #ifndef MULTIPLICATION_PROFITABLE
1055: audio_channel[nr].voltbl = sound_table[v2];
1056: #endif
1.1 root 1057: }
1058:
1.1.1.7 root 1059: int init_audio (void)
1.1 root 1060: {
1.1.1.7 root 1061: int retval;
1062: /* Some backward compatibility hacks until every port initializes
1063: scaled_sample_evtime... */
1064: scaled_sample_evtime_ok = 0;
1065: retval = init_sound ();
1066: if (! scaled_sample_evtime_ok)
1067: scaled_sample_evtime = sample_evtime * CYCLE_UNIT;
1068: return retval;
1069: }
1070:
1071: static uae_u32 ahi_entry (void)
1072: {
1.1.1.10 root 1073: struct audio_channel_data *cdp;
1074: int opcode = m68k_dreg (regs, 0);
1075: int was_enabled;
1076:
1.1.1.7 root 1077: /* D0 contains the function code:
1078: 0: get current output sample rate.
1079: 1: get scaled divider for that frequency
1080: 2: enable/disable AHI output (boolean value in D1)
1081: 3: set right AHI channel info (LC in A0, period in D1, length D2, dmaen D3).
1082: 4: set left AHI channel info (LC in A0, period in D1, length D2, dmaen D3).
1083: 5: return interrupt state. */
1.1.1.10 root 1084: switch (opcode) {
1.1.1.7 root 1085: case 0:
1086: return currprefs.sound_freq;
1087: case 1:
1088: return scaled_sample_evtime;
1089: case 2:
1.1.1.10 root 1090: was_enabled = ahi_enabled;
1091: ahi_enabled = !!m68k_dreg (regs, 1);
1092: if (ahi_enabled > was_enabled) {
1093: audio_channel[4].evtime = CYCLE_UNIT;
1094: audio_channel[5].evtime = CYCLE_UNIT;
1095: if (currprefs.produce_sound > 0) {
1096: schedule_audio ();
1097: events_schedule ();
1098: }
1099: }
1.1.1.7 root 1100: return 0;
1101: case 3:
1.1.1.10 root 1102: case 4:
1.1.1.7 root 1103: /* Must set a frequency lower than sample rate, i.e. using a higher
1104: divider. */
1.1.1.10 root 1105: if (m68k_dreg (regs, 3) && m68k_dreg (regs, 1) < scaled_sample_evtime)
1.1.1.7 root 1106: return 0;
1.1.1.10 root 1107: cdp = audio_channel + opcode + 1;
1108: was_enabled = cdp->dmaen;
1109: cdp->lc = m68k_areg (regs, 0);
1110: cdp->per = m68k_dreg (regs, 1);
1111: cdp->len = m68k_dreg (regs, 2);
1112: cdp->dmaen = m68k_dreg (regs, 3);
1113: if (currprefs.produce_sound > 0) {
1114: if (cdp->dmaen && ! was_enabled) {
1115: cdp->state = 0;
1116: audio_channel_enable_dma (cdp);
1117: } else if (cdp->dmaen == 0) {
1118: cdp->state = 0;
1119: cdp->dat = 0;
1120: }
1121: schedule_audio ();
1122: events_schedule ();
1123: }
1.1.1.7 root 1124: return 1;
1125: case 5:
1126: return ahi_interrupt_state;
1.1.1.8 root 1127: default:
1128: return 0;
1.1.1.7 root 1129: }
1130: }
1131:
1132: void ahi_install (void)
1133: {
1134: uaecptr a = here ();
1.1.1.11 root 1135: org (RTAREA_BASE + 0xFFB0);
1.1.1.7 root 1136: calltrap (deftrap (ahi_entry));
1137: dw (RTS);
1138: org (a);
1.1 root 1139: }
1.1.1.8 root 1140:
1141: /* audio save/restore code FIXME: not working correctly */
1142: /* help needed */
1143:
1144: uae_u8 *restore_audio (uae_u8 *src, int i)
1145: {
1146: struct audio_channel_data *acd;
1147: uae_u16 p;
1148:
1149: acd = audio_channel + i;
1150: acd->state = restore_u8 ();
1151: acd->vol = restore_u8 ();
1152: acd->intreq2 = restore_u8 ();
1153: acd->data_written = restore_u8 ();
1154: acd->len = restore_u16 ();
1155: acd->wlen = restore_u16 ();
1156: p = restore_u16 ();
1157: acd->per = p ? p * CYCLE_UNIT : PERIOD_MAX;
1158: p = restore_u16 ();
1159: acd->wper = p ? p * CYCLE_UNIT : PERIOD_MAX;
1160: acd->lc = restore_u32 ();
1161: acd->pt = restore_u32 ();
1162: acd->evtime = restore_u32 ();
1163:
1164: return src;
1165: }
1166:
1167:
1168: uae_u8 *save_audio (int *len, int i)
1169: {
1170: struct audio_channel_data *acd;
1171: uae_u8 *dst = malloc (100);
1172: uae_u8 *dstbak = dst;
1173: uae_u16 p;
1174:
1175: acd = audio_channel + i;
1176: save_u8 ((uae_u8)acd->state);
1177: save_u8 (acd->vol);
1178: save_u8 (acd->intreq2);
1179: save_u8 (acd->data_written);
1180: save_u16 (acd->len);
1181: save_u16 (acd->wlen);
1182: p = acd->per == PERIOD_MAX ? 0 : acd->per / CYCLE_UNIT;
1183: save_u16 (p);
1184: p = acd->per == PERIOD_MAX ? 0 : acd->wper / CYCLE_UNIT;
1185: save_u16 (p);
1186: save_u32 (acd->lc);
1187: save_u32 (acd->pt);
1188: save_u32 (acd->evtime);
1189: *len = dst - dstbak;
1190: return dstbak;
1191: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.