(MESS) nes: Properly implemented the Bandai Karaoke Studio expansion

slot. The two Senyou Cassettes (Top Hit 20 Vol 1 & Vol 2) have now to be 
loaded with the following commands "mess nes -cart karaoke -cart2 top20v1" 
(or top20v2). This is accurate to the hardware, because these expansions
had to be manually inserted into the body of the main Karaoke Studio cart 
before playing. [Fabio Priuli]
This commit is contained in:
Fabio Priuli 2014-02-19 05:48:54 +00:00
parent 57aaa4f9a6
commit 5c2b6036df
7 changed files with 370 additions and 56 deletions

1
.gitattributes vendored
View File

@ -184,6 +184,7 @@ hash/neogeo.xml svneol=native#text/xml
hash/nes.hsi svneol=native#text/xml
hash/nes.xml svneol=native#text/xml
hash/nes_datach.xml svneol=native#text/xml
hash/nes_kstudio.xml svneol=native#text/xml
hash/nes_ntbrom.xml svneol=native#text/xml
hash/next.xml svneol=native#text/xml
hash/ngp.xml svneol=native#text/xml

View File

@ -49845,50 +49845,6 @@ preliminary proto for the PAL version, still running on NTSC systems) or the gfx
</part>
</software>
<software name="karaok1" supported="no">
<description>Karaoke Studio Senyou Cassette Vol. 1 (Jpn, Hacked)</description>
<year>1987</year>
<publisher>Bandai</publisher>
<info name="serial" value="BA-KARAOKE-VOL1"/>
<info name="release" value="19871001"/>
<info name="alt_title" value="カラオケスタジオ 専用カセット トップヒット20 VOL. 1"/>
<part name="cart" interface="nes_cart">
<feature name="slot" value="karastudio" />
<feature name="pcb" value="BANDAI-KARAOKE" />
<feature name="mirroring" value="horizontal" />
<dataarea name="prg" size="262144">
<rom name="karaoke studio (japan).prg" size="131072" crc="adfad6b6" sha1="5ab1d9cd55978af770a87749bd375741a63cb3d8" offset="00000" status="baddump" />
<!-- HACK!! (necessary until we support proper cart subslot for this board) -->
<rom name="karaoke studio senyou cassette vol. 1 (japan).prg" size="131072" crc="7dda2982" sha1="4a5f9af0a810dba95a2ba82c4c23a07adbbe845f" offset="0x20000" status="baddump" />
</dataarea>
<!-- 8k VRAM on cartridge -->
<dataarea name="vram" size="8192">
</dataarea>
</part>
</software>
<software name="karaok2" supported="no">
<description>Karaoke Studio Senyou Cassette Vol. 2 (Jpn, Hacked)</description>
<year>1988</year>
<publisher>Bandai</publisher>
<info name="serial" value="BA-KARAOKE-VOL2"/>
<info name="release" value="19880218"/>
<info name="alt_title" value="カラオケスタジオ 専用カセット トップヒット20 VOL. 2"/>
<part name="cart" interface="nes_cart">
<feature name="slot" value="karastudio" />
<feature name="pcb" value="BANDAI-KARAOKE" />
<feature name="mirroring" value="horizontal" />
<dataarea name="prg" size="262144">
<rom name="karaoke studio (japan).prg" size="131072" crc="adfad6b6" sha1="5ab1d9cd55978af770a87749bd375741a63cb3d8" offset="00000" status="baddump" />
<!-- HACK!! (necessary until we support proper cart subslot for this board) -->
<rom name="karaoke studio senyou cassette vol. 2 (japan).prg" size="131072" crc="66473923" sha1="8a64ac421c82c8bc0c47e8fb28890ba13a086d56" offset="0x20000" status="baddump" />
</dataarea>
<!-- 8k VRAM on cartridge -->
<dataarea name="vram" size="8192">
</dataarea>
</part>
</software>
<software name="colordinp" cloneof="colordin">
<description>Color A Dinosaur (USA, Prototype)</description>
<year>1993</year>

36
hash/nes_kstudio.xml Normal file
View File

