From 48984b84fc12233149f8aac32202cb2add399706 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 30 Aug 2008 12:09:17 +0300 Subject: [PATCH] imported winuaesrc1520b4.zip --- catweasel.c | 791 ++----------- include/catweasel.h | 1 + jit/compemu_raw_x86.c | 2 +- od-win32/ahidsound_new.c | 840 +++++--------- od-win32/ahidsoundx_new.c | 2080 ++++++++++++++++++++++++++++++++++ od-win32/dinput.c | 4 +- od-win32/direct3d.c | 25 +- od-win32/sounddep/sound.c | 135 ++- od-win32/win32.c | 30 +- od-win32/win32.h | 5 +- od-win32/win32gfx.c | 15 +- od-win32/winuaechangelog.txt | 16 +- 12 files changed, 2598 insertions(+), 1346 deletions(-) create mode 100755 od-win32/ahidsoundx_new.c diff --git a/catweasel.c b/catweasel.c index 5f10cc02..01a51ea8 100755 --- a/catweasel.c +++ b/catweasel.c @@ -24,9 +24,11 @@ static int mouse_x[2], mouse_y[2], mouse_px[2], mouse_py[2]; 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; @@ -35,18 +37,20 @@ int catweasel_isjoystick(void) } 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; @@ -56,7 +60,7 @@ static void sid_write(uae_u8 reg, uae_u8 val, int sidnum) 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; @@ -66,12 +70,12 @@ static uae_u8 sid_read(uae_u8 reg, int sidnum) 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); @@ -108,9 +112,9 @@ static uae_u8 get_buttons(void) 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]; @@ -121,7 +125,7 @@ int catweasel_read_mouse(int port, int *dx, int *dy, int *buttons) return 1; } -static void sid_reset(void) +static void sid_reset (void) { int i; for (i = 0; i < 0x19; i++) { @@ -130,13 +134,13 @@ static void sid_reset(void) } } -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) { @@ -181,7 +185,7 @@ void catweasel_hsync (void) { int i; - if (cwc.type < CATWEASEL_TYPE_MK3) + if (cwc.type < CATWEASEL_TYPE_MK3 || !cwc.direct_access) return; cwhsync--; if (cwhsync > 0) @@ -244,7 +248,7 @@ void catweasel_hsync (void) 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); @@ -256,7 +260,7 @@ int catweasel_read_keyboard (uae_u8 *keycode) { uae_u8 v; - if (!cwc.can_kb) + if (!cwc.can_kb || !cwc.direct_access) return 0; if (!currprefs.catweasel) return 0; @@ -309,15 +313,15 @@ void catweasel_do_bput (uaecptr addr, uae_u32 b) #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); @@ -325,7 +329,7 @@ static void cw_resetFPGA(void) 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); @@ -337,7 +341,7 @@ static int catweasel3_configure(void) return 1; } -static int catweasel4_configure(void) +static int catweasel4_configure (void) { struct zfile *f; time_t t; @@ -534,12 +538,15 @@ int catweasel_init(void) } 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); @@ -548,11 +555,15 @@ int catweasel_init(void) } 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; @@ -590,44 +601,53 @@ int catweasel_init(void) 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); @@ -642,12 +662,14 @@ fail: 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; @@ -678,11 +700,11 @@ int catweasel_detect (void) } 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; } @@ -690,677 +712,4 @@ int catweasel_detect (void) 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]<>(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 diff --git a/include/catweasel.h b/include/catweasel.h index 7ae6c458..acee5bd8 100755 --- a/include/catweasel.h +++ b/include/catweasel.h @@ -27,6 +27,7 @@ typedef struct catweasel_drive { 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 */ diff --git a/jit/compemu_raw_x86.c b/jit/compemu_raw_x86.c index 5639b7e5..e86cea6f 100755 --- a/jit/compemu_raw_x86.c +++ b/jit/compemu_raw_x86.c @@ -1973,7 +1973,7 @@ int EvalException (LPEXCEPTION_POINTERS blah, int n_except) 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) { diff --git a/od-win32/ahidsound_new.c b/od-win32/ahidsound_new.c index bb2ff3bb..168450f9 100755 --- a/od-win32/ahidsound_new.c +++ b/od-win32/ahidsound_new.c @@ -1,7 +1,7 @@ /* * UAE - The Un*x Amiga Emulator * - * DirectSound AHI 7.1 wrapper + * OpenAL AHI 7.1 wrapper * * Copyright 2008 Toni Wilen */ @@ -36,11 +36,8 @@ #include "ahidsound_new.h" #include "dxwrap.h" -#include -#include -#include -#include -#include +#include +#include #define AHI_STRUCT_VERSION 1 @@ -49,6 +46,7 @@ static int ahi_debug = 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) @@ -321,7 +319,7 @@ struct dssample { uae_u32 len; uae_u32 type; uae_u32 sampletype; - uae_u32 offset; + ALuint al_buffer[2]; }; struct chsample { @@ -332,24 +330,16 @@ 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 { @@ -371,17 +361,17 @@ 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]; @@ -460,8 +450,11 @@ static int sendsignal (struct DSAHI *dsahip) 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); @@ -475,7 +468,7 @@ static void setchannelevent (struct DSAHI *dsahip, struct dschannel *dc) 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)) @@ -523,172 +516,136 @@ static void setevent (struct DSAHI *dsahip) 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; } @@ -699,24 +656,17 @@ static int ds_reinit (struct DSAHI *dsahip) 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; @@ -725,96 +675,30 @@ static void ds_setvolume (struct DSAHI *dsahip, struct dschannel *dc) 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); @@ -855,7 +739,8 @@ STATIC_INLINE void makexch (struct DSAHI *dsahip, struct dschannel *dc, uae_u8 * } } -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; @@ -1011,10 +896,12 @@ static void copysampledata (struct DSAHI *dsahip, struct dschannel *dc, struct d 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; @@ -1074,228 +961,118 @@ static void dorecord (struct DSAHI *dsahip) 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++; } } @@ -1321,141 +1098,66 @@ void ahi_hsync (void) 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) @@ -1468,30 +1170,37 @@ 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; } @@ -1530,6 +1239,7 @@ static uae_u32 AHIsub_AllocAudio (TrapContext *ctx) if (!ds_init (dsahip)) return AHISF_ERROR; + dsahip->maxplaysamples = PLAYSAMPLES; dsahip->sounds = UAE_MAXSOUNDS; dsahip->channels = UAE_MAXCHANNELS; @@ -1552,10 +1262,13 @@ static uae_u32 AHIsub_AllocAudio (TrapContext *ctx) 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; @@ -1604,7 +1317,7 @@ static void AHIsub_FreeAudio (TrapContext *ctx) 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; @@ -1672,6 +1385,10 @@ static uae_u32 getattr2 (uae_u32 attribute, uae_u32 argument, uae_u32 def) return -1; case AHIDB_MaxRecordSamples: return RECORDSAMPLES; + case AHIDB_MaxPlaySamples: + if (def < dsahip->maxplaysamples) + def = dsahip->maxplaysamples; + return def; default: return def; } @@ -1684,9 +1401,10 @@ static uae_u32 AHIsub_GetAttr (TrapContext *ctx) 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); @@ -1706,7 +1424,7 @@ static uae_u32 AHIsub_HardwareControl (TrapContext *ctx) 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) @@ -1719,7 +1437,7 @@ static uae_u32 AHIsub_HardwareControl (TrapContext *ctx) case AHIC_Output: if (dsahip->output != argument) { dsahip->output = argument; - if (dsahip->DS) + if (dsahip->al_dev) ds_reinit (dsahip); } break; @@ -1853,16 +1571,15 @@ static uae_u32 AHIsub_SetSound (TrapContext *ctx) 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); @@ -1875,13 +1592,12 @@ static uae_u32 AHIsub_SetSound (TrapContext *ctx) 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; } @@ -1981,6 +1697,14 @@ static uae_u32 AHIsub_LoadSound (TrapContext *ctx) 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; } @@ -2065,7 +1789,7 @@ void init_ahi_v2 (void) { 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); } diff --git a/od-win32/ahidsoundx_new.c b/od-win32/ahidsoundx_new.c new file mode 100755 index 00000000..99e324d0 --- /dev/null +++ b/od-win32/ahidsoundx_new.c @@ -0,0 +1,2080 @@ +/* + * UAE - The Un*x Amiga Emulator + * + * DirectSound AHI 7.1 wrapper + * + * Copyright 2008 Toni Wilen + */ + +#include "sysconfig.h" + +#if defined(AHI) + +#include +#include + +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include + +#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 diff --git a/od-win32/dinput.c b/od-win32/dinput.c index 68324110..133326f8 100755 --- a/od-win32/dinput.c +++ b/od-win32/dinput.c @@ -365,7 +365,7 @@ static int initialize_catweasel(void) 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; @@ -392,7 +392,7 @@ static int initialize_catweasel(void) 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; diff --git a/od-win32/direct3d.c b/od-win32/direct3d.c index c2afc830..00eb0cb4 100755 --- a/od-win32/direct3d.c +++ b/od-win32/direct3d.c @@ -961,7 +961,7 @@ void D3D_free (void) 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; @@ -972,9 +972,6 @@ const char *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth) 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) { @@ -1010,11 +1007,19 @@ const char *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth) } } + 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; @@ -1057,13 +1062,13 @@ const char *D3D_init (HWND ahwnd, int w_w, int w_h, int t_w, int t_h, int depth) 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; } diff --git a/od-win32/sounddep/sound.c b/od-win32/sounddep/sound.c index 735711c8..4319d520 100755 --- a/od-win32/sounddep/sound.c +++ b/od-win32/sounddep/sound.c @@ -351,7 +351,7 @@ static int open_audio_al (int size) 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); @@ -381,7 +381,7 @@ static int open_audio_al (int size) 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; @@ -739,6 +739,7 @@ static void finish_sound_buffer_al (void) 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); @@ -748,7 +749,7 @@ static void finish_sound_buffer_al (void) 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", @@ -1101,48 +1102,108 @@ static BOOL CALLBACK DSEnumProc (LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDr 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++) { diff --git a/od-win32/win32.c b/od-win32/win32.c index 73752297..97f4df8d 100755 --- a/od-win32/win32.c +++ b/od-win32/win32.c @@ -320,10 +320,14 @@ static void setcursor (int oldx, int oldy) 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, @@ -487,7 +491,7 @@ void setmouseactive (int active) 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) { @@ -514,7 +518,7 @@ void setmouseactive (int active) ClipCursor (&amigawin_rect); } showcursor = 1; - setcursor (-1, -1); + setcursor (-30000, -30000); } inputdevice_acquire (TRUE); } else { @@ -676,9 +680,6 @@ static LRESULT CALLBACK AmigaWindowProc (HWND hWnd, UINT message, WPARAM wParam, if (ignore_messages_all) return DefWindowProc (hWnd, message, wParam, lParam); - if (hMainWnd == 0) - hMainWnd = hWnd; - switch (message) { @@ -768,6 +769,7 @@ static LRESULT CALLBACK AmigaWindowProc (HWND hWnd, UINT message, WPARAM wParam, 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); @@ -775,6 +777,7 @@ static LRESULT CALLBACK AmigaWindowProc (HWND hWnd, UINT message, WPARAM wParam, 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) { @@ -1609,7 +1612,7 @@ HMODULE language_load (WORD language) 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 { @@ -3226,9 +3229,14 @@ static int PASCAL WinMain2 (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR 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); diff --git a/od-win32/win32.h b/od-win32/win32.h index 5e202e32..121300de 100755 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -15,9 +15,9 @@ #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 "" @@ -146,6 +146,7 @@ struct sound_device { GUID guid; char *name; + char *alname; int type; }; extern struct sound_device sound_devices[MAX_SOUND_DEVICES]; diff --git a/od-win32/win32gfx.c b/od-win32/win32gfx.c index 0fd09e0e..b90ae473 100755 --- a/od-win32/win32gfx.c +++ b/od-win32/win32gfx.c @@ -819,6 +819,7 @@ static void close_hwnds (void) if (hStatusWnd) { ShowWindow (hStatusWnd, SW_HIDE); DestroyWindow (hStatusWnd); + hStatusWnd = 0; } if (hAmigaWnd) { addnotifications (hAmigaWnd, TRUE); @@ -837,9 +838,8 @@ static void close_hwnds (void) if (hMainWnd) { ShowWindow (hMainWnd, SW_HIDE); DestroyWindow (hMainWnd); + hMainWnd = 0; } - hMainWnd = 0; - hStatusWnd = 0; } @@ -1860,8 +1860,15 @@ static int create_windows_2 (void) 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; } @@ -1989,7 +1996,11 @@ static int create_windows_2 (void) 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); diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 389fa510..7832c7ab 100755 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,11 +1,23 @@ +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: -- 2.47.3