(MESS) msx.c: [Wilbert Pol]

- Reimplemented the cartridge slots as slot devices.
- Moved the msx slot layouts to inline machine configuration.
- Started adding support for a few more firmware types.
- Add turbo support to Panasonic FS-A1FX/FS-A1WX/FS-A1WSX.
This commit is contained in:
Wilbert Pol 2014-05-14 19:04:52 +00:00
parent 8ab3ccb194
commit c74226bb26
50 changed files with 6893 additions and 5443 deletions

44
.gitattributes vendored
View File

@ -970,6 +970,48 @@ src/emu/bus/midi/midiinport.c svneol=native#text/plain
src/emu/bus/midi/midiinport.h svneol=native#text/plain
src/emu/bus/midi/midioutport.c svneol=native#text/plain
src/emu/bus/midi/midioutport.h svneol=native#text/plain
src/emu/bus/msx_cart/ascii.c svneol=native#text/plain
src/emu/bus/msx_cart/ascii.h svneol=native#text/plain
src/emu/bus/msx_cart/cartridge.c svneol=native#text/plain
src/emu/bus/msx_cart/cartridge.h svneol=native#text/plain
src/emu/bus/msx_cart/crossblaim.c svneol=native#text/plain
src/emu/bus/msx_cart/crossblaim.h svneol=native#text/plain
src/emu/bus/msx_cart/fmpac.c svneol=native#text/plain
src/emu/bus/msx_cart/fmpac.h svneol=native#text/plain
src/emu/bus/msx_cart/konami.c svneol=native#text/plain
src/emu/bus/msx_cart/konami.h svneol=native#text/plain
src/emu/bus/msx_cart/korean.c svneol=native#text/plain
src/emu/bus/msx_cart/korean.h svneol=native#text/plain
src/emu/bus/msx_cart/majutsushi.c svneol=native#text/plain
src/emu/bus/msx_cart/majutsushi.h svneol=native#text/plain
src/emu/bus/msx_cart/msxdos2.c svneol=native#text/plain
src/emu/bus/msx_cart/msxdos2.h svneol=native#text/plain
src/emu/bus/msx_cart/nomapper.c svneol=native#text/plain
src/emu/bus/msx_cart/nomapper.h svneol=native#text/plain
src/emu/bus/msx_cart/rtype.c svneol=native#text/plain
src/emu/bus/msx_cart/rtype.h svneol=native#text/plain
src/emu/bus/msx_cart/superloderunner.c svneol=native#text/plain
src/emu/bus/msx_cart/superloderunner.h svneol=native#text/plain
src/emu/bus/msx_slot/bunsetsu.c svneol=native#text/plain
src/emu/bus/msx_slot/bunsetsu.h svneol=native#text/plain
src/emu/bus/msx_slot/cartridge.c svneol=native#text/plain
src/emu/bus/msx_slot/cartridge.h svneol=native#text/plain
src/emu/bus/msx_slot/disk.c svneol=native#text/plain
src/emu/bus/msx_slot/disk.h svneol=native#text/plain
src/emu/bus/msx_slot/fs4600.c svneol=native#text/plain
src/emu/bus/msx_slot/fs4600.h svneol=native#text/plain
src/emu/bus/msx_slot/music.c svneol=native#text/plain
src/emu/bus/msx_slot/music.h svneol=native#text/plain
src/emu/bus/msx_slot/panasonic08.c svneol=native#text/plain
src/emu/bus/msx_slot/panasonic08.h svneol=native#text/plain
src/emu/bus/msx_slot/ram.c svneol=native#text/plain
src/emu/bus/msx_slot/ram.h svneol=native#text/plain
src/emu/bus/msx_slot/ram_mm.c svneol=native#text/plain
src/emu/bus/msx_slot/ram_mm.h svneol=native#text/plain
src/emu/bus/msx_slot/rom.c svneol=native#text/plain
src/emu/bus/msx_slot/rom.h svneol=native#text/plain
src/emu/bus/msx_slot/slot.c svneol=native#text/plain
src/emu/bus/msx_slot/slot.h svneol=native#text/plain
src/emu/bus/nes/2a03pur.c svneol=native#text/plain
src/emu/bus/nes/2a03pur.h svneol=native#text/plain
src/emu/bus/nes/act53.c svneol=native#text/plain
@ -8290,7 +8332,6 @@ src/mess/includes/mpf1.h svneol=native#text/plain
src/mess/includes/mpz80.h svneol=native#text/plain
src/mess/includes/msbc1.h svneol=native#text/plain
src/mess/includes/msx.h svneol=native#text/plain
src/mess/includes/msx_slot.h svneol=native#text/plain
src/mess/includes/mtx.h svneol=native#text/plain
src/mess/includes/mz700.h svneol=native#text/plain
src/mess/includes/mz80.h svneol=native#text/plain
@ -8642,7 +8683,6 @@ src/mess/machine/mikro80.c svneol=native#text/plain
src/mess/machine/mm1kb.c svneol=native#text/plain
src/mess/machine/mm1kb.h svneol=native#text/plain
src/mess/machine/msx.c svneol=native#text/plain
src/mess/machine/msx_slot.c svneol=native#text/plain
src/mess/machine/mtx.c svneol=native#text/plain
src/mess/machine/mz700.c svneol=native#text/plain
src/mess/machine/mz80.c svneol=native#text/plain

View File

@ -387,6 +387,38 @@ BUSOBJS += $(BUSOBJ)/isbx/isbc_218a.o
endif
#-------------------------------------------------
#
#@src/emu/bus/msx_slot/slot.h,BUSES += MSX_SLOT
#-------------------------------------------------
ifneq ($(filter MSX_SLOT,$(BUSES)),)
OBJDIRS += $(BUSOBJ)/msx_slot
BUSOBJS += $(BUSOBJ)/msx_slot/bunsetsu.o
BUSOBJS += $(BUSOBJ)/msx_slot/cartridge.o
BUSOBJS += $(BUSOBJ)/msx_slot/disk.o
BUSOBJS += $(BUSOBJ)/msx_slot/fs4600.o
BUSOBJS += $(BUSOBJ)/msx_slot/music.o
BUSOBJS += $(BUSOBJ)/msx_slot/panasonic08.o
BUSOBJS += $(BUSOBJ)/msx_slot/rom.o
BUSOBJS += $(BUSOBJ)/msx_slot/ram.o
BUSOBJS += $(BUSOBJ)/msx_slot/ram_mm.o
BUSOBJS += $(BUSOBJ)/msx_slot/slot.o
OBJDIRS += $(BUSOBJ)/msx_cart
BUSOBJS += $(BUSOBJ)/msx_cart/ascii.o
BUSOBJS += $(BUSOBJ)/msx_cart/cartridge.o
BUSOBJS += $(BUSOBJ)/msx_cart/crossblaim.o
BUSOBJS += $(BUSOBJ)/msx_cart/fmpac.o
BUSOBJS += $(BUSOBJ)/msx_cart/konami.o
BUSOBJS += $(BUSOBJ)/msx_cart/korean.o
BUSOBJS += $(BUSOBJ)/msx_cart/majutsushi.o
BUSOBJS += $(BUSOBJ)/msx_cart/msxdos2.o
BUSOBJS += $(BUSOBJ)/msx_cart/nomapper.o
BUSOBJS += $(BUSOBJ)/msx_cart/rtype.o
BUSOBJS += $(BUSOBJ)/msx_cart/superloderunner.o
endif
#-------------------------------------------------
#
#@src/emu/bus/kc/kc.h,BUSES += KC

View File

