summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nes/mmc5.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/nes/mmc5.cpp')
-rw-r--r--src/devices/bus/nes/mmc5.cpp127
1 files changed, 76 insertions, 51 deletions
diff --git a/src/devices/bus/nes/mmc5.cpp b/src/devices/bus/nes/mmc5.cpp
index 171af3c86e9..1b0bf30caf3 100644
--- a/src/devices/bus/nes/mmc5.cpp
+++ b/src/devices/bus/nes/mmc5.cpp
@@ -20,19 +20,21 @@
#include "speaker.h"
+#define LOG_UNHANDLED (1U << 1)
+#define LOG_BANK_INFO (1U << 2)
+
#ifdef NES_PCB_DEBUG
-#define VERBOSE 1
+#define VERBOSE (LOG_UNHANDLED | LOG_GENERAL)
#else
-#define VERBOSE 0
+#define VERBOSE (LOG_UNHANDLED)
#endif
-
-#define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
+#include "logmacro.h"
#define LAST_CHR_REG_A 0
#define LAST_CHR_REG_B 1
-static const int m_mmc5_attrib[4] = {0x00, 0x55, 0xaa, 0xff};
+static const uint8_t m_mmc5_attrib[4] = {0x00, 0x55, 0xaa, 0xff};
//-------------------------------------------------
// constructor
@@ -43,11 +45,11 @@ DEFINE_DEVICE_TYPE(NES_EXROM, nes_exrom_device, "nes_exrom", "NES Cart ExROM (MM
nes_exrom_device::nes_exrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_nrom_device(mconfig, NES_EXROM, tag, owner, clock), m_irq_count(0)
- , m_irq_status(0), m_irq_enable(0), m_mult1(0), m_mult2(0), m_mmc5_scanline(0), m_vrom_page_a(0), m_vrom_page_b(0), m_floodtile(0), m_floodattr(0)
+ , m_irq_status(0), m_irq_enable(false), m_pcm_irq(false), m_mult1(0), m_mult2(0), m_mmc5_scanline(0), m_vrom_page_a(0), m_vrom_page_b(0), m_floodtile(0), m_floodattr(0)
, m_prg_mode(0), m_chr_mode(0), m_wram_protect_1(0), m_wram_protect_2(0), m_exram_control(0), m_wram_base(0), m_last_chr(0), m_ex1_chr(0)
, m_split_chr(0), m_ex1_bank(0), m_ex1_attrib(0), m_high_chr(0), m_split_scr(0), m_split_rev(0), m_split_ctrl(0), m_split_yst(0), m_split_bank(0), m_vcount(0)
, m_ppu(*this, ":ppu") // FIXME: this dependency should not exist
- , m_sound(*this, "mmc5snd") // FIXME: this is a hack, it should be separated device, similar not same as NES APU!!!
+ , m_sound(*this, "mmc5snd")
{
}
@@ -62,6 +64,7 @@ void nes_exrom_device::device_start()
save_item(NAME(m_irq_count));
save_item(NAME(m_irq_status));
save_item(NAME(m_irq_enable));
+ save_item(NAME(m_pcm_irq));
save_item(NAME(m_mult1));
save_item(NAME(m_mult2));
save_item(NAME(m_vrom_page_a));
@@ -96,14 +99,14 @@ void nes_exrom_device::device_start()
void nes_exrom_device::pcb_reset()
{
- m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
prg16_89ab(m_prg_chunks - 2);
prg16_cdef(m_prg_chunks - 1);
chr8(0, m_chr_source);
m_irq_count = 0;
m_irq_status = 0;
- m_irq_enable = 0;
+ m_irq_enable = false;
+ m_pcm_irq = false;
m_mult1 = m_mult2 = 0;
m_vrom_page_a = m_vrom_page_b = 0;
@@ -159,7 +162,7 @@ void nes_exrom_device::pcb_reset()
iNES: mapper 5
- MESS status: Partially supported
+ MAME status: Partially supported
-------------------------------------------------*/
@@ -236,16 +239,20 @@ void nes_exrom_device::update_prg()
}
}
-void nes_exrom_device::hblank_irq(int scanline, int vblank, int blanked )
+void nes_exrom_device::update_irq()
+{
+ set_irq_line(((BIT(m_irq_status, 7) && m_irq_enable) || m_pcm_irq) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+void nes_exrom_device::hblank_irq(int scanline, bool vblank, bool blanked)
{
m_vcount = scanline;
if (scanline == m_irq_count)
{
- if (m_irq_enable)
- set_irq_line(ASSERT_LINE);
-
m_irq_status = 0xff;
+ update_irq();
}
// "In Frame" flag
@@ -256,6 +263,13 @@ void nes_exrom_device::hblank_irq(int scanline, int vblank, int blanked )
}
+void nes_exrom_device::pcm_irq(int state)
+{
+ m_pcm_irq = state;
+ update_irq();
+}
+
+
void nes_exrom_device::set_mirror(int page, int src)
{
switch (src)
@@ -279,7 +293,7 @@ void nes_exrom_device::set_mirror(int page, int src)
inline bool nes_exrom_device::in_split()
{
- int tile = m_ppu->get_tilenum();
+ int const tile = m_ppu->get_tilenum();
if (tile < 34)
{
@@ -293,7 +307,7 @@ inline bool nes_exrom_device::in_split()
uint8_t nes_exrom_device::nt_r(offs_t offset)
{
- int page = ((offset & 0xc00) >> 10);
+ int const page = ((offset & 0xc00) >> 10);
switch (m_nt_src[page])
{
@@ -315,16 +329,16 @@ uint8_t nes_exrom_device::nt_r(offs_t offset)
// but it does not work yet
if (m_split_scr && !(m_exram_control & 0x02) && in_split())
{
- int tile = m_ppu->get_tilenum();
+ int const tile = m_ppu->get_tilenum();
if ((offset & 0x3ff) >= 0x3c0)
{
- int pos = (((m_split_yst + m_vcount) & ~0x1f) | (tile & 0x1f)) >> 2;
+ int const pos = (((m_split_yst + m_vcount) & ~0x1f) | (tile & 0x1f)) >> 2;
return m_exram[0x3c0 | pos];
}
else
{
- int pos = (((m_split_yst + m_vcount) & 0xf8) << 2) | (tile & 0x1f);
+ int const pos = (((m_split_yst + m_vcount) & 0xf8) << 2) | (tile & 0x1f);
return m_exram[pos];
}
}
@@ -346,7 +360,7 @@ uint8_t nes_exrom_device::nt_r(offs_t offset)
void nes_exrom_device::nt_w(offs_t offset, uint8_t data)
{
- int page = ((offset & 0xc00) >> 10);
+ int const page = ((offset & 0xc00) >> 10);
if (!m_nt_writable[page])
return;
@@ -392,19 +406,19 @@ inline uint8_t nes_exrom_device::base_chr_r(int bank, uint32_t offset)
inline uint8_t nes_exrom_device::split_chr_r(uint32_t offset)
{
- uint32_t helper = (m_split_bank * 0x1000) + (offset & 0x3f8) + (m_split_yst & 7);
+ uint32_t const helper = (m_split_bank * 0x1000) + (offset & 0x3f8) + (m_split_yst & 7);
return m_vrom[helper & (m_vrom_size - 1)];
}
inline uint8_t nes_exrom_device::bg_ex1_chr_r(uint32_t offset)
{
- uint32_t helper = (m_ex1_bank * 0x1000) + (offset & 0xfff);
+ uint32_t const helper = (m_ex1_bank * 0x1000) + (offset & 0xfff);
return m_vrom[helper & (m_vrom_size - 1)];
}
uint8_t nes_exrom_device::chr_r(offs_t offset)
{
- int bank = offset >> 10;
+ int const bank = offset >> 10;
// Extended Attribute Mode (Ex1) does affect BG drawing even for 8x16 sprites (JustBreed uses it extensively!)
// However, if a game enables Ex1 but does not write a new m_ex1_bank, I'm not sure here we get the correct behavior
@@ -433,9 +447,12 @@ uint8_t nes_exrom_device::chr_r(offs_t offset)
uint8_t nes_exrom_device::read_l(offs_t offset)
{
int value;
- LOG_MMC(("exrom read_l, offset: %04x\n", offset));
+ LOG("exrom read_l, offset: %04x\n", offset);
offset += 0x100;
+ if ((offset >= 0x1000) && (offset <= 0x1015))
+ return m_sound->read(offset & 0x1f);
+
if ((offset >= 0x1c00) && (offset <= 0x1fff))
{
// EXRAM
@@ -452,7 +469,7 @@ uint8_t nes_exrom_device::read_l(offs_t offset)
if (!machine().side_effects_disabled())
{
m_irq_status &= ~0x80;
- set_irq_line(CLEAR_LINE);
+ update_irq();
}
return value;
@@ -464,7 +481,7 @@ uint8_t nes_exrom_device::read_l(offs_t offset)
default:
if (!machine().side_effects_disabled())
- logerror("MMC5 uncaught read, offset: %04x\n", offset + 0x4100);
+ LOGMASKED(LOG_UNHANDLED, "MMC5 uncaught read, offset: %04x\n", offset + 0x4100);
return get_open_bus();
}
}
@@ -472,7 +489,7 @@ uint8_t nes_exrom_device::read_l(offs_t offset)
void nes_exrom_device::write_l(offs_t offset, uint8_t data)
{
- LOG_MMC(("exrom write_l, offset: %04x, data: %02x\n", offset, data));
+ LOG("exrom write_l, offset: %04x, data: %02x\n", offset, data);
offset += 0x100;
if ((offset >= 0x1000) && (offset <= 0x1015))
@@ -488,7 +505,7 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
m_exram[offset - 0x1c00] = data;
else if (m_exram_control != 0x03) // Modes 0,1 = write data in frame / write 0 otherwise
{
- if (m_irq_status & 0x40)
+ if (BIT(m_irq_status, 6))
m_exram[offset - 0x1c00] = data;
else
m_exram[offset - 0x1c00] = 0x00;
@@ -502,29 +519,29 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
case 0x1100:
m_prg_mode = data & 0x03;
update_prg();
- //LOG_MMC(("MMC5 rom bank mode: %02x\n", data));
+ LOGMASKED(LOG_BANK_INFO, "MMC5 rom bank mode: %02x\n", data);
break;
case 0x1101:
m_chr_mode = data & 0x03;
m_ex1_chr = 0;
m_split_chr = 0;
- //LOG_MMC(("MMC5 vrom bank mode: %02x\n", data));
+ LOGMASKED(LOG_BANK_INFO, "MMC5 vrom bank mode: %02x\n", data);
break;
case 0x1102:
m_wram_protect_1 = data & 0x03;
- LOG_MMC(("MMC5 vram protect 1: %02x\n", data));
+ LOG("MMC5 vram protect 1: %02x\n", data);
break;
case 0x1103:
m_wram_protect_2 = data & 0x03;
- LOG_MMC(("MMC5 vram protect 2: %02x\n", data));
+ LOG("MMC5 vram protect 2: %02x\n", data);
break;
case 0x1104: // Extra VRAM (EXRAM)
m_exram_control = data & 0x03;
- LOG_MMC(("MMC5 exram control: %02x\n", data));
+ LOG("MMC5 exram control: %02x\n", data);
break;
case 0x1105:
@@ -543,7 +560,7 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
break;
case 0x1113:
- LOG_MMC(("MMC5 mid RAM bank select: %02x\n", data & 0x07));
+ LOG("MMC5 mid RAM bank select: %02x\n", data & 0x07);
m_wram_base = data & 0x07;
break;
@@ -604,12 +621,12 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
case 0x1203:
m_irq_count = data;
- LOG_MMC(("MMC5 irq scanline: %d\n", m_irq_count));
+ LOG("MMC5 irq scanline: %d\n", m_irq_count);
break;
case 0x1204:
- m_irq_enable = data & 0x80;
- LOG_MMC(("MMC5 irq enable: %02x\n", data));
+ m_irq_enable = BIT(data, 7);
+ LOG("MMC5 irq enable: %02x\n", data);
break;
case 0x1205:
@@ -621,7 +638,7 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
break;
default:
- logerror("MMC5 uncaught write, offset: %04x, data: %02x\n", offset + 0x4100, data);
+ LOG("MMC5 uncaught write, offset: %04x, data: %02x\n", offset + 0x4100, data);
break;
}
}
@@ -632,10 +649,10 @@ void nes_exrom_device::write_l(offs_t offset, uint8_t data)
// same mechanism is used also when "WRAM" is mapped in higher banks
uint8_t nes_exrom_device::read_m(offs_t offset)
{
- LOG_MMC(("exrom read_m, offset: %04x\n", offset));
+ LOG("exrom read_m, offset: %04x\n", offset);
if (!m_battery.empty() && !m_prgram.empty()) // 2 chips present: first is BWRAM, second is WRAM
{
- if (m_wram_base & 0x04)
+ if (BIT(m_wram_base, 2))
return m_prgram[(offset + (m_wram_base & 0x03) * 0x2000) & (m_prgram.size() - 1)];
else
return m_battery[(offset + (m_wram_base & 0x03) * 0x2000) & (m_battery.size() - 1)];
@@ -650,7 +667,7 @@ uint8_t nes_exrom_device::read_m(offs_t offset)
void nes_exrom_device::write_m(offs_t offset, uint8_t data)
{
- LOG_MMC(("exrom write_m, offset: %04x, data: %02x\n", offset, data));
+ LOG("exrom write_m, offset: %04x, data: %02x\n", offset, data);
if (m_wram_protect_1 != 0x02 || m_wram_protect_2 != 0x01)
return;
@@ -663,24 +680,31 @@ void nes_exrom_device::write_m(offs_t offset, uint8_t data)
// some games (e.g. Bandit Kings of Ancient China) write to PRG-RAM through 0x8000-0xdfff
uint8_t nes_exrom_device::read_h(offs_t offset)
{
- LOG_MMC(("exrom read_h, offset: %04x\n", offset));
- int bank = offset / 0x2000;
+ LOG("exrom read_h, offset: %04x\n", offset);
+ int const bank = offset / 0x2000;
+ uint8_t ret = 0;
if (bank < 3 && offset >= bank * 0x2000 && offset < (bank + 1) * 0x2000 && m_prg_ram_mapped[bank])
{
if (!m_battery.empty() && m_ram_hi_banks[bank] < 4)
- return m_battery[((m_ram_hi_banks[bank] * 0x2000) + (offset & 0x1fff)) & (m_battery.size() - 1)];
+ ret = m_battery[((m_ram_hi_banks[bank] * 0x2000) + (offset & 0x1fff)) & (m_battery.size() - 1)];
else if (!m_prgram.empty())
- return m_prgram[(((m_ram_hi_banks[bank] & 3) * 0x2000) + (offset & 0x1fff)) & (m_prgram.size() - 1)];
+ ret = m_prgram[(((m_ram_hi_banks[bank] & 3) * 0x2000) + (offset & 0x1fff)) & (m_prgram.size() - 1)];
}
-
- return hi_access_rom(offset);
+ else
+ ret = hi_access_rom(offset);
+ if (!machine().side_effects_disabled())
+ {
+ if (BIT(~offset, 14))
+ m_sound->pcm_w(ret);
+ }
+ return ret;
}
void nes_exrom_device::write_h(offs_t offset, uint8_t data)
{
- LOG_MMC(("exrom write_h, offset: %04x, data: %02x\n", offset, data));
- int bank = offset / 0x2000;
+ LOG("exrom write_h, offset: %04x, data: %02x\n", offset, data);
+ int const bank = offset / 0x2000;
if (m_wram_protect_1 != 0x02 || m_wram_protect_2 != 0x01 || bank == 3 || !m_prg_ram_mapped[bank])
return;
@@ -699,6 +723,7 @@ void nes_exrom_device::device_add_mconfig(machine_config &config)
// additional sound hardware
SPEAKER(config, "addon").front_center();
- // TODO: temporary; will be separated device
- NES_APU(config, m_sound, XTAL(21'477'272)/12).add_route(ALL_OUTPUTS, "addon", 0.90);
+ MMC5_SOUND(config, m_sound, XTAL(21'477'272)/12);
+ m_sound->irq().set(FUNC(nes_exrom_device::pcm_irq));
+ m_sound->add_route(ALL_OUTPUTS, "addon", 0.90);
}