|
|
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.2 root 898: }
1.1.1.6 root 899: /* Select the right interpolation method. */
900: if (sample_handler == sample16_handler
901: || sample_handler == sample16i_crux_handler
902: || sample_handler == sample16i_rh_handler)
903: sample_handler = (currprefs.sound_interpol == 0 ? sample16_handler
904: : currprefs.sound_interpol == 1 ? sample16i_rh_handler
905: : sample16i_crux_handler);
906: else if (sample_handler == sample16s_handler
907: || sample_handler == sample16si_crux_handler
908: || sample_handler == sample16si_rh_handler)
909: sample_handler = (currprefs.sound_interpol == 0 ? sample16s_handler
910: : currprefs.sound_interpol == 1 ? sample16si_rh_handler
911: : sample16si_crux_handler);
1.1.1.7 root 912: if (currprefs.produce_sound == 0) {
913: eventtab[ev_audio].active = 0;
914: events_schedule ();
915: }
1.1.1.2 root 916: }
917:
918: void update_audio (void)
919: {
920: unsigned long int n_cycles;
921:
1.1.1.8 root 922: if (currprefs.produce_sound == 0 || savestate_state == STATE_RESTORE)
1.1.1.2 root 923: return;
924:
1.1.1.7 root 925: n_cycles = get_cycles () - last_cycles;
1.1.1.2 root 926: for (;;) {
927: unsigned long int best_evtime = n_cycles + 1;
928: if (audio_channel[0].state != 0 && best_evtime > audio_channel[0].evtime)
1.1.1.10 root 929: best_evtime = audio_channel[0].evtime;
1.1.1.2 root 930: if (audio_channel[1].state != 0 && best_evtime > audio_channel[1].evtime)
1.1.1.10 root 931: best_evtime = audio_channel[1].evtime;
1.1.1.2 root 932: if (audio_channel[2].state != 0 && best_evtime > audio_channel[2].evtime)
1.1.1.10 root 933: best_evtime = audio_channel[2].evtime;
1.1.1.2 root 934: if (audio_channel[3].state != 0 && best_evtime > audio_channel[3].evtime)
1.1.1.10 root 935: best_evtime = audio_channel[3].evtime;
1.1.1.7 root 936: if (audio_channel[4].state != 0 && best_evtime > audio_channel[4].evtime)
1.1.1.10 root 937: best_evtime = audio_channel[4].evtime;
1.1.1.7 root 938: if (audio_channel[5].state != 0 && best_evtime > audio_channel[5].evtime)
1.1.1.10 root 939: best_evtime = audio_channel[5].evtime;
1.1.1.7 root 940: if (currprefs.produce_sound > 1 && best_evtime > next_sample_evtime)
1.1.1.2 root 941: best_evtime = next_sample_evtime;
942:
943: if (best_evtime > n_cycles)
944: break;
945:
946: next_sample_evtime -= best_evtime;
947: audio_channel[0].evtime -= best_evtime;
948: audio_channel[1].evtime -= best_evtime;
949: audio_channel[2].evtime -= best_evtime;
950: audio_channel[3].evtime -= best_evtime;
1.1.1.7 root 951: audio_channel[4].evtime -= best_evtime;
952: audio_channel[5].evtime -= best_evtime;
1.1.1.2 root 953: n_cycles -= best_evtime;
1.1.1.3 root 954: if (next_sample_evtime == 0 && currprefs.produce_sound > 1) {
1.1.1.7 root 955: next_sample_evtime = scaled_sample_evtime;
1.1.1.2 root 956: (*sample_handler) ();
957: }
958: if (audio_channel[0].evtime == 0 && audio_channel[0].state != 0)
959: audio_handler (0);
960: if (audio_channel[1].evtime == 0 && audio_channel[1].state != 0)
961: audio_handler (1);
962: if (audio_channel[2].evtime == 0 && audio_channel[2].state != 0)
963: audio_handler (2);
964: if (audio_channel[3].evtime == 0 && audio_channel[3].state != 0)
965: audio_handler (3);
1.1.1.7 root 966: if (audio_channel[4].evtime == 0 && audio_channel[4].state != 0)
967: ahi_handler (4);
968: if (audio_channel[5].evtime == 0 && audio_channel[5].state != 0)
969: ahi_handler (5);
1.1.1.2 root 970: }
1.1.1.7 root 971: last_cycles = get_cycles () - n_cycles;
972: }
973:
974: void audio_evhandler (void)
975: {
976: if (currprefs.produce_sound == 0)
977: abort ();
978:
979: update_audio ();
980: schedule_audio ();
1.1.1.2 root 981: }
982:
983: void AUDxDAT (int nr, uae_u16 v)
984: {
985: struct audio_channel_data *cdp = audio_channel + nr;
986:
1.1.1.7 root 987: if (currprefs.produce_sound == 0)
988: return;
989:
1.1.1.2 root 990: update_audio ();
991:
992: cdp->dat = v;
993: if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
994: cdp->state = 2;
995: INTREQ(0x8000 | (0x80 << nr));
996: /* data_written = 2 ???? */
997: cdp->evtime = cdp->per;
1.1.1.7 root 998: schedule_audio ();
999: events_schedule ();
1.1.1.2 root 1000: }
1001: }
1002:
1003: void AUDxLCH (int nr, uae_u16 v)
1004: {
1005: update_audio ();
1006:
1007: audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((uae_u32)v << 16);
1008: }
1009:
1010: void AUDxLCL (int nr, uae_u16 v)
1011: {
1012: update_audio ();
1013:
1014: audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE);
1015: }
1016:
1017: void AUDxPER (int nr, uae_u16 v)
1018: {
1.1.1.7 root 1019: unsigned long per = v * CYCLE_UNIT;
1.1.1.2 root 1020: update_audio ();
1021:
1.1.1.7 root 1022: if (per == 0)
1023: per = PERIOD_MAX;
1.1.1.2 root 1024:
1.1.1.7 root 1025: if (per < maxhpos * CYCLE_UNIT / 2 && currprefs.produce_sound < 3)
1026: per = maxhpos * CYCLE_UNIT / 2;
1.1.1.2 root 1027:
1.1.1.8 root 1028: if (audio_channel[nr].per == PERIOD_MAX
1029: && per != PERIOD_MAX)
1030: {
1031: audio_channel[nr].evtime = CYCLE_UNIT;
1.1.1.9 root 1032: if (currprefs.produce_sound > 0) {
1033: schedule_audio ();
1034: events_schedule ();
1035: }
1.1.1.8 root 1036: }
1.1.1.7 root 1037: audio_channel[nr].per = per;
1.1.1.2 root 1038: }
1039:
1040: void AUDxLEN (int nr, uae_u16 v)
1041: {
1042: update_audio ();
1043: audio_channel[nr].len = v;
1044: }
1045:
1046: void AUDxVOL (int nr, uae_u16 v)
1047: {
1048: int v2 = v & 64 ? 63 : v & 63;
1049:
1050: update_audio ();
1051:
1052: audio_channel[nr].vol = v2;
1053: #ifndef MULTIPLICATION_PROFITABLE
1054: audio_channel[nr].voltbl = sound_table[v2];
1055: #endif
1.1 root 1056: }
1057:
1.1.1.7 root 1058: int init_audio (void)
1.1 root 1059: {
1.1.1.7 root 1060: int retval;
1061: /* Some backward compatibility hacks until every port initializes
1062: scaled_sample_evtime... */
1063: scaled_sample_evtime_ok = 0;
1064: retval = init_sound ();
1065: if (! scaled_sample_evtime_ok)
1066: scaled_sample_evtime = sample_evtime * CYCLE_UNIT;
1067: return retval;
1068: }
1069:
1070: static uae_u32 ahi_entry (void)
1071: {
1.1.1.10 root 1072: struct audio_channel_data *cdp;
1073: int opcode = m68k_dreg (regs, 0);
1074: int was_enabled;
1075:
1.1.1.7 root 1076: /* D0 contains the function code:
1077: 0: get current output sample rate.
1078: 1: get scaled divider for that frequency
1079: 2: enable/disable AHI output (boolean value in D1)
1080: 3: set right AHI channel info (LC in A0, period in D1, length D2, dmaen D3).
1081: 4: set left AHI channel info (LC in A0, period in D1, length D2, dmaen D3).
1082: 5: return interrupt state. */
1.1.1.10 root 1083: switch (opcode) {
1.1.1.7 root 1084: case 0:
1085: return currprefs.sound_freq;
1086: case 1:
1087: return scaled_sample_evtime;
1088: case 2:
1.1.1.10 root 1089: was_enabled = ahi_enabled;
1090: ahi_enabled = !!m68k_dreg (regs, 1);
1091: if (ahi_enabled > was_enabled) {
1092: audio_channel[4].evtime = CYCLE_UNIT;
1093: audio_channel[5].evtime = CYCLE_UNIT;
1094: if (currprefs.produce_sound > 0) {
1095: schedule_audio ();
1096: events_schedule ();
1097: }
1098: }
1.1.1.7 root 1099: return 0;
1100: case 3:
1.1.1.10 root 1101: case 4:
1.1.1.7 root 1102: /* Must set a frequency lower than sample rate, i.e. using a higher
1103: divider. */
1.1.1.10 root 1104: if (m68k_dreg (regs, 3) && m68k_dreg (regs, 1) < scaled_sample_evtime)
1.1.1.7 root 1105: return 0;
1.1.1.10 root 1106: cdp = audio_channel + opcode + 1;
1107: was_enabled = cdp->dmaen;
1108: cdp->lc = m68k_areg (regs, 0);
1109: cdp->per = m68k_dreg (regs, 1);
1110: cdp->len = m68k_dreg (regs, 2);
1111: cdp->dmaen = m68k_dreg (regs, 3);
1112: if (currprefs.produce_sound > 0) {
1113: if (cdp->dmaen && ! was_enabled) {
1114: cdp->state = 0;
1115: audio_channel_enable_dma (cdp);
1116: } else if (cdp->dmaen == 0) {
1117: cdp->state = 0;
1118: cdp->dat = 0;
1119: }
1120: schedule_audio ();
1121: events_schedule ();
1122: }
1.1.1.7 root 1123: return 1;
1124: case 5:
1125: return ahi_interrupt_state;
1.1.1.8 root 1126: default:
1127: return 0;
1.1.1.7 root 1128: }
1129: }
1130:
1131: void ahi_install (void)
1132: {
1133: uaecptr a = here ();
1.1.1.11! root 1134: org (RTAREA_BASE + 0xFFB0);
1.1.1.7 root 1135: calltrap (deftrap (ahi_entry));
1136: dw (RTS);
1137: org (a);
1.1 root 1138: }
1.1.1.8 root 1139:
1140: /* audio save/restore code FIXME: not working correctly */
1141: /* help needed */
1142:
1143: uae_u8 *restore_audio (uae_u8 *src, int i)
1144: {
1145: struct audio_channel_data *acd;
1146: uae_u16 p;
1147:
1148: acd = audio_channel + i;
1149: acd->state = restore_u8 ();
1150: acd->vol = restore_u8 ();
1151: acd->intreq2 = restore_u8 ();
1152: acd->data_written = restore_u8 ();
1153: acd->len = restore_u16 ();
1154: acd->wlen = restore_u16 ();
1155: p = restore_u16 ();
1156: acd->per = p ? p * CYCLE_UNIT : PERIOD_MAX;
1157: p = restore_u16 ();
1158: acd->wper = p ? p * CYCLE_UNIT : PERIOD_MAX;
1159: acd->lc = restore_u32 ();
1160: acd->pt = restore_u32 ();
1161: acd->evtime = restore_u32 ();
1162:
1163: return src;
1164: }
1165:
1166:
1167: uae_u8 *save_audio (int *len, int i)
1168: {
1169: struct audio_channel_data *acd;
1170: uae_u8 *dst = malloc (100);
1171: uae_u8 *dstbak = dst;
1172: uae_u16 p;
1173:
1174: acd = audio_channel + i;
1175: save_u8 ((uae_u8)acd->state);
1176: save_u8 (acd->vol);
1177: save_u8 (acd->intreq2);
1178: save_u8 (acd->data_written);
1179: save_u16 (acd->len);
1180: save_u16 (acd->wlen);
1181: p = acd->per == PERIOD_MAX ? 0 : acd->per / CYCLE_UNIT;
1182: save_u16 (p);
1183: p = acd->per == PERIOD_MAX ? 0 : acd->wper / CYCLE_UNIT;
1184: save_u16 (p);
1185: save_u32 (acd->lc);
1186: save_u32 (acd->pt);
1187: save_u32 (acd->evtime);
1188: *len = dst - dstbak;
1189: return dstbak;
1190: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.