simpsons, k053260: Fix the pan, fix the interrupts, fix the general volume [O. Galibert, P. Bennett]

This commit is contained in:
Olivier Galibert 2020-05-01 19:26:47 +02:00
parent a97d097b3b
commit 8720db13ca
5 changed files with 80 additions and 29 deletions

View File

@ -59,12 +59,28 @@
#define LOG 0
static constexpr int CLOCKS_PER_SAMPLE = 32;
static constexpr int CLOCKS_PER_SAMPLE = 64;
// device type definition
DEFINE_DEVICE_TYPE(K053260, k053260_device, "k053260", "K053260 KDSC")
;
// Pan multipliers. Set according to integer angles in degrees, amusingly.
// Exact precision hard to know, the floating point-ish output format makes
// comparisons iffy. So we used a 1.16 format.
const int k053260_device::pan_mul[8][2] = {
{ 0, 0 }, // No sound for pan 0
{ 65536, 0 }, // 0 degrees
{ 59870, 26656 }, // 24 degrees
{ 53684, 37950 }, // 35 degrees
{ 46341, 46341 }, // 45 degrees
{ 37950, 53684 }, // 55 degrees
{ 26656, 59870 }, // 66 degrees
{ 0, 65536 } // 90 degrees
};
//**************************************************************************
@ -79,7 +95,10 @@ k053260_device::k053260_device(const machine_config &mconfig, const char *tag, d
: device_t(mconfig, K053260, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, device_rom_interface(mconfig, *this, 21)
, m_sh1_cb(*this)
, m_sh2_cb(*this)
, m_stream(nullptr)
, m_timer(nullptr)
, m_keyon(0)
, m_mode(0)
, m_voice{ { *this }, { *this }, { *this }, { *this } }
@ -94,15 +113,21 @@ k053260_device::k053260_device(const machine_config &mconfig, const char *tag, d
void k053260_device::device_start()
{
m_sh1_cb.resolve_safe();
m_sh2_cb.resolve_safe();
m_stream = stream_alloc( 0, 2, clock() / CLOCKS_PER_SAMPLE );
/* register with the save state system */
save_item(NAME(m_portdata));
save_item(NAME(m_keyon));
save_item(NAME(m_mode));
save_item(NAME(m_timer_state));
for (int i = 0; i < 4; i++)
m_voice[i].voice_start(i);
m_timer = timer_alloc(0);
}
@ -113,6 +138,7 @@ void k053260_device::device_start()
void k053260_device::device_clock_changed()
{
m_stream->set_sample_rate(clock() / CLOCKS_PER_SAMPLE);
m_timer->adjust(attotime::from_ticks(16, clock()), 0, attotime::from_ticks(16, clock()));
}
@ -122,6 +148,8 @@ void k053260_device::device_clock_changed()
void k053260_device::device_reset()
{
m_timer->adjust(attotime::from_ticks(16, clock()), 0, attotime::from_ticks(16, clock()));
for (auto & elem : m_voice)
elem.voice_reset();
}
@ -137,6 +165,17 @@ void k053260_device::rom_bank_updated()
}
void k053260_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch(m_timer_state) {
case 0: m_sh1_cb(ASSERT_LINE); break;
case 1: m_sh1_cb(CLEAR_LINE); break;
case 2: m_sh2_cb(ASSERT_LINE); break;
case 3: m_sh2_cb(CLEAR_LINE); break;
}
m_timer_state = (m_timer_state+1) & 3;
}
u8 k053260_device::main_read(offs_t offset)
{
// sub-to-main ports
@ -289,8 +328,8 @@ void k053260_device::sound_stream_update(sound_stream &stream, stream_sample_t *
voice.play(buffer);
}
outputs[0][j] = limit( buffer[0] >> 1, MAXOUT, MINOUT );
outputs[1][j] = limit( buffer[1] >> 1, MAXOUT, MINOUT );
outputs[0][j] = limit( buffer[0], MAXOUT, MINOUT );
outputs[1][j] = limit( buffer[1], MAXOUT, MINOUT );
}
}
else
@ -384,8 +423,8 @@ void k053260_device::KDSC_Voice::set_pan(u8 data)
void k053260_device::KDSC_Voice::update_pan_volume()
{
m_pan_volume[0] = m_volume * (8 - m_pan);
m_pan_volume[1] = m_volume * m_pan;
m_pan_volume[0] = m_volume * pan_mul[m_pan][0];
m_pan_volume[1] = m_volume * pan_mul[m_pan][1];
}
void k053260_device::KDSC_Voice::key_on()
@ -394,8 +433,8 @@ void k053260_device::KDSC_Voice::key_on()
m_counter = 0x1000 - CLOCKS_PER_SAMPLE; // force update on next sound_stream_update
m_output = 0;
m_playing = true;
if (LOG) m_device.logerror("K053260: start = %06x, length = %06x, pitch = %04x, vol = %02x, loop = %s, %s\n",
m_start, m_length, m_pitch, m_volume, m_loop ? "yes" : "no", m_kadpcm ? "KADPCM" : "PCM" );
if (LOG) m_device.logerror("K053260: start = %06x, length = %06x, pitch = %04x, vol = %02x:%x, loop = %s, %s\n",
m_start, m_length, m_pitch, m_volume, m_pan, m_loop ? "yes" : "no", m_kadpcm ? "KADPCM" : "PCM" );
}
void k053260_device::KDSC_Voice::key_off()
@ -451,8 +490,8 @@ void k053260_device::KDSC_Voice::play(stream_sample_t *outputs)
}
}
outputs[0] += m_output * m_pan_volume[0];
outputs[1] += m_output * m_pan_volume[1];
outputs[0] += (m_output * m_pan_volume[0]) >> 15;
outputs[1] += (m_output * m_pan_volume[1]) >> 15;
}
u8 k053260_device::KDSC_Voice::read_rom()

