diff options
author | 2015-11-08 12:56:12 +0100 | |
---|---|---|
committer | 2015-11-08 12:56:12 +0100 | |
commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/devices/bus/nes/cony.cpp | |
parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/devices/bus/nes/cony.cpp')
-rw-r--r-- | src/devices/bus/nes/cony.cpp | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/src/devices/bus/nes/cony.cpp b/src/devices/bus/nes/cony.cpp new file mode 100644 index 00000000000..a64063ebc8a --- /dev/null +++ b/src/devices/bus/nes/cony.cpp @@ -0,0 +1,397 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli +/*********************************************************************************************************** + + + NES/Famicom cartridge emulation for Cony/Yoko PCBs + + + Here we emulate the following PCBs + + * UNL-CONY [mapper 83] + * UNL-YOKO + + TODO: fix glitches and emulate properly the variants + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "cony.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_CONY = &device_creator<nes_cony_device>; +const device_type NES_YOKO = &device_creator<nes_yoko_device>; + + +nes_cony_device::nes_cony_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) + : nes_nrom_device(mconfig, type, name, tag, owner, clock, shortname, source) +{ +} + +nes_cony_device::nes_cony_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_nrom_device(mconfig, NES_CONY, "NES Cart Cony PCB", tag, owner, clock, "nes_cony", __FILE__) +{ +} + +nes_yoko_device::nes_yoko_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : nes_cony_device(mconfig, NES_YOKO, "NES Cart Yoko PCB", tag, owner, clock, "nes_yoko", __FILE__) +{ +} + + + + +void nes_cony_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_low_reg)); + save_item(NAME(m_reg)); + save_item(NAME(m_extra1)); + save_item(NAME(m_latch1)); + save_item(NAME(m_latch2)); +} + +void nes_cony_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg16_89ab(0); + prg8_cd(0x1e); + prg8_ef(0x1f); + chr8(0, m_chr_source); + + m_irq_enable = 0; + m_irq_count = 0; + + m_latch1 = 0; + m_latch2 = 0; + m_extra1 = 0; + + memset(m_low_reg, 0, sizeof(m_low_reg)); + memset(m_reg, 0, sizeof(m_reg)); + m_reg[9] = 0x0f; +} + +void nes_yoko_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_low_reg)); + save_item(NAME(m_reg)); + save_item(NAME(m_extra1)); + save_item(NAME(m_extra2)); + save_item(NAME(m_latch1)); + save_item(NAME(m_latch2)); +} + +void nes_yoko_device::pcb_reset() +{ + m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM; + prg16_89ab(0); + prg8_cd(0x1e); + prg8_ef(0x1f); + chr8(0, m_chr_source); + + m_irq_enable = 0; + m_irq_count = 0; + + m_latch1 = 0; + m_latch2 = 0; + m_extra1 = 0; + m_extra2 = 0; + + memset(m_low_reg, 0, sizeof(m_low_reg)); + memset(m_reg, 0, sizeof(m_reg)); + m_reg[9] = 0x0f; +} + + + + + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +/*------------------------------------------------- + + Cony Bootleg Board + + Games: Dragon Ball Party, Fatal Fury 2, Street Blaster II + Pro, World Heroes 2 + + iNES: mapper 83 + + In MESS: Supported. + + -------------------------------------------------*/ + +void nes_cony_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if (id == TIMER_IRQ) + { + if (m_irq_enable) + { + if (!m_irq_count) + { + m_maincpu->set_input_line(M6502_IRQ_LINE, HOLD_LINE); + m_irq_enable = 0; + m_irq_count = 0xffff; + } + else + m_irq_count--; + } + } +} + +WRITE8_MEMBER(nes_cony_device::write_l) +{ + LOG_MMC(("cony write_l, offset: %04x, data: %02x\n", offset, data)); + + if (offset >= 0x1000 && offset < 0x1103) // from 0x5100-0x51ff + m_low_reg[offset & 0x03] = data; +} + +READ8_MEMBER(nes_cony_device::read_l) +{ + LOG_MMC(("cony read_l, offset: %04x\n", offset)); + + if (offset == 0x0f00) // 0x5000 + { + // read dipswitch bit! - currently unimplemented + } + if (offset >= 0x1000 && offset < 0x1103) // from 0x5100-0x51ff + return m_low_reg[offset & 0x03]; + else + return 0x00; +} + +void nes_cony_device::set_prg() +{ + prg16_89ab(m_reg[8] & 0x3f); + prg16_cdef((m_reg[8] & 0x30) | 0x0f); +} + +void nes_cony_device::set_chr() +{ + // FIXME: here we emulate at least 3 different boards!!! + // one board switches 1k VROM banks only + // one writes to 0x8000 and then switches 2k VROM banks only + // one writes to 0x831n (n=2,3,4,5) and then switches 2k VROM banks only + // we should split them and possibly document the proper behavior of each variant + if (m_latch1 && !m_latch2) + { + chr2_0(m_reg[0], CHRROM); + chr2_2(m_reg[1], CHRROM); + chr2_4(m_reg[6], CHRROM); + chr2_6(m_reg[7], CHRROM); + } + else + { + chr1_0(m_reg[0] | ((m_reg[8] & 0x30) << 4), CHRROM); + chr1_1(m_reg[1] | ((m_reg[8] & 0x30) << 4), CHRROM); + chr1_2(m_reg[2] | ((m_reg[8] & 0x30) << 4), CHRROM); + chr1_3(m_reg[3] | ((m_reg[8] & 0x30) << 4), CHRROM); + chr1_4(m_reg[4] | ((m_reg[8] & 0x30) << 4), CHRROM); + chr1_5(m_reg[5] | ((m_reg[8] & 0x30) << 4), CHRROM); + chr1_6(m_reg[6] | ((m_reg[8] & 0x30) << 4), CHRROM); + chr1_7(m_reg[7] | ((m_reg[8] & 0x30) << 4), CHRROM); + } +} + +WRITE8_MEMBER(nes_cony_device::write_h) +{ + LOG_MMC(("cony write_h, offset: %04x, data: %02x\n", offset, data)); + + switch (offset) + { + case 0x0000: + m_latch1 = 1; + case 0x3000: + case 0x30ff: + case 0x31ff: + m_reg[8] = data; + set_prg(); + set_chr(); + break; + case 0x0100: + m_extra1 = data & 0x80; + switch (data & 0x03) + { + case 0: + set_nt_mirroring(PPU_MIRROR_VERT); + break; + case 1: + set_nt_mirroring(PPU_MIRROR_HORZ); + break; + case 2: + set_nt_mirroring(PPU_MIRROR_LOW); + break; + case 3: + set_nt_mirroring(PPU_MIRROR_HIGH); + break; + } + break; + case 0x0200: + m_irq_count = (m_irq_count & 0xff00) | data; + break; + case 0x0201: + m_irq_enable = m_extra1; + m_irq_count = (data << 8) | (m_irq_count & 0xff); + break; + case 0x0300: + prg8_89(data); + break; + case 0x0301: + prg8_ab(data); + break; + case 0x0302: + prg8_cd(data); + break; + case 0x0312: + case 0x0313: + case 0x0314: + case 0x0315: + m_latch2 = 1; + case 0x0310: + case 0x0311: + case 0x0316: + case 0x0317: + m_reg[offset - 0x0310] = data; + set_chr(); + break; + case 0x0318: + m_reg[9] = data; // unused? + set_prg(); + break; + } +} + +/*------------------------------------------------- + + Yoko Bootleg Board + + Games: Mortal Kombat II, Master Figther VI' + + + Very similar to Cony board + + In MESS: Supported. + + -------------------------------------------------*/ + +WRITE8_MEMBER(nes_yoko_device::write_l) +{ + LOG_MMC(("yoko write_l, offset: %04x, data: %02x\n", offset, data)); + + if (offset >= 0x1300) // from 0x5400 + m_low_reg[offset & 0x03] = data; +} + +READ8_MEMBER(nes_yoko_device::read_l) +{ + LOG_MMC(("yoko read_l, offset: %04x\n", offset)); + + if (offset >= 0x0f00 && offset < 0x1300) // 0x5000 + { + // read dipswitch bit! - currently unimplemented + } + if (offset >= 0x1300) // from 0x5400 + return m_low_reg[offset & 0x03]; + else + return 0x00; +} + +void nes_yoko_device::set_prg() +{ + if (m_extra1 & 0x10) + { + int base = (m_extra2 & 0x08) << 1; + prg8_89(base | (m_reg[0] & 0x0f)); + prg8_ab(base | (m_reg[1] & 0x0f)); + prg8_cd(base | (m_reg[2] & 0x0f)); + prg8_ef(base | 0x0f); + } + else if (m_extra1 & 0x08) + prg32(m_extra2 >> 1); + else + { + prg16_89ab(m_extra2); + prg16_cdef(0xff); + } +} + +void nes_yoko_device::set_chr() +{ + chr2_0(m_reg[4], CHRROM); + chr2_2(m_reg[5], CHRROM); + chr2_4(m_reg[6], CHRROM); + chr2_6(m_reg[7], CHRROM); +} + +WRITE8_MEMBER(nes_yoko_device::write_h) +{ + LOG_MMC(("yoko write_h, offset: %04x, data: %02x\n", offset, data)); + + switch (offset & 0x0c17) + { + case 0x0000: + m_extra2 = data; + set_prg(); + break; + case 0x400: + m_extra1 = data; + if (data & 1) + set_nt_mirroring(PPU_MIRROR_HORZ); + else + set_nt_mirroring(PPU_MIRROR_VERT); + set_prg(); + break; + case 0x0800: + m_irq_count = (m_irq_count & 0xff00) | data; + break; + case 0x0801: + m_irq_enable = m_extra1 & 0x80; + m_irq_count = (data << 8) | (m_irq_count & 0xff); + break; + case 0x0c00: + case 0x0c01: + case 0x0c02: + m_reg[offset & 3] = data; + set_prg(); + break; + case 0x0c10: + case 0x0c11: + case 0x0c16: + case 0x0c17: + m_reg[4 + (offset & 3)] = data; + set_chr(); + break; + } +} |