Fix regressions in k573dio/k573fpga/mas3507d (#5133)

* Fix memory address stuff (fixes graphics, random glitches, games not booting, etc)

* Handle playback flag

* Add volume control

* This doesn't do anything

* Fix transitioning between two MP3 files

* Revert change

* Fix the way playback time is reported which should fix looping

* Fix audio decoding

* Fix timing issue

* Small cleanup

* Store the original key1 in k573dio, not k573fpga

* Restore masks for RAM addresses to avoid overflows

* Rework how starting and stopping the MAS3507D works as well as reporting playback time
This commit is contained in:
Windy Fairy 2019-06-05 22:46:14 +09:00 committed by R. Belmont
parent 59f6afab3f
commit 060378ca9a
6 changed files with 59 additions and 54 deletions

View File

@ -30,7 +30,6 @@ void mas3507d_device::device_start()
{
current_rate = 44100;
stream = stream_alloc(0, 2, current_rate);
mp3dec_init(&mp3_dec);
cb_sample.resolve();
}
@ -42,7 +41,13 @@ void mas3507d_device::device_reset()
i2c_bus_address = UNKNOWN;
i2c_bus_curbit = -1;
i2c_bus_curval = 0;
total_sample_count = 0;
mp3dec_init(&mp3_dec);
memset(mp3data.data(), 0, mp3data.size());
memset(samples.data(), 0, samples.size());
mp3_count = 0;
sample_count = 0;
total_frame_count = 0;
}
void mas3507d_device::i2c_scl_w(bool line)
@ -284,6 +289,7 @@ void mas3507d_device::mem_write(int bank, uint32_t adr, uint32_t val)
case 0x0032f: logerror("MAS3507D: OutputConfig = %05x\n", val); break;
case 0x107f8:
logerror("MAS3507D: left->left gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val));
stream->set_output_gain(0, gain_to_percentage(val));
break;
case 0x107f9:
logerror("MAS3507D: left->right gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val));
@ -293,6 +299,7 @@ void mas3507d_device::mem_write(int bank, uint32_t adr, uint32_t val)
break;
case 0x107fb:
logerror("MAS3507D: right->right gain = %05x (%d dB, %f%%)\n", val, gain_to_db(val), gain_to_percentage(val));
stream->set_output_gain(1, gain_to_percentage(val));
break;
default: logerror("MAS3507D: %d:%04x = %05x\n", bank, adr, val); break;
}
@ -321,7 +328,7 @@ void mas3507d_device::run_program(uint32_t adr)
void mas3507d_device::fill_buffer()
{
while(mp3_count < mp3data.size()) {
while(mp3_count + 2 < mp3data.size()) {
u16 v = cb_sample();
mp3data[mp3_count++] = v >> 8;
mp3data[mp3_count++] = v;
@ -343,15 +350,14 @@ void mas3507d_device::fill_buffer()
std::copy(mp3data.begin() + mp3_info.frame_bytes, mp3data.end(), mp3data.begin());
mp3_count -= mp3_info.frame_bytes;
if(mp3_info.channels == 1)
sample_count = scount;
else
sample_count = scount;
sample_count = scount;
if(mp3_info.hz != current_rate) {
current_rate = mp3_info.hz;
stream->set_sample_rate(current_rate);
}
total_frame_count += scount;
}
void mas3507d_device::append_buffer(stream_sample_t **outputs, int &pos, int scount)
@ -391,22 +397,30 @@ void mas3507d_device::append_buffer(stream_sample_t **outputs, int &pos, int sco
sample_count -= s1;
}
void mas3507d_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
void mas3507d_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int csamples)
{
int pos = 0;
total_sample_count += samples;
append_buffer(outputs, pos, samples);
append_buffer(outputs, pos, csamples);
for(;;) {
if(pos == samples)
if(pos == csamples)
return;
fill_buffer();
if(!sample_count) {
for(int i=pos; i != samples; i++) {
// In the case of a bad frame or no frames being around, reset the state of the decoder
mp3dec_init(&mp3_dec);
memset(mp3data.data(), 0, mp3data.size());
memset(samples.data(), 0, samples.size());
mp3_count = 0;
sample_count = 0;
total_frame_count = 0;
for(int i=pos; i != csamples; i++) {
outputs[0][i] = 0;
outputs[1][i] = 0;
}
return;
}
append_buffer(outputs, pos, samples);
append_buffer(outputs, pos, csamples);
}
}

View File

@ -22,8 +22,7 @@ public:
void i2c_scl_w(bool line);
void i2c_sda_w(bool line);
void reset_sample_count() { total_sample_count = 0; }
u32 get_sample_count() const { return total_sample_count; }
u32 get_frame_count() const { return total_frame_count; }
protected:
virtual void device_start() override;
@ -36,13 +35,14 @@ private:
enum { IDLE, STARTED, NAK, ACK, ACK2 } i2c_bus_state;
enum { UNKNOWN, VALIDATED, WRONG } i2c_bus_address;
std::array<u8, 8000> mp3data;
std::array<u8, 0xe00> mp3data;
std::array<mp3d_sample_t, MINIMP3_MAX_SAMPLES_PER_FRAME> samples;
bool i2c_scli, i2c_sclo, i2c_sdai, i2c_sdao;
int i2c_bus_curbit;
uint8_t i2c_bus_curval;
int mp3_count, sample_count, current_rate;
u32 total_sample_count;
u32 total_frame_count;
bool playback_enabled, playback_waiting;
mp3dec_t mp3_dec;
mp3dec_frame_info_t mp3_info;
@ -54,7 +54,6 @@ private:
void i2c_device_got_byte(uint8_t byte);
void i2c_device_got_stop();
enum { UNDEFINED, CONTROL, DATA_READ, DATA_WRITE, BAD } i2c_subdest;
enum { CMD_BAD, CMD_RUN, CMD_READ_CTRL, CMD_WRITE_REG, CMD_WRITE_MEM, CMD_READ_REG, CMD_READ_MEM } i2c_command;
int i2c_bytecount;

View File

@ -89,8 +89,8 @@ void k573dio_device::amap(address_map &map)
map(0xb4, 0xb5).rw(FUNC(k573dio_device::ram_r), FUNC(k573dio_device::ram_w));
map(0xb6, 0xb7).w(FUNC(k573dio_device::ram_read_adr_high_w));
map(0xb8, 0xb9).w(FUNC(k573dio_device::ram_read_adr_low_w));
map(0xca, 0xcb).rw(FUNC(k573dio_device::mp3_playback_high_r), FUNC(k573dio_device::mp3_playback_high_w));
map(0xcc, 0xcd).rw(FUNC(k573dio_device::mp3_playback_low_r), FUNC(k573dio_device::mp3_playback_low_w));
map(0xca, 0xcb).r(FUNC(k573dio_device::mp3_frame_count_high_r));
map(0xcc, 0xcd).r(FUNC(k573dio_device::mp3_frame_count_low_r));
map(0xce, 0xcf).r(FUNC(k573dio_device::mp3_unk_r));
map(0xe0, 0xe1).w(FUNC(k573dio_device::output_1_w));
map(0xe2, 0xe3).w(FUNC(k573dio_device::output_0_w));
@ -216,9 +216,9 @@ WRITE16_MEMBER(k573dio_device::mpeg_start_adr_low_w)
{
logerror("FPGA MPEG start address low %04x\n", data);
k573fpga->set_mp3_cur_adr((k573fpga->get_mp3_cur_adr() & 0xffff0000) | data); // low
if(is_ddrsbm_fpga)
k573fpga->set_crypto_key3(0);
mas3507d->reset_sample_count();
}
WRITE16_MEMBER(k573dio_device::mpeg_end_adr_high_w)
@ -235,12 +235,14 @@ WRITE16_MEMBER(k573dio_device::mpeg_end_adr_low_w)
READ16_MEMBER(k573dio_device::mpeg_key_1_r)
{
return k573fpga->get_crypto_key1();
// Dance Dance Revolution Solo Bass Mix reads this key before starting songs
return crypto_key1;
}
WRITE16_MEMBER(k573dio_device::mpeg_key_1_w)
{
logerror("FPGA MPEG key 1/3 %04x\n", data);
crypto_key1 = data;
k573fpga->set_crypto_key1(data);
}
@ -260,6 +262,11 @@ WRITE16_MEMBER(k573dio_device::mas_i2c_w)
READ16_MEMBER(k573dio_device::mpeg_ctrl_r)
{
if (k573fpga->get_mpeg_ctrl() == 0x1000 && !k573fpga->is_playing()) {
// Set the FPGA to stop mode so that data won't be sent anymore
k573fpga->set_mpeg_ctrl(0xa000);
}
return k573fpga->get_mpeg_ctrl();
}
@ -271,18 +278,18 @@ WRITE16_MEMBER(k573dio_device::mpeg_ctrl_w)
WRITE16_MEMBER(k573dio_device::ram_write_adr_high_w)
{
// read and write address are shared
ram_adr = (ram_adr & 0x0000ffff) | (data << 16);
ram_adr = ((ram_adr & 0x0000ffff) | (data << 16)) & 0x1ffffff;
}
WRITE16_MEMBER(k573dio_device::ram_write_adr_low_w)
{
// read and write address are shared
ram_adr = (ram_adr & 0xffff0000) | data;
ram_adr = ((ram_adr & 0xffff0000) | data) & 0x1ffffff;
}
READ16_MEMBER(k573dio_device::ram_r)
{
uint16_t res = ram[(ram_read_adr & 0x7fffff) >> 1];
uint16_t res = ram[(ram_read_adr & 0x1ffffff) >> 1];
ram_read_adr += 2;
return res;
}
@ -296,37 +303,23 @@ WRITE16_MEMBER(k573dio_device::ram_w)
WRITE16_MEMBER(k573dio_device::ram_read_adr_high_w)
{
// read and write address are shared
ram_read_adr = (ram_read_adr & 0x001fffff) | (data << 16);
ram_read_adr = ((ram_read_adr & 0x0000ffff) | (data << 16)) & 0x1ffffff;
}
WRITE16_MEMBER(k573dio_device::ram_read_adr_low_w)
{
// read and write address are shared
ram_read_adr = (ram_read_adr & 0xffff0000) | data;
ram_read_adr = ((ram_read_adr & 0xffff0000) | data) & 0x1ffffff;
}
READ16_MEMBER(k573dio_device::mp3_playback_high_r)
READ16_MEMBER(k573dio_device::mp3_frame_count_high_r)
{
//logerror("mp3_playback_high_r: %08x (%08x)\n", mp3_playback & 0xffff0000, mp3_playback);
return (mas3507d->get_sample_count() & 0xffff0000) >> 16;
return (mas3507d->get_frame_count() & 0xffff0000) >> 16;
}
WRITE16_MEMBER(k573dio_device::mp3_playback_high_w)
READ16_MEMBER(k573dio_device::mp3_frame_count_low_r)
{
//mp3_playback = (mp3_playback & 0x0000ffff) | (data << 16);
//logerror("mp3_playback_low_w: %08x\n", mp3_playback);
}
READ16_MEMBER(k573dio_device::mp3_playback_low_r)
{
//logerror("mp3_playback_low_r: %08x (%08x) %08x %08x\n", mp3_playback & 0x0000ffff, mp3_playback, m_samples->get_position(0), m_samples->get_position(1));
return mas3507d->get_sample_count() & 0x0000ffff;
}
WRITE16_MEMBER(k573dio_device::mp3_playback_low_w)
{
//mp3_playback = (mp3_playback & 0xffff0000) | data;
//logerror("mp3_playback_low_w: %08x\n", mp3_playback & 0x0000ffff);
return mas3507d->get_frame_count() & 0x0000ffff;
}
WRITE16_MEMBER(k573dio_device::output_1_w)

View File

@ -43,10 +43,8 @@ public:
DECLARE_WRITE16_MEMBER(ram_w);
DECLARE_WRITE16_MEMBER(ram_read_adr_high_w);
DECLARE_WRITE16_MEMBER(ram_read_adr_low_w);
DECLARE_READ16_MEMBER(mp3_playback_high_r);
DECLARE_WRITE16_MEMBER(mp3_playback_high_w);
DECLARE_READ16_MEMBER(mp3_playback_low_r);
DECLARE_WRITE16_MEMBER(mp3_playback_low_w);
DECLARE_READ16_MEMBER(mp3_frame_count_high_r);
DECLARE_READ16_MEMBER(mp3_frame_count_low_r);
DECLARE_WRITE16_MEMBER(output_0_w);
DECLARE_WRITE16_MEMBER(output_1_w);
DECLARE_WRITE16_MEMBER(output_7_w);
@ -82,6 +80,7 @@ private:
void output(int offset, uint16_t data);
bool is_ddrsbm_fpga;
u16 crypto_key1;
};
DECLARE_DEVICE_TYPE(KONAMI_573_DIGITAL_IO_BOARD, k573dio_device)

View File

@ -140,10 +140,11 @@ u16 k573fpga_device::decrypt_ddrsbm(u16 data)
u16 k573fpga_device::get_decrypted()
{
if(mp3_cur_adr >= mp3_end_adr || (mpeg_ctrl_flag & 0xe000) != 0xe000)
if(mp3_cur_adr >= mp3_end_adr || (mpeg_ctrl_flag & 0xe000) != 0xe000) {
return 0;
}
u16 src = ram[(mp3_cur_adr & 0x1ffffff) >> 1];
u16 src = ram[mp3_cur_adr >> 1];
u16 result = use_ddrsbm_fpga ? decrypt_ddrsbm(src) : decrypt_default(src);
mp3_cur_adr += 2;

View File

@ -23,9 +23,6 @@ public:
void set_crypto_key1(u16 v) { crypto_key1 = v; }
void set_crypto_key2(u16 v) { crypto_key2 = v; }
void set_crypto_key3(u8 v) { crypto_key3 = v; }
u16 get_crypto_key1() const { return crypto_key1; }
u16 get_crypto_key2() const { return crypto_key2; }
u8 get_crypto_key3() const { return crypto_key3; }
uint32_t get_mp3_cur_adr() { return mp3_cur_adr; }
void set_mp3_cur_adr(u32 v) { mp3_cur_adr = v; }
@ -39,6 +36,8 @@ public:
u16 get_mpeg_ctrl();
void set_mpeg_ctrl(u16 data);
bool is_playing() { return (mpeg_ctrl_flag & 0xe000) == 0xe000 && mp3_cur_adr < mp3_end_adr; }
protected:
virtual void device_start() override;
virtual void device_reset() override;