@ -0,0 +1,442 @@
#include "emu.h"
#include "ascii.h"
const device_type MSX_CART_ASCII8 = &device_creator<msx_cart_ascii8>;
const device_type MSX_CART_ASCII16 = &device_creator<msx_cart_ascii16>;
const device_type MSX_CART_ASCII8_SRAM = &device_creator<msx_cart_ascii8_sram>;
const device_type MSX_CART_ASCII16_SRAM = &device_creator<msx_cart_ascii16_sram>;
msx_cart_ascii8::msx_cart_ascii8(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_ASCII8, "MSX Cartridge - ASCII8", tag, owner, clock, "msx_cart_ascii8", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_bank_mask(0)
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = 0;
m_bank_base[i] = NULL;
}
}
void msx_cart_ascii8::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_ascii8::restore_banks), this));
}
void msx_cart_ascii8::restore_banks()
{
for (int i = 0; i < 4; i++)
{
m_bank_base[i] = get_rom_base() + (m_selected_bank[i] & m_bank_mask ) * 0x2000;
}
}
void msx_cart_ascii8::device_reset()
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = 0;
}
}
void msx_cart_ascii8::initialize_cartridge()
{
UINT32 size = get_rom_size();
if ( size > 256 * 0x2000 )
{
fatalerror("ascii8: ROM is too big\n");
}
UINT16 banks = size / 0x2000;
if (size != banks * 0x2000 || (~(banks - 1) % banks))
{
fatalerror("ascii8: Invalid ROM size\n");
}
m_bank_mask = banks - 1;
restore_banks();
}
READ8_MEMBER(msx_cart_ascii8::read_cart)
{
if ( offset >= 0x4000 && offset < 0xC000 )
{
return m_bank_base[(offset - 0x4000) >> 13][offset & 0x1fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_ascii8::write_cart)
{
if (offset >= 0x6000 && offset < 0x8000)
{
UINT8 bank = (offset / 0x800) & 0x03;
m_selected_bank[bank] = data;
m_bank_base[bank] = get_rom_base() + (m_selected_bank[bank] & m_bank_mask ) * 0x2000;
}
}
msx_cart_ascii16::msx_cart_ascii16(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_ASCII16, "MSX Cartridge - ASCII16", tag, owner, clock, "msx_cart_ascii16", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_bank_mask(0)
{
for (int i = 0; i < 2; i++)
{
m_selected_bank[i] = 0;
m_bank_base[i] = NULL;
}
}
void msx_cart_ascii16::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_ascii16::restore_banks), this));
}
void msx_cart_ascii16::restore_banks()
{
for (int i = 0; i < 2; i++)
{
m_bank_base[i] = get_rom_base() + (m_selected_bank[i] & m_bank_mask) * 0x4000;
}
}
void msx_cart_ascii16::device_reset()
{
for (int i = 0; i < 2; i++)
{
m_selected_bank[i] = 0;
}
}
void msx_cart_ascii16::initialize_cartridge()
{
UINT32 size = get_rom_size();
if ( size > 256 * 0x4000 )
{
fatalerror("ascii16: ROM is too big\n");
}
UINT16 banks = size / 0x4000;
if (size != banks * 0x4000 || (~(banks - 1) % banks))
{
fatalerror("ascii16: Invalid ROM size\n");
}
m_bank_mask = banks - 1;
restore_banks();
}
READ8_MEMBER(msx_cart_ascii16::read_cart)
{
if ( offset >= 0x4000 && offset < 0xC000 )
{
return m_bank_base[offset >> 15][offset & 0x3fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_ascii16::write_cart)
{
if (offset >= 0x6000 && offset < 0x6800)
{
m_selected_bank[0] = data;
m_bank_base[0] = get_rom_base() + (m_selected_bank[0] & m_bank_mask) * 0x4000;
}
if (offset >= 0x7000 && offset < 0x7800)
{
m_selected_bank[1] = data;
m_bank_base[1] = get_rom_base() + (m_selected_bank[1] & m_bank_mask) * 0x4000;
}
}
msx_cart_ascii8_sram::msx_cart_ascii8_sram(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_ASCII8_SRAM, "MSX Cartridge - ASCII8 w/SRAM", tag, owner, clock, "msx_cart_ascii8_sram", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_bank_mask(0)
, m_sram_select_mask(0)
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = 0;
m_bank_base[i] = NULL;
}
}
void msx_cart_ascii8_sram::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_ascii8_sram::restore_banks), this));
}
void msx_cart_ascii8_sram::setup_bank(UINT8 bank)
{
if (m_selected_bank[bank] & ~(m_sram_select_mask | m_bank_mask))
{
// Nothing is mapped
m_bank_base[bank] = NULL;
}
else if (m_selected_bank[bank] & m_sram_select_mask)
{
// SRAM is selected
m_bank_base[bank] = get_sram_base();
}
else
{
m_bank_base[bank] = get_rom_base() + (m_selected_bank[bank] & m_bank_mask ) * 0x2000;
}
}
void msx_cart_ascii8_sram::restore_banks()
{
for (int i = 0; i < 4; i++)
{
setup_bank(i);
}
}
void msx_cart_ascii8_sram::device_reset()
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = 0;
}
}
void msx_cart_ascii8_sram::initialize_cartridge()
{
UINT32 size = get_rom_size();
if ( size > 128 * 0x2000 )
{
fatalerror("ascii8_sram: ROM is too big\n");
}
UINT16 banks = size / 0x2000;
if (size != banks * 0x2000 || (~(banks - 1) % banks))
{
fatalerror("ascii8_sram: Invalid ROM size\n");
}
if (get_sram_size() != 0x2000)
{
fatalerror("ascii8_sram: Unsupported SRAM size\n");
}
m_bank_mask = banks - 1;
m_sram_select_mask = banks;
restore_banks();
}
READ8_MEMBER(msx_cart_ascii8_sram::read_cart)
{
if ( offset >= 0x4000 && offset < 0xC000 )
{
UINT8 *bank_base = m_bank_base[(offset - 0x4000) >> 13];
if (bank_base != NULL)
{
return bank_base[offset & 0x1fff];
}
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_ascii8_sram::write_cart)
{
if (offset >= 0x6000 && offset < 0x8000)
{
UINT8 bank = (offset / 0x800) & 0x03;
m_selected_bank[bank] = data;
setup_bank(bank);
}
else if (offset >= 0x8000 && offset < 0xc000)
{
UINT8 bank = (offset & 0x2000) ? 3 : 2;
if ((m_selected_bank[bank] & m_sram_select_mask) && !(m_selected_bank[bank] & ~(m_sram_select_mask | m_bank_mask)))
{
// Write to SRAM
m_bank_base[bank][offset & 0x1fff] = data;
}
}
}
msx_cart_ascii16_sram::msx_cart_ascii16_sram(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_ASCII16_SRAM, "MSX Cartridge - ASCII16 w/SRAM", tag, owner, clock, "msx_cart_ascii16_sram", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_bank_mask(0)
, m_sram_select_mask(0)
{
for (int i = 0; i < 2; i++)
{
m_selected_bank[i] = 0;
m_bank_base[i] = NULL;
}
}
void msx_cart_ascii16_sram::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_ascii16_sram::restore_banks), this));
}
void msx_cart_ascii16_sram::setup_bank(UINT8 bank)
{
if (m_selected_bank[bank] & ~(m_sram_select_mask | m_bank_mask))
{
// Nothing is mapped
m_bank_base[bank] = NULL;
}
else if (m_selected_bank[bank] & m_sram_select_mask)
{
// SRAM is selected
m_bank_base[bank] = get_sram_base();
}
else
{
m_bank_base[bank] = get_rom_base() + (m_selected_bank[bank] & m_bank_mask) * 0x4000;
}
}
void msx_cart_ascii16_sram::restore_banks()
{
for (int i = 0; i < 2; i++)
{
setup_bank(i);
}
}
void msx_cart_ascii16_sram::device_reset()
{
for (int i = 0; i < 2; i++)
{
m_selected_bank[i] = 0;
}
}
void msx_cart_ascii16_sram::initialize_cartridge()
{
UINT32 size = get_rom_size();
if ( size > 128 * 0x4000 )
{
fatalerror("ascii16_sram: ROM is too big\n");
}
UINT16 banks = size / 0x4000;
if (size != banks * 0x4000 || (~(banks - 1) % banks))
{
fatalerror("ascii16_sram: Invalid ROM size\n");
}
if (get_sram_size() != 0x800)
{
fatalerror("ascii16_sram: Unsupported SRAM size\n");
}
m_bank_mask = banks - 1;
m_sram_select_mask = banks;
restore_banks();
}
READ8_MEMBER(msx_cart_ascii16_sram::read_cart)
{
if ( offset >= 0x4000 && offset < 0xC000 )
{
UINT8 bank = offset >> 15;
if (m_bank_base[bank] != NULL)
{
if (m_selected_bank[bank] & m_sram_select_mask)
{
return m_bank_base[bank][offset & 0x7ff];
}
else
{
return m_bank_base[bank][offset & 0x3fff];
}
}
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_ascii16_sram::write_cart)
{
if (offset >= 0x6000 && offset < 0x6800)
{
m_selected_bank[0] = data;
setup_bank(0);
}
if (offset >= 0x7000 && offset < 0x7800)
{
m_selected_bank[1] = data;
setup_bank(1);
}
if (offset >= 0x8000 && offset < 0xc000)
{
if ((m_selected_bank[1] & m_sram_select_mask) && !(m_selected_bank[1] & ~(m_sram_select_mask | m_bank_mask)))
{
// Write to SRAM
m_bank_base[1][offset & 0x7ff] = data;
}
}
}

View File

@ -0,0 +1,116 @@
#ifndef __MSX_CART_ASCII_H
#define __MSX_CART_ASCII_H
#include "bus/msx_cart/cartridge.h"
extern const device_type MSX_CART_ASCII8;
extern const device_type MSX_CART_ASCII16;
extern const device_type MSX_CART_ASCII8_SRAM;
extern const device_type MSX_CART_ASCII16_SRAM;
class msx_cart_ascii8 : public device_t
, public msx_cart_interface
{
public:
msx_cart_ascii8(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_bank_mask;
UINT8 m_selected_bank[4];
UINT8 *m_bank_base[4];
};
class msx_cart_ascii16 : public device_t
, public msx_cart_interface
{
public:
msx_cart_ascii16(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_bank_mask;
UINT8 m_selected_bank[2];
UINT8 *m_bank_base[2];
};
class msx_cart_ascii8_sram : public device_t
, public msx_cart_interface
{
public:
msx_cart_ascii8_sram(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_bank_mask;
UINT8 m_selected_bank[4];
UINT8 *m_bank_base[4];
UINT8 m_sram_select_mask;
void setup_bank(UINT8 bank);
};
class msx_cart_ascii16_sram : public device_t
, public msx_cart_interface
{
public:
msx_cart_ascii16_sram(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_bank_mask;
UINT8 m_selected_bank[2];
UINT8 *m_bank_base[2];
UINT8 m_sram_select_mask;
void setup_bank(UINT8 bank);
};
#endif

View File

@ -0,0 +1,59 @@
#include "emu.h"
#include "cartridge.h"
#include "ascii.h"
#include "crossblaim.h"
#include "fmpac.h"
#include "konami.h"
#include "korean.h"
#include "majutsushi.h"
#include "msxdos2.h"
#include "nomapper.h"
#include "rtype.h"
#include "superloderunner.h"
SLOT_INTERFACE_START(msx_cart)
SLOT_INTERFACE_INTERNAL("nomapper", MSX_CART_NOMAPPER)
SLOT_INTERFACE_INTERNAL("msxdos2", MSX_CART_MSXDOS2)
SLOT_INTERFACE_INTERNAL("konami_scc", MSX_CART_KONAMI_SCC)
SLOT_INTERFACE_INTERNAL("konami", MSX_CART_KONAMI)
SLOT_INTERFACE_INTERNAL("ascii8", MSX_CART_ASCII8)
SLOT_INTERFACE_INTERNAL("ascii16", MSX_CART_ASCII16)
SLOT_INTERFACE_INTERNAL("gamemaster2", MSX_CART_GAMEMASTER2)
SLOT_INTERFACE_INTERNAL("ascii8_sram", MSX_CART_ASCII8_SRAM)
SLOT_INTERFACE_INTERNAL("ascii16_sram", MSX_CART_ASCII16_SRAM)
SLOT_INTERFACE_INTERNAL("rtype", MSX_CART_RTYPE)
SLOT_INTERFACE_INTERNAL("majutsushi", MSX_CART_MAJUTSUSHI)
SLOT_INTERFACE_INTERNAL("fmpac", MSX_CART_FMPAC)
SLOT_INTERFACE_INTERNAL("superloderunner", MSX_CART_SUPERLODERUNNER)
SLOT_INTERFACE_INTERNAL("synthesizer", MSX_CART_SYNTHESIZER)
SLOT_INTERFACE_INTERNAL("cross_blaim", MSX_CART_CROSSBLAIM)
// SLOT_INTERFACE_INTERNAL("disk_rom", MSX_CART_DISK_ROM)
SLOT_INTERFACE_INTERNAL("korean_80in1", MSX_CART_KOREAN_80IN1)
SLOT_INTERFACE_INTERNAL("korean_90in1", MSX_CART_KOREAN_90IN1)
SLOT_INTERFACE_INTERNAL("korean_126in1", MSX_CART_KOREAN_126IN1)
SLOT_INTERFACE_INTERNAL("sound_snatcher", MSX_CART_SOUND_SNATCHER)
SLOT_INTERFACE_INTERNAL("sound_sdsnatch", MSX_CART_SOUND_SDSNATCHER)
SLOT_INTERFACE_END
msx_cart_interface::msx_cart_interface(const machine_config &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device)
{
}
void msx_cart_interface::rom_alloc(UINT32 size)
{
m_rom.resize(size);
}
void msx_cart_interface::ram_alloc(UINT32 size)
{
m_ram.resize(size);
}
void msx_cart_interface::sram_alloc(UINT32 size)
{
m_sram.resize(size);
}

View File

@ -0,0 +1,42 @@
#ifndef __MSX_CART_CARTRIDGE_H
#define __MSX_CART_CARTRIDGE_H
SLOT_INTERFACE_EXTERN(msx_cart);
class msx_cart_interface : public device_slot_card_interface
{
public:
msx_cart_interface(const machine_config &mconfig, device_t &device);
// This is called after loading cartridge contents and allows the cartridge
// implementation to perform some additional initialization based on the
// cartridge contents.
virtual void initialize_cartridge() {}
// reading and writing
virtual DECLARE_READ8_MEMBER(read_cart) { return 0xff; }
virtual DECLARE_WRITE8_MEMBER(write_cart) {}
// ROM/RAM/SRAM management
// Mainly used by the cartridge slot when loading images
void rom_alloc(UINT32 size);
void ram_alloc(UINT32 size);
void sram_alloc(UINT32 size);
UINT8* get_rom_base() { return m_rom; }
UINT8* get_ram_base() { return m_ram; }
UINT8* get_sram_base() { return m_sram; }
UINT32 get_rom_size() { return m_rom.count(); }
UINT32 get_ram_size() { return m_ram.count(); }
UINT32 get_sram_size() { return m_sram.count(); }
protected:
dynamic_buffer m_rom;
dynamic_buffer m_ram;
dynamic_buffer m_sram;
};
#endif

View File

@ -0,0 +1,81 @@
#include "emu.h"
#include "crossblaim.h"
const device_type MSX_CART_CROSSBLAIM = &device_creator<msx_cart_crossblaim>;
msx_cart_crossblaim::msx_cart_crossblaim(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_CROSSBLAIM, "MSX Cartridge - Cross Blaim", tag, owner, clock, "msx_cart_crossblaim", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_selected_bank(1)
{
for (int i = 0; i < 4; i++)
{
m_bank_base[i] = NULL;
}
}
void msx_cart_crossblaim::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_crossblaim::restore_banks), this));
}
void msx_cart_crossblaim::setup_bank()
{
m_bank_base[0] = ( m_selected_bank & 2 ) ? NULL : get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
m_bank_base[2] = get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
m_bank_base[3] = ( m_selected_bank & 2 ) ? NULL : get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
}
void msx_cart_crossblaim::restore_banks()
{
m_bank_base[1] = get_rom_base();
setup_bank();
}
void msx_cart_crossblaim::device_reset()
{
m_selected_bank = 1;
}
void msx_cart_crossblaim::initialize_cartridge()
{
if (get_rom_size() != 0x10000)
{
fatalerror("crossblaim: Invalid ROM size\n");
}
restore_banks();
}
READ8_MEMBER(msx_cart_crossblaim::read_cart)
{
UINT8 *bank_base = m_bank_base[offset >> 14];
if (bank_base != NULL)
{
return bank_base[offset & 0x3fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_crossblaim::write_cart)
{
m_selected_bank = data & 3;
if (m_selected_bank == 0)
{
m_selected_bank = 1;
}
setup_bank();
}

View File

@ -0,0 +1,35 @@
#ifndef __MSX_CART_CROSSBLAIM_H
#define __MSX_CART_CROSSBLAIM_H
#include "bus/msx_cart/cartridge.h"
extern const device_type MSX_CART_CROSSBLAIM;
class msx_cart_crossblaim : public device_t
, public msx_cart_interface
{
public:
msx_cart_crossblaim(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_selected_bank;
UINT8 *m_bank_base[4];
void setup_bank();
};
#endif

View File

@ -0,0 +1,172 @@
/**********************************************************************************
When backing up the SRAM from an FM-PAC the file seems to be prefixed
with: PAC2 BACKUP DATA. We only store the raw sram contents.
**********************************************************************************/
#include "emu.h"
#include "fmpac.h"
const device_type MSX_CART_FMPAC = &device_creator<msx_cart_fmpac>;
msx_cart_fmpac::msx_cart_fmpac(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_FMPAC, "MSX Cartridge - FM-PAC", tag, owner, clock, "msx_cart_fmpac", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_ym2413(*this, "ym2413")
, m_selected_bank(0)
, m_bank_base(NULL)
, m_sram_active(false)
, m_opll_active(false)
, m_1ffe(0)
, m_1fff(0)
, m_7ff6(0)
{
}
static MACHINE_CONFIG_FRAGMENT( fmpac )
// 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'.
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_10_738635MHz/3)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
MACHINE_CONFIG_END
machine_config_constructor msx_cart_fmpac::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( fmpac );
}
void msx_cart_fmpac::device_start()
{
save_item(NAME(m_selected_bank));
save_item(NAME(m_sram_active));
save_item(NAME(m_opll_active));
save_item(NAME(m_1ffe));
save_item(NAME(m_1fff));
save_item(NAME(m_7ff6));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_fmpac::restore_banks), this));
// Install IO read/write handlers
address_space &space = machine().device<cpu_device>("maincpu")->space(AS_IO);
space.install_write_handler(0x7c, 0x7d, write8_delegate(FUNC(msx_cart_fmpac::write_ym2413), this));
}
void msx_cart_fmpac::restore_banks()
{
m_bank_base = get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
}
void msx_cart_fmpac::device_reset()
{
m_selected_bank = 0;
m_sram_active = false;
m_opll_active = false;
m_1ffe = 0;
m_1fff = 0;
m_7ff6 = 0;
}
void msx_cart_fmpac::initialize_cartridge()
{
if ( get_rom_size() != 0x10000 )
{
fatalerror("fmpac: Invalid ROM size\n");
}
if ( get_sram_size() != 0x2000 )
{
fatalerror("fmpac: Invalid SRAM size\n");
}
restore_banks();
}
READ8_MEMBER(msx_cart_fmpac::read_cart)
{
if (offset >= 0x4000 && offset < 0x8000)
{
if (offset == 0x7ff6)
{
return m_7ff6;
}
if (offset == 0x7ff7)
{
return m_selected_bank & 0x03;
}
if (m_sram_active)
{
if (offset & 0x2000)
{
return 0xff;
}
return get_sram_base()[offset & 0x1fff];
}
else
{
return m_bank_base[offset & 0x3fff];
}
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_fmpac::write_cart)
{
if (offset >= 0x4000 && offset < 0x6000)
{
if (m_sram_active)
{
get_sram_base()[offset & 0x1fff] = data;
}
if (offset == 0x5ffe)
{
m_1ffe = data;
}
if (offset == 0x5fff)
{
m_1fff = data;
}
m_sram_active = (m_1ffe == 0x4d) && (m_1fff == 0x69);
}
switch (offset)
{
case 0x7ff4:
case 0x7ff5:
if (m_opll_active)
{
m_ym2413->write(space, offset & 1, data);
}
break;
case 0x7ff6:
m_7ff6 = data & 0x11;
m_opll_active = (m_7ff6 & 0x01);
break;
case 0x7ff7:
m_selected_bank = data;
restore_banks();
break;
}
}
WRITE8_MEMBER(msx_cart_fmpac::write_ym2413)
{
if (m_opll_active)
{
m_ym2413->write(space, offset & 1, data);
}
}

View File

@ -0,0 +1,44 @@
#ifndef __MSX_CART_FMPAC_H
#define __MSX_CART_FMPAC_H
#include "bus/msx_cart/cartridge.h"
#include "sound/2413intf.h"
extern const device_type MSX_CART_FMPAC;
class msx_cart_fmpac : public device_t
, public msx_cart_interface
{
public:
msx_cart_fmpac(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual machine_config_constructor device_mconfig_additions() const;
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
DECLARE_WRITE8_MEMBER(write_ym2413);
private:
required_device<ym2413_device> m_ym2413;
UINT8 m_selected_bank;
UINT8 *m_bank_base;
bool m_sram_active;
bool m_opll_active;
UINT8 m_1ffe;
UINT8 m_1fff;
UINT8 m_7ff6;
};
#endif

View File

@ -0,0 +1,862 @@
#include "emu.h"
#include "konami.h"
const device_type MSX_CART_KONAMI = &device_creator<msx_cart_konami>;
const device_type MSX_CART_KONAMI_SCC = &device_creator<msx_cart_konami_scc>;
const device_type MSX_CART_GAMEMASTER2 = &device_creator<msx_cart_gamemaster2>;
const device_type MSX_CART_SYNTHESIZER = &device_creator<msx_cart_synthesizer>;
const device_type MSX_CART_SOUND_SNATCHER = &device_creator<msx_cart_konami_sound_snatcher>;
const device_type MSX_CART_SOUND_SDSNATCHER = &device_creator<msx_cart_konami_sound_sdsnatcher>;
msx_cart_konami::msx_cart_konami(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_KONAMI, "MSX Cartridge - KONAMI", tag, owner, clock, "msx_cart_konami", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_bank_mask(0)
{
for (int i = 0; i < 3; i++)
{
m_selected_bank[i] = 0;
}
for (int i = 0; i < 8; i++)
{
m_bank_base[i] = NULL;
}
}
void msx_cart_konami::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_konami::restore_banks), this));
}
void msx_cart_konami::restore_banks()
{
m_bank_base[0] = get_rom_base();
m_bank_base[1] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
m_bank_base[2] = get_rom_base();
m_bank_base[3] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
m_bank_base[4] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
m_bank_base[5] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
m_bank_base[6] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
m_bank_base[7] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
}
void msx_cart_konami::device_reset()
{
for (int i = 0; i < 3; i++)
{
m_selected_bank[i] = i + 1;
}
}
void msx_cart_konami::initialize_cartridge()
{
UINT32 size = get_rom_size();
if ( get_rom_size() > 256 * 0x2000 )
{
fatalerror("konami: ROM is too big\n");
}
UINT16 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::read_cart)
{
return m_bank_base[offset >> 13][offset & 0x1fff];
}
WRITE8_MEMBER(msx_cart_konami::write_cart)
{
switch (offset)
{
case 0x6000:
m_selected_bank[0] = data;
m_bank_base[1] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
m_bank_base[3] = get_rom_base() + ( m_selected_bank[0] & m_bank_mask ) * 0x2000;
break;
case 0x8000:
m_selected_bank[1] = data;
m_bank_base[4] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
m_bank_base[6] = get_rom_base() + ( m_selected_bank[1] & m_bank_mask ) * 0x2000;
break;
case 0xa000:
m_selected_bank[2] = data;
m_bank_base[5] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
m_bank_base[7] = get_rom_base() + ( m_selected_bank[2] & m_bank_mask ) * 0x2000;
break;
}
}
msx_cart_konami_scc::msx_cart_konami_scc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_KONAMI_SCC, "MSX Cartridge - KONAMI+SCC", tag, owner, clock, "msx_cart_konami_scc", __FILE__)
, 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] = 0;
}
for (int i = 0; i < 8; i++)
{
m_bank_base[i] = NULL;
}
}
static MACHINE_CONFIG_FRAGMENT( konami_scc )
// 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'.
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("k051649", K051649, XTAL_10_738635MHz/3/2)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.15)
MACHINE_CONFIG_END
machine_config_constructor msx_cart_konami_scc::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( konami_scc );
}
void msx_cart_konami_scc::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::restore_banks), this));
}
void msx_cart_konami_scc::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_reset()
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = i;
}
m_scc_active = false;
}
void msx_cart_konami_scc::initialize_cartridge()
{
UINT32 size = get_rom_size();
if ( get_rom_size() > 256 * 0x2000 )
{
fatalerror("konami_scc: ROM is too big\n");
}
UINT16 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::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::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::msx_cart_gamemaster2(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_GAMEMASTER2, "MSX Cartridge - GAMEMASTER2", tag, owner, clock, "msx_cart_gamemaster2", __FILE__)
, msx_cart_interface(mconfig, *this)
{
for (int i = 0; i < 3; i++)
{
m_selected_bank[i] = 0;
}
for (int i = 0; i < 8; i++)
{
m_bank_base[i] = NULL;
}
}
void msx_cart_gamemaster2::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_gamemaster2::restore_banks), this));
}
void msx_cart_gamemaster2::setup_bank(UINT8 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::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_reset()
{
for (int i = 0; i < 3; i++)
{
m_selected_bank[i] = i + 1;
}
}
void msx_cart_gamemaster2::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::read_cart)
{
UINT8 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::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::msx_cart_synthesizer(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_SYNTHESIZER, "MSX Cartridge - Synthesizer", tag, owner, clock, "msx_cart_synthesizer", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_bank_base(NULL)
, m_dac(*this, "dac")
{
}
static MACHINE_CONFIG_FRAGMENT( synthesizer )
// 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'.
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("dac", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.20)
MACHINE_CONFIG_END
machine_config_constructor msx_cart_synthesizer::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( synthesizer );
}
void msx_cart_synthesizer::device_start()
{
}
void msx_cart_synthesizer::initialize_cartridge()
{
if ( get_rom_size() != 0x8000 )
{
fatalerror("synthesizer: Invalid ROM size\n");
}
m_bank_base = get_rom_base();
}
READ8_MEMBER(msx_cart_synthesizer::read_cart)
{
if (offset >= 0x4000 && offset < 0xc000 )
{
return m_bank_base[offset - 0x4000];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_synthesizer::write_cart)
{
if ((offset & 0xc010) == 0x4000)
{
m_dac->write_unsigned8(data);
}
}
msx_cart_konami_sound::msx_cart_konami_sound(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
, msx_cart_interface(mconfig, *this)
, m_k052539(*this, "k052539")
, m_scc_active(false)
, m_sccplus_active(false)
, m_scc_mode(0)
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = 0;
}
for (int i = 0; i < 8; i++)
{
m_bank_base[i] = NULL;
}
for (int i = 0; i < 16; i++)
{
m_ram_bank[i] = NULL;
}
for (int i = 0; i < 4; i++)
{
m_ram_enabled[i] = false;
}
}
static MACHINE_CONFIG_FRAGMENT( konami_sound )
// 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'.
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("k052539", K051649, XTAL_10_738635MHz/3/2)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.15)
MACHINE_CONFIG_END
machine_config_constructor msx_cart_konami_sound::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( konami_sound );
}
void msx_cart_konami_sound::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::restore_banks), this));
}
void msx_cart_konami_sound::restore_banks()
{
for (int i = 0; i < 4; i++)
{
setup_bank(i);
}
}
void msx_cart_konami_sound::setup_bank(UINT8 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_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::initialize_cartridge()
{
restore_banks();
}
READ8_MEMBER(msx_cart_konami_sound::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 *base = m_bank_base[offset >> 13];
if (base != NULL)
{
return base[offset & 0x1fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_konami_sound::write_cart)
{
switch (offset & 0xe000)
{
case 0x4000:
if (m_ram_enabled[0] && m_bank_base[2] != NULL)
{
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] != NULL)
{
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] != NULL)
{
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] != NULL)
{
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::msx_cart_konami_sound_snatcher(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: msx_cart_konami_sound(mconfig, MSX_CART_SOUND_SNATCHER, "MSX Cartridge - Sound Snatcher", tag, owner, clock, "msx_cart_sound_snatcher", __FILE__)
{
}
void msx_cart_konami_sound_snatcher::initialize_cartridge()
{
msx_cart_konami_sound::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::msx_cart_konami_sound_sdsnatcher(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: msx_cart_konami_sound(mconfig, MSX_CART_SOUND_SDSNATCHER, "MSX Cartridge - Sound SD Snatcher", tag, owner, clock, "msx_cart_sound_sdsnatcher", __FILE__)
{
}
void msx_cart_konami_sound_sdsnatcher::initialize_cartridge()
{
msx_cart_konami_sound::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;
}
}

View File

@ -0,0 +1,169 @@
#ifndef __MSX_CART_KONAMI_H
#define __MSX_CART_KONAMI_H
#include "bus/msx_cart/cartridge.h"
#include "sound/k051649.h"
#include "sound/dac.h"
extern const device_type MSX_CART_KONAMI;
extern const device_type MSX_CART_KONAMI_SCC;
extern const device_type MSX_CART_GAMEMASTER2;
extern const device_type MSX_CART_SYNTHESIZER;
extern const device_type MSX_CART_SOUND_SNATCHER;
extern const device_type MSX_CART_SOUND_SDSNATCHER;
class msx_cart_konami : public device_t
, public msx_cart_interface
{
public:
msx_cart_konami(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_bank_mask;
UINT8 m_selected_bank[3];
UINT8 *m_bank_base[8];
};
class msx_cart_konami_scc : public device_t
, public msx_cart_interface
{
public:
msx_cart_konami_scc(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual machine_config_constructor device_mconfig_additions() const;
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
required_device<k051649_device> m_k051649;
UINT8 m_bank_mask;
UINT8 m_selected_bank[4];
UINT8 *m_bank_base[8];
bool m_scc_active;
};
class msx_cart_gamemaster2 : public device_t
, public msx_cart_interface
{
public:
msx_cart_gamemaster2(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_selected_bank[3];
UINT8 *m_bank_base[8];
void setup_bank(UINT8 bank);
};
class msx_cart_synthesizer : public device_t
, public msx_cart_interface
{
public:
msx_cart_synthesizer(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual machine_config_constructor device_mconfig_additions() const;
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
private:
UINT8 *m_bank_base;
required_device<dac_device> m_dac;
};
class msx_cart_konami_sound : public device_t
, public msx_cart_interface
{
public:
msx_cart_konami_sound(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual machine_config_constructor device_mconfig_additions() const;
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
protected:
UINT8 *m_ram_bank[16];
private:
// This is actually a K052539
required_device<k051649_device> m_k052539;
UINT8 m_selected_bank[4];
UINT8 *m_bank_base[8];
bool m_scc_active;
bool m_sccplus_active;
bool m_ram_enabled[4];
UINT8 m_scc_mode;
void setup_bank(UINT8 bank);
};
class msx_cart_konami_sound_snatcher : public msx_cart_konami_sound
{
public:
msx_cart_konami_sound_snatcher(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual void initialize_cartridge();
};
class msx_cart_konami_sound_sdsnatcher : public msx_cart_konami_sound
{
public:
msx_cart_konami_sound_sdsnatcher(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual void initialize_cartridge();
};
#endif

View File

@ -0,0 +1,297 @@
#include "emu.h"
#include "korean.h"
const device_type MSX_CART_KOREAN_80IN1 = &device_creator<msx_cart_korean_80in1>;
const device_type MSX_CART_KOREAN_90IN1 = &device_creator<msx_cart_korean_90in1>;
const device_type MSX_CART_KOREAN_126IN1 = &device_creator<msx_cart_korean_126in1>;
msx_cart_korean_80in1::msx_cart_korean_80in1(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_KOREAN_80IN1, "MSX Cartridge - Korean 80-in-1", tag, owner, clock, "msx_cart_korean_80in1", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_bank_mask(0)
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = i;
m_bank_base[i] = NULL;
}
}
void msx_cart_korean_80in1::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_korean_80in1::restore_banks), this));
}
void msx_cart_korean_80in1::setup_bank(UINT8 bank)
{
m_bank_base[bank] = get_rom_base() + ( m_selected_bank[bank] & m_bank_mask ) * 0x2000;
}
void msx_cart_korean_80in1::restore_banks()
{
for (int i = 0; i < 4; i++)
{
setup_bank(i);
}
}
void msx_cart_korean_80in1::device_reset()
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = i;
}
}
void msx_cart_korean_80in1::initialize_cartridge()
{
UINT32 size = get_rom_size();
if ( size > 256 * 0x2000 )
{
fatalerror("korean_80in1: ROM is too big\n");
}
UINT16 banks = size / 0x2000;
if (size != banks * 0x2000 || (~(banks - 1) % banks))
{
fatalerror("korean_80in1: Invalid ROM size\n");
}
m_bank_mask = banks - 1;
restore_banks();
}
READ8_MEMBER(msx_cart_korean_80in1::read_cart)
{
if (offset >= 0x4000 && offset < 0xc000)
{
return m_bank_base[(offset - 0x4000) >> 13][offset & 0x1fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_korean_80in1::write_cart)
{
if (offset >= 0x4000 && offset < 0x4004)
{
UINT8 bank = offset & 3;
m_selected_bank[bank] = data;
setup_bank(bank);
}
}
msx_cart_korean_90in1::msx_cart_korean_90in1(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_KOREAN_90IN1, "MSX Cartridge - Korean 90-in-1", tag, owner, clock, "msx_cart_korean_90in1", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_bank_mask(0)
, m_selected_bank(0)
{
for (int i = 0; i < 4; i++)
{
m_bank_base[i] = NULL;
}
}
void msx_cart_korean_90in1::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_korean_90in1::restore_banks), this));
// Install IO read/write handlers
address_space &space = machine().device<cpu_device>("maincpu")->space(AS_IO);
space.install_write_handler(0x77, 0x77, write8_delegate(FUNC(msx_cart_korean_90in1::banking), this));
}
void msx_cart_korean_90in1::restore_banks()
{
UINT8 *base = get_rom_base();
switch (m_selected_bank & 0xc0)
{
case 0x80:
base += (m_selected_bank & 0x3e & m_bank_mask) * 0x4000;
m_bank_base[0] = base;
m_bank_base[1] = base + 0x2000;
m_bank_base[2] = base + 0x4000;
m_bank_base[3] = base + 0x6000;
break;
case 0xc0:
base += (m_selected_bank & m_bank_mask) * 0x4000;
m_bank_base[0] = base;
m_bank_base[1] = base + 0x2000;
m_bank_base[2] = base + 0x2000;
m_bank_base[3] = base;
break;
default:
base += (m_selected_bank & m_bank_mask) * 0x4000;
m_bank_base[0] = base;
m_bank_base[1] = base + 0x2000;
m_bank_base[2] = base;
m_bank_base[3] = base + 0x2000;
break;
}
}
void msx_cart_korean_90in1::device_reset()
{
m_selected_bank = 0;
}
void msx_cart_korean_90in1::initialize_cartridge()
{
UINT32 size = get_rom_size();
if ( size > 64 * 0x4000 )
{
fatalerror("korean_90in1: ROM is too big\n");
}
UINT16 banks = size / 0x4000;
if (size != banks * 0x4000 || (~(banks - 1) % banks))
{
fatalerror("korean_90in1: Invalid ROM size\n");
}
m_bank_mask = banks - 1;
restore_banks();
}
READ8_MEMBER(msx_cart_korean_90in1::read_cart)
{
if (offset >= 0x4000 && offset < 0xc000)
{
return m_bank_base[(offset - 0x4000) >> 13][offset & 0x1fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_korean_90in1::banking)
{
m_selected_bank = data;
restore_banks();
}
msx_cart_korean_126in1::msx_cart_korean_126in1(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_KOREAN_126IN1, "MSX Cartridge - Korean 126-in-1", tag, owner, clock, "msx_cart_korean_126in1", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_bank_mask(0)
{
for (int i = 0; i < 2; i++)
{
m_selected_bank[i] = i;
m_bank_base[i] = NULL;
}
}
void msx_cart_korean_126in1::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_korean_126in1::restore_banks), this));
}
void msx_cart_korean_126in1::setup_bank(UINT8 bank)
{
m_bank_base[bank] = get_rom_base() + ( m_selected_bank[bank] & m_bank_mask ) * 0x4000;
}
void msx_cart_korean_126in1::restore_banks()
{
for (int i = 0; i < 2; i++)
{
setup_bank(i);
}
}
void msx_cart_korean_126in1::device_reset()
{
for (int i = 0; i < 2; i++)
{
m_selected_bank[i] = i;
}
}
void msx_cart_korean_126in1::initialize_cartridge()
{
UINT32 size = get_rom_size();
if ( size > 256 * 0x4000 )
{
fatalerror("korean_126in1: ROM is too big\n");
}
UINT16 banks = size / 0x4000;
if (size != banks * 0x4000 || (~(banks - 1) % banks))
{
fatalerror("korean_126in1: Invalid ROM size\n");
}
m_bank_mask = banks - 1;
restore_banks();
}
READ8_MEMBER(msx_cart_korean_126in1::read_cart)
{
if (offset >= 0x4000 && offset < 0xc000)
{
return m_bank_base[offset >> 15][offset & 0x3fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_korean_126in1::write_cart)
{
if (offset >= 0x4000 && offset < 0x4002)
{
UINT8 bank = offset & 1;
m_selected_bank[bank] = data;
setup_bank(bank);
}
}

View File

@ -0,0 +1,89 @@
#ifndef __MSX_CART_KOREAN_H
#define __MSX_CART_KOREAN_H
#include "bus/msx_cart/cartridge.h"
extern const device_type MSX_CART_KOREAN_80IN1;
extern const device_type MSX_CART_KOREAN_90IN1;
extern const device_type MSX_CART_KOREAN_126IN1;
class msx_cart_korean_80in1 : public device_t
, public msx_cart_interface
{
public:
msx_cart_korean_80in1(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_bank_mask;
UINT8 m_selected_bank[4];
UINT8 *m_bank_base[4];
void setup_bank(UINT8 bank);
};
class msx_cart_korean_90in1 : public device_t
, public msx_cart_interface
{
public:
msx_cart_korean_90in1(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
DECLARE_WRITE8_MEMBER(banking);
void restore_banks();
private:
UINT8 m_bank_mask;
UINT8 m_selected_bank;
UINT8 *m_bank_base[4];
};
class msx_cart_korean_126in1 : public device_t
, public msx_cart_interface
{
public:
msx_cart_korean_126in1(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_bank_mask;
UINT8 m_selected_bank[2];
UINT8 *m_bank_base[2];
void setup_bank(UINT8 bank);
};
#endif

View File

@ -0,0 +1,114 @@
#include "emu.h"
#include "majutsushi.h"
const device_type MSX_CART_MAJUTSUSHI = &device_creator<msx_cart_majutsushi>;
msx_cart_majutsushi::msx_cart_majutsushi(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_MAJUTSUSHI, "MSX Cartridge - Majutsushi", tag, owner, clock, "msx_cart_majutsushi", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_dac(*this, "dac")
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = 0;
}
for (int i = 0; i < 8; i++)
{
m_bank_base[i] = NULL;
}
}
static MACHINE_CONFIG_FRAGMENT( majutsushi )
// 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'.
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("dac", DAC, 0)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
MACHINE_CONFIG_END
machine_config_constructor msx_cart_majutsushi::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( majutsushi );
}
void msx_cart_majutsushi::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_majutsushi::restore_banks), this));
}
void msx_cart_majutsushi::restore_banks()
{
m_bank_base[0] = get_rom_base() + ( m_selected_bank[0] & 0x0f ) * 0x2000;
m_bank_base[1] = get_rom_base() + ( m_selected_bank[1] & 0x0f ) * 0x2000;
m_bank_base[2] = get_rom_base() + ( m_selected_bank[0] & 0x0f ) * 0x2000;
m_bank_base[3] = get_rom_base() + ( m_selected_bank[1] & 0x0f ) * 0x2000;
m_bank_base[4] = get_rom_base() + ( m_selected_bank[2] & 0x0f ) * 0x2000;
m_bank_base[5] = get_rom_base() + ( m_selected_bank[3] & 0x0f ) * 0x2000;
m_bank_base[6] = get_rom_base() + ( m_selected_bank[2] & 0x0f ) * 0x2000;
m_bank_base[7] = get_rom_base() + ( m_selected_bank[3] & 0x0f ) * 0x2000;
}
void msx_cart_majutsushi::device_reset()
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = i;
}
}
void msx_cart_majutsushi::initialize_cartridge()
{
if ( get_rom_size() != 0x20000 )
{
fatalerror("majutsushi: Invalid ROM size\n");
}
restore_banks();
}
READ8_MEMBER(msx_cart_majutsushi::read_cart)
{
return m_bank_base[offset >> 13][offset & 0x1fff];
}
WRITE8_MEMBER(msx_cart_majutsushi::write_cart)
{
switch (offset & 0xe000)
{
case 0x4000:
if (offset & 0x1000)
{
m_dac->write_unsigned8(data);
}
break;
case 0x6000:
m_selected_bank[1] = data & 0x0f;
m_bank_base[1] = get_rom_base() + m_selected_bank[1] * 0x2000;
m_bank_base[3] = get_rom_base() + m_selected_bank[1] * 0x2000;
break;
case 0x8000:
m_selected_bank[2] = data & 0x0f;
m_bank_base[4] = get_rom_base() + m_selected_bank[2] * 0x2000;
m_bank_base[6] = get_rom_base() + m_selected_bank[2] * 0x2000;
break;
case 0xa000:
m_selected_bank[3] = data & 0x0f;
m_bank_base[5] = get_rom_base() + m_selected_bank[3] * 0x2000;
m_bank_base[7] = get_rom_base() + m_selected_bank[3] * 0x2000;
break;
}
}

