static HANDLE handle = INVALID_HANDLE_VALUE;
-int catweasel_isjoystick(void)
+int catweasel_isjoystick (void)
{
uae_u8 b = cwc.can_joy;
+ if (!cwc.direct_access)
+ return 0;
if (b) {
if (cwc.type == CATWEASEL_TYPE_MK3 && cwc.sid[0])
b |= 0x80;
}
return b;
}
-int catweasel_ismouse(void)
+int catweasel_ismouse (void)
{
+ if (!cwc.direct_access)
+ return 0;
return cwc.can_mouse;
}
static int hsync_requested;
-static void hsync_request(void)
+static void hsync_request (void)
{
hsync_requested = 10;
};
-static void sid_write(uae_u8 reg, uae_u8 val, int sidnum)
+static void sid_write (uae_u8 reg, uae_u8 val, int sidnum)
{
if (sidnum >= cwc.can_sid)
return;
catweasel_do_bget(0xd8); // dummy read
}
-static uae_u8 sid_read(uae_u8 reg, int sidnum)
+static uae_u8 sid_read (uae_u8 reg, int sidnum)
{
if (sidnum >= cwc.can_sid)
return 0;
return catweasel_do_bget(0xd8);
}
-static uae_u8 get_buttons(void)
+static uae_u8 get_buttons (void)
{
uae_u8 b, b2;
b = 0;
- if (cwc.type < CATWEASEL_TYPE_MK3)
+ if (cwc.type < CATWEASEL_TYPE_MK3 || !cwc.direct_access)
return b;
hsync_request();
b2 = catweasel_do_bget(0xc8) & (0x80 | 0x40);
return b;
}
-int catweasel_read_mouse(int port, int *dx, int *dy, int *buttons)
+int catweasel_read_mouse (int port, int *dx, int *dy, int *buttons)
{
- if (!cwc.can_mouse)
+ if (!cwc.can_mouse || !cwc.direct_access)
return 0;
hsync_request();
*dx = mouse_x[port];
return 1;
}
-static void sid_reset(void)
+static void sid_reset (void)
{
int i;
for (i = 0; i < 0x19; i++) {
}
}
-static void catweasel_detect_sid(void)
+static void catweasel_detect_sid (void)
{
int i, j;
uae_u8 b1, b2;
cwc.sid[0] = cwc.sid[1] = 0;
- if (!cwc.can_sid)
+ if (!cwc.can_sid || !cwc.direct_access)
return;
sid_reset();
if (cwc.type >= CATWEASEL_TYPE_MK4) {
{
int i;
- if (cwc.type < CATWEASEL_TYPE_MK3)
+ if (cwc.type < CATWEASEL_TYPE_MK3 || !cwc.direct_access)
return;
cwhsync--;
if (cwhsync > 0)
int catweasel_read_joystick (uae_u8 *dir, uae_u8 *buttons)
{
- if (!cwc.can_joy)
+ if (!cwc.can_joy || !cwc.direct_access)
return 0;
hsync_request();
*dir = catweasel_do_bget(0xc0);
{
uae_u8 v;
- if (!cwc.can_kb)
+ if (!cwc.can_kb || !cwc.direct_access)
return 0;
if (!currprefs.catweasel)
return 0;
#include "core.cw4.c"
-static int cw_config_done(void)
+static int cw_config_done (void)
{
return ioport_read (cwc.iobase + 7) & 4;
}
-static int cw_fpga_ready(void)
+static int cw_fpga_ready (void)
{
return ioport_read (cwc.iobase + 7) & 8;
}
-static void cw_resetFPGA(void)
+static void cw_resetFPGA (void)
{
ioport_write (cwc.iobase + 2, 227);
ioport_write (cwc.iobase + 3, 0);
ioport_write (cwc.iobase + 3, 65);
}
-static int catweasel3_configure(void)
+static int catweasel3_configure (void)
{
ioport_write (cwc.iobase, 241);
ioport_write (cwc.iobase + 1, 0);
return 1;
}
-static int catweasel4_configure(void)
+static int catweasel4_configure (void)
{
struct zfile *f;
time_t t;
} else {
cwc.direct_type = force_direct_catweasel >= 0x400 ? 3 : 1;
}
+ cwc.direct_access = 1;
} else {
for (i = 0; i < 4; i++) {
if (currprefs.catweasel > 0)
i = currprefs.catweasel;
+ if (currprefs.catweasel < 0)
+ i = -currprefs.catweasel + 1;
sprintf (name, "\\\\.\\CAT%d_F0", i);
handle = CreateFile (name, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
}
if (handle == INVALID_HANDLE_VALUE)
catweasel_detect();
+ cwc.direct_access = 0;
+ if (currprefs.catweasel < 0)
+ cwc.direct_access = 1;
}
if (handle == INVALID_HANDLE_VALUE) {
strcpy(name, "[DIRECT]");
if (cwc.direct_type && ioport_init()) {
+ cwc.direct_access = 1;
if (cwc.direct_type == 4 && catweasel4_configure()) {
cwc.type = 4;
cwc.can_joy = 2;
cwc.can_sid = buffer[6] ? 1 : 0;
cwc.can_kb = buffer[7] & 1;
cwc.can_mouse = (buffer[4] & 2) ? 2 : 0;
- if (!DeviceIoControl (handle, CW_LOCK_EXCLUSIVE, 0, 0, buffer, sizeof (buffer), &len, 0)) {
- write_log ("CW: CW_LOCK_EXCLUSIVE failed %d\n", GetLastError());
+ if (!DeviceIoControl (handle, CW_LOCK_EXCLUSIVE, 0, 0, buffer, sizeof (buffer), &len, 0)) {
+ write_log ("CW: CW_LOCK_EXCLUSIVE failed %d\n", GetLastError ());
goto fail;
}
model = *((uae_u32*)(buffer + 4));
base = *((uae_u32*)(buffer + 0));
cwc.type = model == 0 ? 1 : model == 2 ? 4 : 3;
cwc.iobase = base;
+ if (!cwc.direct_access) {
+ if (!DeviceIoControl (handle, CW_UNLOCK_EXCLUSIVE, 0, 0, 0, 0, &len, 0)) {
+ write_log ("CW: CW_UNLOCK_EXCLUSIVE failed %d\n", GetLastError ());
+ }
+ }
if (cwc.type == CATWEASEL_TYPE_MK4 && cwc.can_sid)
cwc.can_sid = 2;
}
- if (cwc.type == CATWEASEL_TYPE_MK4) {
- if (cwc.can_mouse) {
- int i;
- catweasel_do_bput(3, 0x81);
- catweasel_do_bput(0xd0, 4|8); // amiga mouse + pullups
- // clear mouse counters
- for (i = 0; i < 2; i++) {
- catweasel_do_bput(0xc4 + i * 8, 0);
- catweasel_do_bput(0xc0 + i * 8, 0);
+ if (cwc.direct_access) {
+ if (cwc.type == CATWEASEL_TYPE_MK4) {
+ if (cwc.can_mouse) {
+ int i;
+ catweasel_do_bput (3, 0x81);
+ catweasel_do_bput (0xd0, 4|8); // amiga mouse + pullups
+ // clear mouse counters
+ for (i = 0; i < 2; i++) {
+ catweasel_do_bput (0xc4 + i * 8, 0);
+ catweasel_do_bput (0xc0 + i * 8, 0);
+ }
}
+ catweasel_do_bput (3, 0x41); /* enable MK3-mode */
}
- catweasel_do_bput(3, 0x41); /* enable MK3-mode */
+ if (cwc.can_joy)
+ catweasel_do_bput (0xcc, 0); // joystick buttons = input
}
- if (cwc.can_joy)
- catweasel_do_bput(0xcc, 0); // joystick buttons = input
//catweasel_init_controller(&cwc);
- sprintf(tmp, "CW: Catweasel MK%d @%p (%s) enabled.",
- cwc.type, (uae_u8*)cwc.iobase, name);
- if (cwc.can_sid) {
- char *p = tmp + strlen(tmp);
- catweasel_detect_sid();
- sprintf(p, " SID0=%d", cwc.sid[0]);
- if (cwc.can_sid > 1) {
- p += strlen(p);
- sprintf(p, " SID1=%d", cwc.sid[1]);
+ sprintf(tmp, "CW: Catweasel MK%d @%p (%s) enabled. %s.",
+ cwc.type, (uae_u8*)cwc.iobase, name, cwc.direct_access ? "DIRECTIO": "API");
+ if (cwc.direct_access) {
+ if (cwc.can_sid) {
+ char *p = tmp + strlen(tmp);
+ catweasel_detect_sid ();
+ sprintf(p, " SID0=%d", cwc.sid[0]);
+ if (cwc.can_sid > 1) {
+ p += strlen(p);
+ sprintf(p, " SID1=%d", cwc.sid[1]);
+ }
}
}
write_log ("%s\n", tmp);
void catweasel_free (void)
{
- if (cwc.type == 4)
- catweasel_do_bput(3, 0x61); // enable floppy passthrough
+ if (cwc.direct_access) {
+ if (cwc.type == 4)
+ catweasel_do_bput(3, 0x61); // enable floppy passthrough
+ }
if (handle != INVALID_HANDLE_VALUE)
CloseHandle (handle);
handle = INVALID_HANDLE_VALUE;
- ioport_free();
+ ioport_free ();
memset (&cwc, 0, sizeof cwc);
mouse_x[0] = mouse_x[1] = mouse_y[0] = mouse_y[1] = 0;
mouse_px[0] = mouse_px[1] = mouse_py[0] = mouse_py[1] = 0;
}
if (h == INVALID_HANDLE_VALUE) {
if (force_direct_catweasel >= 100) {
- if (ioport_init())
+ if (ioport_init ())
return TRUE;
return FALSE;
}
- if (direct_detect()) {
+ if (direct_detect ()) {
detected = 1;
return TRUE;
}
return FALSE;
}
-#if 0
-
-#define outb(v,port) catweasel_do_bput(port,v)
-#define inb(port) catweasel_do_bget(port)
-
-#define LONGEST_TRACK 16000
-
-static uae_u8 mfmbuf[LONGEST_TRACK * 4];
-static uae_u8 tmpmfmbuffer[LONGEST_TRACK * 2];
-
-static int bitshiftcompare(uae_u8 *src,int bit,int len,uae_u8 *comp)
-{
- uae_u8 b;
- int ones,zeros,len2;
-
- ones=zeros=0;
- len2=len;
- while(len--) {
- b = (comp[0] << bit) | (comp[1] >> (8 - bit));
- if(b != *src) return 1;
- if(b==0x00) zeros++;
- if(b==0xff) ones++;
- src++;
- comp++;
- }
- if(ones==len2||zeros==len2) return 1;
- return 0;
-}
-
-static uae_u8 *mergepieces(uae_u8 *start,int len,int bits,uae_u8 *sync)
-{
- uae_u8 *dst=tmpmfmbuffer;
- uae_u8 b;
- int size;
- int shift;
-
- size=len-(sync-start);
- memcpy(dst,sync,size);
- dst+=size;
- b=start[len];
- b&=~(255>>bits);
- b|=start[0]>>bits;
- *dst++=b;
- shift=8-bits;
- while(start<=sync+2000) {
- *dst++=(start[0]<<shift)|(start[1]>>(8-shift));
- start++;
- }
- return tmpmfmbuffer;
-}
-
-#define SCANOFFSET 1 /* scanning range in bytes, -SCANOFFSET to SCANOFFSET */
-#define SCANOFFSET2 20
-#define SCANLENGHT 200 /* scanning length in bytes */
-
-static uae_u8* scantrack(uae_u8 *sync1,uae_u8 *sync2,int *trackbytes,int *trackbits)
-{
- int i,bits,bytes,matched;
- uae_u8 *sync2bak=sync2;
-
- sync1+=SCANOFFSET2;
- sync2+=SCANOFFSET2;
- while(sync1 < sync2bak - 2*SCANOFFSET - SCANOFFSET2 - SCANLENGHT) {
- matched=0x7fff;
- for(i=0;i<2*SCANOFFSET*8;i++) {
- bits=i&7;
- bytes=-SCANOFFSET+(i>>3);
- if(!bitshiftcompare(sync1,bits,SCANLENGHT,sync2+bytes)) {
- if(matched==0x7fff) {
- matched=i;
- } else {
- break;
- }
- }
- }
- if(matched!=0x7fff && i>=2*SCANOFFSET*8) {
- bits=matched&7;
- bytes=-SCANOFFSET+(matched>>3);
- *trackbytes=sync2+bytes-sync1;
- *trackbits=bits;
- return mergepieces(sync1,*trackbytes,*trackbits,sync2bak);
- }
- sync1++;
- sync2++;
- }
- return 0;
-}
-
-static unsigned char threshtab[128];
-
-static void codec_makethresh(int trycnt, const unsigned char *origt, unsigned char *t, int numthresh)
-{
- static unsigned char tab[10] = { 0, 0, 0, 0, -1, -2, 1, 2, -1, 1 };
-
- if (trycnt >= sizeof (tab))
- trycnt = sizeof (tab) - 1;
- while(numthresh--)
- t[numthresh] = origt[numthresh] + tab[trycnt];
-}
-
-static void codec_init_threshtab(int trycnt, const unsigned char *origt)
-{
- static unsigned char old_thresholds[2] = { 0, 0 };
- unsigned char t[2];
- int a, i;
-
- codec_makethresh(trycnt, origt, t, 2);
-
- if(*(unsigned short*)t == *(unsigned short*)old_thresholds)
- return;
-
- for(i=0,a=2; i<128; i++) {
- if(i == t[0] || i == t[1])
- a++;
- threshtab[i] = a;
- }
-
- *(unsigned short*)&old_thresholds = *(unsigned short*)t;
-}
-
-static __inline__ void CWSetCReg(catweasel_contr *c, unsigned char clear, unsigned char set)
-{
- c->control_register = (c->control_register & ~clear) | set;
- outb(c->control_register, c->io_sr);
-}
-
-static void CWTriggerStep(catweasel_contr *c)
-{
- CWSetCReg(c, c->crm_step, 0);
- CWSetCReg(c, 0, c->crm_step);
-}
-
-void catweasel_init_controller(catweasel_contr *c)
-{
- int i, j;
-
- if(!c->iobase)
- return;
-
- switch(c->type) {
- case CATWEASEL_TYPE_MK1:
- c->crm_sel0 = 1 << 5;
- c->crm_sel1 = 1 << 4;
- c->crm_mot0 = 1 << 3;
- c->crm_mot1 = 1 << 7;
- c->crm_dir = 1 << 1;
- c->crm_step = 1 << 0;
- c->srm_trk0 = 1 << 4;
- c->srm_dchg = 1 << 5;
- c->srm_writ = 1 << 1;
- c->io_sr = c->iobase + 2;
- c->io_mem = c->iobase;
- break;
- case CATWEASEL_TYPE_MK3:
- case CATWEASEL_TYPE_MK4:
- c->crm_sel0 = 1 << 2;
- c->crm_sel1 = 1 << 3;
- c->crm_mot0 = 1 << 1;
- c->crm_mot1 = 1 << 5;
- c->crm_dir = 1 << 4;
- c->crm_step = 1 << 7;
- c->srm_trk0 = 1 << 2;
- c->srm_dchg = 1 << 5;
- c->srm_writ = 1 << 6;
- c->srm_dskready = 1 << 4;
- c->io_sr = c->iobase + 0xe8;
- c->io_mem = c->iobase + 0xe0;
- break;
- default:
- return;
- }
-
- c->control_register = 255;
-
- /* select all drives, step inside */
- CWSetCReg(c, c->crm_dir | c->crm_sel0 | c->crm_sel1, 0);
- for(i=0;i<2;i++) {
- c->drives[i].number = i;
- c->drives[i].contr = c;
- c->drives[i].diskindrive = 0;
-
- /* select only the respective drive, step to track 0 */
- if(i == 0) {
- CWSetCReg(c, c->crm_sel0, c->crm_dir | c->crm_sel1);
- } else {
- CWSetCReg(c, c->crm_sel1, c->crm_dir | c->crm_sel0);
- }
-
- for(j = 0; j < 86 && (inb(c->io_sr) & c->srm_trk0); j++) {
- CWTriggerStep(c);
- sleep_millis(6);
- }
-
- if(j < 86) {
- c->drives[i].type = 1;
- c->drives[i].track = 0;
- } else {
- c->drives[i].type = 0;
- }
- }
- c->drives[0].sel = c->crm_sel0;
- c->drives[0].mot = c->crm_mot0;
- c->drives[1].sel = c->crm_sel1;
- c->drives[1].mot = c->crm_mot1;
- CWSetCReg(c, 0, c->crm_sel0 | c->crm_sel1); /* deselect all drives */
-}
-
-void catweasel_free_controller(catweasel_contr *c)
-{
- if(!c->iobase)
- return;
-
- /* all motors off, deselect all drives */
- CWSetCReg(c, 0, c->crm_mot0 | c->crm_mot1 | c->crm_sel0 | c->crm_sel1);
-}
-
-void catweasel_set_motor(catweasel_drive *d, int on)
-{
- CWSetCReg(d->contr, d->sel, 0);
- if (on)
- CWSetCReg(d->contr, d->mot, 0);
- else
- CWSetCReg(d->contr, 0, d->mot);
- CWSetCReg(d->contr, 0, d->sel);
-}
-
-int catweasel_step(catweasel_drive *d, int dir)
-{
- catweasel_contr *c = d->contr;
- CWSetCReg(c, d->sel, 0);
- if (dir > 0)
- CWSetCReg(c, c->crm_dir, 0);
- else
- CWSetCReg(c, 0, c->crm_dir);
- CWTriggerStep (c);
- CWSetCReg(c, 0, d->sel);
- d->track += dir > 0 ? 1 : -1;
- return 1;
-}
-
-int catweasel_disk_changed(catweasel_drive *d)
-{
- int ret;
- CWSetCReg(d->contr, d->sel, 0);
- ret = (inb(d->contr->io_sr) & d->contr->srm_dchg) ? 0 : 1;
- CWSetCReg(d->contr, 0, d->sel);
- return ret;
-}
-
-int catweasel_diskready(catweasel_drive *d)
-{
- int ret;
- CWSetCReg(d->contr, d->sel, 0);
- ret = (inb(d->contr->io_sr) & d->contr->srm_dskready) ? 0 : 1;
- CWSetCReg(d->contr, 0, d->sel);
- return ret;
-}
-
-int catweasel_track0(catweasel_drive *d)
-{
- int ret;
- CWSetCReg(d->contr, d->sel, 0);
- ret = (inb(d->contr->io_sr) & d->contr->srm_trk0) ? 0 : 1;
- CWSetCReg(d->contr, 0, d->sel);
- if (ret)
- d->track = 0;
- return ret;
-}
-
-int catweasel_write_protected(catweasel_drive *d)
-{
- int ret;
- CWSetCReg(d->contr, d->sel, 0);
- ret = !(inb(d->contr->io_sr) & 8);
- CWSetCReg(d->contr, 0, d->sel);
- return ret;
-}
-
-uae_u8 catweasel_read_byte(catweasel_drive *d)
-{
- return inb(d->contr->io_mem);
-}
-
-static const unsigned char amiga_thresholds[] = { 0x22, 0x30 }; // 27, 38 for 5.25"
-
-#define FLOPPY_WRITE_LEN 6250
-
-#define MFMMASK 0x55555555
-static uae_u32 getmfmlong (uae_u16 * mbuf)
-{
- return (uae_u32)(((*mbuf << 16) | *(mbuf + 1)) & MFMMASK);
-}
-
-static int drive_write_adf_amigados (uae_u16 *mbuf, uae_u16 *mend, uae_u8 *writebuffer, int track)
-{
- int i, secwritten = 0;
- uae_u32 odd, even, chksum, id, dlong;
- uae_u8 *secdata;
- uae_u8 secbuf[544];
- char sectable[22];
- int num_sectors = 11;
- int ec = 0;
-
- memset (sectable, 0, sizeof (sectable));
- mend -= (4 + 16 + 8 + 512);
- while (secwritten < num_sectors) {
- int trackoffs;
-
- do {
- while (*mbuf++ != 0x4489) {
- if (mbuf >= mend) {
- ec = 1;
- goto err;
- }
- }
- } while (*mbuf++ != 0x4489);
-
- odd = getmfmlong (mbuf);
- even = getmfmlong (mbuf + 2);
- mbuf += 4;
- id = (odd << 1) | even;
-
- trackoffs = (id & 0xff00) >> 8;
- if (trackoffs > 10) {
- ec = 2;
- goto err;
- }
- chksum = odd ^ even;
- for (i = 0; i < 4; i++) {
- odd = getmfmlong (mbuf);
- even = getmfmlong (mbuf + 8);
- mbuf += 2;
-
- dlong = (odd << 1) | even;
- if (dlong) {
- ec = 6;
- goto err;
- }
- chksum ^= odd ^ even;
- } /* could check here if the label is nonstandard */
- mbuf += 8;
- odd = getmfmlong (mbuf);
- even = getmfmlong (mbuf + 2);
- mbuf += 4;
- if (((odd << 1) | even) != chksum) {
- ec = 3;
- goto err;
- }
- odd = (id & 0x00ff0000) >> 16;
- if (odd != track) {
- ec = 7;
- goto err;
- }
- odd = getmfmlong (mbuf);
- even = getmfmlong (mbuf + 2);
- mbuf += 4;
- chksum = (odd << 1) | even;
- secdata = secbuf + 32;
- for (i = 0; i < 128; i++) {
- odd = getmfmlong (mbuf);
- even = getmfmlong (mbuf + 256);
- mbuf += 2;
- dlong = (odd << 1) | even;
- *secdata++ = dlong >> 24;
- *secdata++ = dlong >> 16;
- *secdata++ = dlong >> 8;
- *secdata++ = dlong;
- chksum ^= odd ^ even;
- }
- mbuf += 256;
- if (chksum) {
- ec = 4;
- goto err;
- }
- sectable[trackoffs] = 1;
- secwritten++;
- memcpy (writebuffer + trackoffs * 512, secbuf + 32, 512);
- }
- if (secwritten == 0 || secwritten < 0) {
- ec = 5;
- goto err;
- }
- return 0;
-err:
- write_log ("mfm decode error %d. secwritten=%d\n", ec, secwritten);
- for (i = 0; i < num_sectors; i++)
- write_log ("%d:%d ", i, sectable[i]);
- write_log ("\n");
- return ec;
-}
-
-static void mfmcode (uae_u16 * mfm, int words)
-{
- uae_u32 lastword = 0;
-
- while (words--) {
- uae_u32 v = *mfm;
- uae_u32 lv = (lastword << 16) | v;
- uae_u32 nlv = 0x55555555 & ~lv;
- uae_u32 mfmbits = (nlv << 1) & (nlv >> 1);
-
- *mfm++ = v | mfmbits;
- lastword = v;
- }
-}
-
-#define FLOPPY_GAP_LEN 360
-
-static int amigados_mfmcode (uae_u8 *src, uae_u16 *dst, int num_secs, int track)
-{
- int sec;
- memset (dst, 0xaa, FLOPPY_GAP_LEN * 2);
-
- for (sec = 0; sec < num_secs; sec++) {
- uae_u8 secbuf[544];
- int i;
- uae_u16 *mfmbuf = dst + 544 * sec + FLOPPY_GAP_LEN;
- uae_u32 deven, dodd;
- uae_u32 hck = 0, dck = 0;
-
- secbuf[0] = secbuf[1] = 0x00;
- secbuf[2] = secbuf[3] = 0xa1;
- secbuf[4] = 0xff;
- secbuf[5] = track;
- secbuf[6] = sec;
- secbuf[7] = num_secs - sec;
-
- for (i = 8; i < 24; i++)
- secbuf[i] = 0;
-
- mfmbuf[0] = mfmbuf[1] = 0xaaaa;
- mfmbuf[2] = mfmbuf[3] = 0x4489;
-
- memcpy (secbuf + 32, src + sec * 512, 512);
- deven = ((secbuf[4] << 24) | (secbuf[5] << 16)
- | (secbuf[6] << 8) | (secbuf[7]));
- dodd = deven >> 1;
- deven &= 0x55555555;
- dodd &= 0x55555555;
-
- mfmbuf[4] = dodd >> 16;
- mfmbuf[5] = dodd;
- mfmbuf[6] = deven >> 16;
- mfmbuf[7] = deven;
-
- for (i = 8; i < 48; i++)
- mfmbuf[i] = 0xaaaa;
- for (i = 0; i < 512; i += 4) {
- deven = ((secbuf[i + 32] << 24) | (secbuf[i + 33] << 16)
- | (secbuf[i + 34] << 8) | (secbuf[i + 35]));
- dodd = deven >> 1;
- deven &= 0x55555555;
- dodd &= 0x55555555;
- mfmbuf[(i >> 1) + 32] = dodd >> 16;
- mfmbuf[(i >> 1) + 33] = dodd;
- mfmbuf[(i >> 1) + 256 + 32] = deven >> 16;
- mfmbuf[(i >> 1) + 256 + 33] = deven;
- }
-
- for (i = 4; i < 24; i += 2)
- hck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
-
- deven = dodd = hck;
- dodd >>= 1;
- mfmbuf[24] = dodd >> 16;
- mfmbuf[25] = dodd;
- mfmbuf[26] = deven >> 16;
- mfmbuf[27] = deven;
-
- for (i = 32; i < 544; i += 2)
- dck ^= (mfmbuf[i] << 16) | mfmbuf[i + 1];
-
- deven = dodd = dck;
- dodd >>= 1;
- mfmbuf[28] = dodd >> 16;
- mfmbuf[29] = dodd;
- mfmbuf[30] = deven >> 16;
- mfmbuf[31] = deven;
- mfmcode (mfmbuf + 4, 544 - 4);
-
- }
- return (num_secs * 544 + FLOPPY_GAP_LEN) * 2 * 8;
-}
-
-static uae_u16 amigamfmbuffer[LONGEST_TRACK];
-static uae_u8 amigabuffer[512*22];
-
-/* search and align to 0x4489 WORDSYNC markers */
-static int isamigatrack(uae_u8 *mfmdata, uae_u8 *mfmdatae, uae_u16 *mfmdst, int track)
-{
- uae_u16 *dst = amigamfmbuffer;
- int len;
- int shift, syncshift, sync,ret;
- uae_u32 l;
- uae_u16 w;
-
- sync = syncshift = shift = 0;
- len = (mfmdatae - mfmdata) * 8;
- if (len > LONGEST_TRACK * 8)
- len = LONGEST_TRACK * 8;
- while (len--) {
- l = (mfmdata[0] << 16) | (mfmdata[1] << 8) | (mfmdata[2] << 0);
- w = l >> (8 - shift);
- if (w == 0x4489) {
- sync = 1;
- syncshift = 0;
- }
- if (sync) {
- if (syncshift == 0) *dst++ = w;
- syncshift ++;
- if (syncshift == 16) syncshift = 0;
- }
- shift++;
- if (shift == 8) {
- mfmdata++;
- shift = 0;
- }
- }
- if (sync) {
- ret=drive_write_adf_amigados (amigamfmbuffer, dst, amigabuffer, track);
- if(!ret)
- return amigados_mfmcode (amigabuffer, mfmdst, 11, track);
- write_log ("decode error %d\n", ret);
- } else {
- write_log ("decode error: no sync found\n");
- }
- return 0;
-}
-
-
-
-int catweasel_fillmfm (catweasel_drive *d, uae_u16 *mfm, int side, int clock, int rawmode)
-{
- int i, j, oldsync, syncs[10], synccnt, endcnt;
- uae_u32 tt1 = 0, tt2 = 0;
- uae_u8 *p1;
- int bytes = 0, bits = 0;
- static int lasttrack, trycnt;
-
- if (cwc.type == 0)
- return 0;
- if (d->contr->control_register & d->mot)
- return 0;
- if (!catweasel_read (d, side, 1, rawmode))
- return 0;
- if(d->contr->type == CATWEASEL_TYPE_MK1) {
- inb(d->contr->iobase + 1);
- inb(d->contr->io_mem); /* ignore first byte */
- } else {
- outb(0, d->contr->iobase + 0xe4);
- }
- catweasel_read_byte (d);
- if (lasttrack == d->track)
- trycnt++;
- else
- trycnt = 0;
- lasttrack = d->track;
- codec_init_threshtab(trycnt, amiga_thresholds);
- i = 0; j = 0;
- synccnt = 0;
- oldsync = -1;
- endcnt = 0;
- while (j < LONGEST_TRACK * 4) {
- uae_u8 b = catweasel_read_byte (d);
- if (b >= 250) {
- if (b == 255 - endcnt) {
- endcnt++;
- if (endcnt == 5)
- break;
- } else
- endcnt = 0;
- }
- if (rawmode) {
- if (b & 0x80) {
- if (oldsync < j) {
- syncs[synccnt++] = j;
- oldsync = j + 300;
- }
- }
- if (synccnt >= 3 && j > oldsync)
- break;
- }
- b = threshtab[b & 0x7f];
- tt1 = (tt1 << b) + 1;
- tt2 += b;
-
- if (tt2 >= 16) {
- tt2 -= 16;
- mfmbuf[j++] = tt1 >> (tt2 + 8);
- mfmbuf[j++] = tt1 >> tt2;
- }
- i++;
- }
- write_log ("cyl=%d, side=%d, length %d, syncs %d\n", d->track, side, j, synccnt);
- if (rawmode) {
- if (synccnt >= 3) {
- p1 = scantrack (mfmbuf + syncs[1], mfmbuf + syncs[2], &bytes, &bits);
- if (p1) {
- j = 0;
- for (i = 0; i < bytes + 2; i+=2) {
- mfm[j++] = (p1[i] << 8) | p1[i + 1];
- }
- return bytes * 8 + bits;
- }
- }
- } else {
- return isamigatrack (mfmbuf, mfmbuf + j, mfm, d->track * 2 + side);
- }
- return 0;
-}
-
-int catweasel_read(catweasel_drive *d, int side, int clock, int rawmode)
-{
- int iobase = d->contr->iobase;
-
- CWSetCReg(d->contr, d->sel, 0);
- if(d->contr->type == CATWEASEL_TYPE_MK1) {
- CWSetCReg(d->contr, 1<<2, (!side)<<2); /* set disk side */
-
- inb(iobase+1); /* ra reset */
- outb(clock*128, iobase+3);
-
- inb(iobase+1);
- inb(iobase+0);
-// inb(iobase+0);
-// outb(0, iobase+3); /* don't store index pulse */
-
- inb(iobase+1);
-
- inb(iobase+7); /* start reading */
- sleep_millis(rawmode ? 550 : 225);
- outb(0, iobase+1); /* stop reading, don't reset RAM pointer */
-
- outb(128, iobase+0); /* add data end mark */
- outb(128, iobase+0);
-
- inb(iobase+1); /* Reset RAM pointer */
- } else {
- CWSetCReg(d->contr, 1<<6, (!side)<<6); /* set disk side */
-
- outb(0, iobase + 0xe4); /* Reset memory pointer */
- switch(clock) {
- case 0: /* 28MHz */
- outb(128, iobase + 0xec);
- break;
- case 1: /* 14MHz */
- outb(0, iobase + 0xec);
- break;
- }
- inb(iobase + 0xe0);
- inb(iobase + 0xe0);
- outb(0, iobase + 0xec); /* no IRQs, no MFM predecode */
- inb(iobase + 0xe0);
- outb(0, iobase + 0xec); /* don't store index pulse */
-
- outb(0, iobase + 0xe4); /* Reset memory pointer */
- inb(iobase + 0xf0); /* start reading */
- sleep_millis(rawmode ? 550 : 225);
- inb(iobase + 0xe4); /* stop reading, don't reset RAM pointer */
-
- outb(255, iobase + 0xe0); /* add data end mark */
- outb(254, iobase + 0xe0); /* add data end mark */
- outb(253, iobase + 0xe0); /* add data end mark */
- outb(252, iobase + 0xe0); /* add data end mark */
- outb(251, iobase + 0xe0); /* add data end mark */
- outb(0, iobase + 0xe4); /* Reset memory pointer */
- }
- CWSetCReg(d->contr, 0, d->sel);
- return 1;
-}
-
-#endif
-
#endif
\ No newline at end of file
typedef struct catweasel_contr {
int type; /* see CATWEASEL_TYPE_* defines below */
+ int direct_access;
int direct_type;
int iobase; /* 0 = not present (factory default is 0x320) */
void (*msdelay)(int ms); /* microseconds delay routine, provided by host program */
return EXCEPTION_CONTINUE_EXECUTION;
}
}
- write_log ("JIT: Can't handle access %08.8X!\n", i);
+ write_log ("JIT: Can't handle access %08X!\n", i);
#if 0
if (i)
{
/*
* UAE - The Un*x Amiga Emulator
*
- * DirectSound AHI 7.1 wrapper
+ * OpenAL AHI 7.1 wrapper
*
* Copyright 2008 Toni Wilen
*/
#include "ahidsound_new.h"
#include "dxwrap.h"
-#include <mmsystem.h>
-#include <mmreg.h>
-#include <dsound.h>
-#include <ks.h>
-#include <ksmedia.h>
+#include <al.h>
+#include <alc.h>
#define AHI_STRUCT_VERSION 1
#define UAE_MAXCHANNELS 24
#define UAE_MAXSOUNDS 256
#define RECORDSAMPLES 2048
+#define PLAYSAMPLES 1536
#define ub_Flags 34
#define ub_Pad1 (ub_Flags + 1)
uae_u32 len;
uae_u32 type;
uae_u32 sampletype;
- uae_u32 offset;
+ ALuint al_buffer[2];
};
struct chsample {
struct dssample *ds;
int srcplayoffset;
int srcplaylen;
- int stopit;
};
struct dschannel {
int num;
struct chsample cs;
struct chsample csnext;
- LPDIRECTSOUNDBUFFER8 dsb;
-
- uae_u8 *buffer;
- int mixlength;
- int buffercursor;
- int hsync;
int channelsignal;
- int srcoffset;
-
int dsplaying;
- int dscursor;
+ ALuint al_source;
+ int samplecounter;
};
struct DSAHI {
int playing, recording;
evt evttime;
uae_u32 signalchannelmask;
- LPDIRECTSOUND8 DS;
- LPDIRECTSOUNDCAPTURE DSC;
- LPDIRECTSOUNDCAPTUREBUFFER dscb;
+ ALCdevice *al_dev;
+ ALCcontext *al_ctx;
+ int al_bufferformat;
+ uae_u8 *tmpbuffer;
+ int tmpbuffer_size;
int dsrecording;
- int recordingcursor;
int record_ch;
int record_bytespersample;
- int channellength_record;
- int mixlength_record;
int record_wait;
+ int maxplaysamples;
};
static struct DSAHI dsahi[1];
ch = get_word (channelinfo + ahieci_Channels);
if (ch > UAE_MAXCHANNELS)
ch = UAE_MAXCHANNELS;
- for (i = 0; i < ch; i++)
- put_long (channelinfo + ahieci_Offset + i * 4, dsahip->channel[i].srcoffset);
+ for (i = 0; i < ch; i++) {
+ int v;
+ alGetSourcei (dsahip->channel[i].al_source, AL_SAMPLE_OFFSET, &v);
+ put_long (channelinfo + ahieci_Offset + i * 4, v);
+ }
}
uae_Signal (task, signalmask);
int ch = dc - &dsahip->channel[0];
uae_u32 mask;
- if (!dsahip->playing || ahi_paused || dc->dsb == NULL)
+ if (!dsahip->playing || ahi_paused || !dc->al_source)
return;
mask = get_long (puaebase + pub_ChannelSignal);
if (mask & (1 << ch))
event2_newevent2 (t, dsahip - &dsahi[0], evtfunc);
}
+static void alClear (void)
+{
+ alGetError ();
+}
+static int alError (const char *format,...)
+{
+ char buffer[1000];
+ va_list parms;
+ int err;
-
-const static GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010,
- {0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};
+ err = alGetError ();
+ if (err == AL_NO_ERROR)
+ return 0;
+ va_start (parms, format);
+ _vsnprintf (buffer, sizeof buffer -1, format, parms);
+ sprintf (buffer + strlen (buffer), ": ERR=%x\n", err);
+ write_log ("%s", buffer);
+ return err;
+}
static void ds_freechannel (struct DSAHI *ahidsp, struct dschannel *dc)
{
if (!dc)
return;
- if (dc->dsb)
- IDirectSoundBuffer8_Release (dc->dsb);
- xfree (dc->buffer);
+ alDeleteSources (1, &dc->al_source);
memset (dc, 0, sizeof (struct dschannel));
+ dc->al_source = -1;
+}
+
+static void ds_freesample (struct DSAHI *ahidsp, struct dssample *ds)
+{
+ if (!ds)
+ return;
+ alDeleteBuffers (2, ds->al_buffer);
+ memset (ds, 0, sizeof (struct dssample));
+ ds->al_buffer[0] = -1;
+ ds->al_buffer[1] = -1;
}
static void ds_free (struct DSAHI *dsahip)
{
int i;
+ if (!ahi_active)
+ return;
for (i = 0; i < dsahip->channels; i++) {
struct dschannel *dc = &dsahip->channel[i];
ds_freechannel (dsahip, dc);
}
- if (dsahip->DS)
- IDirectSound_Release (dsahip->DS);
- dsahip->DS = NULL;
+ for (i = 0; i < dsahip->sounds; i++) {
+ struct dssample *ds = &dsahip->sample[i];
+ ds_freesample (dsahip, ds);
+ }
+ alcMakeContextCurrent (NULL);
+ alcDestroyContext (dsahip->al_ctx);
+ dsahip->al_ctx = 0;
+ alcCloseDevice (dsahip->al_dev);
+ dsahip->al_dev = 0;
if (ahi_debug && ahi_active)
- write_log ("AHI: DSOUND freed\n");
+ write_log ("AHI: OpenAL freed\n");
ahi_active = 0;
}
-DWORD fillsupportedmodes (LPDIRECTSOUND8 lpDS, int freq, struct dsaudiomodes *dsam);
-static struct dsaudiomodes supportedmodes[16];
-
static void ds_free_record (struct DSAHI *dsahip)
{
- if (dsahip->dscb)
- IDirectSoundCaptureBuffer_Release (dsahip->dscb);
- if (dsahip->DSC)
- IDirectSoundCapture_Release (dsahip->DSC);
- dsahip->dscb = NULL;
- dsahip->DSC = NULL;
}
static int ds_init_record (struct DSAHI *dsahip)
{
- HRESULT hr;
- WAVEFORMATEXTENSIBLE wavfmt;
- DSCBUFFERDESC dbd;
uae_u32 pbase = get_long (dsahip->audioctrl + ahiac_DriverData);
int freq = get_long (dsahip->audioctrl + ahiac_MixFreq);
- if (dsahip->DSC)
- return 1;
if (!freq)
return 0;
- dsahip->mixlength_record = RECORDSAMPLES; // in sample units, not bytes
- dsahip->record_ch = 2;
- dsahip->record_bytespersample = 2;
- dsahip->channellength_record = freq * dsahip->record_bytespersample * dsahip->record_ch * 10;
- put_long (pbase + pub_RecordBufferSize, dsahip->mixlength_record);
- put_long (pbase + pub_RecordBufferSizeBytes, dsahip->mixlength_record * dsahip->record_ch * dsahip->record_bytespersample);
- put_long (pbase + pub_RecordSampleType, AHIST_S16S);
- put_word (pbase + pub_RecordHookDone, 0);
-
- hr = DirectSoundCaptureCreate (&record_devices[dsahip->input].guid, &dsahip->DSC, NULL);
- if (FAILED (hr)) {
- write_log ("AHI: DirectSoundCaptureCreate() failure %dHz: %s\n", freq, DXError (hr));
- goto end;
- }
- memset (&dbd, 0, sizeof dbd);
- dbd.dwSize = sizeof dbd;
- dbd.dwBufferBytes = dsahip->channellength_record;
- dbd.lpwfxFormat = &wavfmt.Format;
- dbd.dwFlags = 0 ;
- memset (&wavfmt, 0, sizeof wavfmt);
- wavfmt.Format.nChannels = dsahip->record_ch;
- wavfmt.Format.nSamplesPerSec = freq;
- wavfmt.Format.wBitsPerSample = dsahip->record_bytespersample * 8;
- wavfmt.Format.wFormatTag = WAVE_FORMAT_PCM;
- wavfmt.Format.nBlockAlign = wavfmt.Format.wBitsPerSample / 8 * wavfmt.Format.nChannels;
- wavfmt.Format.nAvgBytesPerSec = wavfmt.Format.nBlockAlign * wavfmt.Format.nSamplesPerSec;
- hr = IDirectSoundCapture_CreateCaptureBuffer (dsahip->DSC, &dbd, &dsahip->dscb, NULL);
- if (FAILED (hr)) {
- write_log ("AHI: CreateCaptureSoundBuffer() failure: %s\n", DXError(hr));
- goto end;
- }
- if (ahi_debug)
- write_log ("AHI: DSOUND Recording initialized. %dHz, %s\n", freq, record_devices[dsahip->input].name);
-
- put_word (pbase + pub_FuncMode, get_word (pbase + pub_FuncMode) | FUNCMODE_RECORDALLOC);
- sendsignal (dsahip);
- return 1;
-end:
- ds_free_record (dsahip);
return 0;
}
static int ds_init (struct DSAHI *dsahip)
{
int freq = 44100;
- DSCAPS DSCaps;
- HRESULT hr;
- DWORD speakerconfig;
-
- hr = DirectSoundCreate8 (&sound_devices[dsahip->output].guid, &dsahip->DS, NULL);
- if (FAILED (hr)) {
- write_log ("AHI: DirectSoundCreate8() failure: %s\n", DXError (hr));
- return 0;
+ int v, wrapped;
+ struct sound_device *sd;
+
+ sd = &sound_devices[currprefs.win32_soundcard];
+ wrapped = 0;
+ while (sd->type != SOUND_DEVICE_AL) {
+ sd++;
+ if (sd->name == NULL) {
+ if (wrapped)
+ return 0;
+ wrapped = 1;
+ sd = sound_devices;
+ }
}
-
- hr = IDirectSound_SetCooperativeLevel (dsahip->DS, hMainWnd, DSSCL_PRIORITY);
- if (FAILED (hr)) {
- write_log ("AHI: Can't set cooperativelevel: %s\n", DXError (hr));
+ dsahip->al_dev = alcOpenDevice (sd->alname);
+ if (!dsahip->al_dev)
goto error;
- }
+ dsahip->al_ctx = alcCreateContext (dsahip->al_dev, NULL);
+ if (!dsahip->al_ctx)
+ goto error;
+ alcMakeContextCurrent (dsahip->al_ctx);
- fillsupportedmodes (dsahip->DS, default_freq, supportedmodes);
dsahip->chout = 2;
- if (SUCCEEDED (IDirectSound8_GetSpeakerConfig (dsahip->DS, &speakerconfig))) {
- if (speakerconfig >= DSSPEAKER_CONFIG (DSSPEAKER_5POINT1)) {
- cansurround = 1;
- dsahip->chout = 6;
- if (speakerconfig >= DSSPEAKER_CONFIG (DSSPEAKER_7POINT1))
- dsahip->chout = 8;
- }
+ dsahip->al_bufferformat = AL_FORMAT_STEREO16;
+ if (v = alGetEnumValue ("AL_FORMAT_QUAD16")) {
+ dsahip->chout = 4;
+ cansurround = 1;
+ dsahip->al_bufferformat = v;
+ }
+ if (v = alGetEnumValue ("AL_FORMAT_51CHN16")) {
+ dsahip->chout = 6;
+ cansurround = 1;
+ dsahip->al_bufferformat = v;
}
-
dsahip->bitspersampleout = dsahip->bits24 ? 24 : 16;
dsahip->bytespersampleout = dsahip->bitspersampleout / 8;
dsahip->channellength = 65536 * dsahip->chout * dsahip->bytespersampleout;
- dsahip->mixlength = 4000 * dsahip->chout * dsahip->bytespersampleout;
if (ahi_debug)
- write_log("AHI: CH=%d BLEN=%d MLEN=%d SC=%08x\n",
- dsahip->chout, dsahip->channellength, dsahip->mixlength, speakerconfig);
-
- memset (&DSCaps, 0, sizeof (DSCaps));
- DSCaps.dwSize = sizeof (DSCaps);
- hr = IDirectSound_GetCaps (dsahip->DS, &DSCaps);
- if (FAILED(hr)) {
- write_log ("AHI: Error getting DirectSound capabilities: %s\n", DXError (hr));
- goto error;
- }
- if (DSCaps.dwFlags & DSCAPS_EMULDRIVER) {
- write_log ("AHI: Emulated DirectSound driver detected, don't complain if sound quality is crap :)\n");
- }
- if (DSCaps.dwFlags & DSCAPS_CONTINUOUSRATE) {
- int minfreq = DSCaps.dwMinSecondarySampleRate;
- int maxfreq = DSCaps.dwMaxSecondarySampleRate;
- if (minfreq > freq && freq < 22050) {
- freq = minfreq;
- write_log ("AHI: minimum supported frequency: %d\n", minfreq);
- }
- if (maxfreq < freq && freq > 44100) {
- freq = maxfreq;
- write_log ("AHI: maximum supported frequency: %d\n", maxfreq);
- }
- }
+ write_log("AHI: CH=%d BLEN=%d\n",
+ dsahip->chout, dsahip->channellength);
+ dsahip->tmpbuffer_size = 2000000;
+ dsahip->tmpbuffer = xmalloc (dsahip->tmpbuffer_size);
if (ahi_debug)
- write_log ("AHI: DSOUND initialized: %s\n", sound_devices[dsahip->output].name);
+ write_log ("AHI: OpenAL initialized: %s\n", sound_devices[dsahip->output].name);
return 1;
error:
if (ahi_debug)
- write_log ("AHI: DSOUND initialization failed\n");
+ write_log ("AHI: OpenAL initialization failed\n");
ds_free (dsahip);
return 0;
}
return ds_init (dsahip);
}
-
static void ds_setvolume (struct DSAHI *dsahip, struct dschannel *dc)
{
- HRESULT hr;
- LONG vol, pan;
-
- if (dc->dsb) {
+ if (dc->al_source != -1) {
if (abs (dc->cs.volume) != abs (dc->csnext.volume)) {
- vol = (LONG)((DSBVOLUME_MIN / 2) + (-DSBVOLUME_MIN / 2) * log (1 + (2.718281828 - 1) * (abs (dc->csnext.volume) / 65536.0)));
- hr = IDirectSoundBuffer_SetVolume (dc->dsb, vol);
- if (FAILED (hr))
- write_log ("AHI: SetVolume(%d,%d) failed: %s\n", dc->num, vol, DXError (hr));
+ float vol = (float)(abs (dc->csnext.volume) / 65536.0);
+ alClear ();
+ alSourcef (dc->al_source, AL_GAIN, vol);
+ alError ("AHI: SetVolume(%d,%d)", dc->num, vol);
}
if (abs (dc->cs.panning) != abs (dc->csnext.panning)) {
- pan = (abs (dc->csnext.panning) - 0x8000) * DSBPAN_RIGHT / 32768;
- hr = IDirectSoundBuffer_SetPan (dc->dsb, pan);
- if (FAILED (hr))
- write_log ("AHI: SetPan(%d,%d) failed: %s\n", dc->num, pan, DXError (hr));
+;// pan = (abs (dc->csnext.panning) - 0x8000) * DSBPAN_RIGHT / 32768;
}
}
dc->cs.volume = dc->csnext.volume;
static void ds_setfreq (struct DSAHI *dsahip, struct dschannel *dc)
{
- HRESULT hr;
-
- if (dc->cs.frequency != dc->csnext.frequency && dc->csnext.frequency > 0 && dc->dsb) {
- hr = IDirectSoundBuffer8_SetFrequency (dc->dsb, dc->csnext.frequency);
- if (FAILED (hr))
- write_log ("AHI: SetFrequency(%d,%d) failed: %s\n", dc->num, dc->csnext.frequency, DXError (hr));
+ if (dc->dsplaying && dc->cs.frequency != dc->csnext.frequency && dc->csnext.frequency > 0 && dc->al_source != -1) {
+ //alClear ();
+ //alSourcei (dc->al_source, AL_FREQUENCY, dc->csnext.frequency);
+ //alError ("AHI: SetFrequency(%d,%d)", dc->num, dc->csnext.frequency);
}
dc->cs.frequency = dc->csnext.frequency;
}
static int ds_allocchannel (struct DSAHI *dsahip, struct dschannel *dc)
{
- HRESULT hr;
- DSBUFFERDESC dd;
- WAVEFORMATEXTENSIBLE wavfmt;
- LPDIRECTSOUNDBUFFER pdsb;
- LPDIRECTSOUNDBUFFER8 pdsb8;
- int round;
-
- if (dc->dsb)
+ if (dc->al_source != -1)
return 1;
- pdsb = NULL;
- for (round = 0; supportedmodes[round].ch; round++) {
- DWORD ksmode = 0;
-
- pdsb = NULL;
- if (supportedmodes[round].ch != dsahip->chout)
- continue;
-
- memset (&wavfmt, 0, sizeof (WAVEFORMATEXTENSIBLE));
- wavfmt.Format.nChannels = dsahip->chout;
- wavfmt.Format.nSamplesPerSec = default_freq;
- wavfmt.Format.wBitsPerSample = dsahip->bitspersampleout;
- if (dsahip->chout <= 2) {
- wavfmt.Format.wFormatTag = WAVE_FORMAT_PCM;
- } else {
- DWORD ksmode = 0;
- wavfmt.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
- wavfmt.Format.cbSize = sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX);
- wavfmt.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- wavfmt.Samples.wValidBitsPerSample = dsahip->bitspersampleout;
- wavfmt.dwChannelMask = supportedmodes[round].ksmode;
- }
- wavfmt.Format.nBlockAlign = dsahip->bytespersampleout * wavfmt.Format.nChannels;
- wavfmt.Format.nAvgBytesPerSec = wavfmt.Format.nBlockAlign * wavfmt.Format.nSamplesPerSec;
-
- memset (&dd, 0, sizeof dd);
- dd.dwSize = sizeof dd;
- dd.dwBufferBytes = dsahip->channellength;
- dd.lpwfxFormat = &wavfmt.Format;
- dd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY;
- dd.dwFlags |= DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
- dd.dwFlags |= dsahip->chout >= 4 ? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE;
- dd.guid3DAlgorithm = GUID_NULL;
-
- hr = IDirectSound_CreateSoundBuffer (dsahip->DS, &dd, &pdsb, NULL);
- if (SUCCEEDED (hr))
- break;
- if (dd.dwFlags & DSBCAPS_LOCHARDWARE) {
- HRESULT hr2 = hr;
- dd.dwFlags &= ~DSBCAPS_LOCHARDWARE;
- dd.dwFlags |= DSBCAPS_LOCSOFTWARE;
- hr = IDirectSound_CreateSoundBuffer (dsahip->DS, &dd, &pdsb, NULL);
- if (SUCCEEDED (hr))
- break;
- }
- write_log ("AHI: DS sound buffer failed (ch=%d,bps=%d): %s\n",
- dsahip->chout, dsahip->bitspersampleout, DXError (hr));
- }
- if (pdsb == NULL)
- goto error;
-
- hr = IDirectSound_QueryInterface (pdsb, &IID_IDirectSoundBuffer8, (LPVOID*)&pdsb8);
- if (FAILED (hr)) {
- write_log ("AHI: Secondary QueryInterface(IID_IDirectSoundBuffer8) failure: %s\n", DXError (hr));
+ alClear ();
+ alGenSources (1, &dc->al_source);
+ if (alError ("alGenSources()"))
goto error;
- }
- IDirectSound_Release (pdsb);
- dc->dsb = pdsb8;
-
dc->cs.frequency = -1;
dc->cs.volume = -1;
dc->cs.panning = -1;
ds_setvolume (dsahip, dc);
ds_setfreq (dsahip, dc);
- dc->mixlength = dsahip->mixlength;
- dc->buffer = xcalloc (dc->mixlength, 1);
- dc->buffercursor = 0;
if (ahi_debug)
- write_log ("AHI: allocated directsound buffer for channel %d\n", dc->num);
+ write_log ("AHI: allocated OpenAL source for channel %d. vol=%d pan=%d freq=%d\n",
+ dc->num, dc->cs.volume, dc->cs.panning, dc->cs.frequency);
return 1;
error:
ds_freechannel (dsahip, dc);
}
}
-static void copysampledata (struct DSAHI *dsahip, struct dschannel *dc, struct dssample *ds, uae_u8 **psrcp, uae_u8 *srce, uae_u8 *srcp, void *dstp, int dstlen)
+/* sample conversion routines */
+static int copysampledata (struct DSAHI *dsahip, struct dschannel *dc, struct dssample *ds, uae_u8 **psrcp, uae_u8 *srce, uae_u8 *srcp, void *dstp, int dstlen)
{
int i;
uae_u8 *src = *psrcp;
break;
}
*psrcp = src;
+ return dstlen * och2;
}
static void dorecord (struct DSAHI *dsahip)
{
+#if 0
uae_u32 pbase = get_long (dsahip->audioctrl + ahiac_DriverData);
HRESULT hr;
DWORD cpos, rpos, diff;
dsahip->recordingcursor += mixlength_bytes;
if (dsahip->recordingcursor >= dsahip->channellength_record)
dsahip->recordingcursor -= dsahip->channellength_record;
+#endif
}
-static int ds_copysample (struct DSAHI *dsahip, struct dschannel *dc)
-{
- HRESULT hr;
- DWORD playc, writec;
- DWORD size1, size2;
- DWORD diff;
- void *buf1, *buf2;
-
- hr = IDirectSoundBuffer8_GetCurrentPosition (dc->dsb, &playc, &writec);
- if (FAILED (hr)) {
- write_log ("AHI: GetCurrentPosition(%d) failed, %s\n", dc->num, DXError (hr));
- return 0;
- }
-
- if (dc->dscursor >= writec)
- diff = dc->dscursor - writec;
- else
- diff = dsahip->channellength - writec + dc->dscursor;
-
- if (diff > dsahip->channellength / 2) {
- dc->dscursor = writec + dc->mixlength;
- write_log ("AHI: Resync\n");
- }
- if (diff > dc->mixlength)
- return 0;
- hr = IDirectSoundBuffer8_Lock (dc->dsb, dc->dscursor, dc->mixlength, &buf1, &size1, &buf2, &size2, 0);
- if (hr == DSERR_BUFFERLOST) {
- IDirectSoundBuffer8_Restore (dc->dsb);
- hr = IDirectSoundBuffer8_Lock (dc->dsb, dc->dscursor, dc->mixlength, &buf1, &size1, &buf2, &size2, 0);
- }
- if (SUCCEEDED (hr)) {
- memcpy (buf1, dc->buffer, size1);
- if (buf2)
- memcpy (buf2, dc->buffer + size1, size2);
- IDirectSoundBuffer8_Unlock (dc->dsb, buf1, size1, buf2, size2);
- }
-
- if (ahi_debug > 1)
- write_log ("%d playc=%08d writec=%08d dscursor=%08d\n",
- diff / (dsahip->chout * dsahip->bytespersampleout),
- playc, writec, dc->dscursor);
-
- dc->dscursor += dc->mixlength;
- if (dc->dscursor >= dsahip->channellength)
- dc->dscursor -= dsahip->channellength;
-
- return 1;
-}
-
-static int calcdelay (struct dschannel *dc, int len)
+static void al_setloop (struct dschannel *dc, int state)
{
- int rate = vblank_hz * maxvpos;
- int freq = dc->cs.frequency;
- int hsyncs = rate * len / freq;
- hsyncs = hsyncs * 2 / 3;
- if (hsyncs > 0)
- hsyncs--;
- return hsyncs;
+ alClear ();
+ alSourcei (dc->al_source, AL_LOOPING, state ? AL_TRUE : AL_FALSE);
+ alError ("AHI: ds_play() alSourcei(AL_LOOPING)");
}
-#if 0
-static void checkvolfreq (struct DSAHI *dsahip, struct dschannel *dc)
+static void al_startplay (struct dschannel *dc)
{
- if (dc->cs.frequency != dc->csnext.frequency)
- ds_setfreq (dsahip, dc);
- if (dc->cs.volume != dc->csnext.volume || dc->cs.panning != dc->csnext.panning)
- ds_setvolume (dsahip, dc);
+ al_setloop (dc, TRUE);
+ alClear ();
+ alSourcePlay (dc->al_source);
+ alError ("AHI: ds_play() alSourcePlay");
}
-static void getmixbufferlen (struct DSAHI *dsahip, struct dschannel *dc)
+static void preparesample (struct DSAHI *dsahip, struct dschannel *dc)
{
- int olen = dc->mixlength;
- dc->mixlength = (dc->csnext.frequency / 24) * dsahip->bytespersampleout * dsahip->chout;
- if (dc->mixlength > dsahip->mixlength)
- dc->mixlength = dsahip->mixlength;
- if (dc->mixlength < 100)
- dc->mixlength = 100;
- if (ahi_debug && olen != dc->mixlength)
- write_log ("AHI: channel %d: buffer %d frames\n",
- dc->num, dc->mixlength / (dsahip->bytespersampleout * dsahip->chout));
+ uae_u8 *p, *ps, *pe;
+ struct dssample *ds;
+ int num, slen, dlen, offset;
+
+ memcpy (&dc->cs, &dc->csnext, sizeof (struct chsample));
+ dc->csnext.ds = NULL;
+ ds = dc->cs.ds;
+ ps = p = get_real_address (ds->addr);
+ pe = ps + ds->len * ds->bytespersample * ds->ch;
+ num = ds->len / dsahip->maxplaysamples;
+ offset = dsahip->maxplaysamples * dc->samplecounter;
+ slen = dsahip->maxplaysamples;
+ if (dc->samplecounter == num - 1)
+ slen = ds->len - dsahip->maxplaysamples * (num - 1);
+ p += (offset + dc->cs.srcplayoffset) * ds->bytespersample * ds->ch;
+ dlen = copysampledata (dsahip, dc, ds, &p, pe, ps, dsahip->tmpbuffer, slen);
+ alClear ();
+ alBufferData (ds->al_buffer[dc->samplecounter], dsahip->al_bufferformat, dsahip->tmpbuffer, dlen, dc->cs.frequency);
+ alError ("AHI: preparesample:alBufferData()");
}
-static void copysample (struct DSAHI *dsahip, struct dschannel *dc)
+static void al_initsample (struct DSAHI *dsahip, struct dschannel *dc)
{
- int dstlen, dstlenbytes;
struct dssample *ds;
- int srclen, srclendstbytes;
- int chbytesout;
- uae_u8 *dstbuf;
- uae_u32 addr, addre, addrs;
- int chbytesin;
- int waitlen;
-
- assert (dc->buffercursor < dc->mixlength);
-
- chbytesout = dsahip->chout * dsahip->bytespersampleout;
- dstbuf = dc->buffer + dc->buffercursor;
- dstlenbytes = dc->mixlength - dc->buffercursor;
- dstlen = dstlenbytes / chbytesout;
-
- ds = dc->cs.ds;
- if (ds == NULL) {
- ds = dc->ds = dc->nextds;
- dc->srcplaylen = dc->nextsrcplaylen;
- dc->srcplayoffset = dc->nextsrcplayoffset;
- dc->nextds = NULL;
- dc->nextsrcplaylen = 0;
- dc->nextsrcplayoffset = 0;
- dc->srcoffset = 0;
- if (ds != NULL) { // sample started
- int len;
- setchannelevent (dsahip, dc);
- len = dc->srcplaylen;
- if (len > dstlen)
- len = dstlen;
- dc->hsync = calcdelay (dc, len);
- return;
- }
- }
- if (ds == NULL)
- goto cempty;
-
- chbytesin = ds->ch * ds->bytespersample;
- if (ds->addr == 0 && ds->len == 0xffffffff) {
- addrs = addr = ds->offset;
- } else {
- addr = ds->addr;
- addr += dc->srcplayoffset * chbytesin;
- addrs = addr;
- }
- addre = addr + dc->srcplaylen * chbytesin;
- addr += dc->srcoffset * chbytesin;
-
- srclen = dc->srcplaylen - dc->srcoffset;
- assert (srclen > 0);
- srclendstbytes = srclen * chbytesout;
- if (srclendstbytes > dstlenbytes) {
- srclendstbytes = dstlenbytes;
- srclen = srclendstbytes / chbytesout;
- }
- if (dstlenbytes > srclendstbytes) {
- dstlenbytes = srclendstbytes;
- dstlen = dstlenbytes / chbytesout;
+ alSourceStop (dc->al_source);
+ alClear ();
+ alSourcei (dc->al_source, AL_BUFFER, AL_NONE);
+ alError ("AHI: al_initsample:AL_BUFFER=AL_NONE");
+ dc->samplecounter = 0;
+ preparesample (dsahip, dc);
+ ds = dc->cs.ds;
+ alClear ();
+ alSourceQueueBuffers (dc->al_source, 1, &ds->al_buffer[dc->samplecounter]);
+ alError ("AHI: al_initsample:alSourceQueueBuffers(freq=%d)", dc->cs.frequency);
+ if (dc->dsplaying) {
+ dc->dsplaying = 1;
+ al_startplay (dc);
+ setchannelevent (dsahip, dc);
}
+ dc->samplecounter++;
+}
- waitlen = dstlen;
-
- assert (dstlen > 0);
-
- if (valid_address (addrs, addre - addrs)) {
- uae_u8 *naddr = get_real_address (addr);
- uae_u8 *naddre = get_real_address (addre);
- uae_u8 *naddrs = get_real_address (addrs);
- copysampledata (dsahip, dc, ds, &naddr, naddre, naddrs, dstbuf, dstlen);
- dc->srcoffset = (naddr - naddrs) / chbytesin;
- if (dc->srcoffset == 0) {
- // looping or next sample
- if (dc->nextsrcplaylen < 0) { // stop sample
- int off = dstlenbytes;
- dc->nextsrcplaylen = 0;
- dc->nextds = NULL;
- setchannelevent (dsahip, dc);
- dstlenbytes = dc->mixlength - off - dc->buffercursor;
- dstlen = dstlenbytes / chbytesout;
- memset (dstbuf + off, 0, dstlenbytes);
- goto empty;
- }
- if (dc->nextds) {
- dc->ds = NULL;
- dc->buffercursor += dstlenbytes;
- dc->hsync = 0;
- return;
- }
- setchannelevent (dsahip, dc);
+static void al_queuesample (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ int v, restart;
+ al_setloop (dc, FALSE);
+ if (!dc->csnext.ds)
+ return;
+ restart = 0;
+ if (dc->dsplaying) {
+ alClear ();
+ alGetSourcei (dc->al_source, AL_SOURCE_STATE, &v);
+ alError ("AHI: queuesample AL_SOURCE_STATE");
+ if (v != AL_PLAYING) {
+ alClear ();
+ alSourceRewind (dc->al_source);
+ alError ("AHI: queuesample:restart");
+ restart = 1;
+ if (ahi_debug)
+ write_log ("AHI: queuesample, play restart\n");
}
-
- } else {
- goto cempty;
}
-
- dc->hsync = calcdelay (dc, waitlen);
- dc->buffercursor += dstlenbytes;
- checkvolfreq (dsahip, dc);
- //write_log ("%d ", dstlen / (dsahip->chout * dsahip->bytespersampleout));
- return;
-
-cempty:
- memset (dstbuf, 0, dstlenbytes);
-empty:
- dc->ds = NULL;
- dc->hsync = calcdelay (dc, waitlen);
- dc->buffercursor += dstlenbytes;
- checkvolfreq (dsahip, dc);
+ dc->samplecounter = 0;
+ preparesample (dsahip, dc);
+ alClear ();
+ alSourceQueueBuffers (dc->al_source, 1, &dc->cs.ds->al_buffer[dc->samplecounter]);
+ alError ("AHI: al_queuesample:alSourceQueueBuffers(freq=%d)", dc->cs.frequency);
+ if (dc->dsplaying)
+ dc->dsplaying = 1;
+ if (restart)
+ al_startplay (dc);
+ al_setloop (dc, FALSE);
+ if (ahi_debug)
+ write_log ("AHI: sample %d queued to channel %d\n", dc->cs.ds->num, dc->num);
}
-#endif
-static void incchannel (struct DSAHI *dsahip, struct dschannel *dc, int samplecnt)
+static int unqueuebuffers (struct dschannel *dc)
{
- struct chsample *cs = &dc->cs;
-
- if (cs->ds == NULL)
- return;
- dc->srcoffset += samplecnt;
- while (dc->srcoffset >= cs->srcplaylen) {
- dc->srcoffset -= cs->srcplaylen;
- setchannelevent (dsahip, dc);
- if (dc->csnext.stopit) {
- memset (cs, 0, sizeof (struct chsample));
- memset (&dc->csnext, 0, sizeof (struct chsample));
- dc->srcoffset = 0;
- return;
- }
- if (dc->csnext.ds) {
- memcpy (cs, &dc->csnext, sizeof (struct chsample));
- memset (&dc->csnext, 0, sizeof (struct chsample));
- continue;
- }
+ int v, cnt = 0;
+ for (;;) {
+ ALuint tmp;
+ alClear ();
+ alGetSourcei (dc->al_source, AL_BUFFERS_PROCESSED, &v);
+ if (alError ("AHI: hsync AL_BUFFERS_PROCESSED %d", dc->num))
+ return cnt;
+ if (v == 0)
+ return cnt;
+ alSourceUnqueueBuffers (dc->al_source, 1, &tmp);
+ cnt++;
}
}
return;
flags = get_long (pbase + pub_ChannelSignalAck);
for (i = 0; i < UAE_MAXCHANNELS; i++) {
+ int v, removed;
struct dschannel *dc = &dsahip->channel[i];
- HRESULT hr;
- DWORD playc, writec, diff, samplediff;
-
- if (dc->dsb == NULL)
- continue;
- if (dc->dsplaying == 0)
- continue;
- hr = IDirectSoundBuffer8_GetCurrentPosition (dc->dsb, &playc, &writec);
- if (FAILED (hr)) {
- write_log ("AHI: GetCurrentPosition(%d) failed, %s\n", dc->num, DXError (hr));
- continue;
- }
- if (dc->dscursor >= writec)
- diff = dc->dscursor - writec;
- else
- diff = dsahip->channellength - writec + dc->dscursor;
- if (diff > dsahip->channellength / 2) {
- dc->dscursor = writec + dc->mixlength;
- write_log ("AHI: Resync %d\n", dc->num);
- }
-
- if (dc->dscursor < 0) {
- dc->dscursor = writec;
- memcpy (&dc->cs, &dc->csnext, sizeof (struct chsample));
- }
- samplediff = diff / (dsahip->chout * dsahip->bytespersampleout);
- incchannel (dsahip, dc, samplediff);
-// copysample (dsahip, dc, &dc->cs);
-
-
-
-
- if (diff > dc->mixlength)
+ if (dc->dsplaying != 1 || dc->al_source == -1)
continue;
-
-
-#if 0
- if (dc->buffer == NULL)
- continue;
- if (dc->hsync > 0) {
- dc->hsync--;
- continue;
- }
- if (dc->channelsignal) {
- if (!(flags & (1 << dc->num)))
- continue;
- dc->channelsignal = 0;
- flags &= ~(1 << dc->num);
+ removed = unqueuebuffers (dc);
+ v = 0;
+ alClear ();
+ alGetSourcei (dc->al_source, AL_SOURCE_STATE, &v);
+ alError ("AHI: hsync AL_SOURCE_STATE");
+ if (v != AL_PLAYING) {
+ setchannelevent (dsahip, dc);
+ if (ahi_debug)
+ write_log ("AHI: channel %d stopped state=%d\n", dc->num, v);
+ if (dc->csnext.ds)
+ al_queuesample (dsahip, dc);
+ else
+ dc->dsplaying = 2;
}
- if (dsahip->enabledisable)
- continue;
- if (dc->buffercursor < dc->mixlength)
- copysample (dsahip, dc);
- assert (dc->buffercursor <= dc->mixlength);
- if (dc->buffercursor == dc->mixlength) {
- if (ds_copysample (dsahip, dc)) {
- getmixbufferlen (dsahip, dc);
- dc->buffercursor = 0;
- } else {
- dc->hsync = 100;
- }
+ if (removed) {
+ if (ahi_debug)
+ write_log ("sample end channel %d\n", dc->num);
+ setchannelevent (dsahip, dc);
+ if (dc->csnext.ds)
+ al_queuesample (dsahip, dc);
}
-#endif
}
put_long (pbase + pub_ChannelSignalAck, flags);
}
static void ds_record (struct DSAHI *dsahip, int start)
{
- HRESULT hr;
-
- if (dsahip->dscb == NULL)
- return;
- if (dsahip->dsrecording && start)
- return;
- dsahip->dsrecording = 0;
- if (start) {
- hr = IDirectSoundCaptureBuffer_Start (dsahip->dscb, DSCBSTART_LOOPING);
- if (FAILED (hr)) {
- write_log ("AHI: DirectSoundCaptureBuffer_Start failed: %s\n", DXError (hr));
- return;
- }
- dsahip->dsrecording = 1;
- } else {
- hr = IDirectSoundCaptureBuffer_Stop (dsahip->dscb);
- if (FAILED (hr)) {
- write_log ("AHI: DirectSoundCaptureBuffer_Stop failed: %s\n", DXError (hr));
- return;
- }
- }
}
static void ds_stop (struct DSAHI *dsahip, struct dschannel *dc)
{
- HRESULT hr;
-
dc->dsplaying = 0;
- if (dc->dsb == NULL)
+ if (dc->al_source == -1)
return;
if (ahi_debug)
write_log ("AHI: ds_stop(%d)\n", dc->num);
- hr = IDirectSoundBuffer8_Stop (dc->dsb);
- if (FAILED (hr))
- write_log ("AHI: IDirectSoundBuffer8_Stop() failed, %s\n", DXError (hr));
+ alClear ();
+ alSourceStop (dc->al_source);
+ alError ("AHI: alSourceStop");
+ unqueuebuffers (dc);
}
static void ds_play (struct DSAHI *dsahip, struct dschannel *dc)
{
- HRESULT hr;
- DWORD status, playc, writec;
-
- if (dc->dsb == NULL)
- return;
- if (dc->dsplaying)
+ if (dc->dsplaying) {
+ dc->dsplaying = 1;
return;
+ }
+ dc->dsplaying = 1;
if (dc->cs.frequency == 0)
return;
- dc->dsplaying = 1;
+ if (dc->al_source == -1)
+ return;
if (ahi_debug)
write_log ("AHI: ds_play(%d)\n", dc->num);
- hr = IDirectSoundBuffer8_GetStatus (dc->dsb, &status);
- if (FAILED (hr))
- write_log ("AHI: ds_play() IDirectSoundBuffer8_GetStatus() failed, %s\n", DXError (hr));
- hr = IDirectSoundBuffer8_Play (dc->dsb, 0, 0, DSBPLAY_LOOPING);
- if (FAILED (hr))
- write_log ("AHI: ds_play() IDirectSoundBuffer8_Play() failed, %s\n", DXError (hr));
- hr = IDirectSoundBuffer8_GetCurrentPosition (dc->dsb, &playc, &writec);
- if (FAILED (hr))
- write_log ("AHI: ds_play() IDirectSoundBuffer8_GetCurrentPosition() failed, %s\n", DXError (hr));
- dc->dscursor = writec + dc->mixlength;
- if (dc->dscursor >= dsahip->channellength)
- dc->dscursor -= dsahip->channellength;
- if (ahi_debug)
- write_log("AHI: ds_play(%d) Start=%d->%d\n", dc->num, writec, dc->dscursor);
+ al_startplay (dc);
}
void ahi2_pause_sound (int paused)
return;
for (i = 0; i < UAE_MAXCHANNELS; i++) {
struct dschannel *dc = &dsahip->channel[i];
- if (dc->dsb == NULL)
+ if (dc->al_source == -1)
continue;
if (paused) {
ds_stop (dsahip, dc);
} else {
ds_play (dsahip, dc);
+ setchannelevent (dsahip, dc);
}
}
}
static uae_u32 init (TrapContext *ctx)
{
- int i;
+ int i, j;
enumerate_sound_devices ();
xahi_author = ds ("Toni Wilen");
xahi_copyright = ds ("GPL");
- xahi_version = ds ("uae2 0.1 (xx.xx.2008)\r\n");
- for (i = 0; sound_devices[i].name; i++)
- xahi_output[i] = ds (sound_devices[i].name);
- xahi_output_num = i;
- for (i = 0; record_devices[i].name; i++)
- xahi_input[i] = ds (record_devices[i].name);
- xahi_input_num = i;
+ xahi_version = ds ("uae2 0.2 (xx.xx.2008)\r\n");
+ j = 0;
+ for (i = 0; sound_devices[i].name; i++) {
+ if (sound_devices[i].type == SOUND_DEVICE_AL)
+ xahi_output[j++] = ds (sound_devices[i].name);
+ }
+ xahi_output_num = j;
+ j = 0;
+ for (i = 0; record_devices[i].name; i++) {
+ if (record_devices[i].type == SOUND_DEVICE_AL)
+ xahi_input[j++] = ds (record_devices[i].name);
+ }
+ xahi_input_num = j;
return 1;
}
if (!ds_init (dsahip))
return AHISF_ERROR;
+ dsahip->maxplaysamples = PLAYSAMPLES;
dsahip->sounds = UAE_MAXSOUNDS;
dsahip->channels = UAE_MAXCHANNELS;
for (i = 0; i < dsahip->channels; i++) {
struct dschannel *dc = &dsahip->channel[i];
dc->num = i;
+ dc->al_source = -1;
}
for (i = 0; i < dsahip->sounds; i++) {
struct dssample *ds = &dsahip->sample[i];
ds->num = -1;
+ ds->al_buffer[0] = -1;
+ ds->al_buffer[1] = -1;
}
ahi_active = 1;
return ret;
static uae_u32 frequencies[] = { 48000, 44100 };
#define MAX_FREQUENCIES (sizeof (frequencies) / sizeof (uae_u32))
-static uae_u32 getattr2 (uae_u32 attribute, uae_u32 argument, uae_u32 def)
+static uae_u32 getattr2 (struct DSAHI *dsahip, uae_u32 attribute, uae_u32 argument, uae_u32 def)
{
int i;
return -1;
case AHIDB_MaxRecordSamples:
return RECORDSAMPLES;
+ case AHIDB_MaxPlaySamples:
+ if (def < dsahip->maxplaysamples)
+ def = dsahip->maxplaysamples;
+ return def;
default:
return def;
}
uae_u32 def = m68k_dreg (&ctx->regs, 2);
uae_u32 taglist = m68k_areg (&ctx->regs, 1);
uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ struct DSAHI *dsahip = GETAHI;
uae_u32 v;
- v = getattr2 (attribute, argument, def);
+ v = getattr2 (dsahip, attribute, argument, def);
if (ahi_debug)
write_log ("AHI: GetAttr(%08x=%d,%08x,%08x)=%08x\n", attribute, attribute & 0x7fff, argument, def, v);
case AHIC_Input:
if (dsahip->input != argument) {
dsahip->input = argument;
- if (dsahip->dscb) {
+ if (dsahip->al_dev) {
ds_free_record (dsahip);
ds_init_record (dsahip);
if (dsahip->recording)
case AHIC_Output:
if (dsahip->output != argument) {
dsahip->output = argument;
- if (dsahip->DS)
+ if (dsahip->al_dev)
ds_reinit (dsahip);
}
break;
channel, sound, offset, length, audioctrl, flags);
if (dc == NULL)
return AHIE_UNKNOWN;
- if (ds->num < 0)
- return AHIE_UNKNOWN;
if (sound == 0xffff) {
if (flags & AHISF_IMM) {
dc->cs.ds = NULL;
dc->csnext.ds = NULL;
}
- dc->csnext.srcplaylen = -1;
return 0;
}
+ if (ds == NULL || ds->num < 0)
+ return AHIE_UNKNOWN;
ds_allocchannel (dsahip, dc);
dc->cs.backwards = length < 0;
length = abs (length);
dc->csnext.srcplayoffset = offset;
if (flags & AHISF_IMM)
dc->cs.ds = NULL;
- if (dc->cs.ds == NULL) {
- dc->buffercursor = 0;
- dc->hsync = 0;
- }
ds_setfreq (dsahip, dc);
ds_setvolume (dsahip, dc);
- ds_play (dsahip, dc);
+ if (dc->cs.ds == NULL)
+ al_initsample (dsahip, dc);
+ else
+ al_queuesample (dsahip, dc);
return 0;
}
ds->bitspersample = bps;
ds->ch = ch;
ds->bytespersample = bps / 8;
+ if (ds->al_buffer[0] == -1) {
+ alClear ();
+ alGenBuffers (2, ds->al_buffer);
+ if (alError ("AHI: alGenBuffers"))
+ return AHIE_NOMEM;
+ if (ahi_debug)
+ write_log ("AHI:LoadSound:allocated OpenAL buffer\n");
+ }
return AHIE_OK;
}
{
uaecptr a = here ();
org (rtarea_base + 0xFFC8);
- calltrap (deftrapres (ahi_demux, 0, "ahi_winuae_v2"));
+ calltrap (deftrapres (ahi_demux, 0, "ahi_v2"));
dw (RTS);
org (a);
}
--- /dev/null
+/*
+ * UAE - The Un*x Amiga Emulator
+ *
+ * DirectSound AHI 7.1 wrapper
+ *
+ * Copyright 2008 Toni Wilen
+ */
+
+#include "sysconfig.h"
+
+#if defined(AHI)
+
+#include <ctype.h>
+#include <assert.h>
+
+#include <windows.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <math.h>
+#include <process.h>
+
+#include "sysdeps.h"
+#include "options.h"
+#include "audio.h"
+#include "memory.h"
+#include "events.h"
+#include "custom.h"
+#include "newcpu.h"
+#include "autoconf.h"
+#include "traps.h"
+#include "threaddep/thread.h"
+#include "native2amiga.h"
+#include "od-win32/win32.h"
+#include "sounddep/sound.h"
+#include "ahidsound_new.h"
+#include "dxwrap.h"
+
+#include <mmsystem.h>
+#include <mmreg.h>
+#include <dsound.h>
+#include <ks.h>
+#include <ksmedia.h>
+
+#define AHI_STRUCT_VERSION 1
+
+static int ahi_debug = 1;
+
+#define UAE_MAXCHANNELS 24
+#define UAE_MAXSOUNDS 256
+#define RECORDSAMPLES 2048
+
+#define ub_Flags 34
+#define ub_Pad1 (ub_Flags + 1)
+#define ub_Pad2 (ub_Pad1 + 1)
+#define ub_SysLib (ub_Pad2 + 2)
+#define ub_SegList (ub_SysLib + 4)
+#define ub_DOSBase (ub_SegList + 4)
+#define ub_AHIFunc (ub_DOSBase + 4)
+
+#define pub_SizeOf 0
+#define pub_Version (pub_SizeOf + 4)
+#define pub_Index (pub_Version + 4)
+#define pub_Base (pub_Index + 4)
+#define pub_audioctrl (pub_Base + 4)
+#define pub_FuncTask (pub_audioctrl + 4)
+#define pub_WaitMask (pub_FuncTask + 4)
+#define pub_WaitSigBit (pub_WaitMask + 4)
+#define pub_FuncMode (pub_WaitSigBit +4)
+#define pub_TaskMode (pub_FuncMode + 2)
+#define pub_ChannelSignal (pub_TaskMode + 2)
+#define pub_ChannelSignalAck (pub_ChannelSignal + 4)
+#define pub_ahism_Channel (pub_ChannelSignalAck + 4)
+#define pub_RecordHookDone (pub_ahism_Channel + 2)
+#define pub_RecordSampleType (pub_RecordHookDone + 2)
+#define pub_RecordBufferSize (pub_RecordSampleType + 4)
+#define pub_RecordBufferSizeBytes (pub_RecordBufferSize + 4)
+#define pub_RecordBuffer (pub_RecordBufferSizeBytes + 4)
+#define pub_ChannelInfo (pub_RecordBuffer + 4 + 4 + 4 + 4)
+#define pub_End (pub_ChannelInfo + 4)
+
+#define FUNCMODE_PLAY 1
+#define FUNCMODE_RECORD 2
+#define FUNCMODE_RECORDALLOC 4
+
+#define ahie_Effect 0
+#define ahieci_Func 4
+#define ahieci_Channels 8
+#define ahieci_Pad 10
+#define ahieci_Offset 12
+
+#if 0
+struct AHISampleInfo
+{
+ ULONG ahisi_Type; /* Format of samples */
+ APTR ahisi_Address; /* Address to array of samples */
+ ULONG ahisi_Length; /* Number of samples in array */
+};
+#endif
+
+#define ahisi_Type 0
+#define ahisi_Address 4
+#define ahisi_Length 8
+
+#if 0
+struct AHIAudioCtrlDrv
+{
+ struct AHIAudioCtrl ahiac_AudioCtrl;
+ ULONG ahiac_Flags; /* See below for definition */
+ struct Hook *ahiac_SoundFunc; /* AHIA_SoundFunc */
+ struct Hook *ahiac_PlayerFunc; /* AHIA_PlayerFunc */
+ Fixed ahiac_PlayerFreq; /* AHIA_PlayerFreq */
+ Fixed ahiac_MinPlayerFreq; /* AHIA_MinPlayerFreq */
+ Fixed ahiac_MaxPlayerFreq; /* AHIA_MaxPlayerFreq */
+ ULONG ahiac_MixFreq; /* AHIA_MixFreq */
+ UWORD ahiac_Channels; /* AHIA_Channels */
+ UWORD ahiac_Sounds; /* AHIA_Sounds */
+
+ APTR ahiac_DriverData; /* Unused. Store whatever you want here. */
+
+ struct Hook *ahiac_MixerFunc; /* Mixing routine Hook */
+ struct Hook *ahiac_SamplerFunc; /* Sampler routine Hook */
+ ULONG ahiac_Obsolete;
+ ULONG ahiac_BuffSamples; /* Samples to mix this pass. */
+ ULONG ahiac_MinBuffSamples; /* Min. samples to mix each pass. */
+ ULONG ahiac_MaxBuffSamples; /* Max. samples to mix each pass. */
+ ULONG ahiac_BuffSize; /* Buffer size ahiac_MixerFunc needs. */
+ ULONG ahiac_BuffType; /* Buffer format (V2) */
+ BOOL (*ahiac_PreTimer)(void); /* Call before mixing (V4) */
+ void (*ahiac_PostTimer)(void); /* Call after mixing (V4) */
+ ULONG ahiac_AntiClickSamples; /* AntiClick samples (V6) */
+ struct Hook *ahiac_PreTimerFunc; /* A Hook wrapper for ahiac_PreTimer (V6) */
+ struct Hook *ahiac_PostTimerFunc; /* A Hook wrapper for ahiac_PostTimer (V6) */
+#endif
+
+#define ahiac_AudioCtrl 0
+#define ahiac_Flags ahiac_AudioCtrl + 4
+#define ahiac_SoundFunc ahiac_Flags + 4
+#define ahiac_PlayerFunc ahiac_SoundFunc + 4
+#define ahiac_PlayerFreq ahiac_PlayerFunc + 4
+#define ahiac_MinPlayerFreq ahiac_PlayerFreq + 4
+#define ahiac_MaxPlayerFreq ahiac_MinPlayerFreq + 4
+#define ahiac_MixFreq ahiac_MaxPlayerFreq + 4
+#define ahiac_Channels ahiac_MixFreq + 4
+#define ahiac_Sounds ahiac_Channels + 2
+#define ahiac_DriverData ahiac_Sounds + 2
+#define ahiac_MixerFunc ahiac_DriverData + 4
+#define ahiac_SamplerFunc ahiac_MixerFunc + 4
+#define ahiac_Obsolete ahiac_SamplerFunc + 4
+#define ahiac_BuffSamples ahiac_Obsolete + 4
+#define ahiac_MinBuffSamples ahiac_BuffSamples + 4
+#define ahiac_MaxBuffSamples ahiac_MinBuffSamples + 4
+#define ahiac_BuffSize ahiac_MaxBuffSamples + 4
+#define ahiac_BuffType ahiac_BuffSize + 4
+#define ahiac_PreTimer ahiac_BuffType + 4
+#define ahiac_PostTimer ahiac_PreTimer + 4
+#define ahiac_AntiClickSamples ahiac_PostTimer + 4
+#define ahiac_PreTimerFunc ahiac_AntiClickSamples + 4
+#define ahiac_PostTimerFunc ahiac_PreTimerFunc + 4
+
+/* AHIsub_AllocAudio return flags */
+#define AHISF_ERROR (1<<0)
+#define AHISF_MIXING (1<<1)
+#define AHISF_TIMING (1<<2)
+#define AHISF_KNOWSTEREO (1<<3)
+#define AHISF_KNOWHIFI (1<<4)
+#define AHISF_CANRECORD (1<<5)
+#define AHISF_CANPOSTPROCESS (1<<6)
+#define AHISF_KNOWMULTICHANNEL (1<<7)
+
+#define AHISB_ERROR (0)
+#define AHISB_MIXING (1)
+#define AHISB_TIMING (2)
+#define AHISB_KNOWSTEREO (3)
+#define AHISB_KNOWHIFI (4)
+#define AHISB_CANRECORD (5)
+#define AHISB_CANPOSTPROCESS (6)
+#define AHISB_KNOWMULTICHANNEL (7)
+
+ /* AHIsub_Start() and AHIsub_Stop() flags */
+#define AHISF_PLAY (1<<0)
+#define AHISF_RECORD (1<<1)
+
+#define AHISB_PLAY (0)
+#define AHISB_RECORD (1)
+
+ /* ahiac_Flags */
+#define AHIACF_VOL (1<<0)
+#define AHIACF_PAN (1<<1)
+#define AHIACF_STEREO (1<<2)
+#define AHIACF_HIFI (1<<3)
+#define AHIACF_PINGPONG (1<<4)
+#define AHIACF_RECORD (1<<5)
+#define AHIACF_MULTTAB (1<<6)
+#define AHIACF_MULTICHANNEL (1<<7)
+
+#define AHIACB_VOL (0)
+#define AHIACB_PAN (1)
+#define AHIACB_STEREO (2)
+#define AHIACB_HIFI (3)
+#define AHIACB_PINGPONG (4)
+#define AHIACB_RECORD (5)
+#define AHIACB_MULTTAB (6)
+#define AHIACB_MULTICHANNEL (7)
+
+#define AHISB_IMM 0
+#define AHISB_NODELAY 1
+#define AHISF_IMM (1 << AHISB_IMM)
+#define AHISF_NODELAY (1 << SHISB_NODELAY)
+
+#define AHIET_CANCEL (1 << 31)
+#define AHIET_MASTERVOLUME 1
+#define AHIET_OUTPUTBUFFER 2
+#define AHIET_DSPMASK 3
+#define AHIET_DSPECHO 4
+#define AHIET_CHANNELINFO 5
+
+#define AHI_TagBase (0x80000000)
+#define AHI_TagBaseR (AHI_TagBase|0x8000)
+
+ /* AHI_ControlAudioA tags */
+#define AHIC_Play (AHI_TagBase+80) /* Boolean */
+#define AHIC_Record (AHI_TagBase+81) /* Boolean */
+#define AHIC_MonitorVolume (AHI_TagBase+82)
+#define AHIC_MonitorVolume_Query (AHI_TagBase+83) /* ti_Data is pointer to Fixed (LONG) */
+#define AHIC_MixFreq_Query (AHI_TagBase+84) /* ti_Data is pointer to ULONG */
+/* --- New for V2, they will be ignored by V1 --- */
+#define AHIC_InputGain (AHI_TagBase+85)
+#define AHIC_InputGain_Query (AHI_TagBase+86) /* ti_Data is pointer to Fixed (LONG) */
+#define AHIC_OutputVolume (AHI_TagBase+87)
+#define AHIC_OutputVolume_Query (AHI_TagBase+88) /* ti_Data is pointer to Fixed (LONG) */
+#define AHIC_Input (AHI_TagBase+89)
+#define AHIC_Input_Query (AHI_TagBase+90) /* ti_Data is pointer to ULONG */
+#define AHIC_Output (AHI_TagBase+91)
+#define AHIC_Output_Query (AHI_TagBase+92) /* ti_Data is pointer to ULONG */
+
+ /* AHI_GetAudioAttrsA tags */
+#define AHIDB_AudioID (AHI_TagBase+100)
+#define AHIDB_Driver (AHI_TagBaseR+101) /* Pointer to name of driver */
+#define AHIDB_Flags (AHI_TagBase+102) /* Private! */
+#define AHIDB_Volume (AHI_TagBase+103) /* Boolean */
+#define AHIDB_Panning (AHI_TagBase+104) /* Boolean */
+#define AHIDB_Stereo (AHI_TagBase+105) /* Boolean */
+#define AHIDB_HiFi (AHI_TagBase+106) /* Boolean */
+#define AHIDB_PingPong (AHI_TagBase+107) /* Boolean */
+#define AHIDB_MultTable (AHI_TagBase+108) /* Private! */
+#define AHIDB_Name (AHI_TagBaseR+109) /* Pointer to name of this mode */
+#define AHIDB_Bits (AHI_TagBase+110) /* Output bits */
+#define AHIDB_MaxChannels (AHI_TagBase+111) /* Max supported channels */
+#define AHIDB_MinMixFreq (AHI_TagBase+112) /* Min mixing freq. supported */
+#define AHIDB_MaxMixFreq (AHI_TagBase+113) /* Max mixing freq. supported */
+#define AHIDB_Record (AHI_TagBase+114) /* Boolean */
+#define AHIDB_Frequencies (AHI_TagBase+115)
+#define AHIDB_FrequencyArg (AHI_TagBase+116) /* ti_Data is frequency index */
+#define AHIDB_Frequency (AHI_TagBase+117)
+#define AHIDB_Author (AHI_TagBase+118) /* Pointer to driver author name */
+#define AHIDB_Copyright (AHI_TagBase+119) /* Pointer to driver copyright notice */
+#define AHIDB_Version (AHI_TagBase+120) /* Pointer to driver version string */
+#define AHIDB_Annotation (AHI_TagBase+121) /* Pointer to driver annotation text */
+#define AHIDB_BufferLen (AHI_TagBase+122) /* Specifies the string buffer size */
+#define AHIDB_IndexArg (AHI_TagBase+123) /* ti_Data is frequency! */
+#define AHIDB_Index (AHI_TagBase+124)
+#define AHIDB_Realtime (AHI_TagBase+125) /* Boolean */
+#define AHIDB_MaxPlaySamples (AHI_TagBase+126) /* It's sample *frames* */
+#define AHIDB_MaxRecordSamples (AHI_TagBase+127) /* It's sample *frames* */
+#define AHIDB_FullDuplex (AHI_TagBase+129) /* Boolean */
+/* --- New for V2, they will be ignored by V1 --- */
+#define AHIDB_MinMonitorVolume (AHI_TagBase+130)
+#define AHIDB_MaxMonitorVolume (AHI_TagBase+131)
+#define AHIDB_MinInputGain (AHI_TagBase+132)
+#define AHIDB_MaxInputGain (AHI_TagBase+133)
+#define AHIDB_MinOutputVolume (AHI_TagBase+134)
+#define AHIDB_MaxOutputVolume (AHI_TagBase+135)
+#define AHIDB_Inputs (AHI_TagBase+136)
+#define AHIDB_InputArg (AHI_TagBase+137) /* ti_Data is input index */
+#define AHIDB_Input (AHI_TagBase+138)
+#define AHIDB_Outputs (AHI_TagBase+139)
+#define AHIDB_OutputArg (AHI_TagBase+140) /* ti_Data is input index */
+#define AHIDB_Output (AHI_TagBase+141)
+/* --- New for V4, they will be ignored by V2 and earlier --- */
+#define AHIDB_Data (AHI_TagBaseR+142) /* Private! */
+#define AHIDB_DriverBaseName (AHI_TagBaseR+143) /* Private! */
+/* --- New for V6, they will be ignored by V4 and earlier --- */
+#define AHIDB_MultiChannel (AHI_TagBase+144) /* Boolean */
+
+/* Sound Types */
+#define AHIST_NOTYPE (~0UL) /* Private */
+#define AHIST_SAMPLE (0UL) /* 8 or 16 bit sample */
+#define AHIST_DYNAMICSAMPLE (1UL) /* Dynamic sample */
+#define AHIST_INPUT (1UL<<29) /* The input from your sampler */
+#define AHIST_BW (1UL<<30) /* Private */
+
+ /* Sample types */
+/* Note that only AHIST_M8S, AHIST_S8S, AHIST_M16S and AHIST_S16S
+ (plus AHIST_M32S, AHIST_S32S and AHIST_L7_1 in V6)
+ are supported by AHI_LoadSound(). */
+#define AHIST_M8S (0UL) /* Mono, 8 bit signed (BYTE) */
+#define AHIST_M16S (1UL) /* Mono, 16 bit signed (WORD) */
+#define AHIST_S8S (2UL) /* Stereo, 8 bit signed (2×BYTE) */
+#define AHIST_S16S (3UL) /* Stereo, 16 bit signed (2×WORD) */
+#define AHIST_M32S (8UL) /* Mono, 32 bit signed (LONG) */
+#define AHIST_S32S (10UL) /* Stereo, 32 bit signed (2×LONG) */
+#define AHIST_M8U (4UL) /* OBSOLETE! */
+#define AHIST_L7_1 (0x00c3000aUL) /* 7.1, 32 bit signed (8×LONG) */
+
+ /* Error codes */
+#define AHIE_OK (0UL) /* No error */
+#define AHIE_NOMEM (1UL) /* Out of memory */
+#define AHIE_BADSOUNDTYPE (2UL) /* Unknown sound type */
+#define AHIE_BADSAMPLETYPE (3UL) /* Unknown/unsupported sample type */
+#define AHIE_ABORTED (4UL) /* User-triggered abortion */
+#define AHIE_UNKNOWN (5UL) /* Error, but unknown */
+#define AHIE_HALFDUPLEX (6UL) /* CMD_WRITE/CMD_READ failure */
+
+struct dssample {
+ int num;
+ int ch;
+ int bitspersample;
+ int bytespersample;
+ uae_u32 addr;
+ uae_u32 len;
+ uae_u32 type;
+ uae_u32 sampletype;
+ uae_u32 offset;
+};
+
+struct chsample {
+ int frequency;
+ int volume;
+ int panning;
+ int backwards;
+ struct dssample *ds;
+ int srcplayoffset;
+ int srcplaylen;
+ int stopit;
+};
+
+struct dschannel {
+ int num;
+ struct chsample cs;
+ struct chsample csnext;
+ LPDIRECTSOUNDBUFFER8 dsb;
+
+ uae_u8 *buffer;
+ int mixlength;
+ int buffercursor;
+ int hsync;
+ int channelsignal;
+ int srcoffset;
+
+ int dsplaying;
+ int dscursor;
+};
+
+struct DSAHI {
+ uae_u32 audioctrl;
+ int chout;
+ int bits24;
+ int bitspersampleout;
+ int bytespersampleout;
+ int channellength;
+ int mixlength;
+ int input;
+ int output;
+ int channels;
+ int sounds;
+ int playerfreq;
+ int enabledisable;
+ struct dssample *sample;
+ struct dschannel *channel;
+ int playing, recording;
+ evt evttime;
+ uae_u32 signalchannelmask;
+ LPDIRECTSOUND8 DS;
+
+ LPDIRECTSOUNDCAPTURE DSC;
+ LPDIRECTSOUNDCAPTUREBUFFER dscb;
+ int dsrecording;
+ int recordingcursor;
+ int record_ch;
+ int record_bytespersample;
+ int channellength_record;
+ int mixlength_record;
+ int record_wait;
+};
+
+static struct DSAHI dsahi[1];
+
+#define GETAHI (&dsahi[get_long(get_long(audioctrl + ahiac_DriverData) + pub_Index)])
+#define GETSAMPLE (dsahip && sound >= 0 && sound < UAE_MAXSOUNDS ? &dsahip->sample[sound] : NULL)
+#define GETCHANNEL (dsahip && channel >= 0 && channel < UAE_MAXCHANNELS ? &dsahip->channel[channel] : NULL)
+
+static int default_freq = 44100;
+static int cansurround;
+static uae_u32 xahi_author, xahi_copyright, xahi_version;
+static uae_u32 xahi_output[MAX_SOUND_DEVICES], xahi_output_num;
+static uae_u32 xahi_input[MAX_SOUND_DEVICES], xahi_input_num;
+static int ahi_paused;
+static int ahi_active;
+
+#define TAG_DONE (0L) /* terminates array of TagItems. ti_Data unused */
+#define TAG_IGNORE (1L) /* ignore this item, not end of array */
+#define TAG_MORE (2L) /* ti_Data is pointer to another array of TagItems */
+#define TAG_SKIP (3L) /* skip this and the next ti_Data items */
+#define TAG_USER ((uae_u32)(1L << 31))
+
+static uae_u32 gettag (uae_u32 *tagpp, uae_u32 *datap)
+{
+ uae_u32 tagp = *tagpp;
+ for (;;) {
+ uae_u32 tag = get_long (tagp);
+ uae_u32 data = get_long (tagp + 4);
+ switch (tag)
+ {
+ case TAG_DONE:
+ return 0;
+ case TAG_IGNORE:
+ tagp += 8;
+ break;
+ case TAG_MORE:
+ tagp = data;
+ break;
+ case TAG_SKIP:
+ tagp += data * 8;
+ break;
+ default:
+ tagp += 8;
+ *tagpp = tagp;
+ *datap = data;
+ return tag;
+ }
+ }
+}
+
+
+static int sendsignal (struct DSAHI *dsahip)
+{
+ uae_u32 audioctrl = dsahip->audioctrl;
+ uae_u32 puaebase = get_long (audioctrl + ahiac_DriverData);
+ uae_u32 channelinfo;
+ uae_u32 task, signalmask;
+ uae_s16 taskmode = get_word (puaebase + pub_TaskMode);
+ uae_s16 funcmode = get_word (puaebase + pub_FuncMode);
+ task = get_long (puaebase + pub_FuncTask);
+ signalmask = get_long (puaebase + pub_WaitMask);
+
+ if ((!dsahip->playing && !dsahip->recording) || ahi_paused)
+ return 0;
+ if (taskmode <= 0)
+ return 0;
+ if (dsahip->enabledisable) {
+ // allocate Amiga-side recordingbuffer
+ funcmode &= FUNCMODE_RECORDALLOC;
+ put_word (puaebase + pub_FuncMode, funcmode);
+ }
+
+ channelinfo = get_long (puaebase + pub_ChannelInfo);
+ if (channelinfo) {
+ int i, ch;
+ ch = get_word (channelinfo + ahieci_Channels);
+ if (ch > UAE_MAXCHANNELS)
+ ch = UAE_MAXCHANNELS;
+ for (i = 0; i < ch; i++)
+ put_long (channelinfo + ahieci_Offset + i * 4, dsahip->channel[i].srcoffset);
+ }
+
+ uae_Signal (task, signalmask);
+ return 1;
+}
+
+static void setchannelevent (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ uae_u32 audioctrl = dsahip->audioctrl;
+ uae_u32 puaebase = get_long (audioctrl + ahiac_DriverData);
+ int ch = dc - &dsahip->channel[0];
+ uae_u32 mask;
+
+ if (!dsahip->playing || ahi_paused || dc->dsb == NULL)
+ return;
+ mask = get_long (puaebase + pub_ChannelSignal);
+ if (mask & (1 << ch))
+ return;
+ dc->channelsignal = 1;
+ put_long (puaebase + pub_ChannelSignal, mask | (1 << ch));
+ sendsignal (dsahip);
+}
+
+static void evtfunc (uae_u32 v)
+{
+ if (ahi_active) {
+ struct DSAHI *dsahip = &dsahi[v];
+ uae_u32 audioctrl = dsahip->audioctrl;
+ uae_u32 puaebase = get_long (audioctrl + ahiac_DriverData);
+
+ put_word (puaebase + pub_FuncMode, get_word (puaebase + pub_FuncMode) | FUNCMODE_PLAY);
+ if (sendsignal (dsahip)) {
+ event2_newevent2 (dsahip->evttime, v, evtfunc);
+ } else {
+ dsahip->evttime = 0;
+ }
+ }
+}
+
+static void setevent (struct DSAHI *dsahip)
+{
+ uae_u32 audioctrl = dsahip->audioctrl;
+ uae_u32 freq = get_long (audioctrl + ahiac_PlayerFreq);
+ double f;
+ uae_u32 cycles;
+ evt t;
+
+ f = ((double)(freq >> 16)) + ((double)(freq & 0xffff)) / 65536.0;
+ if (f < 1)
+ return;
+ cycles = maxhpos * maxvpos * vblank_hz;
+ t = (evt)(cycles / f);
+ if (dsahip->evttime == t)
+ return;
+ write_log ("AHI: playerfunc freq = %.2fHz\n", f);
+ dsahip->evttime = t;
+ if (t < 10)
+ return;
+ event2_newevent2 (t, dsahip - &dsahi[0], evtfunc);
+}
+
+
+
+const static GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001,0x0000,0x0010,
+ {0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71}};
+
+static void ds_freechannel (struct DSAHI *ahidsp, struct dschannel *dc)
+{
+ if (!dc)
+ return;
+ if (dc->dsb)
+ IDirectSoundBuffer8_Release (dc->dsb);
+ xfree (dc->buffer);
+ memset (dc, 0, sizeof (struct dschannel));
+}
+
+static void ds_free (struct DSAHI *dsahip)
+{
+ int i;
+
+ for (i = 0; i < dsahip->channels; i++) {
+ struct dschannel *dc = &dsahip->channel[i];
+ ds_freechannel (dsahip, dc);
+ }
+ if (dsahip->DS)
+ IDirectSound_Release (dsahip->DS);
+ dsahip->DS = NULL;
+ if (ahi_debug && ahi_active)
+ write_log ("AHI: DSOUND freed\n");
+ ahi_active = 0;
+}
+
+DWORD fillsupportedmodes (LPDIRECTSOUND8 lpDS, int freq, struct dsaudiomodes *dsam);
+static struct dsaudiomodes supportedmodes[16];
+
+static void ds_free_record (struct DSAHI *dsahip)
+{
+ if (dsahip->dscb)
+ IDirectSoundCaptureBuffer_Release (dsahip->dscb);
+ if (dsahip->DSC)
+ IDirectSoundCapture_Release (dsahip->DSC);
+ dsahip->dscb = NULL;
+ dsahip->DSC = NULL;
+}
+
+static int ds_init_record (struct DSAHI *dsahip)
+{
+ HRESULT hr;
+ WAVEFORMATEXTENSIBLE wavfmt;
+ DSCBUFFERDESC dbd;
+ uae_u32 pbase = get_long (dsahip->audioctrl + ahiac_DriverData);
+ int freq = get_long (dsahip->audioctrl + ahiac_MixFreq);
+
+ if (dsahip->DSC)
+ return 1;
+ if (!freq)
+ return 0;
+ dsahip->mixlength_record = RECORDSAMPLES; // in sample units, not bytes
+ dsahip->record_ch = 2;
+ dsahip->record_bytespersample = 2;
+ dsahip->channellength_record = freq * dsahip->record_bytespersample * dsahip->record_ch * 10;
+ put_long (pbase + pub_RecordBufferSize, dsahip->mixlength_record);
+ put_long (pbase + pub_RecordBufferSizeBytes, dsahip->mixlength_record * dsahip->record_ch * dsahip->record_bytespersample);
+ put_long (pbase + pub_RecordSampleType, AHIST_S16S);
+ put_word (pbase + pub_RecordHookDone, 0);
+
+ hr = DirectSoundCaptureCreate (&record_devices[dsahip->input].guid, &dsahip->DSC, NULL);
+ if (FAILED (hr)) {
+ write_log ("AHI: DirectSoundCaptureCreate() failure %dHz: %s\n", freq, DXError (hr));
+ goto end;
+ }
+ memset (&dbd, 0, sizeof dbd);
+ dbd.dwSize = sizeof dbd;
+ dbd.dwBufferBytes = dsahip->channellength_record;
+ dbd.lpwfxFormat = &wavfmt.Format;
+ dbd.dwFlags = 0 ;
+ memset (&wavfmt, 0, sizeof wavfmt);
+ wavfmt.Format.nChannels = dsahip->record_ch;
+ wavfmt.Format.nSamplesPerSec = freq;
+ wavfmt.Format.wBitsPerSample = dsahip->record_bytespersample * 8;
+ wavfmt.Format.wFormatTag = WAVE_FORMAT_PCM;
+ wavfmt.Format.nBlockAlign = wavfmt.Format.wBitsPerSample / 8 * wavfmt.Format.nChannels;
+ wavfmt.Format.nAvgBytesPerSec = wavfmt.Format.nBlockAlign * wavfmt.Format.nSamplesPerSec;
+ hr = IDirectSoundCapture_CreateCaptureBuffer (dsahip->DSC, &dbd, &dsahip->dscb, NULL);
+ if (FAILED (hr)) {
+ write_log ("AHI: CreateCaptureSoundBuffer() failure: %s\n", DXError(hr));
+ goto end;
+ }
+ if (ahi_debug)
+ write_log ("AHI: DSOUND Recording initialized. %dHz, %s\n", freq, record_devices[dsahip->input].name);
+
+ put_word (pbase + pub_FuncMode, get_word (pbase + pub_FuncMode) | FUNCMODE_RECORDALLOC);
+ sendsignal (dsahip);
+ return 1;
+end:
+ ds_free_record (dsahip);
+ return 0;
+}
+
+static int ds_init (struct DSAHI *dsahip)
+{
+ int freq = 44100;
+ DSCAPS DSCaps;
+ HRESULT hr;
+ DWORD speakerconfig;
+
+ hr = DirectSoundCreate8 (&sound_devices[dsahip->output].guid, &dsahip->DS, NULL);
+ if (FAILED (hr)) {
+ write_log ("AHI: DirectSoundCreate8() failure: %s\n", DXError (hr));
+ return 0;
+ }
+
+ hr = IDirectSound_SetCooperativeLevel (dsahip->DS, hMainWnd, DSSCL_PRIORITY);
+ if (FAILED (hr)) {
+ write_log ("AHI: Can't set cooperativelevel: %s\n", DXError (hr));
+ goto error;
+ }
+
+ fillsupportedmodes (dsahip->DS, default_freq, supportedmodes);
+ dsahip->chout = 2;
+ if (SUCCEEDED (IDirectSound8_GetSpeakerConfig (dsahip->DS, &speakerconfig))) {
+ if (speakerconfig >= DSSPEAKER_CONFIG (DSSPEAKER_5POINT1)) {
+ cansurround = 1;
+ dsahip->chout = 6;
+ if (speakerconfig >= DSSPEAKER_CONFIG (DSSPEAKER_7POINT1))
+ dsahip->chout = 8;
+ }
+ }
+
+ dsahip->bitspersampleout = dsahip->bits24 ? 24 : 16;
+ dsahip->bytespersampleout = dsahip->bitspersampleout / 8;
+ dsahip->channellength = 65536 * dsahip->chout * dsahip->bytespersampleout;
+ dsahip->mixlength = 4000 * dsahip->chout * dsahip->bytespersampleout;
+ if (ahi_debug)
+ write_log("AHI: CH=%d BLEN=%d MLEN=%d SC=%08x\n",
+ dsahip->chout, dsahip->channellength, dsahip->mixlength, speakerconfig);
+
+ memset (&DSCaps, 0, sizeof (DSCaps));
+ DSCaps.dwSize = sizeof (DSCaps);
+ hr = IDirectSound_GetCaps (dsahip->DS, &DSCaps);
+ if (FAILED(hr)) {
+ write_log ("AHI: Error getting DirectSound capabilities: %s\n", DXError (hr));
+ goto error;
+ }
+ if (DSCaps.dwFlags & DSCAPS_EMULDRIVER) {
+ write_log ("AHI: Emulated DirectSound driver detected, don't complain if sound quality is crap :)\n");
+ }
+ if (DSCaps.dwFlags & DSCAPS_CONTINUOUSRATE) {
+ int minfreq = DSCaps.dwMinSecondarySampleRate;
+ int maxfreq = DSCaps.dwMaxSecondarySampleRate;
+ if (minfreq > freq && freq < 22050) {
+ freq = minfreq;
+ write_log ("AHI: minimum supported frequency: %d\n", minfreq);
+ }
+ if (maxfreq < freq && freq > 44100) {
+ freq = maxfreq;
+ write_log ("AHI: maximum supported frequency: %d\n", maxfreq);
+ }
+ }
+
+ if (ahi_debug)
+ write_log ("AHI: DSOUND initialized: %s\n", sound_devices[dsahip->output].name);
+
+ return 1;
+error:
+ if (ahi_debug)
+ write_log ("AHI: DSOUND initialization failed\n");
+ ds_free (dsahip);
+ return 0;
+}
+
+static int ds_reinit (struct DSAHI *dsahip)
+{
+ ds_free (dsahip);
+ return ds_init (dsahip);
+}
+
+
+static void ds_setvolume (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ HRESULT hr;
+ LONG vol, pan;
+
+ if (dc->dsb) {
+ if (abs (dc->cs.volume) != abs (dc->csnext.volume)) {
+ vol = (LONG)((DSBVOLUME_MIN / 2) + (-DSBVOLUME_MIN / 2) * log (1 + (2.718281828 - 1) * (abs (dc->csnext.volume) / 65536.0)));
+ hr = IDirectSoundBuffer_SetVolume (dc->dsb, vol);
+ if (FAILED (hr))
+ write_log ("AHI: SetVolume(%d,%d) failed: %s\n", dc->num, vol, DXError (hr));
+ }
+ if (abs (dc->cs.panning) != abs (dc->csnext.panning)) {
+ pan = (abs (dc->csnext.panning) - 0x8000) * DSBPAN_RIGHT / 32768;
+ hr = IDirectSoundBuffer_SetPan (dc->dsb, pan);
+ if (FAILED (hr))
+ write_log ("AHI: SetPan(%d,%d) failed: %s\n", dc->num, pan, DXError (hr));
+ }
+ }
+ dc->cs.volume = dc->csnext.volume;
+ dc->cs.panning = dc->csnext.panning;
+}
+
+static void ds_setfreq (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ HRESULT hr;
+
+ if (dc->cs.frequency != dc->csnext.frequency && dc->csnext.frequency > 0 && dc->dsb) {
+ hr = IDirectSoundBuffer8_SetFrequency (dc->dsb, dc->csnext.frequency);
+ if (FAILED (hr))
+ write_log ("AHI: SetFrequency(%d,%d) failed: %s\n", dc->num, dc->csnext.frequency, DXError (hr));
+ }
+ dc->cs.frequency = dc->csnext.frequency;
+}
+
+static int ds_allocchannel (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ HRESULT hr;
+ DSBUFFERDESC dd;
+ WAVEFORMATEXTENSIBLE wavfmt;
+ LPDIRECTSOUNDBUFFER pdsb;
+ LPDIRECTSOUNDBUFFER8 pdsb8;
+ int round;
+
+ if (dc->dsb)
+ return 1;
+ pdsb = NULL;
+ for (round = 0; supportedmodes[round].ch; round++) {
+ DWORD ksmode = 0;
+
+ pdsb = NULL;
+ if (supportedmodes[round].ch != dsahip->chout)
+ continue;
+
+ memset (&wavfmt, 0, sizeof (WAVEFORMATEXTENSIBLE));
+ wavfmt.Format.nChannels = dsahip->chout;
+ wavfmt.Format.nSamplesPerSec = default_freq;
+ wavfmt.Format.wBitsPerSample = dsahip->bitspersampleout;
+ if (dsahip->chout <= 2) {
+ wavfmt.Format.wFormatTag = WAVE_FORMAT_PCM;
+ } else {
+ DWORD ksmode = 0;
+ wavfmt.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+ wavfmt.Format.cbSize = sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX);
+ wavfmt.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+ wavfmt.Samples.wValidBitsPerSample = dsahip->bitspersampleout;
+ wavfmt.dwChannelMask = supportedmodes[round].ksmode;
+ }
+ wavfmt.Format.nBlockAlign = dsahip->bytespersampleout * wavfmt.Format.nChannels;
+ wavfmt.Format.nAvgBytesPerSec = wavfmt.Format.nBlockAlign * wavfmt.Format.nSamplesPerSec;
+
+ memset (&dd, 0, sizeof dd);
+ dd.dwSize = sizeof dd;
+ dd.dwBufferBytes = dsahip->channellength;
+ dd.lpwfxFormat = &wavfmt.Format;
+ dd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY;
+ dd.dwFlags |= DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY;
+ dd.dwFlags |= dsahip->chout >= 4 ? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE;
+ dd.guid3DAlgorithm = GUID_NULL;
+
+ hr = IDirectSound_CreateSoundBuffer (dsahip->DS, &dd, &pdsb, NULL);
+ if (SUCCEEDED (hr))
+ break;
+ if (dd.dwFlags & DSBCAPS_LOCHARDWARE) {
+ HRESULT hr2 = hr;
+ dd.dwFlags &= ~DSBCAPS_LOCHARDWARE;
+ dd.dwFlags |= DSBCAPS_LOCSOFTWARE;
+ hr = IDirectSound_CreateSoundBuffer (dsahip->DS, &dd, &pdsb, NULL);
+ if (SUCCEEDED (hr))
+ break;
+ }
+ write_log ("AHI: DS sound buffer failed (ch=%d,bps=%d): %s\n",
+ dsahip->chout, dsahip->bitspersampleout, DXError (hr));
+ }
+ if (pdsb == NULL)
+ goto error;
+
+ hr = IDirectSound_QueryInterface (pdsb, &IID_IDirectSoundBuffer8, (LPVOID*)&pdsb8);
+ if (FAILED (hr)) {
+ write_log ("AHI: Secondary QueryInterface(IID_IDirectSoundBuffer8) failure: %s\n", DXError (hr));
+ goto error;
+ }
+ IDirectSound_Release (pdsb);
+ dc->dsb = pdsb8;
+
+ dc->cs.frequency = -1;
+ dc->cs.volume = -1;
+ dc->cs.panning = -1;
+ ds_setvolume (dsahip, dc);
+ ds_setfreq (dsahip, dc);
+ dc->mixlength = dsahip->mixlength;
+ dc->buffer = xcalloc (dc->mixlength, 1);
+ dc->buffercursor = 0;
+ if (ahi_debug)
+ write_log ("AHI: allocated directsound buffer for channel %d\n", dc->num);
+ return 1;
+error:
+ ds_freechannel (dsahip, dc);
+ return 0;
+}
+
+#define MAKEXCH makexch (dsahip, dc, dst, i, och2, l, r)
+
+STATIC_INLINE void makexch (struct DSAHI *dsahip, struct dschannel *dc, uae_u8 *dst, int idx, int och2, uae_s32 l, uae_s32 r)
+{
+ if (dsahip->bits24) {
+ } else {
+ uae_s16 *dst2 = (uae_u16*)(&dst[idx * och2]);
+ l >>= 8;
+ r >>= 8;
+ if (dc->cs.volume < 0) {
+ l = -l;
+ r = -r;
+ }
+ dst2[0] = l;
+ dst2[1] = r;
+ if (dsahip->chout <= 2)
+ return;
+ dst2[4] = dst2[0];
+ dst2[5] = dst2[1];
+ if (dc->cs.panning < 0) {
+ // surround only
+ dst2[2] = 0; // center
+ dst2[3] = (dst2[0] + dst2[1]) / 4; // lfe
+ dst2[0] = dst2[1] = 0;
+ return;
+ }
+ dst2[2] = dst2[3] = (dst2[0] + dst2[1]) / 4;
+ if (dsahip->chout <= 6)
+ return;
+ dst2[6] = dst2[4];
+ dst2[7] = dst2[5];
+ }
+}
+
+/* sample conversion routines */
+static void copysampledata (struct DSAHI *dsahip, struct dschannel *dc, struct dssample *ds, uae_u8 **psrcp, uae_u8 *srce, uae_u8 *srcp, void *dstp, int dstlen)
+{
+ int i;
+ uae_u8 *src = *psrcp;
+ uae_u8 *dst = (uae_u8*)dstp;
+ int och = dsahip->chout;
+ int och2 = och * 2;
+ int ich = ds->ch;
+ int len;
+
+ len = dstlen;
+ switch (ds->sampletype)
+ {
+ case AHIST_M8S:
+ for (i = 0; i < len; i++) {
+ uae_u32 l = (src[0] << 16) | (src[0] << 8) | src[0] ;
+ uae_u32 r = (src[0] << 16) | (src[0] << 8) | src[0];
+ src += 1;
+ if (src >= srce)
+ src = srcp;
+ MAKEXCH;
+ }
+ break;
+ case AHIST_S8S:
+ for (i = 0; i < len; i++) {
+ uae_u32 l = (src[0] << 16) | (src[0] << 8) | src[0] ;
+ uae_u32 r = (src[1] << 16) | (src[1] << 8) | src[1];
+ src += 2;
+ if (src >= srce)
+ src = srcp;
+ MAKEXCH;
+ }
+ break;
+ case AHIST_M16S:
+ for (i = 0; i < len; i++) {
+ uae_u32 l = (src[0] << 16) | (src[1] << 8) | src[1];
+ uae_u32 r = (src[0] << 16) | (src[1] << 8) | src[1];
+ src += 2;
+ if (src >= srce)
+ src = srcp;
+ MAKEXCH;
+ }
+ break;
+ case AHIST_S16S:
+ for (i = 0; i < len; i++) {
+ uae_u32 l = (src[0] << 16) | (src[1] << 8) | src[1];
+ uae_u32 r = (src[2] << 16) | (src[3] << 8) | src[3];
+ src += 4;
+ if (src >= srce)
+ src = srcp;
+ MAKEXCH;
+ }
+ break;
+ case AHIST_M32S:
+ for (i = 0; i < len; i++) {
+ uae_u32 l = (src[3] << 16) | (src[2] << 8) | src[1];
+ uae_u32 r = (src[3] << 16) | (src[2] << 8) | src[1];
+ src += 4;
+ if (src >= srce)
+ src = srcp;
+ MAKEXCH;
+ }
+ break;
+ case AHIST_S32S:
+ for (i = 0; i < len; i++) {
+ uae_u32 l = (src[3] << 16) | (src[2] << 8) | src[1];
+ uae_u32 r = (src[7] << 16) | (src[6] << 8) | src[5];
+ src += 8;
+ if (src >= srce)
+ src = srcp;
+ MAKEXCH;
+ }
+ break;
+ case AHIST_L7_1:
+ if (och == 8) {
+ for (i = 0; i < len; i++) {
+ if (dsahip->bits24) {
+ uae_u32 fl = (src[0 * 4 + 3] << 16) | (src[0 * 4 + 2] << 8) | src[0 * 4 + 1];
+ uae_u32 fr = (src[1 * 4 + 3] << 16) | (src[1 * 4 + 2] << 8) | src[1 * 4 + 1];
+ uae_u32 cc = (src[6 * 4 + 3] << 16) | (src[6 * 4 + 2] << 8) | src[6 * 4 + 1];
+ uae_u32 lf = (src[7 * 4 + 3] << 16) | (src[7 * 4 + 2] << 8) | src[7 * 4 + 1];
+ uae_u32 bl = (src[2 * 4 + 3] << 16) | (src[2 * 4 + 2] << 8) | src[2 * 4 + 1];
+ uae_u32 br = (src[3 * 4 + 3] << 16) | (src[3 * 4 + 2] << 8) | src[3 * 4 + 1];
+ uae_u32 sl = (src[4 * 4 + 3] << 16) | (src[4 * 4 + 2] << 8) | src[4 * 4 + 1];
+ uae_u32 sr = (src[5 * 4 + 3] << 16) | (src[5 * 4 + 2] << 8) | src[5 * 4 + 1];
+ uae_s32 *dst2 = (uae_s32*)(&dst[i * och2]);
+ dst2[0] = fl;
+ dst2[1] = fr;
+ dst2[2] = cc;
+ dst2[3] = lf;
+ dst2[4] = bl;
+ dst2[5] = br;
+ dst2[6] = sl;
+ dst2[7] = sr;
+ } else {
+ uae_u16 fl = (src[0 * 4 + 3] << 8) | src[0 * 4 + 2];
+ uae_u16 fr = (src[1 * 4 + 3] << 8) | src[1 * 4 + 2];
+ uae_u16 cc = (src[6 * 4 + 3] << 8) | src[6 * 4 + 2];
+ uae_u16 lf = (src[7 * 4 + 3] << 8) | src[7 * 4 + 2];
+ uae_u16 bl = (src[2 * 4 + 3] << 8) | src[2 * 4 + 2];
+ uae_u16 br = (src[3 * 4 + 3] << 8) | src[3 * 4 + 2];
+ uae_u16 sl = (src[4 * 4 + 3] << 8) | src[4 * 4 + 2];
+ uae_u16 sr = (src[5 * 4 + 3] << 8) | src[5 * 4 + 2];
+ uae_s16 *dst2 = (uae_s16*)(&dst[i * och2]);
+ dst2[0] = fl;
+ dst2[1] = fr;
+ dst2[2] = cc;
+ dst2[3] = lf;
+ dst2[4] = bl;
+ dst2[5] = br;
+ dst2[6] = sl;
+ dst2[7] = sr;
+ }
+ dst += och2;
+ src += 8 * 4;
+ if (src >= srce)
+ src = srcp;
+ }
+ } else if (och == 6) { /* 7.1 -> 5.1 */
+ for (i = 0; i < len; i++) {
+ if (dsahip->bits24) {
+ uae_s32 *dst2 = (uae_s32*)(&dst[i * och2]);
+ uae_u32 fl = (src[0 * 4 + 3] << 16) | (src[0 * 4 + 2] << 8) | src[0 * 4 + 1];
+ uae_u32 fr = (src[1 * 4 + 3] << 16) | (src[1 * 4 + 2] << 8) | src[1 * 4 + 1];
+ uae_u32 cc = (src[6 * 4 + 3] << 16) | (src[6 * 4 + 2] << 8) | src[6 * 4 + 1];
+ uae_u32 lf = (src[7 * 4 + 3] << 16) | (src[7 * 4 + 2] << 8) | src[7 * 4 + 1];
+ uae_u32 bl = (src[2 * 4 + 3] << 16) | (src[2 * 4 + 2] << 8) | src[2 * 4 + 1];
+ uae_u32 br = (src[3 * 4 + 3] << 16) | (src[3 * 4 + 2] << 8) | src[3 * 4 + 1];
+ uae_u32 sl = (src[4 * 4 + 3] << 16) | (src[4 * 4 + 2] << 8) | src[4 * 4 + 1];
+ uae_u32 sr = (src[5 * 4 + 3] << 16) | (src[5 * 4 + 2] << 8) | src[5 * 4 + 1];
+ } else {
+ uae_s16 *dst2 = (uae_s16*)(&dst[i * och2]);
+ uae_u16 fl = (src[0 * 4 + 3] << 8) | src[0 * 4 + 2];
+ uae_u16 fr = (src[1 * 4 + 3] << 8) | src[1 * 4 + 2];
+ uae_u16 cc = (src[6 * 4 + 3] << 8) | src[6 * 4 + 2];
+ uae_u16 lf = (src[7 * 4 + 3] << 8) | src[7 * 4 + 2];
+ uae_u16 bl = (src[2 * 4 + 3] << 8) | src[2 * 4 + 2];
+ uae_u16 br = (src[3 * 4 + 3] << 8) | src[3 * 4 + 2];
+ uae_u16 sl = (src[4 * 4 + 3] << 8) | src[4 * 4 + 2];
+ uae_u16 sr = (src[5 * 4 + 3] << 8) | src[5 * 4 + 2];
+ dst2[0] = fl;
+ dst2[1] = fr;
+ dst2[2] = cc;
+ dst2[3] = lf;
+ dst2[4] = (bl + sl) / 2;
+ dst2[5] = (br + sr) / 2;
+ }
+ dst += och2;
+ src += 8 * 4;
+ if (src >= srce)
+ src = srcp;
+ }
+ }
+ break;
+ }
+ *psrcp = src;
+}
+
+static void dorecord (struct DSAHI *dsahip)
+{
+ uae_u32 pbase = get_long (dsahip->audioctrl + ahiac_DriverData);
+ HRESULT hr;
+ DWORD cpos, rpos, diff;
+ void *buf1, *buf2;
+ DWORD size1, size2;
+ uae_u32 recordbuf;
+ int mixlength_bytes;
+
+ if (dsahip->dscb == NULL)
+ return;
+ if (dsahip->record_wait && !get_word (pbase + pub_RecordHookDone))
+ return;
+ dsahip->record_wait = 0;
+ mixlength_bytes = dsahip->mixlength_record * dsahip->record_ch * dsahip->record_bytespersample;
+ recordbuf = get_long (pbase + pub_RecordBuffer);
+ if (recordbuf == 0 || !valid_address (recordbuf, mixlength_bytes))
+ return;
+ hr = IDirectSoundCaptureBuffer_GetCurrentPosition (dsahip->dscb, &cpos, &rpos);
+ if (FAILED (hr)) {
+ write_log ("AHI: IDirectSoundCaptureBuffer_GetCurrentPosition() failed %s\n", DXError (hr));
+ return;
+ }
+ if (rpos < dsahip->recordingcursor)
+ rpos += dsahip->channellength_record;
+ diff = rpos - dsahip->recordingcursor;
+ if (diff < mixlength_bytes)
+ return;
+ hr = IDirectSoundCaptureBuffer_Lock (dsahip->dscb, dsahip->recordingcursor, mixlength_bytes, &buf1, &size1, &buf2, &size2, 0);
+ if (SUCCEEDED (hr)) {
+ uae_u8 *addr = get_real_address (recordbuf);
+ uae_u8 *b = (uae_u8*)buf1;
+ int s;
+ b = (uae_u8*)buf1;
+ s = size1;
+ while (s > 0) {
+ addr[0] = b[1];
+ addr[1] = b[0];
+ addr += 2;
+ b += 2;
+ s -= 2;
+ }
+ b = (uae_u8*)buf2;
+ s = size2;
+ while (s > 0) {
+ addr[0] = b[1];
+ addr[1] = b[0];
+ addr += 2;
+ b += 2;
+ s -= 2;
+ }
+ IDirectSoundCaptureBuffer_Unlock (dsahip->dscb, buf1, size1, buf2, size2);
+ put_word (pbase + pub_RecordHookDone, 0);
+ dsahip->record_wait = 1;
+ put_word (pbase + pub_FuncMode, get_word (pbase + pub_FuncMode) | FUNCMODE_RECORD);
+ sendsignal (dsahip);
+ }
+ dsahip->recordingcursor += mixlength_bytes;
+ if (dsahip->recordingcursor >= dsahip->channellength_record)
+ dsahip->recordingcursor -= dsahip->channellength_record;
+}
+
+static int ds_copysample (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ HRESULT hr;
+ DWORD playc, writec;
+ DWORD size1, size2;
+ DWORD diff;
+ void *buf1, *buf2;
+
+ hr = IDirectSoundBuffer8_GetCurrentPosition (dc->dsb, &playc, &writec);
+ if (FAILED (hr)) {
+ write_log ("AHI: GetCurrentPosition(%d) failed, %s\n", dc->num, DXError (hr));
+ return 0;
+ }
+
+ if (dc->dscursor >= writec)
+ diff = dc->dscursor - writec;
+ else
+ diff = dsahip->channellength - writec + dc->dscursor;
+
+ if (diff > dsahip->channellength / 2) {
+ dc->dscursor = writec + dc->mixlength;
+ write_log ("AHI: Resync\n");
+ }
+ if (diff > dc->mixlength)
+ return 0;
+
+ hr = IDirectSoundBuffer8_Lock (dc->dsb, dc->dscursor, dc->mixlength, &buf1, &size1, &buf2, &size2, 0);
+ if (hr == DSERR_BUFFERLOST) {
+ IDirectSoundBuffer8_Restore (dc->dsb);
+ hr = IDirectSoundBuffer8_Lock (dc->dsb, dc->dscursor, dc->mixlength, &buf1, &size1, &buf2, &size2, 0);
+ }
+ if (SUCCEEDED (hr)) {
+ memcpy (buf1, dc->buffer, size1);
+ if (buf2)
+ memcpy (buf2, dc->buffer + size1, size2);
+ IDirectSoundBuffer8_Unlock (dc->dsb, buf1, size1, buf2, size2);
+ }
+
+ if (ahi_debug > 1)
+ write_log ("%d playc=%08d writec=%08d dscursor=%08d\n",
+ diff / (dsahip->chout * dsahip->bytespersampleout),
+ playc, writec, dc->dscursor);
+
+ dc->dscursor += dc->mixlength;
+ if (dc->dscursor >= dsahip->channellength)
+ dc->dscursor -= dsahip->channellength;
+
+ return 1;
+}
+
+static int calcdelay (struct dschannel *dc, int len)
+{
+ int rate = vblank_hz * maxvpos;
+ int freq = dc->cs.frequency;
+ int hsyncs = rate * len / freq;
+ hsyncs = hsyncs * 2 / 3;
+ if (hsyncs > 0)
+ hsyncs--;
+ return hsyncs;
+}
+
+#if 0
+static void checkvolfreq (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ if (dc->cs.frequency != dc->csnext.frequency)
+ ds_setfreq (dsahip, dc);
+ if (dc->cs.volume != dc->csnext.volume || dc->cs.panning != dc->csnext.panning)
+ ds_setvolume (dsahip, dc);
+}
+
+static void getmixbufferlen (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ int olen = dc->mixlength;
+ dc->mixlength = (dc->csnext.frequency / 24) * dsahip->bytespersampleout * dsahip->chout;
+ if (dc->mixlength > dsahip->mixlength)
+ dc->mixlength = dsahip->mixlength;
+ if (dc->mixlength < 100)
+ dc->mixlength = 100;
+ if (ahi_debug && olen != dc->mixlength)
+ write_log ("AHI: channel %d: buffer %d frames\n",
+ dc->num, dc->mixlength / (dsahip->bytespersampleout * dsahip->chout));
+}
+
+static void copysample (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ int dstlen, dstlenbytes;
+ struct dssample *ds;
+ int srclen, srclendstbytes;
+ int chbytesout;
+ uae_u8 *dstbuf;
+ uae_u32 addr, addre, addrs;
+ int chbytesin;
+ int waitlen;
+
+ assert (dc->buffercursor < dc->mixlength);
+
+ chbytesout = dsahip->chout * dsahip->bytespersampleout;
+ dstbuf = dc->buffer + dc->buffercursor;
+ dstlenbytes = dc->mixlength - dc->buffercursor;
+ dstlen = dstlenbytes / chbytesout;
+
+ ds = dc->cs.ds;
+ if (ds == NULL) {
+ ds = dc->ds = dc->nextds;
+ dc->srcplaylen = dc->nextsrcplaylen;
+ dc->srcplayoffset = dc->nextsrcplayoffset;
+ dc->nextds = NULL;
+ dc->nextsrcplaylen = 0;
+ dc->nextsrcplayoffset = 0;
+ dc->srcoffset = 0;
+ if (ds != NULL) { // sample started
+ int len;
+ setchannelevent (dsahip, dc);
+ len = dc->srcplaylen;
+ if (len > dstlen)
+ len = dstlen;
+ dc->hsync = calcdelay (dc, len);
+ return;
+ }
+ }
+ if (ds == NULL)
+ goto cempty;
+
+ chbytesin = ds->ch * ds->bytespersample;
+ if (ds->addr == 0 && ds->len == 0xffffffff) {
+ addrs = addr = ds->offset;
+ } else {
+ addr = ds->addr;
+ addr += dc->srcplayoffset * chbytesin;
+ addrs = addr;
+ }
+ addre = addr + dc->srcplaylen * chbytesin;
+ addr += dc->srcoffset * chbytesin;
+
+ srclen = dc->srcplaylen - dc->srcoffset;
+ assert (srclen > 0);
+ srclendstbytes = srclen * chbytesout;
+
+ if (srclendstbytes > dstlenbytes) {
+ srclendstbytes = dstlenbytes;
+ srclen = srclendstbytes / chbytesout;
+ }
+ if (dstlenbytes > srclendstbytes) {
+ dstlenbytes = srclendstbytes;
+ dstlen = dstlenbytes / chbytesout;
+ }
+
+ waitlen = dstlen;
+
+ assert (dstlen > 0);
+
+ if (valid_address (addrs, addre - addrs)) {
+ uae_u8 *naddr = get_real_address (addr);
+ uae_u8 *naddre = get_real_address (addre);
+ uae_u8 *naddrs = get_real_address (addrs);
+ copysampledata (dsahip, dc, ds, &naddr, naddre, naddrs, dstbuf, dstlen);
+ dc->srcoffset = (naddr - naddrs) / chbytesin;
+ if (dc->srcoffset == 0) {
+ // looping or next sample
+ if (dc->nextsrcplaylen < 0) { // stop sample
+ int off = dstlenbytes;
+ dc->nextsrcplaylen = 0;
+ dc->nextds = NULL;
+ setchannelevent (dsahip, dc);
+ dstlenbytes = dc->mixlength - off - dc->buffercursor;
+ dstlen = dstlenbytes / chbytesout;
+ memset (dstbuf + off, 0, dstlenbytes);
+ goto empty;
+ }
+ if (dc->nextds) {
+ dc->ds = NULL;
+ dc->buffercursor += dstlenbytes;
+ dc->hsync = 0;
+ return;
+ }
+ setchannelevent (dsahip, dc);
+
+ }
+
+ } else {
+ goto cempty;
+ }
+
+ dc->hsync = calcdelay (dc, waitlen);
+ dc->buffercursor += dstlenbytes;
+ checkvolfreq (dsahip, dc);
+ //write_log ("%d ", dstlen / (dsahip->chout * dsahip->bytespersampleout));
+ return;
+
+cempty:
+ memset (dstbuf, 0, dstlenbytes);
+empty:
+ dc->ds = NULL;
+ dc->hsync = calcdelay (dc, waitlen);
+ dc->buffercursor += dstlenbytes;
+ checkvolfreq (dsahip, dc);
+}
+#endif
+
+static void incchannel (struct DSAHI *dsahip, struct dschannel *dc, int samplecnt)
+{
+ struct chsample *cs = &dc->cs;
+
+ if (cs->ds == NULL)
+ return;
+ dc->srcoffset += samplecnt;
+ while (dc->srcoffset >= cs->srcplaylen) {
+ dc->srcoffset -= cs->srcplaylen;
+ setchannelevent (dsahip, dc);
+ if (dc->csnext.stopit) {
+ memset (cs, 0, sizeof (struct chsample));
+ memset (&dc->csnext, 0, sizeof (struct chsample));
+ dc->srcoffset = 0;
+ return;
+ }
+ if (dc->csnext.ds) {
+ memcpy (cs, &dc->csnext, sizeof (struct chsample));
+ memset (&dc->csnext, 0, sizeof (struct chsample));
+ continue;
+ }
+ }
+}
+
+void ahi_hsync (void)
+{
+ struct DSAHI *dsahip = &dsahi[0];
+ static int cnt;
+ uae_u32 pbase;
+ int i, flags;
+
+ if (ahi_paused || !ahi_active)
+ return;
+ pbase = get_long (dsahip->audioctrl + ahiac_DriverData);
+ if (cnt >= 0)
+ cnt--;
+ if (cnt < 0) {
+ if (dsahip->dsrecording && dsahip->enabledisable == 0) {
+ dorecord (dsahip);
+ cnt = 100;
+ }
+ }
+ if (!dsahip->playing)
+ return;
+ flags = get_long (pbase + pub_ChannelSignalAck);
+ for (i = 0; i < UAE_MAXCHANNELS; i++) {
+ struct dschannel *dc = &dsahip->channel[i];
+ HRESULT hr;
+ DWORD playc, writec, diff, samplediff;
+
+ if (dc->dsb == NULL)
+ continue;
+ if (dc->dsplaying == 0)
+ continue;
+ hr = IDirectSoundBuffer8_GetCurrentPosition (dc->dsb, &playc, &writec);
+ if (FAILED (hr)) {
+ write_log ("AHI: GetCurrentPosition(%d) failed, %s\n", dc->num, DXError (hr));
+ continue;
+ }
+ if (dc->dscursor >= writec)
+ diff = dc->dscursor - writec;
+ else
+ diff = dsahip->channellength - writec + dc->dscursor;
+ if (diff > dsahip->channellength / 2) {
+ dc->dscursor = writec + dc->mixlength;
+ write_log ("AHI: Resync %d\n", dc->num);
+ }
+
+ if (dc->dscursor < 0) {
+ dc->dscursor = writec;
+ memcpy (&dc->cs, &dc->csnext, sizeof (struct chsample));
+ }
+ samplediff = diff / (dsahip->chout * dsahip->bytespersampleout);
+ incchannel (dsahip, dc, samplediff);
+// copysample (dsahip, dc, &dc->cs);
+
+
+
+
+ if (diff > dc->mixlength)
+ continue;
+
+
+#if 0
+ if (dc->buffer == NULL)
+ continue;
+ if (dc->hsync > 0) {
+ dc->hsync--;
+ continue;
+ }
+ if (dc->channelsignal) {
+ if (!(flags & (1 << dc->num)))
+ continue;
+ dc->channelsignal = 0;
+ flags &= ~(1 << dc->num);
+ }
+ if (dsahip->enabledisable)
+ continue;
+ if (dc->buffercursor < dc->mixlength)
+ copysample (dsahip, dc);
+ assert (dc->buffercursor <= dc->mixlength);
+ if (dc->buffercursor == dc->mixlength) {
+ if (ds_copysample (dsahip, dc)) {
+ getmixbufferlen (dsahip, dc);
+ dc->buffercursor = 0;
+ } else {
+ dc->hsync = 100;
+ }
+ }
+#endif
+ }
+ put_long (pbase + pub_ChannelSignalAck, flags);
+}
+
+static void ds_record (struct DSAHI *dsahip, int start)
+{
+ HRESULT hr;
+
+ if (dsahip->dscb == NULL)
+ return;
+ if (dsahip->dsrecording && start)
+ return;
+ dsahip->dsrecording = 0;
+ if (start) {
+ hr = IDirectSoundCaptureBuffer_Start (dsahip->dscb, DSCBSTART_LOOPING);
+ if (FAILED (hr)) {
+ write_log ("AHI: DirectSoundCaptureBuffer_Start failed: %s\n", DXError (hr));
+ return;
+ }
+ dsahip->dsrecording = 1;
+ } else {
+ hr = IDirectSoundCaptureBuffer_Stop (dsahip->dscb);
+ if (FAILED (hr)) {
+ write_log ("AHI: DirectSoundCaptureBuffer_Stop failed: %s\n", DXError (hr));
+ return;
+ }
+ }
+}
+
+static void ds_stop (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ HRESULT hr;
+
+ dc->dsplaying = 0;
+ if (dc->dsb == NULL)
+ return;
+ if (ahi_debug)
+ write_log ("AHI: ds_stop(%d)\n", dc->num);
+ hr = IDirectSoundBuffer8_Stop (dc->dsb);
+ if (FAILED (hr))
+ write_log ("AHI: IDirectSoundBuffer8_Stop() failed, %s\n", DXError (hr));
+}
+
+static void ds_play (struct DSAHI *dsahip, struct dschannel *dc)
+{
+ HRESULT hr;
+ DWORD status, playc, writec;
+
+ if (dc->dsb == NULL)
+ return;
+ if (dc->dsplaying)
+ return;
+ if (dc->cs.frequency == 0)
+ return;
+ dc->dsplaying = 1;
+ if (ahi_debug)
+ write_log ("AHI: ds_play(%d)\n", dc->num);
+ hr = IDirectSoundBuffer8_GetStatus (dc->dsb, &status);
+ if (FAILED (hr))
+ write_log ("AHI: ds_play() IDirectSoundBuffer8_GetStatus() failed, %s\n", DXError (hr));
+ hr = IDirectSoundBuffer8_Play (dc->dsb, 0, 0, DSBPLAY_LOOPING);
+ if (FAILED (hr))
+ write_log ("AHI: ds_play() IDirectSoundBuffer8_Play() failed, %s\n", DXError (hr));
+ hr = IDirectSoundBuffer8_GetCurrentPosition (dc->dsb, &playc, &writec);
+ if (FAILED (hr))
+ write_log ("AHI: ds_play() IDirectSoundBuffer8_GetCurrentPosition() failed, %s\n", DXError (hr));
+ dc->dscursor = writec + dc->mixlength;
+ if (dc->dscursor >= dsahip->channellength)
+ dc->dscursor -= dsahip->channellength;
+ if (ahi_debug)
+ write_log("AHI: ds_play(%d) Start=%d->%d\n", dc->num, writec, dc->dscursor);
+}
+
+void ahi2_pause_sound (int paused)
+{
+ int i;
+ struct DSAHI *dsahip = &dsahi[0];
+
+ ahi_paused = paused;
+ if (!dsahip->playing && !dsahip->recording)
+ return;
+ for (i = 0; i < UAE_MAXCHANNELS; i++) {
+ struct dschannel *dc = &dsahip->channel[i];
+ if (dc->dsb == NULL)
+ continue;
+ if (paused) {
+ ds_stop (dsahip, dc);
+ } else {
+ ds_play (dsahip, dc);
+ }
+ }
+}
+
+static uae_u32 init (TrapContext *ctx)
+{
+ int i;
+
+ enumerate_sound_devices ();
+ xahi_author = ds ("Toni Wilen");
+ xahi_copyright = ds ("GPL");
+ xahi_version = ds ("uae2 0.1 (xx.xx.2008)\r\n");
+ for (i = 0; sound_devices[i].name; i++)
+ xahi_output[i] = ds (sound_devices[i].name);
+ xahi_output_num = i;
+ for (i = 0; record_devices[i].name; i++)
+ xahi_input[i] = ds (record_devices[i].name);
+ xahi_input_num = i;
+ return 1;
+}
+
+static uae_u32 AHIsub_AllocAudio (TrapContext *ctx)
+{
+ int i;
+ uae_u32 tags = m68k_areg (&ctx->regs, 1);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ uae_u32 pbase = get_long (audioctrl + ahiac_DriverData);
+ uae_u32 tag, data, v, ver, size;
+ uae_u32 ret = AHISF_KNOWSTEREO | AHISF_KNOWHIFI;
+ struct DSAHI *dsahip = &dsahi[0];
+
+ if (ahi_debug)
+ write_log ("AHI: AllocAudio(%08x,%08x)\n", tags, audioctrl);
+
+ ver = get_long (pbase + pub_Version);
+ size = get_long (pbase + pub_SizeOf);
+ if (ver != AHI_STRUCT_VERSION) {
+ gui_message ("AHI: Incompatible DEVS:AHI/uae2.audio\nVersion mismatch %d<>%d.", ver, AHI_STRUCT_VERSION);
+ return AHISF_ERROR;
+ }
+ if (size < pub_End) {
+ gui_message ("AHI: Incompatible DEVS:AHI/uae2.audio.\nInternal structure size %d<%d.", size, pub_End);
+ return AHISF_ERROR;
+ }
+
+
+ v = get_long (pbase + pub_Index);
+ if (v != -1) {
+ write_log ("AHI: corrupted memory\n");
+ return AHISF_ERROR;
+ }
+ put_long (pbase + pub_Index, dsahip - dsahi);
+ dsahip->audioctrl = audioctrl;
+
+ if (!ds_init (dsahip))
+ return AHISF_ERROR;
+ dsahip->sounds = UAE_MAXSOUNDS;
+ dsahip->channels = UAE_MAXCHANNELS;
+
+ if (xahi_input_num)
+ ret |= AHISF_CANRECORD;
+ if (cansurround)
+ ret |= AHISF_KNOWMULTICHANNEL;
+
+ while ((tag = gettag (&tags, &data))) {
+ if (ahi_debug)
+ write_log ("- TAG %08x=%d: %08x=%u\n", tag, tag & 0x7fff, data, data);
+ }
+ if (dsahip->sounds < 0 || dsahip->sounds > 1000) {
+ ds_free (dsahip);
+ ds_free_record (dsahip);
+ return AHISF_ERROR;
+ }
+ dsahip->sample = xcalloc (sizeof (struct dssample), dsahip->sounds);
+ dsahip->channel = xcalloc (sizeof (struct dschannel), dsahip->channels);
+ for (i = 0; i < dsahip->channels; i++) {
+ struct dschannel *dc = &dsahip->channel[i];
+ dc->num = i;
+ }
+ for (i = 0; i < dsahip->sounds; i++) {
+ struct dssample *ds = &dsahip->sample[i];
+ ds->num = -1;
+ }
+ ahi_active = 1;
+ return ret;
+}
+
+static void AHIsub_Disable (TrapContext *ctx)
+{
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ struct DSAHI *dsahip = GETAHI;
+ if (ahi_debug)
+ write_log ("AHI: Disable(%08x)\n", audioctrl);
+ dsahip->enabledisable++;
+}
+
+static void AHIsub_Enable (TrapContext *ctx)
+{
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ struct DSAHI *dsahip = GETAHI;
+ if (ahi_debug)
+ write_log ("AHI: Enable(%08x)\n", audioctrl);
+ dsahip->enabledisable--;
+ if (dsahip->enabledisable == 0 && dsahip->playing)
+ setevent (dsahip);
+}
+
+static void AHIsub_FreeAudio (TrapContext *ctx)
+{
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ uae_u32 pbase = get_long (audioctrl + ahiac_DriverData);
+ struct DSAHI *dsahip = GETAHI;
+ if (ahi_debug)
+ write_log ("AHI: FreeAudio(%08x)\n", audioctrl);
+ if (ahi_active == 0)
+ return;
+ ahi_active = 0;
+ put_long (pbase + pub_Index, -1);
+ if (dsahip) {
+ ds_free (dsahip);
+ ds_free_record (dsahip);
+ xfree (dsahip->channel);
+ xfree (dsahip->sample);
+ memset (dsahip, 0, sizeof (struct DSAHI));
+ }
+}
+
+static uae_u32 frequencies[] = { 48000, 44100 };
+#define MAX_FREQUENCIES (sizeof (frequencies) / sizeof (uae_u32))
+
+static uae_u32 getattr2 (uae_u32 attribute, uae_u32 argument, uae_u32 def)
+{
+ int i;
+
+ switch (attribute)
+ {
+ case AHIDB_Bits:
+ return 32;
+ case AHIDB_Frequencies:
+ return MAX_FREQUENCIES;
+ case AHIDB_Frequency:
+ if (argument < 0 || argument >= MAX_FREQUENCIES)
+ argument = 0;
+ return frequencies[argument];
+ case AHIDB_Index:
+ if (argument <= frequencies[0])
+ return 0;
+ if (argument >= frequencies[MAX_FREQUENCIES - 1])
+ return MAX_FREQUENCIES - 1;
+ for (i = 1; i < MAX_FREQUENCIES; i++) {
+ if (frequencies[i] > argument) {
+ if (argument - frequencies[i - 1] < frequencies[i] - argument)
+ return i - 1;
+ else
+ return i;
+ }
+ }
+ return 0;
+ case AHIDB_Author:
+ return xahi_author;
+ case AHIDB_Copyright:
+ return xahi_copyright;
+ case AHIDB_Version:
+ return xahi_version;
+ case AHIDB_Record:
+ return -1;
+ case AHIDB_Realtime:
+ return -1;
+ case AHIDB_MinOutputVolume:
+ return 0x00000;
+ case AHIDB_MaxOutputVolume:
+ return 0x10000;
+ case AHIDB_Outputs:
+ return xahi_output_num;
+ case AHIDB_Output:
+ if (argument >= 0 && argument < xahi_output_num)
+ return xahi_output[argument];
+ return 0;
+ case AHIDB_Inputs:
+ return xahi_input_num;
+ case AHIDB_Input:
+ if (argument >= 0 && argument < xahi_input_num)
+ return xahi_input[argument];
+ return 0;
+ case AHIDB_Volume:
+ return -1;
+ case AHIDB_Panning:
+ return -1;
+ case AHIDB_HiFi:
+ return -1;
+ case AHIDB_MultiChannel:
+ return cansurround ? -1 : 0;
+ case AHIDB_MaxChannels:
+ return UAE_MAXCHANNELS;
+ case AHIDB_FullDuplex:
+ return -1;
+ case AHIDB_MaxRecordSamples:
+ return RECORDSAMPLES;
+ default:
+ return def;
+ }
+}
+
+static uae_u32 AHIsub_GetAttr (TrapContext *ctx)
+{
+ uae_u32 attribute = m68k_dreg (&ctx->regs, 0);
+ uae_u32 argument = m68k_dreg (&ctx->regs, 1);
+ uae_u32 def = m68k_dreg (&ctx->regs, 2);
+ uae_u32 taglist = m68k_areg (&ctx->regs, 1);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ uae_u32 v;
+
+ v = getattr2 (attribute, argument, def);
+ if (ahi_debug)
+ write_log ("AHI: GetAttr(%08x=%d,%08x,%08x)=%08x\n", attribute, attribute & 0x7fff, argument, def, v);
+
+ return v;
+}
+
+static uae_u32 AHIsub_HardwareControl (TrapContext *ctx)
+{
+ uae_u32 attribute = m68k_dreg (&ctx->regs, 0);
+ uae_u32 argument = m68k_dreg (&ctx->regs, 1);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ struct DSAHI *dsahip = GETAHI;
+ if (ahi_debug)
+ write_log ("AHI: HardwareControl(%08x=%d,%08x,%08x)\n", attribute, attribute & 0x7fff, argument, audioctrl);
+ switch (attribute)
+ {
+ case AHIC_Input:
+ if (dsahip->input != argument) {
+ dsahip->input = argument;
+ if (dsahip->dscb) {
+ ds_free_record (dsahip);
+ ds_init_record (dsahip);
+ if (dsahip->recording)
+ ds_record (dsahip, 1);
+ }
+ }
+ break;
+ case AHIC_Input_Query:
+ return dsahip->input;
+ case AHIC_Output:
+ if (dsahip->output != argument) {
+ dsahip->output = argument;
+ if (dsahip->DS)
+ ds_reinit (dsahip);
+ }
+ break;
+ case AHIC_Output_Query:
+ return dsahip->output;
+ }
+ return 0;
+}
+
+static uae_u32 AHIsub_Start (TrapContext *ctx)
+{
+ uae_u32 flags = m68k_dreg (&ctx->regs, 0);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ struct DSAHI *dsahip = GETAHI;
+ int i;
+
+ if (ahi_debug)
+ write_log ("AHI: Play(%08x,%08x)\n",
+ flags, audioctrl);
+ if ((flags & AHISF_PLAY) && !dsahip->playing) {
+ dsahip->playing = 1;
+ setevent (dsahip);
+ for (i = 0; i < dsahip->channels; i++) {
+ struct dschannel *dc = &dsahip->channel[i];
+ ds_play (dsahip, dc);
+ }
+ }
+ if ((flags & AHISF_RECORD) && !dsahip->recording) {
+ dsahip->recording = 1;
+ ds_init_record (dsahip);
+ ds_record (dsahip, 1);
+ }
+ return 0;
+}
+
+static uae_u32 AHIsub_Stop (TrapContext *ctx)
+{
+ uae_u32 flags = m68k_dreg (&ctx->regs, 0);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ struct DSAHI *dsahip = GETAHI;
+ int i;
+
+ if (ahi_debug)
+ write_log ("AHI: Stop(%08x,%08x)\n",
+ flags, audioctrl);
+ if ((flags & AHISF_PLAY) && dsahip->playing) {
+ dsahip->playing = 0;
+ for (i = 0; i < dsahip->channels; i++) {
+ struct dschannel *dc = &dsahip->channel[i];
+ ds_stop (dsahip, dc);
+ }
+ }
+ if ((flags & AHISF_RECORD) && dsahip->recording) {
+ dsahip->recording = 0;
+ ds_record (dsahip, 0);
+ ds_free_record (dsahip);
+ }
+ return 0;
+}
+
+static uae_u32 AHIsub_Update (TrapContext *ctx)
+{
+ uae_u32 flags = m68k_dreg (&ctx->regs, 0);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ struct DSAHI *dsahip = GETAHI;
+ if (ahi_debug)
+ write_log ("AHI: Update(%08x,%08x)\n", flags, audioctrl);
+ setevent (dsahip);
+ return 0;
+}
+
+static uae_u32 AHIsub_SetVol (TrapContext *ctx)
+{
+ uae_u16 channel = m68k_dreg (&ctx->regs, 0);
+ uae_u32 volume = m68k_dreg (&ctx->regs, 1);
+ uae_u32 pan = m68k_dreg (&ctx->regs, 2);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ uae_u32 flags = m68k_dreg (&ctx->regs, 3);
+ struct DSAHI *dsahip = GETAHI;
+ struct dschannel *dc = GETCHANNEL;
+
+ if (ahi_debug)
+ write_log ("AHI: SetVol(%d,%d,%d,%08x,%08x)\n",
+ channel, volume, pan, audioctrl, flags);
+ if (dc) {
+ dc->csnext.volume = volume;
+ dc->csnext.panning = pan;
+ if (flags & AHISF_IMM) {
+ ds_setvolume (dsahip, dc);
+ }
+ }
+ return 0;
+}
+
+static uae_u32 AHIsub_SetFreq (TrapContext *ctx)
+{
+ uae_u16 channel = m68k_dreg (&ctx->regs, 0);
+ uae_u32 frequency = m68k_dreg (&ctx->regs, 1);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ uae_u32 flags = m68k_dreg (&ctx->regs, 3);
+ struct DSAHI *dsahip = GETAHI;
+ struct dschannel *dc = GETCHANNEL;
+
+ if (ahi_debug)
+ write_log ("AHI: SetFreq(%d,%d,%08x,%08x)\n",
+ channel, frequency, audioctrl, flags);
+ if (dc) {
+ dc->csnext.frequency = frequency;
+ if (flags & AHISF_IMM) {
+ ds_setfreq (dsahip, dc);
+ ds_play (dsahip, dc);
+ }
+ }
+ return 0;
+}
+
+static uae_u32 AHIsub_SetSound (TrapContext *ctx)
+{
+ uae_u16 channel = m68k_dreg (&ctx->regs, 0);
+ uae_u16 sound = m68k_dreg (&ctx->regs, 1);
+ uae_u32 offset = m68k_dreg (&ctx->regs, 2);
+ uae_u32 length = m68k_dreg (&ctx->regs, 3);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ uae_u32 flags = m68k_dreg (&ctx->regs, 4);
+ struct DSAHI *dsahip = GETAHI;
+ struct dssample *ds = GETSAMPLE;
+ struct dschannel *dc = GETCHANNEL;
+
+ if (ahi_debug)
+ write_log ("AHI: SetSound(%d,%d,%08x,%d,%08x,%08x)\n",
+ channel, sound, offset, length, audioctrl, flags);
+ if (dc == NULL)
+ return AHIE_UNKNOWN;
+ if (ds->num < 0)
+ return AHIE_UNKNOWN;
+ if (sound == 0xffff) {
+ if (flags & AHISF_IMM) {
+ dc->cs.ds = NULL;
+ dc->csnext.ds = NULL;
+ }
+ dc->csnext.srcplaylen = -1;
+ return 0;
+ }
+ ds_allocchannel (dsahip, dc);
+ dc->cs.backwards = length < 0;
+ length = abs (length);
+ if (length == 0)
+ length = ds->len;
+ if (length > ds->len)
+ length = ds->len;
+ dc->csnext.ds = ds;
+ dc->csnext.srcplaylen = length;
+ dc->csnext.srcplayoffset = offset;
+ if (flags & AHISF_IMM)
+ dc->cs.ds = NULL;
+ if (dc->cs.ds == NULL) {
+ dc->buffercursor = 0;
+ dc->hsync = 0;
+ }
+ ds_setfreq (dsahip, dc);
+ ds_setvolume (dsahip, dc);
+ ds_play (dsahip, dc);
+ return 0;
+}
+
+static uae_u32 AHIsub_SetEffect (TrapContext *ctx)
+{
+ uae_u32 effect = m68k_areg (&ctx->regs, 0);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ uae_u32 effectype = get_long (effect);
+ uae_u32 puaebase = get_long (audioctrl + ahiac_DriverData);
+ struct DSAHI *dsahip = GETAHI;
+
+ if (ahi_debug)
+ write_log ("AHI: SetEffect(%08x (%08x),%08x)\n", effect, effectype, audioctrl);
+ switch (effectype)
+ {
+ case AHIET_CHANNELINFO:
+ put_long (puaebase + pub_ChannelInfo, effect);
+ break;
+ case AHIET_CHANNELINFO | AHIET_CANCEL:
+ put_long (puaebase + pub_ChannelInfo, 0);
+ break;
+ case AHIET_MASTERVOLUME:
+ case AHIET_MASTERVOLUME | AHIET_CANCEL:
+ break;
+ default:
+ return AHIE_UNKNOWN;
+ }
+ return AHIE_OK;
+}
+
+static uae_u32 AHIsub_LoadSound (TrapContext *ctx)
+{
+ uae_u16 sound = m68k_dreg (&ctx->regs, 0);
+ uae_u32 type = m68k_dreg (&ctx->regs, 1);
+ uae_u32 info = m68k_areg (&ctx->regs, 0);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ struct DSAHI *dsahip = GETAHI;
+ uae_u32 ret = AHIE_BADSOUNDTYPE;
+ int sampletype = get_long (info + ahisi_Type);
+ uae_u32 addr = get_long (info + ahisi_Address);
+ uae_u32 len = get_long (info + ahisi_Length);
+ struct dssample *ds = GETSAMPLE;
+ int ch;
+ int bps;
+
+ if (ahi_debug)
+ write_log ("AHI: LoadSound(%d,%d,%08x,%08x,SMP=%d,ADDR=%08x,LEN=%d)\n",
+ sound, type, info, audioctrl, sampletype, addr, len);
+
+ if (!ds)
+ return AHIE_BADSOUNDTYPE;
+
+ ds->num = sound;
+ if (!cansurround && sampletype == AHIST_L7_1)
+ return AHIE_BADSOUNDTYPE;
+ ds->addr = addr;
+ ds->sampletype = sampletype;
+ ds->type = type;
+ ds->len = len;
+
+ switch (sampletype)
+ {
+ case AHIST_M8S:
+ case AHIST_M16S:
+ case AHIST_M32S:
+ ch = 1;
+ break;
+ case AHIST_S8S:
+ case AHIST_S16S:
+ case AHIST_S32S:
+ ch = 2;
+ break;
+ case AHIST_L7_1:
+ ch = 8;
+ break;
+ default:
+ return 0;
+ }
+ switch (sampletype)
+ {
+ case AHIST_M8S:
+ case AHIST_S8S:
+ bps = 8;
+ break;
+ case AHIST_M16S:
+ case AHIST_S16S:
+ bps = 16;
+ break;
+ case AHIST_M32S:
+ case AHIST_S32S:
+ case AHIST_L7_1:
+ bps = 24;
+ break;
+ default:
+ return 0;
+ }
+ ds->bitspersample = bps;
+ ds->ch = ch;
+ ds->bytespersample = bps / 8;
+ return AHIE_OK;
+}
+
+static uae_u32 AHIsub_UnloadSound (TrapContext *ctx)
+{
+ uae_u16 sound = m68k_dreg (&ctx->regs, 0);
+ uae_u32 audioctrl = m68k_areg (&ctx->regs, 2);
+ struct DSAHI *dsahip = GETAHI;
+ struct dssample *ds = GETSAMPLE;
+
+ if (ahi_debug)
+ write_log ("AHI: UnloadSound(%d,%08x)\n",
+ sound, audioctrl);
+ ds->num = -1;
+ return AHIE_OK;
+}
+
+static uae_u32 REGPARAM2 ahi_demux (TrapContext *ctx)
+{
+ uae_u32 ret = 0;
+ uae_u32 sp = m68k_areg (&ctx->regs, 7);
+ uae_u32 offset = get_long (sp + 4);
+
+ if (0 && ahi_debug)
+ write_log ("AHI: %d\n", offset);
+
+ switch (offset)
+ {
+ case 0xffffffff:
+ ret = init (ctx);
+ break;
+ case 0:
+ ret = AHIsub_AllocAudio (ctx);
+ break;
+ case 1:
+ AHIsub_FreeAudio (ctx);
+ break;
+ case 2:
+ AHIsub_Disable (ctx);
+ break;
+ case 3:
+ AHIsub_Enable (ctx);
+ break;
+ case 4:
+ ret = AHIsub_Start (ctx);
+ break;
+ case 5:
+ ret = AHIsub_Update (ctx);
+ break;
+ case 6:
+ ret = AHIsub_Stop (ctx);
+ break;
+ case 7:
+ ret = AHIsub_SetVol (ctx);
+ break;
+ case 8:
+ ret = AHIsub_SetFreq (ctx);
+ break;
+ case 9:
+ ret = AHIsub_SetSound (ctx);
+ break;
+ case 10:
+ ret = AHIsub_SetEffect (ctx);
+ break;
+ case 11:
+ ret = AHIsub_LoadSound (ctx);
+ break;
+ case 12:
+ ret = AHIsub_UnloadSound (ctx);
+ break;
+ case 13:
+ ret = AHIsub_GetAttr (ctx);
+ break;
+ case 14:
+ ret = AHIsub_HardwareControl (ctx);
+ break;
+ }
+ return ret;
+}
+
+void init_ahi_v2 (void)
+{
+ uaecptr a = here ();
+ org (rtarea_base + 0xFFC8);
+ calltrap (deftrapres (ahi_demux, 0, "ahi_winuae_v2"));
+ dw (RTS);
+ org (a);
+}
+
+void free_ahi_v2 (void)
+{
+ ds_free_record (&dsahi[0]);
+ ds_free (&dsahi[0]);
+}
+
+#endif
char tmp[MAX_DPATH];
struct didata *did;
- if (catweasel_ismouse()) {
+ if (catweasel_ismouse ()) {
for (i = 0; i < 2 && num_mouse < MAX_INPUT_DEVICES; i++) {
did = di_mouse;
did += num_mouse;
num_mouse++;
}
}
- if (catweasel_isjoystick()) {
+ if (catweasel_isjoystick ()) {
for (i = 0; i < 2 && num_joystick < MAX_INPUT_DEVICES; i++) {
did = di_joystick;
did += num_joystick;
const char *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth)
{
- HRESULT ret;
+ HRESULT ret, hr;
static char errmsg[100] = { 0 };
D3DDISPLAYMODE mode;
D3DDISPLAYMODEEX modeex;
D3D_free ();
D3D_canshaders ();
- adapter = currprefs.gfx_display - 1;
- if (adapter < 0)
- adapter = 0;
d3d_enabled = 0;
scanlines_ok = 0;
if (currprefs.gfx_filter != UAE_FILTER_DIRECT3D) {
}
}
+ adapter = currprefs.gfx_display - 1;
+ if (adapter < 0)
+ adapter = 0;
+ if (adapter >= IDirect3D9_GetAdapterCount (d3d))
+ adapter = 0;
+
modeex.Size = sizeof modeex;
if (d3dex && D3DEX)
IDirect3D9Ex_GetAdapterDisplayModeEx (d3dex, adapter, &modeex, NULL);
- IDirect3D9_GetAdapterDisplayMode (d3d, adapter, &mode);
- IDirect3D9_GetDeviceCaps (d3d, adapter, D3DDEVTYPE_HAL, &d3dCaps);
+ if (FAILED (hr = IDirect3D9_GetAdapterDisplayMode (d3d, adapter, &mode)))
+ write_log ("D3D: IDirect3D9_GetAdapterDisplayMode failed %s\n", D3D_ErrorString (hr));
+ if (FAILED (hr = IDirect3D9_GetDeviceCaps (d3d, adapter, D3DDEVTYPE_HAL, &d3dCaps)))
+ write_log ("D3D: IDirect3D9_GetDeviceCaps failed %s\n", D3D_ErrorString (hr));
memset (&dpp, 0, sizeof (dpp));
dpp.Windowed = isfullscreen() <= 0;
flags |= D3DCREATE_NOWINDOWCHANGES | D3DCREATE_FPU_PRESERVE;
if (d3d_ex && D3DEX) {
- ret = IDirect3D9Ex_CreateDeviceEx (d3dex, adapter, D3DDEVTYPE_HAL, ahwnd, flags, &dpp, &modeex, &d3ddevex);
+ ret = IDirect3D9Ex_CreateDeviceEx (d3dex, adapter, D3DDEVTYPE_HAL, d3dhwnd, flags, &dpp, &modeex, &d3ddevex);
d3ddev = (LPDIRECT3DDEVICE9)d3ddevex;
} else {
- ret = IDirect3D9_CreateDevice (d3d, adapter, D3DDEVTYPE_HAL, ahwnd, flags, &dpp, &d3ddev);
+ ret = IDirect3D9_CreateDevice (d3d, adapter, D3DDEVTYPE_HAL, d3dhwnd, flags, &dpp, &d3ddev);
}
- if(FAILED (ret)) {
- sprintf (errmsg, "%s failed, %s\n", d3d_ex ? "CreateDeviceEx" : "CreateDevice", D3D_ErrorString (ret));
+ if (FAILED (ret)) {
+ sprintf (errmsg, "%s failed, %s\n", d3d_ex && D3DEX ? "CreateDeviceEx" : "CreateDevice", D3D_ErrorString (ret));
D3D_free ();
return errmsg;
}
sndbufsize = SND_MAX_BUFFER;
al_bufsize = size;
al_bigbuffer = xcalloc (al_bufsize, 1);
- al_dev = alcOpenDevice (sound_devices[currprefs.win32_soundcard].name);
+ al_dev = alcOpenDevice (sound_devices[currprefs.win32_soundcard].alname);
if (!al_dev)
goto error;
al_ctx = alcCreateContext (al_dev, NULL);
goto error;
write_log ("SOUND: %08X,CH=%d,FREQ=%d '%s' buffer %d (%d)\n",
- al_format, ch, freq, sound_devices[currprefs.win32_soundcard].name,
+ al_format, ch, freq, sound_devices[currprefs.win32_soundcard].alname,
sndbufsize, al_bufsize);
return 1;
memcpy (al_bigbuffer + al_offset, sndbuffer, sndbufsize);
al_offset += sndbufsize;
if (al_offset >= al_bufsize) {
+ ALuint tmp;
alGetSourcei (al_Source, AL_BUFFERS_PROCESSED, &v);
while (v == 0 && waiting_for_buffer < 0) {
sleep_millis (1);
alGetSourcei (al_Source, AL_BUFFERS_PROCESSED, &v);
}
- alSourceUnqueueBuffers (al_Source, 1, &al_Buffers[al_toggle]);
+ alSourceUnqueueBuffers (al_Source, 1, &tmp);
alGetError ();
// write_log (" %d %08x %08x %08x %d %d\n",
return TRUE;
}
+static void OpenALEnumerate (struct sound_device *sds, const char *pDeviceNames, const char *ppDefaultDevice, int skipdetect)
+{
+ struct sound_device *sd;
+ while (pDeviceNames && *pDeviceNames) {
+ ALCdevice *pDevice;
+ const char *devname;
+ int i, ok;
+ for (i = 0; i < MAX_SOUND_DEVICES; i++) {
+ sd = &sds[i];
+ if (sd->name == NULL)
+ break;
+ }
+ if (i >= MAX_SOUND_DEVICES)
+ return;
+ devname = pDeviceNames;
+ if (ppDefaultDevice)
+ devname = ppDefaultDevice;
+ ok = 0;
+ if (!skipdetect) {
+ pDevice = alcOpenDevice (devname);
+ if (pDevice) {
+ ALCcontext *context = alcCreateContext (pDevice, NULL);
+ if (context) {
+ ALint iMajorVersion = 0, iMinorVersion = 0;
+ alcMakeContextCurrent (context);
+ alcGetIntegerv (pDevice, ALC_MAJOR_VERSION, sizeof (ALint), &iMajorVersion);
+ alcGetIntegerv (pDevice, ALC_MINOR_VERSION, sizeof (ALint), &iMinorVersion);
+ if (iMajorVersion > 1 || (iMajorVersion == 1 && iMinorVersion > 0)) {
+ ok = 1;
+ }
+ }
+ alcMakeContextCurrent (NULL);
+ alcDestroyContext (context);
+ }
+ alcCloseDevice (pDevice);
+ } else {
+ ok = 1;
+ }
+ if (ok) {
+ sd->type = SOUND_DEVICE_AL;
+ if (ppDefaultDevice) {
+ char tmp[MAX_DPATH];
+ sprintf (tmp, "Default [%s]", devname);
+ sd->alname = my_strdup (ppDefaultDevice);
+ sd->name = my_strdup (tmp);
+ } else {
+ sd->alname = my_strdup (pDeviceNames);
+ sd->name = my_strdup (pDeviceNames);
+ }
+ }
+ if (ppDefaultDevice)
+ ppDefaultDevice = NULL;
+ else
+ pDeviceNames += strlen (pDeviceNames) + 1;
+ }
+}
+
+static int isdllversion (const char *name, int version, int revision)
+{
+ DWORD dwVersionHandle, dwFileVersionInfoSize;
+ LPVOID lpFileVersionData = NULL;
+ int ok = 0;
+
+ dwFileVersionInfoSize = GetFileVersionInfoSize (name, &dwVersionHandle);
+ if (dwFileVersionInfoSize) {
+ if (lpFileVersionData = xcalloc (1, dwFileVersionInfoSize)) {
+ if (GetFileVersionInfo (name, dwVersionHandle, dwFileVersionInfoSize, lpFileVersionData)) {
+ VS_FIXEDFILEINFO *vsFileInfo = NULL;
+ UINT uLen;
+ if (VerQueryValue (lpFileVersionData, TEXT("\\"), (void **)&vsFileInfo, &uLen)) {
+ if (vsFileInfo) {
+ write_log ("%s %d.%d.%d.%d\n", name,
+ HIWORD (vsFileInfo->dwProductVersionMS), LOWORD (vsFileInfo->dwProductVersionMS),
+ HIWORD (vsFileInfo->dwProductVersionLS), LOWORD (vsFileInfo->dwProductVersionLS));
+ if (vsFileInfo->dwProductVersionMS >= version * 65536 + revision)
+ ok = 1;
+ }
+ }
+ }
+ xfree (lpFileVersionData);
+ }
+ }
+ return ok;
+}
+
+
int enumerate_sound_devices (void)
{
if (!num_sound_devices) {
HMODULE l = NULL;
DirectSoundEnumerate ((LPDSENUMCALLBACK)DSEnumProc, sound_devices);
DirectSoundCaptureEnumerate ((LPDSENUMCALLBACK)DSEnumProc, record_devices);
- l = LoadLibrary ("openal32.dll");
- if (l != NULL) {
- FreeLibrary (l);
+ if (isdllversion ("openal32.dll", 6, 14)) {
if (alcIsExtensionPresent (NULL, "ALC_ENUMERATION_EXT")) {
- const ALchar* pDeviceNames = alcGetString (NULL, ALC_DEVICE_SPECIFIER);
const ALchar* ppDefaultDevice = alcGetString (NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
- while (pDeviceNames && *pDeviceNames) {
- struct sound_device *sd;
- ALCdevice *pDevice;
- int i;
- for (i = 0; i < MAX_SOUND_DEVICES; i++) {
- sd = &sound_devices[i];
- if (sd->name == NULL)
- break;
- }
- if (i >= MAX_SOUND_DEVICES)
- break;
- pDevice = alcOpenDevice (pDeviceNames);
- if (pDevice) {
- ALCcontext *context = alcCreateContext (pDevice, NULL);
- if (context) {
- ALint iMajorVersion = 0, iMinorVersion = 0;
- alcMakeContextCurrent (context);
- alcGetIntegerv (pDevice, ALC_MAJOR_VERSION, sizeof (ALint), &iMajorVersion);
- alcGetIntegerv (pDevice, ALC_MINOR_VERSION, sizeof (ALint), &iMinorVersion);
- if (iMajorVersion > 1 || (iMajorVersion == 1 && iMinorVersion > 0)) {
- sd->type = SOUND_DEVICE_AL;
- sd->name = my_strdup (pDeviceNames);
- }
- alcMakeContextCurrent (NULL);
- alcDestroyContext (context);
- }
- alcCloseDevice (pDevice);
- }
- pDeviceNames += strlen (pDeviceNames) + 1;
- }
+ const ALchar* pDeviceNames = alcGetString (NULL, ALC_DEVICE_SPECIFIER);
+ if (alcIsExtensionPresent (NULL, "ALC_ENUMERATE_ALL_EXT"))
+ pDeviceNames = alcGetString (NULL, ALC_ALL_DEVICES_SPECIFIER);
+ OpenALEnumerate (sound_devices, pDeviceNames, ppDefaultDevice, FALSE);
+ ppDefaultDevice = alcGetString (NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
+ pDeviceNames = alcGetString (NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
+ OpenALEnumerate (record_devices, pDeviceNames, ppDefaultDevice, TRUE);
}
}
for (num_sound_devices = 0; num_sound_devices < MAX_SOUND_DEVICES; num_sound_devices++) {
int y = (amigawin_rect.bottom - amigawin_rect.top) / 2;
mouseposx = oldx - x;
mouseposy = oldy - y;
- if (abs (mouseposx) < 50 && abs (mouseposy) < 50)
- return;
- mouseposx = 0;
- mouseposy = 0;
+ if (oldx >= 30000 || oldy >= 30000 || oldx <= -30000 || oldy <= -30000) {
+ mouseposx = mouseposy = 0;
+ oldx = oldy = 0;
+ } else {
+ if (abs (mouseposx) < 50 && abs (mouseposy) < 50)
+ return;
+ }
+ mouseposx = mouseposy = 0;
// if (oldx < amigawin_rect.left || oldy < amigawin_rect.top || oldx > amigawin_rect.right || oldy > amigawin_rect.bottom) {
if (oldx < 0 || oldy < 0 || oldx > amigawin_rect.right - amigawin_rect.left || oldy > amigawin_rect.bottom - amigawin_rect.top) {
write_log ("Mouse out of range: %dx%d (%dx%d %dx%d)\n", oldx, oldy,
if (rp_isactive ())
w3 = rp_getparent ();
#endif
- if (!(fw == w1 || fw == w2)) {
+ if (isfullscreen () > 0 || (!(fw == w1 || fw == w2))) {
if (SetForegroundWindow (w2) == FALSE) {
if (SetForegroundWindow (w1) == FALSE) {
if (w3 == NULL || SetForegroundWindow (w3) == FALSE) {
ClipCursor (&amigawin_rect);
}
showcursor = 1;
- setcursor (-1, -1);
+ setcursor (-30000, -30000);
}
inputdevice_acquire (TRUE);
} else {
if (ignore_messages_all)
return DefWindowProc (hWnd, message, wParam, lParam);
- if (hMainWnd == 0)
- hMainWnd = hWnd;
-
switch (message)
{
case WM_MOUSEWHEEL:
if (dinput_winmouse () >= 0) {
int val = ((short)HIWORD (wParam));
+ write_log ("dinput_winmouse=%d dinput_wheelbuttonstart=%d wheel=%d\n", dinput_winmouse(), dinput_wheelbuttonstart(), val);
setmousestate (dinput_winmouse (), 2, val, 0);
if (val < 0)
setmousebuttonstate (dinput_winmouse (), dinput_wheelbuttonstart () + 0, -1);
setmousebuttonstate (dinput_winmouse (), dinput_wheelbuttonstart () + 1, -1);
return TRUE;
}
+ //write_log ("dinput_winmouse() = %d\n", dinput_winmouse());
return 0;
case WM_MOUSEHWHEEL:
if (dinput_winmouse () >= 0) {
if (vsFileInfo &&
HIWORD(vsFileInfo->dwProductVersionMS) == UAEMAJOR
&& LOWORD(vsFileInfo->dwProductVersionMS) == UAEMINOR
- && (HIWORD(vsFileInfo->dwProductVersionLS) == UAESUBREV)) {
+ && (HIWORD(vsFileInfo->dwProductVersionLS) == UAESUBREV || HIWORD(vsFileInfo->dwProductVersionLS) == UAESUBREV - 1)) {
success = TRUE;
write_log ("Translation DLL '%s' loaded and enabled\n", dllbuf);
} else {
sortdisplays ();
write_log ("Display buffer mode = %d\n", ddforceram);
write_log ("Enumerating sound devices:\n");
- for (i = 0; i < enumerate_sound_devices (); i++) {
+ enumerate_sound_devices ();
+ for (i = 0; sound_devices[i].name; i++) {
write_log ("%d:%s: %s\n", i, sound_devices[i].type == SOUND_DEVICE_DS ? "DS" : "AL", sound_devices[i].name);
}
+ write_log ("Enumerating recording devices:\n");
+ for (i = 0; record_devices[i].name; i++) {
+ write_log ("%d:%s: %s\n", i, record_devices[i].type == SOUND_DEVICE_DS ? "DS" : "AL", record_devices[i].name);
+ }
write_log ("done\n");
memset (&devmode, 0, sizeof(devmode));
devmode.dmSize = sizeof (DEVMODE);
#define GETBDM(x) (((x) - ((x / 10000) * 10000)) / 100)
#define GETBDD(x) ((x) % 100)
-#define WINUAEBETA 3
+#define WINUAEBETA 4
#define WINUAEPUBLICBETA 1
-#define WINUAEDATE MAKEBD(2008, 8, 24)
+#define WINUAEDATE MAKEBD(2008, 8, 30)
#define WINUAEEXTRA ""
#define WINUAEREV ""
{
GUID guid;
char *name;
+ char *alname;
int type;
};
extern struct sound_device sound_devices[MAX_SOUND_DEVICES];
if (hStatusWnd) {
ShowWindow (hStatusWnd, SW_HIDE);
DestroyWindow (hStatusWnd);
+ hStatusWnd = 0;
}
if (hAmigaWnd) {
addnotifications (hAmigaWnd, TRUE);
if (hMainWnd) {
ShowWindow (hMainWnd, SW_HIDE);
DestroyWindow (hMainWnd);
+ hMainWnd = 0;
}
- hMainWnd = 0;
- hStatusWnd = 0;
}
if (hStatusWnd)
createstatuswindow ();
in_sizemove--;
+ } else {
+ w = nw;
+ h = nh;
+ x = nx;
+ y = ny;
}
GetWindowRect (hAmigaWnd, &amigawin_rect);
+ if (d3dfs || dxfs)
+ SetCursorPos (x + w / 2, y + h / 2);
write_log ("window already open\n");
return 1;
}
close_hwnds();
return 0;
}
+ if (hMainWnd == NULL)
+ hMainWnd = hAmigaWnd;
GetWindowRect (hAmigaWnd, &amigawin_rect);
+ if (dxfs || d3dfs)
+ SetCursorPos (x + w / 2, y + h / 2);
addnotifications (hAmigaWnd, FALSE);
if (hMainWnd != hAmigaWnd) {
ShowWindow (hMainWnd, SW_SHOWNORMAL);
+Beta 4: (final beta)
+
+- check openal32.dll version before using
+- accept 1.5.1 language DLL files (no GUI changes)
+- Catweasel: do not use direct access to read joyports if driver is
+ installed, caused conflicts with driver provided joystick/mouse
+ (note that I still don't care about CW until 64-bit compatible
+ drivers are released, if ever. Do not ask stupid questions.)
+- fixed D3D 8876086C error if display number in configuration file was
+ bigger than current number of displays
+
Beta 3:
- bsdsocket initialization rewritten, should be more reliable now
if uae rom is moved and/or other extra residents enabled
+ (I don't understand how it was supposed to work previously..)
- OpenAL sound mode problems fixed ("I hope")
-- Raw mouse/"name of mouse" mouse wheel support fixed (always been
- broken)
+- Raw mouse/"name of mouse" mouse wheel support fixed (has always
+ been broken)
Beta 2: