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
|
||||
// copyright-holders:
|
||||
/***************************************************************************
|
||||
/**************************************************************************************************
|
||||
|
||||
Sega Z80 Digital Sound Board
|
||||
Sega Digital Sound Board 2
|
||||
|
||||
used for Model 1/2/3
|
||||
|
||||
***************************************************************************/
|
||||
**************************************************************************************************/
|
||||
|
||||
|
||||
#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_vol(0x7f),
|
||||
m_mp_pan(0),
|
||||
m_mp_state(0),
|
||||
m_lp_start(0),
|
||||
m_lp_end(0),
|
||||
m_start(0),
|
||||
m_end(0),
|
||||
m_mp_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(0xd20001) flsbeats reads here
|
||||
// map(0xe00001) acknowledge FIFO writes?
|
||||
// map(0xe00003) MPEG FIFO writes
|
||||
map(0xe00003, 0xe00003).w(FUNC(dsb2_device::fifo_w));
|
||||
// MPEG status
|
||||
map(0xe80001, 0xe80001).lr8(NAME([] () { return 0x01; }));
|
||||
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)
|
||||
{
|
||||
// TODO: unknown clocks
|
||||
// TODO: 1 kHz timer for irq2
|
||||
M68000(config, m_ourcpu, 8000000);
|
||||
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));
|
||||
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_end));
|
||||
save_item(NAME(m_mp_vol));
|
||||
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_end));
|
||||
save_item(NAME(m_start));
|
||||
@ -95,11 +96,13 @@ void dsb2_device::device_reset()
|
||||
m_audio_pos = m_audio_avail = 0;
|
||||
std::fill(std::begin(m_audio_buf), std::end(m_audio_buf), 0);
|
||||
m_mp_vol = 0x7f;
|
||||
m_mp_state = 0;
|
||||
m_command = IDLE;
|
||||
m_player = NOT_PLAYING;
|
||||
|
||||
m_uart->write_cts(0);
|
||||
}
|
||||
|
||||
m_timer_1kHz->adjust(attotime::from_hz(1000), 0, attotime::from_hz(1000));
|
||||
}
|
||||
|
||||
void dsb2_device::device_stop()
|
||||
{
|
||||
@ -116,10 +119,144 @@ void dsb2_device::output_txd(int 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)
|
||||
{
|
||||
//int samples = stream.samples();
|
||||
//int sampindex = 0;
|
||||
int samples = stream.samples();
|
||||
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>
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
class dsb2_device : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
@ -47,19 +43,36 @@ private:
|
||||
|
||||
std::unique_ptr<mpeg_audio> m_decoder;
|
||||
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;
|
||||
|
||||
emu_timer *m_timer_1kHz;
|
||||
TIMER_CALLBACK_MEMBER(timer_irq_cb);
|
||||
|
||||
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;
|
||||
|
||||
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