View File

@ -0,0 +1,37 @@
#ifndef __MSX_CART_MAJUTSUSHI_H
#define __MSX_CART_MAJUTSUSHI_H
#include "bus/msx_cart/cartridge.h"
#include "sound/dac.h"
extern const device_type MSX_CART_MAJUTSUSHI;
class msx_cart_majutsushi : public device_t
, public msx_cart_interface
{
public:
msx_cart_majutsushi(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual machine_config_constructor device_mconfig_additions() const;
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
required_device<dac_device> m_dac;
UINT8 m_selected_bank[4];
UINT8 *m_bank_base[8];
};
#endif

View File

@ -0,0 +1,66 @@
#include "emu.h"
#include "msxdos2.h"
const device_type MSX_CART_MSXDOS2 = &device_creator<msx_cart_msxdos2>;
msx_cart_msxdos2::msx_cart_msxdos2(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_MSXDOS2, "MSX Cartridge - MSXDOS2", tag, owner, clock, "msx_cart_msxdos2", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_selected_bank(0)
, m_bank_base(NULL)
{
}
void msx_cart_msxdos2::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_msxdos2::restore_banks), this));
}
void msx_cart_msxdos2::restore_banks()
{
m_bank_base = get_rom_base() + ( m_selected_bank & 0x03 ) * 0x4000;
}
void msx_cart_msxdos2::device_reset()
{
m_selected_bank = 0;
}
void msx_cart_msxdos2::initialize_cartridge()
{
if (get_rom_size() != 0x10000)
{
fatalerror("msxdos2: Invalid ROM size\n");
}
restore_banks();
}
READ8_MEMBER(msx_cart_msxdos2::read_cart)
{
if (offset >= 0x4000 && offset < 0x8000)
{
return m_bank_base[offset & 0x3fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_msxdos2::write_cart)
{
if (offset == 0x6000)
{
m_selected_bank = data;
restore_banks();
}
}

View File

@ -0,0 +1,33 @@
#ifndef __MSX_CART_MSXDOS2_H
#define __MSX_CART_MSXDOS2_H
#include "bus/msx_cart/cartridge.h"
extern const device_type MSX_CART_MSXDOS2;
class msx_cart_msxdos2 : public device_t
, public msx_cart_interface
{
public:
msx_cart_msxdos2(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_selected_bank;
UINT8 *m_bank_base;
};
#endif

View File

@ -0,0 +1,49 @@
#include "emu.h"
#include "nomapper.h"
const device_type MSX_CART_NOMAPPER = &device_creator<msx_cart_nomapper>;
msx_cart_nomapper::msx_cart_nomapper(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_NOMAPPER, "MSX Cartridge - ROM", tag, owner, clock, "msx_cart_nomapper", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_start_address(0)
, m_end_address(0)
{
}
void msx_cart_nomapper::device_start()
{
}
void msx_cart_nomapper::initialize_cartridge()
{
UINT32 size = get_rom_size();
m_start_address = 0x4000;
if (size <= 0x4000)
{
// Check if this ROM should be in page 2
UINT8 *rom = get_rom_base();
if (rom[0] == 'A' && rom[1] == 'B' && (rom[3] & 0x80))
{
m_start_address = 0x8000;
}
}
m_end_address = MIN(m_start_address + size, 0x10000);
}
READ8_MEMBER(msx_cart_nomapper::read_cart)
{
if ( offset >= m_start_address && offset < m_end_address )
{
return get_rom_base()[offset - m_start_address];
}
return 0xff;
}

View File

@ -0,0 +1,28 @@
#ifndef __MSX_CART_NOMAPPER_H
#define __MSX_CART_NOMAPPER_H
#include "bus/msx_cart/cartridge.h"
extern const device_type MSX_CART_NOMAPPER;
class msx_cart_nomapper : public device_t
, public msx_cart_interface
{
public:
msx_cart_nomapper(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
private:
UINT32 m_start_address;
UINT32 m_end_address;
};
#endif

View File

@ -0,0 +1,77 @@
#include "emu.h"
#include "rtype.h"
const device_type MSX_CART_RTYPE = &device_creator<msx_cart_rtype>;
msx_cart_rtype::msx_cart_rtype(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_RTYPE, "MSX Cartridge - R-Type", tag, owner, clock, "msx_cart_rtype", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_selected_bank(0)
{
for (int i = 0; i < 2; i++)
{
m_bank_base[i] = NULL;
}
}
void msx_cart_rtype::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_rtype::restore_banks), this));
}
void msx_cart_rtype::restore_banks()
{
m_bank_base[0] = get_rom_base() + 15 * 0x4000;
if (m_selected_bank & 0x10)
{
m_selected_bank &= 0x17;
}
m_bank_base[1] = get_rom_base() + m_selected_bank * 0x4000;
}
void msx_cart_rtype::device_reset()
{
m_selected_bank = 15;
}
void msx_cart_rtype::initialize_cartridge()
{
if ( get_rom_size() != 0x80000 && get_rom_size() != 0x60000 )
{
fatalerror("rtype: Invalid ROM size\n");
}
restore_banks();
}
READ8_MEMBER(msx_cart_rtype::read_cart)
{
if (offset >= 0x4000 && offset < 0xc000)
{
return m_bank_base[offset >> 15][offset & 0x3fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_rtype::write_cart)
{
if (offset >= 0x7000 && offset < 0x8000)
{
m_selected_bank = data & 0x1f;
if (m_selected_bank & 0x10)
{
m_selected_bank &= 0x17;
}
m_bank_base[1] = get_rom_base() + m_selected_bank * 0x4000;
}
}

View File

@ -0,0 +1,33 @@
#ifndef __MSX_CART_RTYPE_H
#define __MSX_CART_RTYPE_H
#include "bus/msx_cart/cartridge.h"
extern const device_type MSX_CART_RTYPE;
class msx_cart_rtype : public device_t
, public msx_cart_interface
{
public:
msx_cart_rtype(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_reset();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
virtual DECLARE_WRITE8_MEMBER(write_cart);
void restore_banks();
private:
UINT8 m_selected_bank;
UINT8 *m_bank_base[2];
};
#endif

View File

@ -0,0 +1,61 @@
#include "emu.h"
#include "superloderunner.h"
const device_type MSX_CART_SUPERLODERUNNER = &device_creator<msx_cart_superloderunner>;
msx_cart_superloderunner::msx_cart_superloderunner(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_CART_SUPERLODERUNNER, "MSX Cartridge - Super Lode Runner", tag, owner, clock, "msx_cart_superloderunner", __FILE__)
, msx_cart_interface(mconfig, *this)
, m_selected_bank(0)
, m_bank_base(NULL)
{
}
void msx_cart_superloderunner::device_start()
{
save_item(NAME(m_selected_bank));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_cart_superloderunner::restore_banks), this));
// Install evil memory write handler
address_space &space = machine().device<cpu_device>("maincpu")->space(AS_PROGRAM);
space.install_write_handler(0x0000, 0x0000, write8_delegate(FUNC(msx_cart_superloderunner::banking), this));
}
void msx_cart_superloderunner::restore_banks()
{
m_bank_base = get_rom_base() + (m_selected_bank & 0x0f) * 0x4000;
}
void msx_cart_superloderunner::initialize_cartridge()
{
if (get_rom_size() != 0x20000)
{
fatalerror("crossblaim: Invalid ROM size\n");
}
restore_banks();
}
READ8_MEMBER(msx_cart_superloderunner::read_cart)
{
if (offset >= 0x8000 && offset < 0xc000)
{
return m_bank_base[offset & 0x3fff];
}
return 0xff;
}
WRITE8_MEMBER(msx_cart_superloderunner::banking)
{
m_selected_bank = data;
restore_banks();
}

View File

@ -0,0 +1,33 @@
#ifndef __MSX_CART_SUPERLODERUNNER_H
#define __MSX_CART_SUPERLODERUNNER_H
#include "bus/msx_cart/cartridge.h"
extern const device_type MSX_CART_SUPERLODERUNNER;
class msx_cart_superloderunner : public device_t
, public msx_cart_interface
{
public:
msx_cart_superloderunner(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void initialize_cartridge();
virtual DECLARE_READ8_MEMBER(read_cart);
DECLARE_WRITE8_MEMBER(banking);
void restore_banks();
private:
UINT8 m_selected_bank;
UINT8 *m_bank_base;
};
#endif

View File

@ -0,0 +1,77 @@
/*
Emulation for the bunsetsu internal firmware mapper found in a number of MSX machines
*/
#include "emu.h"
#include "bunsetsu.h"
const device_type MSX_SLOT_BUNSETSU = &device_creator<msx_slot_bunsetsu_device>;
msx_slot_bunsetsu_device::msx_slot_bunsetsu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: msx_slot_rom_device(mconfig, MSX_SLOT_BUNSETSU, "MSX Internal BUNSETSU", tag, owner, clock, "msx_slot_bunsetsu", __FILE__)
, m_bunsetsu_region(NULL)
, m_bunsetsu_region_tag(NULL)
, m_bunsetsu_address(0)
{
}
void msx_slot_bunsetsu_device::device_start()
{
msx_slot_rom_device::device_start();
if (m_bunsetsu_region_tag == NULL)
{
fatalerror("msx_slot_bunsetsu_device: no bunsetsu region tag specified\n");
}
m_bunsetsu_region = owner()->memregion(m_bunsetsu_region_tag);
if (m_bunsetsu_region == NULL)
{
fatalerror("msx_slot_bunsetsu_device: Unable to find region with tag '%s'\n", m_bunsetsu_region_tag);
}
if (m_bunsetsu_region->bytes() != 0x20000)
{
fatalerror("msx_slot_bunsetsu_device: Bunsetsu region must be 0x20000 bytes.\n");
}
}
void msx_slot_bunsetsu_device::device_reset()
{
m_bunsetsu_address = 0;
}
READ8_MEMBER(msx_slot_bunsetsu_device::read)
{
if (offset == 0xbfff)
{
return m_bunsetsu_region->u8(m_bunsetsu_address++ & 0x1ffff);
}
return msx_slot_rom_device::read(space, offset);
}
WRITE8_MEMBER(msx_slot_bunsetsu_device::write)
{
switch (offset)
{
case 0xbffc:
m_bunsetsu_address = (m_bunsetsu_address & 0xffff00) | data;
break;
case 0xbffd:
m_bunsetsu_address = (m_bunsetsu_address & 0xff00ff) | (data << 8);
break;
case 0xbffe:
m_bunsetsu_address = (m_bunsetsu_address & 0x00ffff) | (data << 16);
break;
}
}

View File

@ -0,0 +1,38 @@
#ifndef __MSX_SLOT_BUNSETSU_H
#define __MSX_SLOT_BUNSETSU_H
#include "bus/msx_slot/slot.h"
#include "bus/msx_slot/rom.h"
extern const device_type MSX_SLOT_BUNSETSU;
#define MCFG_MSX_SLOT_BUNSETSU_ADD(_tag, _startpage, _numpages, _region, _offset, _bunsetsu_region_tag) \
MCFG_MSX_INTERNAL_SLOT_ADD(_tag, MSX_SLOT_BUNSETSU, _startpage, _numpages) \
msx_slot_rom_device::set_rom_start(*device, _region, _offset); \
msx_slot_bunsetsu_device::set_bunsetsu_region_tag(*device, _bunsetsu_region_tag); \
class msx_slot_bunsetsu_device : public msx_slot_rom_device
{
public:
msx_slot_bunsetsu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration helpers
static void set_bunsetsu_region_tag(device_t &device, const char *tag) { dynamic_cast<msx_slot_bunsetsu_device &>(device).m_bunsetsu_region_tag = tag; }
virtual void device_start();
virtual void device_reset();
virtual DECLARE_READ8_MEMBER(read);
virtual DECLARE_WRITE8_MEMBER(write);
private:
memory_region *m_bunsetsu_region;
const char *m_bunsetsu_region_tag;
UINT32 m_bunsetsu_address;
};
#endif

View File

@ -0,0 +1,317 @@
#include "emu.h"
#include "bus/msx_slot/cartridge.h"
#include "hashfile.h"
enum
{
NOMAPPER = 0,
ASCII8,
ASCII8_SRAM,
ASCII16,
ASCII16_SRAM,
CROSSBLAIM,
GAMEMASTER2,
KOREAN_80IN1,
KOREAN_90IN1,
KOREAN_126IN1,
FMPAC,
RTYPE,
KONAMI,
KONAMI_SCC,
SUPERLODERUNNER,
MAJUTSUSHI,
DISK_ROM,
SYNTHESIZER,
MSXDOS2
};
const device_type MSX_SLOT_CARTRIDGE = &device_creator<msx_slot_cartridge_device>;
msx_slot_cartridge_device::msx_slot_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_SLOT_CARTRIDGE, "MSX Cartridge slot", tag, owner, clock, "msx_slot_cartridge", __FILE__)
, device_image_interface(mconfig, *this)
, device_slot_interface(mconfig, *this)
, msx_internal_slot_interface()
{
}
static const struct
{
int pcb_id;
const char *slot_option;
} slot_list[] =
{
{ NOMAPPER, "nomapper" },
{ ASCII8, "ascii8" },
{ ASCII8_SRAM, "ascii8_sram" },
{ ASCII16, "ascii16" },
{ ASCII16_SRAM, "ascii16_sram" },
{ CROSSBLAIM, "cross_blaim" },
{ GAMEMASTER2, "gamemaster2" },
{ KOREAN_80IN1, "korean_80in1" },
{ KOREAN_90IN1, "korean_90in1" },
{ KOREAN_126IN1, "korean_126in1" },
{ FMPAC, "fmpac" },
{ RTYPE, "rtype" },
{ KONAMI, "konami" },
{ KONAMI_SCC, "konami_scc" },
{ SUPERLODERUNNER, "superloderunner" },
{ MAJUTSUSHI, "majutsushi" },
{ DISK_ROM, "disk_rom" },
{ SYNTHESIZER, "synthesizer" },
{ MSXDOS2, "msxdos2" }
};
static const char *msx_cart_get_slot_option(int type)
{
for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
{
if (slot_list[i].pcb_id == type)
return slot_list[i].slot_option;
}
return slot_list[0].slot_option;
}
void msx_slot_cartridge_device::device_start()
{
m_cartridge = dynamic_cast<msx_cart_interface *>(get_card_device());
}
bool msx_slot_cartridge_device::call_load()
{
if ( m_cartridge )
{
if ( software_entry() )
{
// Allocate and copy rom contents
UINT32 length = get_software_region_length("rom");
m_cartridge->rom_alloc( length );
UINT8 *rom_base = m_cartridge->get_rom_base();
memcpy(rom_base, get_software_region("rom"), length);
// Allocate ram
length = get_software_region_length("ram");
m_cartridge->ram_alloc( length );
// Allocate sram
length = get_software_region_length("sram");
m_cartridge->sram_alloc( length );
}
else
{
UINT32 length = this->length();
UINT32 length_aligned = 0x4000;
while (length_aligned < length )
{
length_aligned *= 2;
}
m_cartridge->rom_alloc(length_aligned);
m_cartridge->ram_alloc(0);
m_cartridge->sram_alloc(0);
if (fread(m_cartridge->get_rom_base(), length) != length)
{
seterror(IMAGE_ERROR_UNSPECIFIED, "Unable to fully read file");
return IMAGE_INIT_FAIL;
}
// Check if there's some mapper related
astring extrainfo;
if (hashfile_extrainfo(*this, extrainfo))
{
}
}
m_cartridge->initialize_cartridge();
if (m_cartridge->get_sram_size() > 0)
{
battery_load(m_cartridge->get_sram_base(), m_cartridge->get_sram_size(), 0x00);
}
}
return IMAGE_INIT_PASS;
}
void msx_slot_cartridge_device::call_unload()
{
if (m_cartridge)
{
if (m_cartridge->get_sram_size() > 0)
{
battery_save(m_cartridge->get_sram_base(), m_cartridge->get_sram_size());
}
}
}
bool msx_slot_cartridge_device::call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry)
{
load_software_part_region(*this, swlist, swname, start_entry);
return true;
}
int msx_slot_cartridge_device::get_cart_type(UINT8 *rom, UINT32 length)
{
if (length < 0x2000)
{
return -1;
}
if (length < 0x10000)
{
return NOMAPPER;
}
if ( (rom[0x10] == 'Y') && (rom[0x11] == 'Z') && (length > 0x18000) )
{
return GAMEMASTER2;
}
int kon4 = 0, kon5 = 0, asc8 = 0, asc16 = 0;
for (int i=0; i < length-3; i++)
{
if (rom[i] == 0x32 && rom[i+1] == 0)
{
switch (rom[i+2])
{
case 0x60:
case 0x70:
asc16++;
asc8++;
break;
case 0x68:
case 0x78:
asc8++;
asc16--;
break;
}
switch (rom[i+2])
{
case 0x60:
case 0x80:
case 0xa0:
kon4++;
break;
case 0x50:
case 0x70:
case 0x90:
case 0xb0:
kon5++;
break;
}
}
}
if (MAX (kon4, kon5) > MAX (asc8, asc16) )
{
return (kon5 > kon4) ? KONAMI_SCC : KONAMI;
}
else
{
return (asc8 > asc16) ? ASCII8 : ASCII16;
}
return NOMAPPER;
}
void msx_slot_cartridge_device::get_default_card_software(astring &result)
{
if (open_image_file(mconfig().options()))
{
const char *slot_string = "nomapper";
UINT32 length = core_fsize(m_file);
dynamic_buffer rom(length);
int type = NOMAPPER;
// Check if there's some mapper related information in the hashfiles
astring extrainfo;
if (hashfile_extrainfo(*this, extrainfo))
{
int extrainfo_type = -1;
if (1 == sscanf(extrainfo.cstr(), "%d", &extrainfo_type))
{
static const struct { int extrainfo; int mapper; } extrainfo_map[] = {
//{ 0, NOMAPPER },
{ 1, MSXDOS2 },
{ 2, KONAMI_SCC },
{ 3, KONAMI },
{ 4, ASCII8 },
{ 5, ASCII16 },
{ 6, GAMEMASTER2 },
{ 7, ASCII8_SRAM },
{ 8, ASCII16_SRAM },
{ 9, RTYPE },
{ 10, MAJUTSUSHI },
{ 11, FMPAC },
{ 12, SUPERLODERUNNER },
{ 13, SYNTHESIZER },
{ 14, CROSSBLAIM },
{ 15, DISK_ROM },
{ 16, KOREAN_80IN1 },
{ 17, KOREAN_126IN1 }
};
for (int i = 0; i < ARRAY_LENGTH(extrainfo_map); i++)
{
if (extrainfo_map[i].extrainfo == extrainfo_type)
{
type = extrainfo_map[i].mapper;
}
}
}
}
if (type == NOMAPPER)
{
// Not identified through hashfile, try automatic detection
type = get_cart_type(rom, length);
}
if (type > NOMAPPER)
{
slot_string = msx_cart_get_slot_option(type);
}
result.cpy(slot_string);
return;
}
software_get_default_slot(result, "nomapper");
}
READ8_MEMBER(msx_slot_cartridge_device::read)
{
if ( m_cartridge )
{
return m_cartridge->read_cart(space, offset);
}
return 0xFF;
}
WRITE8_MEMBER(msx_slot_cartridge_device::write)
{
if ( m_cartridge )
{
m_cartridge->write_cart(space, offset, data);
}
}

View File

@ -0,0 +1,57 @@
#ifndef __MSX_SLOT_CARTRIDGE_H
#define __MSX_SLOT_CARTRIDGE_H
#include "slot.h"
#include "bus/msx_cart/cartridge.h"
extern const device_type MSX_SLOT_CARTRIDGE;
#define MCFG_MSX_SLOT_CARTRIDGE_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, MSX_SLOT_CARTRIDGE, 0) \
MCFG_DEVICE_SLOT_INTERFACE(msx_cart, NULL, false)
class msx_slot_cartridge_device : public device_t
, public device_image_interface
, public device_slot_interface
, public msx_internal_slot_interface
{
public:
// construction/destruction
msx_slot_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// device-level overrides
virtual void device_start();
virtual void device_config_complete() { update_names(MSX_SLOT_CARTRIDGE, "cartridge", "cart"); }
// image-level overrides
virtual bool call_load();
virtual void call_unload();
virtual bool call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry);
virtual iodevice_t image_type() const { return IO_CARTSLOT; }
virtual bool is_readable() const { return true; }
virtual bool is_writeable() const { return false; }
virtual bool is_creatable() const { return false; }
virtual bool must_be_loaded() const { return false; }
virtual bool is_reset_on_load() const { return true; }
virtual const option_guide *create_option_guide() const { return NULL; }
virtual const char *image_interface() const { return "msx_cart"; }
virtual const char *file_extensions() const { return "mx1,bin,rom"; }
// slot interface overrides
virtual void get_default_card_software(astring &result);
// msx_internal_slot-level overrides
virtual DECLARE_READ8_MEMBER(read);
virtual DECLARE_WRITE8_MEMBER(write);
private:
msx_cart_interface *m_cartridge;
int get_cart_type(UINT8 *rom, UINT32 length);
};
#endif

