summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/ks0164.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/ks0164.cpp')
-rw-r--r--src/devices/sound/ks0164.cpp144
1 files changed, 98 insertions, 46 deletions
diff --git a/src/devices/sound/ks0164.cpp b/src/devices/sound/ks0164.cpp
index 3431c49c0f7..fc45a2f74cb 100644
--- a/src/devices/sound/ks0164.cpp
+++ b/src/devices/sound/ks0164.cpp
@@ -9,6 +9,43 @@
DEFINE_DEVICE_TYPE(KS0164, ks0164_device, "ks0164", "Samsung KS0164 Wavetable Synthesizer")
+// Picked up from vrender0
+const u16 ks0164_device::sample_dec[0x100]=
+{
+ 0x8000, 0x8400, 0x8800, 0x8c00, 0x9000, 0x9400, 0x9800, 0x9c00,
+ 0xa000, 0xa400, 0xa800, 0xac00, 0xb000, 0xb400, 0xb800, 0xbc00,
+ 0x4000, 0x4400, 0x4800, 0x4c00, 0x5000, 0x5400, 0x5800, 0x5c00,
+ 0x6000, 0x6400, 0x6800, 0x6c00, 0x7000, 0x7400, 0x7800, 0x7c00,
+ 0xc000, 0xc200, 0xc400, 0xc600, 0xc800, 0xca00, 0xcc00, 0xce00,
+ 0xd000, 0xd200, 0xd400, 0xd600, 0xd800, 0xda00, 0xdc00, 0xde00,
+ 0x2000, 0x2200, 0x2400, 0x2600, 0x2800, 0x2a00, 0x2c00, 0x2e00,
+ 0x3000, 0x3200, 0x3400, 0x3600, 0x3800, 0x3a00, 0x3c00, 0x3e00,
+ 0xe000, 0xe100, 0xe200, 0xe300, 0xe400, 0xe500, 0xe600, 0xe700,
+ 0xe800, 0xe900, 0xea00, 0xeb00, 0xec00, 0xed00, 0xee00, 0xef00,
+ 0x1000, 0x1100, 0x1200, 0x1300, 0x1400, 0x1500, 0x1600, 0x1700,
+ 0x1800, 0x1900, 0x1a00, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00,
+ 0xf000, 0xf080, 0xf100, 0xf180, 0xf200, 0xf280, 0xf300, 0xf380,
+ 0xf400, 0xf480, 0xf500, 0xf580, 0xf600, 0xf680, 0xf700, 0xf780,
+ 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b00, 0x0b80,
+ 0x0c00, 0x0c80, 0x0d00, 0x0d80, 0x0e00, 0x0e80, 0x0f00, 0x0f80,
+ 0xf800, 0xf840, 0xf880, 0xf8c0, 0xf900, 0xf940, 0xf980, 0xf9c0,
+ 0xfa00, 0xfa40, 0xfa80, 0xfac0, 0xfb00, 0xfb40, 0xfb80, 0xfbc0,
+ 0x0400, 0x0440, 0x0480, 0x04c0, 0x0500, 0x0540, 0x0580, 0x05c0,
+ 0x0600, 0x0640, 0x0680, 0x06c0, 0x0700, 0x0740, 0x0780, 0x07c0,
+ 0xfc00, 0xfc20, 0xfc40, 0xfc60, 0xfc80, 0xfca0, 0xfcc0, 0xfce0,
+ 0xfd00, 0xfd20, 0xfd40, 0xfd60, 0xfd80, 0xfda0, 0xfdc0, 0xfde0,
+ 0x0200, 0x0220, 0x0240, 0x0260, 0x0280, 0x02a0, 0x02c0, 0x02e0,
+ 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0, 0x03e0,
+ 0xfe00, 0xfe10, 0xfe20, 0xfe30, 0xfe40, 0xfe50, 0xfe60, 0xfe70,
+ 0xfe80, 0xfe90, 0xfea0, 0xfeb0, 0xfec0, 0xfed0, 0xfee0, 0xfef0,
+ 0x0100, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170,
+ 0x0180, 0x0190, 0x01a0, 0x01b0, 0x01c0, 0x01d0, 0x01e0, 0x01f0,
+ 0x0000, 0x0008, 0x0010, 0x0018, 0x0020, 0x0028, 0x0030, 0x0038,
+ 0x0040, 0x0048, 0x0050, 0x0058, 0x0060, 0x0068, 0x0070, 0x0078,
+ 0xff80, 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8,
+ 0xffc0, 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8,
+};
+
ks0164_device::ks0164_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, KS0164, tag, owner, clock),
device_sound_interface(mconfig, *this),
@@ -17,7 +54,8 @@ ks0164_device::ks0164_device(const machine_config &mconfig, const char *tag, dev
m_midi_tx(*this),
m_mem_region(*this, DEVICE_SELF),
m_cpu(*this, "cpu"),
- m_mem_config("mem", ENDIANNESS_BIG, 16, 23)
+ m_mem_config("mem", ENDIANNESS_BIG, 16, 23),
+ m_notif_rom_space()
{
}
@@ -52,11 +90,19 @@ void ks0164_device::device_start()
space().install_rom(0, rend, ((1 << 23) - 1) ^ rmask, m_mem_region->base());
}
+ m_notif_rom_space = space().add_change_notifier([this] (read_or_write mode) {
+ // HACK: If something external changes the ROM space after initial load then reset the CPU because the program code also changed (used by BMkey ROM PCBs)
+ for(int voice = 0; voice < 0x20; voice++) {
+ // Disable all voices
+ m_sregs[voice][0] &= ~1;
+ }
+
+ m_cpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
+ });
+
m_stream = stream_alloc(0, 2, clock()/3/2/2/32);
space().cache(m_mem_cache);
- m_timer = timer_alloc(0);
-
- m_midi_tx.resolve_safe();
+ m_timer = timer_alloc(FUNC(ks0164_device::irq_timer_tick), this);
set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
set_rate(clock(), 542);
@@ -98,7 +144,7 @@ void ks0164_device::device_reset()
m_timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1));
}
-void ks0164_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(ks0164_device::irq_timer_tick)
{
m_timer_interrupt = true;
if(m_irqen_76 & 0x40)
@@ -175,7 +221,11 @@ void ks0164_device::mpu401_ctrl_w(u8 data)
u8 ks0164_device::mpu401_data_r()
{
- // logerror("mpu pop %02x\n", m_mpu_out);
+ if (!machine().side_effects_disabled())
+ {
+ m_mpu_status &= ~MPUS_TX_FULL;
+ // logerror("mpu pop %02x\n", m_mpu_out);
+ }
return m_mpu_out;
}
@@ -205,9 +255,12 @@ void ks0164_device::mpu401_istatus_w(u8 data)
u8 ks0164_device::mpu401_r()
{
- m_mpu_status &= ~MPUS_RX_FULL;
- m_cpu->set_input_line(11, CLEAR_LINE);
- // logerror("mpu_r %02x (%04x)\n", m_mpu_in, m_cpu->pc());
+ if (!machine().side_effects_disabled())
+ {
+ m_mpu_status &= ~MPUS_RX_FULL;
+ m_cpu->set_input_line(11, CLEAR_LINE);
+ // logerror("mpu_r %02x (%04x)\n", m_mpu_in, m_cpu->pc());
+ }
return m_mpu_in;
}
@@ -273,7 +326,7 @@ void ks0164_device::bank2_select_w(offs_t, u16 data, u16 mem_mask)
u16 ks0164_device::voice_r(offs_t offset)
{
m_stream->update();
- logerror("voice read %02x.%02x -> %04x (%04x)\n", m_voice_select & 0x1f, offset, m_sregs[m_voice_select & 0x1f][offset], m_cpu->pc());
+ // logerror("voice read %02x.%02x -> %04x (%04x)\n", m_voice_select & 0x1f, offset, m_sregs[m_voice_select & 0x1f][offset], m_cpu->pc());
return m_sregs[m_voice_select & 0x1f][offset];
}
@@ -282,18 +335,18 @@ void ks0164_device::voice_w(offs_t offset, u16 data, u16 mem_mask)
m_stream->update();
u16 old = m_sregs[m_voice_select & 0x1f][offset];
COMBINE_DATA(&m_sregs[m_voice_select & 0x1f][offset]);
- if(0)
- if(m_cpu->pc() < 0x5f94 || m_cpu->pc() > 0x5fc0)
- logerror("voice %02x.%02x = %04x @ %04x (%04x)\n", m_voice_select & 0x1f, offset, m_sregs[m_voice_select & 0x1f][offset], mem_mask, m_cpu->pc());
+ if(0 && m_sregs[m_voice_select & 0x1f][offset] != old && offset == 0)
+ logerror("voice %02x.%02x = %04x @ %04x (%04x)\n", m_voice_select & 0x1f, offset, m_sregs[m_voice_select & 0x1f][offset], mem_mask, m_cpu->pc());
if(offset == 0 && (data & 1) && !(old & 1))
- logerror("keyon %02x mode=%04x (%s %c %c %c) cur=%02x%04x.%04x loop=%02x%04x.%04x end=%02x%04x.%04x pitch=%02x.%03x 10=%02x/%02x:%02x/%02x 14=%03x/%03x:%03x/%03x 18=%04x/%04x c=%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ logerror("keyon %02x mode=%04x (%s %c %c %c %c) cur=%02x%04x.%04x loop=%02x%04x.%04x end=%02x%04x.%04x pitch=%x.%03x 10=%02x/%02x:%02x/%02x 14=%03x/%03x:%03x/%03x 18=%04x/%04x c=%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
m_voice_select,
m_sregs[m_voice_select & 0x1f][0x00],
- m_sregs[m_voice_select & 0x1f][0x00] & 0x8000 ? " 8" : "16",
- m_sregs[m_voice_select & 0x1f][0x00] & 0x0400 ? 'c' : 'l',
- m_sregs[m_voice_select & 0x1f][0x00] & 0x0008 ? '3' : '-',
+ m_sregs[m_voice_select & 0x1f][0x00] & 0x8000 ? " 8" : "16", // 8-bit/16-bit samples
+ m_sregs[m_voice_select & 0x1f][0x00] & 0x0400 ? 'c' : 'l', // compressed/linear samples
+ m_sregs[m_voice_select & 0x1f][0x00] & 0x0010 ? '4' : '-',
+ m_sregs[m_voice_select & 0x1f][0x00] & 0x0008 ? 'l' : '-', // loop
m_sregs[m_voice_select & 0x1f][0x00] & 0x0004 ? '2' : '-',
m_sregs[m_voice_select & 0x1f][0x01], // cur
@@ -308,8 +361,8 @@ void ks0164_device::voice_w(offs_t offset, u16 data, u16 mem_mask)
m_sregs[m_voice_select & 0x1f][0x0e],
m_sregs[m_voice_select & 0x1f][0x0f],
- m_sregs[m_voice_select & 0x1f][0x08] & 0x1f, // pitch
- m_sregs[m_voice_select & 0x1f][0x08] >> 5,
+ m_sregs[m_voice_select & 0x1f][0x08] & 0xf, // pitch
+ m_sregs[m_voice_select & 0x1f][0x08] >> 4,
m_sregs[m_voice_select & 0x1f][0x10] >> 9,
m_sregs[m_voice_select & 0x1f][0x12] >> 9,
@@ -388,7 +441,7 @@ u8 ks0164_device::voice_select_r()
void ks0164_device::voice_select_w(u8 data)
{
m_voice_select = data;
- logerror("voice_select = %02x (%04x)\n", m_voice_select, m_cpu->pc());
+ // logerror("voice_select = %02x (%04x)\n", m_voice_select, m_cpu->pc());
}
void ks0164_device::cpu_map(address_map &map)
@@ -415,16 +468,6 @@ void ks0164_device::cpu_map(address_map &map)
map(0xe000, 0xffff).ram();
}
-u16 ks0164_device::uncomp_8_16(u8 value)
-{
- int xp = value >> 5;
- s16 o = (0x10 | (value & 0xf)) << 10;
- o = o >> xp;
- if(value & 0x10)
- o = -o;
- return o;
-}
-
void ks0164_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
{
for(int sample = 0; sample != outputs[0].samples(); sample++) {
@@ -432,12 +475,7 @@ void ks0164_device::sound_stream_update(sound_stream &stream, std::vector<read_s
for(int voice = 0; voice < 0x20; voice++) {
u16 *regs = m_sregs[voice];
if(regs[0] & 0x0001) {
-
u64 current = (u64(regs[1]) << 32) | (u64(regs[2]) << 16) | regs[3];
-
- if(current & 0xc000000000)
- continue;
-
u32 adr = current >> 16;
s16 samp0, samp1;
switch(regs[0] & 0x8400) {
@@ -447,8 +485,8 @@ void ks0164_device::sound_stream_update(sound_stream &stream, std::vector<read_s
break;
case 0x8400: // 8 bits compressed
- samp0 = uncomp_8_16(m_mem_cache.read_byte(adr));
- samp1 = uncomp_8_16(m_mem_cache.read_byte(adr+1));
+ samp0 = sample_dec[m_mem_cache.read_byte(adr)];
+ samp1 = sample_dec[m_mem_cache.read_byte(adr+1)];
break;
default:
@@ -458,25 +496,39 @@ void ks0164_device::sound_stream_update(sound_stream &stream, std::vector<read_s
}
s16 samp = samp0 + (((samp1 - samp0) * (current & 0xffff)) >> 16);
- u32 step = 0x10000 | (regs[8] & ~0x1f);
- u32 shift = regs[8] & 0x1f;
- if(shift > 0x10)
- step >>= 0x20 - shift;
+ u32 step = 0x10000 | (regs[8] & ~0xf);
+ u32 shift = regs[8] & 0xf;
+ if(shift >= 0x8)
+ step >>= 0x10 - shift;
else if(shift)
step <<= shift;
current += step;
u64 end = (u64(regs[0xd]) << 32) | (u64(regs[0xe]) << 16) | regs[0xf];
if(current >= end) {
- // Is there a loop enabled flag?
- u64 loop = (u64(regs[9]) << 32) | (regs[0xa] << 16) | regs[0xb];
- current = current - end + loop;
+ if (regs[0] & 8) {
+ u64 loop = (u64(regs[9]) << 32) | (u64(regs[0xa]) << 16) | regs[0xb];
+ while(current >= end)
+ current = current - end + loop;
+ } else {
+ regs[0] = ~1;
+ regs[0xc] = 0;
+ regs[0x10] = regs[0x12] = regs[0x14] = regs[0x16] = 0;
+ }
}
regs[1] = current >> 32;
regs[2] = current >> 16;
regs[3] = current;
- suml += samp;
- sumr += samp;
+ suml += (s64(samp) * regs[0x12] * regs[0x16]) >> 32;
+ sumr += (s64(samp) * regs[0x10] * regs[0x14]) >> 32;
+
+ if(regs[0xc]) {
+ regs[0x10] += regs[0x11];
+ regs[0x12] += regs[0x13];
+ regs[0x14] += regs[0x15];
+ regs[0x16] += regs[0x17];
+ regs[0xc] --;
+ }
}
}
outputs[0].put_int(sample, suml, 32768 * 32);