2022-09-16 15:05:54 +00:00
|
|
|
/*
|
|
|
|
License: Zlib
|
|
|
|
see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details
|
|
|
|
|
|
|
|
Copyright holder(s): cam900
|
|
|
|
Konami K053260 core
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "k053260.hpp"
|
|
|
|
|
2023-04-02 05:32:47 +00:00
|
|
|
void k053260_core::tick(u32 cycle)
|
2022-09-16 15:05:54 +00:00
|
|
|
{
|
|
|
|
m_out[0] = m_out[1] = 0;
|
|
|
|
if (m_ctrl.sound_en())
|
|
|
|
{
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
2023-04-02 05:32:47 +00:00
|
|
|
m_voice[i].tick(cycle);
|
2022-09-16 15:05:54 +00:00
|
|
|
m_out[0] += m_voice[i].out(0);
|
|
|
|
m_out[1] += m_voice[i].out(1);
|
|
|
|
}
|
|
|
|
}
|
2023-04-02 05:32:47 +00:00
|
|
|
/*
|
2022-09-16 15:05:54 +00:00
|
|
|
// dac clock (YM3012 format)
|
|
|
|
u8 dac_clock = m_dac.clock();
|
|
|
|
if (bitfield(++dac_clock, 0, 4) == 0)
|
|
|
|
{
|
|
|
|
m_intf.write_int(m_dac.state());
|
|
|
|
u8 dac_state = m_dac.state();
|
|
|
|
if (bitfield(++dac_state, 0) == 0)
|
|
|
|
{
|
|
|
|
m_ym3012.tick(bitfield(dac_state, 1), m_out[bitfield(dac_state, 1) ^ 1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_dac.set_state(bitfield(dac_state, 0, 2));
|
|
|
|
}
|
|
|
|
m_dac.set_clock(bitfield(dac_clock, 0, 4));
|
2023-04-02 05:32:47 +00:00
|
|
|
*/
|
2022-09-16 15:05:54 +00:00
|
|
|
}
|
|
|
|
|
2023-04-02 05:32:47 +00:00
|
|
|
void k053260_core::voice_t::tick(u32 cycle)
|
2022-09-16 15:05:54 +00:00
|
|
|
{
|
|
|
|
if (m_enable && m_busy)
|
|
|
|
{
|
|
|
|
// update counter
|
2023-04-02 05:32:47 +00:00
|
|
|
m_counter += cycle;
|
|
|
|
if (m_counter >= 0x1000)
|
2022-09-16 15:05:54 +00:00
|
|
|
{
|
|
|
|
if (m_bitpos < 8)
|
|
|
|
{
|
|
|
|
m_bitpos += 8;
|
2023-04-02 15:34:09 +00:00
|
|
|
m_addr = m_reverse ? bitfield(m_addr - 1, 0, 21) : bitfield(m_addr + 1, 0, 21);
|
2022-09-16 15:05:54 +00:00
|
|
|
m_remain--;
|
2023-04-02 05:32:47 +00:00
|
|
|
if (m_remain < 0) // check end flag
|
|
|
|
{
|
|
|
|
if (m_loop)
|
|
|
|
{
|
|
|
|
m_addr = m_start;
|
|
|
|
m_remain = m_length;
|
|
|
|
m_output = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_busy = false;
|
|
|
|
}
|
|
|
|
}
|
2022-09-16 15:05:54 +00:00
|
|
|
}
|
2023-04-02 05:32:47 +00:00
|
|
|
m_data = m_host.m_intf.read_sample(bitfield(m_addr, 0, 21)); // fetch ROM
|
2022-09-16 15:05:54 +00:00
|
|
|
if (m_adpcm)
|
|
|
|
{
|
2023-04-02 05:32:47 +00:00
|
|
|
m_bitpos -= 4;
|
2023-04-02 15:34:09 +00:00
|
|
|
const u8 nibble = bitfield(m_data, m_reverse ? (~m_bitpos & 4) : (m_bitpos & 4), 4); // get nibble from ROM
|
2023-04-02 05:32:47 +00:00
|
|
|
if (nibble)
|
|
|
|
{
|
|
|
|
m_output += m_host.adpcm_lut(nibble);
|
|
|
|
}
|
2022-09-16 15:05:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_bitpos -= 8;
|
|
|
|
}
|
2023-04-02 05:34:10 +00:00
|
|
|
m_counter = (m_counter - 0x1000) + bitfield(m_pitch, 0, 12);
|
2022-09-16 15:05:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// calculate output
|
2023-04-02 05:32:47 +00:00
|
|
|
s32 output = (m_adpcm ? m_output : sign_ext<s32>(m_data, 8)) * s32(m_volume);
|
2022-09-16 15:05:54 +00:00
|
|
|
// use math for now; actually fomula unknown
|
2023-04-02 05:32:47 +00:00
|
|
|
m_out[0] = (output * m_host.pan_lut(m_pan, 0)) >> 7;
|
|
|
|
m_out[1] = (output * m_host.pan_lut(m_pan, 1)) >> 7;
|
2022-09-16 15:05:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_out[0] = m_out[1] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 k053260_core::read(u8 address)
|
|
|
|
{
|
|
|
|
address &= 0x3f; // 6 bit for CPU read
|
|
|
|
|
|
|
|
switch (address)
|
|
|
|
{
|
|
|
|
case 0x0:
|
|
|
|
case 0x1: // Answer from host
|
|
|
|
return m_host2snd[address & 1];
|
|
|
|
break;
|
|
|
|
case 0x29: // Voice playing status
|
|
|
|
return (m_voice[0].busy() ? 0x1 : 0x0) | (m_voice[1].busy() ? 0x2 : 0x0) |
|
|
|
|
(m_voice[2].busy() ? 0x4 : 0x0) | (m_voice[3].busy() ? 0x8 : 0x0);
|
|
|
|
case 0x2e: // ROM readback
|
|
|
|
{
|
|
|
|
if (!m_ctrl.rom_read())
|
|
|
|
{
|
|
|
|
return 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
const u32 rom_addr = m_voice[0].start() + m_voice[0].length();
|
|
|
|
m_voice[0].length_inc();
|
|
|
|
return m_intf.read_sample(rom_addr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0xff;
|
|
|
|
}
|
|
|
|
|
|
|
|
void k053260_core::write(u8 address, u8 data)
|
|
|
|
{
|
|
|
|
address &= 0x3f; // 6 bit for CPU write
|
|
|
|
|
|
|
|
switch (address)
|
|
|
|
{
|
|
|
|
case 0x2:
|
|
|
|
case 0x3: // Reply to host
|
|
|
|
m_snd2host[address & 1] = data;
|
|
|
|
break;
|
|
|
|
case 0x08:
|
|
|
|
case 0x09:
|
|
|
|
case 0x0a:
|
|
|
|
case 0x0b:
|
|
|
|
case 0x0c:
|
|
|
|
case 0x0d:
|
|
|
|
case 0x0e:
|
|
|
|
case 0x0f: // voice 0
|
|
|
|
case 0x10:
|
|
|
|
case 0x11:
|
|
|
|
case 0x12:
|
|
|
|
case 0x13:
|
|
|
|
case 0x14:
|
|
|
|
case 0x15:
|
|
|
|
case 0x16:
|
|
|
|
case 0x17: // voice 1
|
|
|
|
case 0x18:
|
|
|
|
case 0x19:
|
|
|
|
case 0x1a:
|
|
|
|
case 0x1b:
|
|
|
|
case 0x1c:
|
|
|
|
case 0x1d:
|
|
|
|
case 0x1e:
|
|
|
|
case 0x1f: // voice 2
|
|
|
|
case 0x20:
|
|
|
|
case 0x21:
|
|
|
|
case 0x22:
|
|
|
|
case 0x23:
|
|
|
|
case 0x24:
|
|
|
|
case 0x25:
|
|
|
|
case 0x26:
|
|
|
|
case 0x27: // voice 3
|
|
|
|
m_voice[bitfield(address - 0x8, 3, 2)].write(bitfield(address, 0, 3), data);
|
|
|
|
break;
|
|
|
|
case 0x28: // keyon/off toggle
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
2023-04-02 15:34:09 +00:00
|
|
|
m_voice[i].set_reverse(bitfield(data, 4 + i));
|
2022-09-16 15:05:54 +00:00
|
|
|
if (bitfield(data, i) && (!m_voice[i].enable()))
|
|
|
|
{ // rising edge (keyon)
|
|
|
|
m_voice[i].keyon();
|
|
|
|
}
|
|
|
|
else if ((!bitfield(data, i)) && m_voice[i].enable())
|
|
|
|
{ // falling edge (keyoff)
|
|
|
|
m_voice[i].keyoff();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x2a: // loop/adpcm flag
|
|
|
|
for (int i = 0; i < 4; i++)
|
|
|
|
{
|
|
|
|
m_voice[i].set_loop(bitfield(data, i));
|
|
|
|
m_voice[i].set_adpcm(bitfield(data, i + 4));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x2c:
|
|
|
|
m_voice[0].set_pan(bitfield(data, 0, 3));
|
|
|
|
m_voice[1].set_pan(bitfield(data, 3, 3));
|
|
|
|
break;
|
|
|
|
case 0x2d:
|
|
|
|
m_voice[2].set_pan(bitfield(data, 0, 3));
|
|
|
|
m_voice[3].set_pan(bitfield(data, 3, 3));
|
|
|
|
break;
|
|
|
|
case 0x2f: m_ctrl.write(data); break;
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_reg[address] = data;
|
|
|
|
}
|
|
|
|
|
|
|
|
// write registers on each voices
|
|
|
|
void k053260_core::voice_t::write(u8 address, u8 data)
|
|
|
|
{
|
|
|
|
switch (address)
|
|
|
|
{
|
|
|
|
case 0: // pitch LSB
|
|
|
|
m_pitch = (m_pitch & ~0x00ff) | data;
|
|
|
|
break;
|
|
|
|
case 1: // pitch MSB
|
|
|
|
m_pitch = (m_pitch & ~0x0f00) | (u16(bitfield(data, 0, 4)) << 8);
|
|
|
|
break;
|
|
|
|
case 2: // source length LSB
|
|
|
|
m_length = (m_length & ~0x000ff) | data;
|
|
|
|
break;
|
|
|
|
case 3: // source length MSB
|
|
|
|
m_length = (m_length & ~0x0ff00) | (u16(data) << 8);
|
|
|
|
break;
|
|
|
|
case 4: // start address bit 0-7
|
|
|
|
m_start = (m_start & ~0x0000ff) | data;
|
|
|
|
break;
|
|
|
|
case 5: // start address bit 8-15
|
|
|
|
m_start = (m_start & ~0x00ff00) | (u32(data) << 8);
|
|
|
|
break;
|
|
|
|
case 6: // start address bit 16-20
|
2023-07-31 11:06:07 +00:00
|
|
|
m_start = (m_start & ~0x1f0000) | (u32(bitfield(data, 0, 5)) << 16);
|
2022-09-16 15:05:54 +00:00
|
|
|
break;
|
|
|
|
case 7: // volume
|
|
|
|
m_volume = bitfield(data, 0, 7);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// key on trigger
|
|
|
|
void k053260_core::voice_t::keyon()
|
|
|
|
{
|
|
|
|
m_enable = m_busy = 1;
|
|
|
|
m_counter = bitfield(m_pitch, 0, 12);
|
|
|
|
m_addr = m_start;
|
|
|
|
m_remain = m_length;
|
|
|
|
m_bitpos = 4;
|
2023-04-02 05:32:47 +00:00
|
|
|
m_data = 0;
|
|
|
|
m_output = 0;
|
2023-04-02 05:55:10 +00:00
|
|
|
std::fill_n(m_out, 2, 0);
|
2022-09-16 15:05:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// key off trigger
|
|
|
|
void k053260_core::voice_t::keyoff() { m_enable = m_busy = 0; }
|
|
|
|
|
|
|
|
// reset chip
|
|
|
|
void k053260_core::reset()
|
|
|
|
{
|
|
|
|
for (auto &elem : m_voice)
|
|
|
|
{
|
|
|
|
elem.reset();
|
|
|
|
}
|
|
|
|
|
2023-04-02 05:32:47 +00:00
|
|
|
//m_intf.write_int(0);
|
2022-09-16 15:05:54 +00:00
|
|
|
|
2023-04-02 05:55:10 +00:00
|
|
|
std::fill_n(m_host2snd, 2, 0);
|
|
|
|
std::fill_n(m_snd2host, 2, 0);
|
2022-09-16 15:05:54 +00:00
|
|
|
m_ctrl.reset();
|
2023-04-02 05:32:47 +00:00
|
|
|
//m_dac.reset();
|
2022-09-16 15:05:54 +00:00
|
|
|
|
2023-04-02 05:55:10 +00:00
|
|
|
std::fill_n(m_reg, 64, 0);
|
|
|
|
std::fill_n(m_out, 2, 0);
|
2022-09-16 15:05:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// reset voice
|
|
|
|
void k053260_core::voice_t::reset()
|
|
|
|
{
|
2023-04-02 05:32:47 +00:00
|
|
|
m_enable = 0;
|
|
|
|
m_busy = 0;
|
|
|
|
m_loop = 0;
|
|
|
|
m_adpcm = 0;
|
|
|
|
m_pitch = 0;
|
2023-04-02 15:34:09 +00:00
|
|
|
m_reverse = 0;
|
2023-04-02 05:32:47 +00:00
|
|
|
m_start = 0;
|
|
|
|
m_length = 0;
|
|
|
|
m_volume = 0;
|
|
|
|
m_pan = 4;
|
|
|
|
m_counter = 0;
|
|
|
|
m_addr = 0;
|
|
|
|
m_remain = 0;
|
|
|
|
m_bitpos = 4;
|
|
|
|
m_data = 0;
|
|
|
|
m_output = 0;
|
2022-09-16 15:05:54 +00:00
|
|
|
m_out[0] = m_out[1] = 0;
|
|
|
|
}
|