369
src/emu/bus/msx_slot/disk.c Normal file
View File

@ -0,0 +1,369 @@
/*
From: erbo@xs4all.nl (erik de boer)
sony and philips have used (almost) the same design
and this is the memory layout
but it is not a msx standard !
WD1793 or wd2793 registers
address
7FF8H read status register
write command register
7FF9H r/w track register (r/o on NMS 8245 and Sony)
7FFAH r/w sector register (r/o on NMS 8245 and Sony)
7FFBH r/w data register
hardware registers
address
7FFCH r/w bit 0 side select
7FFDH r/w b7>M-on , b6>in-use , b1>ds1 , b0>ds0 (all neg. logic)
7FFEH not used
7FFFH read b7>drq , b6>intrq
set on 7FFDH bit 2 always to 0 (some use it as disk change reset)
*/
#include "emu.h"
#include "disk.h"
const device_type MSX_SLOT_DISK1 = &device_creator<msx_slot_disk1_device>;
const device_type MSX_SLOT_DISK2 = &device_creator<msx_slot_disk2_device>;
msx_slot_disk_device::msx_slot_disk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
: msx_slot_rom_device(mconfig, type, name, tag, owner, clock, shortname, source)
, m_fdc(NULL)
, m_floppy0(NULL)
, m_floppy1(NULL)
, m_floppy(NULL)
, m_fdc_tag(NULL)
, m_floppy0_tag(NULL)
, m_floppy1_tag(NULL)
{
}
void msx_slot_disk_device::device_start()
{
msx_slot_rom_device::device_start();
if (m_fdc_tag == NULL)
{
fatalerror("msx_slot_disk_device: no FDC tag specified\n");
}
m_fdc = owner()->subdevice<wd_fdc_analog_t>(m_fdc_tag);
m_floppy0 = owner()->subdevice<floppy_connector>(m_floppy0_tag);
m_floppy1 = owner()->subdevice<floppy_connector>(m_floppy1_tag);
if (m_fdc == NULL)
{
fatalerror("msx_slot_disk_device: Unable to find FDC with tag '%s'\n", m_fdc_tag);
}
if (m_floppy0 == NULL && m_floppy1 == NULL)
{
logerror("msx_slot_disk_device: Warning: both floppy0 and floppy1 were not found\n");
}
}
msx_slot_disk1_device::msx_slot_disk1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: msx_slot_disk_device(mconfig, MSX_SLOT_DISK1, "MSX Internal floppy type 1", tag, owner, clock, "msx_slot_disk1", __FILE__)
, m_side_control(0)
, m_control(0)
{
}
void msx_slot_disk1_device::device_start()
{
msx_slot_disk_device::device_start();
save_item(NAME(m_side_control));
save_item(NAME(m_control));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_slot_disk1_device::post_load), this));
}
void msx_slot_disk1_device::device_reset()
{
m_fdc->dden_w(false);
}
void msx_slot_disk1_device::post_load()
{
UINT8 data = m_control;
// To make sure the FDD busy led status gets set correctly
m_control ^= 0x40;
set_control(data);
}
void msx_slot_disk1_device::set_side_control(UINT8 data)
{
m_side_control = data;
if (m_floppy)
{
m_floppy->ss_w(m_side_control & 0x01);
}
}
void msx_slot_disk1_device::set_control(UINT8 data)
{
UINT8 old_m_control = m_control;
m_control = data;
switch (m_control & 0x03)
{
case 0:
case 2:
m_floppy = m_floppy0 ? m_floppy0->get_device() : NULL;
break;
case 1:
m_floppy = m_floppy1 ? m_floppy1->get_device() : NULL;
break;
default:
m_floppy = NULL;
break;
}
if (m_floppy)
{
m_floppy->mon_w((m_control & 0x80) ? 0 : 1);
m_floppy->ss_w(m_side_control & 0x01);
}
m_fdc->set_floppy(m_floppy);
if ((old_m_control ^ m_control) & 0x40)
{
set_led_status(machine(), 0, !(m_control & 0x40));
}
}
READ8_MEMBER(msx_slot_disk1_device::read)
{
switch (offset)
{
case 0x7ff8:
case 0xbff8:
return m_fdc->status_r();
case 0x7ff9:
case 0xbff9:
return m_fdc->track_r();
case 0x7ffa:
case 0xbffa:
return m_fdc->sector_r();
case 0x7ffb:
case 0xbffb:
return m_fdc->data_r();
case 0x7ffc:
case 0xbffc:
return 0xfe | (m_side_control & 0x01);
case 0x7ffd:
case 0xbffd:
return ( m_control & 0x83 ) | 0x78;
case 0x7fff:
case 0xbfff:
return 0x3f | (m_fdc->intrq_r() ? 0 : 0x40) | (m_fdc->drq_r() ? 0 : 0x80);
}
return msx_slot_rom_device::read(space, offset);
}
WRITE8_MEMBER(msx_slot_disk1_device::write)
{
switch (offset)
{
case 0x7ff8:
case 0xbff8:
m_fdc->cmd_w(data);
break;
case 0x7ff9:
case 0xbff9:
m_fdc->track_w(data);
break;
case 0x7ffa:
case 0xbffa:
m_fdc->sector_w(data);
break;
case 0x7ffb:
case 0xbffb:
m_fdc->data_w(data);
break;
case 0x7ffc:
case 0xbffc:
set_side_control(data);
break;
case 0x7ffd:
case 0xbffd:
set_control(data);
break;
}
}
msx_slot_disk2_device::msx_slot_disk2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: msx_slot_disk_device(mconfig, MSX_SLOT_DISK2, "MSX Internal floppy type 2", tag, owner, clock, "msx_slot_disk2", __FILE__)
, m_control(0)
{
}
void msx_slot_disk2_device::device_start()
{
msx_slot_disk_device::device_start();
save_item(NAME(m_control));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_slot_disk2_device::post_load), this));
}
void msx_slot_disk2_device::device_reset()
{
m_fdc->dden_w(false);
}
void msx_slot_disk2_device::post_load()
{
UINT8 data = m_control;
// To make sure the FDD busy led status gets set correctly
m_control ^= 0x40;
set_control(data);
}
void msx_slot_disk2_device::set_control(UINT8 data)
{
UINT8 old_m_control = m_control;
m_control = data;
switch (m_control & 3)
{
case 1:
m_floppy = m_floppy0 ? m_floppy0->get_device() : NULL;
break;
case 2:
m_floppy = m_floppy1 ? m_floppy1->get_device() : NULL;
break;
default:
m_floppy = NULL;
break;
}
if (m_floppy)
{
m_floppy->mon_w((m_control & 0x08) ? 0 : 1);
m_floppy->ss_w((m_control & 0x04) ? 0 : 1);
}
m_fdc->set_floppy(m_floppy);
if ((old_m_control ^ m_control) & 0x40)
{
set_led_status(machine(), 0, !(m_control & 0x40));
}
}
READ8_MEMBER(msx_slot_disk2_device::read)
{
switch (offset)
{
case 0x7fb8:
case 0xbfb8:
return m_fdc->status_r();
case 0x7fb9:
case 0xbfb9:
return m_fdc->track_r();
case 0x7fba:
case 0xbfba:
return m_fdc->sector_r();
case 0x7fbb:
case 0xbfbb:
return m_fdc->data_r();
case 0x7fbc:
case 0xbfbc:
return 0x3f | (m_fdc->drq_r() ? 0 : 0x40) | (m_fdc->intrq_r() ? 0x80 : 0);
}
return msx_slot_rom_device::read(space, offset);
}
WRITE8_MEMBER(msx_slot_disk2_device::write)
{
switch (offset)
{
case 0x7fb8:
case 0xbfb8:
m_fdc->cmd_w(data);
break;
case 0x7fb9:
case 0xbfb9:
m_fdc->track_w(data);
break;
case 0x7fba:
case 0xbfba:
m_fdc->sector_w(data);
break;
case 0x7fbb:
case 0xbfbb:
m_fdc->data_w(data);
break;
case 0x7fbc:
case 0xbfbc:
set_control(data);
break;
default:
printf("Unmapped write writing %02x to %04x\n", data, offset);
break;
}
}

