1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * Toccata Z2 board emulation
5 *
6 * Copyright 2014-2015 Toni Wilen
7 *
8 */
9 
10 #include "sysconfig.h"
11 #include "sysdeps.h"
12 
13 #include "options.h"
14 #include "uae.h"
15 #include "memory.h"
16 #include "newcpu.h"
17 #include "debug.h"
18 #include "custom.h"
19 #include "sndboard.h"
20 #include "audio.h"
21 #include "autoconf.h"
22 #include "pci_hw.h"
23 #include "qemuvga/qemuaudio.h"
24 
25 static uae_u8 *sndboard_get_buffer(int *frames);
26 static void sndboard_release_buffer(uae_u8 *buffer, int frames);
27 static void sndboard_free_capture(void);
28 static bool sndboard_init_capture(int freq);
29 
30 static double base_event_clock;
31 
32 #define DEBUG_TOCCATA 0
33 
34 #define BOARD_MASK 65535
35 #define BOARD_SIZE 65536
36 
37 #define FIFO_SIZE 1024
38 #define FIFO_SIZE_HALF (FIFO_SIZE / 2)
39 
40 static const uae_u8 toccata_autoconfig[16] = { 0xc1, 12, 0, 0, 18260 >> 8, 18260 & 255 };
41 
42 struct toccata_data {
43 	uae_u8 acmemory[128];
44 	int configured;
45 	uae_u8 ad1848_index;
46 	uae_u8 ad1848_regs[16];
47 	uae_u8 ad1848_status;
48 	int autocalibration;
49 	uae_u8 toccata_status;
50 	int toccata_irq;
51 	int fifo_read_index;
52 	int fifo_write_index;
53 	int data_in_fifo;
54 	uae_u8 fifo[FIFO_SIZE];
55 
56 	int fifo_record_read_index;
57 	int fifo_record_write_index;
58 	int data_in_record_fifo;
59 	uae_u8 record_fifo[FIFO_SIZE];
60 
61 	int ch_sample[2];
62 
63 	int fifo_half;
64 	int toccata_active;
65 	int left_volume, right_volume;
66 
67 	int freq, freq_adjusted, channels, samplebits;
68 	int event_time, record_event_time;
69 	int record_event_counter;
70 	int bytespersample;
71 };
72 
73 static struct toccata_data toccata;
74 
75 extern addrbank toccata_bank;
76 
77 #define STATUS_ACTIVE 1
78 #define STATUS_RESET 2
79 #define STATUS_FIFO_CODEC 4
80 #define STATUS_FIFO_RECORD 8
81 #define STATUS_FIFO_PLAY 0x10
82 #define STATUS_RECORD_INTENA 0x40
83 #define STATUS_PLAY_INTENA 0x80
84 
85 #define STATUS_READ_INTREQ 128
86 #define STATUS_READ_PLAY_HALF 8
87 #define STATUS_READ_RECORD_HALF 4
88 
89 
update_sndboard_sound(double clk)90 void update_sndboard_sound (double clk)
91 {
92 	base_event_clock = clk;
93 }
94 
process_fifo(void)95 static void process_fifo(void)
96 {
97 	struct toccata_data *data = &toccata;
98 	int prev_data_in_fifo = data->data_in_fifo;
99 	if (data->data_in_fifo >= data->bytespersample) {
100 		uae_s16 v;
101 		if (data->samplebits == 8) {
102 			v = data->fifo[data->fifo_read_index] << 8;
103 			v |= data->fifo[data->fifo_read_index];
104 			data->ch_sample[0] = v;
105 			if (data->channels == 2) {
106 				v = data->fifo[data->fifo_read_index + 1] << 8;
107 				v |= data->fifo[data->fifo_read_index + 1];
108 			}
109 			data->ch_sample[1] = v;
110 		} else if (data->samplebits == 16) {
111 			v = data->fifo[data->fifo_read_index + 1] << 8;
112 			v |= data->fifo[data->fifo_read_index + 0];
113 			data->ch_sample[0] = v;
114 			if (data->channels == 2) {
115 				v = data->fifo[data->fifo_read_index + 3] << 8;
116 				v |= data->fifo[data->fifo_read_index + 2];
117 			}
118 			data->ch_sample[1] = v;
119 		}
120 		data->data_in_fifo -= data->bytespersample;
121 		data->fifo_read_index += data->bytespersample;
122 		data->fifo_read_index = data->fifo_read_index % FIFO_SIZE;
123 	}
124 
125 	data->ch_sample[0] = data->ch_sample[0] * data->left_volume / 32768;
126 	data->ch_sample[1] = data->ch_sample[1] * data->right_volume / 32768;
127 
128 	if (data->data_in_fifo < FIFO_SIZE_HALF && prev_data_in_fifo >= FIFO_SIZE_HALF)
129 		data->fifo_half |= STATUS_FIFO_PLAY;
130 }
131 
audio_state_sndboard_toccata(int ch)132 static void audio_state_sndboard_toccata(int ch)
133 {
134 	struct toccata_data *data = &toccata;
135 	if ((data->toccata_active & STATUS_FIFO_PLAY) && ch == 0) {
136 		// get all bytes at once to prevent fifo going out of sync
137 		// if fifo has for example 3 bytes remaining but we need 4.
138 		process_fifo();
139 	}
140 	if (data->toccata_active && (data->toccata_status & STATUS_FIFO_CODEC)) {
141 		int old = data->toccata_irq;
142 		if ((data->fifo_half & STATUS_FIFO_PLAY) && (data->toccata_status & STATUS_PLAY_INTENA) && (data->toccata_status & STATUS_FIFO_PLAY)) {
143 			data->toccata_irq |= STATUS_READ_PLAY_HALF;
144 		}
145 		if ((data->fifo_half & STATUS_FIFO_RECORD) && (data->toccata_status & STATUS_FIFO_RECORD) && (data->toccata_status & STATUS_FIFO_RECORD)) {
146 			data->toccata_irq |= STATUS_READ_RECORD_HALF;
147 		}
148 		if (old != data->toccata_irq) {
149 			sndboard_rethink();
150 #if DEBUG_TOCCATA > 2
151 			write_log(_T("TOCCATA IRQ\n"));
152 #endif
153 		}
154 	}
155 	audio_state_sndboard_state(ch, data->ch_sample[ch], data->event_time);
156 }
157 
get_volume(uae_u8 v)158 static int get_volume(uae_u8 v)
159 {
160 	int out;
161 	if (v & 0x80) // Mute bit
162 		return 0;
163 	out = v & 63;
164 	out = 64 - out;
165 	out *= 32768 / 64;
166 	return out;
167 }
168 
get_volume_in(uae_u8 v)169 static int get_volume_in(uae_u8 v)
170 {
171 	int out;
172 	if (v & 0x80) // Mute bit
173 		return 0;
174 	out = v & 31;
175 	out = 32 - out;
176 	out *= 32768 / 32;
177 	return out;
178 }
179 
calculate_volume_toccata(void)180 static void calculate_volume_toccata(void)
181 {
182 	struct toccata_data *data = &toccata;
183 	data->left_volume = (100 - currprefs.sound_volume_board) * 32768 / 100;
184 	data->right_volume = (100 - currprefs.sound_volume_board) * 32768 / 100;
185 
186 	data->left_volume = get_volume(data->ad1848_regs[6]) * data->left_volume / 32768;
187 	data->right_volume = get_volume(data->ad1848_regs[7]) * data->right_volume / 32768;
188 
189 	if (currprefs.sound_toccata_mixer) {
190 		sound_paula_volume[0] = get_volume_in(data->ad1848_regs[4]);
191 		sound_paula_volume[1] = get_volume_in(data->ad1848_regs[5]);
192 
193 		sound_cd_volume[0] = get_volume_in(data->ad1848_regs[2]);
194 		sound_cd_volume[1] = get_volume_in(data->ad1848_regs[3]);
195 	}
196 }
197 
198 static const int freq_crystals[] = {
199 	// AD1848 documentation says 24.576MHz but photo of board shows 24.582MHz
200 	// Added later: It seems there are boards that have correct crystal and
201 	// also boards with wrong crystal..
202 	// So we can use correct one in emulation.
203 	24576000,
204 	16934400
205 };
206 static const int freq_dividers[] = {
207 	3072,
208 	1536,
209 	896,
210 	768,
211 	448,
212 	384,
213 	512,
214 	2560
215 };
216 
codec_setup(void)217 static void codec_setup(void)
218 {
219 	struct toccata_data *data = &toccata;
220 	uae_u8 c = data->ad1848_regs[8];
221 
222 	data->channels = (c & 0x10) ? 2 : 1;
223 	data->samplebits = (c & 0x40) ? 16 : 8;
224 	data->freq = freq_crystals[c & 1] / freq_dividers[(c >> 1) & 7];
225 	data->freq_adjusted = ((data->freq + 49) / 100) * 100;
226 	data->bytespersample = (data->samplebits / 8) * data->channels;
227 	write_log(_T("TOCCATA start %s freq=%d bits=%d channels=%d\n"),
228 		((data->toccata_active & (STATUS_FIFO_PLAY | STATUS_FIFO_RECORD)) == (STATUS_FIFO_PLAY | STATUS_FIFO_RECORD)) ? _T("Play+Record") :
229 		(data->toccata_active & STATUS_FIFO_PLAY) ? _T("Play") : _T("Record"),
230 		data->freq, data->samplebits, data->channels);
231 }
232 
233 static int capture_buffer_size = 48000 * 2 * 2; // 1s at 48000/stereo/16bit
234 static int capture_read_index, capture_write_index;
235 static uae_u8 *capture_buffer;
236 
codec_start(void)237 static void codec_start(void)
238 {
239 	struct toccata_data *data = &toccata;
240 	data->toccata_active  = (data->ad1848_regs[9] & 1) ? STATUS_FIFO_PLAY : 0;
241 	data->toccata_active |= (data->ad1848_regs[9] & 2) ? STATUS_FIFO_RECORD : 0;
242 
243 	codec_setup();
244 
245 	data->event_time = base_event_clock * CYCLE_UNIT / data->freq;
246 	data->record_event_time = base_event_clock * CYCLE_UNIT / (data->freq_adjusted * data->bytespersample);
247 	data->record_event_counter = 0;
248 
249 	if (data->toccata_active & STATUS_FIFO_PLAY) {
250 		audio_enable_sndboard(true);
251 	}
252 	if (data->toccata_active & STATUS_FIFO_RECORD) {
253 		capture_buffer = xcalloc(uae_u8, capture_buffer_size);
254 		sndboard_init_capture(data->freq_adjusted);
255 	}
256 }
257 
codec_stop(void)258 static void codec_stop(void)
259 {
260 	struct toccata_data *data = &toccata;
261 	write_log(_T("TOCCATA stop\n"));
262 	data->toccata_active = 0;
263 	sndboard_free_capture();
264 	audio_enable_sndboard(false);
265 	xfree(capture_buffer);
266 	capture_buffer = NULL;
267 }
268 
sndboard_rethink(void)269 void sndboard_rethink(void)
270 {
271 	struct toccata_data *data = &toccata;
272 	uae_int_requested &= ~0x200;
273 	if (data->toccata_irq)
274 		uae_int_requested |= 0x200;
275 }
276 
sndboard_process_capture(void)277 static void sndboard_process_capture(void)
278 {
279 	struct toccata_data *data = &toccata;
280 	int frames;
281 	uae_u8 *buffer = sndboard_get_buffer(&frames);
282 	if (buffer && frames) {
283 		uae_u8 *p = buffer;
284 		int bytes = frames * 4;
285 		if (bytes >= capture_buffer_size - capture_write_index) {
286 			memcpy(capture_buffer + capture_write_index, p, capture_buffer_size - capture_write_index);
287 			p += capture_buffer_size - capture_write_index;
288 			bytes -=  capture_buffer_size - capture_write_index;
289 			capture_write_index = 0;
290 		}
291 		if (bytes > 0 && bytes < capture_buffer_size - capture_write_index) {
292 			memcpy(capture_buffer + capture_write_index, p, bytes);
293 			capture_write_index += bytes;
294 		}
295 	}
296 	sndboard_release_buffer(buffer, frames);
297 }
298 
sndboard_hsync(void)299 void sndboard_hsync(void)
300 {
301 	struct toccata_data *data = &toccata;
302 	static int capcnt;
303 
304 	if (data->autocalibration > 0)
305 		data->autocalibration--;
306 
307 	if (data->toccata_active & STATUS_FIFO_RECORD) {
308 
309 		capcnt--;
310 		if (capcnt <= 0) {
311 			sndboard_process_capture();
312 			capcnt = data->record_event_time * 312 / (maxhpos * CYCLE_UNIT);
313 		}
314 
315 		data->record_event_counter += maxhpos * CYCLE_UNIT;
316 		int bytes = data->record_event_counter / data->record_event_time;
317 		bytes &= ~3;
318 		if (bytes < 64 || capture_read_index == capture_write_index)
319 			return;
320 
321 		int oldfifo = data->data_in_record_fifo;
322 		int oldbytes = bytes;
323 		int size = FIFO_SIZE - data->data_in_record_fifo;
324 		while (size > 0 && capture_read_index != capture_write_index && bytes > 0) {
325 			uae_u8 *fifop = &data->fifo[data->fifo_record_write_index];
326 			uae_u8 *bufp = &capture_buffer[capture_read_index];
327 
328 			if (data->samplebits == 8) {
329 				fifop[0] = bufp[1];
330 				data->fifo_record_write_index++;
331 				data->data_in_record_fifo++;
332 				size--;
333 				bytes--;
334 				if (data->channels == 2) {
335 					fifop[1] = bufp[3];
336 					data->fifo_record_write_index++;
337 					data->data_in_record_fifo++;
338 					size--;
339 					bytes--;
340 				}
341 			} else if (data->samplebits == 16) {
342 				fifop[0] = bufp[1];
343 				fifop[1] = bufp[0];
344 				data->fifo_record_write_index += 2;
345 				data->data_in_record_fifo += 2;
346 				size -= 2;
347 				bytes -= 2;
348 				if (data->channels == 2) {
349 					fifop[2] = bufp[3];
350 					fifop[3] = bufp[2];
351 					data->fifo_record_write_index += 2;
352 					data->data_in_record_fifo += 2;
353 					size -= 2;
354 					bytes -= 2;
355 				}
356 			}
357 
358 			data->fifo_record_write_index %= FIFO_SIZE;
359 			capture_read_index += 4;
360 			if (capture_read_index >= capture_buffer_size)
361 				capture_read_index = 0;
362 		}
363 
364 		write_log(_T("%d %d %d %d\n"), capture_read_index, capture_write_index, size, bytes);
365 
366 		if (data->data_in_record_fifo > FIFO_SIZE_HALF && oldfifo <= FIFO_SIZE_HALF) {
367 			data->fifo_half |= STATUS_FIFO_RECORD;
368 			audio_state_sndboard(-1);
369 		}
370 		data->record_event_counter -= oldbytes * data->record_event_time;
371 	}
372 }
373 
sndboard_vsync_toccata(void)374 static void sndboard_vsync_toccata(void)
375 {
376 	struct toccata_data *data = &toccata;
377 	if (data->toccata_active) {
378 		calculate_volume_toccata();
379 		audio_activate();
380 	}
381 }
382 
toccata_put(uaecptr addr,uae_u8 v)383 static void toccata_put(uaecptr addr, uae_u8 v)
384 {
385 	struct toccata_data *data = &toccata;
386 	int idx = data->ad1848_index & 15;
387 
388 #if DEBUG_TOCCATA > 2
389 	if (addr & 0x4000)
390 		write_log(_T("TOCCATA PUT %08x %02x %d PC=%08X\n"), addr, v, idx, M68K_GETPC);
391 #endif
392 
393 	if ((addr & 0x6801) == 0x6001) {
394 		// AD1848 register 0
395 		data->ad1848_index = v;
396 	} else if ((addr & 0x6801) == 0x6801) {
397 		// AD1848 register 1
398 		uae_u8 old = data->ad1848_regs[idx];
399 		data->ad1848_regs[idx] = v;
400 #if DEBUG_TOCCATA > 0
401 		write_log(_T("TOCCATA PUT reg %d = %02x PC=%08x\n"), idx, v, M68K_GETPC);
402 #endif
403 		switch(idx)
404 		{
405 			case 9:
406 			if (v & 8) // ACI enabled
407 				data->autocalibration = 50;
408 			if (!(old & 3) && (v & 3))
409 				codec_start();
410 			else if ((old & 3) && !(v & 3))
411 				codec_stop();
412 			break;
413 
414 			case 2:
415 			case 3:
416 			case 4:
417 			case 5:
418 			case 6:
419 			case 7:
420 			case 8:
421 				calculate_volume_toccata();
422 			break;
423 
424 		}
425 	} else if ((addr & 0x6800) == 0x2000) {
426 		// FIFO input
427 		if (data->toccata_status & STATUS_FIFO_PLAY) {
428 			// 7202LA datasheet says fifo can't overflow
429 			if (((data->fifo_write_index + 1) % FIFO_SIZE) != data->fifo_read_index) {
430 				data->fifo[data->fifo_write_index] = v;
431 				data->fifo_write_index++;
432 				data->fifo_write_index %= FIFO_SIZE;
433 				data->data_in_fifo++;
434 			}
435 		}
436 		data->toccata_irq &= ~STATUS_READ_PLAY_HALF;
437 		data->fifo_half &= ~STATUS_FIFO_PLAY;
438 	} else if ((addr & 0x6800) == 0x0000) {
439 		// Board status
440 		if (v & STATUS_RESET) {
441 			codec_stop();
442 			data->toccata_status = 0;
443 			data->toccata_irq = 0;
444 			v = 0;
445 		}
446 		if (v == STATUS_ACTIVE) {
447 			data->fifo_write_index = 0;
448 			data->fifo_read_index = 0;
449 			data->data_in_fifo = 0;
450 			data->toccata_status = 0;
451 			data->toccata_irq = 0;
452 			data->fifo_half = 0;
453 		}
454 		data->toccata_status = v;
455 #if DEBUG_TOCCATA > 0
456 		write_log(_T("TOCCATA PUT STATUS %08x %02x %d PC=%08X\n"), addr, v, idx, M68K_GETPC);
457 #endif
458 	} else {
459 		write_log(_T("TOCCATA PUT UNKNOWN %08x\n"), addr);
460 	}
461 }
462 
toccata_get(uaecptr addr)463 static uae_u8 toccata_get(uaecptr addr)
464 {
465 	struct toccata_data *data = &toccata;
466 	int idx = data->ad1848_index & 15;
467 	uae_u8 v = 0;
468 
469 	if ((addr & 0x6801) == 0x6001) {
470 		// AD1848 register 0
471 		v = data->ad1848_index;
472 	} else if ((addr & 0x6801) == 0x6801) {
473 		// AD1848 register 1
474 		v = data->ad1848_regs[idx];
475 #if DEBUG_TOCCATA > 0
476 		write_log(_T("TOCCATA GET reg %d = %02x PC=%08x\n"), idx, v, M68K_GETPC);
477 #endif
478 		switch (idx)
479 		{
480 			case 11:
481 			if (data->autocalibration > 10 && data->autocalibration < 30)
482 				data->ad1848_regs[11] |= 0x20;
483 			else
484 				data->ad1848_regs[11] &= ~0x20;
485 			break;
486 			case 12:
487 				// revision
488 				v = 0x0a;
489 			break;
490 		}
491 	} else if ((addr & 0x6800) == 0x2000) {
492 		// FIFO output
493 		v = data->fifo[data->fifo_record_read_index];
494 		if (data->toccata_status & STATUS_FIFO_RECORD) {
495 			if (data->data_in_record_fifo > 0) {
496 				data->fifo_record_read_index++;
497 				data->fifo_record_read_index %= FIFO_SIZE;
498 				data->data_in_record_fifo--;
499 			}
500 		}
501 		data->toccata_irq &= ~STATUS_READ_RECORD_HALF;
502 		data->fifo_half &= ~STATUS_FIFO_RECORD;
503 	} else if ((addr & 0x6800) == 0x0000) {
504 		// Board status
505 		v = STATUS_READ_INTREQ; // active low
506 		if (data->toccata_irq) {
507 			v &= ~STATUS_READ_INTREQ;
508 			v |= data->toccata_irq;
509 			data->toccata_irq = 0;
510 		}
511 #if DEBUG_TOCCATA > 0
512 		write_log(_T("TOCCATA GET STATUS %08x %02x %d PC=%08X\n"), addr, v, idx, M68K_GETPC);
513 #endif
514 	} else {
515 		write_log(_T("TOCCATA GET UNKNOWN %08x\n"), addr);
516 	}
517 
518 #if DEBUG_TOCCATA > 2
519 	write_log(_T("TOCCATA GET %08x %02x %d PC=%08X\n"), addr, v, idx, M68K_GETPC);
520 #endif
521 	return v;
522 }
523 
toccata_bput(uaecptr addr,uae_u32 b)524 static void REGPARAM2 toccata_bput(uaecptr addr, uae_u32 b)
525 {
526 	struct toccata_data *data = &toccata;
527 	b &= 0xff;
528 	addr &= BOARD_MASK;
529 	if (!data->configured) {
530 		switch (addr)
531 		{
532 			case 0x48:
533 			map_banks_z2(&toccata_bank, expamem_z2_pointer >> 16, BOARD_SIZE >> 16);
534 			data->configured = 1;
535 			expamem_next(&toccata_bank, NULL);
536 			break;
537 			case 0x4c:
538 			data->configured = -1;
539 			expamem_shutup(&toccata_bank);
540 			break;
541 		}
542 		return;
543 	}
544 	if (data->configured > 0)
545 		toccata_put(addr, b);
546 }
547 
toccata_wput(uaecptr addr,uae_u32 b)548 static void REGPARAM2 toccata_wput(uaecptr addr, uae_u32 b)
549 {
550 	toccata_bput(addr + 0, b >> 8);
551 	toccata_bput(addr + 1, b >> 0);
552 }
553 
toccata_lput(uaecptr addr,uae_u32 b)554 static void REGPARAM2 toccata_lput(uaecptr addr, uae_u32 b)
555 {
556 	toccata_bput(addr + 0, b >> 24);
557 	toccata_bput(addr + 1, b >> 16);
558 	toccata_bput(addr + 2, b >>  8);
559 	toccata_bput(addr + 3, b >>  0);
560 }
561 
toccata_bget(uaecptr addr)562 static uae_u32 REGPARAM2 toccata_bget(uaecptr addr)
563 {
564 	struct toccata_data *data = &toccata;
565 	uae_u8 v = 0;
566 	addr &= BOARD_MASK;
567 	if (!data->configured) {
568 		if (addr >= sizeof data->acmemory)
569 			return 0;
570 		return data->acmemory[addr];
571 	}
572 	if (data->configured > 0)
573 		v = toccata_get(addr);
574 	return v;
575 }
toccata_wget(uaecptr addr)576 static uae_u32 REGPARAM2 toccata_wget(uaecptr addr)
577 {
578 	uae_u16 v;
579 	v = toccata_get(addr) << 8;
580 	v |= toccata_get(addr + 1) << 0;
581 	return v;
582 }
toccata_lget(uaecptr addr)583 static uae_u32 REGPARAM2 toccata_lget(uaecptr addr)
584 {
585 	uae_u32 v;
586 	v = toccata_get(addr) << 24;
587 	v |= toccata_get(addr + 1) << 16;
588 	v |= toccata_get(addr + 2) << 8;
589 	v |= toccata_get(addr + 3) << 0;
590 	return v;
591 }
592 
593 addrbank toccata_bank = {
594 	toccata_lget, toccata_wget, toccata_bget,
595 	toccata_lput, toccata_wput, toccata_bput,
596 	default_xlate, default_check, NULL, NULL, _T("Toccata"),
597 	dummy_lgeti, dummy_wgeti,
598 	ABFLAG_IO, S_READ, S_WRITE
599 };
600 
ew(uae_u8 * acmemory,int addr,uae_u32 value)601 static void ew (uae_u8 *acmemory, int addr, uae_u32 value)
602 {
603 	addr &= 0xffff;
604 	if (addr == 00 || addr == 02 || addr == 0x40 || addr == 0x42) {
605 		acmemory[addr] = (value & 0xf0);
606 		acmemory[addr + 2] = (value & 0x0f) << 4;
607 	} else {
608 		acmemory[addr] = ~(value & 0xf0);
609 		acmemory[addr + 2] = ~((value & 0x0f) << 4);
610 	}
611 }
612 
sndboard_init(int devnum)613 addrbank *sndboard_init(int devnum)
614 {
615 	struct toccata_data *data = &toccata;
616 	memset(data->ad1848_regs, 0, sizeof data->ad1848_regs);
617 	data->ad1848_regs[2] = 0x80;
618 	data->ad1848_regs[3] = 0x80;
619 	data->ad1848_regs[4] = 0x80;
620 	data->ad1848_regs[5] = 0x80;
621 	data->ad1848_regs[6] = 0x80;
622 	data->ad1848_regs[7] = 0x80;
623 	data->ad1848_regs[9] = 0x10;
624 	data->ad1848_status = 0xcc;
625 	data->ad1848_index = 0x40;
626 	calculate_volume_toccata();
627 
628 	data->configured = 0;
629 	memset(data->acmemory, 0xff, sizeof data->acmemory);
630 	for (int i = 0; i < 16; i++) {
631 		uae_u8 b = toccata_autoconfig[i];
632 		ew(data->acmemory, i * 4, b);
633 	}
634 	return &toccata_bank;
635 }
636 
sndboard_free(void)637 void sndboard_free(void)
638 {
639 	struct toccata_data *data = &toccata;
640 	data->toccata_irq = 0;
641 	uae_int_requested &= ~0x200;
642 }
643 
sndboard_reset(void)644 void sndboard_reset(void)
645 {
646 	struct toccata_data *data = &toccata;
647 	data->ch_sample[0] = 0;
648 	data->ch_sample[1] = 0;
649 	audio_enable_sndboard(false);
650 }
651 
652 struct fm801_data
653 {
654 	struct pci_board_state *pcibs;
655 	uaecptr play_dma[2], play_dma2[2];
656 	uae_u16 play_len, play_len2;
657 	uae_u16 play_control;
658 	uae_u16 interrupt_control;
659 	uae_u16 interrupt_status;
660 	int dmach;
661 	int freq;
662 	int bits;
663 	int ch;
664 	int bytesperframe;
665 	bool play_on;
666 	int left_volume, right_volume;
667 	int ch_sample[2];
668 	int event_time;
669 };
670 static struct fm801_data fm801;
671 static bool fm801_active;
672 static const int fm801_freq[16] = { 5500, 8000, 9600, 11025, 16000, 19200, 22050, 32000, 38400, 44100, 48000 };
673 
calculate_volume_fm801(void)674 static void calculate_volume_fm801(void)
675 {
676 	struct fm801_data *data = &fm801;
677 	data->left_volume = (100 - currprefs.sound_volume_board) * 32768 / 100;
678 	data->right_volume = (100 - currprefs.sound_volume_board) * 32768 / 100;
679 }
680 
sndboard_vsync_fm801(void)681 static void sndboard_vsync_fm801(void)
682 {
683 	audio_activate();
684 	calculate_volume_fm801();
685 }
686 
fm801_stop(struct fm801_data * data)687 static void fm801_stop(struct fm801_data *data)
688 {
689 	write_log(_T("FM801 STOP\n"));
690 	data->play_on = false;
691 	audio_enable_sndboard(false);
692 }
693 
fm801_swap_buffers(struct fm801_data * data)694 static void fm801_swap_buffers(struct fm801_data *data)
695 {
696 	data->dmach = data->dmach ? 0 : 1;
697 	data->play_dma2[data->dmach] = data->play_dma[data->dmach];
698 	data->play_len2 = data->play_len;
699 	// stop at the end of buffer
700 	if (!(data->play_control & 0x20) && !(data->play_control & 0x80))
701 		fm801_stop(data);
702 }
703 
fm801_interrupt(struct fm801_data * data)704 static void fm801_interrupt(struct fm801_data *data)
705 {
706 	if ((data->interrupt_status & 0x100) && !(data->interrupt_control & 1)) {
707 		data->pcibs->board->irq(data->pcibs, true);
708 	} else {
709 		data->pcibs->board->irq(data->pcibs, false);
710 	}
711 }
712 
audio_state_sndboard_fm801(int ch)713 static void audio_state_sndboard_fm801(int ch)
714 {
715 	struct fm801_data *data = &fm801;
716 
717 	if (data->play_on && ch == 0) {
718 		uae_u8 sample[2 * 6] = { 0 };
719 		uae_s16 l, r;
720 		pci_read_dma(data->pcibs, data->play_dma2[data->dmach], sample, data->bytesperframe);
721 		if (data->bits == 8) {
722 			if (data->ch == 1) {
723 				sample[1] = sample[0];
724 				sample[2] = sample[0];
725 				sample[3] = sample[0];
726 			} else {
727 				sample[2] = sample[1];
728 				sample[3] = sample[1];
729 				sample[1] = sample[0];
730 			}
731 		} else {
732 			if (data->ch == 1) {
733 				sample[2] = sample[0];
734 				sample[3] = sample[1];
735 			}
736 		}
737 		l = (sample[1] << 8) | sample[0];
738 		r = (sample[3] << 8) | sample[2];
739 		data->ch_sample[0] = l;
740 		data->ch_sample[1] = r;
741 		data->ch_sample[0] = data->ch_sample[0] * data->left_volume / 32768;
742 		data->ch_sample[1] = data->ch_sample[1] * data->right_volume / 32768;
743 
744 		data->play_len2 -= data->bytesperframe;
745 		data->play_dma2[data->dmach] += data->bytesperframe;
746 		if (data->play_len2 == 0xffff) {
747 			fm801_swap_buffers(data);
748 			data->interrupt_status |= 0x100;
749 			fm801_interrupt(data);
750 		}
751 	}
752 	audio_state_sndboard_state(ch, data->ch_sample[ch], data->event_time);
753 }
754 
fm801_hsync_handler(struct pci_board_state * pcibs)755 static void fm801_hsync_handler(struct pci_board_state *pcibs)
756 {
757 }
758 
fm801_play(struct fm801_data * data)759 static void fm801_play(struct fm801_data *data)
760 {
761 	uae_u16 control = data->play_control;
762 	int f = (control >> 8) & 15;
763 	data->freq = fm801_freq[f];
764 	if (!data->freq)
765 		data->freq = 44100;
766 	data->event_time = base_event_clock * CYCLE_UNIT / data->freq;
767 	data->bits = (control & 0x4000) ? 16 : 8;
768 	f = (control >> 12) & 3;
769 	switch (f)
770 	{
771 		case 0:
772 		data->ch = (control & 0x8000) ? 2 : 1;
773 		break;
774 		case 1:
775 		data->ch = 4;
776 		break;
777 		case 2:
778 		data->ch = 6;
779 		break;
780 		case 3:
781 		data->ch = 6;
782 		break;
783 	}
784 	data->bytesperframe = data->bits * data->ch / 8;
785 	data->play_on = true;
786 
787 	data->dmach = 1;
788 	fm801_swap_buffers(data);
789 
790 	calculate_volume_fm801();
791 
792 	write_log(_T("FM801 PLAY: freq=%d ch=%d bits=%d\n"), data->freq, data->ch, data->bits);
793 
794 	audio_enable_sndboard(true);
795 }
796 
fm801_pause(struct fm801_data * data,bool pause)797 static void fm801_pause(struct fm801_data *data, bool pause)
798 {
799 	write_log(_T("FM801 PAUSED %d\n"), pause);
800 }
fm801_control(struct fm801_data * data,uae_u16 control)801 static void fm801_control(struct fm801_data *data, uae_u16 control)
802 {
803 	uae_u16 old_control = data->play_control;
804 	data->play_control = control;
805 	data->play_control &= ~(8 | 16);
806 	if ((data->play_control & 0x20) && !(old_control & 0x20)) {
807 		fm801_play(data);
808 	} else if (!(data->play_control & 0x20) && (old_control & 0x20)) {
809 		if (data->play_control & 0x80)
810 			fm801_stop(data);
811 	} else if (data->play_control & 0x20) {
812 		if ((data->play_control & 0x40) && !(old_control & 0x40)) {
813 			fm801_pause(data, true);
814 		} else if (!(data->play_control & 0x40) && (old_control & 0x40)) {
815 			fm801_pause(data, true);
816 		}
817 	}
818 
819 }
820 
fm801_bput(struct pci_board_state * pcibs,uaecptr addr,uae_u32 b)821 static void REGPARAM2 fm801_bput(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b)
822 {
823 	struct fm801_data *data = &fm801;
824 }
fm801_wput(struct pci_board_state * pcibs,uaecptr addr,uae_u32 b)825 static void REGPARAM2 fm801_wput(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b)
826 {
827 	struct fm801_data *data = &fm801;
828 	switch (addr)
829 	{
830 		case 0x08:
831 		fm801_control(data, b);
832 		break;
833 		case 0x0a:
834 		data->play_len = b;
835 		break;
836 		case 0x56:
837 		data->interrupt_control = b;
838 		fm801_interrupt(data);
839 		break;
840 		case 0x5a:
841 		data->interrupt_status &= ~b;
842 		fm801_interrupt(data);
843 		break;
844 	}
845 }
fm801_lput(struct pci_board_state * pcibs,uaecptr addr,uae_u32 b)846 static void REGPARAM2 fm801_lput(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b)
847 {
848 	struct fm801_data *data = &fm801;
849 	switch (addr)
850 	{
851 		case 0x0c:
852 		data->play_dma[0] = b;
853 		break;
854 		case 0x10:
855 		data->play_dma[1] = b;
856 		break;
857 	}
858 }
fm801_bget(struct pci_board_state * pcibs,uaecptr addr)859 static uae_u32 REGPARAM2 fm801_bget(struct pci_board_state *pcibs, uaecptr addr)
860 {
861 	struct fm801_data *data = &fm801;
862 	uae_u32 v = 0;
863 	return v;
864 }
fm801_wget(struct pci_board_state * pcibs,uaecptr addr)865 static uae_u32 REGPARAM2 fm801_wget(struct pci_board_state *pcibs, uaecptr addr)
866 {
867 	struct fm801_data *data = &fm801;
868 	uae_u32 v = 0;
869 	switch (addr) {
870 		case 0x08:
871 		v = data->play_control;
872 		break;
873 		case 0x0a:
874 		v = data->play_len2;
875 		break;
876 		case 0x56:
877 		v = data->interrupt_control;
878 		break;
879 		case 0x5a:
880 		v = data->interrupt_status;
881 		break;
882 
883 	}
884 	return v;
885 }
fm801_lget(struct pci_board_state * pcibs,uaecptr addr)886 static uae_u32 REGPARAM2 fm801_lget(struct pci_board_state *pcibs, uaecptr addr)
887 {
888 	struct fm801_data *data = &fm801;
889 	uae_u32 v = 0;
890 	switch(addr)
891 	{
892 		case 0x0c:
893 		v = data->play_dma2[data->dmach];
894 		break;
895 		case 0x10:
896 		v = data->play_dma2[data->dmach];
897 		break;
898 	}
899 	return v;
900 }
901 
fm801_reset(struct pci_board_state * pcibs)902 static void fm801_reset(struct pci_board_state *pcibs)
903 {
904 	struct fm801_data *data = &fm801;
905 	data->play_control = 0xca00;
906 	data->interrupt_control = 0x00df;
907 }
908 
fm801_free(struct pci_board_state * pcibs)909 static void fm801_free(struct pci_board_state *pcibs)
910 {
911 	struct fm801_data *data = &fm801;
912 	fm801_active = false;
913 	fm801_stop(data);
914 }
915 
fm801_init(struct pci_board_state * pcibs)916 static bool fm801_init(struct pci_board_state *pcibs)
917 {
918 	struct fm801_data *data = &fm801;
919 	memset(data, 0, sizeof(struct fm801_data));
920 	data->pcibs = pcibs;
921 	fm801_active = true;
922 	return false;
923 }
924 
925 static const struct pci_config fm801_pci_config =
926 {
927 	0x1319, 0x0801, 0, 0, 0xb2, 0x040100, 0x80, 0x1319, 0x1319, 1, 0x04, 0x28, { 128 | 1, 0, 0, 0, 0, 0, 0 }
928 };
929 static const struct pci_config fm801_pci_config_func1 =
930 {
931 	0x1319, 0x0802, 0, 0, 0xb2, 0x098000, 0x80, 0x1319, 0x1319, 0, 0x04, 0x28, { 16 | 1, 0, 0, 0, 0, 0, 0 }
932 };
933 
934 const struct pci_board fm801_pci_board =
935 {
936 	_T("FM801"),
937 	&fm801_pci_config, fm801_init, fm801_free, fm801_reset, fm801_hsync_handler, pci_irq_callback,
938 	{
939 		{ fm801_lget, fm801_wget, fm801_bget, fm801_lput, fm801_wput, fm801_bput },
940 		{ NULL },
941 		{ NULL },
942 		{ NULL },
943 		{ NULL },
944 		{ NULL },
945 		{ NULL },
946 	}
947 };
948 
949 const struct pci_board fm801_pci_board_func1 =
950 {
951 	_T("FM801-2"),
952 	&fm801_pci_config_func1, NULL, NULL, NULL, NULL, NULL,
953 	{
954 		{ fm801_lget, fm801_wget, fm801_bget, fm801_lput, fm801_wput, fm801_bput },
955 		{ NULL },
956 		{ NULL },
957 		{ NULL },
958 		{ NULL },
959 		{ NULL },
960 		{ NULL },
961 	}
962 };
963 
solo1_reset(struct pci_board_state * pcibs)964 static void solo1_reset(struct pci_board_state *pcibs)
965 {
966 }
967 
solo1_free(struct pci_board_state * pcibs)968 static void solo1_free(struct pci_board_state *pcibs)
969 {
970 }
971 
solo1_init(struct pci_board_state * pcibs)972 static bool solo1_init(struct pci_board_state *pcibs)
973 {
974 	return true;
975 }
976 
solo1_sb_put(struct pci_board_state * pcibs,uaecptr addr,uae_u32 b)977 static void solo1_sb_put(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b)
978 {
979 }
solo1_sb_get(struct pci_board_state * pcibs,uaecptr addr)980 static uae_u32 solo1_sb_get(struct pci_board_state *pcibs, uaecptr addr)
981 {
982 	uae_u32 v = 0;
983 	return v;
984 }
985 
solo1_put(struct pci_board_state * pcibs,int bar,uaecptr addr,uae_u32 b)986 static void solo1_put(struct pci_board_state *pcibs, int bar, uaecptr addr, uae_u32 b)
987 {
988 	if (bar == 1)
989 		solo1_sb_put(pcibs, addr, b);
990 }
solo1_get(struct pci_board_state * pcibs,int bar,uaecptr addr)991 static uae_u32 solo1_get(struct pci_board_state *pcibs, int bar, uaecptr addr)
992 {
993 	uae_u32 v = 0;
994 	if (bar == 1)
995 		v = solo1_sb_get(pcibs, addr);
996 	return v;
997 }
998 
solo1_bput(struct pci_board_state * pcibs,uaecptr addr,uae_u32 b)999 static void REGPARAM2 solo1_bput(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b)
1000 {
1001 	write_log(_T("SOLO1 BPUT %08x=%08x %d\n"), addr, b, pcibs->selected_bar);
1002 	solo1_put(pcibs, pcibs->selected_bar, addr + 0, b >> 24);
1003 	solo1_put(pcibs, pcibs->selected_bar, addr + 1, b >> 16);
1004 	solo1_put(pcibs, pcibs->selected_bar, addr + 2, b >>  8);
1005 	solo1_put(pcibs, pcibs->selected_bar, addr + 3, b >>  0);
1006 }
solo1_wput(struct pci_board_state * pcibs,uaecptr addr,uae_u32 b)1007 static void REGPARAM2 solo1_wput(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b)
1008 {
1009 	write_log(_T("SOLO1 WPUT %08x=%08x %d\n"), addr, b, pcibs->selected_bar);
1010 	solo1_put(pcibs, pcibs->selected_bar, addr + 0, b >> 8);
1011 	solo1_put(pcibs, pcibs->selected_bar, addr + 1, b >> 0);
1012 }
solo1_lput(struct pci_board_state * pcibs,uaecptr addr,uae_u32 b)1013 static void REGPARAM2 solo1_lput(struct pci_board_state *pcibs, uaecptr addr, uae_u32 b)
1014 {
1015 	write_log(_T("SOLO1 LPUT %08x=%08x %d\n"), addr, b, pcibs->selected_bar);
1016 	solo1_put(pcibs, pcibs->selected_bar, addr, b);
1017 }
solo1_bget(struct pci_board_state * pcibs,uaecptr addr)1018 static uae_u32 REGPARAM2 solo1_bget(struct pci_board_state *pcibs, uaecptr addr)
1019 {
1020 	uae_u32 v = 0;
1021 	v = solo1_get(pcibs, pcibs->selected_bar, addr);
1022 	write_log(_T("SOLO1 BGET %08x %d\n"), addr, pcibs->selected_bar);
1023 	return v;
1024 }
solo1_wget(struct pci_board_state * pcibs,uaecptr addr)1025 static uae_u32 REGPARAM2 solo1_wget(struct pci_board_state *pcibs, uaecptr addr)
1026 {
1027 	uae_u32 v = 0;
1028 	write_log(_T("SOLO1 WGET %08x %d\n"), addr, pcibs->selected_bar);
1029 	return v;
1030 }
solo1_lget(struct pci_board_state * pcibs,uaecptr addr)1031 static uae_u32 REGPARAM2 solo1_lget(struct pci_board_state *pcibs, uaecptr addr)
1032 {
1033 	uae_u32 v = 0;
1034 	write_log(_T("SOLO1 LGET %08x %d\n"), addr, pcibs->selected_bar);
1035 	return v;
1036 }
1037 
1038 static const struct pci_config solo1_pci_config =
1039 {
1040 	0x125d, 0x1969, 0, 0, 0, 0x040100, 0, 0x125d, 0x1818, 1, 2, 0x18, { 16 | 1, 16 | 1, 16 | 1, 4 | 1, 4 | 1, 0, 0 }
1041 };
1042 const struct pci_board solo1_pci_board =
1043 {
1044 	_T("SOLO1"),
1045 	&solo1_pci_config, solo1_init, solo1_free, solo1_reset, NULL, pci_irq_callback,
1046 	{
1047 		{ solo1_lget, solo1_wget, solo1_bget, solo1_lput, solo1_wput, solo1_bput },
1048 		{ solo1_lget, solo1_wget, solo1_bget, solo1_lput, solo1_wput, solo1_bput },
1049 		{ solo1_lget, solo1_wget, solo1_bget, solo1_lput, solo1_wput, solo1_bput },
1050 		{ solo1_lget, solo1_wget, solo1_bget, solo1_lput, solo1_wput, solo1_bput },
1051 		{ solo1_lget, solo1_wget, solo1_bget, solo1_lput, solo1_wput, solo1_bput },
1052 		{ NULL },
1053 		{ NULL },
1054 	}
1055 };
1056 
1057 static SWVoiceOut *qemu_voice_out;
1058 
calculate_volume_qemu(void)1059 static void calculate_volume_qemu(void)
1060 {
1061 	SWVoiceOut *out = qemu_voice_out;
1062 	if (!out)
1063 		return;
1064 	out->left_volume = (100 - currprefs.sound_volume_board) * 32768 / 100;
1065 	out->right_volume = (100 - currprefs.sound_volume_board) * 32768 / 100;
1066 }
1067 
AUD_close_in(QEMUSoundCard * card,SWVoiceIn * sw)1068 void AUD_close_in(QEMUSoundCard *card, SWVoiceIn *sw)
1069 {
1070 }
AUD_read(SWVoiceIn * sw,void * pcm_buf,int size)1071 int AUD_read(SWVoiceIn *sw, void *pcm_buf, int size)
1072 {
1073 	return size;
1074 }
AUD_write(SWVoiceOut * sw,void * pcm_buf,int size)1075 int AUD_write(SWVoiceOut *sw, void *pcm_buf, int size)
1076 {
1077 	memcpy(sw->samplebuf, pcm_buf, size);
1078 	sw->samplebuf_total = size;
1079 	return sw->samplebuf_total;
1080 }
AUD_set_active_out(SWVoiceOut * sw,int on)1081 void AUD_set_active_out(SWVoiceOut *sw, int on)
1082 {
1083 	sw->active = on != 0;
1084 	sw->event_time = base_event_clock * CYCLE_UNIT / sw->freq;
1085 	sw->samplebuf_index = 0;
1086 	sw->samplebuf_total = 0;
1087 	calculate_volume_qemu();
1088 	audio_enable_sndboard(sw->active);
1089 }
AUD_set_active_in(SWVoiceIn * sw,int on)1090 void AUD_set_active_in(SWVoiceIn *sw, int on)
1091 {
1092 }
AUD_is_active_in(SWVoiceIn * sw)1093 int  AUD_is_active_in(SWVoiceIn *sw)
1094 {
1095 	return 0;
1096 }
AUD_close_out(QEMUSoundCard * card,SWVoiceOut * sw)1097 void AUD_close_out(QEMUSoundCard *card, SWVoiceOut *sw)
1098 {
1099 	qemu_voice_out = NULL;
1100 	audio_enable_sndboard(false);
1101 	xfree(sw);
1102 }
AUD_open_in(QEMUSoundCard * card,SWVoiceIn * sw,const char * name,void * callback_opaque,audio_callback_fn callback_fn,struct audsettings * settings)1103 SWVoiceIn *AUD_open_in(
1104 	QEMUSoundCard *card,
1105 	SWVoiceIn *sw,
1106 	const char *name,
1107 	void *callback_opaque,
1108 	audio_callback_fn callback_fn,
1109 struct audsettings *settings)
1110 {
1111 	return NULL;
1112 }
AUD_open_out(QEMUSoundCard * card,SWVoiceOut * sw,const char * name,void * callback_opaque,audio_callback_fn callback_fn,struct audsettings * settings)1113 SWVoiceOut *AUD_open_out(
1114 	QEMUSoundCard *card,
1115 	SWVoiceOut *sw,
1116 	const char *name,
1117 	void *callback_opaque,
1118 	audio_callback_fn callback_fn,
1119 	struct audsettings *settings)
1120 {
1121 	SWVoiceOut *out = sw;
1122 	if (!sw)
1123 		out = xcalloc(SWVoiceOut, 1);
1124 	int bits = 8;
1125 
1126 	if (settings->fmt >= AUD_FMT_U16)
1127 		bits = 16;
1128 	if (settings->fmt >= AUD_FMT_U32)
1129 		bits = 32;
1130 
1131 	out->callback = callback_fn;
1132 	out->opaque = callback_opaque;
1133 	out->bits = bits;
1134 	out->freq = settings->freq;
1135 	out->ch = settings->nchannels;
1136 	out->fmt = settings->fmt;
1137 	out->bytesperframe = out->ch * bits / 8;
1138 
1139 	write_log(_T("QEMU AUDIO: freq=%d ch=%d bits=%d (fmt=%d) '%s'\n"), out->freq, out->ch, bits, settings->fmt, name);
1140 
1141 	qemu_voice_out = out;
1142 
1143 	return out;
1144 }
1145 
audio_state_sndboard_qemu(int ch)1146 static void audio_state_sndboard_qemu(int ch)
1147 {
1148 	SWVoiceOut *out = qemu_voice_out;
1149 
1150 	if (!out)
1151 		return;
1152 	if (out->active && ch == 0) {
1153 		uae_s16 l, r;
1154 		if (out->samplebuf_index >= out->samplebuf_total) {
1155 			int maxsize = sizeof(out->samplebuf);
1156 			int size = 128 * out->bytesperframe;
1157 			if (size > maxsize)
1158 				size = maxsize;
1159 			out->callback(out->opaque, size);
1160 			out->samplebuf_index = 0;
1161 		}
1162 		uae_u8 *p = out->samplebuf + out->samplebuf_index;
1163 		if (out->bits == 8) {
1164 			if (out->ch == 1) {
1165 				p[1] = p[0];
1166 				p[2] = p[0];
1167 				p[3] = p[0];
1168 			} else {
1169 				p[2] = p[1];
1170 				p[3] = p[1];
1171 				p[1] = p[0];
1172 			}
1173 		} else {
1174 			if (out->ch == 1) {
1175 				p[2] = p[0];
1176 				p[3] = p[1];
1177 			}
1178 		}
1179 		l = (p[1] << 8) | p[0];
1180 		r = (p[3] << 8) | p[2];
1181 		out->ch_sample[0] = l;
1182 		out->ch_sample[1] = r;
1183 		out->ch_sample[0] = out->ch_sample[0] * out->left_volume / 32768;
1184 		out->ch_sample[1] = out->ch_sample[1] * out->right_volume / 32768;
1185 		out->samplebuf_index += out->bytesperframe;
1186 	}
1187 	audio_state_sndboard_state(ch, out->ch_sample[ch], out->event_time);
1188 }
1189 
1190 
sndboard_vsync_qemu(void)1191 static void sndboard_vsync_qemu(void)
1192 {
1193 	audio_activate();
1194 }
1195 
1196 
audio_state_sndboard(int ch)1197 void audio_state_sndboard(int ch)
1198 {
1199 	if (toccata.toccata_active)
1200 		audio_state_sndboard_toccata(ch);
1201 	if (fm801_active)
1202 		audio_state_sndboard_fm801(ch);
1203 	if (qemu_voice_out && qemu_voice_out->active)
1204 		audio_state_sndboard_qemu(ch);
1205 }
1206 
sndboard_vsync(void)1207 void sndboard_vsync(void)
1208 {
1209 	if (toccata.toccata_active)
1210 		sndboard_vsync_toccata();
1211 	if (fm801_active)
1212 		sndboard_vsync_fm801();
1213 	if (qemu_voice_out && qemu_voice_out->active)
1214 		sndboard_vsync_qemu();
1215 }
1216 
sndboard_ext_volume(void)1217 void sndboard_ext_volume(void)
1218 {
1219 	if (toccata.toccata_active)
1220 		calculate_volume_toccata();
1221 	if (fm801_active)
1222 		calculate_volume_fm801();
1223 	if (qemu_voice_out && qemu_voice_out->active)
1224 		calculate_volume_qemu();
1225 }
1226 
1227 #ifdef FSUAE
1228 
sndboard_get_buffer(int * frames)1229 static uae_u8 *sndboard_get_buffer(int *frames)
1230 {
1231 	return NULL;
1232 }
1233 
sndboard_release_buffer(uae_u8 * buffer,int frames)1234 static void sndboard_release_buffer(uae_u8 *buffer, int frames)
1235 {
1236 }
1237 
sndboard_free_capture(void)1238 static void sndboard_free_capture(void)
1239 {
1240 }
1241 
sndboard_init_capture(int freq)1242 static bool sndboard_init_capture(int freq)
1243 {
1244 	return false;
1245 }
1246 
1247 #else
1248 #ifdef _WIN32
1249 
1250 #include <mmdeviceapi.h>
1251 #include <Audioclient.h>
1252 
1253 #define REFTIMES_PER_SEC  10000000
1254 
1255 static const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
1256 static const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
1257 static const IID IID_IAudioClient = __uuidof(IAudioClient);
1258 static const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
1259 
1260 #define EXIT_ON_ERROR(hres) if (FAILED(hres)) { goto Exit; }
1261 #define SAFE_RELEASE(punk)  if ((punk) != NULL) { (punk)->Release(); (punk) = NULL; }
1262 
1263 static IMMDeviceEnumerator *pEnumerator = NULL;
1264 static IMMDevice *pDevice = NULL;
1265 static IAudioClient *pAudioClient = NULL;
1266 static IAudioCaptureClient *pCaptureClient = NULL;
1267 static bool capture_started;
1268 
sndboard_get_buffer(int * frames)1269 static uae_u8 *sndboard_get_buffer(int *frames)
1270 {
1271 	HRESULT hr;
1272 	UINT32 numFramesAvailable;
1273 	BYTE *pData;
1274 	DWORD flags = 0;
1275 
1276 	*frames = -1;
1277 	if (!capture_started)
1278 		return NULL;
1279 	hr = pCaptureClient->GetBuffer(&pData, &numFramesAvailable, &flags, NULL, NULL);
1280 	if (FAILED(hr)) {
1281 		write_log(_T("GetBuffer failed %08x\n"), hr);
1282 		return NULL;
1283 	}
1284 	*frames = numFramesAvailable;
1285 	return pData;
1286 }
1287 
sndboard_release_buffer(uae_u8 * buffer,int frames)1288 static void sndboard_release_buffer(uae_u8 *buffer, int frames)
1289 {
1290 	HRESULT hr;
1291 	if (!capture_started || frames < 0)
1292 		return;
1293 	hr = pCaptureClient->ReleaseBuffer(frames);
1294 	if (FAILED(hr)) {
1295 		write_log(_T("ReleaseBuffer failed %08x\n"), hr);
1296 	}
1297 }
1298 
sndboard_free_capture(void)1299 static void sndboard_free_capture(void)
1300 {
1301 	if (capture_started)
1302 		pAudioClient->Stop();
1303 	capture_started = false;
1304 	SAFE_RELEASE(pEnumerator)
1305 	SAFE_RELEASE(pDevice)
1306 	SAFE_RELEASE(pAudioClient)
1307 	SAFE_RELEASE(pCaptureClient)
1308 }
1309 
sndboard_init_capture(int freq)1310 static bool sndboard_init_capture(int freq)
1311 {
1312 	HRESULT hr;
1313 	WAVEFORMATEX wavfmtsrc;
1314 	WAVEFORMATEX *wavfmt2;
1315 	WAVEFORMATEX *wavfmt;
1316 
1317 	wavfmt2 = NULL;
1318 
1319 	hr = CoCreateInstance(
1320 		CLSID_MMDeviceEnumerator, NULL,
1321 		CLSCTX_ALL, IID_IMMDeviceEnumerator,
1322 		(void**)&pEnumerator);
1323 	EXIT_ON_ERROR(hr)
1324 
1325 	hr = pEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice);
1326 	EXIT_ON_ERROR(hr)
1327 
1328 	hr = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);
1329 	EXIT_ON_ERROR(hr)
1330 
1331 	memset (&wavfmtsrc, 0, sizeof wavfmtsrc);
1332 	wavfmtsrc.nChannels = 2;
1333 	wavfmtsrc.nSamplesPerSec = freq;
1334 	wavfmtsrc.wBitsPerSample = 16;
1335 	wavfmtsrc.wFormatTag = WAVE_FORMAT_PCM;
1336 	wavfmtsrc.cbSize = 0;
1337 	wavfmtsrc.nBlockAlign = wavfmtsrc.wBitsPerSample / 8 * wavfmtsrc.nChannels;
1338 	wavfmtsrc.nAvgBytesPerSec = wavfmtsrc.nBlockAlign * wavfmtsrc.nSamplesPerSec;
1339 
1340 	bool init = false;
1341 	AUDCLNT_SHAREMODE exc;
1342 	for (int mode = 0; mode < 2; mode++) {
1343 		exc = mode == 0 ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED;
1344 		int time = mode == 0 ? 0 : REFTIMES_PER_SEC / 50;
1345 
1346 		wavfmt = &wavfmtsrc;
1347 		hr = pAudioClient->IsFormatSupported(exc, &wavfmtsrc, &wavfmt2);
1348 		if (SUCCEEDED(hr)) {
1349 			hr = pAudioClient->Initialize(exc, 0, time, 0, wavfmt, NULL);
1350 			if (SUCCEEDED(hr)) {
1351 				init = true;
1352 				break;
1353 			}
1354 		}
1355 
1356 		if (hr == S_FALSE && wavfmt2) {
1357 			wavfmt = wavfmt2;
1358 			hr = pAudioClient->Initialize(exc, 0, time, 0, wavfmt, NULL);
1359 			if (SUCCEEDED(hr)) {
1360 				init = true;
1361 				break;
1362 			}
1363 		}
1364 	}
1365 
1366 	if (!init) {
1367 		write_log(_T("sndboard capture init, freq=%d, failed\n"), freq);
1368 		goto Exit;
1369 	}
1370 
1371 
1372 	hr = pAudioClient->GetService(IID_IAudioCaptureClient, (void**)&pCaptureClient);
1373 	EXIT_ON_ERROR(hr)
1374 
1375 	hr = pAudioClient->Start();
1376 	EXIT_ON_ERROR(hr)
1377 	capture_started = true;
1378 
1379 	CoTaskMemFree(wavfmt2);
1380 
1381 	write_log(_T("sndboard capture started: freq=%d mode=%s\n"), freq, exc == AUDCLNT_SHAREMODE_EXCLUSIVE ? _T("exclusive") : _T("shared"));
1382 
1383 	return true;
1384 Exit:;
1385 	CoTaskMemFree(wavfmt2);
1386 	write_log(_T("sndboard capture init failed %08x\n"), hr);
1387 	sndboard_free_capture();
1388 	return false;
1389 }
1390 
1391 #endif
1392 #endif
1393