mirror of
https://github.com/holub/mame
synced 2025-07-04 09:28:51 +03:00
sega/dsb2.cpp: add basic MPEG playback
This commit is contained in:
parent
3103e0c799
commit
16cc6c9d80
@ -1,12 +1,10 @@
|
|||||||
// license:BSD-3-Clause
|
// license:BSD-3-Clause
|
||||||
// copyright-holders:
|
// copyright-holders:
|
||||||
/***************************************************************************
|
/**************************************************************************************************
|
||||||
|
|
||||||
Sega Z80 Digital Sound Board
|
Sega Digital Sound Board 2
|
||||||
|
|
||||||
used for Model 1/2/3
|
**************************************************************************************************/
|
||||||
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
@ -28,14 +26,15 @@ dsb2_device::dsb2_device(const machine_config &mconfig, const char *tag, device_
|
|||||||
m_mp_end(0),
|
m_mp_end(0),
|
||||||
m_mp_vol(0x7f),
|
m_mp_vol(0x7f),
|
||||||
m_mp_pan(0),
|
m_mp_pan(0),
|
||||||
m_mp_state(0),
|
|
||||||
m_lp_start(0),
|
m_lp_start(0),
|
||||||
m_lp_end(0),
|
m_lp_end(0),
|
||||||
m_start(0),
|
m_start(0),
|
||||||
m_end(0),
|
m_end(0),
|
||||||
m_mp_pos(0),
|
m_mp_pos(0),
|
||||||
m_audio_pos(0),
|
m_audio_pos(0),
|
||||||
m_audio_avail(0)
|
m_audio_avail(0),
|
||||||
|
m_command(mpeg_command_t::IDLE),
|
||||||
|
m_player(mpeg_player_t::NOT_PLAYING)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +46,7 @@ void dsb2_device::dsb2_map(address_map &map)
|
|||||||
// map(0xd00001) system control?
|
// map(0xd00001) system control?
|
||||||
// map(0xd20001) flsbeats reads here
|
// map(0xd20001) flsbeats reads here
|
||||||
// map(0xe00001) acknowledge FIFO writes?
|
// map(0xe00001) acknowledge FIFO writes?
|
||||||
// map(0xe00003) MPEG FIFO writes
|
map(0xe00003, 0xe00003).w(FUNC(dsb2_device::fifo_w));
|
||||||
// MPEG status
|
// MPEG status
|
||||||
map(0xe80001, 0xe80001).lr8(NAME([] () { return 0x01; }));
|
map(0xe80001, 0xe80001).lr8(NAME([] () { return 0x01; }));
|
||||||
map(0xf00000, 0xf1ffff).ram();
|
map(0xf00000, 0xf1ffff).ram();
|
||||||
@ -56,7 +55,6 @@ void dsb2_device::dsb2_map(address_map &map)
|
|||||||
void dsb2_device::device_add_mconfig(machine_config &config)
|
void dsb2_device::device_add_mconfig(machine_config &config)
|
||||||
{
|
{
|
||||||
// TODO: unknown clocks
|
// TODO: unknown clocks
|
||||||
// TODO: 1 kHz timer for irq2
|
|
||||||
M68000(config, m_ourcpu, 8000000);
|
M68000(config, m_ourcpu, 8000000);
|
||||||
m_ourcpu->set_addrmap(AS_PROGRAM, &dsb2_device::dsb2_map);
|
m_ourcpu->set_addrmap(AS_PROGRAM, &dsb2_device::dsb2_map);
|
||||||
|
|
||||||
@ -75,11 +73,14 @@ void dsb2_device::device_start()
|
|||||||
m_decoder.reset(new mpeg_audio(&m_mpeg_rom[0], mpeg_audio::L2, false, 0));
|
m_decoder.reset(new mpeg_audio(&m_mpeg_rom[0], mpeg_audio::L2, false, 0));
|
||||||
stream_alloc(0, 2, 32000);
|
stream_alloc(0, 2, 32000);
|
||||||
|
|
||||||
|
m_timer_1kHz = timer_alloc(FUNC(dsb2_device::timer_irq_cb), this);
|
||||||
|
|
||||||
save_item(NAME(m_mp_start));
|
save_item(NAME(m_mp_start));
|
||||||
save_item(NAME(m_mp_end));
|
save_item(NAME(m_mp_end));
|
||||||
save_item(NAME(m_mp_vol));
|
save_item(NAME(m_mp_vol));
|
||||||
save_item(NAME(m_mp_pan));
|
save_item(NAME(m_mp_pan));
|
||||||
save_item(NAME(m_mp_state));
|
// save_item(NAME(m_command));
|
||||||
|
// save_item(NAME(m_player));
|
||||||
save_item(NAME(m_lp_start));
|
save_item(NAME(m_lp_start));
|
||||||
save_item(NAME(m_lp_end));
|
save_item(NAME(m_lp_end));
|
||||||
save_item(NAME(m_start));
|
save_item(NAME(m_start));
|
||||||
@ -95,11 +96,13 @@ void dsb2_device::device_reset()
|
|||||||
m_audio_pos = m_audio_avail = 0;
|
m_audio_pos = m_audio_avail = 0;
|
||||||
std::fill(std::begin(m_audio_buf), std::end(m_audio_buf), 0);
|
std::fill(std::begin(m_audio_buf), std::end(m_audio_buf), 0);
|
||||||
m_mp_vol = 0x7f;
|
m_mp_vol = 0x7f;
|
||||||
m_mp_state = 0;
|
m_command = IDLE;
|
||||||
|
m_player = NOT_PLAYING;
|
||||||
|
|
||||||
m_uart->write_cts(0);
|
m_uart->write_cts(0);
|
||||||
}
|
|
||||||
|
|
||||||
|
m_timer_1kHz->adjust(attotime::from_hz(1000), 0, attotime::from_hz(1000));
|
||||||
|
}
|
||||||
|
|
||||||
void dsb2_device::device_stop()
|
void dsb2_device::device_stop()
|
||||||
{
|
{
|
||||||
@ -116,10 +119,144 @@ void dsb2_device::output_txd(int state)
|
|||||||
m_rxd_handler(state);
|
m_rxd_handler(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TIMER_CALLBACK_MEMBER(dsb2_device::timer_irq_cb)
|
||||||
|
{
|
||||||
|
m_ourcpu->set_input_line(2, HOLD_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsb2_device::fifo_w(offs_t offset, u8 data)
|
||||||
|
{
|
||||||
|
switch(m_command)
|
||||||
|
{
|
||||||
|
case mpeg_command_t::START_ADDRESS_HI:
|
||||||
|
m_start &= 0x00ffff;
|
||||||
|
m_start |= (uint32_t)data << 16;
|
||||||
|
m_command = mpeg_command_t::START_ADDRESS_MD;
|
||||||
|
break;
|
||||||
|
case mpeg_command_t::START_ADDRESS_MD:
|
||||||
|
m_start &= 0xff00ff;
|
||||||
|
m_start |= (uint32_t)data << 8;
|
||||||
|
m_command = mpeg_command_t::START_ADDRESS_LO;
|
||||||
|
break;
|
||||||
|
case mpeg_command_t::START_ADDRESS_LO:
|
||||||
|
m_start &= 0xffff00;
|
||||||
|
m_start |= data;
|
||||||
|
|
||||||
|
m_mp_start = m_start;
|
||||||
|
m_command = mpeg_command_t::IDLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mpeg_command_t::END_ADDRESS_HI:
|
||||||
|
m_end &= 0x00ffff;
|
||||||
|
m_end |= (uint32_t)data << 16;
|
||||||
|
m_command = mpeg_command_t::END_ADDRESS_MD;
|
||||||
|
break;
|
||||||
|
case mpeg_command_t::END_ADDRESS_MD:
|
||||||
|
m_end &= 0xff00ff;
|
||||||
|
m_end |= (uint32_t)data << 8;
|
||||||
|
m_command = mpeg_command_t::END_ADDRESS_LO;
|
||||||
|
break;
|
||||||
|
case mpeg_command_t::END_ADDRESS_LO:
|
||||||
|
m_end &= 0xffff00;
|
||||||
|
m_end |= data;
|
||||||
|
|
||||||
|
m_mp_end = m_end;
|
||||||
|
m_command = mpeg_command_t::IDLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mpeg_command_t::IDLE:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if ((data & 0xfe) == 0x14)
|
||||||
|
m_command = mpeg_command_t::START_ADDRESS_HI;
|
||||||
|
if ((data & 0xfe) == 0x24)
|
||||||
|
m_command = mpeg_command_t::END_ADDRESS_HI;
|
||||||
|
if ((data & 0xfe) == 0x74)
|
||||||
|
{
|
||||||
|
m_mp_pos = m_mp_start * 8;
|
||||||
|
m_player = mpeg_player_t::PLAYING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((data & 0xfe) == 0x84)
|
||||||
|
{
|
||||||
|
m_player = mpeg_player_t::NOT_PLAYING;
|
||||||
|
m_audio_pos = m_audio_avail = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void dsb2_device::sound_stream_update(sound_stream &stream)
|
void dsb2_device::sound_stream_update(sound_stream &stream)
|
||||||
{
|
{
|
||||||
//int samples = stream.samples();
|
int samples = stream.samples();
|
||||||
//int sampindex = 0;
|
int sampindex = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
while (samples && (m_audio_pos < m_audio_avail))
|
||||||
|
{
|
||||||
|
switch (m_mp_pan)
|
||||||
|
{
|
||||||
|
case 0: // stereo
|
||||||
|
stream.put_int(0, sampindex, m_audio_buf[m_audio_pos*2] * m_mp_vol, 32768 * 128);
|
||||||
|
stream.put_int(1, sampindex, m_audio_buf[m_audio_pos*2+1] * m_mp_vol, 32768 * 128);
|
||||||
|
sampindex++;
|
||||||
|
break;
|
||||||
|
|
||||||
// ...
|
case 1: // left only
|
||||||
|
stream.put_int(0, sampindex, m_audio_buf[m_audio_pos*2] * m_mp_vol, 32768 * 128);
|
||||||
|
stream.put_int(1, sampindex, m_audio_buf[m_audio_pos*2] * m_mp_vol, 32768 * 128);
|
||||||
|
sampindex++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // right only
|
||||||
|
stream.put_int(0, sampindex, m_audio_buf[m_audio_pos*2+1] * m_mp_vol, 32768 * 128);
|
||||||
|
stream.put_int(1, sampindex, m_audio_buf[m_audio_pos*2+1] * m_mp_vol, 32768 * 128);
|
||||||
|
sampindex++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_audio_pos++;
|
||||||
|
samples--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!samples)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_player == mpeg_player_t::NOT_PLAYING)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int sample_rate, channel_count;
|
||||||
|
bool const ok = m_decoder->decode_buffer(m_mp_pos, m_mp_end * 8, m_audio_buf, m_audio_avail, sample_rate, channel_count);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
m_audio_pos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if (m_mp_state == 2)
|
||||||
|
//{
|
||||||
|
// if (m_mp_pos == m_lp_start * 8)
|
||||||
|
// {
|
||||||
|
// // We're looping on un-decodable crap, abort abort abort
|
||||||
|
// m_mp_state = 0;
|
||||||
|
// }
|
||||||
|
// m_mp_pos = m_lp_start * 8;
|
||||||
|
//
|
||||||
|
// if (m_lp_end)
|
||||||
|
// {
|
||||||
|
// m_mp_end = m_lp_end;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
{
|
||||||
|
m_player = mpeg_player_t::NOT_PLAYING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
//**************************************************************************
|
|
||||||
// TYPE DEFINITIONS
|
|
||||||
//**************************************************************************
|
|
||||||
|
|
||||||
class dsb2_device : public device_t, public device_sound_interface
|
class dsb2_device : public device_t, public device_sound_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -47,19 +43,36 @@ private:
|
|||||||
|
|
||||||
std::unique_ptr<mpeg_audio> m_decoder;
|
std::unique_ptr<mpeg_audio> m_decoder;
|
||||||
int16_t m_audio_buf[1152*2];
|
int16_t m_audio_buf[1152*2];
|
||||||
uint32_t m_mp_start, m_mp_end, m_mp_vol, m_mp_pan, m_mp_state, m_lp_start, m_lp_end, m_start, m_end;
|
uint32_t m_mp_start, m_mp_end, m_mp_vol, m_mp_pan, m_lp_start, m_lp_end, m_start, m_end;
|
||||||
int32_t m_mp_pos, m_audio_pos, m_audio_avail;
|
int32_t m_mp_pos, m_audio_pos, m_audio_avail;
|
||||||
|
|
||||||
|
emu_timer *m_timer_1kHz;
|
||||||
|
TIMER_CALLBACK_MEMBER(timer_irq_cb);
|
||||||
|
|
||||||
void output_txd(int state);
|
void output_txd(int state);
|
||||||
|
|
||||||
// void mpeg_trigger_w(uint8_t data);
|
|
||||||
// void mpeg_start_w(offs_t offset, uint8_t data);
|
|
||||||
// void mpeg_end_w(offs_t offset, uint8_t data);
|
|
||||||
// void mpeg_volume_w(uint8_t data);
|
|
||||||
// void mpeg_stereo_w(uint8_t data);
|
|
||||||
// uint8_t mpeg_pos_r(offs_t offset);
|
|
||||||
|
|
||||||
void dsb2_map(address_map &map) ATTR_COLD;
|
void dsb2_map(address_map &map) ATTR_COLD;
|
||||||
|
|
||||||
|
enum mpeg_command_t : u8 {
|
||||||
|
IDLE,
|
||||||
|
START_ADDRESS_HI,
|
||||||
|
START_ADDRESS_MD,
|
||||||
|
START_ADDRESS_LO,
|
||||||
|
END_ADDRESS_HI,
|
||||||
|
END_ADDRESS_MD,
|
||||||
|
END_ADDRESS_LO
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mpeg_player_t : u8 {
|
||||||
|
NOT_PLAYING,
|
||||||
|
PLAYING
|
||||||
|
};
|
||||||
|
|
||||||
|
mpeg_command_t m_command;
|
||||||
|
mpeg_player_t m_player;
|
||||||
|
|
||||||
|
|
||||||
|
void fifo_w(offs_t offset, u8 data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user