View File

@ -0,0 +1,97 @@
#ifndef __MSX_SLOT_DISK_H
#define __MSX_SLOT_DISK_H
#include "bus/msx_slot/slot.h"
#include "bus/msx_slot/rom.h"
#include "machine/wd_fdc.h"
#include "imagedev/flopdrv.h"
#include "imagedev/floppy.h"
extern const device_type MSX_SLOT_DISK1;
extern const device_type MSX_SLOT_DISK2;
#define MCFG_MSX_SLOT_DISK1_ADD(_tag, _startpage, _numpages, _region, _offset, _fdc_tag, _floppy0_tag, _floppy1_tag) \
MCFG_MSX_INTERNAL_SLOT_ADD(_tag, MSX_SLOT_DISK1, _startpage, _numpages) \
msx_slot_rom_device::set_rom_start(*device, _region, _offset); \
msx_slot_disk_device::set_fdc_tag(*device, _fdc_tag); \
msx_slot_disk_device::set_floppy0_tag(*device, _floppy0_tag); \
msx_slot_disk_device::set_floppy1_tag(*device, _floppy1_tag);
#define MCFG_MSX_SLOT_DISK2_ADD(_tag, _startpage, _numpages, _region, _offset, _fdc_tag, _floppy0_tag, _floppy1_tag) \
MCFG_MSX_INTERNAL_SLOT_ADD(_tag, MSX_SLOT_DISK2, _startpage, _numpages) \
msx_slot_rom_device::set_rom_start(*device, _region, _offset); \
msx_slot_disk_device::set_fdc_tag(*device, _fdc_tag); \
msx_slot_disk_device::set_floppy0_tag(*device, _floppy0_tag); \
msx_slot_disk_device::set_floppy1_tag(*device, _floppy1_tag);
class msx_slot_disk_device : public msx_slot_rom_device
{
public:
msx_slot_disk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
virtual void device_start();
// static configuration helpers
static void set_fdc_tag(device_t &device, const char *tag) { dynamic_cast<msx_slot_disk_device &>(device).m_fdc_tag = tag; }
static void set_floppy0_tag(device_t &device, const char *tag) { dynamic_cast<msx_slot_disk_device &>(device).m_floppy0_tag = tag; }
static void set_floppy1_tag(device_t &device, const char *tag) { dynamic_cast<msx_slot_disk_device &>(device).m_floppy1_tag = tag; }
protected:
wd_fdc_analog_t *m_fdc;
floppy_connector *m_floppy0;
floppy_connector *m_floppy1;
floppy_image_device *m_floppy;
private:
const char *m_fdc_tag;
const char *m_floppy0_tag;
const char *m_floppy1_tag;
};
class msx_slot_disk1_device : public msx_slot_disk_device
{
public:
msx_slot_disk1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual void device_start();
virtual void device_reset();
virtual DECLARE_READ8_MEMBER(read);
virtual DECLARE_WRITE8_MEMBER(write);
void post_load();
private:
UINT8 m_side_control;
UINT8 m_control;
void set_control(UINT8 data);
void set_side_control(UINT8 data);
};
class msx_slot_disk2_device : public msx_slot_disk_device
{
public:
msx_slot_disk2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual void device_start();
virtual void device_reset();
virtual DECLARE_READ8_MEMBER(read);
virtual DECLARE_WRITE8_MEMBER(write);
void post_load();
private:
UINT8 m_control;
void set_control(UINT8 data);
};
#endif

View File

@ -0,0 +1,162 @@
/*
Emulation for the internal firmware mapper in the National FS-4600.
*/
#include "emu.h"
#include "fs4600.h"
const device_type MSX_SLOT_FS4600 = &device_creator<msx_slot_fs4600_device>;
msx_slot_fs4600_device::msx_slot_fs4600_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_SLOT_FS4600, "MSX Internal FS4600 Firmware", tag, owner, clock, "msx_slot_fs4600", __FILE__)
, msx_internal_slot_interface()
, m_nvram(*this, "nvram")
, m_region(NULL)
, m_region_offset(0)
, m_rom(NULL)
, m_sram_address(0)
, m_control(0)
{
for (int i = 0; i < 4; i++)
{
m_selected_bank[i] = 0;
m_bank_base[i] = 0;
}
memset(m_sram, 0, sizeof(m_sram));
}
static MACHINE_CONFIG_FRAGMENT( fs4600 )
MCFG_NVRAM_ADD_0FILL("nvram")
MACHINE_CONFIG_END
machine_config_constructor msx_slot_fs4600_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( fs4600 );
}
void msx_slot_fs4600_device::set_rom_start(device_t &device, const char *region, UINT32 offset)
{
msx_slot_fs4600_device &dev = downcast<msx_slot_fs4600_device &>(device);
dev.m_region = region;
dev.m_region_offset = offset;
}
void msx_slot_fs4600_device::device_start()
{
assert(m_region != NULL );
memory_region *m_rom_region = owner()->memregion(m_region);
// Sanity checks
if (m_rom_region == NULL )
{
fatalerror("Rom slot '%s': Unable to find memory region '%s'\n", tag(), m_region);
}
if (m_rom_region->bytes() < m_region_offset + 0x100000)
{
fatalerror("Memory region '%s' is too small for the FS4600 firmware\n", m_region);
}
m_rom = m_rom_region->base() + m_region_offset;
m_nvram->set_base(m_sram, 0x1000);
save_item(NAME(m_selected_bank));
save_item(NAME(m_sram_address));
save_item(NAME(m_control));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_slot_fs4600_device::restore_banks), this));
restore_banks();
}
void msx_slot_fs4600_device::restore_banks()
{
for (int i = 0; i < 4; i++)
{
m_bank_base[i] = m_rom + ( ( m_selected_bank[i] * 0x4000 ) & 0x0fffff );
}
}
READ8_MEMBER(msx_slot_fs4600_device::read)
{
if ((m_control & 0x02) && ((offset & 0x3fff) == 0x3ffd))
{
return m_sram[m_sram_address++ & 0xfff];
}
if ((m_control & 0x04) && (offset& 0x7ff8) == 0x7ff0)
{
return m_selected_bank[(offset >> 1) & 0x03];
}
return m_bank_base[offset >> 14][offset & 0x3fff];
}
WRITE8_MEMBER(msx_slot_fs4600_device::write)
{
if (offset == 0x7ff9)
{
m_control = data;
}
else
{
if (m_control & 0x02)
{
switch (offset & 0x3fff)
{
case 0x3ffa:
m_sram_address = (m_sram_address & 0x00ffff) | (data << 16);
break;
case 0x3ffb:
m_sram_address = (m_sram_address & 0xff00ff) | (data << 8);
break;
case 0x3ffc:
m_sram_address = (m_sram_address & 0xffff00) | data;
break;
case 0x3ffd:
m_sram[m_sram_address++ & 0xfff] = data;
break;
default:
logerror("Unhandled write %02x to %04x\n", data, offset);
break;
}
}
else
{
switch (offset)
{
case 0x6000:
m_selected_bank[1] = data;
m_bank_base[1] = m_rom + ( ( m_selected_bank[1] * 0x4000 ) & 0x0fffff );
break;
case 0x6400:
m_selected_bank[0] = data;
m_bank_base[0] = m_rom + ( ( m_selected_bank[0] * 0x4000 ) & 0x0fffff );
break;
case 0x7000:
m_selected_bank[2] = data;
m_bank_base[2] = m_rom + ( ( m_selected_bank[2] * 0x4000 ) & 0x0fffff );
break;
default:
logerror("Unhandled write %02x to %04x\n", data, offset);;
break;
}
}
}
}

View File

@ -0,0 +1,45 @@
#ifndef __MSX_SLOT_FS4600_H
#define __MSX_SLOT_FS4600_H
#include "slot.h"
#include "machine/nvram.h"
extern const device_type MSX_SLOT_FS4600;
#define MCFG_MSX_SLOT_FS4600_ADD(_tag, _startpage, _numpages, _region, _offset) \
MCFG_MSX_INTERNAL_SLOT_ADD(_tag, MSX_SLOT_FS4600, _startpage, _numpages) \
msx_slot_fs4600_device::set_rom_start(*device, _region, _offset);
class msx_slot_fs4600_device : public device_t,
public msx_internal_slot_interface
{
public:
msx_slot_fs4600_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration helpers
static void set_rom_start(device_t &device, const char *region, UINT32 offset);
virtual void device_start();
virtual machine_config_constructor device_mconfig_additions() const;
virtual DECLARE_READ8_MEMBER(read);
virtual DECLARE_WRITE8_MEMBER(write);
void restore_banks();
private:
required_device<nvram_device> m_nvram;
const char *m_region;
UINT32 m_region_offset;
const UINT8 *m_rom;
UINT8 m_selected_bank[4];
const UINT8 *m_bank_base[4];
UINT32 m_sram_address;
UINT8 m_sram[0x1000];
UINT8 m_control;
};
#endif

View File

@ -0,0 +1,69 @@
#include "emu.h"
#include "music.h"
const device_type MSX_SLOT_MUSIC = &device_creator<msx_slot_music_device>;
msx_slot_music_device::msx_slot_music_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: msx_slot_rom_device(mconfig, MSX_SLOT_MUSIC, "MSX Internal MSX-MUSIC", tag, owner, clock, "msx_slot_music", __FILE__)
, m_ym2413(NULL)
, m_ym2413_tag(NULL)
, m_opll_active(false)
, m_unlock(0)
{
}
void msx_slot_music_device::device_start()
{
msx_slot_rom_device::device_start();
if (m_ym2413_tag == NULL)
{
fatalerror("msx_slot_music_device: no YM2413 tag specified\n");
}
m_ym2413 = owner()->subdevice<ym2413_device>(m_ym2413_tag);
if (m_ym2413 == NULL)
{
fatalerror("msx_slot_ym2413_device: Unable to find YM2413 with tag '%s'\n", m_ym2413_tag);
}
// Install IO read/write handlers
address_space &space = machine().device<cpu_device>("maincpu")->space(AS_IO);
space.install_write_handler(0x7c, 0x7d, write8_delegate(FUNC(msx_slot_music_device::write_ym2413), this));
}
void msx_slot_music_device::device_reset()
{
m_opll_active = false;
}
READ8_MEMBER(msx_slot_music_device::read)
{
return msx_slot_rom_device::read(space, offset);
}
WRITE8_MEMBER(msx_slot_music_device::write)
{
if (m_unlock == 0xbe && data == 0x41)
{
m_opll_active = true;
}
m_unlock = data;
}
WRITE8_MEMBER(msx_slot_music_device::write_ym2413)
{
if (m_opll_active)
{
m_ym2413->write(space, offset & 1, data);
}
}

View File

@ -0,0 +1,43 @@
#ifndef __MSX_SLOT_MUSIC_H
#define __MSX_SLOT_MUSIC_H
#include "bus/msx_slot/slot.h"
#include "bus/msx_slot/rom.h"
#include "sound/2413intf.h"
extern const device_type MSX_SLOT_MUSIC;
#define MCFG_MSX_SLOT_MUSIC_ADD(_tag, _startpage, _numpages, _region, _offset, _ym2413_tag) \
MCFG_MSX_INTERNAL_SLOT_ADD(_tag, MSX_SLOT_MUSIC, _startpage, _numpages) \
msx_slot_rom_device::set_rom_start(*device, _region, _offset); \
msx_slot_music_device::set_ym2413_tag(*device, _ym2413_tag); \
class msx_slot_music_device : public msx_slot_rom_device
{
public:
msx_slot_music_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration helpers
static void set_ym2413_tag(device_t &device, const char *tag) { dynamic_cast<msx_slot_music_device &>(device).m_ym2413_tag = tag; }
virtual void device_start();
virtual void device_reset();
virtual DECLARE_READ8_MEMBER(read);
virtual DECLARE_WRITE8_MEMBER(write);
DECLARE_WRITE8_MEMBER(write_ym2413);
private:
ym2413_device *m_ym2413;
const char *m_ym2413_tag;
bool m_opll_active;
UINT8 m_unlock;
};
#endif

View File

@ -0,0 +1,176 @@
/*
Emulation of the firmware mapper as found in Panasonic FS-A1WX andFS-A1WSX machines.
Todo:
- Anything besides the basic mapping
- SRAM?
*/
#include "emu.h"
#include "panasonic08.h"
const device_type MSX_SLOT_PANASONIC08 = &device_creator<msx_slot_panasonic08_device>;
msx_slot_panasonic08_device::msx_slot_panasonic08_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_SLOT_PANASONIC08, "MSX Internal Panasonic08", tag, owner, clock, "msx_slot_panasonic08", __FILE__)
, msx_internal_slot_interface()
, m_region(NULL)
, m_region_offset(0)
, m_rom(NULL)
, m_control(0)
{
for (int i = 0; i < 8; i++)
{
m_selected_bank[i] = 0;
m_bank_base[i] = 0;
}
memset(m_sram, 0, sizeof(m_sram));
}
static MACHINE_CONFIG_FRAGMENT( panasonic08 )
MACHINE_CONFIG_END
machine_config_constructor msx_slot_panasonic08_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( panasonic08 );
}
void msx_slot_panasonic08_device::set_rom_start(device_t &device, const char *region, UINT32 offset)
{
msx_slot_panasonic08_device &dev = downcast<msx_slot_panasonic08_device &>(device);
dev.m_region = region;
dev.m_region_offset = offset;
}
void msx_slot_panasonic08_device::device_start()
{
assert(m_region != NULL );
memory_region *m_rom_region = owner()->memregion(m_region);
// Sanity checks
if (m_rom_region == NULL )
{
fatalerror("Rom slot '%s': Unable to find memory region '%s'\n", tag(), m_region);
}
if (m_rom_region->bytes() < m_region_offset + 0x200000)
{
fatalerror("Memory region '%s' is too small for the FS4600 firmware\n", m_region);
}
m_rom = m_rom_region->base() + m_region_offset;
save_item(NAME(m_selected_bank));
save_item(NAME(m_control));
save_item(NAME(m_sram));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_slot_panasonic08_device::restore_banks), this));
restore_banks();
}
void msx_slot_panasonic08_device::map_bank(int bank)
{
if (m_selected_bank[bank] >= 0x80 && m_selected_bank[bank] < 0x84) // Are these banks were sram is present? Mirroring?
{
logerror("panasonic08: mapping bank %d to sram\n", bank);
m_bank_base[bank] = m_sram;
}
else
{
m_bank_base[bank] = m_rom + ( ( m_selected_bank[bank] * 0x2000 ) & 0x1fffff );
}
}
void msx_slot_panasonic08_device::restore_banks()
{
for (int i = 0; i < 8; i++)
{
map_bank(i);
}
}
READ8_MEMBER(msx_slot_panasonic08_device::read)
{
if (m_control & 0x04)
{
// 7ff0 - 6000
// 7ff1 - 6400
// 7ff2 - 6800
// 7ff3 - 6c00
// 7ff4 - 7000
// 7ff5 - 7800
if (offset >= 0x7ff0 && offset < 0x7ff6) // maybe 7ff8 would make more sense here??
{
return m_selected_bank[offset - 0x7ff0];
}
}
return m_bank_base[offset >> 13][offset & 0x1fff];
}
WRITE8_MEMBER(msx_slot_panasonic08_device::write)
{
if ((offset & 0xc000) == 0x8000)
{
UINT8 bank = m_selected_bank[offset >> 13];
if (bank >= 0x80 && bank < 0x84) // Are these banks were sram is present? Mirroring?
{
logerror("panasonic08: writing %02x to sram %04x\n", data, offset & 0x1fff);
m_sram[offset & 0x1fff] = data;
}
}
switch (offset)
{
case 0x6000: /* Switched 0x0000-0x1FFF */
m_selected_bank[0] = data;
map_bank(0);
break;
case 0x6400: /* Switches 0x2000-0x3FFF */
m_selected_bank[1] = data;
map_bank(1);
break;
case 0x6800: /* Switches 0x4000-0x5FFF */
m_selected_bank[2] = data;
map_bank(2);
break;
case 0x6c00:
m_selected_bank[3] = data;
map_bank(3);
break;
case 0x7000: /* Switches 0x8000-0x9FFF */
m_selected_bank[4] = data;
map_bank(4);
break;
case 0x7800:
m_selected_bank[5] = data;
map_bank(5);
break;
case 0x7ff9:
m_control = data;
break;
default:
logerror("Unhandled write %02x to %04x\n", data, offset);
break;
}
}

View File