@ -0,0 +1,36 @@
<?xml version="1.0"?>
<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
<softwarelist name="nes_kstudio" description="Nintendo Entertainment System - Karaoke Studio expansion cartridges">
<software name="top20v1" supported="partial">
<description>Karaoke Studio - Senyou Cassette - Top Hit 20 Vol. 1 (Jpn)</description>
<year>1987</year>
<publisher>Bandai</publisher>
<info name="serial" value="BA-KARAOKE-VOL1"/>
<info name="release" value="19871001"/>
<info name="alt_title" value="カラオケスタジオ 専用カセット トップヒット20 VOL. 1"/>
<part name="cart" interface="ks_cart">
<feature name="slot" value="ks_exp" />
<dataarea name="rom" size="131072">
<rom name="karaoke studio senyou cassette vol. 1 (japan).prg" size="131072" crc="7dda2982" sha1="4a5f9af0a810dba95a2ba82c4c23a07adbbe845f" offset="0000" status="baddump" />
</dataarea>
</part>
</software>
<software name="top20v2" supported="partial">
<description>Karaoke Studio - Senyou Cassette - Top Hit 20 Vol. 2 (Jpn)</description>
<year>1988</year>
<publisher>Bandai</publisher>
<info name="serial" value="BA-KARAOKE-VOL2"/>
<info name="release" value="19880218"/>
<info name="alt_title" value="カラオケスタジオ 専用カセット トップヒット20 VOL. 2"/>
<part name="cart" interface="ks_cart">
<feature name="slot" value="ks_exp" />
<dataarea name="rom" size="131072">
<rom name="karaoke studio senyou cassette vol. 2 (japan).prg" size="131072" crc="66473923" sha1="8a64ac421c82c8bc0c47e8fb28890ba13a086d56" offset="0000" status="baddump" />
</dataarea>
</part>
</software>
</softwarelist>

View File

@ -1070,8 +1070,9 @@ static MACHINE_CONFIG_START( nes, nes_state )
MCFG_NES_CARTRIDGE_ADD("nes_slot", nes_crt_interface, nes_cart, NULL)
MCFG_SOFTWARE_LIST_ADD("cart_list", "nes")
MCFG_SOFTWARE_LIST_ADD("ntb_list", "nes_ntbrom") // Sunsoft Nantettate! Baseball mini-carts
MCFG_SOFTWARE_LIST_ADD("datach_list", "nes_datach") // Bandai Datach Joint ROM System mini-carts
MCFG_SOFTWARE_LIST_ADD("ntb_list", "nes_ntbrom") // Sunsoft Nantettate! Baseball mini-carts
MCFG_SOFTWARE_LIST_ADD("kstudio_list", "nes_kstudio") // Bandai Karaoke Studio expansion carts
MCFG_SOFTWARE_LIST_ADD("datach_list", "nes_datach") // Bandai Datach Joint ROM System mini-carts
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( nespal, nes )

View File

