diff options
author | Windy Fairy <39211915+windyfairy@users.noreply.github.com> | 2019-05-20 20:45:33 +0900 |
---|---|---|
committer | R. Belmont <rb6502@users.noreply.github.com> | 2019-05-20 07:45:33 -0400 |
commit | 347fb288ad6eb2dd6be683a7e938dfb6014cf284 (patch) | |
tree | 0ba99e2567e40915e2f7c892a9788410fc43555f | |
parent | c16b3d8a8b372ceb9d302d7d47f61f534eb53a84 (diff) |
k573dio/k573fpga: Full playability with all testable games (#5086)
* Fix issues with remaining GFDM games
* Fix DDR Solo Bass Mix
* Fix regressions with DSEM2, DDR Extreme, DDR Max 2
* Fix MP3 streaming and get rid of workaround to load full files
* Attempt to fix timing issues by emulating a buffer before the song actually plays.
This value was found by choosing something that had a tight but known timing window (the Konami logo sound in DM10) and finding an offset that didn't allow you to hear it loop before the song end command was sent.
* Revert changes for dynamic base address because I still can't figure out a more logical way that Konami could've implemented this.
* Use the last non-0 diff to fix some games
* Some small refactoring
* This should be the same as GF10DM9
* Use a block size that's more in line with what the real FPGA uses
-rw-r--r-- | src/mame/drivers/ksys573.cpp | 69 | ||||
-rw-r--r-- | src/mame/machine/k573dio.cpp | 19 | ||||
-rw-r--r-- | src/mame/machine/k573dio.h | 6 | ||||
-rw-r--r-- | src/mame/machine/k573fpga.cpp | 286 | ||||
-rw-r--r-- | src/mame/machine/k573fpga.h | 5 |
5 files changed, 169 insertions, 216 deletions
diff --git a/src/mame/drivers/ksys573.cpp b/src/mame/drivers/ksys573.cpp index c691abe3ff9..76a3b7f3cbd 100644 --- a/src/mame/drivers/ksys573.cpp +++ b/src/mame/drivers/ksys573.cpp @@ -405,6 +405,10 @@ public: m_lamps(*this, "lamp%u", 0U) { } + void drmn9m(machine_config &config); + void drmn10m(machine_config &config); + void gtfrk10m(machine_config &config); + void gtfrk11m(machine_config &config); void gtfrk10mb(machine_config &config); void ddr(machine_config &config); void pnchmn(machine_config &config); @@ -432,7 +436,6 @@ public: void gtrfrks(machine_config &config); void gchgchmp(machine_config &config); void ddr5m(machine_config &config); - void ddrmax(machine_config &config); void drmn4m(machine_config &config); void fbaitbc(machine_config &config); void ddr4ms(machine_config &config); @@ -2295,16 +2298,6 @@ void ksys573_state::ddr5m(machine_config &config) casszi(config); } -void ksys573_state::ddrmax(machine_config &config) -{ - k573d(config); - subdevice<k573dio_device>("k573dio")->output_callback().set(FUNC(ksys573_state::ddr_output_callback)); - subdevice<k573dio_device>("k573dio")->set_buffer_speed(0x4000); - - pccard2_32mb(config); - casszi(config); -} - // Dancing Stage void ksys573_state::dsfdcta(machine_config &config) @@ -2398,6 +2391,28 @@ void ksys573_state::drmn4m(machine_config &config) KONAMI_573_MULTI_SESSION_UNIT(config, "k573msu", 0); } +void ksys573_state::drmn9m(machine_config &config) +{ + k573d(config); + subdevice<k573dio_device>("k573dio")->output_callback().set(FUNC(ksys573_state::drmn_output_callback)); + subdevice<k573dio_device>("k573dio")->set_mp3_dynamic_base(0x00540000); + + casszi(config); + + KONAMI_573_MULTI_SESSION_UNIT(config, "k573msu", 0); +} + +void ksys573_state::drmn10m(machine_config &config) +{ + k573d(config); + subdevice<k573dio_device>("k573dio")->output_callback().set(FUNC(ksys573_state::drmn_output_callback)); + subdevice<k573dio_device>("k573dio")->set_mp3_dynamic_base(0x00500000); + + casszi(config); + + KONAMI_573_MULTI_SESSION_UNIT(config, "k573msu", 0); +} + // Guitar Freaks void ksys573_state::gtrfrks(machine_config &config) @@ -2434,14 +2449,30 @@ void ksys573_state::gtrfrk7m(machine_config &config) pccard1_32mb(config); } +void ksys573_state::gtfrk10m(machine_config &config) +{ + k573d(config); + casszi(config); + pccard1_32mb(config); + subdevice<k573dio_device>("k573dio")->set_mp3_dynamic_base(0x00540000); +} + void ksys573_state::gtfrk10mb(machine_config &config) { gtrfrk7m(config); - subdevice<k573dio_device>("k573dio")->set_mp3_dynamic_base(0x00500000); + subdevice<k573dio_device>("k573dio")->set_mp3_dynamic_base(0x00540000); KONAMI_573_NETWORK_PCB_UNIT(config, "k573npu", 0); } +void ksys573_state::gtfrk11m(machine_config &config) +{ + k573d(config); + casszi(config); + pccard1_32mb(config); + subdevice<k573dio_device>("k573dio")->set_mp3_dynamic_base(0x00500000); +} + // Miscellaneous void ksys573_state::konami573x(machine_config &config) @@ -5074,8 +5105,8 @@ GAME( 2001, drmn5m, pcnfrk5m, drmn4m, drmn, ksys573_state, empty_ini GAME( 2001, gtrfrk6m, sys573, gtrfrk5m, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 6th Mix (G*B06 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.9 */ GAME( 2001, drmn6m, sys573, drmn4m, drmn, ksys573_state, empty_init, ROT0, "Konami", "DrumMania 6th Mix (G*B16 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ GAME( 2001, gtrfrk7m, sys573, gtrfrk7m, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 7th Mix (G*B17 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ -GAME( 2001, ddrmax, sys573, ddrmax, ddr, ksys573_state, empty_init, ROT0, "Konami", "DDR Max - Dance Dance Revolution 6th Mix (G*B19 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.9 */ -GAME( 2002, ddrmax2, sys573, ddrmax, ddr, ksys573_state, empty_init, ROT0, "Konami", "DDR Max 2 - Dance Dance Revolution 7th Mix (G*B20 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ +GAME( 2001, ddrmax, sys573, ddr5m, ddr, ksys573_state, empty_init, ROT0, "Konami", "DDR Max - Dance Dance Revolution 6th Mix (G*B19 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.9 */ +GAME( 2002, ddrmax2, sys573, ddr5m, ddr, ksys573_state, empty_init, ROT0, "Konami", "DDR Max 2 - Dance Dance Revolution 7th Mix (G*B20 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ GAME( 2002, mrtlbeat, sys573, ddr5m, ddr, ksys573_state, empty_init, ROT0, "Konami", "Martial Beat (G*B47 VER. JBA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.9 */ GAME( 2002, drmn7m, sys573, drmn4m, drmn, ksys573_state, empty_init, ROT0, "Konami", "DrumMania 7th Mix power-up ver. (G*C07 VER. JBA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ GAME( 2002, drmn7ma, drmn7m, drmn4m, drmn, ksys573_state, empty_init, ROT0, "Konami", "DrumMania 7th Mix (G*C07 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ @@ -5085,9 +5116,9 @@ GAME( 2002, dsem2, sys573, ddr5m, ddr, ksys573_state, empty_ini GAME( 2002, ddrextrm, sys573, ddr5m, ddr, ksys573_state, empty_init, ROT0, "Konami", "Dance Dance Revolution Extreme (G*C36 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ GAME( 2003, drmn8m, sys573, drmn4m, drmn, ksys573_state, empty_init, ROT0, "Konami", "DrumMania 8th Mix (G*C07 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ GAME( 2003, gtrfrk9m, sys573, gtrfrk7m, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 9th Mix (G*C39 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ -GAME( 2003, drmn9m, sys573, drmn4m, drmn, ksys573_state, empty_init, ROT0, "Konami", "DrumMania 9th Mix (G*D09 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ -GAME( 2003, gtfrk10m, sys573, gtrfrk7m, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 10th Mix (G*D10 VER. JAB)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ -GAME( 2003, gtfrk10ma, gtfrk10m, gtrfrk7m, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 10th Mix (G*D10 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ +GAME( 2003, drmn9m, sys573, drmn9m, drmn, ksys573_state, empty_init, ROT0, "Konami", "DrumMania 9th Mix (G*D09 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ +GAME( 2003, gtfrk10m, sys573, gtfrk10m, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 10th Mix (G*D10 VER. JAB)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ +GAME( 2003, gtfrk10ma, gtfrk10m, gtfrk10m, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 10th Mix (G*D10 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ GAME( 2003, gtfrk10mb, gtfrk10m, gtfrk10mb, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 10th Mix eAmusement (G*D10 VER. JBA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ -GAME( 2004, gtfrk11m, sys573, gtrfrk7m, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 11th Mix (G*D39 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ -GAME( 2004, drmn10m, sys573, drmn4m, drmn, ksys573_state, empty_init, ROT0, "Konami", "DrumMania 10th Mix (G*D40 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ +GAME( 2004, gtfrk11m, sys573, gtfrk11m, gtrfrks, ksys573_state, empty_init, ROT0, "Konami", "Guitar Freaks 11th Mix (G*D39 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ +GAME( 2004, drmn10m, sys573, drmn10m, drmn, ksys573_state, empty_init, ROT0, "Konami", "DrumMania 10th Mix (G*D40 VER. JAA)", MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* BOOT VER 1.95 */ diff --git a/src/mame/machine/k573dio.cpp b/src/mame/machine/k573dio.cpp index 2c29645951c..86c92e3c11f 100644 --- a/src/mame/machine/k573dio.cpp +++ b/src/mame/machine/k573dio.cpp @@ -76,13 +76,12 @@ void k573dio_device::amap(address_map &map) map(0x0a, 0x0b).r(FUNC(k573dio_device::a0a_r)); map(0x10, 0x11).w(FUNC(k573dio_device::a10_w)); map(0x80, 0x81).r(FUNC(k573dio_device::a80_r)); - map(0xa8, 0xa9).r(FUNC(k573dio_device::aa8_r)); map(0xc4, 0xc5).r(FUNC(k573dio_device::ac4_r)); map(0xa0, 0xa1).w(FUNC(k573dio_device::mpeg_start_adr_high_w)); map(0xa2, 0xa3).w(FUNC(k573dio_device::mpeg_start_adr_low_w)); map(0xa4, 0xa5).w(FUNC(k573dio_device::mpeg_end_adr_high_w)); map(0xa6, 0xa7).w(FUNC(k573dio_device::mpeg_end_adr_low_w)); - map(0xa8, 0xa9).w(FUNC(k573dio_device::mpeg_key_1_w)); + map(0xa8, 0xa9).rw(FUNC(k573dio_device::mpeg_key_1_r), FUNC(k573dio_device::mpeg_key_1_w)); map(0xac, 0xad).rw(FUNC(k573dio_device::mas_i2c_r), FUNC(k573dio_device::mas_i2c_w)); map(0xae, 0xaf).rw(FUNC(k573dio_device::mpeg_ctrl_r), FUNC(k573dio_device::mpeg_ctrl_w)); map(0xb0, 0xb1).w(FUNC(k573dio_device::ram_write_adr_high_w)); @@ -112,8 +111,7 @@ k573dio_device::k573dio_device(const machine_config &mconfig, const char *tag, d k573fpga(*this, "k573fpga"), digital_id(*this, "digital_id"), output_cb(*this), - is_ddrsbm_fpga(false), - buffer_speed(0x400) + is_ddrsbm_fpga(false) { } @@ -126,7 +124,6 @@ void k573dio_device::device_start() k573fpga->set_ram(ram.get()); k573fpga->set_ddrsbm_fpga(is_ddrsbm_fpga); - k573fpga->set_buffer_speed(buffer_speed); k573fpga->set_mp3_dynamic_base(mp3_dynamic_base); device_reset(); @@ -195,12 +192,6 @@ WRITE16_MEMBER(k573dio_device::a10_w) logerror("%s: a10_w (%s)\n", tag(), machine().describe_context()); } -READ16_MEMBER(k573dio_device::aa8_r) -{ - logerror("%s: aa8_r (%s)\n", tag(), machine().describe_context()); - return 1; -} - READ16_MEMBER(k573dio_device::ac4_r) { // What is this? @@ -237,10 +228,16 @@ WRITE16_MEMBER(k573dio_device::mpeg_end_adr_low_w) k573fpga->set_mp3_end_adr((k573fpga->get_mp3_end_adr() & 0xffff0000) | data); // low } +READ16_MEMBER(k573dio_device::mpeg_key_1_r) +{ + return crypto_key1; +} + WRITE16_MEMBER(k573dio_device::mpeg_key_1_w) { logerror("FPGA MPEG key 1/3 %04x\n", data); k573fpga->set_crypto_key1(data); + crypto_key1 = data; } READ16_MEMBER(k573dio_device::mas_i2c_r) diff --git a/src/mame/machine/k573dio.h b/src/mame/machine/k573dio.h index a0320a00892..e75618139ed 100644 --- a/src/mame/machine/k573dio.h +++ b/src/mame/machine/k573dio.h @@ -20,7 +20,6 @@ public: void amap(address_map &map); void set_ddrsbm_fpga(bool flag) { is_ddrsbm_fpga = flag; } - void set_buffer_speed(uint32_t speed) { buffer_speed = speed; } void set_mp3_dynamic_base(uint32_t base) { mp3_dynamic_base = base; } DECLARE_READ16_MEMBER(a00_r); @@ -30,13 +29,13 @@ public: DECLARE_READ16_MEMBER(a0a_r); DECLARE_WRITE16_MEMBER(a10_w); DECLARE_READ16_MEMBER(a80_r); - DECLARE_READ16_MEMBER(aa8_r); DECLARE_READ16_MEMBER(ac4_r); DECLARE_WRITE16_MEMBER(mpeg_start_adr_high_w); DECLARE_WRITE16_MEMBER(mpeg_start_adr_low_w); DECLARE_WRITE16_MEMBER(mpeg_end_adr_high_w); DECLARE_WRITE16_MEMBER(mpeg_end_adr_low_w); + DECLARE_READ16_MEMBER(mpeg_key_1_r); DECLARE_WRITE16_MEMBER(mpeg_key_1_w); DECLARE_READ16_MEMBER(mas_i2c_r); DECLARE_WRITE16_MEMBER(mas_i2c_w); @@ -84,7 +83,8 @@ private: void output(int offset, uint16_t data); bool is_ddrsbm_fpga; - uint32_t buffer_speed, mp3_dynamic_base; + uint32_t mp3_dynamic_base; + uint16_t crypto_key1; }; DECLARE_DEVICE_TYPE(KONAMI_573_DIGITAL_IO_BOARD, k573dio_device) diff --git a/src/mame/machine/k573fpga.cpp b/src/mame/machine/k573fpga.cpp index f184f99211b..d28a9e076bb 100644 --- a/src/mame/machine/k573fpga.cpp +++ b/src/mame/machine/k573fpga.cpp @@ -5,15 +5,18 @@ #include "k573fpga.h" -// TODO: Check if this is optimal -#define MINIMUM_BUFFER 1 - -// TODO: Is this really needed? Confirm -#define MAX_FRAME_SYNC_MATCHES 1 +// This will delay playback until there are SAMPLES_BUFFER samples in the buffer. +// This fixes some timing issues. Increase value to delay playback. +// The current value was decided by finding a delay that allowed the Konami logo +// to playback on the Drummania 10th Mix loading sequence, but finish just in time +// for the game to send the stop playback command before it looped again. +// TODO: Verify this with real hardware somehow. +#define SAMPLES_BUFFER 1152 * 30 #define MINIMP3_ONLY_MP3 #define MINIMP3_NO_STDIO #define MINIMP3_IMPLEMENTATION +#define MAX_FRAME_SYNC_MATCHES 1 #include "minimp3/minimp3.h" #include "minimp3/minimp3_ex.h" @@ -28,7 +31,7 @@ k573fpga_device::k573fpga_device(const machine_config &mconfig, const char *tag, void k573fpga_device::device_start() { ram_swap = std::make_unique<uint16_t[]>(32 * 1024 * 1024); - save_pointer(NAME(ram_swap), 32 * 1024 * 1024 ); + save_pointer(NAME(ram_swap), 32 * 1024 * 1024); device_reset(); } @@ -40,7 +43,6 @@ void k573fpga_device::device_reset() crypto_key1 = 0; crypto_key2 = 0; crypto_key3 = 0; - mp3_last_frame = 0; mp3_last_adr = 0; mp3_last_decrypt_adr = 0; mp3_next_sync = 0; @@ -61,7 +63,7 @@ void k573fpga_device::device_reset() channel_r_pcm = nullptr; last_buffer_size_channel_r = 0; - memset((void*)ram_swap.get(), 0, 12 * 1024 * 1024 * 2); + memset((void*)ram_swap.get(), 0, 32 * 1024 * 1024 * 2); memset(&mp3_info, 0, sizeof(mp3_info)); mas3507d->set_samples(m_samples); @@ -85,24 +87,21 @@ void k573fpga_device::device_add_mconfig(machine_config &config) } uint32_t k573fpga_device::get_mp3_playback() { - if (mp3_start_adr == 0) { - if (m_samples->get_position(0) == 0 && decrypt_finished) { - // The game is still requesting position updates after the song has ended. - // This happens in some games like DDR 4th Mix Plus where it uses - // the position in song for actual game engine timings. - // The counter will properly end when the game signals to the FPGA to stop playback. - last_position_update += position_diff; - } else { + if (m_samples->get_position(0) == 0 && decrypt_finished) { + // The game is still requesting position updates after the song has ended. + // This happens in some games like DDR 4th Mix Plus where it uses + // the position in song for actual game engine timings. + // The counter will properly end when the game signals to the FPGA to stop playback. + last_position_update += position_diff; + } else { + if (m_samples->get_position(0) - last_position_update > 0) { position_diff = m_samples->get_position(0) - last_position_update; - last_position_update = m_samples->get_position(0); } last_position_update = m_samples->get_position(0); - - return last_position_update; } - return 0; + return last_position_update; } uint16_t k573fpga_device::i2c_read() @@ -121,12 +120,12 @@ void k573fpga_device::i2c_write(uint16_t data) uint16_t k573fpga_device::get_mpeg_ctrl() { - if (mpeg_ctrl_flag == 0xe000 || (m_samples->get_position(0) > 0 && mp3_decrypt_mode)) { + if (mpeg_ctrl_flag == 0xe000 || m_samples->get_position(0) > 0) { // This has been tested with real hardware, but this flag is always held 0x1000 when the audio is being played - return mpeg_ctrl_flag | 0x1000; + return 0x1000; } - return mpeg_ctrl_flag; + return 0x0000; } void k573fpga_device::set_mpeg_ctrl(uint16_t data) @@ -147,7 +146,6 @@ void k573fpga_device::set_mpeg_ctrl(uint16_t data) if ((data & 0xa000) == 0xa000) { // Reset playback state for start and stop events - mp3_last_frame = 0; mp3_next_sync = 0; mp3_last_adr = mp3_start_adr; mp3_last_decrypt_adr = mp3_start_adr; @@ -169,12 +167,6 @@ void k573fpga_device::set_mpeg_ctrl(uint16_t data) channel_r_pcm = nullptr; } } - - if ((data & 0xe000) == 0xe000) { - mp3_decrypt_mode = true; - } else { - mp3_decrypt_mode = false; - } } inline uint16_t k573fpga_device::fpga_decrypt_byte_real(uint16_t v) @@ -268,30 +260,38 @@ inline uint16_t k573fpga_device::fpga_decrypt_byte_ddrsbm(uint16_t data, uint32_ SAMPLES_UPDATE_CB_MEMBER(k573fpga_device::k573fpga_stream_update) { - if ((mpeg_ctrl_flag & 0xe000) != 0xe000 || mp3_last_adr >= mp3_end_adr || (m_samples->get_position(0) < mp3_next_sync && mp3_next_sync != 0)) { + if (mp3_last_adr >= mp3_end_adr) { + mp3_next_sync = 0; + return; + } + + if ((mpeg_ctrl_flag & 0xe000) != 0xe000 || (m_samples->get_position(0) < mp3_next_sync && mp3_next_sync != 0)) { return; } - int new_samples = 0; - - if (!use_ddrsbm_fpga && mp3_start_adr != mp3_dynamic_base) { - // Base addresses are kind of a "hack" and should be dealt with eventually. - // Files that are loaded at he base address are dynamic, meaning the data constantly changes. - // Data will not get loaded outside of the base address region past the boot sequence, however. - // As such, it's possible to decrypt and play the full file if it's not at the designated base address. - // Only 4 games seem to use a base address that is non-0: GF11DM10 (0x00540000) and GF10DM9 (0x00500000). - // This way of doing things seems kind of arbitrary, so it most likely doesn't need to be handled in a - // specific case like this, but this leads to much better performance overall since the data is usually - // small (<1mb). - // Another interesting thing about base addresses is that non-base address files are almost always looped - // in-game, with the exception of the Konami logo sound. Without looping non-base address sounds, things - // like system BGMs and song wheel previews will stop looping. + int new_samples = mp3_info.samples; + int decrypt_buffer_speed = buffer_speed; + if (mp3_next_sync == 0 && last_copied_samples == 0) { crypto_key1 = orig_crypto_key1; crypto_key2 = orig_crypto_key2; crypto_key3 = orig_crypto_key3; - for (int32_t cur_idx = mp3_start_adr; cur_idx < mp3_end_adr; cur_idx += 2) { + mp3_last_decrypt_adr = mp3_start_adr; + + // Cover a large chunk of ID3 or junk at the beginning of a file when decrypting first frame + decrypt_buffer_speed = buffer_speed = 0xe00; + + last_position_update = 0; + position_diff = 0; + decrypt_finished = false; + } + + // Decrypt chunk of data + if (mp3_last_decrypt_adr < mp3_end_adr && mp3_last_adr + decrypt_buffer_speed >= mp3_last_decrypt_adr) { + int32_t cur_idx; + + for (cur_idx = mp3_last_decrypt_adr; cur_idx - mp3_last_decrypt_adr < decrypt_buffer_speed && cur_idx < mp3_end_adr; cur_idx += 2) { if (use_ddrsbm_fpga) { ram_swap[cur_idx >> 1] = fpga_decrypt_byte_ddrsbm(ram[cur_idx >> 1], (cur_idx - mp3_start_adr) / 2); } else { @@ -309,139 +309,74 @@ SAMPLES_UPDATE_CB_MEMBER(k573fpga_device::k573fpga_stream_update) crypto_key3++; } - // Decrypt entire block of memory - if (mp3_info.buffer != NULL) { - free(mp3_info.buffer); - } - - mp3dec_load_buf(&mp3_dec, ((uint8_t*)ram_swap.get()) + mp3_start_adr, mp3_end_adr - mp3_start_adr, &mp3_info, NULL, NULL); - new_samples = mp3_info.samples; - last_copied_samples = 0; - mp3_last_adr += mp3_end_adr - mp3_start_adr; - } else { - // For base address files, decrypt in a streaming manner. - // By the time the play flag is set, there's usually enough data to decode the first frame or two. - // Some files (specifcially GFDM's audio) has a large 0x600 byte ID3 header, so in order to guarantee that - // the first frame is found, I've found it best to decrypt 0x2000 bytes in the first go and then a smaller - // amount after that for every subsequent update. + mp3_last_decrypt_adr = cur_idx; + } - new_samples = mp3_info.samples; + int samples; + int free_format_bytes = 0, frame_size = 0; + int buf_size = decrypt_buffer_speed; + uint8_t *buf = (uint8_t*)ram_swap.get() + mp3_last_adr; - int decrypt_buffer = MINIMUM_BUFFER; - int decrypt_buffer_speed = buffer_speed; + // Detect first frame in MP3 data + if (mp3_next_sync == 0 && last_copied_samples == 0) { + buf_size = 0xe00; - if (mp3_next_sync == 0) { - crypto_key1 = orig_crypto_key1; - crypto_key2 = orig_crypto_key2; - crypto_key3 = orig_crypto_key3; + // Everything on the System 573 has a header 0x600 or less from what I've seen, but just ot be sure, check the first 0xe00 bytes + uint32_t first_frame = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size); + buf += first_frame; + mp3_last_adr += first_frame; + buf_size -= first_frame; - mp3_last_decrypt_adr = mp3_start_adr; + buffer_speed = hdr_frame_bytes(buf, free_format_bytes) * 2; + } - // Cover a large chunk of ID3 or junk at the beginning of a file when decrypting first frame - decrypt_buffer = 1; - decrypt_buffer_speed = 0x2000; + if (mp3_last_adr >= mp3_end_adr) { + mp3_next_sync = 0; + return; + } - last_position_update = 0; - position_diff = 0; - decrypt_finished = false; + if (mp3_next_sync == 0 && last_copied_samples == 0) { + // For the first iteration, we need to set up the MP3 state and such + if (mp3_info.buffer != NULL) { + free(mp3_info.buffer); } - // Decrypt chunk of data - if (mp3_last_decrypt_adr < mp3_end_adr && mp3_last_adr + decrypt_buffer_speed * decrypt_buffer >= mp3_last_decrypt_adr) { - int32_t cur_idx; + memset(&mp3_info, 0, sizeof(mp3_info)); + memset(&mp3_frame_info, 0, sizeof(mp3_frame_info)); + new_samples = 0; - for (cur_idx = mp3_last_decrypt_adr; cur_idx - mp3_last_decrypt_adr < decrypt_buffer_speed * decrypt_buffer && cur_idx < mp3_end_adr; cur_idx += 2) { - if (use_ddrsbm_fpga) { - ram_swap[cur_idx >> 1] = fpga_decrypt_byte_ddrsbm(ram[cur_idx >> 1], (cur_idx - mp3_start_adr) / 2); - } else { - ram_swap[cur_idx >> 1] = fpga_decrypt_byte_real(ram[cur_idx >> 1]); - } + /* try to make allocation size assumption by first frame */ + mp3dec_init(&mp3_dec); - if (!use_ddrsbm_fpga) { - crypto_key1 = (crypto_key1 & 0x8000) | ((crypto_key1 << 1) & 0x7FFE) | ((crypto_key1 >> 14) & 1); + samples = mp3dec_decode_frame(&mp3_dec, buf, buf_size, mp3_pcm, &mp3_frame_info); - if ((((crypto_key1 >> 15) ^ crypto_key1) & 1) != 0) { - crypto_key2 = (crypto_key2 << 1) | (crypto_key2 >> 15); - } - } - - crypto_key3++; - } - - mp3_last_decrypt_adr = cur_idx; + if (!samples) { + return; } - int samples; - int free_format_bytes = 0, frame_size = 0; - int buf_size = decrypt_buffer_speed * decrypt_buffer; - - uint8_t *buf = (uint8_t*)ram_swap.get() + mp3_last_adr; + samples *= mp3_frame_info.channels; - // Detect first frame in MP3 data - if (mp3_next_sync == 0) { - buf_size = 0x2000; - - // Everything on the System 573 has a header 0x600 or less from what I've seen, but just ot be sure, check the first 0x2000 bytes - uint32_t first_frame = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size); - buf += first_frame; - mp3_last_adr += first_frame; - buf_size -= first_frame; - } + mp3_allocated = (buf_size / mp3_frame_info.frame_bytes) * samples * sizeof(mp3d_sample_t) + MINIMP3_MAX_SAMPLES_PER_FRAME * sizeof(mp3d_sample_t); + mp3_info.buffer = (mp3d_sample_t*)malloc(mp3_allocated); - // Skip x amount of samples previously read (this fixes some weird glitches) - for (int frame_skip = 0; frame_skip < mp3_last_frame && buf < (uint8_t*)ram_swap.get() + mp3_end_adr; frame_skip++) { - mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size); - buf += frame_size; - mp3_last_adr += frame_size; + if (!mp3_info.buffer) { + return; } - mp3_last_frame = 0; - - if (mp3_next_sync == 0) { - // For the first iteration, we need to set up the MP3 state and such - if (mp3_info.buffer != NULL) { - free(mp3_info.buffer); - } - - memset(&mp3_info, 0, sizeof(mp3_info)); - memset(&mp3_frame_info, 0, sizeof(mp3_frame_info)); - new_samples = 0; - - /* try to make allocation size assumption by first frame */ - mp3dec_init(&mp3_dec); - - samples = mp3dec_decode_frame(&mp3_dec, buf, buf_size, mp3_pcm, &mp3_frame_info); - - if (!samples) { - return; - } - - samples *= mp3_frame_info.channels; - - mp3_allocated = (buf_size / mp3_frame_info.frame_bytes) * samples * sizeof(mp3d_sample_t) + MINIMP3_MAX_SAMPLES_PER_FRAME * sizeof(mp3d_sample_t); - mp3_info.buffer = (mp3d_sample_t*)malloc(mp3_allocated); - - if (!mp3_info.buffer) { - return; - } - - mp3_info.samples = samples; - memcpy(mp3_info.buffer, mp3_pcm, mp3_info.samples * sizeof(mp3d_sample_t)); - - /* save info */ - mp3_info.channels = mp3_frame_info.channels; - mp3_info.hz = mp3_frame_info.hz; - mp3_info.layer = mp3_frame_info.layer; - mp3_last_frame = 0; - - decrypt_buffer = 8; - } + mp3_info.samples = samples; + memcpy(mp3_info.buffer, mp3_pcm, mp3_info.samples * sizeof(mp3d_sample_t)); + /* save info */ + mp3_info.channels = mp3_frame_info.channels; + mp3_info.hz = mp3_frame_info.hz; + mp3_info.layer = mp3_frame_info.layer; + mp3_last_adr += mp3_frame_info.frame_bytes; + } else { /* decode rest frames */ buf_size = decrypt_buffer_speed * 2; - for (int frame_skip = 0; frame_skip < decrypt_buffer && buf < (uint8_t*)ram_swap.get() + mp3_end_adr; frame_skip++) { + if (buf < (uint8_t*)ram_swap.get() + mp3_end_adr) { if (buf + buf_size > (uint8_t*)ram_swap.get() + mp3_end_adr) { buf_size = ((uint8_t*)ram_swap.get() + mp3_end_adr) - buf; } @@ -452,36 +387,25 @@ SAMPLES_UPDATE_CB_MEMBER(k573fpga_device::k573fpga_stream_update) samples = mp3dec_decode_frame(&mp3_dec, buf, buf_size, mp3_info.buffer + mp3_info.samples, &mp3_frame_info); - if (buf + buf_size >= (uint8_t*)ram_swap.get() + mp3_end_adr) { - // Some songs have a weird frame at the very end of the song which can be skipped usually. - mp3_last_adr += buf_size; - break; - } - if (!samples) { mp3_last_decrypt_adr = mp3_start_adr; // Force it to redecrypt everything in case the previous decrypt was too fast to find a full frame crypto_key1 = orig_crypto_key1; crypto_key2 = orig_crypto_key2; crypto_key3 = orig_crypto_key3; - break; - } - if (mp3_info.hz != mp3_frame_info.hz || mp3_info.layer != mp3_frame_info.layer) { - break; - } - - if (mp3_info.channels && mp3_info.channels != mp3_frame_info.channels) { - break; + if (buf + buf_size >= (uint8_t*)ram_swap.get() + mp3_end_adr) { + // Some songs have a weird frame at the very end of the song which can be skipped usually. + mp3_last_adr += buf_size; + } + } else if (mp3_info.hz == mp3_frame_info.hz && mp3_info.layer == mp3_frame_info.layer && mp3_info.channels && mp3_info.channels == mp3_frame_info.channels) { + mp3_last_adr += mp3_frame_info.frame_bytes; + mp3_info.samples += samples * mp3_frame_info.channels; } - - buf += mp3_frame_info.frame_bytes; - mp3_info.samples += samples * mp3_frame_info.channels; - mp3_last_frame++; } - - new_samples = mp3_info.samples - new_samples; } + new_samples = mp3_info.samples - new_samples; + if (new_samples > 0) { size_t buffer_size = 0; @@ -541,10 +465,12 @@ SAMPLES_UPDATE_CB_MEMBER(k573fpga_device::k573fpga_stream_update) last_copied_samples = buffer_size; - m_samples->update_raw(0, channel_l_pcm, buffer_size, mp3_info.hz, mp3_start_adr != mp3_dynamic_base); - m_samples->update_raw(1, channel_r_pcm, buffer_size, mp3_info.hz, mp3_start_adr != mp3_dynamic_base); + if (last_copied_samples > SAMPLES_BUFFER) { + m_samples->update_raw(0, channel_l_pcm, buffer_size, mp3_info.hz, mp3_start_adr != mp3_dynamic_base); + m_samples->update_raw(1, channel_r_pcm, buffer_size, mp3_info.hz, mp3_start_adr != mp3_dynamic_base); - mp3_next_sync = buffer_size - (buffer_size / 3); // Grab more data sometime before the current buffer ends. This is arbitrary and kinda hacky, but it worked best between various games in my testing. + mp3_next_sync = buffer_size - (buffer_size / 4); // Grab more data sometime before the current buffer ends. This is arbitrary and kinda hacky, but it worked best between various games in my testing. + } } if (mp3_last_adr >= mp3_end_adr) { diff --git a/src/mame/machine/k573fpga.h b/src/mame/machine/k573fpga.h index 0ef9481a6a9..71b949b4419 100644 --- a/src/mame/machine/k573fpga.h +++ b/src/mame/machine/k573fpga.h @@ -47,7 +47,6 @@ public: uint16_t get_mpeg_ctrl(); void set_mpeg_ctrl(uint16_t data); - void set_buffer_speed(uint32_t speed) { buffer_speed = speed; } void set_mp3_dynamic_base(uint32_t base) { mp3_dynamic_base = base; } protected: @@ -65,11 +64,11 @@ private: uint32_t mp3_start_adr, mp3_end_adr, mpeg_ctrl_flag; bool use_ddrsbm_fpga; - uint32_t mp3_last_frame, mp3_last_adr, mp3_next_sync, mp3_last_decrypt_adr; + uint32_t mp3_last_adr, mp3_next_sync, mp3_last_decrypt_adr; int16_t *channel_l_pcm, *channel_r_pcm; size_t last_buffer_size_channel_l, last_buffer_size_channel_r, last_copied_samples; uint32_t last_position_update, position_diff; - bool mp3_decrypt_mode, decrypt_finished; + bool decrypt_finished; mp3d_sample_t mp3_pcm[MINIMP3_MAX_SAMPLES_PER_FRAME]; mp3dec_file_info_t mp3_info; |