@ -0,0 +1,44 @@
#ifndef __MSX_SLOT_PANASONIC08_H
#define __MSX_SLOT_PANASONIC08_H
#include "slot.h"
extern const device_type MSX_SLOT_PANASONIC08;
#define MCFG_MSX_SLOT_PANASONIC08_ADD(_tag, _startpage, _numpages, _region, _offset) \
MCFG_MSX_INTERNAL_SLOT_ADD(_tag, MSX_SLOT_PANASONIC08, _startpage, _numpages) \
msx_slot_panasonic08_device::set_rom_start(*device, _region, _offset);
class msx_slot_panasonic08_device : public device_t,
public msx_internal_slot_interface
{
public:
msx_slot_panasonic08_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration helpers
static void set_rom_start(device_t &device, const char *region, UINT32 offset);
virtual void device_start();
virtual machine_config_constructor device_mconfig_additions() const;
virtual DECLARE_READ8_MEMBER(read);
virtual DECLARE_WRITE8_MEMBER(write);
void restore_banks();
private:
const char *m_region;
UINT32 m_region_offset;
const UINT8 *m_rom;
UINT8 m_selected_bank[8];
const UINT8 *m_bank_base[8];
UINT8 m_control;
UINT8 m_sram[0x2000];
void map_bank(int bank);
};
#endif

View File

@ -0,0 +1,36 @@
#include "emu.h"
#include "ram.h"
const device_type MSX_SLOT_RAM = &device_creator<msx_slot_ram_device>;
msx_slot_ram_device::msx_slot_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_SLOT_RAM, "MSX Internal RAM", tag, owner, clock, "msx_slot_ram", __FILE__)
, msx_internal_slot_interface()
{
}
void msx_slot_ram_device::device_start()
{
m_ram.resize(m_size);
save_item(NAME(m_ram));
}
READ8_MEMBER(msx_slot_ram_device::read)
{
if ( offset >= m_start_address && offset < m_end_address )
{
return m_ram[ offset - m_start_address ];
}
return 0xFF;
}
WRITE8_MEMBER(msx_slot_ram_device::write)
{
if ( offset >= m_start_address && offset < m_end_address )
{
m_ram[offset - m_start_address] = data;
}
}

View File

@ -0,0 +1,26 @@
#ifndef __MSX_SLOT_RAM_H
#define __MSX_SLOT_RAM_H
#include "slot.h"
#define MCFG_MSX_SLOT_RAM_ADD(_tag, _startpage, _numpages) \
MCFG_MSX_INTERNAL_SLOT_ADD(_tag, MSX_SLOT_RAM, _startpage, _numpages) \
class msx_slot_ram_device : public device_t,
public msx_internal_slot_interface
{
public:
msx_slot_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
virtual void device_start();
virtual DECLARE_READ8_MEMBER(read);
virtual DECLARE_WRITE8_MEMBER(write);
private:
dynamic_array<UINT8> m_ram;
};
extern const device_type MSX_SLOT_RAM;
#endif

View File

@ -0,0 +1,79 @@
#include "emu.h"
#include "ram_mm.h"
const device_type MSX_SLOT_RAM_MM = &device_creator<msx_slot_ram_mm_device>;
msx_slot_ram_mm_device::msx_slot_ram_mm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_SLOT_RAM_MM, "MSX Internal Memory Mapped RAM", tag, owner, clock, "msx_slot_ram_mm", __FILE__)
, msx_internal_slot_interface()
, m_total_size(0)
, m_bank_mask(0)
, m_ramio_set_bits(0)
{
}
void msx_slot_ram_mm_device::device_start()
{
// Valid mapper sizes are 64KB, 128KB, 256KB, 512KB, 1MB, 2MB, and 4MB */
switch (m_total_size)
{
case 64*1024: m_bank_mask = 0x03; break;
case 128*1024: m_bank_mask = 0x07; break;
case 256*1024: m_bank_mask = 0x0F; break;
case 512*1024: m_bank_mask = 0x1F; break;
case 1024*1024: m_bank_mask = 0x3F; break;
case 2048*1024: m_bank_mask = 0x7F; break;
case 4096*1024: m_bank_mask = 0xFF; break;
default: fatalerror("Invalid memory mapper size specified\n");
}
m_ram.resize(m_total_size);
for ( int i = 0; i < 4; i++ )
{
m_bank_selected[i] = 3 -i;
m_bank_base[i] = m_ram + 0x4000 * m_bank_selected[i];
}
save_item(NAME(m_ram));
save_item(NAME(m_bank_selected));
machine().save().register_postload(save_prepost_delegate(FUNC(msx_slot_ram_mm_device::restore_banks), this));
// Install IO read/write handlers
address_space &space = machine().device<cpu_device>("maincpu")->space(AS_IO);
space.install_read_handler(0xFC, 0xFF, read8_delegate(FUNC(msx_slot_ram_mm_device::read_mapper_bank), this));
space.install_write_handler(0xFC, 0xFF, write8_delegate(FUNC(msx_slot_ram_mm_device::write_mapper_bank), this));
}
void msx_slot_ram_mm_device::restore_banks()
{
for ( int i = 0; i < 3; i++ )
{
m_bank_base[i] = m_ram + 0x4000 * ( m_bank_selected[i] & m_bank_mask );
}
}
READ8_MEMBER(msx_slot_ram_mm_device::read)
{
return m_bank_base[offset >> 14][offset & 0x3fff];
}
WRITE8_MEMBER(msx_slot_ram_mm_device::write)
{
m_bank_base[offset >> 14][offset & 0x3fff] = data;
}
READ8_MEMBER(msx_slot_ram_mm_device::read_mapper_bank)
{
return m_bank_selected[offset & 3] | m_ramio_set_bits;
}
WRITE8_MEMBER(msx_slot_ram_mm_device::write_mapper_bank)
{
offset &= 3;
m_bank_selected[offset] = data;
m_bank_base[offset] = m_ram + 0x4000 * ( m_bank_selected[offset] & m_bank_mask );
}

View File

@ -0,0 +1,44 @@
#ifndef __MSX_SLOT_RAM_MM_H
#define __MSX_SLOT_RAM_MM_H
#include "slot.h"
#define MCFG_MSX_SLOT_RAM_MM_ADD(_tag, _total_size) \
MCFG_MSX_INTERNAL_SLOT_ADD(_tag, MSX_SLOT_RAM_MM, 0, 4) \
msx_slot_ram_mm_device::set_total_size(*device, _total_size);
#define MCFG_MSX_SLOT_RAMM_SET_RAMIO_BITS(_ramio_set_bits) \
msx_slot_ram_mm_device::set_ramio_set_bits(*device, _ramio_set_bits);
class msx_slot_ram_mm_device : public device_t
, public msx_internal_slot_interface
{
public:
msx_slot_ram_mm_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
static void set_total_size(device_t &device, UINT32 total_size) { dynamic_cast<msx_slot_ram_mm_device &>(device).m_total_size = total_size; }
static void set_ramio_set_bits(device_t &device, UINT8 ramio_set_bits) { dynamic_cast<msx_slot_ram_mm_device &>(device).m_ramio_set_bits = ramio_set_bits; }
virtual void device_start();
virtual DECLARE_READ8_MEMBER(read);
virtual DECLARE_WRITE8_MEMBER(write);
DECLARE_READ8_MEMBER(read_mapper_bank);
DECLARE_WRITE8_MEMBER(write_mapper_bank);
void restore_banks();
private:
dynamic_array<UINT8> m_ram;
UINT32 m_total_size;
UINT8 m_bank_mask;
UINT8 m_bank_selected[4];
UINT8 *m_bank_base[4];
UINT8 m_ramio_set_bits;
};
extern const device_type MSX_SLOT_RAM_MM;
#endif

View File

@ -0,0 +1,66 @@
#include "emu.h"
#include "rom.h"
const device_type MSX_SLOT_ROM = &device_creator<msx_slot_rom_device>;
msx_slot_rom_device::msx_slot_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, MSX_SLOT_ROM, "MSX Internal ROM", tag, owner, clock, "msx_slot_rom", __FILE__)
, msx_internal_slot_interface()
, m_region(NULL)
, m_region_offset(0)
, m_rom(NULL)
{
}
msx_slot_rom_device::msx_slot_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
, msx_internal_slot_interface()
, m_region(NULL)
, m_region_offset(0)
, m_rom(NULL)
{
}
void msx_slot_rom_device::set_rom_start(device_t &device, const char *region, UINT32 offset)
{
msx_slot_rom_device &dev = downcast<msx_slot_rom_device &>(device);
dev.m_region = region;
dev.m_region_offset = offset;
}
void msx_slot_rom_device::device_start()
{
assert(m_region != NULL );
memory_region *m_rom_region = owner()->memregion(m_region);
// Sanity checks
if (m_rom_region == NULL )
{
fatalerror("Rom slot '%s': Unable to find memory region '%s'\n", tag(), m_region);
}
if (m_rom_region->bytes() < m_region_offset + m_size)
{
fatalerror("Memory region '%s' is too small for rom slot '%s'\n", m_region, tag());
}
m_rom = m_rom_region->base() + m_region_offset;
}
READ8_MEMBER(msx_slot_rom_device::read)
{
if ( offset >= m_start_address && offset < m_end_address )
{
return m_rom[ offset - m_start_address ];
}
return 0xFF;
}

View File

@ -0,0 +1,32 @@
#ifndef __MSX_SLOT_ROM_H
#define __MSX_SLOT_ROM_H
#include "slot.h"
#define MCFG_MSX_SLOT_ROM_ADD(_tag, _startpage, _numpages, _region, _offset) \
MCFG_MSX_INTERNAL_SLOT_ADD(_tag, MSX_SLOT_ROM, _startpage, _numpages) \
msx_slot_rom_device::set_rom_start(*device, _region, _offset);
class msx_slot_rom_device : public device_t,
public msx_internal_slot_interface
{
public:
msx_slot_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
msx_slot_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration helpers
static void set_rom_start(device_t &device, const char *region, UINT32 offset);
virtual void device_start();
virtual DECLARE_READ8_MEMBER(read);
private:
const char *m_region;
UINT32 m_region_offset;
const UINT8 *m_rom;
};
extern const device_type MSX_SLOT_ROM;
#endif

View File

@ -0,0 +1,35 @@
/***********************************************************************************************************
MSX (logical) internal slot interfacing
The MSX standard uses logically defined slots, subslots, and pages to access rom and optional components
in a system. There are no physical slots inside the system. A piece of rom/component can occur in multiple
pages; and multiple pieces of rom/ram/components can occur in a single slot.
***********************************************************************************************************/
#include "emu.h"
#include "slot.h"
msx_internal_slot_interface::msx_internal_slot_interface()
: m_start_address(0)
, m_size(0)
, m_end_address(0)
{
}
void msx_internal_slot_interface::set_start_address(device_t &device, UINT32 start_address)
{
msx_internal_slot_interface &dev = dynamic_cast<msx_internal_slot_interface &>(device);
dev.m_start_address = start_address;
dev.m_end_address = dev.m_start_address + dev.m_size;
}
void msx_internal_slot_interface::set_size(device_t &device, UINT32 size)
{
msx_internal_slot_interface &dev = dynamic_cast<msx_internal_slot_interface &>(device);
dev.m_size = size;
dev.m_end_address = dev.m_start_address + dev.m_size;
}

View File

