summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes/irem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nes/irem.cpp')
-rw-r--r--src/devices/bus/nes/irem.cpp352
1 files changed, 352 insertions, 0 deletions
diff --git a/src/devices/bus/nes/irem.cpp b/src/devices/bus/nes/irem.cpp
new file mode 100644
index 00000000000..43f5bab1d7d
--- /dev/null
+++ b/src/devices/bus/nes/irem.cpp
@@ -0,0 +1,352 @@
+// license:BSD-3-Clause
+// copyright-holders:Fabio Priuli
+/***********************************************************************************************************
+
+
+ NES/Famicom cartridge emulation for IREM PCBs
+
+
+ Here we emulate the following PCBs
+
+ * IREM LROG017 [mapper 77]
+ * IREM Holy Diver [mapper 78]
+ * IREM TAM-S1 [mapper 97]
+ * IREM G101 [mapper 32]
+ * IREM H3001 [mapper 65]
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "irem.h"
+
+#include "cpu/m6502/m6502.h"
+
+#ifdef NES_PCB_DEBUG
+#define VERBOSE 1
+#else
+#define VERBOSE 0
+#endif
+
+#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+const device_type NES_LROG017 = &device_creator<nes_lrog017_device>;
+const device_type NES_HOLYDIVR = &device_creator<nes_holydivr_device>;
+const device_type NES_TAM_S1 = &device_creator<nes_tam_s1_device>;
+const device_type NES_G101 = &device_creator<nes_g101_device>;
+const device_type NES_H3001 = &device_creator<nes_h3001_device>;
+
+
+nes_lrog017_device::nes_lrog017_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_LROG017, "NES Cart Irem Discrete 74*161/161/21/138 PCB", tag, owner, clock, "nes_lrog017", __FILE__)
+{
+}
+
+nes_holydivr_device::nes_holydivr_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_HOLYDIVR, "NES Cart Irem Holy Diver PCB", tag, owner, clock, "nes_holydivr", __FILE__)
+{
+}
+
+nes_tam_s1_device::nes_tam_s1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_TAM_S1, "NES Cart Irem TAM-S1 PCB", tag, owner, clock, "nes_tam_s1", __FILE__)
+{
+}
+
+nes_g101_device::nes_g101_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_G101, "NES Cart Irem G-101 PCB", tag, owner, clock, "nes_g101", __FILE__)
+{
+}
+
+nes_h3001_device::nes_h3001_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : nes_nrom_device(mconfig, NES_H3001, "NES Cart Irem H-3001 PCB", tag, owner, clock, "nes_h3001", __FILE__)
+{
+}
+
+
+
+
+void nes_lrog017_device::device_start()
+{
+ common_start();
+}
+
+void nes_lrog017_device::pcb_reset()
+{
+ prg32(0);
+ chr2_0(0, CHRROM);
+ chr2_2(0, CHRRAM);
+ chr2_4(1, CHRRAM);
+ chr2_6(2, CHRRAM);
+}
+
+void nes_holydivr_device::device_start()
+{
+ common_start();
+}
+
+void nes_holydivr_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, m_chr_source);
+}
+
+void nes_tam_s1_device::device_start()
+{
+ common_start();
+}
+
+void nes_tam_s1_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg16_89ab(m_prg_chunks - 1);
+ prg16_cdef(0);
+ chr8(0, m_chr_source);
+}
+
+void nes_g101_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_latch));
+}
+
+void nes_g101_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, m_chr_source);
+
+ m_latch = 0;
+}
+
+void nes_h3001_device::device_start()
+{
+ common_start();
+ irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer->adjust(attotime::zero, 0, machine().device<cpu_device>("maincpu")->cycles_to_attotime(1));
+
+ save_item(NAME(m_irq_enable));
+ save_item(NAME(m_irq_count));
+ save_item(NAME(m_irq_count_latch));
+}
+
+void nes_h3001_device::pcb_reset()
+{
+ m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, m_chr_source);
+
+ m_irq_enable = 0;
+ m_irq_count = 0;
+ m_irq_count_latch = 0;
+}
+
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
+ Irem LROG017 - Discrete board emulation (74*161/161/21/138)
+
+ Games: Napoleon Senki
+
+ iNES: mapper 77
+
+ This board should use 2KB of CHRRAM as NTRAM, instead
+ of using directly 4-screen mirroring, but for the
+ moment we cheat in this way...
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_lrog017_device::write_h)
+{
+ LOG_MMC(("lrog017 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ // this pcb is subject to bus conflict
+ data = account_bus_conflict(offset, data);
+
+ prg32(data);
+ chr2_0((data >> 4), CHRROM);
+}
+
+/*-------------------------------------------------
+
+ Irem Holy Diver board emulation
+
+ iNES: mapper 78 (shared with JF-16)
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_holydivr_device::write_h)
+{
+ LOG_MMC(("holy diver write_h, offset: %04x, data: %02x\n", offset, data));
+
+ // this pcb is subject to bus conflict
+ data = account_bus_conflict(offset, data);
+
+ set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ chr8(data >> 4, CHRROM);
+ prg16_89ab(data);
+}
+
+/*-------------------------------------------------
+
+ Irem TAM-S1 board emulation
+
+ Games: Kaiketsu Yanchamaru
+
+ iNES: mapper 97
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_tam_s1_device::write_h)
+{
+ LOG_MMC(("tam s1 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ if (offset < 0x4000)
+ {
+ // this pcb is subject to bus conflict
+ data = account_bus_conflict(offset, data);
+
+ set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ prg16_cdef(data);
+ }
+}
+
+/*-------------------------------------------------
+
+ Irem G-101 board emulation
+
+ Major League uses hardwired mirroring
+
+ iNES: mapper 32
+
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(nes_g101_device::write_h)
+{
+ LOG_MMC(("g101 write_h, offset: %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ if (m_latch)
+ {
+ prg8_89(0xfe);
+ prg8_cd(data & 0x1f);
+ }
+ else
+ {
+ prg8_89(data & 0x1f);
+ prg8_cd(0xfe);
+ }
+ break;
+ case 0x1000:
+ m_latch = BIT(data, 1);
+ if (m_pcb_ctrl_mirror)
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 0x2000:
+ prg8_ab(data & 0x1f);
+ break;
+ case 0x3000:
+ chr1_x(offset & 0x07, data & 0x7f, CHRROM);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Irem H-3001 board emulation
+
+ Games: Daiku no Gen San 2 - Akage no Dan no Gyakushuu,
+ Kaiketsu Yanchamaru 3, Spartan X 2
+
+ iNES: mapper 65
+
+ In MESS: Supported.
+
+ -------------------------------------------------*/
+
+
+void nes_h3001_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (id == TIMER_IRQ)
+ {
+ if (m_irq_enable)
+ {
+ // 16bit counter, IRQ fired when the counter reaches 0
+ // after firing, the counter is *not* reloaded and does not wrap
+ if (m_irq_count > 0)
+ m_irq_count--;
+
+ if (!m_irq_count)
+ {
+ m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE);
+ m_irq_enable = 0;
+ }
+ }
+ }
+}
+
+WRITE8_MEMBER(nes_h3001_device::write_h)
+{
+ LOG_MMC(("h3001 write_h, offset %04x, data: %02x\n", offset, data));
+
+ switch (offset & 0x7fff)
+ {
+ case 0x0000:
+ prg8_89(data);
+ break;
+
+ case 0x1001:
+ set_nt_mirroring(BIT(data, 7) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+
+ case 0x1003:
+ m_irq_enable = data & 0x80;
+ m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
+ break;
+
+ case 0x1004:
+ m_irq_count = m_irq_count_latch;
+ m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
+ break;
+
+ case 0x1005:
+ m_irq_count_latch = (m_irq_count_latch & 0x00ff) | (data << 8);
+ break;
+
+ case 0x1006:
+ m_irq_count_latch = (m_irq_count_latch & 0xff00) | data;
+ break;
+
+ case 0x2000:
+ prg8_ab(data);
+ break;
+
+ case 0x3000: case 0x3001: case 0x3002: case 0x3003:
+ case 0x3004: case 0x3005: case 0x3006: case 0x3007:
+ chr1_x(offset & 0x07, data, CHRROM);
+ break;
+
+ case 0x4000:
+ prg8_cd(data);
+ break;
+
+ default:
+ break;
+ }
+}