diff options
author | Wilbert Pol <wilbert@jdg.info> | 2014-05-14 19:04:52 +0000 |
---|---|---|
committer | Wilbert Pol <wilbert@jdg.info> | 2014-05-14 19:04:52 +0000 |
commit | c74226bb26acd1afdcc59f20e174d126423f60b9 (patch) | |
tree | 67a584a596dc13b820cfdbe411eaf826852475ff /src/emu | |
parent | 8ab3ccb194ff9cb37bda434489a82da854b24af6 (diff) |
(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.
Diffstat (limited to 'src/emu')
43 files changed, 4820 insertions, 0 deletions
diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak index 9067f5bca1d..d0436681130 100644 --- a/src/emu/bus/bus.mak +++ b/src/emu/bus/bus.mak @@ -389,6 +389,38 @@ 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 #------------------------------------------------- diff --git a/src/emu/bus/msx_cart/ascii.c b/src/emu/bus/msx_cart/ascii.c new file mode 100644 index 00000000000..fa8d7a51d12 --- /dev/null +++ b/src/emu/bus/msx_cart/ascii.c @@ -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; + } + } +} + diff --git a/src/emu/bus/msx_cart/ascii.h b/src/emu/bus/msx_cart/ascii.h new file mode 100644 index 00000000000..24ad955e32f --- /dev/null +++ b/src/emu/bus/msx_cart/ascii.h @@ -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 + diff --git a/src/emu/bus/msx_cart/cartridge.c b/src/emu/bus/msx_cart/cartridge.c new file mode 100644 index 00000000000..6c724982526 --- /dev/null +++ b/src/emu/bus/msx_cart/cartridge.c @@ -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); +} diff --git a/src/emu/bus/msx_cart/cartridge.h b/src/emu/bus/msx_cart/cartridge.h new file mode 100644 index 00000000000..bcd51c263a7 --- /dev/null +++ b/src/emu/bus/msx_cart/cartridge.h @@ -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 diff --git a/src/emu/bus/msx_cart/crossblaim.c b/src/emu/bus/msx_cart/crossblaim.c new file mode 100644 index 00000000000..304364a84db --- /dev/null +++ b/src/emu/bus/msx_cart/crossblaim.c @@ -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(); +} + diff --git a/src/emu/bus/msx_cart/crossblaim.h b/src/emu/bus/msx_cart/crossblaim.h new file mode 100644 index 00000000000..36251bdb937 --- /dev/null +++ b/src/emu/bus/msx_cart/crossblaim.h @@ -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 diff --git a/src/emu/bus/msx_cart/fmpac.c b/src/emu/bus/msx_cart/fmpac.c new file mode 100644 index 00000000000..62703094b22 --- /dev/null +++ b/src/emu/bus/msx_cart/fmpac.c @@ -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); + } +} + diff --git a/src/emu/bus/msx_cart/fmpac.h b/src/emu/bus/msx_cart/fmpac.h new file mode 100644 index 00000000000..d6d44d091d8 --- /dev/null +++ b/src/emu/bus/msx_cart/fmpac.h @@ -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 diff --git a/src/emu/bus/msx_cart/konami.c b/src/emu/bus/msx_cart/konami.c new file mode 100644 index 00000000000..ee8115efd07 --- /dev/null +++ b/src/emu/bus/msx_cart/konami.c @@ -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; + } + +} + diff --git a/src/emu/bus/msx_cart/konami.h b/src/emu/bus/msx_cart/konami.h new file mode 100644 index 00000000000..18d0429d302 --- /dev/null +++ b/src/emu/bus/msx_cart/konami.h @@ -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 diff --git a/src/emu/bus/msx_cart/korean.c b/src/emu/bus/msx_cart/korean.c new file mode 100644 index 00000000000..a6688cb3340 --- /dev/null +++ b/src/emu/bus/msx_cart/korean.c @@ -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); + } +} + diff --git a/src/emu/bus/msx_cart/korean.h b/src/emu/bus/msx_cart/korean.h new file mode 100644 index 00000000000..76062632923 --- /dev/null +++ b/src/emu/bus/msx_cart/korean.h @@ -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 diff --git a/src/emu/bus/msx_cart/majutsushi.c b/src/emu/bus/msx_cart/majutsushi.c new file mode 100644 index 00000000000..a89ad1f2328 --- /dev/null +++ b/src/emu/bus/msx_cart/majutsushi.c @@ -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; + } +} + diff --git a/src/emu/bus/msx_cart/majutsushi.h b/src/emu/bus/msx_cart/majutsushi.h new file mode 100644 index 00000000000..95188585169 --- /dev/null +++ b/src/emu/bus/msx_cart/majutsushi.h @@ -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 diff --git a/src/emu/bus/msx_cart/msxdos2.c b/src/emu/bus/msx_cart/msxdos2.c new file mode 100644 index 00000000000..10af9d6de28 --- /dev/null +++ b/src/emu/bus/msx_cart/msxdos2.c @@ -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(); + } +} + diff --git a/src/emu/bus/msx_cart/msxdos2.h b/src/emu/bus/msx_cart/msxdos2.h new file mode 100644 index 00000000000..eeaaf584e4a --- /dev/null +++ b/src/emu/bus/msx_cart/msxdos2.h @@ -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 diff --git a/src/emu/bus/msx_cart/nomapper.c b/src/emu/bus/msx_cart/nomapper.c new file mode 100644 index 00000000000..faa91b3d1dc --- /dev/null +++ b/src/emu/bus/msx_cart/nomapper.c @@ -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; +} + diff --git a/src/emu/bus/msx_cart/nomapper.h b/src/emu/bus/msx_cart/nomapper.h new file mode 100644 index 00000000000..c469f776cdc --- /dev/null +++ b/src/emu/bus/msx_cart/nomapper.h @@ -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 diff --git a/src/emu/bus/msx_cart/rtype.c b/src/emu/bus/msx_cart/rtype.c new file mode 100644 index 00000000000..25c1ec18f89 --- /dev/null +++ b/src/emu/bus/msx_cart/rtype.c @@ -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; + } +} + diff --git a/src/emu/bus/msx_cart/rtype.h b/src/emu/bus/msx_cart/rtype.h new file mode 100644 index 00000000000..999ba3232ff --- /dev/null +++ b/src/emu/bus/msx_cart/rtype.h @@ -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 diff --git a/src/emu/bus/msx_cart/superloderunner.c b/src/emu/bus/msx_cart/superloderunner.c new file mode 100644 index 00000000000..8337ca63254 --- /dev/null +++ b/src/emu/bus/msx_cart/superloderunner.c @@ -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(); +} + diff --git a/src/emu/bus/msx_cart/superloderunner.h b/src/emu/bus/msx_cart/superloderunner.h new file mode 100644 index 00000000000..5508f3f361f --- /dev/null +++ b/src/emu/bus/msx_cart/superloderunner.h @@ -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 diff --git a/src/emu/bus/msx_slot/bunsetsu.c b/src/emu/bus/msx_slot/bunsetsu.c new file mode 100644 index 00000000000..49d529bc003 --- /dev/null +++ b/src/emu/bus/msx_slot/bunsetsu.c @@ -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; + } +} + diff --git a/src/emu/bus/msx_slot/bunsetsu.h b/src/emu/bus/msx_slot/bunsetsu.h new file mode 100644 index 00000000000..d798cc52b34 --- /dev/null +++ b/src/emu/bus/msx_slot/bunsetsu.h @@ -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 + diff --git a/src/emu/bus/msx_slot/cartridge.c b/src/emu/bus/msx_slot/cartridge.c new file mode 100644 index 00000000000..199d1c8a1b7 --- /dev/null +++ b/src/emu/bus/msx_slot/cartridge.c @@ -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); + } +} + diff --git a/src/emu/bus/msx_slot/cartridge.h b/src/emu/bus/msx_slot/cartridge.h new file mode 100644 index 00000000000..6716dc3ca14 --- /dev/null +++ b/src/emu/bus/msx_slot/cartridge.h @@ -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 + diff --git a/src/emu/bus/msx_slot/disk.c b/src/emu/bus/msx_slot/disk.c new file mode 100644 index 00000000000..3995bbc73e6 --- /dev/null +++ b/src/emu/bus/msx_slot/disk.c @@ -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; + } +} + diff --git a/src/emu/bus/msx_slot/disk.h b/src/emu/bus/msx_slot/disk.h new file mode 100644 index 00000000000..afeff77d527 --- /dev/null +++ b/src/emu/bus/msx_slot/disk.h @@ -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 + diff --git a/src/emu/bus/msx_slot/fs4600.c b/src/emu/bus/msx_slot/fs4600.c new file mode 100644 index 00000000000..76adbc65411 --- /dev/null +++ b/src/emu/bus/msx_slot/fs4600.c @@ -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; + } + } + } +} + diff --git a/src/emu/bus/msx_slot/fs4600.h b/src/emu/bus/msx_slot/fs4600.h new file mode 100644 index 00000000000..61f855e7a08 --- /dev/null +++ b/src/emu/bus/msx_slot/fs4600.h @@ -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 diff --git a/src/emu/bus/msx_slot/music.c b/src/emu/bus/msx_slot/music.c new file mode 100644 index 00000000000..77e8369fef4 --- /dev/null +++ b/src/emu/bus/msx_slot/music.c @@ -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); + } +} + diff --git a/src/emu/bus/msx_slot/music.h b/src/emu/bus/msx_slot/music.h new file mode 100644 index 00000000000..0dda5bf779c --- /dev/null +++ b/src/emu/bus/msx_slot/music.h @@ -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 + diff --git a/src/emu/bus/msx_slot/panasonic08.c b/src/emu/bus/msx_slot/panasonic08.c new file mode 100644 index 00000000000..af762c32cfa --- /dev/null +++ b/src/emu/bus/msx_slot/panasonic08.c @@ -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; + } +} + diff --git a/src/emu/bus/msx_slot/panasonic08.h b/src/emu/bus/msx_slot/panasonic08.h new file mode 100644 index 00000000000..6eedae2d505 --- /dev/null +++ b/src/emu/bus/msx_slot/panasonic08.h @@ -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 diff --git a/src/emu/bus/msx_slot/ram.c b/src/emu/bus/msx_slot/ram.c new file mode 100644 index 00000000000..f3a46daf8dc --- /dev/null +++ b/src/emu/bus/msx_slot/ram.c @@ -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; + } +} + diff --git a/src/emu/bus/msx_slot/ram.h b/src/emu/bus/msx_slot/ram.h new file mode 100644 index 00000000000..9f66808b234 --- /dev/null +++ b/src/emu/bus/msx_slot/ram.h @@ -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 diff --git a/src/emu/bus/msx_slot/ram_mm.c b/src/emu/bus/msx_slot/ram_mm.c new file mode 100644 index 00000000000..3c5bc7b47a1 --- /dev/null +++ b/src/emu/bus/msx_slot/ram_mm.c @@ -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 ); +} + diff --git a/src/emu/bus/msx_slot/ram_mm.h b/src/emu/bus/msx_slot/ram_mm.h new file mode 100644 index 00000000000..5027fa428e1 --- /dev/null +++ b/src/emu/bus/msx_slot/ram_mm.h @@ -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 + diff --git a/src/emu/bus/msx_slot/rom.c b/src/emu/bus/msx_slot/rom.c new file mode 100644 index 00000000000..fcae656ac41 --- /dev/null +++ b/src/emu/bus/msx_slot/rom.c @@ -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; +} + + diff --git a/src/emu/bus/msx_slot/rom.h b/src/emu/bus/msx_slot/rom.h new file mode 100644 index 00000000000..dfed30f902d --- /dev/null +++ b/src/emu/bus/msx_slot/rom.h @@ -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 diff --git a/src/emu/bus/msx_slot/slot.c b/src/emu/bus/msx_slot/slot.c new file mode 100644 index 00000000000..ad8b08634ec --- /dev/null +++ b/src/emu/bus/msx_slot/slot.c @@ -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; +} + diff --git a/src/emu/bus/msx_slot/slot.h b/src/emu/bus/msx_slot/slot.h new file mode 100644 index 00000000000..3ddf36a038f --- /dev/null +++ b/src/emu/bus/msx_slot/slot.h @@ -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 |