// license:BSD-3-Clause
// copyright-holders:windyfairy
#include "emu.h"
#include "speaker.h"
#include "k573fpga.h"
k573fpga_device::k573fpga_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, KONAMI_573_DIGITAL_FPGA, tag, owner, clock),
use_ddrsbm_fpga(false)
{
}
void k573fpga_device::device_start()
{
}
void k573fpga_device::device_reset()
{
mp3_cur_adr = 0;
mp3_end_adr = 0;
crypto_key1 = 0;
crypto_key2 = 0;
crypto_key3 = 0;
}
u16 k573fpga_device::get_mpeg_ctrl()
{
if ((mpeg_ctrl_flag & 0xe000) == 0xe000) {
// This has been tested with real hardware, but this flag is always held 0x1000 when the audio is being played
return 0x1000;
}
return 0x0000;
}
void k573fpga_device::set_mpeg_ctrl(u16 data)
{
logerror("FPGA MPEG control %c%c%c | %08x %08x\n",
data & 0x8000 ? '#' : '.',
data & 0x4000 ? '#' : '.',
data & 0x2000 ? '#' : '.',
mp3_cur_adr, mp3_end_adr);
mpeg_ctrl_flag = data;
}
u16 k573fpga_device::decrypt_default(u16 v)
{
u16 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>(
(u16)crypto_key3,
7, 0, 6, 1,
5, 2, 4, 3,
3, 4, 2, 5,
1, 6, 0, 7
);
crypto_key1 = (crypto_key1 & 0x8000) | ((crypto_key1 << 1) & 0x7FFE) | ((crypto_key1 >> 14) & 1);
if(((crypto_key1 >> 15) ^ crypto_key1) & 1)
crypto_key2 = (crypto_key2 << 1) | (crypto_key2 >> 15);
crypto_key3++;
return v;
}
u16 k573fpga_device::decrypt_ddrsbm(u16 data)
{
u8 key[16] = {0};
u16 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 & 0x8080) >> 7) | ((key_state & 0x7f7f) << 1);
}
u16 output_word = 0;
for(int cur_bit = 0; cur_bit < 8; cur_bit++) {
int even_bit_shift = cur_bit * 2;
int odd_bit_shift = cur_bit * 2 + 1;
bool is_even_bit_set = data & (1 << even_bit_shift);
bool is_odd_bit_set = data & (1 << odd_bit_shift);
bool is_key_bit_set = key[crypto_key3 & 15] & (1 << cur_bit);
bool is_scramble_bit_set = key[(crypto_key3 - 1) & 15] & (1 << cur_bit);
if(is_scramble_bit_set)
std::swap(is_even_bit_set, is_odd_bit_set);
if(is_even_bit_set ^ is_key_bit_set)
output_word |= 1 << even_bit_shift;
if(is_odd_bit_set)
output_word |= 1 << odd_bit_shift;
}
crypto_key3++;
return output_word;
}
u16 k573fpga_device::get_decrypted()
{
if(mp3_cur_adr >= mp3_end_adr || (mpeg_ctrl_flag & 0xe000) != 0xe000) {
return 0;
}
u16 src = ram[mp3_cur_adr >> 1];
u16 result = use_ddrsbm_fpga ? decrypt_ddrsbm(src) : decrypt_default(src);
mp3_cur_adr += 2;
return result;
}
DEFINE_DEVICE_TYPE(KONAMI_573_DIGITAL_FPGA, k573fpga_device, "k573fpga", "Konami 573 Digital I/O FPGA")