@ -0,0 +1,37 @@
/***********************************************************************************************************
MSX (logical) internal slot/page interfacing
The MSX standard uses logically defined slots, subslots, and pages to access rom and optional components
in a system. There are no physical slots inside the system. A piece of rom/component can occur in multiple
pages; and multiple pieces of rom/ram/components can occur in a single slot.
***********************************************************************************************************/
#ifndef __MSX_SLOT_SLOT_H
#define __MSX_SLOT_SLOT_H
#define MCFG_MSX_INTERNAL_SLOT_ADD(_tag, _type, _startpage, _numpages) \
MCFG_DEVICE_ADD(_tag, _type, 0) \
msx_internal_slot_interface::set_start_address(*device, _startpage * 0x4000); \
msx_internal_slot_interface::set_size(*device, _numpages * 0x4000);
class msx_internal_slot_interface
{
public:
msx_internal_slot_interface();
// static configuration helpers
static void set_start_address(device_t &device, UINT32 start_address);
static void set_size(device_t &device, UINT32 size);
virtual DECLARE_READ8_MEMBER(read) { return 0xFF; }
virtual DECLARE_WRITE8_MEMBER(write) { }
protected:
UINT32 m_start_address;
UINT32 m_size;
UINT32 m_end_address;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,6 @@
#include "sound/ay8910.h"
#include "sound/dac.h"
#include "sound/wave.h"
#include "sound/k051649.h"
#include "sound/2413intf.h"
#include "video/v9938.h"
#include "video/tms9928a.h"
@ -28,124 +27,155 @@
#include "formats/msx_dsk.h"
//#include "osdepend.h"
#include "hashfile.h"
#include "includes/msx_slot.h"
#include "machine/wd_fdc.h"
#include "imagedev/floppy.h"
#include "bus/msx_slot/slot.h"
#include "bus/msx_slot/rom.h"
#include "bus/msx_slot/ram.h"
#include "bus/msx_slot/cartridge.h"
#include "bus/msx_slot/ram_mm.h"
#include "bus/msx_slot/disk.h"
#include "bus/msx_slot/music.h"
#include "bus/msx_slot/bunsetsu.h"
#include "bus/msx_slot/fs4600.h"
#include "bus/msx_slot/panasonic08.h"
#define MSX_MAX_CARTS (2)
#define TC8521_TAG "rtc"
#define MCFG_MSX_LAYOUT(_layout) \
msx_state::set_layout(*owner, msx_slot_layout_##_layout);
#define MCFG_MSX_LAYOUT_ROM(_tag, _prim, _sec, _page, _numpages, _region, _offset) \
MCFG_MSX_SLOT_ROM_ADD(_tag, _page, _numpages, _region, _offset) \
msx_state::install_slot_pages(*owner, _prim, _sec, _page, _numpages, device);
#define MCFG_MSX_LAYOUT_RAM(_tag, _prim, _sec, _page, _numpages) \
MCFG_MSX_SLOT_RAM_ADD(_tag, _page, _numpages) \
msx_state::install_slot_pages(*owner, _prim, _sec, _page, _numpages, device);
#define MCFG_MSX_LAYOUT_CARTRIDGE(_tag, _prim, _sec) \
MCFG_MSX_SLOT_CARTRIDGE_ADD(_tag) \
msx_state::install_slot_pages(*owner, _prim, _sec, 0, 4, device);
#define MCFG_MSX_LAYOUT_RAM_MM(_tag, _prim, _sec, _total_size) \
MCFG_MSX_SLOT_RAM_MM_ADD(_tag, _total_size) \
msx_state::install_slot_pages(*owner, _prim, _sec, 0, 4, device);
#define MCFG_MSX_RAMIO_SET_BITS(_ramio_set_bits) \
msx_state::set_ramio_set_bits(*owner, _ramio_set_bits);
MCFG_MSX_SLOT_RAMM_SET_RAMIO_BITS(_ramio_set_bits)
#define MCFG_MSX_LAYOUT_DISK1(_tag, _prim, _sec, _page, _numpages, _region, _offset) \
MCFG_MSX_SLOT_DISK1_ADD(_tag, _page, _numpages, _region, _offset, "fdc", "fdc:0", "fdc:1") \
msx_state::install_slot_pages(*owner, _prim, _sec, _page, _numpages, device);
#define MCFG_MSX_LAYOUT_DISK2(_tag, _prim, _sec, _page, _numpages, _region, _offset) \
MCFG_MSX_SLOT_DISK2_ADD(_tag, _page, _numpages, _region, _offset, "fdc", "fdc:0", "fdc:1") \
msx_state::install_slot_pages(*owner, _prim, _sec, _page, _numpages, device);
#define MCFG_MSX_LAYOUT_MUSIC(_tag, _prim, _sec, _page, _numpages, _region, _offset) \
MCFG_MSX_SLOT_MUSIC_ADD(_tag, _page, _numpages, _region, _offset, "ym2413" ) \
msx_state::install_slot_pages(*owner, _prim, _sec, _page, _numpages, device);
#define MCFG_MSX_LAYOUT_BUNSETSU(_tag, _prim, _sec, _page, _numpages, _region, _offset, _bunsetsu_tag) \
MCFG_MSX_SLOT_BUNSETSU_ADD(_tag, _page, _numpages, _region, _offset, _bunsetsu_tag) \
msx_state::install_slot_pages(*owner, _prim, _sec, _page, _numpages, device);
#define MCFG_MSX_LAYOUT_FS4600(_tag, _prim, _sec, _page, _numpages, _region, _offset) \
MCFG_MSX_SLOT_FS4600_ADD(_tag, _page, _numpages, _region, _offset) \
msx_state::install_slot_pages(*owner, _prim, _sec, _page, _numpages, device);
#define MCFG_MSX_LAYOUT_PANASONIC08(_tag, _prim, _sec, _page, _numpages, _region, _offset) \
MCFG_MSX_SLOT_PANASONIC08_ADD(_tag, _page, _numpages, _region, _offset) \
msx_state::install_slot_pages(*owner, _prim, _sec, _page, _numpages, device);
class msx_state : public driver_device
{
public:
msx_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_layout(NULL),
m_maincpu(*this, "maincpu"),
m_v9938(*this, "v9938"),
m_v9958(*this, "v9958"),
m_cassette(*this, "cassette"),
m_ay8910(*this, "ay8910"),
m_ym(*this, "ym2413"),
m_k051649(*this, "k051649"),
m_dac(*this, "dac"),
m_rtc(*this, TC8521_TAG),
m_fdc(*this, "fdc"),
m_floppy0(*this, "fdc:0"),
m_floppy1(*this, "fdc:1"),
m_floppy(NULL),
m_bank1(*this, "bank1"),
m_bank2(*this, "bank2"),
m_bank3(*this, "bank3"),
m_bank4(*this, "bank4"),
m_bank5(*this, "bank5"),
m_bank6(*this, "bank6"),
m_bank7(*this, "bank7"),
m_bank8(*this, "bank8"),
m_bank9(*this, "bank9"),
m_bank10(*this, "bank10"),
m_bank11(*this, "bank11"),
m_region_maincpu(*this, "maincpu"),
m_region_kanji(*this, "kanji"),
m_io_joy0(*this, "JOY0"),
m_io_joy1(*this, "JOY1"),
m_io_dsw(*this, "DSW"),
m_io_mouse0(*this, "MOUSE0"),
m_io_mouse1(*this, "MOUSE1"),
m_io_key0(*this, "KEY0"),
m_io_key1(*this, "KEY1"),
m_io_key2(*this, "KEY2"),
m_io_key3(*this, "KEY3"),
m_io_key4(*this, "KEY4"),
m_io_key5(*this, "KEY5") { }
: driver_device(mconfig, type, tag)
, m_psg_b(0)
, m_rtc_latch(0)
, m_kanji_latch(0)
, m_primary_slot(0)
, m_port_c_old(0)
, m_keylatch(0)
, m_current_switched_device(0)
, m_maincpu(*this, "maincpu")
, m_v9938(*this, "v9938")
, m_v9958(*this, "v9958")
, m_cassette(*this, "cassette")
, m_ay8910(*this, "ay8910")
, m_dac(*this, "dac")
, m_rtc(*this, TC8521_TAG)
, m_switched_device_as_config("switched_device", ENDIANNESS_LITTLE, 8, 16, 0, address_map_delegate(FUNC(msx_state::switched_device_map), this))
, m_region_maincpu(*this, "maincpu")
, m_region_kanji(*this, "kanji")
, m_io_joy0(*this, "JOY0")
, m_io_joy1(*this, "JOY1")
, m_io_dsw(*this, "DSW")
, m_io_mouse0(*this, "MOUSE0")
, m_io_mouse1(*this, "MOUSE1")
, m_io_key0(*this, "KEY0")
, m_io_key1(*this, "KEY1")
, m_io_key2(*this, "KEY2")
, m_io_key3(*this, "KEY3")
, m_io_key4(*this, "KEY4")
, m_io_key5(*this, "KEY5")
{
for (int prim = 0; prim < 4; prim++ )
{
m_slot_expanded[prim] = false;
m_secondary_slot[prim] = 0;
for (int sec = 0; sec < 4; sec++ )
{
for (int page = 0; page < 4; page++ )
{
m_all_slots[prim][sec][page] = NULL;
}
}
}
m_mouse[0] = m_mouse[1] = 0;
m_mouse_stat[0] = m_mouse_stat[1] = 0;
}
// static configuration helpers
static void set_layout(device_t &device, const msx_slot_layout *layout) { downcast<msx_state &>(device).m_layout = layout; }
static void set_ramio_set_bits(device_t &device, UINT8 ramio_set_bits) { downcast<msx_state &>(device).m_ramio_set_bits = ramio_set_bits; }
static void install_slot_pages(device_t &owner, UINT8 prim, UINT8 sec, UINT8 page, UINT8 numpages, device_t *device);
DECLARE_WRITE8_MEMBER(msx_page0_w);
DECLARE_WRITE8_MEMBER(msx_page0_1_w);
DECLARE_WRITE8_MEMBER(msx_page1_w);
DECLARE_WRITE8_MEMBER(msx_page1_1_w);
DECLARE_WRITE8_MEMBER(msx_page1_2_w);
DECLARE_WRITE8_MEMBER(msx_page2_w);
DECLARE_WRITE8_MEMBER(msx_page2_1_w);
DECLARE_WRITE8_MEMBER(msx_page2_2_w);
DECLARE_WRITE8_MEMBER(msx_page2_3_w);
DECLARE_WRITE8_MEMBER(msx_page3_w);
DECLARE_WRITE8_MEMBER(msx_page3_1_w);
DECLARE_ADDRESS_MAP(switched_device_map, 8);
DECLARE_WRITE8_MEMBER(msx_sec_slot_w);
DECLARE_READ8_MEMBER(msx_sec_slot_r);
DECLARE_WRITE8_MEMBER(msx_ram_mapper_w);
DECLARE_READ8_MEMBER(msx_ram_mapper_r);
DECLARE_READ8_MEMBER(msx_kanji_r);
DECLARE_WRITE8_MEMBER(msx_kanji_w);
DECLARE_WRITE8_MEMBER(msx_90in1_w);
DECLARE_WRITE8_MEMBER(msx_ppi_port_a_w);
DECLARE_WRITE8_MEMBER(msx_ppi_port_c_w);
DECLARE_READ8_MEMBER(msx_ppi_port_b_r);
DECLARE_WRITE8_MEMBER(msx_fmpac_w);
DECLARE_READ8_MEMBER(msx_rtc_reg_r);
DECLARE_WRITE8_MEMBER(msx_rtc_reg_w);
DECLARE_WRITE8_MEMBER(msx_rtc_latch_w);
DECLARE_WRITE_LINE_MEMBER(msx_wd179x_intrq_w);
DECLARE_WRITE_LINE_MEMBER(msx_wd179x_drq_w);
DECLARE_READ8_MEMBER(msx_mem_read);
DECLARE_WRITE8_MEMBER(msx_mem_write);
DECLARE_READ8_MEMBER(msx_switched_r);
DECLARE_WRITE8_MEMBER(msx_switched_w);
DECLARE_WRITE_LINE_MEMBER(turbo_w);
/* PSG */
int m_psg_b;
int m_opll_active;
/* mouse */
UINT16 m_mouse[2];
int m_mouse_stat[2];
/* rtc */
int m_rtc_latch;
/* disk */
UINT8 m_dsk_stat;
/* kanji */
int m_kanji_latch;
/* memory */
const msx_slot_layout *m_layout;
slot_state *m_cart_state[MSX_MAX_CARTS];
slot_state *m_state[4];
const msx_slot *m_slot[4];
UINT8 *m_ram_pages[4];
UINT8 *m_empty, m_ram_mapper[4];
UINT8 m_ramio_set_bits;
slot_state *m_all_state[4][4][4];
int m_slot_expanded[4];
msx_internal_slot_interface m_empty_slot;
msx_internal_slot_interface *m_all_slots[4][4][4];
msx_internal_slot_interface *m_current_page[4];
bool m_slot_expanded[4];
UINT8 m_primary_slot;
UINT8 m_secondary_slot[4];
UINT8 m_superloderunner_bank;
UINT8 m_korean90in1_bank;
UINT8 *m_top_page;
int m_port_c_old;
int keylatch;
int m_keylatch;
UINT8 m_current_switched_device;
void msx_memory_map_all ();
void msx_memory_map_page (UINT8 page);
void msx_ch_reset_core ();
@ -156,14 +186,8 @@ public:
optional_device<v9958_device> m_v9958;
required_device<cassette_image_device> m_cassette;
required_device<ay8910_device> m_ay8910;
required_device<ym2413_device> m_ym;
optional_device<k051649_device> m_k051649;
required_device<dac_device> m_dac;
optional_device<rp5c01_device> m_rtc;
optional_device<wd_fdc_analog_t> m_fdc;
optional_device<floppy_connector> m_floppy0;
optional_device<floppy_connector> m_floppy1;
floppy_image_device *m_floppy;
DECLARE_FLOPPY_FORMATS(floppy_formats);
DECLARE_READ8_MEMBER(msx_psg_port_a_r);
@ -180,34 +204,13 @@ public:
TIMER_DEVICE_CALLBACK_MEMBER(msx2p_interrupt);
DECLARE_WRITE8_MEMBER(msx_ay8910_w);
void msx_memory_init();
void msx_memory_set_carts();
DECLARE_DEVICE_IMAGE_LOAD_MEMBER( msx_cart );
DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER( msx_cart );
DECLARE_WRITE_LINE_MEMBER(msx_vdp_interrupt);
// from msx_slot
DECLARE_READ8_MEMBER(konami_scc_bank5);
DECLARE_READ8_MEMBER(msx_diskrom_page1_r);
DECLARE_READ8_MEMBER(msx_diskrom_page2_r);
DECLARE_READ8_MEMBER(msx_diskrom2_page1_r);
DECLARE_READ8_MEMBER(msx_diskrom2_page2_r);
DECLARE_READ8_MEMBER(soundcartridge_scc);
DECLARE_READ8_MEMBER(soundcartridge_sccp);
required_memory_bank m_bank1;
required_memory_bank m_bank2;
required_memory_bank m_bank3;
required_memory_bank m_bank4;
required_memory_bank m_bank5;
required_memory_bank m_bank6;
required_memory_bank m_bank7;
required_memory_bank m_bank8;
required_memory_bank m_bank9;
required_memory_bank m_bank10;
required_memory_bank m_bank11;
protected:
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == 0) ? &m_switched_device_as_config : NULL; }
address_space_config m_switched_device_as_config;
required_memory_region m_region_maincpu;
optional_memory_region m_region_kanji;
required_ioport m_io_joy0;

View File

@ -1,215 +0,0 @@
/*****************************************************************************
*
* includes/msx_slot.h
*
****************************************************************************/
#ifndef MSX_SLOT_H_
#define MSX_SLOT_H_
enum {
MSX_LAYOUT_SLOT_ENTRY,
MSX_LAYOUT_LAST
};
struct msx_slot_layout {
int entry;
int type;
int slot_primary, slot_secondary, slot_page, page_extent;
int size, option;
};
#define MSX_LAYOUT_INIT(msx) \
static const msx_slot_layout msx_slot_layout_##msx[] = {
#define MSX_LAYOUT_SLOT(prim, sec, page, extend, type, size, option) \
{ \
MSX_LAYOUT_SLOT_ENTRY, \
SLOT_##type, \
prim, \
sec, \
page, \
extend, \
size, \
option \
},
#define MSX_LAYOUT_END \
{ \
MSX_LAYOUT_LAST, \
SLOT_END, \
0, \
0, \
0, \
0, \
0, \
0 \
} \
};
enum msx_slot_type {
SLOT_EMPTY = 0,
SLOT_MSXDOS2,
SLOT_KONAMI_SCC,
SLOT_KONAMI,
SLOT_ASCII8,
SLOT_ASCII16,
SLOT_GAMEMASTER2,
SLOT_ASCII8_SRAM,
SLOT_ASCII16_SRAM,
SLOT_RTYPE,
SLOT_MAJUTSUSHI,
SLOT_FMPAC,
SLOT_SUPERLODERUNNER,
SLOT_SYNTHESIZER,
SLOT_CROSS_BLAIM,
SLOT_DISK_ROM,
SLOT_KOREAN_80IN1,
SLOT_KOREAN_126IN1,
SLOT_KOREAN_90IN1,
SLOT_LAST_CARTRIDGE_TYPE = SLOT_KOREAN_90IN1,
SLOT_SOUNDCARTRIDGE,
SLOT_ROM,
SLOT_RAM,
SLOT_RAM_MM,
SLOT_CARTRIDGE1,
SLOT_CARTRIDGE2,
SLOT_DISK_ROM2,
SLOT_END
};
enum msx_mem_type {
MSX_MEM_ROM,
MSX_MEM_RAM,
MSX_MEM_HANDLER
};
struct slot_state {
int m_type;
int m_start_page;
int m_bank_mask;
int m_banks[4];
int m_size;
UINT8 *m_mem;
const char *m_sramfile;
union {
struct {
UINT8 *mem;
int sram_support;
int sram_active;
int opll_active;
} fmpac;
struct {
int active;
} scc;
struct {
UINT8 *mem;
int sram_mask;
int empty_mask;
} sram;
struct {
int scc_active;
int sccp_active;
int ram_mode[4];
int banks_saved[4];
int mode;
} sccp;
} m_cart;
};
struct msx_slot {
int slot_type;
int mem_type;
char name[32];
int (*init)(running_machine &machine, slot_state*, int page, UINT8 *mem, int size);
void (*reset)(running_machine &machine, slot_state*);
void (*map)(running_machine &machine, slot_state*, int page);
void (*write)(running_machine &machine, slot_state*, UINT16, UINT8);
int (*loadsram)(running_machine &machine, slot_state*);
int (*savesram)(running_machine &machine, slot_state*);
};
extern const msx_slot msx_slot_list[];
#define MSX_SLOT_START \
const msx_slot msx_slot_list[] = {
#define MSX_SLOT_ROM(type, ent) { \
type, \
MSX_MEM_ROM, \
#type, \
slot_##ent##_init, \
slot_##ent##_reset, \
slot_##ent##_map, \
NULL, \
NULL, \
NULL \
},
#define MSX_SLOT_RAM(type, ent) { \
type, \
MSX_MEM_RAM, \
#type, \
slot_##ent##_init, \
slot_##ent##_reset, \
slot_##ent##_map, \
NULL, \
NULL, \
NULL \
},
#define MSX_SLOT(type, ent) { \
type, \
MSX_MEM_HANDLER, \
#type, \
slot_##ent##_init, \
slot_##ent##_reset, \
slot_##ent##_map, \
slot_##ent##_write, \
NULL, \
NULL \
},
#define MSX_SLOT_SRAM(type, ent) { \
type, \
MSX_MEM_HANDLER, \
#type, \
slot_##ent##_init, \
slot_##ent##_reset, \
slot_##ent##_map, \
slot_##ent##_write, \
slot_##ent##_loadsram, \
slot_##ent##_savesram \
},
#define MSX_SLOT_NULL(type) { \
type, \
MSX_MEM_ROM, \
#type, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL \
},
#define MSX_SLOT_END \
{ SLOT_END, 0, "", NULL, NULL, NULL, NULL, NULL } \
};
#define MSX_SLOT_INIT(nm) static int \
slot_##nm##_init (running_machine &machine, slot_state *state, int page, UINT8 *mem, int size)
#define MSX_SLOT_MAP(nm) \
static void slot_##nm##_map (running_machine &machine, slot_state *state, int page)
#define MSX_SLOT_WRITE(nm) \
static void slot_##nm##_write (running_machine &machine, slot_state *state, UINT16 addr, UINT8 val)
#define MSX_SLOT_RESET(nm) \
static void slot_##nm##_reset (running_machine &machine, slot_state *state)
#define MSX_SLOT_LOADSRAM(nm) \
static int slot_##nm##_loadsram (running_machine &machine, slot_state *state)
#define MSX_SLOT_SAVESRAM(nm) \
static int slot_##nm##_savesram (running_machine &machine, slot_state *state)
#endif /* MSX_SLOT_H_ */

View File