@ -159,8 +159,9 @@ void nes_state::machine_start()
m_ppu->set_latch(ppu2c0x_latch_delegate(FUNC(device_nes_cart_interface::ppu_latch),m_cartslot->m_cart));
// install additional handlers (read_h, read_ex, write_ex)
if (m_cartslot->get_pcb_id() == STD_NROM368 || m_cartslot->get_pcb_id() == GG_NROM || m_cartslot->get_pcb_id() == SUNSOFT_DCS || m_cartslot->get_pcb_id() == BANDAI_DATACH
|| m_cartslot->get_pcb_id() == AVE_MAXI15 || m_cartslot->get_pcb_id() == KAISER_KS7022 || m_cartslot->get_pcb_id() == KAISER_KS7031 || m_cartslot->get_pcb_id() == BMC_VT5201
if (m_cartslot->get_pcb_id() == STD_NROM368 || m_cartslot->get_pcb_id() == GG_NROM || m_cartslot->get_pcb_id() == SUNSOFT_DCS
|| m_cartslot->get_pcb_id() == BANDAI_DATACH || m_cartslot->get_pcb_id() == BANDAI_KARAOKE || m_cartslot->get_pcb_id() == AVE_MAXI15
|| m_cartslot->get_pcb_id() == KAISER_KS7022 || m_cartslot->get_pcb_id() == KAISER_KS7031 || m_cartslot->get_pcb_id() == BMC_VT5201
|| m_cartslot->get_pcb_id() == UNL_LH32 || m_cartslot->get_pcb_id() == UNL_LH10 || m_cartslot->get_pcb_id() == UNL_2708
|| m_cartslot->get_pcb_id() == UNL_43272 || m_cartslot->get_pcb_id() == BMC_G63IN1 || m_cartslot->get_pcb_id() == BMC_8157
|| m_cartslot->get_pcb_id() == BMC_GOLD150 || m_cartslot->get_pcb_id() == BMC_CH001

View File

@ -8,10 +8,23 @@
Here we emulate the following PCBs Bandai Karaoke Studio [mapper 188]
The Karaoke Studio cart consist of a large connector which fits the FC cart slot, with a microphone
connected. The game data is in the connector itself. The microphone has two buttons on it, and the
game uses these only to navigate through the menus (the two buttons are not read through the controller
port, which is not accessible from the cart, but from $6000-$7fff). Part of the connector body can be
removed to be replaced by an expansion cart containing new songs (we emulate this by adding a -cart2 slot).
TODO:
- emulate the actual expansion slot for the Senyou Cassettes
- verify expansion slot emulation for the Senyou Cassettes:
not much documentation exists about the expansion carts (except for few paragraphs
at Enri's FC webpage), so I implemented it based on "common sense"
* expansion carts do not contain the required game data => main PRG must be in the main cart
so to remain connected even when an expansion is inserted (differently from Datach, where
the base unit contains no PRG)
* bankswicth writes with bit3=0 (to access expansion) when no expansion is present should do
nothing
***********************************************************************************************************/
@ -28,16 +41,157 @@
#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
//-----------------------------------------
//
// Karaoke Studio Cartslot implementation
//
//-----------------------------------------
//-------------------------------------------------
// constructor
// sub-cart interface
//-------------------------------------------------
kstudio_cart_interface::kstudio_cart_interface(const machine_config &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device),
m_rom(NULL),
m_rom_size(0)
{
}
kstudio_cart_interface::~kstudio_cart_interface()
{
}
READ8_MEMBER(kstudio_cart_interface::read)
{
return m_rom[(m_bank * 0x4000) + (offset & 0x3fff)];
}
//-------------------------------------------------
// sub-cart slot device
//-------------------------------------------------
const device_type NES_KSEXPANSION_SLOT = &device_creator<nes_kstudio_slot_device>;
nes_kstudio_slot_device::nes_kstudio_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, NES_KSEXPANSION_SLOT, "NES Karaoke Studio Expansion Slot", tag, owner, clock, "nes_ks_slot", __FILE__),
device_image_interface(mconfig, *this),
device_slot_interface(mconfig, *this)
{
}
nes_kstudio_slot_device::~nes_kstudio_slot_device()
{
}
void nes_kstudio_slot_device::device_start()
{
m_cart = dynamic_cast<kstudio_cart_interface *>(get_card_device());
}
READ8_MEMBER(nes_kstudio_slot_device::read)
{
if (m_cart)
return m_cart->read(space, offset, mem_mask);
return 0xff;
}
bool nes_kstudio_slot_device::call_load()
{
if (m_cart)
{
UINT8 *ROM = m_cart->get_cart_base();
if (!ROM)
return IMAGE_INIT_FAIL;
// Existing exapnsion carts are all 128K, so we only load files of this size
if (software_entry() == NULL)
{
if (length() != 0x20000)
return IMAGE_INIT_FAIL;
fread(&ROM, 0x20000);
}
else
{
if (get_software_region_length("rom") != 0x20000)
return IMAGE_INIT_FAIL;
memcpy(ROM, get_software_region("rom"), 0x20000);
}
}
return IMAGE_INIT_PASS;
}
bool nes_kstudio_slot_device::call_softlist_load(char *swlist, char *swname, rom_entry *start_entry)
{
load_software_part_region(this, swlist, swname, start_entry );
return TRUE;
}
const char * nes_kstudio_slot_device::get_default_card_software(const machine_config &config, emu_options &options)
{
return software_get_default_slot(config, options, this, "ks_exp");
}
//-----------------------------------------------
//
// Karaoke Studio Expansion cart implementation
//
//-----------------------------------------------
ROM_START( ks_exp_rom )
ROM_REGION(0x20000, "exrom", ROMREGION_ERASEFF)
ROM_END
const device_type NES_KSEXPANSION_ROM = &device_creator<nes_kstudio_rom_device>;
nes_kstudio_rom_device::nes_kstudio_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, NES_KSEXPANSION_ROM, "NES Karaoke Studio Expansion ROM", tag, owner, clock, "nes_ks_rom", __FILE__),
kstudio_cart_interface( mconfig, *this )
{
}
void nes_kstudio_rom_device::device_start()
{
m_rom = (UINT8*)memregion("exrom")->base();
save_item(NAME(m_bank));
}
void nes_kstudio_rom_device::device_reset()
{
m_bank = 0;
}
const rom_entry *nes_kstudio_rom_device::device_rom_region() const
{
return ROM_NAME( ks_exp_rom );
}
UINT8 *nes_kstudio_rom_device::get_cart_base()
{
return m_rom;
}
//------------------------------------------
//
// Karaoke Studio Base Cart implementation
//
//------------------------------------------
const device_type NES_KARAOKESTUDIO = &device_creator<nes_karaokestudio_device>;
nes_karaokestudio_device::nes_karaokestudio_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: nes_nrom_device(mconfig, NES_KARAOKESTUDIO, "NES Cart Bandai Karaoke Studio PCB", tag, owner, clock, "nes_karaoke", __FILE__),
m_subslot(*this, "exp_slot"),
m_mic_ipt(*this, "MIC")
{
}
@ -46,6 +200,7 @@ nes_karaokestudio_device::nes_karaokestudio_device(const machine_config &mconfig
void nes_karaokestudio_device::device_start()
{
common_start();
save_item(NAME(m_exp_active));
}
void nes_karaokestudio_device::pcb_reset()
@ -54,6 +209,7 @@ void nes_karaokestudio_device::pcb_reset()
prg16_89ab(0);
prg16_cdef((m_prg_chunks - 1) ^ 0x08);
chr8(0, m_chr_source);
m_exp_active = 0;
}
@ -81,20 +237,47 @@ READ8_MEMBER(nes_karaokestudio_device::read_m)
return m_mic_ipt->read();
}
READ8_MEMBER(nes_karaokestudio_device::read_h)
{
LOG_MMC(("karaoke studio read_h, offset: %04x\n", offset));
// this shall be the proper code, but it's a bit slower, so we access directly the subcart below
//return m_subslot->read(space, offset, mem_mask);
// access expansion cart only if all of the followings are verified
// * we are in $8000-$bfff range
// * there has been a bankswitch write to map the expansion to such range
// * there actually is an expansion cart mounted
if (offset < 0x4000 && m_exp_active && m_subslot->m_cart)
return m_subslot->m_cart->read(space, offset, mem_mask);
else
return hi_access_rom(offset);
}
WRITE8_MEMBER(nes_karaokestudio_device::write_h)
{
LOG_MMC(("karaoke studio write_h, offset: %04x, data: %02x\n", offset, data));
// bit3 1 = M ROM (main unit), 0=E ROM (expansion)
// HACK(?): currently it is not clear how the unit acknowledges the presence of the expansion
// cart (when expansion is present, code keeps switching both from the expansion rom and from
// the main ROM), so we load the expansion after the main PRG and handle banking as follows
data ^= 8;
prg16_89ab(data);
// the main ROM)
// my guess is that writes with bit3=0 and no expansion just do nothing, but it shall be verified
if (offset >= 04000)
{
if (BIT(data, 3))
{
m_exp_active = 0;
prg16_89ab(data & 7);
}
else // expansion cart
{
m_exp_active = 1;
m_subslot->write_prg_bank(data & 7);
}
}
}
static INPUT_PORTS_START( karaoke_mic )
PORT_START("MIC")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("A (Mic Select)") PORT_CODE(KEYCODE_X)
@ -107,3 +290,23 @@ ioport_constructor nes_karaokestudio_device::device_input_ports() const
{
return INPUT_PORTS_NAME( karaoke_mic );
}
//-------------------------------------------------
// CART SLOT
//-------------------------------------------------
static SLOT_INTERFACE_START(karaoke_studio_cart)
SLOT_INTERFACE("ks_exp", NES_KSEXPANSION_ROM)
SLOT_INTERFACE_END
MACHINE_CONFIG_FRAGMENT( karaoke_studio )
MCFG_KSTUDIO_MINICART_ADD("exp_slot", karaoke_studio_cart)
MACHINE_CONFIG_END
machine_config_constructor nes_karaokestudio_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( karaoke_studio );
}

