summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes/aladdin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nes/aladdin.cpp')
-rw-r--r--src/devices/bus/nes/aladdin.cpp339
1 files changed, 339 insertions, 0 deletions
diff --git a/src/devices/bus/nes/aladdin.cpp b/src/devices/bus/nes/aladdin.cpp
new file mode 100644
index 00000000000..67749cbe12d
--- /dev/null
+++ b/src/devices/bus/nes/aladdin.cpp
@@ -0,0 +1,339 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for Camerica/Codemasters Aladdin Deck Enhancer pass-through cart
+
+
+ Here we emulate the following PCBs
+
+ * Camerica ALGNV11 [mapper 71]
+ * Camerica ALGQV11 [mapper 232]
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "aladdin.h"
+
+
+#ifdef NES_PCB_DEBUG
+#define VERBOSE 1
+#else
+#define VERBOSE 0
+#endif
+
+#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+
+//----------------------------------
+//
+// Aladdin Cartslot implementation
+//
+//----------------------------------
+
+//-------------------------------------------------
+// sub-cart interface
+//-------------------------------------------------
+
+aladdin_cart_interface::aladdin_cart_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device),
+ m_rom(NULL),
+ m_rom_size(0),
+ m_rom_mask(0xff)
+{
+}
+
+aladdin_cart_interface::~aladdin_cart_interface()
+{
+}
+
+READ8_MEMBER(aladdin_cart_interface::read)
+{
+ if (offset < 0x4000)
+ return m_rom[(m_lobank * 0x4000) + (offset & 0x3fff)];
+ else
+ return m_rom[(m_hibank * 0x4000) + (offset & 0x3fff)];
+}
+
+//-------------------------------------------------
+// sub-cart slot device
+//-------------------------------------------------
+
+const device_type NES_ALADDIN_SLOT = &device_creator<nes_aladdin_slot_device>;
+
+nes_aladdin_slot_device::nes_aladdin_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, NES_ALADDIN_SLOT, "NES Aladdin Deck Enhancer Cartridge Slot", tag, owner, clock, "nes_ade_slot", __FILE__),
+ device_image_interface(mconfig, *this),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+nes_aladdin_slot_device::~nes_aladdin_slot_device()
+{
+}
+
+
+void nes_aladdin_slot_device::device_start()
+{
+ m_cart = dynamic_cast<aladdin_cart_interface *>(get_card_device());
+}
+
+READ8_MEMBER(nes_aladdin_slot_device::read)
+{
+ if (m_cart)
+ return m_cart->read(space, offset, mem_mask);
+
+ return 0xff;
+}
+
+// 128K for Dizzy The Adventurer, 256K for the others
+bool nes_aladdin_slot_device::call_load()
+{
+ if (m_cart)
+ {
+ UINT8 *ROM = m_cart->get_cart_base();
+ UINT32 size = 0;
+
+ if (!ROM)
+ return IMAGE_INIT_FAIL;
+
+ if (software_entry() == NULL)
+ {
+ if (length() != 0x20010 && length() != 0x40010)
+ return IMAGE_INIT_FAIL;
+
+ UINT8 temp[0x40010];
+ size = length() - 0x10;
+ fread(&temp, length());
+ memcpy(ROM, temp + 0x10, size);
+
+ // double check that iNES files are really mapper 71 or 232
+ {
+ UINT8 mapper = (temp[6] & 0xf0) >> 4;
+ mapper |= temp[7] & 0xf0;
+ if (mapper != 71 && mapper != 232)
+ return IMAGE_INIT_FAIL;
+ }
+ }
+ else
+ {
+ if (get_software_region_length("rom") != 0x20000 && get_software_region_length("rom") != 0x40000)
+ return IMAGE_INIT_FAIL;
+
+ size = get_software_region_length("rom");
+ memcpy(ROM, get_software_region("rom"), size);
+ }
+
+ m_cart->set_cart_size(size);
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+
+bool nes_aladdin_slot_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;
+}
+
+void nes_aladdin_slot_device::get_default_card_software(std::string &result)
+{
+ if (open_image_file(mconfig().options()))
+ {
+ const char *slot_string = "algn";
+ UINT32 len = core_fsize(m_file);
+ dynamic_buffer rom(len);
+ UINT8 mapper;
+
+ core_fread(m_file, &rom[0], len);
+
+ mapper = (rom[6] & 0xf0) >> 4;
+ mapper |= rom[7] & 0xf0;
+
+// if (mapper == 71)
+// slot_string = "algn";
+ if (mapper == 232)
+ slot_string = "algq";
+
+ clear();
+
+ result.assign(slot_string);
+ }
+ else
+ software_get_default_slot(result, "algn");
+}
+
+
+//----------------------------------
+//
+// Aladdin Minicart implementation
+//
+//----------------------------------
+
+ROM_START( ade_rom )
+ ROM_REGION(0x40000, "aderom", ROMREGION_ERASEFF)
+ROM_END
+
+const device_type NES_ALGN_ROM = &device_creator<nes_algn_rom_device>;
+const device_type NES_ALGQ_ROM = &device_creator<nes_algq_rom_device>;
+
+nes_algn_rom_device::nes_algn_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),
+ aladdin_cart_interface( mconfig, *this )
+{
+}
+
+nes_algn_rom_device::nes_algn_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, NES_ALGN_ROM, "NES Aladdin Deck Enhancer ALGN ROM", tag, owner, clock, "nes_algn_rom", __FILE__),
+ aladdin_cart_interface( mconfig, *this )
+{
+}
+
+nes_algq_rom_device::nes_algq_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_algn_rom_device(mconfig, NES_ALGQ_ROM, "NES Aladdin Deck Enhancer ALGQ ROM", tag, owner, clock, "nes_algq_rom", __FILE__)
+{
+}
+
+void nes_algn_rom_device::device_start()
+{
+ m_rom = (UINT8*)memregion("aderom")->base();
+ save_item(NAME(m_lobank));
+}
+
+void nes_algn_rom_device::device_reset()
+{
+ m_lobank = 0;
+ m_hibank = 0x0f & m_rom_mask;
+}
+
+void nes_algq_rom_device::device_start()
+{
+ m_rom = (UINT8*)memregion("aderom")->base();
+ save_item(NAME(m_lobank));
+ save_item(NAME(m_hibank));
+ save_item(NAME(m_bank_base));
+}
+
+void nes_algq_rom_device::device_reset()
+{
+ m_lobank = 0;
+ m_hibank = 3;
+ m_bank_base = 0;
+}
+
+const rom_entry *nes_algn_rom_device::device_rom_region() const
+{
+ return ROM_NAME( ade_rom );
+}
+
+UINT8 *nes_algn_rom_device::get_cart_base()
+{
+ return m_rom;
+}
+
+void nes_algn_rom_device::write_prg(UINT32 offset, UINT8 data)
+{
+ // m_hibank is fixed to the last available bank!
+ if (offset >= 0x4000)
+ m_lobank = data & m_rom_mask;
+}
+
+void nes_algq_rom_device::write_prg(UINT32 offset, UINT8 data)
+{
+ // here hibank & lobank variables are used differently
+ // m_bank_base = 64K block
+ // m_lobank = 16K page inside the block
+ // m_hibank = 3rd page inside the block
+ if (offset < 0x4000)
+ {
+ m_bank_base = ((data >> 3) & 3) << 2;
+ m_lobank = m_bank_base | (m_lobank & 3);
+ m_hibank = m_bank_base | 3;
+ }
+ else
+ m_lobank = m_bank_base | (data & 3);
+}
+
+
+//-----------------------------------------------
+//
+// Camerica/Codemasters Aladdin passthru
+// implementation
+//
+//-----------------------------------------------
+
+const device_type NES_ALADDIN = &device_creator<nes_aladdin_device>;
+
+nes_aladdin_device::nes_aladdin_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_ALADDIN, "NES Cart Camerica Aladdin PCB", tag, owner, clock, "nes_aladdin", __FILE__),
+ m_subslot(*this, "ade_slot")
+{
+}
+
+
+void nes_aladdin_device::device_start()
+{
+ common_start();
+}
+
+void nes_aladdin_device::pcb_reset()
+{
+ prg32(0xff);
+ chr8(0, CHRRAM);
+}
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Camerica/Codemasters Aladdin Deck Enhancer
+
+ iNES: mapper 71 & 232
+
+ In MESS: Supported (but timing issues in some games)
+
+ -------------------------------------------------*/
+
+READ8_MEMBER(nes_aladdin_device::read_h)
+{
+ LOG_MMC(("aladdin read_h, offset: %04x\n", offset));
+ // this shall be the proper code, but it's a bit slower, so we access directly the subcart below
+ //return m_subslot->read(space, offset, mem_mask);
+
+ if (m_subslot->m_cart)
+ return m_subslot->m_cart->read(space, offset, mem_mask);
+ else // this is "fake" in the sense that we fill CPU space with 0xff if no Aladdin cart is loaded
+ return hi_access_rom(offset);
+}
+
+WRITE8_MEMBER(nes_aladdin_device::write_h)
+{
+ LOG_MMC(("aladdin write_h, offset: %04x, data: %02x\n", offset, data));
+ m_subslot->write_prg(offset, data);
+}
+
+//-------------------------------------------------
+// CART SLOT
+//-------------------------------------------------
+
+static SLOT_INTERFACE_START(ade_cart)
+ SLOT_INTERFACE_INTERNAL("algn", NES_ALGN_ROM)
+ SLOT_INTERFACE_INTERNAL("algq", NES_ALGQ_ROM)
+SLOT_INTERFACE_END
+
+
+MACHINE_CONFIG_FRAGMENT( camerica_aladdin )
+ MCFG_ALADDIN_MINICART_ADD("ade_slot", ade_cart)
+MACHINE_CONFIG_END
+
+machine_config_constructor nes_aladdin_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( camerica_aladdin );
+}