diff options
Diffstat (limited to 'src/devices/bus/nes/sunsoft.cpp')
-rw-r--r-- | src/devices/bus/nes/sunsoft.cpp | 229 |
1 files changed, 72 insertions, 157 deletions
diff --git a/src/devices/bus/nes/sunsoft.cpp b/src/devices/bus/nes/sunsoft.cpp index be90e36e535..14ea2ea83c2 100644 --- a/src/devices/bus/nes/sunsoft.cpp +++ b/src/devices/bus/nes/sunsoft.cpp @@ -16,7 +16,7 @@ * Sunsoft-5B [mapper 69] TODO: - - check 1-line glitches due to IRQ in Sunsoft-3 + - 1-line glitches in Fantasy Zone II (Sunsoft-3) seem to be PPU timing related. The cycle-based IRQ timer below "should" be ok. ***********************************************************************************************************/ @@ -27,14 +27,14 @@ #include "sound/ay8910.h" #include "speaker.h" +#define LOG_UNHANDLED (1U << 1) #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" //------------------------------------------------- @@ -64,12 +64,12 @@ nes_sunsoft_3_device::nes_sunsoft_3_device(const machine_config &mconfig, const { } -nes_sunsoft_4_device::nes_sunsoft_4_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_reg(0), m_latch1(0), m_latch2(0), m_wram_enable(0) +nes_sunsoft_4_device::nes_sunsoft_4_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_wram_enable(0) { } -nes_sunsoft_4_device::nes_sunsoft_4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) +nes_sunsoft_4_device::nes_sunsoft_4_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : nes_sunsoft_4_device(mconfig, NES_SUNSOFT_4, tag, owner, clock) { } @@ -91,27 +91,15 @@ nes_sunsoft_5_device::nes_sunsoft_5_device(const machine_config &mconfig, const } -void nes_sunsoft_1_device::device_start() -{ - common_start(); -} - void nes_sunsoft_1_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_sunsoft_2_device::device_start() -{ - common_start(); -} - void nes_sunsoft_2_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); @@ -122,7 +110,7 @@ void nes_sunsoft_2_device::pcb_reset() void nes_sunsoft_3_device::device_start() { common_start(); - irq_timer = timer_alloc(TIMER_IRQ); + irq_timer = timer_alloc(FUNC(nes_sunsoft_3_device::irq_timer_tick), this); irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); save_item(NAME(m_irq_enable)); @@ -132,10 +120,10 @@ void nes_sunsoft_3_device::device_start() void nes_sunsoft_3_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_toggle = 0; m_irq_count = 0; m_irq_enable = 0; @@ -144,32 +132,25 @@ void nes_sunsoft_3_device::pcb_reset() void nes_sunsoft_4_device::device_start() { common_start(); - save_item(NAME(m_latch1)); - save_item(NAME(m_latch2)); save_item(NAME(m_reg)); save_item(NAME(m_wram_enable)); } void nes_sunsoft_4_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_reg = 0; - m_latch1 = 0; - m_latch2 = 0; + m_reg[0] = m_reg[1] = m_reg[2] = 0; m_wram_enable = 0; } void nes_sunsoft_fme7_device::device_start() { common_start(); - irq_timer = timer_alloc(TIMER_IRQ); - // this has to be hardcoded because some some scanline code only suits NTSC... it will be fixed with PPU rewrite - irq_timer->adjust(attotime::zero, 0, attotime::from_hz((21477272.724 / 12))); -// irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); + irq_timer = timer_alloc(FUNC(nes_sunsoft_fme7_device::irq_timer_tick), this); + irq_timer->adjust(attotime::zero, 0, clocks_to_attotime(1)); save_item(NAME(m_wram_bank)); save_item(NAME(m_latch)); @@ -179,7 +160,6 @@ void nes_sunsoft_fme7_device::device_start() void nes_sunsoft_fme7_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); @@ -211,7 +191,7 @@ void nes_sunsoft_fme7_device::pcb_reset() void nes_sunsoft_1_device::write_m(offs_t offset, uint8_t data) { - LOG_MMC(("Sunsoft 1 write_m, offset: %04x, data: %02x\n", offset, data)); + LOG("Sunsoft 1 write_m, offset: %04x, data: %02x\n", offset, data); if (m_vrom_chunks) { @@ -238,7 +218,7 @@ void nes_sunsoft_1_device::write_m(offs_t offset, uint8_t data) void nes_sunsoft_2_device::write_h(offs_t offset, uint8_t data) { uint8_t helper = (data & 0x07) | ((data & 0x80) ? 0x08 : 0x00); - LOG_MMC(("Sunsoft 2 write_h, offset: %04x, data: %02x\n", offset, data)); + LOG("Sunsoft 2 write_h, offset: %04x, data: %02x\n", offset, data); // this pcb is subject to bus conflict data = account_bus_conflict(offset, data); @@ -256,51 +236,33 @@ void nes_sunsoft_2_device::write_h(offs_t offset, uint8_t data) Sunsoft-3 board emulation - The two games using this board have incompatible mirroring - wiring, making necessary two distinct mappers & pcb_id + Games: Fantasy Zone II, Mito Koumon II - Sekai Manyuki iNES: mapper 67 -------------------------------------------------*/ - -void nes_sunsoft_3_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nes_sunsoft_3_device::irq_timer_tick) { - if (id == TIMER_IRQ) + if (m_irq_enable && --m_irq_count == 0xffff) { - if (m_irq_enable) - { - if (!m_irq_count) - { - set_irq_line(ASSERT_LINE); - m_irq_count = 0xffff; - m_irq_enable = 0; - } - else - m_irq_count--; - } + set_irq_line(ASSERT_LINE); + m_irq_enable = 0; } } void nes_sunsoft_3_device::write_h(offs_t offset, uint8_t data) { - LOG_MMC(("Sunsoft 3 write_h, offset %04x, data: %02x\n", offset, data)); + LOG("Sunsoft 3 write_h, offset %04x, data: %02x\n", offset, data); switch (offset & 0x7800) { case 0x0800: - chr2_0(data, CHRROM); - break; case 0x1800: - chr2_2(data, CHRROM); - break; case 0x2800: - chr2_4(data, CHRROM); - break; case 0x3800: - chr2_6(data, CHRROM); + chr2_x((offset >> 11) & 0x06, data & 0x3f, CHRROM); break; - case 0x4000: case 0x4800: m_irq_toggle ^= 1; if (m_irq_toggle) @@ -311,7 +273,6 @@ void nes_sunsoft_3_device::write_h(offs_t offset, uint8_t data) case 0x5800: m_irq_enable = BIT(data, 4); m_irq_toggle = 0; - set_irq_line(CLEAR_LINE); break; case 0x6800: switch (data & 3) @@ -323,10 +284,10 @@ void nes_sunsoft_3_device::write_h(offs_t offset, uint8_t data) } break; case 0x7800: - prg16_89ab(data); + prg16_89ab(data & 0x0f); break; default: - LOG_MMC(("Sunsoft 3 write_h uncaught write, offset: %04x, data: %02x\n", offset, data)); + set_irq_line(CLEAR_LINE); break; } } @@ -341,143 +302,98 @@ void nes_sunsoft_3_device::write_h(offs_t offset, uint8_t data) -------------------------------------------------*/ -void nes_sunsoft_4_device::sun4_mirror( int mirror, int mirr0, int mirr1 ) +void nes_sunsoft_4_device::sun4_mirror() { - switch (mirror) + static constexpr u8 ciram_lut[4] = { - case 0x00: - set_nt_mirroring(PPU_MIRROR_VERT); - break; - case 0x01: - set_nt_mirroring(PPU_MIRROR_HORZ); - break; - case 0x02: - set_nt_mirroring(PPU_MIRROR_LOW); - break; - case 0x03: - set_nt_mirroring(PPU_MIRROR_HIGH); - break; - case 0x10: - set_nt_page(0, VROM, mirr0 | 0x80, 0); - set_nt_page(1, VROM, mirr1 | 0x80, 0); - set_nt_page(2, VROM, mirr0 | 0x80, 0); - set_nt_page(3, VROM, mirr1 | 0x80, 0); - break; - case 0x11: - set_nt_page(0, VROM, mirr0 | 0x80, 0); - set_nt_page(1, VROM, mirr0 | 0x80, 0); - set_nt_page(2, VROM, mirr1 | 0x80, 0); - set_nt_page(3, VROM, mirr1 | 0x80, 0); - break; - case 0x12: - set_nt_page(0, VROM, mirr0 | 0x80, 0); - set_nt_page(1, VROM, mirr0 | 0x80, 0); - set_nt_page(2, VROM, mirr0 | 0x80, 0); - set_nt_page(3, VROM, mirr0 | 0x80, 0); - break; - case 0x13: - set_nt_page(0, VROM, mirr1 | 0x80, 0); - set_nt_page(1, VROM, mirr1 | 0x80, 0); - set_nt_page(2, VROM, mirr1 | 0x80, 0); - set_nt_page(3, VROM, mirr1 | 0x80, 0); - break; - } + PPU_MIRROR_VERT, PPU_MIRROR_HORZ, PPU_MIRROR_LOW, PPU_MIRROR_HIGH + }; + + static constexpr u8 vrom_lut[4][4] = + { + { 0, 1, 0, 1 }, // vert + { 0, 0, 1, 1 }, // horz + { 0, 0, 0, 0 }, // low + { 1, 1, 1, 1 } // high + }; + + int mirr = m_reg[2] & 0x03; + + if (BIT(m_reg[2], 4)) + for (int i = 0; i < 4; i++) + set_nt_page(i, VROM, m_reg[vrom_lut[mirr][i]], 0); + else + set_nt_mirroring(ciram_lut[mirr]); } -void nes_sunsoft_4_device::sun4_write(offs_t offset, uint8_t data) +void nes_sunsoft_4_device::sun4_write(offs_t offset, u8 data) { - LOG_MMC(("Sunsoft 4 write_h, offset %04x, data: %02x\n", offset, data)); + LOG("Sunsoft 4 write_h, offset %04x, data: %02x\n", offset, data); switch (offset & 0x7000) { case 0x0000: - chr2_0(data, CHRROM); - break; case 0x1000: - chr2_2(data, CHRROM); - break; case 0x2000: - chr2_4(data, CHRROM); - break; case 0x3000: - chr2_6(data, CHRROM); + chr2_x((offset >> 11) & 0x06, data, CHRROM); break; case 0x4000: - m_latch1 = data & 0x7f; - sun4_mirror(m_reg, m_latch1, m_latch2); - break; case 0x5000: - m_latch2 = data & 0x7f; - sun4_mirror(m_reg, m_latch1, m_latch2); - break; case 0x6000: - m_reg = data & 0x13; - sun4_mirror(m_reg, m_latch1, m_latch2); + m_reg[(offset >> 12) - 4] = data | 0x80; + sun4_mirror(); break; case 0x7000: prg16_89ab(data & 0x0f); m_wram_enable = BIT(data, 4); break; - default: - LOG_MMC(("Sunsoft 4 write_h uncaught write, offset: %04x, data: %02x\n", offset, data)); - break; } } -void nes_sunsoft_4_device::write_m(offs_t offset, uint8_t data) +void nes_sunsoft_4_device::write_m(offs_t offset, u8 data) { - LOG_MMC(("Sunsoft 4 write_m, offset: %04x, data: %02x\n", offset, data)); + LOG("Sunsoft 4 write_m, offset: %04x, data: %02x\n", offset, data); - if (!m_battery.empty() && m_wram_enable) - m_battery[offset & (m_battery.size() - 1)] = data; - if (!m_prgram.empty() && m_wram_enable) - m_prgram[offset & (m_prgram.size() - 1)] = data; + if (m_wram_enable) + device_nes_cart_interface::write_m(offset, data); } -uint8_t nes_sunsoft_4_device::read_m(offs_t offset) +u8 nes_sunsoft_4_device::read_m(offs_t offset) { - LOG_MMC(("Sunsoft 4 read_m, offset: %04x\n", offset)); + LOG("Sunsoft 4 read_m, offset: %04x\n", offset); - if (!m_battery.empty() && m_wram_enable) - return m_battery[offset & (m_battery.size() - 1)]; - if (!m_prgram.empty() && m_wram_enable) - return m_prgram[offset & (m_prgram.size() - 1)]; + if (m_wram_enable) + return device_nes_cart_interface::read_m(offset); - return get_open_bus(); // open bus + return get_open_bus(); } /*------------------------------------------------- JxROM & Sunsoft 5A / 5B / FME7 board emulation - Notice that Sunsoft-5B = FME7 + sound chip (the latter being - currently unemulated in MESS) + Notice that Sunsoft-5B = FME7 + sound chip iNES: mapper 69 -------------------------------------------------*/ -void nes_sunsoft_fme7_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +TIMER_CALLBACK_MEMBER(nes_sunsoft_fme7_device::irq_timer_tick) { - if (id == TIMER_IRQ) + if (BIT(m_irq_enable, 7)) // counter decrement enabled { - if ((m_irq_enable & 0x80)) // bit7, counter decrement + if (--m_irq_count == 0xffff) { - if (!m_irq_count) - { - m_irq_count = 0xffff; - if (m_irq_enable & 0x01) // bit0, trigger enable - set_irq_line(ASSERT_LINE); - } - else - m_irq_count--; + if (BIT(m_irq_enable, 0)) // IRQs enabled + set_irq_line(ASSERT_LINE); } } } void nes_sunsoft_fme7_device::fme7_write(offs_t offset, uint8_t data) { - LOG_MMC(("fme7_write, offset %04x, data: %02x\n", offset, data)); + LOG("fme7_write, offset %04x, data: %02x\n", offset, data); switch (offset & 0x6000) { @@ -515,8 +431,7 @@ void nes_sunsoft_fme7_device::fme7_write(offs_t offset, uint8_t data) break; case 0x0d: m_irq_enable = data; - if (!(m_irq_enable & 1)) - set_irq_line(CLEAR_LINE); + set_irq_line(CLEAR_LINE); break; case 0x0e: m_irq_count = (m_irq_count & 0xff00) | data; @@ -528,7 +443,7 @@ void nes_sunsoft_fme7_device::fme7_write(offs_t offset, uint8_t data) break; default: - logerror("Sunsoft FME7 write_h uncaught %04x value: %02x\n", offset + 0x8000, data); + LOGMASKED(LOG_UNHANDLED, "Sunsoft FME7 write_h uncaught %04x value: %02x\n", offset + 0x8000, data); break; } } @@ -536,7 +451,7 @@ void nes_sunsoft_fme7_device::fme7_write(offs_t offset, uint8_t data) void nes_sunsoft_fme7_device::write_m(offs_t offset, uint8_t data) { uint8_t bank = m_wram_bank & 0x3f; - LOG_MMC(("Sunsoft FME7 write_m, offset: %04x, data: %02x\n", offset, data)); + LOG("Sunsoft FME7 write_m, offset: %04x, data: %02x\n", offset, data); if (!(m_wram_bank & 0x40)) // is PRG ROM, no write return; @@ -552,7 +467,7 @@ void nes_sunsoft_fme7_device::write_m(offs_t offset, uint8_t data) uint8_t nes_sunsoft_fme7_device::read_m(offs_t offset) { uint8_t bank = m_wram_bank & 0x3f; - LOG_MMC(("Sunsoft FME7 read_m, offset: %04x\n", offset)); + LOG("Sunsoft FME7 read_m, offset: %04x\n", offset); if (!(m_wram_bank & 0x40)) // is PRG ROM return m_prg[((bank * 0x2000) + offset) & (m_prg_size - 1)]; @@ -564,7 +479,7 @@ uint8_t nes_sunsoft_fme7_device::read_m(offs_t offset) return m_prgram[((bank * 0x2000) + offset) & (m_prgram.size() - 1)]; } - return get_open_bus(); // open bus + return get_open_bus(); } @@ -580,7 +495,7 @@ uint8_t nes_sunsoft_fme7_device::read_m(offs_t offset) void nes_sunsoft_5_device::write_h(offs_t offset, uint8_t data) { - LOG_MMC(("sunsoft 5 write_h, offset %04x, data: %02x\n", offset, data)); + LOG("sunsoft 5 write_h, offset %04x, data: %02x\n", offset, data); switch (offset & 0x6000) { @@ -616,5 +531,5 @@ void nes_sunsoft_5_device::device_add_mconfig(machine_config &config) // TODO: this is not how Sunsoft 5B clock signaling works! // The board uses the CLK pin in reality, not hardcoded NTSC values! - YM2149(config, m_ym2149, (XTAL(21'477'272)/12)/2).add_route(ALL_OUTPUTS, "addon", 0.50); // divide by 2 for the internal divider + SUNSOFT_5B_SOUND(config, m_ym2149, XTAL(21'477'272)/12).add_route(ALL_OUTPUTS, "addon", 0.50); } |