@ -16,347 +16,9 @@
#define VERBOSE 0
static int msx_probe_type (UINT8* pmem, int size)
{
int kon4, kon5, asc8, asc16, i;
if (size <= 0x10000) return 0;
if ( (pmem[0x10] == 'Y') && (pmem[0x11] == 'Z') && (size > 0x18000) )
return 6;
kon4 = kon5 = asc8 = asc16 = 0;
for (i=0;i<size-3;i++)
{
if (pmem[i] == 0x32 && pmem[i+1] == 0)
{
switch (pmem[i+2])
{
case 0x60:
case 0x70:
asc16++;
asc8++;
break;
case 0x68:
case 0x78:
asc8++;
asc16--;
}
switch (pmem[i+2])
{
case 0x60:
case 0x80:
case 0xa0:
kon4++;
break;
case 0x50:
case 0x70:
case 0x90:
case 0xb0:
kon5++;
}
}
}
if (MAX (kon4, kon5) > MAX (asc8, asc16) )
return (kon5 > kon4) ? 2 : 3;
else
return (asc8 > asc16) ? 4 : 5;
}
DEVICE_IMAGE_LOAD_MEMBER(msx_state,msx_cart)
{
int size;
int size_aligned;
UINT8 *mem;
int type = -1;
astring extra;
char *sramfile;
slot_state *st;
int id = -1;
if (strcmp(image.device().tag(),":cart1")==0)
id = 0;
if (strcmp(image.device().tag(),":cart2")==0)
id = 1;
if( id == -1 )
{
//logerror ("error: invalid cart tag '%s'\n", image->tag);
return IMAGE_INIT_FAIL;
}
if ( image.software_entry() != NULL )
{
/* Load software from software list */
/* TODO: Add proper SRAM (size) handling */
const char *mapper = image.get_feature("mapper");
if (mapper != NULL)
{
static const struct { const char *mapper_name; int mapper_type; } mapper_types[] =
{
{ "NOMAPPER", SLOT_EMPTY },
{ "M60002-0125SP", SLOT_ASCII8 },
{ "LZ93A13", SLOT_ASCII8 },
{ "NEOS MR6401", SLOT_ASCII8 },
{ "BS6202", SLOT_ASCII8 },
{ "BS6101", SLOT_ASCII8 },
{ "M60002-0125SP-16", SLOT_ASCII16 },
{ "LZ93A13-16", SLOT_ASCII16 },
{ "BS6101-16", SLOT_ASCII16 },
{ "MR6401", SLOT_ASCII16 },
{ "CROSS-BLAIM", SLOT_CROSS_BLAIM },
{ "GMASTER2", SLOT_GAMEMASTER2 },
{ "80IN1", SLOT_KOREAN_80IN1 },
{ "90IN1", SLOT_KOREAN_90IN1 },
{ "126IN1", SLOT_KOREAN_126IN1 },
{ "FM-PAC", SLOT_FMPAC },
{ "IREM TAM-S1", SLOT_RTYPE },
{ "KONAMI", SLOT_KONAMI },
{ "KONAMI-SCC", SLOT_KONAMI_SCC },
{ "SUPERLODE", SLOT_SUPERLODERUNNER },
{ "MAJUTSUSHI", SLOT_MAJUTSUSHI },
{ "DISK_ROM", SLOT_DISK_ROM },
};
for (int i = 0; i < ARRAY_LENGTH(mapper_types) && type < 0; i++)
{
if (!core_stricmp(mapper, mapper_types[i].mapper_name))
type = mapper_types[i].mapper_type;
}
if (-1 == type)
logerror("Mapper '%s' not recognized!\n", mapper);
}
UINT8 *tmp_sram = image.get_software_region("sram");
if (tmp_sram)
{
if (type == SLOT_ASCII8) type = SLOT_ASCII8_SRAM;
if (type == SLOT_ASCII16) type = SLOT_ASCII16_SRAM;
}
UINT8 *rom_region = image.get_software_region("rom");
size = size_aligned = image.get_software_region_length("rom");
mem = auto_alloc_array(machine(), UINT8, size_aligned);
memcpy(mem, rom_region, size_aligned);
}
else
{
/* Old style image loading */
size = image.length ();
if (size < 0x2000)
{
logerror ("cart #%d: error: file is smaller than 2kb, too small to be true!\n", id);
return IMAGE_INIT_FAIL;
}
/* allocate memory and load */
size_aligned = 0x2000;
while (size_aligned < size)
size_aligned *= 2;
mem = auto_alloc_array(machine(),UINT8,size_aligned);
if (!mem)
{
logerror ("cart #%d: error: failed to allocate memory for cartridge\n", id);
return IMAGE_INIT_FAIL;
}
if (size < size_aligned)
memset (mem, 0xff, size_aligned);
if (image.fread(mem, size) != size)
{
logerror ("cart #%d: %s: can't read full %d bytes\n", id, image.filename (), size);
return IMAGE_INIT_FAIL;
}
/* see if msx.crc will tell us more */
if (!hashfile_extrainfo(image, extra))
{
logerror("cart #%d: warning: no information in crc file\n", id);
type = -1;
}
else
if ((1 != sscanf(extra.cstr(), "%d", &type) ) || type < 0 || type > SLOT_LAST_CARTRIDGE_TYPE)
{
logerror("cart #%d: warning: information in crc file not valid\n", id);
type = -1;
}
else
logerror ("cart #%d: info: cart extra info: '%s' = %s\n", id, extra.cstr(), msx_slot_list[type].name);
/* if not, attempt autodetection */
if (type < 0)
{
type = msx_probe_type (mem, size);
if (mem[0] != 'A' || mem[1] != 'B')
logerror("cart #%d: %s: May not be a valid ROM file\n", id, image.filename ());
logerror("cart #%d: Probed cartridge mapper %d/%s\n", id, type, msx_slot_list[type].name);
}
}
/* mapper type 0 always needs 64kB */
if (!type && size_aligned != 0x10000)
{
UINT8 *old_mem = mem;
int old_size_aligned = size_aligned;
size_aligned = 0x10000;
mem = auto_alloc_array(machine(),UINT8, 0x10000);
if (!mem)
{
auto_free(machine(),old_mem);
logerror ("cart #%d: error: cannot allocate memory\n", id);
return IMAGE_INIT_FAIL;
}
if (size < 0x10000)
memset (mem + size, 0xff, 0x10000 - size);
if (size > 0x10000)
{
logerror ("cart #%d: warning: rom truncated to 64kb due to mapperless type (possibly detected)\n", id);
size = 0x10000;
}
/* Copy old contents to newly claimed memory */
memcpy(mem,old_mem,old_size_aligned);
auto_free(machine(),old_mem);
}
/* mapper type 0 (ROM) might need moving around a bit */
if (!type)
{
int i, page = 1;
/* find the correct page */
if (mem[0] == 'A' && mem[1] == 'B')
{
for (i=2; i<=8; i += 2)
{
if (mem[i] || mem[i+1])
{
page = mem[i+1] / 0x40;
break;
}
}
}
if (size <= 0x4000)
{
if (page == 1 || page == 2)
{
/* copy to the respective page */
memcpy (mem + (page * 0x4000), mem, 0x4000);
memset (mem, 0xff, 0x4000);
}
else
{
/* memory is repeated 4 times */
page = -1;
memcpy (mem + 0x4000, mem, 0x4000);
memcpy (mem + 0x8000, mem, 0x4000);
memcpy (mem + 0xc000, mem, 0x4000);
}
}
else /*if (size <= 0xc000) */
{
if (page)
{
/* shift up 16kB; custom memcpy so overlapping memory isn't corrupted. ROM starts in page 1 (0x4000) */
UINT8 *m;
page = 1;
i = 0xc000; m = mem + 0xffff;
while (i--)
{
*m = *(m - 0x4000);
m--;
}
memset (mem, 0xff, 0x4000);
}
}
if (page)
logerror ("cart #%d: info: rom in page %d\n", id, page);
else
logerror ("cart #%d: info: rom duplicted in all pages\n", id);
}
/* kludge */
if (type == 0)
type = SLOT_ROM;
/* allocate and set slot_state for this cartridge */
st = auto_alloc(machine(),slot_state);
if (!st)
{
logerror ("cart #%d: error: cannot allocate memory for cartridge state\n", id);
return IMAGE_INIT_FAIL;
}
memset (st, 0, sizeof (slot_state));
st->m_type = type;
sramfile = auto_alloc_array(machine(), char, strlen (image.filename ()) + 1);
if (sramfile)
{
char *ext;
strcpy (sramfile, image.basename ());
ext = strrchr (sramfile, '.');
if (ext)
*ext = 0;
st->m_sramfile = sramfile;
}
if (msx_slot_list[type].init (machine(), st, 0, mem, size_aligned))
return IMAGE_INIT_FAIL;
if (msx_slot_list[type].loadsram)
msx_slot_list[type].loadsram (machine(), st);
m_cart_state[id] = st;
msx_memory_set_carts();
return IMAGE_INIT_PASS;
}
DEVICE_IMAGE_UNLOAD_MEMBER(msx_state, msx_cart)
{
int id = -1;
if (strcmp(image.device().tag(),":cart1")==0)
id = 0;
if (strcmp(image.device().tag(),":cart2")==0)
id = 1;
if( id == -1 )
{
//logerror ("error: invalid cart tag '%s'\n", image->tag);
return;
}
if (msx_slot_list[m_cart_state[id]->m_type].savesram)
msx_slot_list[m_cart_state[id]->m_type].savesram (machine(), m_cart_state[id]);
}
WRITE_LINE_MEMBER(msx_state::msx_vdp_interrupt)
{
m_maincpu->set_input_line(0, (state ? HOLD_LINE : CLEAR_LINE));
m_maincpu->set_input_line(0, (state ? ASSERT_LINE : CLEAR_LINE));
}
void msx_state::msx_ch_reset_core ()
@ -373,7 +35,6 @@ MACHINE_START_MEMBER(msx_state,msx)
MACHINE_START_MEMBER(msx_state,msx2)
{
m_port_c_old = 0xff;
m_dsk_stat = 0x3f;
}
MACHINE_RESET_MEMBER(msx_state,msx)
@ -612,16 +273,6 @@ WRITE8_MEMBER(msx_state::msx_psg_port_b_w)
m_psg_b = data;
}
WRITE8_MEMBER( msx_state::msx_fmpac_w )
{
if (m_opll_active)
{
if (offset == 1)
m_ym->write(space, 1, data);
else
m_ym->write(space, 0, data);
}
}
/*
** RTC functions
@ -642,53 +293,6 @@ READ8_MEMBER( msx_state::msx_rtc_reg_r )
return m_rtc->read(space, m_rtc_latch);
}
/*
From: erbo@xs4all.nl (erik de boer)
sony and philips have used (almost) the same design
and this is the memory layout
but it is not a msx standard !
WD1793 or wd2793 registers
address
7FF8H read status register
write command register
7FF9H r/w track register (r/o on NMS 8245 and Sony)
7FFAH r/w sector register (r/o on NMS 8245 and Sony)
7FFBH r/w data register
hardware registers
address
7FFCH r/w bit 0 side select
7FFDH r/w b7>M-on , b6>in-use , b1>ds1 , b0>ds0 (all neg. logic)
7FFEH not used
7FFFH read b7>drq , b6>intrq
set on 7FFDH bit 2 always to 0 (some use it as disk change reset)
*/
WRITE_LINE_MEMBER( msx_state::msx_wd179x_intrq_w )
{
if (state)
m_dsk_stat &= ~0x40;
else
m_dsk_stat |= 0x40;
}
WRITE_LINE_MEMBER( msx_state::msx_wd179x_drq_w )
{
if (state)
m_dsk_stat &= ~0x80;
else
m_dsk_stat |= 0x80;
}
/*
** The PPI functions
@ -705,7 +309,7 @@ WRITE8_MEMBER( msx_state::msx_ppi_port_a_w )
WRITE8_MEMBER( msx_state::msx_ppi_port_c_w )
{
keylatch = data & 0x0f;
m_keylatch = data & 0x0f;
/* caps lock */
if ( BIT(m_port_c_old ^ data, 6) )
@ -732,7 +336,7 @@ READ8_MEMBER( msx_state::msx_ppi_port_b_r )
int row, data;
ioport_port *keynames[] = { m_io_key0, m_io_key1, m_io_key2, m_io_key3, m_io_key4, m_io_key5 };
row = keylatch;
row = m_keylatch;
if (row <= 10)
{
data = keynames[row / 2]->read();
@ -750,198 +354,65 @@ READ8_MEMBER( msx_state::msx_ppi_port_b_r )
*
***********************************************************************/
void msx_state::install_slot_pages(device_t &owner, UINT8 prim, UINT8 sec, UINT8 page, UINT8 numpages, device_t *device)
{
msx_state &msx = downcast<msx_state &>(owner);
msx_internal_slot_interface *internal_slot = dynamic_cast<msx_internal_slot_interface *>(device);
for ( int i = page; i < MIN(page + numpages, 4); i++ )
{
msx.m_all_slots[prim][sec][i] = internal_slot;
}
if ( sec )
{
msx.m_slot_expanded[prim] = true;
}
}
void msx_state::msx_memory_init()
{
int prim, sec, page, extent, option;
int size = 0;
const msx_slot_layout *layout= (msx_slot_layout*)NULL;
const msx_slot *slot;
slot_state *st;
UINT8 *mem = NULL;
int count_populated_pages = 0;
if ( m_layout == NULL ) {
fatalerror("No msx slot layout defined for this system!\n");
}
m_empty = auto_alloc_array(machine(), UINT8, 0x4000);
memset (m_empty, 0xff, 0x4000);
for (prim=0; prim<4; prim++) {
for (sec=0; sec<4; sec++) {
for (page=0; page<4; page++) {
m_all_state[prim][sec][page]= (slot_state*)NULL;
}
}
}
for (layout = m_layout; layout->entry != MSX_LAYOUT_LAST; layout++) {
switch (layout->entry) {
case MSX_LAYOUT_SLOT_ENTRY:
prim = layout->slot_primary;
sec = layout->slot_secondary;
page = layout->slot_page;
extent = layout->page_extent;
if (layout->slot_secondary) {
m_slot_expanded[layout->slot_primary]= TRUE;
}
slot = &msx_slot_list[layout->type];
if (slot->slot_type != layout->type) {
logerror ("internal error: msx_slot_list[%d].type != %d\n",
slot->slot_type, slot->slot_type);
}
size = layout->size;
option = layout->option;
if (layout->type != SLOT_CARTRIDGE1 && layout->type != SLOT_CARTRIDGE2)
// Populate all unpopulated slots with the dummy interface
for ( int prim = 0; prim < 4; prim++ )
{
for ( int sec = 0; sec < 4; sec++ )
{
for ( int page = 0; page < 4; page++ )
{
int size_tmp = 0;
if (size < 0x4000)
size_tmp = 0x4000;
else if (size > 0x10000)
size_tmp = 0x10000;
if ( m_all_slots[prim][sec][page] == NULL )
{
m_all_slots[prim][sec][page] = &m_empty_slot;
}
else
size_tmp = size;
int extent_tmp = size_tmp / 0x4000;
if (extent_tmp != extent)
fatalerror("incorrect MSX_LAYOUT_SLOT configuration - expected extent %d but found %d\n", extent, extent_tmp);
}
if (VERBOSE)
{
logerror ("slot %d/%d/%d-%d: type %s, size 0x%x\n",
prim, sec, page, page + extent - 1, slot->name, size);
}
st = (slot_state*)NULL;
if (layout->type == SLOT_CARTRIDGE1) {
st = m_cart_state[0];
if (!st) {
slot = &msx_slot_list[SLOT_SOUNDCARTRIDGE];
size = 0x20000;
{
count_populated_pages++;
}
}
if (layout->type == SLOT_CARTRIDGE2) {
st = m_cart_state[1];
if (!st) {
/* Check whether the optional FM-PAC rom is present */
option = 0x10000;
size = 0x10000;
mem = m_region_maincpu->base() + option;
if (m_region_maincpu->bytes() >= size + option && mem[0] == 'A' && mem[1] == 'B') {
slot = &msx_slot_list[SLOT_FMPAC];
}
else {
slot = &msx_slot_list[SLOT_EMPTY];
}
}
}
if (!st) {
switch (slot->mem_type) {
case MSX_MEM_HANDLER:
case MSX_MEM_ROM:
mem = m_region_maincpu->base() + option;
break;
case MSX_MEM_RAM:
mem = NULL;
break;
}
st = auto_alloc_clear (machine(), slot_state);
memset (st, 0, sizeof (slot_state));
if (slot->init (machine(), st, layout->slot_page, mem, size)) {
continue;
}
}
while (extent--) {
if (page > 3) {
logerror ("internal error: msx_slot_layout wrong, "
"page + extent > 3\n");
break;
}
m_all_state[prim][sec][page] = st;
page++;
}
break;
}
}
if ( count_populated_pages == 0 ) {
fatalerror("No msx slot layout defined for this system!\n");
}
}
void msx_state::msx_memory_reset ()
{
slot_state *st, *last_st = (slot_state*)NULL;
int prim, sec, page;
m_primary_slot = 0;
for (prim=0; prim<4; prim++)
for (int prim=0; prim<4; prim++)
{
m_secondary_slot[prim] = 0;
for (sec=0; sec<4; sec++)
{
for (page=0; page<4; page++)
{
st = m_all_state[prim][sec][page];
if (st && st != last_st)
msx_slot_list[st->m_type].reset (machine(), st);
last_st = st;
}
}
}
}
void msx_state::msx_memory_set_carts()
{
const msx_slot_layout *layout;
int page;
if (!m_layout)
return;
for (layout = m_layout; layout->entry != MSX_LAYOUT_LAST; layout++)
{
if (layout->entry == MSX_LAYOUT_SLOT_ENTRY)
{
switch (layout->type)
{
case SLOT_CARTRIDGE1:
for (page=0; page<4; page++)
m_all_state[layout->slot_primary][layout->slot_secondary][page]
= m_cart_state[0];
break;
case SLOT_CARTRIDGE2:
for (page=0; page<4; page++)
m_all_state[layout->slot_primary][layout->slot_secondary][page]
= m_cart_state[1];
break;
}
}
}
}
void msx_state::msx_memory_map_page (UINT8 page)
{
int slot_primary;
int slot_secondary;
slot_state *st;
const msx_slot *slot;
int slot_primary = (m_primary_slot >> (page * 2)) & 3;
int slot_secondary = (m_secondary_slot[slot_primary] >> (page * 2)) & 3;
slot_primary = (m_primary_slot >> (page * 2)) & 3;
slot_secondary = (m_secondary_slot[slot_primary] >> (page * 2)) & 3;
st = m_all_state[slot_primary][slot_secondary][page];
slot = st ? &msx_slot_list[st->m_type] : &msx_slot_list[SLOT_EMPTY];
m_state[page] = st;
m_slot[page] = slot;
if (VERBOSE)
logerror ("mapping %s in %d/%d/%d\n", slot->name, slot_primary, slot_secondary, page);
slot->map (machine(), st, page);
m_current_page[page] = m_all_slots[slot_primary][slot_secondary][page];
}
void msx_state::msx_memory_map_all ()
@ -950,94 +421,14 @@ void msx_state::msx_memory_map_all ()
msx_memory_map_page (i);
}
WRITE8_MEMBER( msx_state::msx_page0_w )
READ8_MEMBER( msx_state::msx_mem_read )
{
if ( offset == 0 )
{
m_superloderunner_bank = data;
if (m_slot[2]->slot_type == SLOT_SUPERLODERUNNER)
m_slot[2]->map (machine(), m_state[2], 2);
}
switch (m_slot[0]->mem_type)
{
case MSX_MEM_RAM:
m_ram_pages[0][offset] = data;
break;
case MSX_MEM_HANDLER:
m_slot[0]->write (machine(), m_state[0], offset, data);
}
return m_current_page[offset >> 14]->read(space, offset);
}
WRITE8_MEMBER( msx_state::msx_page0_1_w )
WRITE8_MEMBER( msx_state::msx_mem_write )
{
msx_page0_w( space, 0x2000 + offset, data );
}
WRITE8_MEMBER( msx_state::msx_page1_w )
{
switch (m_slot[1]->mem_type)
{
case MSX_MEM_RAM:
m_ram_pages[1][offset] = data;
break;
case MSX_MEM_HANDLER:
m_slot[1]->write (machine(), m_state[1], 0x4000 + offset, data);
}
}
WRITE8_MEMBER( msx_state::msx_page1_1_w )
{
msx_page1_w( space, 0x2000 + offset, data );
}
WRITE8_MEMBER( msx_state::msx_page1_2_w )
{
msx_page1_w( space, 0x3ff8 + offset, data );
}
WRITE8_MEMBER( msx_state::msx_page2_w )
{
switch (m_slot[2]->mem_type)
{
case MSX_MEM_RAM:
m_ram_pages[2][offset] = data;
break;
case MSX_MEM_HANDLER:
m_slot[2]->write (machine(), m_state[2], 0x8000 + offset, data);
}
}
WRITE8_MEMBER( msx_state::msx_page2_1_w )
{
msx_page2_w( space, 0x1800 + offset, data );
}
WRITE8_MEMBER( msx_state::msx_page2_2_w )
{
msx_page2_w( space, 0x2000 + offset, data );
}
WRITE8_MEMBER( msx_state::msx_page2_3_w )
{
msx_page2_w( space, 0x3800 + offset, data );
}
WRITE8_MEMBER( msx_state::msx_page3_w )
{
switch (m_slot[3]->mem_type)
{
case MSX_MEM_RAM:
m_ram_pages[3][offset] = data;
break;
case MSX_MEM_HANDLER:
m_slot[3]->write (machine(), m_state[3], 0xc000 + offset, data);
}
}
WRITE8_MEMBER( msx_state::msx_page3_1_w )
{
msx_page3_w( space, 0x2000 + offset, data );
m_current_page[offset >> 14]->write(space, offset, data);
}
WRITE8_MEMBER( msx_state::msx_sec_slot_w )
@ -1052,42 +443,21 @@ WRITE8_MEMBER( msx_state::msx_sec_slot_w )
msx_memory_map_all ();
}
else
msx_page3_w(space, 0x3fff, data);
m_current_page[3]->write(space, 0xffff, data);
}
READ8_MEMBER( msx_state::msx_sec_slot_r )
{
UINT8 result;
int slot = m_primary_slot >> 6;
if (m_slot_expanded[slot])
result = ~m_secondary_slot[slot];
{
return ~m_secondary_slot[slot];
}
else
result = m_top_page[0x1fff];
return result;
}
WRITE8_MEMBER( msx_state::msx_ram_mapper_w )
{
m_ram_mapper[offset] = data;
if (m_slot[offset]->slot_type == SLOT_RAM_MM)
m_slot[offset]->map (machine(), m_state[offset], offset);
}
READ8_MEMBER( msx_state::msx_ram_mapper_r )
{
return m_ram_mapper[offset] | m_ramio_set_bits;
}
WRITE8_MEMBER( msx_state::msx_90in1_w )
{
m_korean90in1_bank = data;
if (m_slot[1]->slot_type == SLOT_KOREAN_90IN1)
m_slot[1]->map (machine(), m_state[1], 1);
if (m_slot[2]->slot_type == SLOT_KOREAN_90IN1)
m_slot[2]->map (machine(), m_state[2], 2);
{
return m_current_page[3]->read(space, 0xffff);
}
}
READ8_MEMBER( msx_state::msx_kanji_r )
@ -1112,3 +482,24 @@ WRITE8_MEMBER( msx_state::msx_kanji_w )
else
m_kanji_latch = (m_kanji_latch & 0x1f800) | ((data & 0x3f) << 5);
}
READ8_MEMBER( msx_state::msx_switched_r )
{
// Read from selected switched device
return this->space().read_byte( (m_current_switched_device << 8) | offset );
}
WRITE8_MEMBER( msx_state::msx_switched_w )
{
if (offset == 0)
{
// Select switched device
m_current_switched_device = data;
}
else
{
// Write to selected switched device
this->space().write_byte( (m_current_switched_device << 8) | offset, data );
}
}

File diff suppressed because it is too large Load Diff

View File

@ -589,6 +589,7 @@ BUSES += KC
BUSES += MACPDS
BUSES += MIDI
BUSES += MEGADRIVE
BUSES += MSX_SLOT
BUSES += NES
BUSES += NUBUS
BUSES += ORICEXT
@ -1002,7 +1003,9 @@ $(MESSOBJ)/arcadia.a: \
$(MESSOBJ)/ascii.a: \
$(MESS_DRIVERS)/msx.o \
$(MESS_MACHINE)/msx.o \
$(MESS_MACHINE)/msx_slot.o \
$(MESS_MACHINE)/msx_switched.o \
$(MESS_MACHINE)/msx_matsushita.o \
$(MESS_MACHINE)/msx_s1985.o \
$(MESSOBJ)/at.a: \
$(MESS_MACHINE)/at.o \