|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * OS specific functions
5: *
6: * (c) 1995 Bernd Schmidt
7: * (c) 1996 Marcus Sundberg
8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12:
13: #include "config.h"
14: #include "options.h"
15: #include "memory.h"
16: #include "custom.h"
17: #include "os.h"
18: #include "events.h"
19:
20: #ifndef DONT_WANT_SOUND
21: static void sample16_handler(void);
22: static void sample8_handler(void);
23: #endif
24:
25: int joystickpresent = 0;
26:
27: #ifdef HAVE_LINUX_JOYSTICK_H
28:
29: static int js0;
30:
31: struct JS_DATA_TYPE jscal;
32:
33: void read_joystick(UWORD *dir, int *button)
34: {
35: static int minx = MAXINT, maxx = MININT,
36: miny = MAXINT, maxy = MININT;
37: int left = 0, right = 0, top = 0, bot = 0;
38: struct JS_DATA_TYPE buffer;
39: int len;
40:
41: *dir = 0;
42: *button = 0;
43: if (!joystickpresent)
44: return;
45:
46: len = read(js0, &buffer, sizeof(buffer));
47: if (len != sizeof(buffer))
48: return;
49:
50: if (buffer.x < minx) minx = buffer.x;
51: if (buffer.y < miny) miny = buffer.y;
52: if (buffer.x > maxx) maxx = buffer.x;
53: if (buffer.y > maxy) maxy = buffer.y;
54:
55: if (buffer.x < (minx + (maxx-minx)/3))
56: left = 1;
57: else if (buffer.x > (minx + 2*(maxx-minx)/3))
58: right = 1;
59:
60: if (buffer.y < (miny + (maxy-miny)/3))
61: top = 1;
62: else if (buffer.y > (miny + 2*(maxy-miny)/3))
63: bot = 1;
64:
65: if (left) top = !top;
66: if (right) bot = !bot;
67: *dir = bot | (right << 1) | (top << 8) | (left << 9);
68: *button = (buffer.buttons & 3) != 0;
69: }
70:
71: void init_joystick(void)
72: {
73: js0 = open("/dev/js0", O_RDONLY);
74: if (js0 < 0)
75: return;
76: joystickpresent = 1;
77: }
78:
79: void close_joystick(void)
80: {
81: if (joystickpresent)
82: close(js0);
83: }
84:
85: #elif defined(__DOS__)
86:
87: void read_joystick(UWORD *dir, int *button)
88: {
89: static int minx = MAXINT, maxx = MININT,
90: miny = MAXINT, maxy = MININT;
91: int left = 0, right = 0, top = 0, bot = 0;
92: char JoyPort;
93: int laps, JoyX, JoyY;
94:
95: *dir = 0;
96: *button = 0;
97: if (!joystickpresent)
98: return;
99:
100: JoyX = 0;
101: JoyY = 0;
102: laps = 0;
103: __asm__ __volatile__("cli");
104: outportb(0x201, 0xff);
105: do {
106: JoyPort = inportb(0x201);
107: JoyX = JoyX + (JoyPort & 1);
108: JoyY = JoyY + ((JoyPort & 2) >> 1);
109: laps++;
110: } while(((JoyPort & 3) != 0) && (laps != 65535));
111: __asm__ __volatile__("sti");
112:
113: if (JoyX < minx) minx = JoyX;
114: if (JoyY < miny) miny = JoyY;
115: if (JoyX > maxx) maxx = JoyX;
116: if (JoyY > maxy) maxy = JoyY;
117:
118: if (JoyX < (minx + (maxx-minx)/3))
119: left = 1;
120: else if (JoyX > (minx + 2*(maxx-minx)/3))
121: right = 1;
122:
123: if (JoyY < (miny + (maxy-miny)/3))
124: top = 1;
125: else if (JoyY > (miny + 2*(maxy-miny)/3))
126: bot = 1;
127:
128: if (left) top = !top;
129: if (right) bot = !bot;
130: *dir = bot | (right << 1) | (top << 8) | (left << 9);
131: *button = ((~JoyPort) & 48) != 0;
132: }
133:
134: void init_joystick(void)
135: {
136: int laps = 0;
137: char JoyPort;
138: __asm__ __volatile__("cli");
139: outportb(0x201, 0xff);
140: do {
141: JoyPort = inportb(0x201);
142: laps++;
143: } while(((JoyPort & 3) != 0) && (laps != 65535));
144: __asm__ __volatile__("sti");
145: if (laps != 65535)
146: joystickpresent = 1;
147: }
148:
149: void close_joystick(void)
150: {
151: }
152:
153: #else
154: void read_joystick(UWORD *dir, int *button)
155: {
156: *dir = 0;
157: *button = 0;
158: }
159:
160: void init_joystick(void)
161: {
162: }
163:
164: void close_joystick(void)
165: {
166: }
167:
168: #endif
169:
170: int sound_available = 0;
171: static long count = 0;
172:
173: struct audio_channel_data audio_channel[4];
174:
175: /* The buffer is too large... */
176: static UWORD buffer[44100], *bufpt;
177:
178: static ULONG data;
179:
180: int sound_table[256][64];
181: static int smplcnt = 0;
182: static int dspbits = 16, freq_divisor = 1;
183: static int sndbufsize;
184:
185: static void init_sound_table16(void)
186: {
187: int i,j;
188:
189: for (i = 0; i < 256; i++)
190: for (j = 0; j < 64; j++)
191: sound_table[i][j] = j * (BYTE)i;
192: }
193:
194: static void init_sound_table8(void)
195: {
196: int i,j;
197:
198: for (i = 0; i < 256; i++)
199: for (j = 0; j < 64; j++)
200: sound_table[i][j] = (j * (BYTE)i) / 256;
201: }
202:
203: static int exact_log2(int v)
204: {
205: int l = 0;
206: while ((v >>= 1) != 0)
207: l++;
208: return l;
209: }
210:
211: #ifdef LINUX_SOUND
212:
213: #include <sys/ioctl.h>
214: #include <sys/soundcard.h>
215:
216: static int sfd;
217: static int have_sound;
218:
219: int init_sound (void)
220: {
221: int tmp;
222: int rate;
223:
224: unsigned long formats;
225:
226: sfd = open ("/dev/dsp", O_WRONLY);
227: have_sound = !(sfd < 0);
228: if (!have_sound) {
229: return 0;
230: }
231:
232: ioctl (sfd, SNDCTL_DSP_GETFMTS, &formats);
233:
234: if (sound_desired_bsiz < 128 || sound_desired_bsiz > 16384) {
235: fprintf(stderr, "Sound buffer size %d out of range.\n", sound_desired_bsiz);
236: sound_desired_bsiz = 8192;
237: }
238:
239: tmp = 0x00040000 + exact_log2(sound_desired_bsiz);
240: ioctl (sfd, SNDCTL_DSP_SETFRAGMENT, &tmp);
241: ioctl (sfd, SNDCTL_DSP_GETBLKSIZE, &sndbufsize);
242:
243: dspbits = sound_desired_bits;
244: ioctl(sfd, SNDCTL_DSP_SAMPLESIZE, &dspbits);
245: ioctl(sfd, SOUND_PCM_READ_BITS, &dspbits);
246: if (dspbits != sound_desired_bits) {
247: fprintf(stderr, "Can't use sound with %d bits\n", sound_desired_bits);
248: return 0;
249: }
250:
251: tmp = 0;
252: ioctl(sfd, SNDCTL_DSP_STEREO, &tmp);
253:
254: rate = sound_desired_freq;
255: ioctl(sfd, SNDCTL_DSP_SPEED, &rate);
256: ioctl(sfd, SOUND_PCM_READ_RATE, &rate);
257: /* Some soundcards have a bit of tolerance here. */
258: if (rate < sound_desired_freq * 90 / 100 || rate > sound_desired_freq * 110 / 100) {
259: fprintf(stderr, "Can't use sound with desired frequency %d\n", sound_desired_freq);
260: return 0;
261: }
262:
263: eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate;
264:
265: if (dspbits == 16) {
266: /* Will this break horribly on Linux/Alpha? Possible... */
267: if (!(formats & AFMT_S16_LE))
268: return 0;
269: init_sound_table16 ();
270: eventtab[ev_sample].handler = sample16_handler;
271: } else {
272: if (!(formats & AFMT_U8))
273: return 0;
274: init_sound_table8 ();
275: eventtab[ev_sample].handler = sample8_handler;
276: }
277: sound_available = 1;
278: printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n",
279: dspbits, rate, sndbufsize);
280: bufpt = buffer;
281: smplcnt = 0;
282: return 1;
283: }
284:
285: static void flush_sound_buffer(void)
286: {
287: write(sfd, buffer, sndbufsize);
288: bufpt = buffer;
289: }
290:
291: #elif defined(AF_SOUND)
292:
293: #include <AF/AFlib.h>
294:
295: static AFAudioConn *aud;
296: static AC ac;
297: static long aftime;
298: static int rate;
299:
300: static int have_sound;
301:
302: int init_sound (void)
303: {
304: AFSetACAttributes attributes;
305: AFDeviceDescriptor *aDev;
306: int device;
307:
308: aud = AFOpenAudioConn(NULL);
309: have_sound = !(aud == NULL);
310: if (!have_sound) {
311: return 0;
312: }
313:
314: for(device = 0; device < ANumberOfAudioDevices(aud); device++) {
315: aDev = AAudioDeviceDescriptor(aud, device);
316: rate = aDev->playSampleFreq;
317: sndbufsize = (rate / 8) * 4;
318: if(aDev->inputsFromPhone == 0
319: && aDev->outputsToPhone == 0
320: && aDev->playNchannels == 1)
321: break;
322: }
323: if (device == ANumberOfAudioDevices(aud)) {
324: return 0;
325: }
326:
327: dspbits = 16;
328: attributes.type = LIN16;
329: ac = AFCreateAC(aud, device, ACEncodingType, &attributes);
330: aftime = AFGetTime(ac);
331:
332: init_sound_table16 ();
333: eventtab[ev_sample].handler = sample16_handler;
334: eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate;
335:
336: bufpt = buffer;
337: smplcnt = 0;
338: sound_available = 1;
339: printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize);
340: return 1;
341: }
342:
343: static void flush_sound_buffer(void)
344: {
345: long size = (char *)bufpt - (char *)buffer;
346: if (AFGetTime(ac) > aftime)
347: aftime = AFGetTime(ac);
348: AFPlaySamples(ac, aftime, size, (unsigned char*) buffer);
349: aftime += size / 2;
350: bufpt = buffer;
351: }
352:
353: #elif defined(__mac__)
354:
355: #include <Sound.h>
356:
357: static SndChannelPtr newChannel;
358: static ExtSoundHeader theSndBuffer;
359: static SndCommand theCmd;
360:
361: /* The buffer is too large... */
362: static UWORD buffer0[44100], buffer1[44100], *bufpt;
363:
364: static int have_sound;
365: static int nextbuf=0;
366: static Boolean sFlag=true;
367:
368: int init_sound (void)
369: {
370: if (SndNewChannel(&newChannel, sampledSynth, initMono, NULL))
371: return 0;
372: sndbufsize = 44100;
373: init_sound_table8 ();
374: smplcnt = 0;
375: bufpt = buffer0;
376: sound_available = 1;
377: return 1;
378: }
379:
380: static void flush_sound_buffer(void)
381: {
382: bufpt = buffer0;
383:
384: theSndBuffer.samplePtr = (Ptr)buffer0;
385: theSndBuffer.numChannels = 1;
386: theSndBuffer.sampleRate = 0xac440000;
387: theSndBuffer.encode = extSH;
388: theSndBuffer.numFrames = sndbufsize;
389: theSndBuffer.sampleSize = 8;
390: theCmd.param1 = 0;
391: theCmd.param2 = (long)&theSndBuffer;
392: theCmd.cmd = bufferCmd;
393: SndDoCommand(newChannel, &theCmd, false);
394: }
395:
396: #elif defined(__DOS__)
397:
398: #include "dos-sb.h"
399:
400: void (*SND_Write)(void *buf, unsigned long size); // Pointer to function that plays data on card
401: int dos_dsprate = 1; // 0 for 44100 - 1 for 22050
402: int dos_dspbits = 16;
403:
404: int init_sound (void)
405: {
406: int rate;
407:
408: dspbits = sound_desired_bits;
409: rate = sound_desired_freq;
410: if (rate == 22050)
411: dos_dsprate = 1;
412: else if (rate == 44100)
413: dos_dsprate = 0;
414: else {
415: fprintf(stderr, "Can't use sample rate %d!\n", rate);
416: return 0;
417: }
418:
419: if (SB_DetectInitSound(&dspbits, &dos_dsprate, &sndbufsize));
420: else if (0/*OTHER_CARD_DETECT_ROUTINE*/);
421: else
422: return 0;
423:
424: eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate;
425:
426: if (dspbits == 16) {
427: init_sound_table16 ();
428: eventtab[ev_sample].handler = sample16_handler;
429: } else {
430: init_sound_table8 ();
431: eventtab[ev_sample].handler = sample8_handler;
432: }
433: sound_available = 1;
434: printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n",
435: dspbits, rate, sndbufsize);
436: bufpt = buffer;
437: smplcnt = 0;
438: return 1;
439: }
440:
441: static void flush_sound_buffer(void)
442: {
443: SND_Write(buffer, sndbufsize);
444: bufpt = buffer;
445: }
446:
447: #elif defined(SOLARIS_SOUND)
448:
449: #include <sys/audioio.h>
450:
451: static int sfd;
452: static int have_sound;
453:
454: int init_sound (void)
455: {
456: int rate;
457:
458: struct audio_info sfd_info;
459:
460: sfd = open("/dev/audio", O_WRONLY);
461: have_sound = !(sfd <0);
462: if (!have_sound) {
463: return 0;
464: }
465:
466: rate = sound_desired_freq;
467: dspbits = sound_desired_bits;
468: AUDIO_INITINFO(&sfd_info); /* 44100Hz, mono, 16Bit, linear */
469: sfd_info.play.sample_rate = rate;
470: sfd_info.play.channels = 1;
471: sfd_info.play.precision = dspbits;
472: sfd_info.play.encoding = AUDIO_ENCODING_LINEAR;
473: if (ioctl(sfd, AUDIO_SETINFO, &sfd_info)) {
474: fprintf(stderr, "Can't use sample rate %d with %d bits!\n", rate, bits);
475: return 0;
476: }
477: eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate;
478:
479: if (dspbits == 16) {
480: init_sound_table16 ();
481: eventtab[ev_sample].handler = sample16_handler;
482: } else {
483: init_sound_table8 ();
484: eventtab[ev_sample].handler = sample8_handler;
485: }
486:
487: bufpt = buffer;
488: smplcnt = 0;
489: sound_available = 1;
490: sndbufsize = dspbits/8 * rate;
491: printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize);
492: return 1;
493: }
494:
495: static void flush_sound_buffer(void)
496: {
497: write(sfd, buffer, sndbufsize);
498: bufpt = buffer;
499: }
500:
501:
502: #else
503:
504: int init_sound (void)
505: {
506: produce_sound = 0;
507: return 1;
508: }
509:
510: static void flush_sound_buffer(void)
511: {
512: }
513:
514: #endif
515:
516: void AUDxDAT(int nr, UWORD v)
517: {
518: #ifndef DONT_WANT_SOUND
519: struct audio_channel_data *cdp = audio_channel + nr;
520: cdp->dat = v;
521: if (cdp->state == 0 && !(INTREQR() & (0x80 << nr))) {
522: cdp->state = 2;
523: INTREQ(0x8000 | (0x80 << nr));
524: /* data_written = 2 ???? */
525: eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
526: eventtab[ev_aud0 + nr].oldcycles = cycles;
527: eventtab[ev_aud0 + nr].active = 1;
528: events_schedule();
529: }
530: #endif
531: }
532:
533: #ifndef DONT_WANT_SOUND
534: static void sample16_handler(void)
535: {
536: int nr;
537: ULONG data = 0;
538:
539: eventtab[ev_sample].evtime += cycles - eventtab[ev_sample].oldcycles;
540: eventtab[ev_sample].oldcycles = cycles;
541:
542: if (produce_sound < 2)
543: return;
544:
545: for (nr = 0; nr < 4; nr++) {
546: if (!(adkcon & (0x11 << nr)))
547: data += sound_table[audio_channel[nr].current_sample][audio_channel[nr].vol];
548: }
549: *bufpt++ = data;
550: if ((char *)bufpt - (char *)buffer >= sndbufsize) {
551: flush_sound_buffer();
552: }
553: }
554:
555: static void sample8_handler(void)
556: {
557: int nr;
558: ULONG data = 0;
559: unsigned char *bp = (unsigned char *)bufpt;
560:
561: eventtab[ev_sample].evtime += cycles - eventtab[ev_sample].oldcycles;
562: eventtab[ev_sample].oldcycles = cycles;
563:
564: if (produce_sound < 2)
565: return;
566:
567: for (nr = 0; nr < 4; nr++) {
568: if (!(adkcon & (0x11 << nr)))
569: data += sound_table[audio_channel[nr].current_sample][audio_channel[nr].vol];
570: }
571: *bp++ = data + 128;
572: bufpt = (UWORD *)bp;
573:
574: if ((char *)bufpt - (char *)buffer >= sndbufsize) {
575: flush_sound_buffer();
576: }
577: }
578:
579: static void audio_handler(int nr)
580: {
581: struct audio_channel_data *cdp = audio_channel + nr;
582:
583: switch (cdp->state) {
584: case 0:
585: fprintf(stderr, "Bug in sound code\n");
586: break;
587:
588: case 1:
589: /* We come here at the first hsync after DMA was turned on. */
590: eventtab[ev_aud0 + nr].evtime += maxhpos;
591: eventtab[ev_aud0 + nr].oldcycles += maxhpos;
592:
593: cdp->state = 5;
594: INTREQ(0x8000 | (0x80 << nr));
595: if (cdp->wlen != 1)
596: cdp->wlen--;
597: cdp->nextdat = chipmem_bank.wget(cdp->pt);
598: cdp->pt += 2;
599: break;
600:
601: case 5:
602: /* We come here at the second hsync after DMA was turned on. */
603: if (produce_sound == 0)
604: cdp->per = 65535;
605:
606: eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
607: eventtab[ev_aud0 + nr].oldcycles = cycles;
608: cdp->dat = cdp->nextdat;
609: cdp->current_sample = (UBYTE)(cdp->dat >> 8);
610: cdp->state = 2;
611: {
612: int audav = adkcon & (1 << nr);
613: int audap = adkcon & (16 << nr);
614: int napnav = (!audav && !audap) || audav;
615: if (napnav)
616: cdp->data_written = 2;
617: }
618: break;
619:
620: case 2:
621: /* We come here when a 2->3 transition occurs */
622: if (produce_sound == 0)
623: cdp->per = 65535;
624:
625: cdp->current_sample = (UBYTE)(cdp->dat & 0xFF);
626: eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
627: eventtab[ev_aud0 + nr].oldcycles = cycles;
628:
629: cdp->state = 3;
630:
631: /* Period attachment? */
632: if (adkcon & (0x10 << nr)) {
633: if (cdp->intreq2 && cdp->dmaen)
634: INTREQ(0x8000 | (0x80 << nr));
635: cdp->intreq2 = 0;
636:
637: cdp->dat = cdp->nextdat;
638: if (cdp->dmaen)
639: cdp->data_written = 2;
640: if (nr < 3) {
641: if (cdp->dat == 0)
642: (cdp+1)->per = 65535;
643:
644: else if (cdp->dat < maxhpos/2 && produce_sound < 3)
645: (cdp+1)->per = maxhpos/2;
646: else
647: (cdp+1)->per = cdp->dat;
648: }
649: }
650: break;
651:
652: case 3:
653: /* We come here when a 3->2 transition occurs */
654: if (produce_sound == 0)
655: cdp->per = 65535;
656:
657: eventtab[ev_aud0 + nr].evtime = cycles + cdp->per;
658: eventtab[ev_aud0 + nr].oldcycles = cycles;
659:
660: if ((INTREQR() & (0x80 << nr)) && !cdp->dmaen) {
661: cdp->state = 0;
662: cdp->current_sample = 0;
663: eventtab[ev_aud0 + nr].active = 0;
664: break;
665: } else {
666: int audav = adkcon & (1 << nr);
667: int audap = adkcon & (16 << nr);
668: int napnav = (!audav && !audap) || audav;
669: cdp->state = 2;
670:
671: if ((cdp->intreq2 && cdp->dmaen && napnav)
672: || (napnav && !cdp->dmaen))
673: INTREQ(0x8000 | (0x80 << nr));
674: cdp->intreq2 = 0;
675:
676: cdp->dat = cdp->nextdat;
677: cdp->current_sample = (UBYTE)(cdp->dat >> 8);
678:
679: if (cdp->dmaen && napnav)
680: cdp->data_written = 2;
681:
682: /* Volume attachment? */
683: if (audav) {
684: if (nr < 3)
685: (cdp+1)->vol = cdp->dat;
686: }
687: }
688: break;
689:
690: default:
691: cdp->state = 0;
692: eventtab[ev_aud0 + nr].active = 0;
693: break;
694: }
695: }
696:
697: void aud0_handler(void)
698: {
699: audio_handler(0);
700: }
701: void aud1_handler(void)
702: {
703: audio_handler(1);
704: }
705: void aud2_handler(void)
706: {
707: audio_handler(2);
708: }
709: void aud3_handler(void)
710: {
711: audio_handler(3);
712: }
713: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.