summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit347fb288ad6eb2dd6be683a7e938dfb6014cf284 (patch)
tree0ba99e2567e40915e2f7c892a9788410fc43555f
parentc16b3d8a8b372ceb9d302d7d47f61f534eb53a84 (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.cpp69
-rw-r--r--src/mame/machine/k573dio.cpp19
-rw-r--r--src/mame/machine/k573dio.h6
-rw-r--r--src/mame/machine/k573fpga.cpp286
-rw-r--r--src/mame/machine/k573fpga.h5
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;