--- uae/src/os.c 2018/04/24 16:38:39 1.1.1.1 +++ uae/src/os.c 2018/04/24 16:38:55 1.1.1.2 @@ -18,8 +18,7 @@ #include "events.h" #ifndef DONT_WANT_SOUND -static void sample16_handler(void); -static void sample8_handler(void); +static void sample_ulaw_handler(void); #endif int joystickpresent = 0; @@ -150,7 +149,50 @@ void close_joystick(void) { } -#else +#elif defined(AMIGA) + +#define EXEC_TYPES_H /* exec/types.h has trouble as LONG, ULONG, etc. */ +typedef void *APTR; /* are already defined. This avoid the trouble. */ +typedef char *STRPTR; +typedef float *FLOAT; +typedef int BOOL; +#define VOID void + +#include +#include + +#define CIAAPRA 0xBFE001 +#define CUSTOM 0xDFF000 + +static struct Custom *custom= (struct Custom*) CUSTOM; +static struct CIA *cia = (struct CIA *) CIAAPRA; + +void read_joystick(UWORD *dir, int *button) +{ + int bot, right, top, left, joy,fire; + + joy = custom->joy1dat; + fire = !( cia->ciapra & 0x0080 ) ? 1 : 0; + + right = (joy & 0x0002) ? 1 : 0; + left = (joy & 0x0200) ? 1 : 0; + bot = (joy & 0x0001) ? 1 : 0; + top = (joy & 0x0100) ? 1 : 0; + + *button = fire; + *dir = bot | (right << 1) | (top << 8) | (left << 9); +} + +void init_joystick(void) +{ +} + +void close_joystick(void) +{ +} + +#elif !defined(__BEOS__) + void read_joystick(UWORD *dir, int *button) { *dir = 0; @@ -168,21 +210,24 @@ void close_joystick(void) #endif int sound_available = 0; -static long count = 0; struct audio_channel_data audio_channel[4]; +#ifdef __BEOS__ +UWORD *sndbuffer; +#elif !defined(AMIGA) /* The buffer is too large... */ -static UWORD buffer[44100], *bufpt; +static UWORD sndbuffer[44100]; +#endif +UWORD *sndbufpt; static ULONG data; int sound_table[256][64]; -static int smplcnt = 0; -static int dspbits = 16, freq_divisor = 1; -static int sndbufsize; +static int dspbits = 16; +int sndbufsize; -static void init_sound_table16(void) +void init_sound_table16(void) { int i,j; @@ -191,7 +236,7 @@ static void init_sound_table16(void) sound_table[i][j] = j * (BYTE)i; } -static void init_sound_table8(void) +void init_sound_table8 (void) { int i,j; @@ -216,6 +261,12 @@ static int exact_log2(int v) static int sfd; static int have_sound; +void close_sound(void) +{ + if (have_sound) + close(sfd); +} + int init_sound (void) { int tmp; @@ -277,15 +328,14 @@ int init_sound (void) sound_available = 1; printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize); - bufpt = buffer; - smplcnt = 0; + sndbufpt = sndbuffer; return 1; } static void flush_sound_buffer(void) { - write(sfd, buffer, sndbufsize); - bufpt = buffer; + write(sfd, sndbuffer, sndbufsize); + sndbufpt = sndbuffer; } #elif defined(AF_SOUND) @@ -299,6 +349,10 @@ static int rate; static int have_sound; +void close_sound(void) +{ +} + int init_sound (void) { AFSetACAttributes attributes; @@ -333,8 +387,7 @@ int init_sound (void) eventtab[ev_sample].handler = sample16_handler; eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate; - bufpt = buffer; - smplcnt = 0; + sndbufpt = sndbuffer; sound_available = 1; printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize); return 1; @@ -342,12 +395,12 @@ int init_sound (void) static void flush_sound_buffer(void) { - long size = (char *)bufpt - (char *)buffer; + long size = (char *)sndbufpt - (char *)sndbuffer; if (AFGetTime(ac) > aftime) aftime = AFGetTime(ac); - AFPlaySamples(ac, aftime, size, (unsigned char*) buffer); + AFPlaySamples(ac, aftime, size, (unsigned char*) sndbuffer); aftime += size / 2; - bufpt = buffer; + sndbufpt = sndbuffer; } #elif defined(__mac__) @@ -359,27 +412,31 @@ static ExtSoundHeader theSndBuffer; static SndCommand theCmd; /* The buffer is too large... */ -static UWORD buffer0[44100], buffer1[44100], *bufpt; +static UWORD buffer0[44100], buffer1[44100], *sndbufpt; static int have_sound; static int nextbuf=0; static Boolean sFlag=true; +void close_sound(void) +{ +} + int init_sound (void) { if (SndNewChannel(&newChannel, sampledSynth, initMono, NULL)) return 0; sndbufsize = 44100; init_sound_table8 (); - smplcnt = 0; - bufpt = buffer0; + + sndbufpt = buffer0; sound_available = 1; return 1; } static void flush_sound_buffer(void) { - bufpt = buffer0; + sndbufpt = buffer0; theSndBuffer.samplePtr = (Ptr)buffer0; theSndBuffer.numChannels = 1; @@ -395,11 +452,14 @@ static void flush_sound_buffer(void) #elif defined(__DOS__) -#include "dos-sb.h" +#include "sound/sb.h" +#include "sound/gus.h" void (*SND_Write)(void *buf, unsigned long size); // Pointer to function that plays data on card -int dos_dsprate = 1; // 0 for 44100 - 1 for 22050 -int dos_dspbits = 16; + +void close_sound(void) +{ +} int init_sound (void) { @@ -407,16 +467,13 @@ int init_sound (void) dspbits = sound_desired_bits; rate = sound_desired_freq; - if (rate == 22050) - dos_dsprate = 1; - else if (rate == 44100) - dos_dsprate = 0; - else { + if ((rate != 22050) && (rate != 44100)) { fprintf(stderr, "Can't use sample rate %d!\n", rate); return 0; } - if (SB_DetectInitSound(&dspbits, &dos_dsprate, &sndbufsize)); + if (GUS_Init(&dspbits, &rate, &sndbufsize)); + else if (SB_DetectInitSound(&dspbits, &rate, &sndbufsize)); else if (0/*OTHER_CARD_DETECT_ROUTINE*/); else return 0; @@ -431,17 +488,16 @@ int init_sound (void) eventtab[ev_sample].handler = sample8_handler; } sound_available = 1; - printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", + fprintf(stderr, "Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize); - bufpt = buffer; - smplcnt = 0; + sndbufpt = sndbuffer; return 1; } static void flush_sound_buffer(void) { - SND_Write(buffer, sndbufsize); - bufpt = buffer; + SND_Write(sndbuffer, sndbufsize); + sndbufpt = sndbuffer; } #elif defined(SOLARIS_SOUND) @@ -451,6 +507,12 @@ static void flush_sound_buffer(void) static int sfd; static int have_sound; +void close_sound(void) +{ + if (have_sound) + close(sfd); +} + int init_sound (void) { int rate; @@ -463,43 +525,180 @@ int init_sound (void) return 0; } + if (sound_desired_bsiz < 128 || sound_desired_bsiz > 44100) { + fprintf(stderr, "Sound buffer size %d out of range.\n", sound_desired_bsiz); + sound_desired_bsiz = 8192; + } + rate = sound_desired_freq; dspbits = sound_desired_bits; - AUDIO_INITINFO(&sfd_info); /* 44100Hz, mono, 16Bit, linear */ + AUDIO_INITINFO(&sfd_info); sfd_info.play.sample_rate = rate; sfd_info.play.channels = 1; sfd_info.play.precision = dspbits; - sfd_info.play.encoding = AUDIO_ENCODING_LINEAR; + sfd_info.play.encoding = (dspbits == 8 ) ? AUDIO_ENCODING_ULAW : AUDIO_ENCODING_LINEAR; if (ioctl(sfd, AUDIO_SETINFO, &sfd_info)) { - fprintf(stderr, "Can't use sample rate %d with %d bits!\n", rate, bits); + fprintf(stderr, "Can't use sample rate %d with %d bits, %s!\n", rate, dspbits, (dspbits ==8) ? "ulaw" : "linear"); return 0; } eventtab[ev_sample].evtime = (long)maxhpos * maxvpos * 50 / rate; - if (dspbits == 16) { - init_sound_table16 (); - eventtab[ev_sample].handler = sample16_handler; + init_sound_table16 (); + + if (dspbits == 8) { + eventtab[ev_sample].handler = sample_ulaw_handler; } else { - init_sound_table8 (); - eventtab[ev_sample].handler = sample8_handler; + eventtab[ev_sample].handler = sample16_handler; } - bufpt = buffer; + sndbufpt = sndbuffer; smplcnt = 0; sound_available = 1; - sndbufsize = dspbits/8 * rate; - printf ("Sound driver found and configured for %d bits at %d Hz, buffer is %d bytes\n", dspbits, rate, sndbufsize); + sndbufsize = sound_desired_bsiz; + printf ("Sound driver found and configured for %d bits, %s at %d Hz, buffer is %d bytes\n", dspbits, (dspbits ==8) ? "ulaw" : "linear", rate, sndbufsize); return 1; } static void flush_sound_buffer(void) { - write(sfd, buffer, sndbufsize); - bufpt = buffer; + write(sfd, sndbuffer, sndbufsize); + sndbufpt = sndbuffer; } -#else +#elif defined(AMIGA) && !defined(DONT_WANT_SOUND) +/* + * Compared to Linux, AF_SOUND, and mac above, the AMIGA sound processing + * with OS routines is awfull. (sam) + */ +#define DEVICES_TIMER_H /* as there is a conflict on timeval */ +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +static char whichchannel[]={1,2,4,8}; +static struct IOAudio *AudioIO; +static struct MsgPort *AudioMP; +static struct Message *AudioMSG; + +static unsigned char *buffers[2]; +static UWORD *sndbuffer; +static int bufidx, devopen; + +static int have_sound, clockval, oldledstate, period; + +int init_sound (void) +{ /* too complex ? No it is only the allocation of a single channel ! */ + /* it would have been far less painfull if AmigaOS provided a */ + /* SOUND: device handler */ + int rate; + + atexit(close_sound); + + if (sound_desired_bsiz < 2 || sound_desired_bsiz > (128*1024)) { + fprintf(stderr, "Sound buffer size %d out of range.\n", sound_desired_bsiz); + sound_desired_bsiz = 8192; + } + sndbufsize = (sound_desired_bsiz + 1)&~1; + + /* get the buffers */ + buffers[0] = (void*)AllocMem(sndbufsize,MEMF_CHIP|MEMF_CLEAR); + buffers[1] = (void*)AllocMem(sndbufsize,MEMF_CHIP|MEMF_CLEAR); + if(!buffers[0] || !buffers[1]) goto fail; + bufidx = 0; + sndbuffer = sndbufpt = (UWORD*)buffers[bufidx]; + + /* determine the clock */ + { + struct GfxBase *GB; + GB = (void*)OpenLibrary("graphics.library",0L); + if(!GB) goto fail; + if (GB->DisplayFlags & PAL) + clockval = 3546895; /* PAL clock */ + else + clockval = 3579545; /* NTSC clock */ + CloseLibrary((void*)GB); + } + + if (!sound_desired_freq) sound_desired_freq = 1; + if (clockval/sound_desired_freq < 124 || clockval/sound_desired_freq > 65535) { + fprintf(stderr, "Can't use sound with desired frequency %d Hz\n", sound_desired_freq); + sound_desired_freq = 22000; + } + rate = sound_desired_freq; + period = (UWORD)(clockval/rate); + + /* setup the stuff */ + AudioMP = CreatePort(0,0); + if(!AudioMP) goto fail; + AudioIO = (struct IOAudio *)CreateExtIO(AudioMP, sizeof(struct IOAudio)); + if(!AudioIO) goto fail; + + AudioIO->ioa_Request.io_Message.mn_Node.ln_Pri /*pfew!!*/ = 85; + AudioIO->ioa_Data = whichchannel; + AudioIO->ioa_Length = sizeof(whichchannel); + AudioIO->ioa_AllocKey = 0; + if(OpenDevice(AUDIONAME, 0, (void*)AudioIO, 0)) goto fail; + devopen = 1; + + oldledstate = cia->ciapra & (1<ciapra |= (1<ciapra = (cia->ciapra & ~(1<ioa_Request.io_Command = CMD_WRITE; + AudioIO->ioa_Request.io_Flags = ADIOF_PERVOL|IOF_QUICK; + AudioIO->ioa_Data = (BYTE *)buffers[bufidx]; + AudioIO->ioa_Length = sndbufsize; + AudioIO->ioa_Period = period; + AudioIO->ioa_Volume = 64; + AudioIO->ioa_Cycles = 1; + + if(IOSent) WaitIO((void*)AudioIO); else IOSent=1; + BeginIO((void*)AudioIO); + + /* double buffering */ + bufidx = 1 - bufidx; + sndbuffer = sndbufpt = (UWORD*)buffers[bufidx]; +} + +#elif !defined(__BEOS__) int init_sound (void) { @@ -507,6 +706,10 @@ int init_sound (void) return 1; } +void close_sound(void) +{ +} + static void flush_sound_buffer(void) { } @@ -531,7 +734,7 @@ void AUDxDAT(int nr, UWORD v) } #ifndef DONT_WANT_SOUND -static void sample16_handler(void) +void sample16_handler(void) { int nr; ULONG data = 0; @@ -546,17 +749,17 @@ static void sample16_handler(void) if (!(adkcon & (0x11 << nr))) data += sound_table[audio_channel[nr].current_sample][audio_channel[nr].vol]; } - *bufpt++ = data; - if ((char *)bufpt - (char *)buffer >= sndbufsize) { + *sndbufpt++ = data; + if ((char *)sndbufpt - (char *)sndbuffer >= sndbufsize) { flush_sound_buffer(); } } -static void sample8_handler(void) +void sample8_handler(void) { int nr; ULONG data = 0; - unsigned char *bp = (unsigned char *)bufpt; + unsigned char *bp = (unsigned char *)sndbufpt; eventtab[ev_sample].evtime += cycles - eventtab[ev_sample].oldcycles; eventtab[ev_sample].oldcycles = cycles; @@ -568,10 +771,72 @@ static void sample8_handler(void) if (!(adkcon & (0x11 << nr))) data += sound_table[audio_channel[nr].current_sample][audio_channel[nr].vol]; } +#ifdef AMIGA + *bp++ = (unsigned char) data; +#else *bp++ = data + 128; - bufpt = (UWORD *)bp; +#endif + sndbufpt = (UWORD *)bp; + + if ((char *)sndbufpt - (char *)sndbuffer >= sndbufsize) { + flush_sound_buffer(); + } +} + +static char int2ulaw(int ch) +{ + int mask; + + if (ch < 0) { + ch = -ch; + mask = 0x7f; + } + else { + mask = 0xff; + } + + if (ch < 32) { + ch = 0xF0 | ( 15 - (ch/2) ); + } else if (ch < 96) { + ch = 0xE0 | ( 15 - (ch-32)/4 ); + } else if (ch < 224) { + ch = 0xD0 | ( 15 - (ch-96)/8 ); + } else if (ch < 480) { + ch = 0xC0 | ( 15 - (ch-224)/16 ); + } else if (ch < 992 ) { + ch = 0xB0 | ( 15 - (ch-480)/32 ); + } else if (ch < 2016) { + ch = 0xA0 | ( 15 - (ch-992)/64 ); + } else if (ch < 4064) { + ch = 0x90 | ( 15 - (ch-2016)/128 ); + } else if (ch < 8160) { + ch = 0x80 | ( 15 - (ch-4064)/256 ); + } else { + ch = 0x80; + } + return (char)(mask & ch); +} + +static void sample_ulaw_handler(void) +{ + int nr; + ULONG data = 0; + char *bp = (char *)sndbufpt; + + eventtab[ev_sample].evtime += cycles - eventtab[ev_sample].oldcycles; + eventtab[ev_sample].oldcycles = cycles; + + if (produce_sound < 2) + return; + + for (nr = 0; nr < 4; nr++) { + if (!(adkcon & (0x11 << nr))) + data += sound_table[audio_channel[nr].current_sample][audio_channel[nr].vol]; + } + *bp++ = int2ulaw(data); + sndbufpt = (UWORD *)bp; - if ((char *)bufpt - (char *)buffer >= sndbufsize) { + if ((char *)sndbufpt - (char *)sndbuffer >= sndbufsize) { flush_sound_buffer(); } }