ASC: sync with MESS improvements (no whatsnew)

This commit is contained in:
R. Belmont 2010-10-17 20:15:40 +00:00
parent 1d4ea432e9
commit 0d8e40acb6
2 changed files with 90 additions and 97 deletions

View File

@ -4,7 +4,7 @@
Apple Sound Chip (ASC) 344S0063 Apple Sound Chip (ASC) 344S0063
Enhanced Apple Sound Chip (EASC) 343S1063 Enhanced Apple Sound Chip (EASC) 343S1063
Emulation by R. Belmont Emulation by R. Belmont
Registers: Registers:
@ -18,8 +18,8 @@
0x807: CLOCK RATE (0 = Mac 22257 Hz, 1 = undefined, 2 = 22050 Hz, 3 = 44100 Hz) 0x807: CLOCK RATE (0 = Mac 22257 Hz, 1 = undefined, 2 = 22050 Hz, 3 = 44100 Hz)
0x80a: PLAY REC A 0x80a: PLAY REC A
0x80f: TEST (bits 6-7 = digital test, bits 4-5 = analog test) 0x80f: TEST (bits 6-7 = digital test, bits 4-5 = analog test)
0x810: WAVETABLE 0 PHASE (big-endian 8.16 fixed-point, only 24 bits valid) 0x810: WAVETABLE 0 PHASE (big-endian 9.15 fixed-point, only 24 bits valid)
0x814: WAVETABLE 0 INCREMENT (big-endian 8.16 fixed-point, only 24 bits valid) 0x814: WAVETABLE 0 INCREMENT (big-endian 9.15 fixed-point, only 24 bits valid)
0x818: WAVETABLE 1 PHASE 0x818: WAVETABLE 1 PHASE
0x81C: WAVETABLE 1 INCREMENT 0x81C: WAVETABLE 1 INCREMENT
0x820: WAVETABLE 2 PHASE 0x820: WAVETABLE 2 PHASE
@ -141,11 +141,10 @@ void asc_device::device_reset()
memset(m_fifo_b, 0, sizeof(m_fifo_b)); memset(m_fifo_b, 0, sizeof(m_fifo_b));
memset(m_phase, 0, sizeof(m_phase)); memset(m_phase, 0, sizeof(m_phase));
memset(m_incr, 0, sizeof(m_incr)); memset(m_incr, 0, sizeof(m_incr));
memset(m_fifo_a_wrhalf, 0, sizeof(m_fifo_a_wrhalf));
memset(m_fifo_b_wrhalf, 0, sizeof(m_fifo_b_wrhalf));
m_fifo_a_rdptr = m_fifo_b_rdptr = 0; m_fifo_a_rdptr = m_fifo_b_rdptr = 0;
m_fifo_a_wrptr = m_fifo_b_wrptr = 0; m_fifo_a_wrptr = m_fifo_b_wrptr = 0;
m_fifo_cap_a = m_fifo_cap_b = 0;
} }
//------------------------------------------------- //-------------------------------------------------
@ -161,7 +160,7 @@ STREAM_UPDATE( asc_device::static_stream_generate )
void asc_device::stream_generate(stream_sample_t **inputs, stream_sample_t **outputs, int samples) void asc_device::stream_generate(stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{ {
stream_sample_t *outL, *outR; stream_sample_t *outL, *outR;
int i, ch, halt = 0; int i, ch;
static UINT32 wtoffs[2] = { 0, 0x200 }; static UINT32 wtoffs[2] = { 0, 0x200 };
outL = outputs[0]; outL = outputs[0];
@ -177,62 +176,70 @@ void asc_device::stream_generate(stream_sample_t **inputs, stream_sample_t **out
break; break;
case 1: // FIFO mode case 1: // FIFO mode
if ((m_fifo_a_rdptr == 0) && (!m_fifo_a_wrhalf[0]))
{
halt = 1;
}
else if ((m_fifo_a_rdptr == 0x200) && (!m_fifo_a_wrhalf[1]))
{
halt = 1;
}
for (i = 0; i < samples; i++) for (i = 0; i < samples; i++)
{ {
INT8 smpll, smplr; INT8 smpll, smplr;
if (m_fifo_a_rdptr < 0x200) smpll = (INT8)m_fifo_a[m_fifo_a_rdptr]^0x80;
smplr = (INT8)m_fifo_b[m_fifo_b_rdptr]^0x80;
// don't advance the sample pointer if there are no more samples
if (m_fifo_cap_a)
{ {
m_fifo_a_wrhalf[0] = 0; m_fifo_a_rdptr++;
m_fifo_b_wrhalf[0] = 0; m_fifo_a_rdptr &= 0x3ff;
m_fifo_cap_a--;
} }
else
if (m_fifo_cap_b)
{ {
m_fifo_a_wrhalf[1] = 0; m_fifo_b_rdptr++;
m_fifo_b_wrhalf[1] = 0; m_fifo_b_rdptr &= 0x3ff;
m_fifo_cap_b--;
} }
smpll = (INT8)m_fifo_a[m_fifo_a_rdptr++]^0x80; if ((m_fifo_cap_a) || (m_fifo_cap_b))
smplr = (INT8)m_fifo_b[m_fifo_b_rdptr++]^0x80;
if ((m_fifo_a_rdptr == 0x200) || (m_fifo_a_rdptr == 0x400))
{ {
m_regs[R_FIFOSTAT-0x800] |= 1; // fifo A half-empty switch (m_chip_type)
if (m_irq_cb)
{ {
m_irq_cb(this, 1); case ASC_TYPE_SONORA:
if (m_fifo_cap_a <= 0x200)
{
m_regs[R_FIFOSTAT-0x800] |= 0x4; // fifo less than half full
m_regs[R_FIFOSTAT-0x800] |= 0x8; // just pass the damn test
if (m_irq_cb)
{
m_irq_cb(this, 1);
}
}
break;
default:
if (m_fifo_cap_a <= 0x200)
{
m_regs[R_FIFOSTAT-0x800] |= 1; // fifo A half-empty
if (m_irq_cb)
{
m_irq_cb(this, 1);
}
}
// don't update for non-(E)ASC
if (m_fifo_cap_b <= 0x200)
{
m_regs[R_FIFOSTAT-0x800] |= 4; // fifo B half-empty
if (m_irq_cb)
{
m_irq_cb(this, 1);
}
}
break;
} }
} }
if ((m_fifo_b_rdptr == 0x200) || (m_fifo_b_rdptr == 0x400))
{
m_regs[R_FIFOSTAT-0x800] |= 4; // fifo B half-empty
if (m_irq_cb)
{
m_irq_cb(this, 1);
}
}
m_fifo_a_rdptr &= 0x3ff;
m_fifo_b_rdptr &= 0x3ff;
outL[i] = smpll * 64; outL[i] = smpll * 64;
outR[i] = smplr * 64; outR[i] = smplr * 64;
} }
if (halt)
{
// m_regs[R_MODE-0x800] = 0;
}
break; break;
case 2: // wavetable mode case 2: // wavetable mode
@ -242,7 +249,7 @@ void asc_device::stream_generate(stream_sample_t **inputs, stream_sample_t **out
INT8 smpl; INT8 smpl;
mixL = mixR = 0; mixL = mixR = 0;
// update channel pointers // update channel pointers
for (ch = 0; ch < 4; ch++) for (ch = 0; ch < 4; ch++)
{ {
@ -250,11 +257,11 @@ void asc_device::stream_generate(stream_sample_t **inputs, stream_sample_t **out
if (ch < 2) if (ch < 2)
{ {
smpl = (INT8)m_fifo_a[((m_phase[ch]>>16)&0x1ff) + wtoffs[ch&1]]; smpl = (INT8)m_fifo_a[((m_phase[ch]>>15)&0x1ff) + wtoffs[ch&1]];
} }
else else
{ {
smpl = (INT8)m_fifo_b[((m_phase[ch]>>16)&0x1ff) + wtoffs[ch&1]]; smpl = (INT8)m_fifo_b[((m_phase[ch]>>15)&0x1ff) + wtoffs[ch&1]];
} }
smpl ^= 0x80; smpl ^= 0x80;
@ -277,7 +284,7 @@ UINT8 asc_device::read(UINT16 offset)
{ {
UINT8 rv; UINT8 rv;
// printf("ASC: read at %x\n", offset); // printf("ASC: read at %x\n", offset);
// not sure what actually happens when the CPU reads the FIFO... // not sure what actually happens when the CPU reads the FIFO...
if (offset < 0x400) if (offset < 0x400)
@ -409,30 +416,18 @@ UINT8 asc_device::read(UINT16 offset)
void asc_device::write(UINT16 offset, UINT8 data) void asc_device::write(UINT16 offset, UINT8 data)
{ {
// printf("ASC: write %02x to %x\n", data, offset); // printf("ASC: write %02x to %x\n", data, offset);
if (offset < 0x400) if (offset < 0x400)
{ {
if (m_regs[R_MODE-0x800] == 1) if (m_regs[R_MODE-0x800] == 1)
{ {
if (m_fifo_a_wrptr < 0x400)
{
m_fifo_a_wrhalf[0] = 1;
}
else
{
m_fifo_a_wrhalf[1] = 1;
}
m_fifo_a[m_fifo_a_wrptr++] = data; m_fifo_a[m_fifo_a_wrptr++] = data;
m_fifo_cap_a++;
if ((m_fifo_a_wrptr == 0x200) || (m_fifo_a_wrptr == 0x400)) if (m_fifo_cap_a == 0x800)
{ {
m_regs[R_FIFOSTAT-0x800] |= 2; // fifo A half-full m_regs[R_FIFOSTAT-0x800] |= 2; // fifo A full
if (m_irq_cb)
{
m_irq_cb(this, 1);
}
} }
m_fifo_a_wrptr &= 0x3ff; m_fifo_a_wrptr &= 0x3ff;
@ -446,28 +441,16 @@ void asc_device::write(UINT16 offset, UINT8 data)
{ {
if (m_regs[R_MODE-0x800] == 1) if (m_regs[R_MODE-0x800] == 1)
{ {
if (m_fifo_b_wrptr < 0x400)
{
m_fifo_b_wrhalf[0] = 1;
}
else
{
m_fifo_b_wrhalf[1] = 1;
}
m_fifo_b[m_fifo_b_wrptr++] = data; m_fifo_b[m_fifo_b_wrptr++] = data;
m_fifo_cap_b++;
if ((m_fifo_a_wrptr == 0x200) || (m_fifo_a_wrptr == 0x400)) if (m_fifo_cap_b == 0x800)
{ {
m_regs[R_FIFOSTAT-0x800] |= 8; // fifo B half-full m_regs[R_FIFOSTAT-0x800] |= 8; // fifo B full
if (m_irq_cb)
{
m_irq_cb(this, 1);
}
} }
m_fifo_b_wrptr &= 0x3ff; m_fifo_b_wrptr &= 0x3ff;
} }
else else
{ {
m_fifo_b[offset-0x400] = data; m_fifo_b[offset-0x400] = data;
@ -475,7 +458,7 @@ void asc_device::write(UINT16 offset, UINT8 data)
} }
else else
{ {
// printf("ASC: %02x to %x (was %x)\n", data, offset, m_regs[offset-0x800]); // printf("ASC: %02x to %x (was %x)\n", data, offset, m_regs[offset-0x800]);
stream_update(m_stream); stream_update(m_stream);
switch (offset) switch (offset)
@ -483,18 +466,28 @@ void asc_device::write(UINT16 offset, UINT8 data)
case R_MODE: case R_MODE:
data &= 3; // only bits 0 and 1 can be written data &= 3; // only bits 0 and 1 can be written
memset(m_fifo_a_wrhalf, 0, sizeof(m_fifo_a_wrhalf)); if (data != m_regs[R_MODE-0x800])
memset(m_fifo_b_wrhalf, 0, sizeof(m_fifo_b_wrhalf)); {
m_fifo_a_rdptr = m_fifo_b_rdptr = 0;
m_fifo_a_wrptr = m_fifo_b_wrptr = 0;
m_fifo_cap_a = m_fifo_cap_b = 0;
}
break;
m_fifo_a_rdptr = m_fifo_b_rdptr = 0; case R_FIFOMODE:
m_fifo_a_wrptr = m_fifo_b_wrptr = 0; if (data & 0x80)
{
m_fifo_a_rdptr = m_fifo_b_rdptr = 0;
m_fifo_a_wrptr = m_fifo_b_wrptr = 0;
m_fifo_cap_a = m_fifo_cap_b = 0;
}
break; break;
case R_WTCONTROL: case R_WTCONTROL:
// printf("One-shot wavetable %02x\n", data); // printf("One-shot wavetable %02x\n", data);
break; break;
case 0x811: case 0x811:
m_phase[0] &= 0x00ffff; m_phase[0] &= 0x00ffff;
m_phase[0] |= data<<16; m_phase[0] |= data<<16;
break; break;
@ -509,7 +502,7 @@ void asc_device::write(UINT16 offset, UINT8 data)
m_phase[0] |= data; m_phase[0] |= data;
break; break;
case 0x815: case 0x815:
m_incr[0] &= 0x00ffff; m_incr[0] &= 0x00ffff;
m_incr[0] |= data<<16; m_incr[0] |= data<<16;
break; break;
@ -524,7 +517,7 @@ void asc_device::write(UINT16 offset, UINT8 data)
m_incr[0] |= data; m_incr[0] |= data;
break; break;
case 0x819: case 0x819:
m_phase[1] &= 0x00ffff; m_phase[1] &= 0x00ffff;
m_phase[1] |= data<<16; m_phase[1] |= data<<16;
break; break;
@ -539,7 +532,7 @@ void asc_device::write(UINT16 offset, UINT8 data)
m_phase[1] |= data; m_phase[1] |= data;
break; break;
case 0x81d: case 0x81d:
m_incr[1] &= 0x00ffff; m_incr[1] &= 0x00ffff;
m_incr[1] |= data<<16; m_incr[1] |= data<<16;
break; break;
@ -554,7 +547,7 @@ void asc_device::write(UINT16 offset, UINT8 data)
m_incr[1] |= data; m_incr[1] |= data;
break; break;
case 0x821: case 0x821:
m_phase[2] &= 0x00ffff; m_phase[2] &= 0x00ffff;
m_phase[2] |= data<<16; m_phase[2] |= data<<16;
break; break;
@ -569,7 +562,7 @@ void asc_device::write(UINT16 offset, UINT8 data)
m_phase[2] |= data; m_phase[2] |= data;
break; break;
case 0x825: case 0x825:
m_incr[2] &= 0x00ffff; m_incr[2] &= 0x00ffff;
m_incr[2] |= data<<16; m_incr[2] |= data<<16;
break; break;
@ -584,7 +577,7 @@ void asc_device::write(UINT16 offset, UINT8 data)
m_incr[2] |= data; m_incr[2] |= data;
break; break;
case 0x829: case 0x829:
m_phase[3] &= 0x00ffff; m_phase[3] &= 0x00ffff;
m_phase[3] |= data<<16; m_phase[3] |= data<<16;
break; break;
@ -599,7 +592,7 @@ void asc_device::write(UINT16 offset, UINT8 data)
m_phase[3] |= data; m_phase[3] |= data;
break; break;
case 0x82d: case 0x82d:
m_incr[3] &= 0x00ffff; m_incr[3] &= 0x00ffff;
m_incr[3] |= data<<16; m_incr[3] |= data<<16;
break; break;

View File

@ -138,13 +138,13 @@ protected:
UINT8 m_fifo_a[0x400]; UINT8 m_fifo_a[0x400];
UINT8 m_fifo_b[0x400]; UINT8 m_fifo_b[0x400];
UINT8 m_regs[0x100]; UINT8 m_regs[0x800];
UINT32 m_phase[4], m_incr[4]; UINT32 m_phase[4], m_incr[4];
int m_fifo_a_rdptr, m_fifo_b_rdptr; int m_fifo_a_rdptr, m_fifo_b_rdptr;
int m_fifo_a_wrptr, m_fifo_b_wrptr; int m_fifo_a_wrptr, m_fifo_b_wrptr;
int m_fifo_a_wrhalf[2], m_fifo_b_wrhalf[2]; int m_fifo_cap_a, m_fifo_cap_b;
}; };