mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00

misc MACHINE_CONFIG removal (nw) started work on voltage_regulator_device macros removal (nw)
935 lines
22 KiB
C++
935 lines
22 KiB
C++
// license:BSD-3-Clause
|
|
// copyright-holders:Wilbert Pol
|
|
#include "emu.h"
|
|
#include "konami.h"
|
|
|
|
#include "sound/volt_reg.h"
|
|
#include "speaker.h"
|
|
|
|
|
|
DEFINE_DEVICE_TYPE(MSX_CART_KONAMI, msx_cart_konami_device, "msx_cart_konami", "MSX Cartridge - KONAMI")
|
|
DEFINE_DEVICE_TYPE(MSX_CART_KONAMI_SCC, msx_cart_konami_scc_device, "msx_cart_konami_scc", "MSX Cartridge - KONAMI+SCC")
|
|
DEFINE_DEVICE_TYPE(MSX_CART_GAMEMASTER2, msx_cart_gamemaster2_device, "msx_cart_gamemaster2", "MSX Cartridge - GAMEMASTER2")
|
|
DEFINE_DEVICE_TYPE(MSX_CART_SYNTHESIZER, msx_cart_synthesizer_device, "msx_cart_synthesizer", "MSX Cartridge - Synthesizer")
|
|
DEFINE_DEVICE_TYPE(MSX_CART_SOUND_SNATCHER, msx_cart_konami_sound_snatcher_device, "msx_cart_sound_snatcher", "MSX Cartridge - Sound Snatcher")
|
|
DEFINE_DEVICE_TYPE(MSX_CART_SOUND_SDSNATCHER, msx_cart_konami_sound_sdsnatcher_device, "msx_cart_sound_sdsnatcher", "MSX Cartridge - Sound SD Snatcher")
|
|
DEFINE_DEVICE_TYPE(MSX_CART_KEYBOARD_MASTER, msx_cart_keyboard_master_device, "msx_cart_keyboard_master", "MSX Cartridge - Keyboard Master")
|
|
|
|
|
|
msx_cart_konami_device::msx_cart_konami_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
|
: device_t(mconfig, MSX_CART_KONAMI, tag, owner, clock)
|
|
, msx_cart_interface(mconfig, *this)
|
|
, m_bank_mask(0)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
m_selected_bank[i] = i;
|
|
}
|
|
for (auto & elem : m_bank_base)
|
|
{
|
|
elem = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
void msx_cart_konami_device::device_start()
|
|
{
|
|
save_item(NAME(m_selected_bank));
|
|
|
|
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_konami_device::restore_banks), this));
|
|
}
|
|
|
|
|
|
void msx_cart_konami_device::restore_banks()
|
|
{
|
|
m_bank_base[0] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[1] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[6] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[7] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
|
|
}
|
|
|
|
|
|
void msx_cart_konami_device::device_reset()
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
m_selected_bank[i] = i;
|
|
}
|
|
}
|
|
|
|
|
|
void msx_cart_konami_device::initialize_cartridge()
|
|
{
|
|
uint32_t size = get_rom_size();
|
|
|
|
if ( get_rom_size() > 256 * 0x2000 )
|
|
{
|
|
fatalerror("konami: ROM is too big\n");
|
|
}
|
|
|
|
uint16_t banks = size / 0x2000;
|
|
|
|
if (size != banks * 0x2000 || (~(banks - 1) % banks))
|
|
{
|
|
fatalerror("konami: Invalid ROM size\n");
|
|
}
|
|
|
|
m_bank_mask = banks - 1;
|
|
|
|
restore_banks();
|
|
}
|
|
|
|
|
|
READ8_MEMBER(msx_cart_konami_device::read_cart)
|
|
{
|
|
return m_bank_base[offset >> 13][offset & 0x1fff];
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(msx_cart_konami_device::write_cart)
|
|
{
|
|
switch (offset & 0xe000)
|
|
{
|
|
case 0x4000:
|
|
m_selected_bank[0] = data;
|
|
m_bank_base[0] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
|
|
break;
|
|
|
|
case 0x6000:
|
|
m_selected_bank[1] = data;
|
|
m_bank_base[1] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
|
|
break;
|
|
|
|
case 0x8000:
|
|
m_selected_bank[2] = data;
|
|
m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[6] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
|
|
break;
|
|
|
|
case 0xa000:
|
|
m_selected_bank[3] = data;
|
|
m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[7] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
msx_cart_konami_scc_device::msx_cart_konami_scc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
|
: device_t(mconfig, MSX_CART_KONAMI_SCC, tag, owner, clock)
|
|
, msx_cart_interface(mconfig, *this)
|
|
, m_k051649(*this, "k051649")
|
|
, m_bank_mask(0)
|
|
, m_scc_active(false)
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
m_selected_bank[i] = i;
|
|
}
|
|
for (auto & elem : m_bank_base)
|
|
{
|
|
elem = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
void msx_cart_konami_scc_device::device_add_mconfig(machine_config &config)
|
|
{
|
|
// This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
|
|
SPEAKER(config, "mono").front_center();
|
|
K051649(config, m_k051649, XTAL(10'738'635)/3/2).add_route(ALL_OUTPUTS, "mono", 0.15);
|
|
}
|
|
|
|
|
|
void msx_cart_konami_scc_device::device_start()
|
|
{
|
|
save_item(NAME(m_selected_bank));
|
|
save_item(NAME(m_scc_active));
|
|
|
|
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_konami_scc_device::restore_banks), this));
|
|
}
|
|
|
|
|
|
void msx_cart_konami_scc_device::restore_banks()
|
|
{
|
|
m_bank_base[0] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[1] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[6] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[7] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
|
|
}
|
|
|
|
|
|
void msx_cart_konami_scc_device::device_reset()
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
m_selected_bank[i] = i;
|
|
}
|
|
m_scc_active = false;
|
|
}
|
|
|
|
|
|
void msx_cart_konami_scc_device::initialize_cartridge()
|
|
{
|
|
uint32_t size = get_rom_size();
|
|
|
|
if ( get_rom_size() > 256 * 0x2000 )
|
|
{
|
|
fatalerror("konami_scc: ROM is too big\n");
|
|
}
|
|
|
|
uint16_t banks = size / 0x2000;
|
|
|
|
if (size != banks * 0x2000 || (~(banks - 1) % banks))
|
|
{
|
|
fatalerror("konami_scc: Invalid ROM size\n");
|
|
}
|
|
|
|
m_bank_mask = banks - 1;
|
|
|
|
restore_banks();
|
|
}
|
|
|
|
|
|
READ8_MEMBER(msx_cart_konami_scc_device::read_cart)
|
|
{
|
|
if ( m_scc_active && offset >= 0x9800 && offset < 0xa000 )
|
|
{
|
|
if (offset & 0x80)
|
|
{
|
|
if ((offset & 0xff) >= 0xe0)
|
|
{
|
|
return m_k051649->k051649_test_r(space, offset & 0xff);
|
|
}
|
|
return 0xff;
|
|
}
|
|
else
|
|
{
|
|
return m_k051649->k051649_waveform_r(space, offset & 0x7f);
|
|
}
|
|
}
|
|
|
|
return m_bank_base[offset >> 13][offset & 0x1fff];
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(msx_cart_konami_scc_device::write_cart)
|
|
{
|
|
switch (offset & 0xf800)
|
|
{
|
|
case 0x5000:
|
|
m_selected_bank[0] = data;
|
|
m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[6] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
|
|
break;
|
|
|
|
case 0x7000:
|
|
m_selected_bank[1] = data;
|
|
m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[7] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
|
|
break;
|
|
|
|
case 0x9000:
|
|
m_selected_bank[2] = data;
|
|
m_scc_active = ( ( data & 0x3f ) == 0x3f );
|
|
m_bank_base[0] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
|
|
break;
|
|
|
|
case 0x9800:
|
|
if ( m_scc_active )
|
|
{
|
|
offset &= 0xff;
|
|
|
|
if (offset < 0x80)
|
|
{
|
|
m_k051649->k051649_waveform_w(space, offset, data);
|
|
}
|
|
else if (offset < 0xa0)
|
|
{
|
|
offset &= 0x0f;
|
|
if (offset < 0x0a)
|
|
{
|
|
m_k051649->k051649_frequency_w(space, offset, data);
|
|
}
|
|
else if (offset < 0x0f)
|
|
{
|
|
m_k051649->k051649_volume_w(space, offset - 0xa, data);
|
|
}
|
|
else
|
|
{
|
|
m_k051649->k051649_keyonoff_w(space, 0, data);
|
|
}
|
|
}
|
|
else if (offset >= 0xe0)
|
|
{
|
|
m_k051649->k051649_test_w(space, offset, data);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0xb000:
|
|
m_selected_bank[3] = data;
|
|
m_bank_base[1] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
|
|
m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & m_bank_mask ) * 0x2000;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
msx_cart_gamemaster2_device::msx_cart_gamemaster2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
|
: device_t(mconfig, MSX_CART_GAMEMASTER2, tag, owner, clock)
|
|
, msx_cart_interface(mconfig, *this)
|
|
{
|
|
for (auto & elem : m_selected_bank)
|
|
{
|
|
elem = 0;
|
|
}
|
|
for (auto & elem : m_bank_base)
|
|
{
|
|
elem = nullptr;
|
|
}
|
|
}
|
|
|
|
|
|
void msx_cart_gamemaster2_device::device_start()
|
|
{
|
|
save_item(NAME(m_selected_bank));
|
|
|
|
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_gamemaster2_device::restore_banks), this));
|
|
}
|
|
|
|
|
|
void msx_cart_gamemaster2_device::setup_bank(uint8_t bank)
|
|
{
|
|
switch (bank)
|
|
{
|
|
case 0:
|
|
if (m_selected_bank[0] & 0x10)
|
|
{
|
|
m_bank_base[1] = get_sram_base() + ((m_selected_bank[0] & 0x20) ? 0x1000 : 0);
|
|
m_bank_base[3] = get_sram_base() + ((m_selected_bank[0] & 0x20) ? 0x1000 : 0);
|
|
}
|
|
else
|
|
{
|
|
m_bank_base[1] = get_rom_base() + ( m_selected_bank[0] & 0x0f ) * 0x2000;
|
|
m_bank_base[3] = get_rom_base() + ( m_selected_bank[0] & 0x0f ) * 0x2000;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
if (m_selected_bank[1] & 0x10)
|
|
{
|
|
m_bank_base[4] = get_sram_base() + ((m_selected_bank[1] & 0x20) ? 0x1000 : 0);
|
|
m_bank_base[6] = get_sram_base() + ((m_selected_bank[1] & 0x20) ? 0x1000 : 0);
|
|
}
|
|
else
|
|
{
|
|
m_bank_base[4] = get_rom_base() + ( m_selected_bank[1] & 0x0f ) * 0x2000;
|
|
m_bank_base[6] = get_rom_base() + ( m_selected_bank[1] & 0x0f ) * 0x2000;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if (m_selected_bank[2] & 0x10)
|
|
{
|
|
m_bank_base[5] = get_sram_base() + ((m_selected_bank[2] & 0x20) ? 0x1000 : 0);
|
|
m_bank_base[7] = get_sram_base() + ((m_selected_bank[2] & 0x20) ? 0x1000 : 0);
|
|
}
|
|
else
|
|
{
|
|
m_bank_base[5] = get_rom_base() + ( m_selected_bank[2] & 0x0f ) * 0x2000;
|
|
m_bank_base[7] = get_rom_base() + ( m_selected_bank[2] & 0x0f ) * 0x2000;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void msx_cart_gamemaster2_device::restore_banks()
|
|
{
|
|
m_bank_base[0] = get_rom_base();
|
|
m_bank_base[2] = get_rom_base();
|
|
setup_bank(0);
|
|
setup_bank(1);
|
|
setup_bank(2);
|
|
}
|
|
|
|
|
|
void msx_cart_gamemaster2_device::device_reset()
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
m_selected_bank[i] = i + 1;
|
|
}
|
|
}
|
|
|
|
|
|
void msx_cart_gamemaster2_device::initialize_cartridge()
|
|
{
|
|
if ( get_rom_size() != 0x20000 )
|
|
{
|
|
fatalerror("gamemaster2: Invalid ROM size\n");
|
|
}
|
|
|
|
if (get_sram_size() != 0x2000)
|
|
{
|
|
fatalerror("gamemaster2: Invalid SRAM size\n");
|
|
}
|
|
|
|
restore_banks();
|
|
}
|
|
|
|
|
|
READ8_MEMBER(msx_cart_gamemaster2_device::read_cart)
|
|
{
|
|
uint8_t bank = offset >> 13;
|
|
|
|
switch (bank)
|
|
{
|
|
case 1:
|
|
case 3:
|
|
if (m_selected_bank[0] & 0x10)
|
|
{
|
|
return m_bank_base[bank][offset & 0x0fff];
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
case 6:
|
|
if (m_selected_bank[1] & 0x10)
|
|
{
|
|
return m_bank_base[bank][offset & 0x0fff];
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
case 7:
|
|
if (m_selected_bank[2] & 0x10)
|
|
{
|
|
return m_bank_base[bank][offset & 0x0fff];
|
|
}
|
|
break;
|
|
}
|
|
return m_bank_base[bank][offset & 0x1fff];
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(msx_cart_gamemaster2_device::write_cart)
|
|
{
|
|
switch (offset & 0xf000)
|
|
{
|
|
case 0x6000:
|
|
m_selected_bank[0] = data;
|
|
setup_bank(0);
|
|
break;
|
|
|
|
case 0x8000:
|
|
m_selected_bank[1] = data;
|
|
setup_bank(1);
|
|
break;
|
|
|
|
case 0xa000:
|
|
m_selected_bank[2] = data;
|
|
setup_bank(2);
|
|
break;
|
|
|
|
case 0xb000:
|
|
if (m_selected_bank[2] & 0x10)
|
|
{
|
|
m_bank_base[5][offset & 0x0fff] = data;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
msx_cart_synthesizer_device::msx_cart_synthesizer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
|
: device_t(mconfig, MSX_CART_SYNTHESIZER, tag, owner, clock)
|
|
, msx_cart_interface(mconfig, *this)
|
|
, m_bank_base(nullptr)
|
|
, m_dac(*this, "dac")
|
|
{
|
|
}
|
|
|
|
|
|
void msx_cart_synthesizer_device::device_add_mconfig(machine_config &config)
|
|
{
|
|
// This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
|
|
SPEAKER(config, "speaker").front_center();
|
|
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.1); // unknown DAC
|
|
voltage_regulator_device &vref(VOLTAGE_REGULATOR(config, "vref"));
|
|
vref.set_output(5.0);
|
|
vref.add_route(0, "dac", 1.0, DAC_VREF_POS_INPUT);
|
|
vref.add_route(0, "dac", -1.0, DAC_VREF_NEG_INPUT);
|
|
}
|
|
|
|
|
|
void msx_cart_synthesizer_device::device_start()
|
|
{
|
|
}
|
|
|
|
|
|
void msx_cart_synthesizer_device::initialize_cartridge()
|
|
{
|
|
if ( get_rom_size() != 0x8000 )
|
|
{
|
|
fatalerror("synthesizer: Invalid ROM size\n");
|
|
}
|
|
|
|
m_bank_base = get_rom_base();
|
|
}
|
|
|
|
|
|
READ8_MEMBER(msx_cart_synthesizer_device::read_cart)
|
|
{
|
|
if (offset >= 0x4000 && offset < 0xc000 )
|
|
{
|
|
return m_bank_base[offset - 0x4000];
|
|
}
|
|
return 0xff;
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(msx_cart_synthesizer_device::write_cart)
|
|
{
|
|
if ((offset & 0xc010) == 0x4000)
|
|
{
|
|
m_dac->write(data);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
msx_cart_konami_sound_device::msx_cart_konami_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
|
|
: device_t(mconfig, type, tag, owner, clock)
|
|
, msx_cart_interface(mconfig, *this)
|
|
, m_k052539(*this, "k052539")
|
|
, m_scc_active(false)
|
|
, m_sccplus_active(false)
|
|
, m_scc_mode(0)
|
|
{
|
|
for (auto & elem : m_selected_bank)
|
|
{
|
|
elem = 0;
|
|
}
|
|
for (auto & elem : m_bank_base)
|
|
{
|
|
elem = nullptr;
|
|
}
|
|
for (auto & elem : m_ram_bank)
|
|
{
|
|
elem = nullptr;
|
|
}
|
|
for (auto & elem : m_ram_enabled)
|
|
{
|
|
elem = false;
|
|
}
|
|
}
|
|
|
|
|
|
void msx_cart_konami_sound_device::device_add_mconfig(machine_config &config)
|
|
{
|
|
// This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
|
|
SPEAKER(config, "mono").front_center();
|
|
K051649(config, m_k052539, XTAL(10'738'635)/3/2).add_route(ALL_OUTPUTS, "mono", 0.15);
|
|
}
|
|
|
|
|
|
void msx_cart_konami_sound_device::device_start()
|
|
{
|
|
save_item(NAME(m_selected_bank));
|
|
save_item(NAME(m_scc_active));
|
|
save_item(NAME(m_sccplus_active));
|
|
save_item(NAME(m_ram_enabled));
|
|
|
|
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_konami_sound_device::restore_banks), this));
|
|
}
|
|
|
|
|
|
void msx_cart_konami_sound_device::restore_banks()
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
setup_bank(i);
|
|
}
|
|
}
|
|
|
|
|
|
void msx_cart_konami_sound_device::setup_bank(uint8_t bank)
|
|
{
|
|
switch (bank)
|
|
{
|
|
case 0:
|
|
m_bank_base[2] = m_ram_bank[m_selected_bank[0] & 0x0f];
|
|
m_bank_base[6] = m_ram_bank[m_selected_bank[0] & 0x0f];
|
|
break;
|
|
|
|
case 1:
|
|
m_bank_base[3] = m_ram_bank[m_selected_bank[1] & 0x0f];
|
|
m_bank_base[7] = m_ram_bank[m_selected_bank[1] & 0x0f];
|
|
break;
|
|
|
|
case 2:
|
|
m_bank_base[0] = m_ram_bank[m_selected_bank[2] & 0x0f];
|
|
m_bank_base[4] = m_ram_bank[m_selected_bank[2] & 0x0f];
|
|
break;
|
|
|
|
case 3:
|
|
m_bank_base[1] = m_ram_bank[m_selected_bank[3] & 0x0f];
|
|
m_bank_base[5] = m_ram_bank[m_selected_bank[3] & 0x0f];
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void msx_cart_konami_sound_device::device_reset()
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
m_selected_bank[i] = i;
|
|
m_ram_enabled[i] = false;
|
|
}
|
|
m_scc_active = false;
|
|
m_sccplus_active = false;
|
|
}
|
|
|
|
|
|
void msx_cart_konami_sound_device::initialize_cartridge()
|
|
{
|
|
restore_banks();
|
|
}
|
|
|
|
|
|
READ8_MEMBER(msx_cart_konami_sound_device::read_cart)
|
|
{
|
|
if ( m_scc_active && offset >= 0x9800 && offset < 0x9fe0 )
|
|
{
|
|
offset &= 0xff;
|
|
if (offset < 0x80)
|
|
{
|
|
return m_k052539->k051649_waveform_r(space, offset);
|
|
}
|
|
if (offset < 0xa0)
|
|
{
|
|
return 0xff;
|
|
}
|
|
if (offset < 0xc0)
|
|
{
|
|
return m_k052539->k051649_waveform_r(space, offset & 0x9f);
|
|
}
|
|
if (offset < 0xe0)
|
|
{
|
|
return m_k052539->k051649_test_r(space, offset & 0xff);
|
|
}
|
|
return 0xff;
|
|
}
|
|
else if ( m_sccplus_active && offset >= 0xb800 && offset < 0xbfe0)
|
|
{
|
|
offset &= 0xff;
|
|
|
|
if (offset < 0xa0)
|
|
{
|
|
return m_k052539->k052539_waveform_r(space, offset);
|
|
}
|
|
if (offset >= 0xc0 && offset < 0xe0)
|
|
{
|
|
return m_k052539->k051649_test_r(space, offset);
|
|
}
|
|
return 0xff;
|
|
}
|
|
|
|
uint8_t *base = m_bank_base[offset >> 13];
|
|
|
|
if (base != nullptr)
|
|
{
|
|
return base[offset & 0x1fff];
|
|
}
|
|
return 0xff;
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(msx_cart_konami_sound_device::write_cart)
|
|
{
|
|
switch (offset & 0xe000)
|
|
{
|
|
case 0x4000:
|
|
if (m_ram_enabled[0] && m_bank_base[2] != nullptr)
|
|
{
|
|
m_bank_base[2][offset & 0x1fff] = data;
|
|
}
|
|
if ((offset & 0x1800) == 0x1000)
|
|
{
|
|
m_selected_bank[0] = data;
|
|
setup_bank(0);
|
|
}
|
|
break;
|
|
|
|
case 0x6000:
|
|
if (m_ram_enabled[1] && m_bank_base[3] != nullptr)
|
|
{
|
|
m_bank_base[3][offset & 0x1fff] = data;
|
|
}
|
|
if ((offset & 0x1800) == 0x1000)
|
|
{
|
|
m_selected_bank[1] = data;
|
|
setup_bank(1);
|
|
}
|
|
break;
|
|
|
|
case 0x8000:
|
|
if (m_ram_enabled[2] && m_bank_base[0] != nullptr)
|
|
{
|
|
m_bank_base[0][offset & 0x1fff] = data;
|
|
}
|
|
switch (offset & 0x1800)
|
|
{
|
|
case 0x1000: // 0x9000-0x97ff
|
|
m_selected_bank[2] = data;
|
|
m_scc_active = ( ( data & 0x3f ) == 0x3f );
|
|
setup_bank(2);
|
|
break;
|
|
|
|
case 0x1800: // 0x9800-0x9fff
|
|
if ( m_scc_active )
|
|
{
|
|
offset &= 0xff;
|
|
|
|
if (offset < 0x80)
|
|
{
|
|
m_k052539->k051649_waveform_w(space, offset, data);
|
|
}
|
|
else if (offset < 0xa0)
|
|
{
|
|
offset &= 0x0f;
|
|
if (offset < 0x0a)
|
|
{
|
|
m_k052539->k051649_frequency_w(space, offset, data);
|
|
}
|
|
else if (offset < 0x0f)
|
|
{
|
|
m_k052539->k051649_volume_w(space, offset - 0xa, data);
|
|
}
|
|
else
|
|
{
|
|
m_k052539->k051649_keyonoff_w(space, 0, data);
|
|
}
|
|
}
|
|
else if (offset >= 0xe0)
|
|
{
|
|
m_k052539->k051649_test_w(space, offset, data);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0xa000:
|
|
if (m_ram_enabled[3] && m_bank_base[1] != nullptr)
|
|
{
|
|
m_bank_base[1][offset & 0x1fff] = data;
|
|
}
|
|
switch (offset & 0x1800)
|
|
{
|
|
// 0xb000-0xb7ff
|
|
case 0x1000:
|
|
m_selected_bank[3] = data;
|
|
setup_bank(3);
|
|
break;
|
|
|
|
// 0xb800-0xbfff
|
|
case 0x1800:
|
|
if ((offset & 0x7fe) == 0x7fe)
|
|
{
|
|
// 0xbffe-0xbfff
|
|
/* write to mode register */
|
|
m_scc_mode = data;
|
|
|
|
m_ram_enabled[0] = ((m_scc_mode & 0x10) || (m_scc_mode & 0x01));
|
|
m_ram_enabled[1] = ((m_scc_mode & 0x10) || (m_scc_mode & 0x02));
|
|
m_ram_enabled[2] = ((m_scc_mode & 0x10) || ((m_scc_mode & 0x04) && (m_scc_mode & 0x20)));
|
|
m_ram_enabled[3] = (m_scc_mode & 0x10);
|
|
|
|
m_scc_active = ((m_selected_bank[2] & 0x3f) == 0x3f) && !(m_scc_mode & 0x20);
|
|
m_sccplus_active = (m_selected_bank[3] & 0x80) && (m_scc_mode & 0x20);
|
|
}
|
|
else
|
|
{
|
|
if (m_sccplus_active)
|
|
{
|
|
offset &= 0xff;
|
|
if (offset < 0xa0)
|
|
{
|
|
m_k052539->k052539_waveform_w(space, offset, data);
|
|
}
|
|
else if (offset < 0xc0)
|
|
{
|
|
offset &= 0x0f;
|
|
if (offset < 0x0a)
|
|
{
|
|
m_k052539->k051649_frequency_w(space, offset, data);
|
|
}
|
|
else if (offset < 0x0f)
|
|
{
|
|
m_k052539->k051649_volume_w(space, offset - 0x0a, data);
|
|
}
|
|
else if (offset == 0x0f)
|
|
{
|
|
m_k052539->k051649_keyonoff_w(space, 0, data);
|
|
}
|
|
}
|
|
else if (offset < 0xe0)
|
|
{
|
|
m_k052539->k051649_test_w(space, offset, data);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
msx_cart_konami_sound_snatcher_device::msx_cart_konami_sound_snatcher_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
|
: msx_cart_konami_sound_device(mconfig, MSX_CART_SOUND_SNATCHER, tag, owner, clock)
|
|
{
|
|
}
|
|
|
|
|
|
void msx_cart_konami_sound_snatcher_device::initialize_cartridge()
|
|
{
|
|
msx_cart_konami_sound_device::initialize_cartridge();
|
|
|
|
if (get_ram_size() != 0x10000)
|
|
{
|
|
fatalerror("sound_snatcher: Invalid RAM size\n");
|
|
}
|
|
|
|
// The Snatcher Sound cartridge has 64KB RAM available by selecting ram banks 0-7
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
m_ram_bank[i] = get_ram_base() + i * 0x2000;
|
|
}
|
|
}
|
|
|
|
|
|
msx_cart_konami_sound_sdsnatcher_device::msx_cart_konami_sound_sdsnatcher_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
|
: msx_cart_konami_sound_device(mconfig, MSX_CART_SOUND_SDSNATCHER, tag, owner, clock)
|
|
{
|
|
}
|
|
|
|
|
|
void msx_cart_konami_sound_sdsnatcher_device::initialize_cartridge()
|
|
{
|
|
msx_cart_konami_sound_device::initialize_cartridge();
|
|
|
|
if (get_ram_size() != 0x10000)
|
|
{
|
|
fatalerror("sound_sdsnatcher: Invalid RAM size\n");
|
|
}
|
|
|
|
// The SD Snatcher Sound cartrdige has 64KB RAM available by selecting ram banks 8-15
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
m_ram_bank[8+i] = get_ram_base() + i * 0x2000;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
msx_cart_keyboard_master_device::msx_cart_keyboard_master_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
|
: device_t(mconfig, MSX_CART_KEYBOARD_MASTER, tag, owner, clock)
|
|
, msx_cart_interface(mconfig, *this)
|
|
, m_vlm5030(*this, "vlm5030")
|
|
{
|
|
}
|
|
|
|
|
|
void msx_cart_keyboard_master_device::vlm_map(address_map &map)
|
|
{
|
|
map(0x0000, 0xffff).r(FUNC(msx_cart_keyboard_master_device::read_vlm));
|
|
}
|
|
|
|
|
|
void msx_cart_keyboard_master_device::device_add_mconfig(machine_config &config)
|
|
{
|
|
// This is actually incorrect. The sound output is passed back into the MSX machine where it is mixed internally and output through the system 'speaker'.
|
|
SPEAKER(config, "mono").front_center();
|
|
VLM5030(config, m_vlm5030, XTAL(3'579'545));
|
|
m_vlm5030->add_route(ALL_OUTPUTS, "mono", 0.40);
|
|
m_vlm5030->set_addrmap(0, &msx_cart_keyboard_master_device::vlm_map);
|
|
}
|
|
|
|
|
|
void msx_cart_keyboard_master_device::device_start()
|
|
{
|
|
// Install IO read/write handlers
|
|
address_space &space = machine().device<cpu_device>("maincpu")->space(AS_IO);
|
|
space.install_write_handler(0x00, 0x00, write8_delegate(FUNC(vlm5030_device::data_w), m_vlm5030.target()));
|
|
space.install_write_handler(0x20, 0x20, write8_delegate(FUNC(msx_cart_keyboard_master_device::io_20_w), this));
|
|
space.install_read_handler(0x00, 0x00, read8_delegate(FUNC(msx_cart_keyboard_master_device::io_00_r), this));
|
|
}
|
|
|
|
|
|
void msx_cart_keyboard_master_device::initialize_cartridge()
|
|
{
|
|
if (get_rom_size() != 0x4000)
|
|
{
|
|
fatalerror("keyboard_master: Invalid ROM size\n");
|
|
}
|
|
}
|
|
|
|
|
|
READ8_MEMBER(msx_cart_keyboard_master_device::read_cart)
|
|
{
|
|
if (offset >= 0x4000 && offset < 0x8000)
|
|
{
|
|
return m_rom[offset & 0x3fff];
|
|
}
|
|
return 0xff;
|
|
}
|
|
|
|
|
|
READ8_MEMBER(msx_cart_keyboard_master_device::read_vlm)
|
|
{
|
|
return m_rom_vlm5030[offset];
|
|
}
|
|
|
|
|
|
WRITE8_MEMBER(msx_cart_keyboard_master_device::io_20_w)
|
|
{
|
|
m_vlm5030->rst((data & 0x01) ? 1 : 0);
|
|
m_vlm5030->vcu((data & 0x04) ? 1 : 0);
|
|
m_vlm5030->st((data & 0x02) ? 1 : 0);
|
|
}
|
|
|
|
|
|
READ8_MEMBER(msx_cart_keyboard_master_device::io_00_r)
|
|
{
|
|
return m_vlm5030->bsy() ? 0x10 : 0x00;
|
|
}
|