summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/k573fpga.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/k573fpga.cpp')
-rw-r--r--src/mame/machine/k573fpga.cpp804
1 files changed, 402 insertions, 402 deletions
diff --git a/src/mame/machine/k573fpga.cpp b/src/mame/machine/k573fpga.cpp
index d28a9e076bb..eb2197f7c77 100644
--- a/src/mame/machine/k573fpga.cpp
+++ b/src/mame/machine/k573fpga.cpp
@@ -21,461 +21,461 @@
#include "minimp3/minimp3_ex.h"
k573fpga_device::k573fpga_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, KONAMI_573_DIGITAL_FPGA, tag, owner, clock),
- mas3507d(*this, "mpeg"),
- m_samples(*this, "samples"),
- use_ddrsbm_fpga(false)
+ device_t(mconfig, KONAMI_573_DIGITAL_FPGA, tag, owner, clock),
+ mas3507d(*this, "mpeg"),
+ m_samples(*this, "samples"),
+ use_ddrsbm_fpga(false)
{
}
void k573fpga_device::device_start()
{
- ram_swap = std::make_unique<uint16_t[]>(32 * 1024 * 1024);
- save_pointer(NAME(ram_swap), 32 * 1024 * 1024);
+ ram_swap = std::make_unique<uint16_t[]>(32 * 1024 * 1024);
+ save_pointer(NAME(ram_swap), 32 * 1024 * 1024);
- device_reset();
+ device_reset();
}
void k573fpga_device::device_reset()
{
- mp3_start_adr = 0;
- mp3_end_adr = 0;
- crypto_key1 = 0;
- crypto_key2 = 0;
- crypto_key3 = 0;
- mp3_last_adr = 0;
- mp3_last_decrypt_adr = 0;
- mp3_next_sync = 0;
- last_copied_samples = 0;
- decrypt_finished = false;
-
- if (!channel_l_pcm) {
- free(channel_l_pcm);
- }
-
- channel_l_pcm = nullptr;
- last_buffer_size_channel_l = 0;
-
- if (!channel_r_pcm) {
- free(channel_r_pcm);
- }
-
- channel_r_pcm = nullptr;
- last_buffer_size_channel_r = 0;
-
- memset((void*)ram_swap.get(), 0, 32 * 1024 * 1024 * 2);
- memset(&mp3_info, 0, sizeof(mp3_info));
-
- mas3507d->set_samples(m_samples);
-
- last_position_update = 0;
- position_diff = 0;
+ mp3_start_adr = 0;
+ mp3_end_adr = 0;
+ crypto_key1 = 0;
+ crypto_key2 = 0;
+ crypto_key3 = 0;
+ mp3_last_adr = 0;
+ mp3_last_decrypt_adr = 0;
+ mp3_next_sync = 0;
+ last_copied_samples = 0;
+ decrypt_finished = false;
+
+ if (!channel_l_pcm) {
+ free(channel_l_pcm);
+ }
+
+ channel_l_pcm = nullptr;
+ last_buffer_size_channel_l = 0;
+
+ if (!channel_r_pcm) {
+ free(channel_r_pcm);
+ }
+
+ channel_r_pcm = nullptr;
+ last_buffer_size_channel_r = 0;
+
+ memset((void*)ram_swap.get(), 0, 32 * 1024 * 1024 * 2);
+ memset(&mp3_info, 0, sizeof(mp3_info));
+
+ mas3507d->set_samples(m_samples);
+
+ last_position_update = 0;
+ position_diff = 0;
}
void k573fpga_device::device_add_mconfig(machine_config &config)
{
- MAS3507D(config, "mpeg");
-
- /* sound hardware */
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
- SAMPLES(config, m_samples);
- m_samples->set_channels(2);
- m_samples->set_samples_update_callback(FUNC(k573fpga_device::k573fpga_stream_update));
- m_samples->add_route(0, "lspeaker", 1.0);
- m_samples->add_route(1, "rspeaker", 1.0);
+ MAS3507D(config, "mpeg");
+
+ /* sound hardware */
+ SPEAKER(config, "lspeaker").front_left();
+ SPEAKER(config, "rspeaker").front_right();
+ SAMPLES(config, m_samples);
+ m_samples->set_channels(2);
+ m_samples->set_samples_update_callback(FUNC(k573fpga_device::k573fpga_stream_update));
+ m_samples->add_route(0, "lspeaker", 1.0);
+ m_samples->add_route(1, "rspeaker", 1.0);
}
uint32_t k573fpga_device::get_mp3_playback() {
- 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);
- }
-
- return last_position_update;
+ 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);
+ }
+
+ return last_position_update;
}
uint16_t k573fpga_device::i2c_read()
{
- int scl = mas3507d->i2c_scl_r() << 13;
- int sda = mas3507d->i2c_sda_r() << 12;
+ int scl = mas3507d->i2c_scl_r() << 13;
+ int sda = mas3507d->i2c_sda_r() << 12;
- return scl | sda;
+ return scl | sda;
}
void k573fpga_device::i2c_write(uint16_t data)
{
- mas3507d->i2c_scl_w(data & 0x2000);
- mas3507d->i2c_sda_w(data & 0x1000);
+ mas3507d->i2c_scl_w(data & 0x2000);
+ mas3507d->i2c_sda_w(data & 0x1000);
}
uint16_t k573fpga_device::get_mpeg_ctrl()
{
- 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 0x1000;
- }
+ 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 0x1000;
+ }
- return 0x0000;
+ return 0x0000;
}
void k573fpga_device::set_mpeg_ctrl(uint16_t data)
{
- logerror("FPGA MPEG control %c%c%c | %08x %08x\n",
- data & 0x8000 ? '#' : '.',
- data & 0x4000 ? '#' : '.',
- data & 0x2000 ? '#' : '.',
- mp3_start_adr, mp3_end_adr);
-
- mpeg_ctrl_flag = data;
-
- if (data == 0xa000) {
- // Stop playback
- m_samples->stop(0);
- m_samples->stop(1);
- }
-
- if ((data & 0xa000) == 0xa000) {
- // Reset playback state for start and stop events
- mp3_next_sync = 0;
- mp3_last_adr = mp3_start_adr;
- mp3_last_decrypt_adr = mp3_start_adr;
- last_copied_samples = 0;
- last_buffer_size_channel_l = 0;
- last_buffer_size_channel_r = 0;
-
- last_position_update = 0;
- position_diff = 0;
- decrypt_finished = false;
-
- if (channel_l_pcm) {
- free(channel_l_pcm);
- channel_l_pcm = nullptr;
- }
-
- if (channel_r_pcm) {
- free(channel_r_pcm);
- channel_r_pcm = nullptr;
- }
- }
+ logerror("FPGA MPEG control %c%c%c | %08x %08x\n",
+ data & 0x8000 ? '#' : '.',
+ data & 0x4000 ? '#' : '.',
+ data & 0x2000 ? '#' : '.',
+ mp3_start_adr, mp3_end_adr);
+
+ mpeg_ctrl_flag = data;
+
+ if (data == 0xa000) {
+ // Stop playback
+ m_samples->stop(0);
+ m_samples->stop(1);
+ }
+
+ if ((data & 0xa000) == 0xa000) {
+ // Reset playback state for start and stop events
+ mp3_next_sync = 0;
+ mp3_last_adr = mp3_start_adr;
+ mp3_last_decrypt_adr = mp3_start_adr;
+ last_copied_samples = 0;
+ last_buffer_size_channel_l = 0;
+ last_buffer_size_channel_r = 0;
+
+ last_position_update = 0;
+ position_diff = 0;
+ decrypt_finished = false;
+
+ if (channel_l_pcm) {
+ free(channel_l_pcm);
+ channel_l_pcm = nullptr;
+ }
+
+ if (channel_r_pcm) {
+ free(channel_r_pcm);
+ channel_r_pcm = nullptr;
+ }
+ }
}
inline uint16_t k573fpga_device::fpga_decrypt_byte_real(uint16_t v)
{
- uint16_t m = crypto_key1 ^ crypto_key2;
-
- v = bitswap<16>(
- v,
- 15 - BIT(m, 0xF),
- 14 + BIT(m, 0xF),
- 13 - BIT(m, 0xE),
- 12 + BIT(m, 0xE),
- 11 - BIT(m, 0xB),
- 10 + BIT(m, 0xB),
- 9 - BIT(m, 0x9),
- 8 + BIT(m, 0x9),
- 7 - BIT(m, 0x8),
- 6 + BIT(m, 0x8),
- 5 - BIT(m, 0x5),
- 4 + BIT(m, 0x5),
- 3 - BIT(m, 0x3),
- 2 + BIT(m, 0x3),
- 1 - BIT(m, 0x2),
- 0 + BIT(m, 0x2)
- );
-
- v ^= (BIT(m, 0xD) << 14) ^
- (BIT(m, 0xC) << 12) ^
- (BIT(m, 0xA) << 10) ^
- (BIT(m, 0x7) << 8) ^
- (BIT(m, 0x6) << 6) ^
- (BIT(m, 0x4) << 4) ^
- (BIT(m, 0x1) << 2) ^
- (BIT(m, 0x0) << 0);
-
- v ^= bitswap<16>(
- (uint16_t)crypto_key3,
- 7, 0, 6, 1,
- 5, 2, 4, 3,
- 3, 4, 2, 5,
- 1, 6, 0, 7
- );
-
- return (v >> 8) | ((v & 0xff) << 8);
+ uint16_t m = crypto_key1 ^ crypto_key2;
+
+ v = bitswap<16>(
+ v,
+ 15 - BIT(m, 0xF),
+ 14 + BIT(m, 0xF),
+ 13 - BIT(m, 0xE),
+ 12 + BIT(m, 0xE),
+ 11 - BIT(m, 0xB),
+ 10 + BIT(m, 0xB),
+ 9 - BIT(m, 0x9),
+ 8 + BIT(m, 0x9),
+ 7 - BIT(m, 0x8),
+ 6 + BIT(m, 0x8),
+ 5 - BIT(m, 0x5),
+ 4 + BIT(m, 0x5),
+ 3 - BIT(m, 0x3),
+ 2 + BIT(m, 0x3),
+ 1 - BIT(m, 0x2),
+ 0 + BIT(m, 0x2)
+ );
+
+ v ^= (BIT(m, 0xD) << 14) ^
+ (BIT(m, 0xC) << 12) ^
+ (BIT(m, 0xA) << 10) ^
+ (BIT(m, 0x7) << 8) ^
+ (BIT(m, 0x6) << 6) ^
+ (BIT(m, 0x4) << 4) ^
+ (BIT(m, 0x1) << 2) ^
+ (BIT(m, 0x0) << 0);
+
+ v ^= bitswap<16>(
+ (uint16_t)crypto_key3,
+ 7, 0, 6, 1,
+ 5, 2, 4, 3,
+ 3, 4, 2, 5,
+ 1, 6, 0, 7
+ );
+
+ return (v >> 8) | ((v & 0xff) << 8);
}
inline uint16_t k573fpga_device::fpga_decrypt_byte_ddrsbm(uint16_t data, uint32_t crypto_idx)
{
- uint8_t key[16] = {0};
- uint16_t key_state = bitswap<16>(
- crypto_key1,
- 13, 11, 9, 7,
- 5, 3, 1, 15,
- 14, 12, 10, 8,
- 6, 4, 2, 0
- );
-
- for (int i = 0; i < 8; i++) {
- key[i * 2] = key_state & 0xff;
- key[i * 2 + 1] = (key_state >> 8) & 0xff;
- key_state = (((((key_state >> 8) >> 7) & 1) | (((key_state >> 8) << 1) & 0xff)) << 8) |
- (((key_state & 0xff) >> 7) & 1) | (((key_state & 0xff) << 1) & 0xff);
- }
-
- uint16_t output_word = 0;
- for (int cur_bit = 0; cur_bit < 8; cur_bit++) {
- int even_bit_shift = (cur_bit * 2) & 0xff;
- int odd_bit_shift = (cur_bit * 2 + 1) & 0xff;
- int is_even_bit_set = (data & (1 << even_bit_shift)) != 0;
- int is_odd_bit_set = (data & (1 << odd_bit_shift)) != 0;
- int is_key_bit_set = (key[crypto_idx % 16] & (1 << cur_bit)) != 0;
- int is_scramble_bit_set = (key[(crypto_idx - 1) % 16] & (1 << cur_bit)) != 0;
-
- if (is_scramble_bit_set == 1) {
- int t = is_even_bit_set;
- is_even_bit_set = is_odd_bit_set;
- is_odd_bit_set = t;
- }
-
- if (((is_even_bit_set ^ is_key_bit_set)) == 1) {
- output_word |= 1 << even_bit_shift;
- }
-
- if ((is_odd_bit_set) == 1) {
- output_word |= 1 << odd_bit_shift;
- }
- }
-
- return (output_word >> 8) | ((output_word & 0xff) << 8);
+ uint8_t key[16] = {0};
+ uint16_t key_state = bitswap<16>(
+ crypto_key1,
+ 13, 11, 9, 7,
+ 5, 3, 1, 15,
+ 14, 12, 10, 8,
+ 6, 4, 2, 0
+ );
+
+ for (int i = 0; i < 8; i++) {
+ key[i * 2] = key_state & 0xff;
+ key[i * 2 + 1] = (key_state >> 8) & 0xff;
+ key_state = (((((key_state >> 8) >> 7) & 1) | (((key_state >> 8) << 1) & 0xff)) << 8) |
+ (((key_state & 0xff) >> 7) & 1) | (((key_state & 0xff) << 1) & 0xff);
+ }
+
+ uint16_t output_word = 0;
+ for (int cur_bit = 0; cur_bit < 8; cur_bit++) {
+ int even_bit_shift = (cur_bit * 2) & 0xff;
+ int odd_bit_shift = (cur_bit * 2 + 1) & 0xff;
+ int is_even_bit_set = (data & (1 << even_bit_shift)) != 0;
+ int is_odd_bit_set = (data & (1 << odd_bit_shift)) != 0;
+ int is_key_bit_set = (key[crypto_idx % 16] & (1 << cur_bit)) != 0;
+ int is_scramble_bit_set = (key[(crypto_idx - 1) % 16] & (1 << cur_bit)) != 0;
+
+ if (is_scramble_bit_set == 1) {
+ int t = is_even_bit_set;
+ is_even_bit_set = is_odd_bit_set;
+ is_odd_bit_set = t;
+ }
+
+ if (((is_even_bit_set ^ is_key_bit_set)) == 1) {
+ output_word |= 1 << even_bit_shift;
+ }
+
+ if ((is_odd_bit_set) == 1) {
+ output_word |= 1 << odd_bit_shift;
+ }
+ }
+
+ return (output_word >> 8) | ((output_word & 0xff) << 8);
}
SAMPLES_UPDATE_CB_MEMBER(k573fpga_device::k573fpga_stream_update)
{
- if (mp3_last_adr >= mp3_end_adr) {
- mp3_next_sync = 0;
- return;
- }
+ 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;
- }
+ if ((mpeg_ctrl_flag & 0xe000) != 0xe000 || (m_samples->get_position(0) < mp3_next_sync && mp3_next_sync != 0)) {
+ return;
+ }
- int new_samples = mp3_info.samples;
- int decrypt_buffer_speed = buffer_speed;
+ 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;
+ if (mp3_next_sync == 0 && last_copied_samples == 0) {
+ crypto_key1 = orig_crypto_key1;
+ crypto_key2 = orig_crypto_key2;
+ crypto_key3 = orig_crypto_key3;
- mp3_last_decrypt_adr = mp3_start_adr;
+ 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;
- }
+ // 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 {
- ram_swap[cur_idx >> 1] = fpga_decrypt_byte_real(ram[cur_idx >> 1]);
- }
-
- if (!use_ddrsbm_fpga) {
- crypto_key1 = (crypto_key1 & 0x8000) | ((crypto_key1 << 1) & 0x7FFE) | ((crypto_key1 >> 14) & 1);
-
- if ((((crypto_key1 >> 15) ^ crypto_key1) & 1) != 0) {
- crypto_key2 = (crypto_key2 << 1) | (crypto_key2 >> 15);
- }
- }
-
- crypto_key3++;
- }
-
- mp3_last_decrypt_adr = cur_idx;
- }
-
- 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;
-
- // Detect first frame in MP3 data
- if (mp3_next_sync == 0 && last_copied_samples == 0) {
- buf_size = 0xe00;
-
- // 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;
-
- buffer_speed = hdr_frame_bytes(buf, free_format_bytes) * 2;
- }
-
- if (mp3_last_adr >= mp3_end_adr) {
- mp3_next_sync = 0;
- return;
- }
-
- 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);
- }
-
- 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_adr += mp3_frame_info.frame_bytes;
- } else {
- /* decode rest frames */
- buf_size = decrypt_buffer_speed * 2;
-
- 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;
- }
- if ((mp3_allocated - mp3_info.samples * sizeof(mp3d_sample_t)) < MINIMP3_MAX_SAMPLES_PER_FRAME * sizeof(mp3d_sample_t)) {
- mp3_allocated *= 2;
- mp3_info.buffer = (mp3d_sample_t*)realloc(mp3_info.buffer, mp3_allocated);
- }
-
- samples = mp3dec_decode_frame(&mp3_dec, buf, buf_size, mp3_info.buffer + mp3_info.samples, &mp3_frame_info);
-
- 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;
-
- 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;
- }
- }
- }
-
- new_samples = mp3_info.samples - new_samples;
-
- if (new_samples > 0) {
- size_t buffer_size = 0;
-
- if (mp3_info.channels == 1) {
- buffer_size = mp3_info.samples;
- } else {
- buffer_size = mp3_info.samples / 2;
- }
-
- if (channel_l_pcm == nullptr) {
- last_buffer_size_channel_l = buffer_size * 2;
-
- if (last_buffer_size_channel_l == 0) {
- last_buffer_size_channel_l = 0x1000;
- }
-
- channel_l_pcm = (mp3d_sample_t*)calloc(last_buffer_size_channel_l, sizeof(mp3d_sample_t));
- } else if (buffer_size > last_buffer_size_channel_l) {
- // realloc
- last_buffer_size_channel_l = buffer_size * 2;
-
- if (last_buffer_size_channel_l == 0) {
- last_buffer_size_channel_l = 0x1000;
- }
-
- channel_l_pcm = (mp3d_sample_t*)realloc(channel_l_pcm, last_buffer_size_channel_l * sizeof(mp3d_sample_t));
- }
-
- if (channel_r_pcm == nullptr) {
- last_buffer_size_channel_r = buffer_size * 2;
-
- if (last_buffer_size_channel_r == 0) {
- last_buffer_size_channel_r = 0x1000;
- }
-
- channel_r_pcm = (mp3d_sample_t*)calloc(last_buffer_size_channel_r, sizeof(mp3d_sample_t));
- } else if (buffer_size > last_buffer_size_channel_r) {
- // realloc
- last_buffer_size_channel_r = buffer_size * 2;
-
- if (last_buffer_size_channel_r == 0) {
- last_buffer_size_channel_r = 0x1000;
- }
-
- channel_r_pcm = (mp3d_sample_t*)realloc(channel_r_pcm, last_buffer_size_channel_r * sizeof(mp3d_sample_t));
- }
-
- if (mp3_info.channels == 1) {
- memcpy(((int8_t*)channel_l_pcm) + (last_copied_samples * sizeof(mp3d_sample_t)), ((int8_t*)mp3_info.buffer) + (last_copied_samples * sizeof(mp3d_sample_t)), (buffer_size - last_copied_samples) * sizeof(mp3d_sample_t));
- memcpy(((int8_t*)channel_r_pcm) + (last_copied_samples * sizeof(mp3d_sample_t)), ((int8_t*)mp3_info.buffer) + (last_copied_samples * sizeof(mp3d_sample_t)), (buffer_size - last_copied_samples) * sizeof(mp3d_sample_t));
- } else {
- for (size_t i = last_copied_samples; i < buffer_size; i++) {
- channel_l_pcm[i] = mp3_info.buffer[i * sizeof(mp3d_sample_t)];
- channel_r_pcm[i] = mp3_info.buffer[i * sizeof(mp3d_sample_t) + 1];
- }
- }
-
- last_copied_samples = buffer_size;
-
- 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 / 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) {
- decrypt_finished = true;
- }
+ // 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 {
+ ram_swap[cur_idx >> 1] = fpga_decrypt_byte_real(ram[cur_idx >> 1]);
+ }
+
+ if (!use_ddrsbm_fpga) {
+ crypto_key1 = (crypto_key1 & 0x8000) | ((crypto_key1 << 1) & 0x7FFE) | ((crypto_key1 >> 14) & 1);
+
+ if ((((crypto_key1 >> 15) ^ crypto_key1) & 1) != 0) {
+ crypto_key2 = (crypto_key2 << 1) | (crypto_key2 >> 15);
+ }
+ }
+
+ crypto_key3++;
+ }
+
+ mp3_last_decrypt_adr = cur_idx;
+ }
+
+ 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;
+
+ // Detect first frame in MP3 data
+ if (mp3_next_sync == 0 && last_copied_samples == 0) {
+ buf_size = 0xe00;
+
+ // 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;
+
+ buffer_speed = hdr_frame_bytes(buf, free_format_bytes) * 2;
+ }
+
+ if (mp3_last_adr >= mp3_end_adr) {
+ mp3_next_sync = 0;
+ return;
+ }
+
+ 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);
+ }
+
+ 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_adr += mp3_frame_info.frame_bytes;
+ } else {
+ /* decode rest frames */
+ buf_size = decrypt_buffer_speed * 2;
+
+ 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;
+ }
+ if ((mp3_allocated - mp3_info.samples * sizeof(mp3d_sample_t)) < MINIMP3_MAX_SAMPLES_PER_FRAME * sizeof(mp3d_sample_t)) {
+ mp3_allocated *= 2;
+ mp3_info.buffer = (mp3d_sample_t*)realloc(mp3_info.buffer, mp3_allocated);
+ }
+
+ samples = mp3dec_decode_frame(&mp3_dec, buf, buf_size, mp3_info.buffer + mp3_info.samples, &mp3_frame_info);
+
+ 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;
+
+ 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;
+ }
+ }
+ }
+
+ new_samples = mp3_info.samples - new_samples;
+
+ if (new_samples > 0) {
+ size_t buffer_size = 0;
+
+ if (mp3_info.channels == 1) {
+ buffer_size = mp3_info.samples;
+ } else {
+ buffer_size = mp3_info.samples / 2;
+ }
+
+ if (channel_l_pcm == nullptr) {
+ last_buffer_size_channel_l = buffer_size * 2;
+
+ if (last_buffer_size_channel_l == 0) {
+ last_buffer_size_channel_l = 0x1000;
+ }
+
+ channel_l_pcm = (mp3d_sample_t*)calloc(last_buffer_size_channel_l, sizeof(mp3d_sample_t));
+ } else if (buffer_size > last_buffer_size_channel_l) {
+ // realloc
+ last_buffer_size_channel_l = buffer_size * 2;
+
+ if (last_buffer_size_channel_l == 0) {
+ last_buffer_size_channel_l = 0x1000;
+ }
+
+ channel_l_pcm = (mp3d_sample_t*)realloc(channel_l_pcm, last_buffer_size_channel_l * sizeof(mp3d_sample_t));
+ }
+
+ if (channel_r_pcm == nullptr) {
+ last_buffer_size_channel_r = buffer_size * 2;
+
+ if (last_buffer_size_channel_r == 0) {
+ last_buffer_size_channel_r = 0x1000;
+ }
+
+ channel_r_pcm = (mp3d_sample_t*)calloc(last_buffer_size_channel_r, sizeof(mp3d_sample_t));
+ } else if (buffer_size > last_buffer_size_channel_r) {
+ // realloc
+ last_buffer_size_channel_r = buffer_size * 2;
+
+ if (last_buffer_size_channel_r == 0) {
+ last_buffer_size_channel_r = 0x1000;
+ }
+
+ channel_r_pcm = (mp3d_sample_t*)realloc(channel_r_pcm, last_buffer_size_channel_r * sizeof(mp3d_sample_t));
+ }
+
+ if (mp3_info.channels == 1) {
+ memcpy(((int8_t*)channel_l_pcm) + (last_copied_samples * sizeof(mp3d_sample_t)), ((int8_t*)mp3_info.buffer) + (last_copied_samples * sizeof(mp3d_sample_t)), (buffer_size - last_copied_samples) * sizeof(mp3d_sample_t));
+ memcpy(((int8_t*)channel_r_pcm) + (last_copied_samples * sizeof(mp3d_sample_t)), ((int8_t*)mp3_info.buffer) + (last_copied_samples * sizeof(mp3d_sample_t)), (buffer_size - last_copied_samples) * sizeof(mp3d_sample_t));
+ } else {
+ for (size_t i = last_copied_samples; i < buffer_size; i++) {
+ channel_l_pcm[i] = mp3_info.buffer[i * sizeof(mp3d_sample_t)];
+ channel_r_pcm[i] = mp3_info.buffer[i * sizeof(mp3d_sample_t) + 1];
+ }
+ }
+
+ last_copied_samples = buffer_size;
+
+ 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 / 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) {
+ decrypt_finished = true;
+ }
}
DEFINE_DEVICE_TYPE(KONAMI_573_DIGITAL_FPGA, k573fpga_device, "k573fpga", "Konami 573 Digital I/O FPGA")