summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/asc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/asc.cpp')
-rw-r--r--src/devices/sound/asc.cpp112
1 files changed, 65 insertions, 47 deletions
diff --git a/src/devices/sound/asc.cpp b/src/devices/sound/asc.cpp
index 23ec35a2766..231e6b2357f 100644
--- a/src/devices/sound/asc.cpp
+++ b/src/devices/sound/asc.cpp
@@ -4,11 +4,15 @@
asc.c
- Apple Sound Chip (ASC) 344S0063
- Enhanced Apple Sound Chip (EASC) 343S1063
+ Apple Sound Chip (ASC) 344S0053 (original), 344S0063 (cost-reduced)
+ Enhanced Apple Sound Chip (EASC) 343S1036
Emulation by R. Belmont
+ The four-voice wavetable mode is unique to the first-generation ASC.
+ EASC (which was codenamed "Batman") and other ASC clones remove it
+ entirely.
+
Registers:
0x800: VERSION
0x801: MODE (0=inactive, 1=FIFO mode, 2=wavetable mode)
@@ -29,11 +33,15 @@
0x828: WAVETABLE 3 PHASE
0x82C: WAVETABLE 3 INCREMENT
+ TODO: rewrite this, we know so much more now and the "chip variant type" pattern must die.
+
***************************************************************************/
#include "emu.h"
#include "asc.h"
+#include "multibyte.h"
+
// device type definition
DEFINE_DEVICE_TYPE(ASC, asc_device, "asc", "ASC")
@@ -66,7 +74,7 @@ void asc_device::device_start()
memset(m_regs, 0, sizeof(m_regs));
- m_timer = timer_alloc(0, nullptr);
+ m_timer = timer_alloc(FUNC(asc_device::delayed_stream_update), this);
save_item(NAME(m_fifo_a_rdptr));
save_item(NAME(m_fifo_b_rdptr));
@@ -79,8 +87,6 @@ void asc_device::device_start()
save_item(NAME(m_regs));
save_item(NAME(m_phase));
save_item(NAME(m_incr));
-
- write_irq.resolve_safe();
}
@@ -104,10 +110,10 @@ void asc_device::device_reset()
}
//-------------------------------------------------
-// device_timer - called when our device timer expires
+// delayed_stream_update -
//-------------------------------------------------
-void asc_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(asc_device::delayed_stream_update)
{
m_stream->update();
}
@@ -205,8 +211,10 @@ void asc_device::sound_stream_update(sound_stream &stream, std::vector<read_stre
}
break;
- default: // V8/Sonora/Eagle/etc
- if (m_fifo_cap_a < 0x1ff)
+ // Sonora sets the 1/2 full flag continuously, ASC/EASC only does it when it happens
+ case asc_type::SONORA:
+ case asc_type::ARDBEG:
+ if (m_fifo_cap_a <= 0x200)
{
m_regs[R_FIFOSTAT-0x800] |= 1; // fifo A less than half full
@@ -214,23 +222,39 @@ void asc_device::sound_stream_update(sound_stream &stream, std::vector<read_stre
{
m_regs[R_FIFOSTAT-0x800] |= 2; // fifo A empty
}
- write_irq(ASSERT_LINE);
+ if (!(m_regs[0xf09 - 0x800] & 1))
+ {
+ write_irq(ASSERT_LINE);
+ }
}
- if (m_chip_type == asc_type::SONORA)
+ if (m_fifo_cap_b <= 0x200)
{
- if (m_fifo_cap_b < 0x1ff)
- {
- m_regs[R_FIFOSTAT-0x800] |= 4; // fifo B less than half full
+ m_regs[R_FIFOSTAT-0x800] |= 4; // fifo B less than half full
- if (m_fifo_cap_b == 0) // fifo B fully empty
- {
- m_regs[R_FIFOSTAT-0x800] |= 8; // fifo B empty
- }
+ if (m_fifo_cap_b == 0) // fifo B fully empty
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 8; // fifo B empty
+ }
+ if (!(m_regs[0xf29 - 0x800] & 1))
+ {
write_irq(ASSERT_LINE);
}
}
break;
+
+ default: // V8/Eagle/etc
+ if (m_fifo_cap_a < 0x1ff)
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 1; // fifo A less than half full
+
+ if (m_fifo_cap_a == 0) // fifo A fully empty
+ {
+ m_regs[R_FIFOSTAT-0x800] |= 2; // fifo A empty
+ }
+ write_irq(ASSERT_LINE);
+ }
+ break;
}
outL.put_int(i, smpll, 32768 / 64);
@@ -386,33 +410,17 @@ uint8_t asc_device::read(offs_t offset)
// WT inc/phase registers - rebuild from "live" copies"
if ((offset >= 0x810) && (offset <= 0x82f))
{
- m_regs[0x11] = m_phase[0]>>16;
- m_regs[0x12] = m_phase[0]>>8;
- m_regs[0x13] = m_phase[0];
- m_regs[0x15] = m_incr[0]>>16;
- m_regs[0x16] = m_incr[0]>>8;
- m_regs[0x17] = m_incr[0];
-
- m_regs[0x19] = m_phase[1]>>16;
- m_regs[0x1a] = m_phase[1]>>8;
- m_regs[0x1b] = m_phase[1];
- m_regs[0x1d] = m_incr[1]>>16;
- m_regs[0x1e] = m_incr[1]>>8;
- m_regs[0x1f] = m_incr[1];
-
- m_regs[0x21] = m_phase[2]>>16;
- m_regs[0x22] = m_phase[2]>>8;
- m_regs[0x23] = m_phase[2];
- m_regs[0x25] = m_incr[2]>>16;
- m_regs[0x26] = m_incr[2]>>8;
- m_regs[0x27] = m_incr[2];
-
- m_regs[0x29] = m_phase[3]>>16;
- m_regs[0x2a] = m_phase[3]>>8;
- m_regs[0x2b] = m_phase[3];
- m_regs[0x2d] = m_incr[3]>>16;
- m_regs[0x2e] = m_incr[3]>>8;
- m_regs[0x2f] = m_incr[3];
+ put_u24be(&m_regs[0x11], m_phase[0]);
+ put_u24be(&m_regs[0x15], m_incr[0]);
+
+ put_u24be(&m_regs[0x19], m_phase[1]);
+ put_u24be(&m_regs[0x1d], m_incr[1]);
+
+ put_u24be(&m_regs[0x21], m_phase[2]);
+ put_u24be(&m_regs[0x25], m_incr[2]);
+
+ put_u24be(&m_regs[0x29], m_phase[3]);
+ put_u24be(&m_regs[0x2d], m_incr[3]);
}
if (offset >= 0x1000)
@@ -438,11 +446,16 @@ void asc_device::write(offs_t offset, uint8_t data)
m_fifo_a[m_fifo_a_wrptr++] = data;
m_fifo_cap_a++;
- if (m_fifo_cap_a == 0x3ff)
+ if (m_fifo_cap_a == 0x400)
{
m_regs[R_FIFOSTAT-0x800] |= 2; // fifo A full
}
+ if (m_fifo_cap_a > 0x200)
+ {
+ m_regs[R_FIFOSTAT-0x800] &= ~1;
+ }
+
m_fifo_a_wrptr &= 0x3ff;
}
else
@@ -457,11 +470,16 @@ void asc_device::write(offs_t offset, uint8_t data)
m_fifo_b[m_fifo_b_wrptr++] = data;
m_fifo_cap_b++;
- if (m_fifo_cap_b == 0x3ff)
+ if (m_fifo_cap_b == 0x400)
{
m_regs[R_FIFOSTAT-0x800] |= 8; // fifo B full
}
+ if (m_fifo_cap_b > 0x200)
+ {
+ m_regs[R_FIFOSTAT-0x800] &= ~4;
+ }
+
m_fifo_b_wrptr &= 0x3ff;
}
else