summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes/kaiser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nes/kaiser.cpp')
-rw-r--r--src/devices/bus/nes/kaiser.cpp818
1 files changed, 547 insertions, 271 deletions
diff --git a/src/devices/bus/nes/kaiser.cpp b/src/devices/bus/nes/kaiser.cpp
index 52690376e4b..aaa5a247341 100644
--- a/src/devices/bus/nes/kaiser.cpp
+++ b/src/devices/bus/nes/kaiser.cpp
@@ -8,23 +8,22 @@
Here we emulate the following Kaiser bootleg PCBs
+ * Kaiser KS106C
* Kaiser KS202
+ * Kaiser KS7010
* Kaiser KS7012
* Kaiser KS7013B
+ * Kaiser KS7016
+ * Kaiser KS7016B
* Kaiser KS7017
+ * Kaiser KS7021A
* Kaiser KS7022
+ * Kaiser KS7030
+ * Kaiser KS7031
* Kaiser KS7032
- * Kaiser KS7058
- * Kaiser KS7016
* Kaiser KS7037
-
- The Kaiser KS7057 bootleg board is emulated in nes_mmc3_clones.cpp
-
-
- TODO:
- - FCEUmm lists more Kaiser PCBs:
- * KS7030 (for Yume Koujou Doki Doki Panic by Kaiser?)
- but there seem to be no available dumps...
+ * Kaiser KS7057
+ * Kaiser KS7058
***********************************************************************************************************/
@@ -32,100 +31,143 @@
#include "emu.h"
#include "kaiser.h"
+#define LOG_HIFREQ (1U << 1)
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (0)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
//-------------------------------------------------
// constructor
//-------------------------------------------------
-DEFINE_DEVICE_TYPE(NES_KS7058, nes_ks7058_device, "nes_ks7058", "NES Cart Kaiser KS-7058 PCB")
-DEFINE_DEVICE_TYPE(NES_KS7022, nes_ks7022_device, "nes_ks7022", "NES Cart Kaiser KS-7022 PCB")
-DEFINE_DEVICE_TYPE(NES_KS7032, nes_ks7032_device, "nes_ks7032", "NES Cart Kaiser KS-7032 PCB")
+DEFINE_DEVICE_TYPE(NES_KS106C, nes_ks106c_device, "nes_ks106c", "NES Cart Kaiser KS-106C PCB")
DEFINE_DEVICE_TYPE(NES_KS202, nes_ks202_device, "nes_ks202", "NES Cart Kaiser KS-202 PCB")
-DEFINE_DEVICE_TYPE(NES_KS7017, nes_ks7017_device, "nes_ks7017", "NES Cart Kaiser KS-7017 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7010, nes_ks7010_device, "nes_ks7010", "NES Cart Kaiser KS-7010 PCB")
DEFINE_DEVICE_TYPE(NES_KS7012, nes_ks7012_device, "nes_ks7012", "NES Cart Kaiser KS-7012 PCB")
DEFINE_DEVICE_TYPE(NES_KS7013B, nes_ks7013b_device, "nes_ks7013b", "NES Cart Kaiser KS-7013B PCB")
-DEFINE_DEVICE_TYPE(NES_KS7031, nes_ks7031_device, "nes_ks7031", "NES Cart Kaiser KS-7031 PCB")
DEFINE_DEVICE_TYPE(NES_KS7016, nes_ks7016_device, "nes_ks7016", "NES Cart Kaiser KS-7016 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7016B, nes_ks7016b_device, "nes_ks7016b", "NES Cart Kaiser KS-7016B PCB")
+DEFINE_DEVICE_TYPE(NES_KS7017, nes_ks7017_device, "nes_ks7017", "NES Cart Kaiser KS-7017 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7021A, nes_ks7021a_device, "nes_ks7021a", "NES Cart Kaiser KS-7021A PCB")
+DEFINE_DEVICE_TYPE(NES_KS7022, nes_ks7022_device, "nes_ks7022", "NES Cart Kaiser KS-7022 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7030, nes_ks7030_device, "nes_ks7030", "NES Cart Kaiser KS-7030 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7031, nes_ks7031_device, "nes_ks7031", "NES Cart Kaiser KS-7031 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7032, nes_ks7032_device, "nes_ks7032", "NES Cart Kaiser KS-7032 PCB")
DEFINE_DEVICE_TYPE(NES_KS7037, nes_ks7037_device, "nes_ks7037", "NES Cart Kaiser KS-7037 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7057, nes_ks7057_device, "nes_ks7057", "NES Cart Kaiser KS-7057 PCB")
+DEFINE_DEVICE_TYPE(NES_KS7058, nes_ks7058_device, "nes_ks7058", "NES Cart Kaiser KS-7058 PCB")
+
+nes_ks106c_device::nes_ks106c_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS106C, tag, owner, clock), m_latch(0)
+{
+}
-nes_ks7058_device::nes_ks7058_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7058_device::nes_ks7058_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7058, tag, owner, clock)
{
}
-nes_ks7022_device::nes_ks7022_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7022_device::nes_ks7022_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7022, tag, owner, clock), m_latch(0)
{
}
-nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_enable(0), irq_timer(nullptr)
+nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_count_latch(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7032_device::nes_ks7032_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_ks7032_device(mconfig, NES_KS7032, tag, owner, clock)
{
}
-nes_ks202_device::nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks202_device::nes_ks202_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_ks7032_device(mconfig, NES_KS202, tag, owner, clock)
{
}
-nes_ks7017_device::nes_ks7017_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7016_device::nes_ks7016_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 a15_flip)
+ : nes_nrom_device(mconfig, type, tag, owner, clock), m_latch(0), m_a15_flip(a15_flip)
+{
+}
+
+nes_ks7016_device::nes_ks7016_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_ks7016_device(mconfig, NES_KS7016, tag, owner, clock, 0x00)
+{
+}
+
+nes_ks7016b_device::nes_ks7016b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_ks7016_device(mconfig, NES_KS7016B, tag, owner, clock, 0x04)
+{
+}
+
+nes_ks7017_device::nes_ks7017_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7017, tag, owner, clock), m_latch(0), m_irq_count(0), m_irq_status(0), m_irq_enable(0), irq_timer(nullptr)
{
}
-nes_ks7012_device::nes_ks7012_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7021a_device::nes_ks7021a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7021A, tag, owner, clock)
+{
+}
+
+nes_ks7010_device::nes_ks7010_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7010, tag, owner, clock), m_latch(0)
+{
+}
+
+nes_ks7012_device::nes_ks7012_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7012, tag, owner, clock)
{
}
-nes_ks7013b_device::nes_ks7013b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7013b_device::nes_ks7013b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7013B, tag, owner, clock)
{
}
-nes_ks7031_device::nes_ks7031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+nes_ks7030_device::nes_ks7030_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7030, tag, owner, clock)
+{
+}
+
+nes_ks7031_device::nes_ks7031_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: nes_nrom_device(mconfig, NES_KS7031, tag, owner, clock)
{
}
-nes_ks7016_device::nes_ks7016_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_KS7016, tag, owner, clock)
+nes_ks7037_device::nes_ks7037_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7037, tag, owner, clock), m_reg(0)
{
}
-nes_ks7037_device::nes_ks7037_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : nes_nrom_device(mconfig, NES_KS7037, tag, owner, clock)
+nes_ks7057_device::nes_ks7057_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : nes_nrom_device(mconfig, NES_KS7057, tag, owner, clock)
{
}
-void nes_ks7058_device::device_start()
+void nes_ks106c_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
}
-void nes_ks7058_device::pcb_reset()
+void nes_ks106c_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0);
- chr8(0, m_chr_source);
+ prg32(m_latch);
+ chr8(m_latch, CHRROM);
+ set_nt_mirroring(BIT(m_latch, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ m_latch = (m_latch + 1) & 0x03;
}
void nes_ks7022_device::device_start()
@@ -136,7 +178,6 @@ void nes_ks7022_device::device_start()
void nes_ks7022_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);
@@ -147,33 +188,49 @@ void nes_ks7022_device::pcb_reset()
void nes_ks7032_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_ks7032_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_latch));
save_item(NAME(m_irq_enable));
save_item(NAME(m_irq_count));
+ save_item(NAME(m_irq_count_latch));
save_item(NAME(m_reg));
}
void nes_ks7032_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;
m_irq_enable = 0;
m_irq_count = 0;
- memset(m_reg, 0, sizeof(m_reg));
+ m_irq_count_latch = 0;
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
+
prg_update();
+ prg8_ef((m_prg_chunks << 1) - 1);
+ chr8(0, m_chr_source);
+}
+
+void nes_ks7016_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_latch));
+}
+
+void nes_ks7016_device::pcb_reset()
+{
+ prg8_89(0x0c ^ m_a15_flip);
+ prg8_ab(0x0d ^ m_a15_flip);
+ prg8_cd(0x0e ^ m_a15_flip);
+ prg8_ef(0x0f ^ m_a15_flip);
+
+ m_latch = 0;
}
void nes_ks7017_device::device_start()
{
common_start();
- irq_timer = timer_alloc(TIMER_IRQ);
+ irq_timer = timer_alloc(FUNC(nes_ks7017_device::irq_timer_tick), this);
irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1));
save_item(NAME(m_latch));
@@ -184,10 +241,8 @@ void nes_ks7017_device::device_start()
void nes_ks7017_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(0);
prg16_cdef(2);
- chr8(0, m_chr_source);
m_latch = 0;
m_irq_enable = 0;
@@ -195,82 +250,93 @@ void nes_ks7017_device::pcb_reset()
m_irq_status = 0;
}
-void nes_ks7012_device::device_start()
+void nes_ks7021a_device::pcb_reset()
+{
+ prg16_89ab(0);
+ prg16_cdef(m_prg_chunks - 1);
+ chr8(0, CHRROM);
+}
+
+void nes_ks7010_device::device_start()
{
common_start();
+ save_item(NAME(m_latch));
}
-void nes_ks7012_device::pcb_reset()
+void nes_ks7010_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
- prg32(0xff);
- chr8(0, m_chr_source);
+ prg16_89ab(0x05); // all upper banks are fixed
+ prg16_cdef(0x03);
+ chr8(0, CHRROM);
+
+ m_latch = 0;
}
-void nes_ks7013b_device::device_start()
+void nes_ks7012_device::pcb_reset()
{
- common_start();
+ prg32((m_prg_chunks >> 1) - 1);
}
void nes_ks7013b_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_ks7031_device::device_start()
+void nes_ks7030_device::device_start()
{
common_start();
save_item(NAME(m_reg));
}
-void nes_ks7031_device::pcb_reset()
+void nes_ks7030_device::pcb_reset()
{
- prg32(0); // not really used...
- chr8(0, CHRRAM);
+ prg32((m_prg_chunks >> 1) - 1); // not really used...
- m_reg[0] = 0;
- m_reg[1] = 0;
- m_reg[2] = 0;
- m_reg[3] = 0;
+ m_reg[0] = m_reg[1] = 0;
}
-void nes_ks7016_device::device_start()
+void nes_ks7031_device::device_start()
{
common_start();
save_item(NAME(m_reg));
}
-void nes_ks7016_device::pcb_reset()
+void nes_ks7031_device::pcb_reset()
{
- prg8_89(0xc);
- prg8_ab(0xd);
- prg8_cd(0xe);
- prg8_ef(0xf);
- chr8(0, CHRRAM);
+ prg32(0); // not really used...
- m_reg = 4;
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
}
void nes_ks7037_device::device_start()
{
common_start();
- save_item(NAME(m_latch));
save_item(NAME(m_reg));
}
void nes_ks7037_device::pcb_reset()
{
prg8_89(0);
- prg8_ab(0x1e);
+ prg8_ab(0x0e);
prg8_cd(0);
- prg8_ef(0x1f);
- chr8(0, CHRRAM);
+ prg8_ef(0x0f);
- memset(m_reg, 0, sizeof(m_reg));
- m_latch = 0;
+ m_reg = 0;
+}
+
+void nes_ks7057_device::device_start()
+{
+ common_start();
+ save_item(NAME(m_reg));
+}
+
+void nes_ks7057_device::pcb_reset()
+{
+ prg8_ab(0x0d);
+ prg16_cdef(0x07);
+
+ std::fill(std::begin(m_reg), std::end(m_reg), 0x00);
}
@@ -281,6 +347,21 @@ void nes_ks7037_device::pcb_reset()
/*-------------------------------------------------
+ Kaiser Board KS106C
+
+ Games: 4 in 1
+
+ No need to use handlers. At reset the banks change
+ and so does the game.
+
+ NES 2.0: mapper 352
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+/*-------------------------------------------------
+
Kaiser Board KS7058
Games: Tui Do Woo Ma Jeung
@@ -291,13 +372,13 @@ void nes_ks7037_device::pcb_reset()
iNES: mapper 171
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7058_device::write_h(offs_t offset, uint8_t data)
+void nes_ks7058_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7058 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7058 write_h, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7080)
{
@@ -318,24 +399,23 @@ void nes_ks7058_device::write_h(offs_t offset, uint8_t data)
iNES: mapper 175
- In MESS: Supported?
+ In MAME: Supported?
-------------------------------------------------*/
-void nes_ks7022_device::write_h(offs_t offset, uint8_t data)
+void nes_ks7022_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7022 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7022 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset == 0)
set_nt_mirroring(BIT(data, 2) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
-
- if (offset == 0x2000)
+ else if (offset == 0x2000)
m_latch = data & 0x0f;
}
-uint8_t nes_ks7022_device::read_h(offs_t offset)
+u8 nes_ks7022_device::read_h(offs_t offset)
{
- LOG_MMC(("ks7022 read_h, offset: %04x\n", offset));
+ LOG("ks7022 read_h, offset: %04x\n", offset);
if (offset == 0x7ffc)
{
@@ -351,32 +431,27 @@ uint8_t nes_ks7022_device::read_h(offs_t offset)
Kaiser Board KS7032
- Games: A few FDS conversions like Bubble Bobble
- or SMB2
+ Games: FDS conversions of Bubble Bobble, SMB2,
+ and Exciting Soccer
- iNES:
+ These boards have a KS202 ASIC that provide both
+ banking and a cycle-based IRQ similar to the VRC3.
- TODO: available dumps do not seem to use WRAM...
- yet m_reg[4] should switch WRAM bank... investigate!
+ iNES: mapper 142
- In MESS: Supported?
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7032_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_ks7032_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ if (++m_irq_count == 0)
{
- if (m_irq_count == 0xffff)
- {
- m_irq_enable = 0;
- m_irq_count = 0;
- hold_irq_line();
- }
- else
- m_irq_count++;
+ set_irq_line(ASSERT_LINE);
+ m_irq_enable = 0;
+ m_irq_count = m_irq_count_latch;
}
}
}
@@ -388,85 +463,137 @@ void nes_ks7032_device::prg_update()
prg8_cd(m_reg[3]);
}
-void nes_ks7032_device::ks7032_write(offs_t offset, uint8_t data)
+void nes_ks7032_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7032_write, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7032_write, offset: %04x, data: %02x\n", offset, data);
switch (offset & 0x7000)
{
case 0x0000:
- m_irq_count = (m_irq_count & 0xfff0) | (data & 0x0f);
- break;
case 0x1000:
- m_irq_count = (m_irq_count & 0xff0f) | ((data & 0x0f) << 4);
- break;
case 0x2000:
- m_irq_count = (m_irq_count & 0xf0ff) | ((data & 0x0f) << 8);
- break;
case 0x3000:
- m_irq_count = (m_irq_count & 0x0fff) | ((data & 0x0f) << 12);
+ {
+ int shift = 4 * BIT(offset, 12, 2);
+ m_irq_count_latch &= ~(0x000f << shift);
+ m_irq_count_latch |= (data & 0x0f) << shift;
break;
+ }
case 0x4000:
- m_irq_enable = 1;
+ m_irq_enable = BIT(data, 1);
+ if (m_irq_enable)
+ m_irq_count = m_irq_count_latch;
+ set_irq_line(CLEAR_LINE);
+ break;
+ case 0x5000:
+ set_irq_line(CLEAR_LINE);
break;
case 0x6000:
m_latch = data & 0x07;
break;
case 0x7000:
- m_reg[m_latch] = data;
+ m_reg[m_latch] = (m_reg[m_latch] & 0xf0) | (data & 0x0f);
prg_update();
break;
}
}
-uint8_t nes_ks7032_device::read_m(offs_t offset)
+u8 nes_ks7032_device::read_m(offs_t offset)
{
- LOG_MMC(("ks7032 read_m, offset: %04x\n", offset));
- return m_prg[((m_reg[4] * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)];
+ LOG("ks7032 read_m, offset: %04x\n", offset);
+ return m_prg[(m_reg[4] * 0x2000 + offset) & (m_prg_size - 1)];
}
/*-------------------------------------------------
- Kaiser Board KS202
+ Kaiser SMB3 Board with KS202
Games: Super Mario Bros. 3 (Pirate, Alt)
- iNES:
+ A chip, PAL16L8ANC, provides the extra bits overlaid
+ at 0xf000-0xffff. Writes go to both it and the KS202.
- In MESS: Supported?
+ iNES: mapper 56
- -------------------------------------------------*/
+ In MAME: Supported.
+
+ TODO: This device needs renaming of some sort. KS202
+ is a chip found on some Kaiser PCBs that actually
+ provides the functionality implemented above in the
+ KS7032 PCB. It's not clear what SMB3's PCB is.
+ -------------------------------------------------*/
-void nes_ks202_device::write_h(offs_t offset, uint8_t data)
+void nes_ks202_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks202 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks202 write_h, offset: %04x, data: %02x\n", offset, data);
- switch (offset & 0x7000)
+ if (offset >= 0x7000)
{
- case 0x7000:
- m_reg[m_latch] = data;
- prg_update();
- switch (offset & 0xc00)
- {
- case 0x800:
- set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
- break;
- case 0xc00:
- chr1_x(offset & 0x07, data, CHRROM);
- break;
- }
- break;
- default:
- ks7032_write(offset, data);
- break;
+ switch (offset & 0xc00)
+ {
+ case 0x000:
+ if ((offset & 3) == 3)
+ prg8_ef((data & 0x10) | 0x0f);
+ else
+ {
+ int reg = (offset & 3) + 1;
+ m_reg[reg] = (m_reg[reg] & 0x0f) | (data & 0x10);
+ }
+ break;
+ case 0x800:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ break;
+ case 0xc00:
+ chr1_x(offset & 0x07, data & 0x7f, CHRROM);
+ break;
+ }
}
+
+ nes_ks7032_device::write_h(offset, data);
}
-uint8_t nes_ks202_device::read_m(offs_t offset)
+u8 nes_ks202_device::read_m(offs_t offset)
{
- LOG_MMC(("ks202 read_m, offset: %04x\n", offset));
- return m_prgram[offset & 0x1fff];
+ return device_nes_cart_interface::read_m(offset);
+}
+
+/*-------------------------------------------------
+
+ Kaiser Boards KS7016, KS7016B
+
+ Games: Exciting Basket, Meikyuu Jiin Dababa FDS Conversions
+
+ These two variants have fixed upper 32K PRG and switchable
+ 8K PRG at 0x6000-0x7fff. The only difference appears to be
+ a flipped bit in the bank numbers. KS7016 puts banks 0x0c
+ through 0x0f in the upper PRG; KS7016B uses 0x08 to 0x0b.
+ For the switchable 8K PRG the latched bank # patterns are:
+
+ KS7016: 0 1 2 3 4 5 6 7 8 9 A B 8 9 A B
+ KS7016B: 0 1 2 3 4 5 6 7 C D E F C D E F
+
+ (NB: only KS7016B has been verified against PCB, KS7016 is a surmise.)
+
+ NES 2.0: mapper 306, mapper 549
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_ks7016_device::read_m(offs_t offset)
+{
+ LOGMASKED(LOG_HIFREQ, "ks7016 read_m, offset: %04x\n", offset);
+ return m_prg[(m_latch * 0x2000 + offset) & (m_prg_size - 1)];
+}
+
+void nes_ks7016_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ks7016 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ m_latch = BIT(offset, 2, 4);
+ if (m_latch & 0x08)
+ m_latch = (m_latch & 0x0b) | m_a15_flip;
}
/*-------------------------------------------------
@@ -475,74 +602,147 @@ uint8_t nes_ks202_device::read_m(offs_t offset)
Games: Almana no Kiseki FDS conversion
- iNES:
+ NES 2.0: mapper 303
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7017_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(nes_ks7017_device::irq_timer_tick)
{
- if (id == TIMER_IRQ)
+ if (m_irq_enable)
{
- if (m_irq_enable)
+ if (--m_irq_count == 0)
{
- if (!m_irq_count)
- {
- hold_irq_line();
- m_irq_enable = 0;
- m_irq_status |= 0x01;
- }
- else
- m_irq_count--;
+ set_irq_line(ASSERT_LINE);
+ m_irq_enable = 0;
+ m_irq_status |= 0x01;
}
}
}
-void nes_ks7017_device::write_l(offs_t offset, uint8_t data)
+void nes_ks7017_device::write_l(offs_t offset, u8 data)
{
- LOG_MMC(("ks7017 write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7017 write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
-
- if (offset >= 0xa00 && offset < 0xb00)
- m_latch = ((offset >> 2) & 0x03) | ((offset >> 4) & 0x04);
-
- if (offset >= 0x1100 && offset < 0x1200)
- prg16_89ab(m_latch);
+ switch (offset & 0x1f00)
+ {
+ case 0x0a00:
+ m_latch = bitswap<3>(offset, 6, 3, 2);
+ break;
+ case 0x1100:
+ prg16_89ab(m_latch);
+ break;
+ }
}
-void nes_ks7017_device::write_ex(offs_t offset, uint8_t data)
+void nes_ks7017_device::write_ex(offs_t offset, u8 data)
{
- LOG_MMC(("ks7017 write_ex, offset: %04x, data: %02x\n", offset, data));
- offset += 0x20;
+ LOG("ks7017 write_ex, offset: %04x, data: %02x\n", offset, data);
- if (offset == 0x0020) // 0x4020
- m_irq_count = (m_irq_count & 0xff00) | data;
-
- if (offset == 0x0021) // 0x4021
+ offset += 0x4020;
+ switch (offset)
{
- m_irq_count = (m_irq_count & 0x00ff) | (data << 8);
- m_irq_enable = 1;
+ case 0x4020:
+ m_irq_count = (m_irq_count & 0xff00) | data;
+ break;
+ case 0x4021:
+ m_irq_count = (m_irq_count & 0x00ff) | (data << 8);
+ m_irq_enable = 1;
+ break;
+ case 0x4025:
+ set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
}
-
- if (offset == 0x0025) // 0x4025
- set_nt_mirroring(BIT(data, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-uint8_t nes_ks7017_device::read_ex(offs_t offset)
+u8 nes_ks7017_device::read_ex(offs_t offset)
{
- LOG_MMC(("ks7017 read_ex, offset: %04x\n", offset));
- offset += 0x20;
+ LOG("ks7017 read_ex, offset: %04x\n", offset);
- if (offset == 0x0030) // 0x4030
+ offset += 0x4020;
+ if (offset == 0x4030)
{
int temp = m_irq_status;
m_irq_status &= ~0x01;
+ set_irq_line(CLEAR_LINE);
return temp;
}
- return get_open_bus(); // open bus
+ return get_open_bus();
+}
+
+/*-------------------------------------------------
+
+ Kaiser Board KS7021A
+
+ Games: GetsuFumaDen
+
+ This board has a 16K fixed PRG bank at 0xc000 and
+ a swappable 16K PRG bank at 0x8000. CHR banks are
+ selectable by 1K page.
+
+ NES 2.0: mapper 525
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+void nes_ks7021a_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ks7021a write_h, offset: %04x, data: %02x\n", offset, data);
+
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ prg16_89ab(BIT(data, 1, 3));
+ break;
+ case 0x1000:
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ break;
+ case 0x3000:
+ chr1_x(offset & 0x07, data & 0x7f, CHRROM);
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Kaiser Board KS7010
+
+ Games: Akumajo Dracula FDS Conversion
+
+ This board has fixed PRG banks in 0x8000-0xffff.
+ 0x6000-0x7fff is an 8K swappable PRG bank. This bank
+ and the CHR bank are BOTH set by the same latch.
+ Moreover, the latch is set by READING certain
+ addresses and the exact mask is still unknown...
+
+ NES 2.0: mapper 554
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_ks7010_device::read_m(offs_t offset)
+{
+ u8 data = m_prg[(m_latch * 0x2000 + offset) & (m_prg_size - 1)];
+ LOGMASKED(LOG_HIFREQ, "ks7010 read_m, offset: %04x, data: %02x\n", offset, data);
+ return data;
+}
+
+u8 nes_ks7010_device::read_h(offs_t offset)
+{
+ if ((offset >= 0x4ab6 && offset <= 0x4ad6) || offset == 0x6be2 || offset == 0x6be3 || offset == 0x6e32 || offset == 0x7ffc) // HACK! FIXME
+ {
+ m_latch = BIT(offset, 2, 4);
+ chr8(m_latch, CHRROM);
+ }
+
+ u8 data = hi_access_rom(offset);
+ LOGMASKED(LOG_HIFREQ, "ks7010 read_h, offset: %04x, data: %02x\n", offset, data);
+ return data;
}
/*-------------------------------------------------
@@ -551,15 +751,15 @@ uint8_t nes_ks7017_device::read_ex(offs_t offset)
Games: Zanac FDS Conversion
- iNES:
+ NES 2.0: mapper 346
- In MESS: Not working
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7012_device::write_h(offs_t offset, uint8_t data)
+void nes_ks7012_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7012 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7012 write_h, offset: %04x, data: %02x\n", offset, data);
if (offset == 0x60a0)
prg32(0);
@@ -567,101 +767,138 @@ void nes_ks7012_device::write_h(offs_t offset, uint8_t data)
prg32(1);
}
-
/*-------------------------------------------------
Kaiser Board KS7013B
- Games: Highway Star FDS Conversion
+ Games: Highway Star bootleg
- iNES:
+ NES 2.0: mapper 312
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7013b_device::write_m(offs_t offset, uint8_t data)
+void nes_ks7013b_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("ks7013b write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7013b write_l, offset: %04x, data: %02x\n", offset, data);
prg16_89ab(data);
}
-void nes_ks7013b_device::write_h(offs_t offset, uint8_t data)
+void nes_ks7013b_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7013b write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7013b write_h, offset: %04x, data: %02x\n", offset, data);
set_nt_mirroring((data & 1) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
}
-
/*-------------------------------------------------
- Kaiser Board KS7031
+ Kaiser Board KS7030
- Games: Dracula II FDS Conversion
+ Games: Doki Doki Panic (FDS conversion)
- This board is quite weird. It handles 2K PRG chunks
- and the chip contains chunks in reverse order, so
- that the first 2K are actually loaded at the top
- of the 0x8000-0xffff region. Main bank is fixed, while
- the 8K mapped at 0x6000-0x7fff varies with reg writes.
+ This board has a complicated memory layout. The last
+ 32k of the mask ROM is fixed into 0x8000-0xffff, but
+ 8k of WRAM and 8k of bankable PRG (in two 4k banks)
+ are adjacent and overlaid. The ranges are as follows.
+
+ WRAM: PRG:
+ - 3k, 0x6000-0x6bff - 1k, 0x6c00-0x6fff (reg 1, last 1k)
+ - 2k, 0xb800-0xbfff - 4k, 0x7000-0x7fff (reg 0)
+ - 3k, 0xcc00-0xd7ff - 3k, 0xc000-0xcc00 (reg 1, initial 3k)
- TODO: understand how SRAM is handled...
+ The two registers latch part of the address in writes
+ to 0x8000-0x8fff and 0x9000-0x9fff respectively.
- iNES:
+ NES 2.0: mapper 347
- In MESS: Supported.
+ In MAME: Supported.
-------------------------------------------------*/
-uint8_t nes_ks7031_device::read_m(offs_t offset)
+u8 nes_ks7030_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7031 read_m, offset: %04x\n", offset));
- return m_prg[(m_reg[(offset >> 11) & 3] * 0x0800) + (offset & 0x7ff)];
+ LOGMASKED(LOG_HIFREQ, "ks7030 read_m, offset: %04x\n", offset);
+ if (offset < 0x0c00) // first of 3k WRAM
+ return m_prgram[offset];
+ else if (offset < 0x1000) // last 1k of 4k PRG bank
+ return m_prg[m_reg[1] * 0x1000 + offset];
+ else // 4k PRG
+ return m_prg[0x10000 + m_reg[0] * 0x1000 + (offset & 0x0fff)];
}
-uint8_t nes_ks7031_device::read_h(offs_t offset)
+void nes_ks7030_device::write_m(offs_t offset, u8 data)
{
- // here the first 32K are accessed, but in 16x2K blocks loaded in reverse order
- int accessed_2k = (offset >> 11) & 0x0f;
- return m_prg[((0x0f - accessed_2k) * 0x0800) + (offset & 0x7ff)];
+ LOG("ks7030 write_m, offset: %04x\n", offset);
+ if (offset < 0x0c00) // first 3k of WRAM
+ m_prgram[offset] = data;
}
-void nes_ks7031_device::write_h(offs_t offset, uint8_t data)
+u8 nes_ks7030_device::read_h(offs_t offset)
{
- LOG_MMC(("ks7031 write_h, offset: %04x, data: %02x\n", offset, data));
- m_reg[(offset >> 11) & 3] = data & 0x3f;
+ LOGMASKED(LOG_HIFREQ, "ks7030 read_h, offset: %04x\n", offset);
+ if (offset < 0x3800 || offset >= 0x5800) // fixed 32k PRG, split 14k and 10k windows
+ return m_prg[0x18000 + (offset & 0x7fff)];
+ else if (offset < 0x4000) // middle 2k of WRAM
+ return m_prgram[offset - 0x2c00];
+ else if (offset < 0x4c00) // first 3k of 4k PRG bank
+ return m_prg[m_reg[1] * 0x1000 + (offset & 0x0fff)];
+ else // last 3k of WRAM
+ return m_prgram[offset - 0x3800];
}
-
+void nes_ks7030_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ks7030 write_h, offset: %04x\n", offset);
+ if (offset < 0x1000)
+ {
+ set_nt_mirroring(BIT(offset, 3) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
+ m_reg[0] = offset & 0x07;
+ }
+ else if (offset < 0x2000)
+ m_reg[1] = offset & 0x0f;
+ else if (offset >= 0x3800 && offset < 0x4000) // middle 2k of WRAM
+ m_prgram[offset - 0x2c00] = data;
+ else if (offset >= 0x4c00 && offset < 0x5800) // last 3k of WRAM
+ m_prgram[offset - 0x3800] = data;
+}
/*-------------------------------------------------
- Kaiser Board KS7016
+ Kaiser Board KS7031
- Games: Exciting Basket FDS Conversion
+ Games: Dracula II FDS Conversion
+
+ This board is quite weird. It handles 2K PRG chunks
+ and the chip contains chunks in reverse order, so
+ that the first 2K are actually loaded at the top
+ of the 0x8000-0xffff region. Main bank is fixed, while
+ the 8K mapped at 0x6000-0x7fff varies with reg writes.
- iNES:
+ NES 2.0: mapper 305
- In MESS: Unsupported.
+ In MAME: Supported.
-------------------------------------------------*/
-uint8_t nes_ks7016_device::read_m(offs_t offset)
+u8 nes_ks7031_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7016 read_m, offset: %04x\n", offset));
- return m_prg[((m_reg * 0x2000) + (offset & 0x1fff)) & (m_prg_size - 1)];
+ LOGMASKED(LOG_HIFREQ, "ks7031 read_m, offset: %04x\n", offset);
+ return m_prg[(m_reg[BIT(offset, 11, 2)] * 0x0800) + (offset & 0x7ff)];
}
-void nes_ks7016_device::write_h(offs_t offset, uint8_t data)
+u8 nes_ks7031_device::read_h(offs_t offset)
{
- LOG_MMC(("ks7016 write_h, offset: %04x, data: %02x\n", offset, data));
- uint8_t mask = offset & 0x30;
- if ((offset & 0x5943) == 0x5943)
- m_reg = (mask == 0x30) ? 0xb : (((offset >> 2) & 0x0f) << 1);
- if ((offset & 0x5943) == 0x5903)
- m_reg = (mask != 0x30) ? 0xb : (((offset >> 2) & 0x0f) << 1);
+ // here the first 32K are accessed, but in 16x2K blocks loaded in reverse order
+ int accessed_2k = BIT(~offset, 11, 4);
+ return m_prg[accessed_2k * 0x0800 + (offset & 0x7ff)];
}
+void nes_ks7031_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ks7031 write_h, offset: %04x, data: %02x\n", offset, data);
+ m_reg[BIT(offset, 11, 2)] = data & 0x3f;
+}
/*-------------------------------------------------
@@ -674,43 +911,31 @@ void nes_ks7016_device::write_h(offs_t offset, uint8_t data)
but with WRAM split between 0x6000-0x6fff
and 0xb000-0xbfff.
- iNES:
+ NES 2.0: mapper 307
- In MESS: Unsupported.
+ In MAME: Supported.
-------------------------------------------------*/
-void nes_ks7037_device::update_prg()
-{
- prg8_89(m_reg[6]);
- prg8_ab(0xfe);
- prg8_cd(m_reg[7]);
- prg8_ef(0xff);
- set_nt_page(0, CIRAM, m_reg[2] & 1, 1);
- set_nt_page(1, CIRAM, m_reg[3] & 1, 1);
- set_nt_page(2, CIRAM, m_reg[4] & 1, 1);
- set_nt_page(3, CIRAM, m_reg[5] & 1, 1);
-}
-
-uint8_t nes_ks7037_device::read_m(offs_t offset)
+u8 nes_ks7037_device::read_m(offs_t offset)
{
-// LOG_MMC(("ks7037 read_m, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "ks7037 read_m, offset: %04x\n", offset);
if (offset < 0x1000)
- return m_prgram[offset & 0x0fff];
+ return m_prgram[offset];
else
- return m_prg[(0x1e * 0x1000) + (offset & 0x0fff)];
+ return m_prg[0x0f * 0x1000 + (offset & 0x0fff)]; // 4k PRG bank 15 is fixed
}
-void nes_ks7037_device::write_m(offs_t offset, uint8_t data)
+void nes_ks7037_device::write_m(offs_t offset, u8 data)
{
- LOG_MMC(("ks7037 write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7037 write_m, offset: %04x, data: %02x\n", offset, data);
if (offset < 0x1000)
- m_prgram[offset & 0x0fff] = data;
+ m_prgram[offset] = data;
}
-uint8_t nes_ks7037_device::read_h(offs_t offset)
+u8 nes_ks7037_device::read_h(offs_t offset)
{
-// LOG_MMC(("ks7037 read_h, offset: %04x\n", offset));
+ LOGMASKED(LOG_HIFREQ, "ks7037 read_h, offset: %04x\n", offset);
if (offset >= 0x3000 && offset < 0x4000)
return m_prgram[0x1000 + (offset & 0x0fff)];
@@ -718,23 +943,74 @@ uint8_t nes_ks7037_device::read_h(offs_t offset)
return hi_access_rom(offset);
}
-void nes_ks7037_device::write_h(offs_t offset, uint8_t data)
+void nes_ks7037_device::write_h(offs_t offset, u8 data)
{
- LOG_MMC(("ks7037 write_h, offset: %04x, data: %02x\n", offset, data));
+ LOG("ks7037 write_h, offset: %04x, data: %02x\n", offset, data);
- if (offset >= 0x3000 && offset < 0x4000)
- m_prgram[0x1000 + (offset & 0x0fff)] = data;
- else
+ switch (offset & 0x7000)
{
- switch (offset & 0x6001)
- {
- case 0x0000:
- m_latch = data & 7;
- break;
- case 0x0001:
- m_reg[m_latch] = data;
- update_prg();
- break;
- }
+ case 0x0000:
+ case 0x1000:
+ if (!(offset & 1))
+ m_reg = data & 7;
+ else if (m_reg >= 6)
+ prg8_x((m_reg & 1) << 1, data);
+ else if (m_reg >= 2)
+ set_nt_page(bitswap<2>(m_reg, 0, 2), CIRAM, data & 1, 1);
+ break;
+ case 0x3000:
+ m_prgram[0x1000 + (offset & 0x0fff)] = data;
+ break;
+ }
+}
+
+/*-------------------------------------------------
+
+ Kaiser Board KS7057
+
+ Games: Gyruss
+
+ This PCB has fixed banks after 0xa000 and 8x2K
+ swappable banks in 0x6000-0x9fff. Pairs of nibble
+ registers (we store joined as bytes) control the banks,
+ with $B000/$B001, $B002/$B003, $C000/$C001, $C002/$C003
+ selecting 4 banks in 0x8000-0x9fff, and $D000/$D001,
+ $D002/$D003, $E000/$E001, $E002/$E003 selecting the
+ remaining 4 banks in 0x6000-0x7fff.
+
+ NES 2.0: mapper 302
+
+ In MAME: Supported.
+
+ -------------------------------------------------*/
+
+u8 nes_ks7057_device::read_m(offs_t offset)
+{
+ LOG("ks7057 read_m, offset: %04x\n", offset);
+ return m_prg[0x800 * m_reg[BIT(offset, 11, 2) + 4] + (offset & 0x7ff)];
+}
+
+u8 nes_ks7057_device::read_h(offs_t offset)
+{
+ LOGMASKED(LOG_HIFREQ, "ks7057 read_h, offset: %04x\n", offset);
+ if (offset < 0x2000)
+ return m_prg[0x800 * m_reg[BIT(offset, 11, 2)] + (offset & 0x7ff)];
+
+ return hi_access_rom(offset);
+}
+
+void nes_ks7057_device::write_h(offs_t offset, u8 data)
+{
+ LOG("ks7057 write_h, offset: %04x, data: %02x\n", offset, data);
+
+ if (offset < 0x2000)
+ set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_VERT : PPU_MIRROR_HORZ);
+ else if (offset >= 0x3000 && offset < 0x6004)
+ {
+ u8 reg = bitswap<4>(offset, 14, 13, 12, 1) - 6;
+ if (BIT(offset, 0))
+ m_reg[reg] = (m_reg[reg] & 0x0f) | ((data & 0x03) << 4);
+ else
+ m_reg[reg] = (m_reg[reg] & 0xf0) | (data & 0x0f);
}
}