View File

@ -4,6 +4,117 @@
#include "machine/nes_nxrom.h"
//-----------------------------------------
//
// Karaoke Studio Cartslot implementation
//
//-----------------------------------------
// ======================> kstudio_cart_interface
class kstudio_cart_interface : public device_slot_card_interface
{
public:
// construction/destruction
kstudio_cart_interface(const machine_config &mconfig, device_t &device);
virtual ~kstudio_cart_interface();
// reading and writing
virtual DECLARE_READ8_MEMBER(read);
UINT8 *get_cart_base() { return m_rom; }
void write_prg_bank(UINT8 bank) { m_bank = bank; }
protected:
// internal state
UINT8 *m_rom;
UINT32 m_rom_size;
// ROM is accessed via two 16K banks, but only the first one can be switched
UINT8 m_bank;
};
// ======================> nes_kstudio_slot_device
class nes_kstudio_slot_device : public device_t,
public device_image_interface,
public device_slot_interface
{
public:
// construction/destruction
nes_kstudio_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual ~nes_kstudio_slot_device();
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { update_names(); }
// image-level overrides
virtual bool call_load();
virtual bool call_softlist_load(char *swlist, char *swname, rom_entry *start_entry);
virtual iodevice_t image_type() const { return IO_CARTSLOT; }
virtual bool is_readable() const { return 1; }
virtual bool is_writeable() const { return 0; }
virtual bool is_creatable() const { return 0; }
virtual bool must_be_loaded() const { return 0; }
virtual bool is_reset_on_load() const { return 1; }
virtual const char *image_interface() const { return "ks_cart"; }
virtual const char *file_extensions() const { return "bin"; }
virtual const option_guide *create_option_guide() const { return NULL; }
// slot interface overrides
virtual const char * get_default_card_software(const machine_config &config, emu_options &options);
virtual DECLARE_READ8_MEMBER(read);
void write_prg_bank(UINT8 bank) { if (m_cart) m_cart->write_prg_bank(bank); }
kstudio_cart_interface* m_cart;
};
// device type definition
extern const device_type NES_KSEXPANSION_SLOT;
#define MCFG_KSTUDIO_MINICART_ADD(_tag, _slot_intf) \
MCFG_DEVICE_ADD(_tag, NES_KSEXPANSION_SLOT, 0) \
MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, NULL, false)
//-----------------------------------------------
//
// Karaoke Studio Expansion cart implementation
//
//-----------------------------------------------
// ======================> nes_kstudio_rom_device
class nes_kstudio_rom_device : public device_t,
public kstudio_cart_interface
{
public:
// construction/destruction
nes_kstudio_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// optional information overrides
virtual const rom_entry *device_rom_region() const;
virtual UINT8* get_cart_base();
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
};
// device type definition
extern const device_type NES_KSEXPANSION_ROM;
//-------------------------------------------
//
// Karaoke Studio Base Cart implementation
//
//-------------------------------------------
// ======================> nes_karaokestudio_device
class nes_karaokestudio_device : public nes_nrom_device
@ -15,11 +126,16 @@ public:
// device-level overrides
virtual void device_start();
virtual ioport_constructor device_input_ports() const;
virtual DECLARE_WRITE8_MEMBER(write_h);
virtual machine_config_constructor device_mconfig_additions() const;
virtual DECLARE_READ8_MEMBER(read_m);
virtual DECLARE_READ8_MEMBER(read_h);
virtual DECLARE_WRITE8_MEMBER(write_h);
virtual void pcb_reset();
protected:
int m_exp_active;
required_device<nes_kstudio_slot_device> m_subslot;
required_ioport m_mic_ipt;
};