View File

@ -29,11 +29,15 @@ public:
u8 read(offs_t offset);
void write(offs_t offset, u8 data);
auto sh1_cb() { return m_sh1_cb.bind(); }
auto sh2_cb() { return m_sh2_cb.bind(); }
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_clock_changed() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
@ -42,13 +46,22 @@ protected:
virtual void rom_bank_updated() override;
private:
// Pan multipliers
static const int pan_mul[8][2];
// Sample hold lines callbacks (often used for interrupts)
devcb_write_line m_sh1_cb;
devcb_write_line m_sh2_cb;
// configuration
sound_stream * m_stream;
emu_timer *m_timer;
// live state
u8 m_portdata[4];
u8 m_keyon;
u8 m_mode;
int m_timer_state;
// per voice state
class KDSC_Voice
@ -74,7 +87,7 @@ private:
// live state
u32 m_position = 0;
u16 m_pan_volume[2];
int m_pan_volume[2];
u16 m_counter = 0;
s8 m_output = 0;
bool m_playing = false;

View File

@ -157,22 +157,11 @@ WRITE8_MEMBER(simpsons_state::z80_bankswitch_w)
membank("bank2")->set_entry(data & 7);
}
#if 0
void simpsons_state::sound_nmi_callback( int param )
{
m_audiocpu->set_input_line(INPUT_LINE_NMI, (m_nmi_enabled) ? CLEAR_LINE : ASSERT_LINE );
m_nmi_enabled = 0;
}
#endif
void simpsons_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
case TIMER_NMI:
m_audiocpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
break;
case TIMER_DMASTART:
if (m_firq_enabled)
m_maincpu->set_input_line(KONAMI_FIRQ_LINE, ASSERT_LINE);
@ -189,7 +178,17 @@ void simpsons_state::device_timer(emu_timer &timer, device_timer_id id, int para
WRITE8_MEMBER(simpsons_state::z80_arm_nmi_w)
{
m_audiocpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
timer_set(attotime::from_usec(25), TIMER_NMI); /* kludge until the K053260 is emulated correctly */
m_nmi_enabled = machine().time().as_ticks(m_audiocpu->clock());
}
void simpsons_state::z80_nmi_w(int state)
{
if(state && m_nmi_enabled && machine().time().as_ticks(m_audiocpu->clock()) > m_nmi_enabled + 1) {
m_nmi_enabled = 0;
m_audiocpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
} else
m_audiocpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
}
void simpsons_state::z80_map(address_map &map)
@ -338,9 +337,6 @@ void simpsons_state::simpsons(machine_config &config)
EEPROM_ER5911_8BIT(config, "eeprom");
WATCHDOG_TIMER(config, "watchdog");
//So, the horizontal timing of simpsons is 16/32/16/320
//6MHz dot clock
//Vertical is 16/8/16/224
/* video hardware */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
@ -382,8 +378,9 @@ void simpsons_state::simpsons(machine_config &config)
ymsnd.add_route(1, "rspeaker", 0.0);
k053260_device &k053260(K053260(config, "k053260", XTAL(3'579'545))); /* verified on pcb */
k053260.add_route(0, "lspeaker", 0.75);
k053260.add_route(1, "rspeaker", 0.75);
k053260.add_route(0, "lspeaker", 1.00);
k053260.add_route(1, "rspeaker", 1.00);
k053260.sh2_cb().set(FUNC(simpsons_state::z80_nmi_w));
}

View File

@ -31,7 +31,6 @@ public:
private:
enum
{
TIMER_NMI,
TIMER_DMASTART,
TIMER_DMAEND
};
@ -46,7 +45,7 @@ private:
/* misc */
int m_firq_enabled;
//int m_nmi_enabled;
u64 m_nmi_enabled;
/* devices */
required_device<konami_cpu_device> m_maincpu;
@ -71,6 +70,7 @@ private:
INTERRUPT_GEN_MEMBER(simpsons_irq);
void simpsons_video_banking(int bank);
void simpsons_objdma();
void z80_nmi_w(int state);
K052109_CB_MEMBER(tile_callback);
DECLARE_WRITE8_MEMBER(banking_callback);
K053246_CB_MEMBER(sprite_callback);

View File

@ -73,6 +73,7 @@ void simpsons_state::machine_start()
membank("bank2")->configure_entries(2, 6, memregion("audiocpu")->base() + 0x10000, 0x4000);
save_item(NAME(m_firq_enabled));
save_item(NAME(m_nmi_enabled));
save_item(NAME(m_sprite_colorbase));
save_item(NAME(m_layer_colorbase));
save_item(NAME(m_layerpri));
@ -89,6 +90,7 @@ void simpsons_state::machine_reset()
m_sprite_colorbase = 0;
m_firq_enabled = 0;
m_nmi_enabled = 0;
/* init the default banks */
membank("bank1")->set_entry(0);