mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
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:
parent
59f6afab3f
commit
060378ca9a
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user