From 4b7062d6265be9679e3fb18e23bb41b208276e09 Mon Sep 17 00:00:00 2001 From: David Haywood <28625134+DavidHaywood@users.noreply.github.com> Date: Tue, 31 Mar 2020 22:40:43 +0100 Subject: Plug and Play work (#6506) * start to do SoC as separate file (nw) * start moving bits (nw) * (nw) * sledgehammer time (nw) * start putting stuff back together (nw) * main screen turn back on (nw) * input callbacks (nw) * restore this (nw) * continue rebuilding (nw) * rebuilding (nw) * (nw) * senwld boots again (nw) * restore some sets to working (nw) * few repairs (nw) * more repairs (nw) * repair (nw) * repairs (nw) * prepare (nw) * move and tidy (nw) * fixups (nw) * fixes (nw) * refactoring (nw) * shuffle code around (nw) --- scripts/target/mame/mess.lua | 2 + src/devices/video/ppu2c0x_vt.cpp | 2 - src/mame/drivers/nes_vt.cpp | 2118 ++++++++------------------------------ src/mame/machine/nes_vt_soc.cpp | 1587 ++++++++++++++++++++++++++++ src/mame/machine/nes_vt_soc.h | 343 ++++++ 5 files changed, 2365 insertions(+), 1687 deletions(-) create mode 100644 src/mame/machine/nes_vt_soc.cpp create mode 100644 src/mame/machine/nes_vt_soc.h diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 91c38a65b37..47aa48a379a 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -2974,6 +2974,8 @@ files { MAME_DIR .. "src/mame/machine/nes.cpp", MAME_DIR .. "src/mame/video/nes.cpp", MAME_DIR .. "src/mame/drivers/nes_vt.cpp", + MAME_DIR .. "src/mame/machine/nes_vt_soc.cpp", + MAME_DIR .. "src/mame/machine/nes_vt_soc.h", MAME_DIR .. "src/mame/drivers/nes_sh6578.cpp", MAME_DIR .. "src/mame/drivers/nes_clone.cpp", MAME_DIR .. "src/mame/drivers/pokemini.cpp", diff --git a/src/devices/video/ppu2c0x_vt.cpp b/src/devices/video/ppu2c0x_vt.cpp index a701d4076d6..04da1b8740b 100644 --- a/src/devices/video/ppu2c0x_vt.cpp +++ b/src/devices/video/ppu2c0x_vt.cpp @@ -27,8 +27,6 @@ ppu_vt03_device::ppu_vt03_device(const machine_config& mconfig, device_type type m_read_bg(*this), m_read_sp(*this) { - for (int i = 0; i < 6; i++) - m_2012_2017_descramble[i] = 2 + i; } ppu_vt03_device::ppu_vt03_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : diff --git a/src/mame/drivers/nes_vt.cpp b/src/mame/drivers/nes_vt.cpp index 01c0e2b24b3..9e91743fa18 100644 --- a/src/mame/drivers/nes_vt.cpp +++ b/src/mame/drivers/nes_vt.cpp @@ -2,56 +2,9 @@ // copyright-holders:David Haywood /*************************************************************************** - nes_vt.c + nes_vt.cpp - The 'VT' series are SoC solutions that implement enhanced NES hardware - there are several generations of these chips each adding additional - functionality. - - This list is incomplete - - VT01 - plain famiclone? - VT02 - banking scheme to access 32MB, Dual APU with PCM support - VT03 - above + 4bpp sprite / bg modes, enhanced palette - - VT08 - ? - - VT09 - alt 4bpp modes? - - VT16 - ? - VT18 - ? - - VT33 (?) - used in FC Pocket, dgun2573 - Adds scrambled opcodes (XORed with 0xA1) and RGB444 palette mode, - and more advanced PCM modes (CPU and video working, sound NYI) - - VT368 (?) - used in DGUN2561, lxcmcy - Various enhancements not yet emulated. Different banking, possibly an ALU, - larger palette space - - VT36x (?) - used in SY889 - Uses SQI rather than parallel flash - Vaguely OneBus compatible but some registers different ($411C in particular) - Uses RGB format for palettes - Credit to NewRisingSun2 for much of the reverse engineering - same chipset used in Mogis M320, but uses more advanced feature set. - - (more) - - - - todo (VT03): - - APU refactoring to allow for mostly doubled up functionality + PCM channel - *more* - - todo (newer VTxx): - - new PCM audio in FC Pocket and DGUN-2573 - add support for VT368 (?) in DGUN-2561 and lxcmcy - add support for the VT369 (?) featurs used by the MOGIS M320 - - todo (general) + TODO Add more Famiclone roms here, there should be plenty more dumps of VTxx based systems floating about. @@ -67,72 +20,23 @@ ***************************************************************************/ #include "emu.h" -#include "cpu/m6502/n2a03.h" -#include "machine/bankdev.h" -#include "video/ppu2c0x_vt.h" -#include "machine/m6502_vtscr.h" -#include "machine/m6502_swap_op_d5_d6.h" -#include "screen.h" -#include "speaker.h" +#include "machine/nes_vt_soc.h" -class nes_vt_state : public driver_device +class nes_vt_base_state : public driver_device { public: - nes_vt_state(const machine_config& mconfig, device_type type, const char* tag) : + nes_vt_base_state(const machine_config& mconfig, device_type type, const char* tag) : driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), m_io0(*this, "IO0"), m_io1(*this, "IO1"), - m_screen(*this, "screen"), - m_ppu(*this, "ppu"), - m_apu(*this, "apu"), m_cartsel(*this, "CARTSEL"), m_exin0(*this, "EXTRAIN0"), m_exin1(*this, "EXTRAIN1"), m_exin2(*this, "EXTRAIN2"), m_exin3(*this, "EXTRAIN3"), - m_vt_external_space(*this, "vt_ext_space"), - m_prgrom(*this, "mainrom"), - m_initial_e000_bank(0xff), - m_ntram(nullptr), - m_chrram(nullptr) + m_prgrom(*this, "mainrom") { } - void nes_vt_base(machine_config& config); - void nes_vt_base_pal(machine_config& config); - - void nes_vt_pal(machine_config& config); - void nes_vt_pal_2mb(machine_config& config); - void nes_vt_pal_4mb(machine_config& config); - void nes_vt_pal_8mb(machine_config& config); - - void nes_vt(machine_config& config); - void nes_vt_512kb(machine_config& config); - void nes_vt_1mb(machine_config& config); - void nes_vt_2mb(machine_config& config); - void nes_vt_4mb(machine_config& config); - void nes_vt_8mb(machine_config& config); - void nes_vt_16mb(machine_config& config); - void nes_vt_32mb(machine_config& config); - - void nes_vt_4k_ram(machine_config& config); - void nes_vt_4k_ram_16mb(machine_config& config); - - - void nes_vt_4k_ram_pal(machine_config& config); - - /* OneBus read callbacks for getting sprite and tile data during rendering */ - DECLARE_READ8_MEMBER(spr_r); - DECLARE_READ8_MEMBER(chr_r); - - /* Misc PPU */ - DECLARE_WRITE8_MEMBER(vt_dma_w); - DECLARE_WRITE8_MEMBER(vt_fixed_dma_w); - - // TODO: give these better register names so it's clearer what is remapped - void set_8000_scramble(uint8_t reg0, uint8_t reg1, uint8_t reg2, uint8_t reg3, uint8_t reg4, uint8_t reg5, uint8_t reg6, uint8_t reg7); - void set_410x_scramble(uint8_t reg0, uint8_t reg1); - protected: virtual void machine_start() override; virtual void machine_reset() override; @@ -141,46 +45,19 @@ protected: virtual DECLARE_READ8_MEMBER(in1_r); virtual DECLARE_WRITE8_MEMBER(in0_w); - uint32_t screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect); - void nes_vt_map(address_map& map); - required_device m_maincpu; + optional_ioport m_io0; optional_ioport m_io1; uint8_t m_latch0; uint8_t m_latch1; - required_device m_screen; - required_device m_ppu; - required_device m_apu; - - /* APU handling */ - DECLARE_READ8_MEMBER(psg1_4014_r); - DECLARE_READ8_MEMBER(psg1_4015_r); - DECLARE_WRITE8_MEMBER(psg1_4015_w); - DECLARE_WRITE8_MEMBER(psg1_4017_w); - - /* VT03 extension handling */ - DECLARE_WRITE8_MEMBER(vt03_410x_w); - DECLARE_READ8_MEMBER(vt03_410x_r); - /* Misc */ uint32_t m_ahigh; // external banking bits - void update_banks(); uint8_t m_4242; uint8_t m_411c; uint8_t m_411d; - uint8_t m_413x[8]; // CY only? - - uint8_t m_8000_scramble[8]; - uint8_t m_410x_scramble[2]; - - void scrambled_410x_w(uint16_t offset, uint8_t data); - void scrambled_8000_w(address_space& space, uint16_t offset, uint8_t data); - - DECLARE_WRITE8_MEMBER(vt03_8000_mapper_w); - DECLARE_WRITE8_MEMBER(vt03_4034_w); optional_ioport m_cartsel; optional_ioport m_exin0; @@ -188,84 +65,68 @@ protected: optional_ioport m_exin2; optional_ioport m_exin3; - required_device m_vt_external_space; required_region_ptr m_prgrom; - void nes_vt_4k_ram_map(address_map& map); - - /* Misc */ - DECLARE_READ8_MEMBER(rs232flags_region_r); - - uint8_t m_initial_e000_bank; - - void vt_external_space_map_32mbyte(address_map& map); - void vt_external_space_map_16mbyte(address_map& map); - void vt_external_space_map_8mbyte(address_map& map); - void vt_external_space_map_4mbyte(address_map& map); - void vt_external_space_map_2mbyte(address_map& map); - void vt_external_space_map_1mbyte(address_map& map); - void vt_external_space_map_512kbyte(address_map& map); - DECLARE_READ8_MEMBER(vt_rom_r); DECLARE_WRITE8_MEMBER(vtspace_w); + + void configure_soc(nes_vt_soc_device* soc); - DECLARE_READ8_MEMBER(external_space_read) { int bank = (offset & 0x6000) >> 13; int address = (m_bankaddr[bank] * 0x2000) + (offset&0x1fff); m_real_access_address = offset + 0x8000; return m_vt_external_space->read8(address); }; - DECLARE_WRITE8_MEMBER(external_space_write) { int bank = (offset & 0x6000) >> 13; int address = (m_bankaddr[bank] * 0x2000) + (offset&0x1fff); m_real_access_address = offset + 0x8000; m_vt_external_space->write8(address, data); }; + DECLARE_READ8_MEMBER(upper_412c_r); + DECLARE_READ8_MEMBER(upper_412d_r); + DECLARE_WRITE8_MEMBER(upper_412c_w); private: /* APU handling */ - DECLARE_WRITE_LINE_MEMBER(apu_irq); - DECLARE_READ8_MEMBER(apu_read_mem); /* Extra IO */ - DECLARE_WRITE8_MEMBER(extra_io_control_w); - virtual DECLARE_READ8_MEMBER(extrain_01_r); - virtual DECLARE_READ8_MEMBER(extrain_23_r); - virtual DECLARE_WRITE8_MEMBER(extraout_01_w); - virtual DECLARE_WRITE8_MEMBER(extraout_23_w); - - - DECLARE_WRITE8_MEMBER(chr_w); - - void prg_map(address_map& map); - - /* expansion nametable - todo, see if we can refactor NES code to be reusable without having to add full NES bus etc. */ - std::unique_ptr m_ntram; - std::unique_ptr m_chrram; - - DECLARE_READ8_MEMBER(nt_r); - DECLARE_WRITE8_MEMBER(nt_w); + DECLARE_READ8_MEMBER(extrain_0_r); + DECLARE_READ8_MEMBER(extrain_1_r); + DECLARE_READ8_MEMBER(extrain_2_r); + DECLARE_READ8_MEMBER(extrain_3_r); - void scanline_irq(int scanline, int vblank, int blanked); - void hblank_irq(int scanline, int vblank, int blanked); - void video_irq(bool hblank, int scanline, int vblank, int blanked); - - uint8_t m_410x[0xc]; - - uint8_t m_vdma_ctrl; - - int m_timer_irq_enabled; - int m_timer_running; - int m_timer_val; - - uint8_t m_8000_addr_latch; +}; - /* banking etc. */ - uint32_t get_banks(uint8_t bnk); +class nes_vt_state : public nes_vt_base_state +{ +public: + nes_vt_state(const machine_config& mconfig, device_type type, const char* tag) : + nes_vt_base_state(mconfig, type, tag), + m_soc(*this, "soc") + { } - int calculate_real_video_address(int addr, int extended, int readtype); + void nes_vt_pal_2mb(machine_config& config); + void nes_vt_pal_4mb(machine_config& config); + void nes_vt_pal_8mb(machine_config& config); - uint16_t m_real_access_address; + void nes_vt_512kb(machine_config& config); + void nes_vt_1mb(machine_config& config); + void nes_vt_2mb(machine_config& config); + void nes_vt_4mb(machine_config& config); + void nes_vt_8mb(machine_config& config); + void nes_vt_16mb(machine_config& config); + void nes_vt_32mb(machine_config& config); + void nes_vt_4k_ram(machine_config& config); + void nes_vt_4k_ram_16mb(machine_config& config); - int m_bankaddr[4]; + void nes_vt_4k_ram_pal(machine_config& config); + void vt_external_space_map_32mbyte(address_map& map); + void vt_external_space_map_16mbyte(address_map& map); + void vt_external_space_map_8mbyte(address_map& map); + void vt_external_space_map_4mbyte(address_map& map); + void vt_external_space_map_2mbyte(address_map& map); + void vt_external_space_map_1mbyte(address_map& map); + void vt_external_space_map_512kbyte(address_map& map); - uint16_t decode_nt_addr(uint16_t addr); - void do_dma(uint8_t data, bool has_ntsc_bug); +protected: + required_device m_soc; + DECLARE_WRITE8_MEMBER(vt03_8000_mapper_w) { m_soc->vt03_8000_mapper_w(space, offset, data); } }; + class nes_vt_swap_op_d5_d6_state : public nes_vt_state { public: @@ -281,8 +142,6 @@ public: protected: void vt_external_space_map_senwld_512kbyte(address_map& map); - -private: }; class nes_vt_pjoy_state : public nes_vt_state @@ -292,8 +151,7 @@ public: nes_vt_state(mconfig, type, tag) { } -protected: - virtual void machine_reset() override; + void nes_vt_pjoy_4mb(machine_config& config); }; class nes_vt_waixing_state : public nes_vt_state @@ -303,8 +161,8 @@ public: nes_vt_state(mconfig, type, tag) { } -protected: - virtual void machine_reset() override; + void nes_vt_waixing_512kb(machine_config& config); + void nes_vt_waixing_2mb(machine_config& config); }; class nes_vt_waixing_alt_state : public nes_vt_waixing_state @@ -314,8 +172,7 @@ public: nes_vt_waixing_state(mconfig, type, tag) { } -protected: - virtual void machine_reset() override; + void nes_vt_waixing_alt_pal_8mb(machine_config& config); }; @@ -325,8 +182,6 @@ public: nes_vt_timetp36_state(const machine_config& mconfig, device_type type, const char* tag) : nes_vt_state(mconfig, type, tag) { } - -protected: }; class nes_vt_hum_state : public nes_vt_state @@ -335,9 +190,9 @@ public: nes_vt_hum_state(const machine_config& mconfig, device_type type, const char* tag) : nes_vt_state(mconfig, type, tag) { } - -protected: - virtual void machine_reset() override; + + void nes_vt_hummer_2mb(machine_config& config); + void nes_vt_hummer_4mb(machine_config& config); }; class nes_vt_sp69_state : public nes_vt_state @@ -347,24 +202,21 @@ public: nes_vt_state(mconfig, type, tag) { } -protected: - virtual void machine_reset() override; + void nes_vt_4mb_sp69(machine_config& config); }; -class nes_vt_ablping_state : public nes_vt_sp69_state +class nes_vt_ablping_state : public nes_vt_state { public: nes_vt_ablping_state(const machine_config& mconfig, device_type type, const char* tag) : - nes_vt_sp69_state(mconfig, type, tag) + nes_vt_state(mconfig, type, tag) { } void nes_vt_2mb_ablping(machine_config& config); private: - void nes_vt_ablping_map(address_map& map); - - DECLARE_READ8_MEMBER(ablping_410f_r); - DECLARE_WRITE8_MEMBER(ablping_410f_w); + DECLARE_READ8_MEMBER(ablping_extraio_r); + DECLARE_WRITE8_MEMBER(ablping_extraio_w); }; class nes_vt_cy_state : public nes_vt_state @@ -388,18 +240,7 @@ private: void nes_vt_cy_map(address_map& map); void nes_vt_bt_map(address_map& map); - DECLARE_WRITE8_MEMBER(vt03_41bx_w); - DECLARE_READ8_MEMBER(vt03_41bx_r); - DECLARE_WRITE8_MEMBER(vt03_411c_w); - DECLARE_WRITE8_MEMBER(vt03_412c_extbank_w); - - DECLARE_WRITE8_MEMBER(vt03_48ax_w); - DECLARE_READ8_MEMBER(vt03_48ax_r); - - DECLARE_WRITE8_MEMBER(vt03_413x_w); - DECLARE_READ8_MEMBER(vt03_413x_r); - DECLARE_READ8_MEMBER(vt03_414f_r); - DECLARE_READ8_MEMBER(vt03_415c_r); + DECLARE_WRITE8_MEMBER(bittboy_412c_w); DECLARE_READ8_MEMBER(vt_rom_banked_r); }; @@ -441,7 +282,6 @@ public: void nes_vt_fa_4x16mb(machine_config& config); protected: - DECLARE_WRITE8_MEMBER(vtfp_4242_w); private: READ8_MEMBER(vt_rom_banked_r); @@ -451,9 +291,9 @@ private: void nes_vt_dg_baddma_map(address_map& map); void nes_vt_fa_map(address_map& map); - DECLARE_READ8_MEMBER(vtfa_412c_r); - DECLARE_WRITE8_MEMBER(vtfa_412c_extbank_w); - DECLARE_WRITE8_MEMBER(vt03_411c_w); + DECLARE_READ8_MEMBER(fapocket_412c_r); + DECLARE_WRITE8_MEMBER(fapocket_412c_w); + }; class nes_vt_dg_fapocket_state : public nes_vt_dg_state @@ -465,8 +305,6 @@ public: protected: virtual void machine_reset() override; - -private: }; @@ -503,18 +341,10 @@ private: DECLARE_READ8_MEMBER(vt_rom_banked_r); void vt_external_space_map_fp_2x32mbyte(address_map& map); - void nes_vt_hh_map(address_map& map); - void nes_vt_hh_baddma_map(address_map& map); void nes_vt_fp_map(address_map& map); - DECLARE_WRITE8_MEMBER(vtfp_411e_w); - DECLARE_WRITE8_MEMBER(vtfp_4a00_w); - DECLARE_WRITE8_MEMBER(vtfp_412c_extbank_w); - DECLARE_READ8_MEMBER(vtfp_412d_r); - DECLARE_READ8_MEMBER(vtfp_4119_r); - - DECLARE_READ8_MEMBER(vthh_414a_r); - DECLARE_WRITE8_MEMBER(vtfp_411d_w); + DECLARE_READ8_MEMBER(fcpocket_412d_r); + DECLARE_WRITE8_MEMBER(fcpocket_412c_w); }; class nes_vt_ablpinb_state : public nes_vt_state @@ -554,10 +384,6 @@ public: void nes_vt_sudoku_512kb(machine_config& config); -protected: - //virtual void machine_start() override; - //virtual void machine_reset() override; - private: virtual DECLARE_READ8_MEMBER(in0_r) override; virtual DECLARE_READ8_MEMBER(in1_r) override; @@ -572,18 +398,14 @@ public: { } void nes_vt_vg_1mb_majgnc(machine_config& config); - -protected: - -private: }; -READ8_MEMBER(nes_vt_state::vt_rom_r) +READ8_MEMBER(nes_vt_base_state::vt_rom_r) { return m_prgrom[offset]; } -WRITE8_MEMBER(nes_vt_state::vtspace_w) +WRITE8_MEMBER(nes_vt_base_state::vtspace_w) { logerror("%s: vtspace_w %08x : %02x", machine().describe_context(), offset, data); } @@ -664,9 +486,53 @@ void nes_vt_hh_state::vt_external_space_map_fp_2x32mbyte(address_map &map) map(0x0000000, 0x1ffffff).rw(FUNC(nes_vt_hh_state::vt_rom_banked_r), FUNC(nes_vt_hh_state::vt03_8000_mapper_w)); } +READ8_MEMBER(nes_vt_base_state::extrain_0_r) +{ + if (m_exin0) + return m_exin0->read(); + else + { + logerror("%s: extrain_0_r (not hooked up)\n", machine().describe_context()); + } + return 0x00; +} + +READ8_MEMBER(nes_vt_base_state::extrain_1_r) +{ + if (m_exin1) + return m_exin1->read(); + else + { + logerror("%s: extrain_1_r (not hooked up)\n", machine().describe_context()); + } + return 0x00; +} + +READ8_MEMBER(nes_vt_base_state::extrain_2_r) +{ + if (m_exin2) + return m_exin2->read(); + else + { + logerror("%s: extrain_2_r (not hooked up)\n", machine().describe_context()); + } + return 0x00; +} + +READ8_MEMBER(nes_vt_base_state::extrain_3_r) +{ + if (m_exin3) + return m_exin3->read(); + else + { + logerror("%s: extrain_3_r (not hooked up)\n", machine().describe_context()); + } + return 0x00; +} + /* Standard I/O handlers (NES Controller clone) */ -READ8_MEMBER(nes_vt_state::in0_r) +READ8_MEMBER(nes_vt_base_state::in0_r) { //logerror("%s: in0_r\n", machine().describe_context()); uint8_t ret = 0x40; @@ -675,7 +541,7 @@ READ8_MEMBER(nes_vt_state::in0_r) return ret; } -READ8_MEMBER(nes_vt_state::in1_r) +READ8_MEMBER(nes_vt_base_state::in1_r) { //logerror("%s: in1_r\n", machine().describe_context()); uint8_t ret = 0x40; @@ -684,7 +550,7 @@ READ8_MEMBER(nes_vt_state::in1_r) return ret; } -WRITE8_MEMBER(nes_vt_state::in0_w) +WRITE8_MEMBER(nes_vt_base_state::in0_w) { //logerror("%s: in0_w %02x\n", machine().describe_context(), data); if (data & 0x01) @@ -722,1086 +588,53 @@ WRITE8_MEMBER(nes_vt_cy_lexibook_state::in0_w) if ((!(data & 0x02)) && (m_previous_port0 & 0x02)) // 0x02 -> 0x00 transition { m_latch0_bit = m_latch0 & 0x01; - m_latch0 >>= 1; - m_latch1_bit = m_latch1 & 0x01; - m_latch1 >>= 1; - } - - m_previous_port0 = data; -} - - -uint32_t nes_vt_state::get_banks(uint8_t bnk) -{ - switch (m_410x[0xb] & 0x07) - { - case 0: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xC0) | (bnk & 0x3F)); // makes bank 0xff at 0xe000 map to 0x07e000 by default for vectors at 0x007fffx - case 1: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xE0) | (bnk & 0x1F)); - case 2: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xF0) | (bnk & 0x0F)); - case 3: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xF8) | (bnk & 0x07)); - case 4: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xFC) | (bnk & 0x03)); - case 5: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xFE) | (bnk & 0x01)); - case 6: return ((m_410x[0x0] & 0xF0) << 4) + (m_410x[0xa]); - case 7: return ((m_410x[0x0] & 0xF0) << 4) + bnk; - } - - return 0; -} - -// 8000 needs to bank in 60000 ( bank 0x30 ) -void nes_vt_state::update_banks() -{ - //uint32_t amod = m_ahigh >> 13; - - uint8_t bank; - - // 8000-9fff - if ((m_410x[0xb] & 0x40) != 0 || (m_410x[0x5] & 0x40) == 0) - { - if ((m_410x[0x5] & 0x40) == 0) - bank = m_410x[0x7]; - else - bank = m_410x[0x9]; - } - else - bank = 0xfe; - - m_bankaddr[0] = ((/*amod |*/ get_banks(bank)) ); - - // a000-bfff - bank = m_410x[0x8]; - m_bankaddr[1] = ((/*amod |*/ get_banks(bank)) ); - - // c000-dfff - if ((m_410x[0xb] & 0x40) != 0 || (m_410x[0x5] & 0x40) != 0) - { - if ((m_410x[0x5] & 0x40) == 0) - bank = m_410x[0x9]; - else - bank = m_410x[0x7]; - } - else - bank = 0xfe; - - m_bankaddr[2] = ((/*amod |*/ get_banks(bank)) ); - - // e000 - ffff - bank = m_initial_e000_bank; - m_bankaddr[3] = ((/*amod |*/ get_banks(bank)) ); -} - -uint16_t nes_vt_state::decode_nt_addr(uint16_t addr) -{ - bool vert_mirror = !(m_410x[0x6] & 0x01); - int a11 = (addr >> 11) & 0x01; - int a10 = (addr >> 10) & 0x01; - uint16_t base = (addr & 0x3FF); - return ((vert_mirror ? a10 : a11) << 10) | base; -} - -WRITE8_MEMBER(nes_vt_state::vt03_410x_w) -{ - scrambled_410x_w(offset, data); -} - -READ8_MEMBER(nes_vt_state::vt03_410x_r) -{ - return m_410x[offset]; -} - -// ablping polls this (also writes here) what is it? 4-bit DAC? PCM? (inputs only start responding once it finishes writing data on startup but takes longer than a sample should) -// (this is the extended IO port on VT) -READ8_MEMBER(nes_vt_ablping_state::ablping_410f_r) -{ - // needs to change at least - return machine().rand();//0x00; -}; - -WRITE8_MEMBER(nes_vt_ablping_state::ablping_410f_w) -{ - popmessage("ablping_410f_w %02x", data); -}; - -// Source: https://wiki.nesdev.com/w/index.php/NES_2.0_submappers/Proposals#NES_2.0_Mapper_256 - -void nes_vt_state::scrambled_410x_w(uint16_t offset, uint8_t data) -{ - switch (offset) - { - case 0x0: - m_410x[0x0] = data; - update_banks(); - break; - - case 0x1: - // latch timer value - m_410x[0x1] = data; - m_timer_running = 0; - break; - - case 0x2: - //logerror("vt03_4102_w %02x\n", data); - // load latched value and start counting - m_410x[0x2] = data; // value doesn't matter? - m_timer_val = m_410x[0x1]; - m_timer_running = 1; - break; - - case 0x3: - //logerror("vt03_4103_w %02x\n", data); - m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); - // disable timer irq - m_410x[0x3] = data; // value doesn't matter? - m_timer_irq_enabled = 0; - break; - - case 0x4: - //logerror("vt03_4104_w %02x\n", data); - // enable timer irq - m_410x[0x4] = data; // value doesn't matter? - m_timer_irq_enabled = 1; - break; - - case 0x5: - logerror("vt03_4105_w %02x\n", data); - m_410x[0x5] = data; - update_banks(); - break; - - case 0x6: - m_410x[0x6] = data; - break; - - case 0x7: - m_410x[m_410x_scramble[0]] = data; - update_banks(); - break; - - case 0x8: - m_410x[m_410x_scramble[1]] = data; - update_banks(); - break; - - case 0x9: - logerror("vt03_4109_w %02x\n", data); - m_410x[0x9] = data; - update_banks(); - break; - - case 0xa: - logerror("vt03_410aw %02x\n", data); - m_410x[0xa] = data; - update_banks(); - break; - - case 0xb: - /* - - D7 TSYNEN - Timer clock select 0:AD12, 1:HSYNC - D6 Prg Bank 0 Reg 2 enable / disable 0:Disable 1:Enable - D5 RS232 enable / disable 0:Disable 1:Enable - D4 Bus output control 0: normal 1: tristate - D3 6000-7fff and 8000-ffff control - 0 will not active XRWB, 1 will activate - D2-D0 - program bank 0 selector - - */ - - logerror("vt03_410b_w %02x\n", data); - m_410x[0xb] = data; - update_banks(); - break; - } -} - -WRITE8_MEMBER(nes_vt_cy_state::vt03_41bx_w) -{ - logerror("vt03_41bx_w %02x %02x\n", offset, data); -} - -WRITE8_MEMBER(nes_vt_dg_state::vt03_411c_w) -{ - logerror("vt03_411c_w %02x\n", data); - m_411c = data; - update_banks(); -} - -WRITE8_MEMBER(nes_vt_cy_state::vt03_411c_w) -{ - logerror("vt03_411c_w %02x\n", data); - m_411c = data; - update_banks(); -} - -WRITE8_MEMBER(nes_vt_cy_state::vt03_412c_extbank_w) -{ - // bittboy (ok), mc_pg150 (not working) - logerror("%s: vt03_412c_extbank_w %02x\n", machine().describe_context(), data); - m_ahigh = (data & 0x04) ? (1 << 24) : 0x0; -} - -WRITE8_MEMBER(nes_vt_hh_state::vtfp_412c_extbank_w) -{ - // fcpocket - logerror("%s: vtfp_412c_extbank_w %02x\n", machine().describe_context(), data); - m_ahigh = (data & 0x01) ? (1 << 25) : 0x0; -} - -WRITE8_MEMBER(nes_vt_dg_state::vtfp_4242_w) -{ - logerror("vtfp_4242_w %02x\n", data); - m_4242 = data; -} - -WRITE8_MEMBER(nes_vt_hh_state::vtfp_411d_w) -{ - // controls chram access and mapper emulation modes in later models - logerror("vtfp_411d_w %02x\n", data); - m_411d = data; - update_banks(); -} - -WRITE8_MEMBER(nes_vt_dg_state::vtfa_412c_extbank_w) -{ - // fapocket (ok?) (also uses bank from config switch for fake cartridge slot) - logerror("%s: vtfa_412c_extbank_w %02x\n", machine().describe_context(), data); - m_ahigh = 0; - m_ahigh |= (data & 0x01) ? (1 << 25) : 0x0; - m_ahigh |= (data & 0x02) ? (1 << 24) : 0x0; -} - -READ8_MEMBER(nes_vt_dg_state::vtfa_412c_r) -{ - if (m_cartsel) - return m_cartsel->read(); - else - return 0; -} - -READ8_MEMBER(nes_vt_hh_state::vtfp_412d_r) -{ - if (m_cartsel) - return m_cartsel->read(); - else - return 0; -} - -READ8_MEMBER(nes_vt_cy_state::vt03_41bx_r) -{ - switch (offset) - { - case 0x07: - return 0x04; - default: - return 0x00; - } -} - -WRITE8_MEMBER(nes_vt_cy_state::vt03_48ax_w) -{ - logerror("vt03_48ax_w %02x %02x\n", offset, data); -} - -READ8_MEMBER(nes_vt_cy_state::vt03_48ax_r) -{ - switch (offset) - { - case 0x04: - return 0x01; - case 0x05: - return 0x01; - default: - return 0x00; - } -} - -WRITE8_MEMBER(nes_vt_cy_state::vt03_413x_w) -{ - logerror("vt03_413x_w %02x %02x\n", offset, data); - // VT168 style ALU ?? - m_413x[offset] = data; - if (offset == 0x5) - { - uint32_t res = uint32_t((m_413x[5] << 8) | m_413x[4]) * uint32_t((m_413x[1] << 8) | m_413x[0]); - m_413x[0] = res & 0xFF; - m_413x[1] = (res >> 8) & 0xFF; - m_413x[2] = (res >> 16) & 0xFF; - m_413x[3] = (res >> 24) & 0xFF; - m_413x[6] = 0x00; - - } - else if (offset == 0x6) - { - /*uint32_t res = uint32_t((m_413x[5] << 8) | m_413x[4]) * uint32_t((m_413x[1] << 8) | m_413x[0]); - m_413x[0] = res & 0xFF; - m_413x[1] = (res >> 8) & 0xFF; - m_413x[2] = (res >> 16) & 0xFF; - m_413x[3] = (res >> 24) & 0xFF;*/ - m_413x[6] = 0x00; - } -} - - -READ8_MEMBER(nes_vt_cy_state::vt03_413x_r) -{ - logerror("vt03_413x_r %02x\n", offset); - return m_413x[offset]; -} - -READ8_MEMBER(nes_vt_cy_state::vt03_414f_r) -{ - return 0xff; -} - -READ8_MEMBER(nes_vt_cy_state::vt03_415c_r) -{ - return 0xff; -} - -READ8_MEMBER(nes_vt_hh_state::vthh_414a_r) -{ - return 0x80; -} - - -READ8_MEMBER(nes_vt_state::spr_r) -{ - if (m_4242 & 0x1 || m_411d & 0x04) - { - return m_chrram[offset]; - } - else - { - int realaddr = calculate_real_video_address(offset, 0, 1); - - return m_vt_external_space->read8(realaddr); - } -} - -READ8_MEMBER(nes_vt_state::chr_r) -{ - if (m_4242 & 0x1 || m_411d & 0x04) - { - return m_chrram[offset]; - } - else - { - int realaddr = calculate_real_video_address(offset, 1, 0); - return m_vt_external_space->read8(realaddr); - } -} - - -WRITE8_MEMBER(nes_vt_state::chr_w) -{ - if (m_4242 & 0x1 || m_411d & 0x04) - { - logerror("vram write %04x %02x\n", offset, data); - m_chrram[offset] = data; - } -} - -WRITE8_MEMBER(nes_vt_hh_state::vtfp_411e_w) -{ - logerror("411e_w %02x\n", data); - if (data == 0x05) - dynamic_cast(*m_maincpu).set_next_scramble(true); - else if (data == 0x00) - dynamic_cast(*m_maincpu).set_next_scramble(false); -} - -WRITE8_MEMBER(nes_vt_hh_state::vtfp_4a00_w) -{ - logerror("4a00_w %02x\n", data); - //if(data == 0x80) - // dynamic_cast(*m_maincpu).set_scramble(false); -} - - -void nes_vt_state::scanline_irq(int scanline, int vblank, int blanked) -{ - video_irq(false, scanline, vblank, blanked); -} - -void nes_vt_state::hblank_irq(int scanline, int vblank, int blanked) -{ - video_irq(true, scanline, vblank, blanked); -} - -void nes_vt_state::video_irq(bool hblank, int scanline, int vblank, int blanked) -{ - //TSYNEN - if (((m_410x[0xb] >> 7) & 0x01) == hblank) - { - int irqstate = 0; - - //logerror("scanline_irq %d\n", scanline); - - if (m_timer_running && scanline < 0xe0) - { - m_timer_val--; - - if (m_timer_val < 0) - { - if (m_timer_irq_enabled && !blanked) - { - logerror("scanline_irq %d\n", scanline); - irqstate = 1; - } - } - } - - if (irqstate) - m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE); - //else - // m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); - } -} - -/* todo, handle custom VT nametable stuff here */ -READ8_MEMBER(nes_vt_state::nt_r) -{ - return m_ntram[decode_nt_addr(offset)]; -} - -WRITE8_MEMBER(nes_vt_state::nt_w) -{ - //logerror("nt wr %04x %02x", offset, data); - m_ntram[decode_nt_addr(offset)] = data; -} - -void nes_vt_state::machine_start() -{ - save_item(NAME(m_410x)); - save_item(NAME(m_413x)); - - save_item(NAME(m_411c)); - save_item(NAME(m_411d)); - save_item(NAME(m_4242)); - - save_item(NAME(m_8000_addr_latch)); - - save_item(NAME(m_timer_irq_enabled)); - save_item(NAME(m_timer_running)); - save_item(NAME(m_timer_val)); - save_item(NAME(m_vdma_ctrl)); - - m_ntram = std::make_unique(0x2000); - save_pointer(NAME(m_ntram), 0x2000); - - m_chrram = std::make_unique(0x2000); - save_pointer(NAME(m_chrram), 0x2000); - - m_ppu->set_scanline_callback(*this, FUNC(nes_vt_state::scanline_irq)); - m_ppu->set_hblank_callback(*this, FUNC(nes_vt_state::hblank_irq)); - - //m_ppu->set_hblank_callback(*m_cartslot->m_cart, FUNC(device_nes_cart_interface::hblank_irq))); - //m_ppu->space(AS_PROGRAM).install_readwrite_handler(0, 0x1fff, read8_delegate(*m_cartslot->m_cart, FUNC(device_nes_cart_interface::chr_r)), write8_delegate(*m_cartslot->m_cart, FUNC(device_nes_cart_interface::chr_w))); - m_ppu->space(AS_PROGRAM).install_readwrite_handler(0x2000, 0x3eff, read8_delegate(*this, FUNC(nes_vt_state::nt_r)), write8_delegate(*this, FUNC(nes_vt_state::nt_w))); - m_ppu->space(AS_PROGRAM).install_readwrite_handler(0, 0x1fff, read8_delegate(*this, FUNC(nes_vt_state::chr_r)), write8_delegate(*this, FUNC(nes_vt_state::chr_w))); -} - -void nes_vt_state::machine_reset() -{ - // what are the actual defaults? - m_410x[0x0] = 0x00; - m_410x[0x1] = 0x00; - m_410x[0x2] = 0x00; - m_410x[0x3] = 0x00; - m_410x[0x4] = 0x00; - m_410x[0x5] = 0x00; - m_410x[0x6] = 0x00; - m_410x[0x7] = 0x00; - m_410x[0x8] = 0x01; - m_410x[0x9] = 0x02; - m_410x[0xa] = 0x00; - m_410x[0xb] = 0x00; - m_411c = 0x00; - m_411d = 0x00; - m_4242 = 0x00; - - m_timer_irq_enabled = 0; - m_timer_running = 0; - m_timer_val = 0; - m_vdma_ctrl = 0; - - update_banks(); - - // 'no scramble' configuration - m_8000_scramble[0x0] = 0x6; - m_8000_scramble[0x1] = 0x7; - m_8000_scramble[0x2] = 0x2; - m_8000_scramble[0x3] = 0x3; - m_8000_scramble[0x4] = 0x4; - m_8000_scramble[0x5] = 0x5; - m_8000_scramble[0x6] = 0x7; - m_8000_scramble[0x7] = 0x8; - - m_410x_scramble[0x0] = 0x7; - m_410x_scramble[0x1] = 0x8; -} - -void nes_vt_dg_fapocket_state::machine_reset() -{ - nes_vt_state::machine_reset(); - - // fapocket needs this, fcpocket instead reads the switch in software? - if (m_cartsel) - m_ahigh = (m_cartsel->read() == 0x01) ? (1 << 25) : 0x0; - else - m_ahigh = 0; -} - -int nes_vt_state::calculate_real_video_address(int addr, int extended, int readtype) -{ - // might be a VT09 only feature (alt 4bpp mode?) - int alt_order = m_ppu->get_201x_reg(0x0) & 0x40; - - if (readtype == 0) - { - if (m_ppu->get_201x_reg(0x0) & 0x10) - { - extended = 1; - } - else - { - extended = 0; - } - } - else if (readtype == 1) - { - if (m_ppu->get_201x_reg(0x0) & 0x08) - { - extended = 1; - } - else - { - extended = 0; - } - } - - /* - Calculating TVA17 - TVA10 - - -------------------------------------------------------------------------------------------- - | COMR7 | AD[12:10] | TVA17 | TVA16 | TVA15 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | - | (4105, 0x80) | (2006) | | | | | | | | | - -------------------------------------------------------------------------------------------- - | 0/1/C/D | RV47 | RV46 | RV45 | RV44 | RV43 | RV42 | RV41 | AD10 | ** RV40 is never used - | 2/3/E/F | RV57 | RV56 | RV55 | RV54 | RV53 | RV52 | RV51 | AD10 | ** RV50 is never used - | 4/8 | RV07 | RV06 | RV05 | RV04 | RV03 | RV02 | RV01 | RV00 | - | 5/9 | RV17 | RV16 | RV15 | RV14 | RV13 | RV12 | RV11 | RV10 | - | 6/A | RV27 | RV26 | RV25 | RV24 | RV23 | RV22 | RV21 | RV20 | - | 7/B | RV37 | RV36 | RV35 | RV34 | RV33 | RV32 | RV31 | RV30 | - -------------------------------------------------------------------------------------------- - - m_r2012 = rv0x - m_r2013 = rv1x - m_r2014 = rv2x - m_r2015 = rv3x - m_r2016 = rv4x - m_r2017 = rv5x - - */ - int finaladdr = 0; - - int sel = (addr & 0x1c00) | ((m_410x[0x5] & 0x80) ? 0x2000 : 0x000); - - int vbank_tva17_tva10 = 0x00; - - switch ((sel >> 10) & 0xf) - { - case 0x0: - case 0x1: - case 0xc: - case 0xd: - vbank_tva17_tva10 = (m_ppu->get_201x_reg(0x6) & 0xfe) | ((addr & 0x0400) ? 1 : 0); - break; - - case 0x2: - case 0x3: - case 0xe: - case 0xf: - vbank_tva17_tva10 = (m_ppu->get_201x_reg(0x7) & 0xfe) | ((addr & 0x0400) ? 1 : 0); - break; - - case 0x4: - case 0x8: - vbank_tva17_tva10 = m_ppu->get_201x_reg(0x2); - break; - - case 0x5: - case 0x9: - vbank_tva17_tva10 = m_ppu->get_201x_reg(0x3); - break; - - case 0x6: - case 0xa: - vbank_tva17_tva10 = m_ppu->get_201x_reg(0x4); - break; - - case 0x7: - case 0xb: - vbank_tva17_tva10 = m_ppu->get_201x_reg(0x5); - break; - - } - - /* - Calculating VA17 - VA10 (requires TVA17-TVA10 to have been calculated) - - ------------------------------------------------------------------------------ - | VB0S[2:0] | VA[17:10] | - | 201a & 0x7 | VA17 | VA16 | VA15 | VA14 | VA13 | VA12 | VA11 | VA10 | - |----------------------------------------------------------------------------- - | 0x0 | TVA17 | TVA16 | TVA15 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | - | 0x1 | TV67 | TVA16 | TVA15 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | - | 0x2 | RV67 | RV66 | TVA15 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | - | 0x3 | INVALID ***************************************************** | - | 0x4 | RV67 | RV66 | RV65 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | - | 0x5 | RV67 | RV66 | RV65 | RV64 | TVA13 | TVA12 | TVA11 | TVA10 | - | 0x6 | RV67 | RV66 | RV65 | RV64 | RV63 | TVA12 | TVA11 | TVA10 | - | 0x7 | INVALID ***************************************************** | - ------------------------------------------------------------------------------ - - RV67- RV63 = 0x201a & 0xf8 - - */ - - int va17_va10 = 0; - - int swit = m_ppu->get_201x_reg(0xa); - - switch (swit & 0x07) - { - case 0x0: va17_va10 = vbank_tva17_tva10; break; - case 0x1: va17_va10 = (vbank_tva17_tva10 & 0x7f) | (m_ppu->get_201x_reg(0xa) & 0x80); break; - case 0x2: va17_va10 = (vbank_tva17_tva10 & 0x3f) | (m_ppu->get_201x_reg(0xa) & 0xc0); break; - case 0x3: return -1; - case 0x4: va17_va10 = (vbank_tva17_tva10 & 0x1f) | (m_ppu->get_201x_reg(0xa) & 0xe0); break; - case 0x5: va17_va10 = (vbank_tva17_tva10 & 0x0f) | (m_ppu->get_201x_reg(0xa) & 0xf0); break; - case 0x6: va17_va10 = (vbank_tva17_tva10 & 0x07) | (m_ppu->get_201x_reg(0xa) & 0xf8); break; - case 0x7: return -1; - } - - int va34 = m_ppu->get_va34(); - - if (!extended) - { - int is4bpp = 0; - if (readtype == 0) is4bpp = m_ppu->get_201x_reg(0x0) & 0x02; - else if (readtype == 1) is4bpp = m_ppu->get_201x_reg(0x0) & 0x04; - - int va20_va18 = (m_ppu->get_201x_reg(0x8) & 0x70) >> 4; - - finaladdr = ((m_410x[0x0] & 0x0F) << 21) | (va20_va18 << 18) | (va17_va10 << 10) | (addr & 0x03ff); - - if (is4bpp) - { - if (!alt_order) - { - finaladdr = ((finaladdr & ~0xf) << 1) | (va34 << 4) | (finaladdr & 0xf); - } - else - { - finaladdr = (finaladdr << 1) | va34; - } - } - } - else - { - int eva2_eva0 = 0x00; - int is4bpp = 0; - - switch (readtype) - { - case 0: // background display - is4bpp = m_ppu->get_201x_reg(0x0) & 0x02; - - eva2_eva0 |= m_ppu->get_m_read_bg4_bg3(); - - if (m_ppu->get_201x_reg(0x1) & 0x02) - { - if (m_410x[0x6] & 0x1) eva2_eva0 |= 0x4; - } - else - { - if (m_ppu->get_201x_reg(0x8) & 0x08) eva2_eva0 |= 0x4; - } - break; - - case 1: // sprite display - is4bpp = m_ppu->get_201x_reg(0x0) & 0x04; // 16 colors or 16-pixel wide (both adjust the read) - - eva2_eva0 |= m_ppu->get_speva2_speva0(); - - break; - - case 2: // CPU R/W access - // todo - break; - } - - finaladdr = ((m_410x[0x0] & 0x0f) << 21) | (va17_va10 << 13) | (eva2_eva0 << 10) | (addr & 0x03ff); - - if (is4bpp) - { - if (!alt_order) - { - finaladdr = ((finaladdr & ~0xf) << 1) | (va34 << 4) | (finaladdr & 0xf); - } - else - { - finaladdr = (finaladdr << 1) | va34; - } - - } - } - return /*m_ahigh |*/ finaladdr; -} - -/* - nes_vt_state::vt03_8000_mapper_w notes - - used for MMC3/other mapper compatibility - some consoles have scrambled registers for crude copy protection - - is this always there with VT based games? it maps where mappers would be on a NES cartridge - but then seems to be able to alter internal state of extended PPU registers, which is awkward -*/ - -void nes_vt_state::scrambled_8000_w(address_space& space, uint16_t offset, uint8_t data) -{ - offset &= 0x7fff; - - uint16_t addr = m_real_access_address; // we need the actual write address, not the translated one, to keep bittboy happy - if ((m_411d & 0x01) && (m_411d & 0x03)) - { - //CNROM compat - logerror("%s: vtxx_cnrom_8000_w real address: (%04x) translated address: (%04x) %02x\n", machine().describe_context(), addr, offset + 0x8000, data); - m_ppu->set_201x_reg(0x6, data * 8); - m_ppu->set_201x_reg(0x7, data * 8 + 2); - m_ppu->set_201x_reg(0x2, data * 8 + 4); - m_ppu->set_201x_reg(0x3, data * 8 + 5); - m_ppu->set_201x_reg(0x4, data * 8 + 6); - m_ppu->set_201x_reg(0x5, data * 8 + 7); - - } - else if (m_411d & 0x01) - { - //MMC1 compat, TODO - logerror("%s: vtxx_mmc1_8000_w real address: (%04x) translated address: (%04x) %02x\n", machine().describe_context(), addr, offset + 0x8000, data); - - } - else if (m_411d & 0x02) - { - //UNROM compat - logerror("%s: vtxx_unrom_8000_w real address: (%04x) translated address: (%04x) %02x\n", machine().describe_context(), addr, offset + 0x8000, data); - - m_410x[0x7] = ((data & 0x0F) << 1); - m_410x[0x8] = ((data & 0x0F) << 1) + 1; - update_banks(); - } - else - { - //logerror("%s: vtxx_mmc3_8000_w real address: (%04x) translated address: (%04x) %02x\n", machine().describe_context(), addr, offset+0x8000, data ); - - //MMC3 compat - if ((addr < 0xA000) && !(addr & 0x01)) - { - logerror("%s: scrambled_8000_w real address: (%04x) translated address: (%04x) %02x (banking)\n", machine().describe_context(), addr, offset + 0x8000, data); - // Bank select - m_8000_addr_latch = data & 0x07; - // Bank config - m_410x[0x05] = data & ~(1 << 5); - update_banks(); - } - else if ((addr < 0xA000) && (addr & 0x01)) - { - logerror("%s: scrambled_8000_w real address: (%04x) translated address: (%04x) %02x (other scrambled stuff)\n", machine().describe_context(), addr, offset + 0x8000, data); - - switch (m_410x[0x05] & 0x07) - { - case 0x00: - m_ppu->set_201x_reg(m_8000_scramble[0], data); - break; - - case 0x01: - m_ppu->set_201x_reg(m_8000_scramble[1], data); - break; - - case 0x02: // hand? - m_ppu->set_201x_reg(m_8000_scramble[2], data); - break; - - case 0x03: // dog? - m_ppu->set_201x_reg(m_8000_scramble[3], data); - break; - - case 0x04: // ball thrown - m_ppu->set_201x_reg(m_8000_scramble[4], data); - break; - - case 0x05: // ball thrown - m_ppu->set_201x_reg(m_8000_scramble[5], data); - break; - case 0x06: - m_410x[m_8000_scramble[6]] = data; - //m_410x[0x9] = data; - update_banks(); - break; - - case 0x07: - m_410x[m_8000_scramble[7]] = data; - update_banks(); - break; - } - } - else if ((addr >= 0xA000) && (addr < 0xC000) && !(addr & 0x01)) - { - // Mirroring - m_410x[0x6] &= 0xFE; - m_410x[0x6] |= data & 0x01; - } - else if ((addr >= 0xA000) && (addr < 0xC000) && (addr & 0x01)) - { - // PRG RAM control, ignore - } - else if ((addr >= 0xC000) && (addr < 0xE000) && !(addr & 0x01)) - { - // IRQ latch - vt03_410x_w(space, 1, data); - } - else if ((addr >= 0xC000) && (addr < 0xE000) && (addr & 0x01)) - { - // IRQ reload - vt03_410x_w(space, 2, data); - } - else if ((addr >= 0xE000) && !(addr & 0x01)) - { - // IRQ disable - vt03_410x_w(space, 3, data); - } - else if ((addr >= 0xE000) && (addr & 0x01)) - { - // IRQ enable - vt03_410x_w(space, 4, data); - } - else - { - - } - } -} - -// MMC3 compatibility mode - -void nes_vt_state::set_8000_scramble(uint8_t reg0, uint8_t reg1, uint8_t reg2, uint8_t reg3, uint8_t reg4, uint8_t reg5, uint8_t reg6, uint8_t reg7) -{ - m_8000_scramble[0] = reg0; // TODO: name the regs - m_8000_scramble[1] = reg1; - m_8000_scramble[2] = reg2; - m_8000_scramble[3] = reg3; - m_8000_scramble[4] = reg4; - m_8000_scramble[5] = reg5; - m_8000_scramble[6] = reg6; - m_8000_scramble[7] = reg7; -} - -void nes_vt_state::set_410x_scramble(uint8_t reg0, uint8_t reg1) -{ - m_410x_scramble[0] = reg0; // TODO: name the regs - m_410x_scramble[1] = reg1; -} - -WRITE8_MEMBER(nes_vt_state::vt03_8000_mapper_w) -{ - scrambled_8000_w(space, offset, data); - //logerror("%s: vt03_8000_mapper_w (%04x) %02x\n", machine().describe_context(), offset+0x8000, data ); -} - -/* APU plumbing, this is because we have a plain M6502 core in the VT03, otherwise this is handled in the core */ - -READ8_MEMBER(nes_vt_state::psg1_4014_r) -{ - //return m_apu->read(0x14); - return 0x00; -} - -READ8_MEMBER(nes_vt_state::psg1_4015_r) -{ - return m_apu->read(0x15); -} - -WRITE8_MEMBER(nes_vt_state::psg1_4015_w) -{ - m_apu->write(0x15, data); -} - -WRITE8_MEMBER(nes_vt_state::psg1_4017_w) -{ - m_apu->write(0x17, data); -} - -// early units (VT03?) have a DMA bug in NTSC mode -WRITE8_MEMBER(nes_vt_state::vt_dma_w) -{ - do_dma(data, true); -} - -// later units (VT09?) don't appear to have the NTSC DMA bug? (or something else is incorrectly compensating for it in our emulation) -WRITE8_MEMBER(nes_vt_state::vt_fixed_dma_w) -{ - do_dma(data, false); -} - - -void nes_vt_state::do_dma(uint8_t data, bool has_ntsc_bug) -{ - // only NTSC systems have 'broken' DMA which requires the DMA addresses to be shifted by 1, PAL systems work as expected - if (m_ppu->get_is_pal()) - has_ntsc_bug = false; - - uint8_t dma_mode = m_vdma_ctrl & 0x01; - uint8_t dma_len = (m_vdma_ctrl >> 1) & 0x07; - uint8_t src_nib_74 = (m_vdma_ctrl >> 4) & 0x0F; - - int length = 256; - switch (dma_len) - { - case 0x0: length = 256; break; - case 0x4: length = 16; break; - case 0x5: length = 32; break; - case 0x6: length = 64; break; - case 0x7: length = 128; break; - } - - uint16_t src_addr = (data << 8) | (src_nib_74 << 4); - logerror("vthh dma start ctrl=%02x addr=%04x\n", m_vdma_ctrl, src_addr); - - if (dma_mode == 1) - { - logerror("vdma dest %04x\n", m_ppu->get_vram_dest()); - } - - if (has_ntsc_bug && (dma_mode == 1) && ((m_ppu->get_vram_dest() & 0xFF00) == 0x3F00) && !(m_ppu->get_201x_reg(0x1) & 0x80)) - { - length -= 1; - src_addr += 1; - } - else if ((dma_mode == 1) && ((m_ppu->get_vram_dest() & 0xFF00) == 0x3F01) && !(m_ppu->get_201x_reg(0x1) & 0x80)) - { - // Legacy mode for DGUN-2573 compat - m_ppu->set_vram_dest(0x3F00); - m_ppu->set_palette_mode(PAL_MODE_VT0x); - } - - for (int i = 0; i < length; i++) - { - uint8_t spriteData = m_maincpu->space(AS_PROGRAM).read_byte(src_addr + i); - if (dma_mode) - { - m_maincpu->space(AS_PROGRAM).write_byte(0x2007, spriteData); - } - else - { - m_maincpu->space(AS_PROGRAM).write_byte(0x2004, spriteData); - } - //if(((src_addr + i) & 0xFF) == length && (i != 0)) break; + m_latch0 >>= 1; + m_latch1_bit = m_latch1 & 0x01; + m_latch1 >>= 1; } - // should last (length * 4 - 1) CPU cycles. - //((device_t*)m_maincpu)->execute().adjust_icount(-(length * 4 - 1)); + m_previous_port0 = data; } -WRITE8_MEMBER(nes_vt_state::vt03_4034_w) -{ - logerror("vt03_4034_w %02x\n", data); - m_vdma_ctrl = data; -} -WRITE8_MEMBER(nes_vt_state::extra_io_control_w) +// ablping polls this (also writes here) what is it? 4-bit DAC? PCM? (inputs only start responding once it finishes writing data on startup but takes longer than a sample should) +// (this is the extended IO port on VT) +READ8_MEMBER(nes_vt_ablping_state::ablping_extraio_r) { - /* - 410d Extra I/O control - - 0x01 Extra I/O port 0 mode (1 = output, 0 = input) - 0x02 Extra I/O port 0 enable (1 = enable, 0 = disable) - 0x04 Extra I/O port 1 mode (1 = output, 0 = input) - 0x08 Extra I/O port 1 enable (1 = enable, 0 = disable) - 0x10 Extra I/O port 2 mode (1 = output, 0 = input) - 0x20 Extra I/O port 2 enable (1 = enable, 0 = disable) - 0x40 Extra I/O port 3 mode (1 = output, 0 = input) - 0x80 Extra I/O port 3 enable (1 = enable, 0 = disable) - */ - - logerror("%s: extra_io_control_w %02x\n", machine().describe_context(), data); -} + // needs to change at least + return machine().rand()&0xf; +}; -READ8_MEMBER(nes_vt_state::extrain_01_r) +WRITE8_MEMBER(nes_vt_ablping_state::ablping_extraio_w) { - // TODO: check status of 410d port to make sure we only read from enabled ports - uint8_t in0 = 0x00, in1 = 0x00; - if (m_exin0) - in0 = m_exin0->read() & 0x0f; - if (m_exin1) - in1 = m_exin1->read() & 0x0f; + popmessage("ablping_extraio_w %02x", data); +}; - return in0 | (in1<<4); -} -READ8_MEMBER(nes_vt_state::extrain_23_r) +void nes_vt_base_state::machine_start() { - // TODO: check status of 410d port to make sure we only read from enabled ports - uint8_t in2 = 0x00, in3 = 0x00; - if (m_exin2) - in2 = m_exin2->read() & 0x0f; - if (m_exin3) - in3 = m_exin3->read() & 0x0f; - - return in2 | (in3<<4); } -WRITE8_MEMBER(nes_vt_state::extraout_01_w) +void nes_vt_base_state::machine_reset() { - // TODO: use callbacks for this as output can be hooked up to anything - logerror("%s: extraout_01_w %02x\n", machine().describe_context(), data); -} -WRITE8_MEMBER(nes_vt_state::extraout_23_w) -{ - // TODO: use callbacks for this as output can be hooked up to anything - logerror("%s: extraout_23_w %02x\n", machine().describe_context(), data); } -READ8_MEMBER(nes_vt_state::rs232flags_region_r) +void nes_vt_dg_fapocket_state::machine_reset() { - /* - 0x4119 RS232 Flags + Region - - 0x01 - RX bit 8 - 0x02 - RERFF (error status) - 0x04 - unused - 0x08 - XPORN (PAL = 1 NTSC = 0) - 0x10 - XF5OR6 (50hz = 1 60hz = 0) - 0x20 - RINGF (receive status) - 0x40 - TIFLAG (completed sending data status) - 0x80 - RIFLAG (completed receiving data status) - */ - uint8_t ret = 0x00; - - // Palette DMA is buggy on NTSC systems (at least for regular VT03) - // so the palette DMA writes will change based on the reading of these flags - - ret |= m_ppu->get_is_pal() ? 0x08 : 0x00; - ret |= m_ppu->get_is_50hz() ? 0x10 : 0x00; + nes_vt_base_state::machine_reset(); - return ret; + // fapocket needs this, fcpocket instead reads the switch in software? + if (m_cartsel) + m_ahigh = (m_cartsel->read() == 0x01) ? (1 << 25) : 0x0; + else + m_ahigh = 0; } void nes_vt_ablpinb_state::machine_start() { - nes_vt_state::machine_start(); + nes_vt_base_state::machine_start(); save_item(NAME(m_plunger_off)); save_item(NAME(m_plunger_state_count)); @@ -1811,7 +644,7 @@ void nes_vt_ablpinb_state::machine_start() void nes_vt_ablpinb_state::machine_reset() { - nes_vt_state::machine_reset(); + nes_vt_base_state::machine_reset(); m_plunger_off = 0; m_plunger_state_count = 0; @@ -1884,166 +717,6 @@ WRITE8_MEMBER(nes_vt_sudoku_state::in0_w) { } -void nes_vt_state::nes_vt_map(address_map &map) -{ - map(0x0000, 0x07ff).ram(); - // ddrdismx relies on the mirroring - map(0x2000, 0x2007).mirror(0x00e0).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); /* standard PPU registers */ - map(0x2010, 0x201f).mirror(0x00e0).rw(m_ppu, FUNC(ppu_vt03_device::read_extended), FUNC(ppu_vt03_device::write_extended)); /* extra VT PPU registers */ - - map(0x4000, 0x4013).rw(m_apu, FUNC(nesapu_device::read), FUNC(nesapu_device::write)); - map(0x4014, 0x4014).r(FUNC(nes_vt_state::psg1_4014_r)).w(FUNC(nes_vt_state::vt_dma_w)); - map(0x4015, 0x4015).rw(FUNC(nes_vt_state::psg1_4015_r), FUNC(nes_vt_state::psg1_4015_w)); /* PSG status / first control register */ - map(0x4016, 0x4016).rw(FUNC(nes_vt_state::in0_r), FUNC(nes_vt_state::in0_w)); - map(0x4017, 0x4017).r(FUNC(nes_vt_state::in1_r)).w(FUNC(nes_vt_state::psg1_4017_w)); - - map(0x4034, 0x4034).w(FUNC(nes_vt_state::vt03_4034_w)); - - map(0x4100, 0x410b).r(FUNC(nes_vt_state::vt03_410x_r)).w(FUNC(nes_vt_state::vt03_410x_w)); - // 0x410c unused - map(0x410d, 0x410d).w(FUNC(nes_vt_state::extra_io_control_w)); - map(0x410e, 0x410e).rw(FUNC(nes_vt_state::extrain_01_r), FUNC(nes_vt_state::extraout_01_w)); - map(0x410f, 0x410f).rw(FUNC(nes_vt_state::extrain_23_r), FUNC(nes_vt_state::extraout_23_w)); - // 0x4114 RS232 timer (low) - // 0x4115 RS232 timer (high) - // 0x4116 unused - // 0x4117 unused - // 0x4118 unused - map(0x4119, 0x4119).r(FUNC(nes_vt_state::rs232flags_region_r)); - // 0x411a RS232 TX data - // 0x411b RS232 RX data - - map(0x8000, 0xffff).rw(FUNC(nes_vt_state::external_space_read), FUNC(nes_vt_state::external_space_write)); - map(0x6000, 0x7fff).ram(); -} - -/* Some later VT models have more RAM */ -void nes_vt_state::nes_vt_4k_ram_map(address_map &map) -{ - nes_vt_map(map); - map(0x0800, 0x0fff).ram(); -} - -void nes_vt_ablping_state::nes_vt_ablping_map(address_map &map) -{ - nes_vt_map(map); - map(0x410f, 0x410f).rw(FUNC(nes_vt_ablping_state::ablping_410f_r), FUNC(nes_vt_ablping_state::ablping_410f_w)); -} - -void nes_vt_cy_state::nes_vt_cy_map(address_map &map) -{ - nes_vt_4k_ram_map(map); - map(0x41b0, 0x41bf).r(FUNC(nes_vt_cy_state::vt03_41bx_r)).w(FUNC(nes_vt_cy_state::vt03_41bx_w)); - map(0x48a0, 0x48af).r(FUNC(nes_vt_cy_state::vt03_48ax_r)).w(FUNC(nes_vt_cy_state::vt03_48ax_w)); - map(0x4130, 0x4136).r(FUNC(nes_vt_cy_state::vt03_413x_r)).w(FUNC(nes_vt_cy_state::vt03_413x_w)); - map(0x414F, 0x414F).r(FUNC(nes_vt_cy_state::vt03_414f_r)); - map(0x415C, 0x415C).r(FUNC(nes_vt_cy_state::vt03_415c_r)); - -} - -void nes_vt_cy_state::nes_vt_bt_map(address_map &map) -{ - nes_vt_4k_ram_map(map); - map(0x412c, 0x412c).w(FUNC(nes_vt_cy_state::vt03_412c_extbank_w)); -} - - -void nes_vt_hh_state::nes_vt_hh_map(address_map &map) -{ - map(0x0000, 0x1fff).mask(0x0fff).ram(); - map(0x2000, 0x2007).mirror(0x00e0).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); /* standard PPU registers */ - map(0x2010, 0x201f).mirror(0x00e0).rw(m_ppu, FUNC(ppu_vt03_device::read_extended), FUNC(ppu_vt03_device::write_extended)); /* extra VT PPU registers */ - - map(0x4000, 0x4013).rw(m_apu, FUNC(nesapu_device::read), FUNC(nesapu_device::write)); - map(0x4015, 0x4015).rw(FUNC(nes_vt_hh_state::psg1_4015_r), FUNC(nes_vt_hh_state::psg1_4015_w)); /* PSG status / first control register */ - map(0x4016, 0x4016).rw(FUNC(nes_vt_hh_state::in0_r), FUNC(nes_vt_hh_state::in0_w)); - map(0x4017, 0x4017).r(FUNC(nes_vt_hh_state::in1_r)).w(FUNC(nes_vt_hh_state::psg1_4017_w)); - - map(0x4100, 0x410b).r(FUNC(nes_vt_hh_state::vt03_410x_r)).w(FUNC(nes_vt_hh_state::vt03_410x_w)); - - map(0x8000, 0xffff).rw(FUNC(nes_vt_hh_state::external_space_read), FUNC(nes_vt_hh_state::external_space_write)); - - map(0x4034, 0x4034).w(FUNC(nes_vt_hh_state::vt03_4034_w)); - map(0x4014, 0x4014).r(FUNC(nes_vt_hh_state::psg1_4014_r)).w(FUNC(nes_vt_hh_state::vt_fixed_dma_w)); - - map(0x4119, 0x4119).r(FUNC(nes_vt_hh_state::rs232flags_region_r)); - map(0x414a, 0x414a).r(FUNC(nes_vt_hh_state::vthh_414a_r)); - map(0x411d, 0x411d).w(FUNC(nes_vt_hh_state::vtfp_411d_w)); - - map(0x6000, 0x7fff).ram(); -} - -void nes_vt_hh_state::nes_vt_hh_baddma_map(address_map &map) -{ - nes_vt_hh_map(map); - map(0x4014, 0x4014).w(FUNC(nes_vt_hh_state::vt_dma_w)); -} - - -READ8_MEMBER(nes_vt_hh_state::vtfp_4119_r) -{ - // would be PAL/NTSC etc. in base system, maybe different here? - return 0x00; -} - -void nes_vt_hh_state::nes_vt_fp_map(address_map &map) -{ - nes_vt_hh_map(map); - map(0x411e, 0x411e).w(FUNC(nes_vt_hh_state::vtfp_411e_w)); - map(0x4a00, 0x4a00).w(FUNC(nes_vt_hh_state::vtfp_4a00_w)); - map(0x412c, 0x412c).w(FUNC(nes_vt_hh_state::vtfp_412c_extbank_w)); - map(0x412d, 0x412d).r(FUNC(nes_vt_hh_state::vtfp_412d_r)); - map(0x4242, 0x4242).w(FUNC(nes_vt_hh_state::vtfp_4242_w)); - map(0x4119, 0x4119).r(FUNC(nes_vt_hh_state::vtfp_4119_r)); -} - - -void nes_vt_dg_state::nes_vt_dg_map(address_map &map) -{ - map(0x0000, 0x1fff).ram(); - map(0x2000, 0x2007).mirror(0x00e0).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); /* standard PPU registers */ - map(0x2010, 0x201f).mirror(0x00e0).rw(m_ppu, FUNC(ppu_vt03_device::read_extended), FUNC(ppu_vt03_device::write_extended)); /* extra VT PPU registers */ - - map(0x4000, 0x4013).rw(m_apu, FUNC(nesapu_device::read), FUNC(nesapu_device::write)); - map(0x4015, 0x4015).rw(FUNC(nes_vt_dg_state::psg1_4015_r), FUNC(nes_vt_dg_state::psg1_4015_w)); /* PSG status / first control register */ - map(0x4016, 0x4016).rw(FUNC(nes_vt_dg_state::in0_r), FUNC(nes_vt_dg_state::in0_w)); - map(0x4017, 0x4017).r(FUNC(nes_vt_dg_state::in1_r)).w(FUNC(nes_vt_dg_state::psg1_4017_w)); - - map(0x4100, 0x410b).r(FUNC(nes_vt_dg_state::vt03_410x_r)).w(FUNC(nes_vt_dg_state::vt03_410x_w)); - - map(0x411c, 0x411c).w(FUNC(nes_vt_dg_state::vt03_411c_w)); - - map(0x8000, 0xffff).rw(FUNC(nes_vt_dg_state::external_space_read), FUNC(nes_vt_dg_state::external_space_write)); - - map(0x4034, 0x4034).w(FUNC(nes_vt_dg_state::vt03_4034_w)); - map(0x4014, 0x4014).r(FUNC(nes_vt_dg_state::psg1_4014_r)).w(FUNC(nes_vt_dg_state::vt_fixed_dma_w)); - map(0x6000, 0x7fff).ram(); -} - -void nes_vt_dg_state::nes_vt_dg_baddma_map(address_map& map) -{ - nes_vt_dg_map(map); - map(0x4014, 0x4014).w(FUNC(nes_vt_hh_state::vt_dma_w)); -} - -void nes_vt_dg_state::nes_vt_fa_map(address_map &map) -{ - nes_vt_dg_map(map); - - map(0x412c, 0x412c).r(FUNC(nes_vt_dg_state::vtfa_412c_r)).w(FUNC(nes_vt_dg_state::vtfa_412c_extbank_w)); - map(0x4242, 0x4242).w(FUNC(nes_vt_dg_state::vtfp_4242_w)); -} - - -WRITE_LINE_MEMBER(nes_vt_state::apu_irq) -{ -// set_input_line(N2A03_APU_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); -} - -READ8_MEMBER(nes_vt_state::apu_read_mem) -{ - return 0x00;//mintf->program->read_byte(offset); -} /* not strictly needed, but helps us see where things are in ROM to aid with figuring out banking schemes*/ static const gfx_layout helper_layout = @@ -2073,247 +746,274 @@ static GFXDECODE_START( vt03_gfx_helper ) GFXDECODE_ENTRY( "mainrom", 0, helper2_layout, 0x0, 2 ) GFXDECODE_END -uint32_t nes_vt_state::screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect) -{ - return m_ppu->screen_update(screen, bitmap, cliprect); -} - -void nes_vt_state::nes_vt_base(machine_config &config) -{ - /* basic machine hardware */ - M6502_VTSCR(config, m_maincpu, NTSC_APU_CLOCK); // selectable speed? - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_state::nes_vt_map); - - SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_refresh_hz(60.0988); - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC((113.66/(NTSC_APU_CLOCK.dvalue()/1000000)) * - (ppu2c0x_device::VBLANK_LAST_SCANLINE_NTSC-ppu2c0x_device::VBLANK_FIRST_SCANLINE+1+2))); - m_screen->set_size(32*8, 262); - m_screen->set_visarea(0*8, 32*8-1, 0*8, 30*8-1); - m_screen->set_screen_update(FUNC(nes_vt_state::screen_update)); - - GFXDECODE(config, "gfxdecode", "ppu", vt03_gfx_helper); - - PPU_VT03(config, m_ppu, N2A03_NTSC_XTAL); - m_ppu->set_cpu_tag(m_maincpu); - m_ppu->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); - m_ppu->read_bg().set(FUNC(nes_vt_state::chr_r)); - m_ppu->read_sp().set(FUNC(nes_vt_state::spr_r)); - - ADDRESS_MAP_BANK(config, m_vt_external_space); - m_vt_external_space->set_options(ENDIANNESS_NATIVE, 8, 25, 0x2000000); -// m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_32mbyte); // no default map, set according to the ROM size and other things so mirroring works - - /* sound hardware */ - SPEAKER(config, "mono").front_center(); - - /* this should actually be a custom *almost* doubled up APU, however requires more thought - than just using 2 APUs as registers in the 2nd one affect the PCM channel mode but the - DMA control still comes from the 1st, but in the new mode, sound always outputs via the - 2nd. Probably need to split the APU into interface and sound gen logic. */ - NES_APU(config, m_apu, NTSC_APU_CLOCK); - m_apu->irq().set(FUNC(nes_vt_state::apu_irq)); - m_apu->mem_read().set(FUNC(nes_vt_state::apu_read_mem)); - m_apu->add_route(ALL_OUTPUTS, "mono", 0.50); -} - -void nes_vt_state::nes_vt_base_pal(machine_config &config) +void nes_vt_base_state::configure_soc(nes_vt_soc_device* soc) { - nes_vt_base(config); - - m_maincpu->set_clock(PALC_APU_CLOCK); - - PPU_VT03PAL(config.replace(), m_ppu, N2A03_PAL_XTAL); - m_ppu->set_cpu_tag(m_maincpu); - m_ppu->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); - m_ppu->read_bg().set(FUNC(nes_vt_state::chr_r)); - m_ppu->read_sp().set(FUNC(nes_vt_state::spr_r)); + soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_32mbyte); + soc->read_0_callback().set(FUNC(nes_vt_base_state::in0_r)); + soc->read_1_callback().set(FUNC(nes_vt_base_state::in1_r)); + soc->write_0_callback().set(FUNC(nes_vt_base_state::in0_w)); - /* video hardware */ - m_screen->set_refresh_hz(50.0070); - m_screen->set_vblank_time(ATTOSECONDS_IN_USEC((113.66 / (PALC_APU_CLOCK.dvalue() / 1000000)) * - (ppu2c0x_device::VBLANK_LAST_SCANLINE_PAL - ppu2c0x_device::VBLANK_FIRST_SCANLINE_PALC + 1 + 2))); - m_screen->set_size(32 * 8, 312); - m_screen->set_visarea(0 * 8, 32 * 8 - 1, 0 * 8, 30 * 8 - 1); + soc->extra_read_0_callback().set(FUNC(nes_vt_base_state::extrain_0_r)); + soc->extra_read_1_callback().set(FUNC(nes_vt_base_state::extrain_1_r)); + soc->extra_read_2_callback().set(FUNC(nes_vt_base_state::extrain_2_r)); + soc->extra_read_3_callback().set(FUNC(nes_vt_base_state::extrain_3_r)); } void nes_vt_sudoku_state::nes_vt_sudoku_512kb(machine_config &config) { - nes_vt_base(config); - m_vt_external_space->set_map(&nes_vt_sudoku_state::vt_external_space_map_512kbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_sudoku_state::vt_external_space_map_512kbyte); } void nes_vt_vg_1mb_majgnc_state::nes_vt_vg_1mb_majgnc(machine_config &config) { - nes_vt_base(config); - m_ppu->set_palette_mode(PAL_MODE_NEW_VG); - m_vt_external_space->set_map(&nes_vt_vg_1mb_majgnc_state::vt_external_space_map_1mbyte); -} - -void nes_vt_state::nes_vt(machine_config &config) -{ - nes_vt_base(config); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_default_palette_mode(PAL_MODE_NEW_VG); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_vg_1mb_majgnc_state::vt_external_space_map_1mbyte); } - void nes_vt_state::nes_vt_512kb(machine_config& config) { - nes_vt(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_512kbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_512kbyte); } void nes_vt_state::nes_vt_1mb(machine_config& config) { - nes_vt(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_1mbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_1mbyte); } void nes_vt_state::nes_vt_2mb(machine_config& config) { - nes_vt(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_2mbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_2mbyte); } void nes_vt_state::nes_vt_4mb(machine_config& config) { - nes_vt(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_2mbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_4mbyte); } void nes_vt_state::nes_vt_8mb(machine_config& config) { - nes_vt(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_8mbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_8mbyte); } void nes_vt_state::nes_vt_16mb(machine_config& config) { - nes_vt(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_16mbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_16mbyte); } void nes_vt_state::nes_vt_32mb(machine_config& config) { - nes_vt(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_32mbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_32mbyte); +} + +void nes_vt_state::nes_vt_pal_2mb(machine_config& config) +{ + NES_VT_SOC_PAL(config, m_soc, PAL_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_2mbyte); } +void nes_vt_state::nes_vt_pal_4mb(machine_config& config) +{ + NES_VT_SOC_PAL(config, m_soc, PAL_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_4mbyte); +} -void nes_vt_state::nes_vt_pal(machine_config &config) +void nes_vt_state::nes_vt_pal_8mb(machine_config& config) { - nes_vt_base_pal(config); + NES_VT_SOC_PAL(config, m_soc, PAL_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_8mbyte); } -void nes_vt_state::nes_vt_pal_2mb(machine_config& config) +void nes_vt_waixing_state::nes_vt_waixing_512kb(machine_config &config) { - nes_vt_pal(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_2mbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_waixing_state::vt_external_space_map_512kbyte); + m_soc->set_201x_descramble(0x3, 0x2, 0x7, 0x6, 0x5, 0x4); } -void nes_vt_state::nes_vt_pal_4mb(machine_config& config) +void nes_vt_waixing_state::nes_vt_waixing_2mb(machine_config &config) { - nes_vt_pal(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_4mbyte); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_waixing_state::vt_external_space_map_2mbyte); + m_soc->set_201x_descramble(0x3, 0x2, 0x7, 0x6, 0x5, 0x4); } -void nes_vt_state::nes_vt_pal_8mb(machine_config& config) +void nes_vt_waixing_alt_state::nes_vt_waixing_alt_pal_8mb(machine_config &config) { - nes_vt_pal(config); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_8mbyte); + NES_VT_SOC_PAL(config, m_soc, PAL_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_waixing_alt_state::vt_external_space_map_8mbyte); + m_soc->set_201x_descramble(0x3, 0x2, 0x7, 0x6, 0x5, 0x4); + m_soc->set_8000_scramble(0x5, 0x4, 0x3, 0x2, 0x7, 0x6, 0x7, 0x8); } -void nes_vt_waixing_state::machine_reset() +void nes_vt_hum_state::nes_vt_hummer_2mb(machine_config& config) { - nes_vt_state::machine_reset(); - m_ppu->set_201x_descramble(0x3, 0x2, 0x7, 0x6, 0x5, 0x4); // reasonable + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_sp69_state::vt_external_space_map_2mbyte); + m_soc->set_201x_descramble(0x7, 0x6, 0x5, 0x4, 0x2, 0x3); + m_soc->set_8000_scramble(0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x7, 0x8); + GFXDECODE(config, "gfxdecode", "soc:ppu", vt03_gfx_helper); } -void nes_vt_waixing_alt_state::machine_reset() +void nes_vt_hum_state::nes_vt_hummer_4mb(machine_config& config) { - nes_vt_waixing_state::machine_reset(); - set_8000_scramble(0x5, 0x4, 0x3, 0x2, 0x7, 0x6, 0x7, 0x8); + nes_vt_hummer_2mb(config); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hum_state::vt_external_space_map_4mbyte); } -void nes_vt_hum_state::machine_reset() +void nes_vt_pjoy_state::nes_vt_pjoy_4mb(machine_config &config) { - nes_vt_state::machine_reset(); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_sp69_state::vt_external_space_map_4mbyte); + m_soc->set_201x_descramble(0x2, 0x3, 0x4, 0x5, 0x6, 0x7); + m_soc->set_8000_scramble(0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x8, 0x7); + m_soc->set_410x_scramble(0x8, 0x7); + GFXDECODE(config, "gfxdecode", "soc:ppu", vt03_gfx_helper); +} + - m_ppu->set_201x_descramble(0x7, 0x6, 0x5, 0x4, 0x2, 0x3); - set_8000_scramble(0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x7, 0x8); +void nes_vt_sp69_state::nes_vt_4mb_sp69(machine_config& config) +{ + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_sp69_state::vt_external_space_map_4mbyte); + m_soc->set_201x_descramble(0x4, 0x7, 0x2, 0x6, 0x5, 0x3); + m_soc->set_8000_scramble(0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x7, 0x8); + GFXDECODE(config, "gfxdecode", "soc:ppu", vt03_gfx_helper); } -void nes_vt_pjoy_state::machine_reset() +void nes_vt_ablping_state::nes_vt_2mb_ablping(machine_config &config) { - nes_vt_state::machine_reset(); + NES_VT_SOC_PAL(config, m_soc, PAL_APU_CLOCK); + configure_soc(m_soc); - m_ppu->set_201x_descramble(0x2, 0x3, 0x4, 0x5, 0x6, 0x7); - set_8000_scramble(0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x8, 0x7); - set_410x_scramble(0x8, 0x7); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_ablping_state::vt_external_space_map_2mbyte); + m_soc->set_201x_descramble(0x4, 0x7, 0x2, 0x6, 0x5, 0x3); + m_soc->set_8000_scramble(0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x7, 0x8); + + m_soc->extra_read_2_callback().set(FUNC(nes_vt_ablping_state::ablping_extraio_r)); + m_soc->extra_read_3_callback().set(FUNC(nes_vt_ablping_state::ablping_extraio_r)); + m_soc->extra_write_2_callback().set(FUNC(nes_vt_ablping_state::ablping_extraio_w)); + m_soc->extra_write_3_callback().set(FUNC(nes_vt_ablping_state::ablping_extraio_w)); + + GFXDECODE(config, "gfxdecode", "soc:ppu", vt03_gfx_helper); } -void nes_vt_sp69_state::machine_reset() +READ8_MEMBER(nes_vt_base_state::upper_412c_r) { - nes_vt_state::machine_reset(); + logerror("%s: upper_412c_r\n", machine().describe_context()); + return 0x00; +} - m_ppu->set_201x_descramble(0x4, 0x7, 0x2, 0x6, 0x5, 0x3); - set_8000_scramble(0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x7, 0x8); +READ8_MEMBER(nes_vt_base_state::upper_412d_r) +{ + logerror("%s: upper_412d_r\n", machine().describe_context()); + return 0x00; } -void nes_vt_ablping_state::nes_vt_2mb_ablping(machine_config &config) +WRITE8_MEMBER(nes_vt_base_state::upper_412c_w) { - nes_vt(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_ablping_state::nes_vt_ablping_map); - m_vt_external_space->set_map(&nes_vt_ablping_state::vt_external_space_map_2mbyte); + logerror("%s: upper_412c_w %02x\n", machine().describe_context(), data); } + void nes_vt_state::nes_vt_4k_ram(machine_config &config) { - nes_vt(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_state::nes_vt_4k_ram_map); + /* basic machine hardware */ + NES_VT_SOC_4KRAM(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + + GFXDECODE(config, "gfxdecode", "soc:ppu", vt03_gfx_helper); + + dynamic_cast(*m_soc).upper_read_412c_callback().set(FUNC(nes_vt_state::upper_412c_r)); + dynamic_cast(*m_soc).upper_read_412d_callback().set(FUNC(nes_vt_state::upper_412d_r)); + dynamic_cast(*m_soc).upper_write_412c_callback().set(FUNC(nes_vt_state::upper_412c_w)); } void nes_vt_state::nes_vt_4k_ram_16mb(machine_config &config) { - nes_vt(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_state::nes_vt_4k_ram_map); - m_vt_external_space->set_map(&nes_vt_state::vt_external_space_map_16mbyte); + nes_vt_4k_ram(config); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_state::vt_external_space_map_16mbyte); } void nes_vt_state::nes_vt_4k_ram_pal(machine_config &config) { - nes_vt_base_pal(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_state::nes_vt_4k_ram_map); + nes_vt_4k_ram(config); // TODO, use PAL } void nes_vt_cy_state::nes_vt_cy(machine_config &config) { nes_vt_4k_ram(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_cy_state::nes_vt_cy_map); + + NES_VT_SOC_4KRAM_CY(config.replace(), m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); } void nes_vt_cy_state::nes_vt_cy_bigger(machine_config &config) { nes_vt_cy(config); - m_vt_external_space->set_map(&nes_vt_cy_state::vt_external_space_map_32mbyte); // must be some banking of this kind of VT can address over 32mb + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_cy_state::vt_external_space_map_32mbyte); // must be some banking of this kind of VT can address over 32mb } void nes_vt_cy_state::nes_vt_bt(machine_config &config) { nes_vt_4k_ram(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_cy_state::nes_vt_bt_map); + + NES_VT_SOC_4KRAM_BT(config.replace(), m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); +} + + +WRITE8_MEMBER(nes_vt_cy_state::bittboy_412c_w) +{ + //bittboy (ok), mc_pg150 (not working) + logerror("%s: vt03_412c_extbank_w %02x\n", machine().describe_context(), data); + m_ahigh = (data & 0x04) ? (1 << 24) : 0x0; } void nes_vt_cy_state::nes_vt_bt_2x16mb(machine_config& config) { nes_vt_bt(config); - m_vt_external_space->set_map(&nes_vt_cy_state::vt_external_space_map_bitboy_2x16mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_cy_state::vt_external_space_map_bitboy_2x16mbyte); + + dynamic_cast(*m_soc).upper_write_412c_callback().set(FUNC(nes_vt_cy_state::bittboy_412c_w)); } void nes_vt_dg_state::nes_vt_dg(machine_config &config) { nes_vt_4k_ram(config); + + NES_VT_SOC_8KRAM_DG(config.replace(), m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + + /* m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_dg_state::nes_vt_dg_map); m_screen->set_refresh_hz(50.0070); @@ -2321,56 +1021,57 @@ void nes_vt_dg_state::nes_vt_dg(machine_config &config) (ppu2c0x_device::VBLANK_LAST_SCANLINE_PAL-ppu2c0x_device::VBLANK_FIRST_SCANLINE+1+2))); m_screen->set_size(32*8, 312); m_screen->set_visarea(0*8, 32*8-1, 0*8, 30*8-1); + */ } void nes_vt_dg_state::nes_vt_dg_1mb(machine_config& config) { nes_vt_dg(config); - m_vt_external_space->set_map(&nes_vt_dg_state::vt_external_space_map_1mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_dg_state::vt_external_space_map_1mbyte); } void nes_vt_dg_state::nes_vt_dg_baddma_16mb(machine_config& config) { nes_vt_dg(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_dg_state::nes_vt_dg_baddma_map); - m_vt_external_space->set_map(&nes_vt_dg_state::vt_external_space_map_16mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_dg_state::vt_external_space_map_16mbyte); + } void nes_vt_hh_state::nes_vt_vg(machine_config &config) { nes_vt_dg(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::nes_vt_hh_map); - m_ppu->set_palette_mode(PAL_MODE_NEW_VG); + NES_VT_SOC_8KRAM_DG(config.replace(), m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + + m_soc->set_default_palette_mode(PAL_MODE_NEW_VG); + m_soc->force_bad_dma(); } void nes_vt_hh_state::nes_vt_vg_8mb(machine_config& config) { nes_vt_vg(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_8mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_8mbyte); } void nes_vt_hh_state::nes_vt_vg_4mb(machine_config& config) { nes_vt_vg(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_4mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_4mbyte); } void nes_vt_hh_state::nes_vt_vg_16mb(machine_config& config) { nes_vt_vg(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_16mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_16mbyte); } void nes_vt_hh_state::nes_vt_vg_1mb_majkon(machine_config &config) { nes_vt_dg(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::nes_vt_hh_baddma_map); - - m_ppu->set_palette_mode(PAL_MODE_NEW_VG); - - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_1mbyte); - + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_1mbyte); + + m_soc->set_default_palette_mode(PAL_MODE_NEW_VG); } @@ -2378,27 +1079,34 @@ void nes_vt_hh_state::nes_vt_vg_1mb_majkon(machine_config &config) void nes_vt_hh_state::nes_vt_hh(machine_config &config) { nes_vt_4k_ram(config); + + NES_VT_SOC_4KRAM_HH(config.replace(), m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + + m_soc->set_default_palette_mode(PAL_MODE_NEW_RGB); + m_soc->force_bad_dma(); + + /* m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::nes_vt_hh_map); - m_ppu->set_palette_mode(PAL_MODE_NEW_RGB); - /* video hardware */ m_screen->set_refresh_hz(50.0070); m_screen->set_vblank_time(ATTOSECONDS_IN_USEC((106.53/(PAL_APU_CLOCK.dvalue()/1000000)) * (ppu2c0x_device::VBLANK_LAST_SCANLINE_PAL-ppu2c0x_device::VBLANK_FIRST_SCANLINE+1+2))); m_screen->set_size(32*8, 312); m_screen->set_visarea(0*8, 32*8-1, 0*8, 30*8-1); + */ } void nes_vt_hh_state::nes_vt_hh_8mb(machine_config& config) { nes_vt_hh(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_8mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_8mbyte); } void nes_vt_hh_state::nes_vt_hh_4mb(machine_config& config) { nes_vt_hh(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_4mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_4mbyte); } static INPUT_PORTS_START( nes_vt ) @@ -2438,96 +1146,148 @@ static INPUT_PORTS_START( nes_vt_ddr ) PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED ) INPUT_PORTS_END + +READ8_MEMBER(nes_vt_hh_state::fcpocket_412d_r) +{ + if (m_cartsel) + return m_cartsel->read(); + else + return 0; +} + +WRITE8_MEMBER(nes_vt_hh_state::fcpocket_412c_w) +{ + // fcpocket + logerror("%s: vtfp_412c_extbank_w %02x\n", machine().describe_context(), data); + m_ahigh = (data & 0x01) ? (1 << 25) : 0x0; +} + void nes_vt_hh_state::nes_vt_fp(machine_config &config) { nes_vt_4k_ram(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::nes_vt_fp_map); - m_ppu->set_palette_mode(PAL_MODE_NEW_RGB12); + NES_VT_SOC_4KRAM_FP(config.replace(), m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + + m_soc->set_default_palette_mode(PAL_MODE_NEW_RGB12); + m_soc->force_bad_dma(); } + + void nes_vt_hh_state::nes_vt_fp_4x16mb(machine_config& config) { nes_vt_fp(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_fp_2x32mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_fp_2x32mbyte); + + dynamic_cast(*m_soc).upper_write_412c_callback().set(FUNC(nes_vt_hh_state::fcpocket_412c_w)); + dynamic_cast(*m_soc).upper_read_412d_callback().set(FUNC(nes_vt_hh_state::fcpocket_412d_r)); } void nes_vt_hh_state::nes_vt_fp_32mb(machine_config& config) { nes_vt_fp(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_32mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_32mbyte); } void nes_vt_hh_state::nes_vt_fp_bigger(machine_config& config) { nes_vt_fp(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_32mbyte); // must be some kind of banking, or this VT can address > 32Mbyte + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_32mbyte); // must be some kind of banking, or this VT can address > 32Mbyte } void nes_vt_hh_state::nes_vt_fp_16mb(machine_config& config) { nes_vt_fp(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_16mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_16mbyte); } void nes_vt_hh_state::nes_vt_fp_pal(machine_config &config) { - nes_vt_4k_ram_pal(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::nes_vt_fp_map); + nes_vt_fp(config); - m_ppu->set_palette_mode(PAL_MODE_NEW_RGB12); + // set to PAL } void nes_vt_hh_state::nes_vt_fp_pal_32mb(machine_config& config) { - nes_vt_fp_pal(config); - m_vt_external_space->set_map(&nes_vt_hh_state::vt_external_space_map_32mbyte); + nes_vt_4k_ram(config); + + NES_VT_SOC_4KRAM_FP_PAL(config.replace(), m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + + m_soc->set_default_palette_mode(PAL_MODE_NEW_RGB12); + m_soc->force_bad_dma(); + + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_hh_state::vt_external_space_map_32mbyte); } -void nes_vt_dg_state::nes_vt_fa(machine_config &config) +void nes_vt_dg_state::nes_vt_fa(machine_config& config) { nes_vt_4k_ram(config); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_dg_state::nes_vt_fa_map); + + NES_VT_SOC_8KRAM_FA(config.replace(), m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); } -void nes_vt_dg_state::nes_vt_fa_4x16mb(machine_config& config) + +READ8_MEMBER(nes_vt_dg_state::fapocket_412c_r) +{ + if (m_cartsel) + return m_cartsel->read(); + else + return 0; +} + +WRITE8_MEMBER(nes_vt_dg_state::fapocket_412c_w) +{ + // fapocket (ok?) (also uses bank from config switch for fake cartridge slot) + logerror("%s: vtfa_412c_extbank_w %02x\n", machine().describe_context(), data); + m_ahigh = 0; + m_ahigh |= (data & 0x01) ? (1 << 25) : 0x0; + m_ahigh |= (data & 0x02) ? (1 << 24) : 0x0; +} + +void nes_vt_dg_state::nes_vt_fa_4x16mb(machine_config& config) // fapocket { nes_vt_fa(config); - m_vt_external_space->set_map(&nes_vt_dg_state::vt_external_space_map_fapocket_4x16mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_dg_state::vt_external_space_map_fapocket_4x16mbyte); + + dynamic_cast(*m_soc).upper_read_412c_callback().set(FUNC(nes_vt_dg_state::fapocket_412c_r)); + dynamic_cast(*m_soc).upper_write_412c_callback().set(FUNC(nes_vt_dg_state::fapocket_412c_w)); } void nes_vt_swap_op_d5_d6_state::nes_vt_vh2009(machine_config &config) { - nes_vt(config); - - M6502_SWAP_OP_D5_D6(config.replace(), m_maincpu, NTSC_APU_CLOCK); - m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_swap_op_d5_d6_state::nes_vt_map); + NES_VT_SOC(config, m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); + + NES_VT_SOC_SCRAMBLE(config.replace(), m_soc, NTSC_APU_CLOCK); + configure_soc(m_soc); - //m_ppu->set_palette_mode(PAL_MODE_NEW_VG); // gives better title screens, but worse ingame, must be able to switch + //m_soc->set_default_palette_mode(PAL_MODE_NEW_VG); // gives better title screens, but worse ingame, must be able to switch } void nes_vt_swap_op_d5_d6_state::nes_vt_vh2009_4mb(machine_config& config) { nes_vt_vh2009(config); - m_vt_external_space->set_map(&nes_vt_swap_op_d5_d6_state::vt_external_space_map_4mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_swap_op_d5_d6_state::vt_external_space_map_4mbyte); } void nes_vt_swap_op_d5_d6_state::nes_vt_vh2009_8mb(machine_config& config) { nes_vt_vh2009(config); - m_vt_external_space->set_map(&nes_vt_swap_op_d5_d6_state::vt_external_space_map_8mbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_swap_op_d5_d6_state::vt_external_space_map_8mbyte); } void nes_vt_swap_op_d5_d6_state::nes_vt_senwld_512kb(machine_config &config) { nes_vt_vh2009(config); - - m_ppu->set_palette_mode(PAL_MODE_NEW_VG); - - m_vt_external_space->set_map(&nes_vt_swap_op_d5_d6_state::vt_external_space_map_senwld_512kbyte); + m_soc->set_addrmap(AS_PROGRAM, &nes_vt_swap_op_d5_d6_state::vt_external_space_map_senwld_512kbyte); + m_soc->set_default_palette_mode(PAL_MODE_NEW_VG); } static INPUT_PORTS_START( nes_vt_fp ) @@ -2994,30 +1754,11 @@ ROM_START( sudopptv ) ROM_LOAD( "sudokupnptvgame_29lv400tc_000422b9.bin", 0x00000, 0x80000, CRC(722cc36d) SHA1(1f6d1f57478cf175a36722b39c52eded4b669f81) ) ROM_END - ROM_START( ablping ) ROM_REGION( 0x200000, "mainrom", 0 ) ROM_LOAD( "abl_pingpong.bin", 0x00000, 0x200000, CRC(b31de1fb) SHA1(94e8afb2315ba1fa0892191c8e1832391e401c70) ) ROM_END - - -#if 0 -ROM_START( mc_15kin1 ) - ROM_REGION( 0x200000, "mainrom", 0 ) - ROM_LOAD( "15000in1.bin", 0x00000, 0x200000, CRC(29a8cb96) SHA1(c4b31964fbfc5ee97d4a4c7e4d418ea5d84a568d) ) -ROM_END - -ROM_START( mc_18kin1 ) - ROM_REGION( 0x400000, "mainrom", 0 ) - ROM_LOAD( "18000in1.bin", 0x00000, 0x400000, CRC(23c0c325) SHA1(4ad53b5e5a8e65571fd39760278cdf7a6371da47) ) -ROM_END - -ROM_START( gx121in1 ) - ROM_REGION( 0x400000, "mainrom", 0 ) - ROM_LOAD( "gx121in1.bin", 0x00000, 0x400000, CRC(0282d975) SHA1(9ead7505b99a60834724a5818ee120e03c8bf975) ) -ROM_END -#endif ROM_START( dgun2573 ) ROM_REGION( 0x2000000, "mainrom", 0 ) ROM_LOAD( "dgun2573.bin", 0x00000, 0x2000000, BAD_DUMP CRC(cde71a53) SHA1(d0d4c1965876291861781ecde46b1142b062f1f3) ) @@ -3179,12 +1920,12 @@ CONS( 2004, majkon, 0, 0, nes_vt_vg_1mb_majkon, nes_vt, nes_vt_hh_state, emp CONS( 200?, majgnc, 0, 0, nes_vt_vg_1mb_majgnc, majgnc, nes_vt_vg_1mb_majgnc_state, empty_init, "Majesco", "Golden Nugget Casino", MACHINE_NOT_WORKING ) // small black unit, dpad on left, 4 buttons (A,B,X,Y) on right, Start/Reset/Select in middle, unit text "Sudoku Plug & Play TV Game" -CONS( 200?, sudopptv, 0, 0, nes_vt_512kb, nes_vt, nes_vt_waixing_state, empty_init, "Smart Planet", "Sudoku Plug & Play TV Game '6 Intelligent Games'", MACHINE_NOT_WORKING ) +CONS( 200?, sudopptv, 0, 0, nes_vt_waixing_512kb, nes_vt, nes_vt_waixing_state, empty_init, "Smart Planet", "Sudoku Plug & Play TV Game '6 Intelligent Games'", MACHINE_NOT_WORKING ) -CONS( 200?, megapad, 0, 0, nes_vt_2mb, nes_vt, nes_vt_waixing_state, empty_init, "Waixing", "Megapad 31-in-1", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // Happy Biqi has broken sprites, investigate before promoting +CONS( 200?, megapad, 0, 0, nes_vt_waixing_2mb, nes_vt, nes_vt_waixing_state, empty_init, "Waixing", "Megapad 31-in-1", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // Happy Biqi has broken sprites, investigate before promoting // 060303 date code on PCB -CONS( 2006, ablmini, 0, 0, nes_vt_pal_8mb, nes_vt, nes_vt_waixing_alt_state, empty_init, "Advance Bright Ltd", "Double Players Mini Joystick 80-in-1 (MJ8500, ABL TV Game)", MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2006, ablmini, 0, 0, nes_vt_waixing_alt_pal_8mb, nes_vt, nes_vt_waixing_alt_state, empty_init, "Advance Bright Ltd", "Double Players Mini Joystick 80-in-1 (MJ8500, ABL TV Game)", MACHINE_IMPERFECT_GRAPHICS ) // needs PCM samples, Y button is not mapped (not used by any of the games?) CONS( 200?, timetp36, 0, 0, nes_vt_pal_4mb, timetp36, nes_vt_timetp36_state, empty_init, "TimeTop", "Super Game 36-in-1 (TimeTop SuperGame) (PAL)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) @@ -3244,11 +1985,6 @@ CONS( 2017, rtvgc300fz,0, 0, nes_vt_cy_bigger, nes_vt, nes_vt_cy_lexibook_stat CONS( 201?, red5mam, 0, 0, nes_vt_cy_bigger, nes_vt, nes_vt_cy_lexibook_state, empty_init, "Red5", "Mini Arcade Machine (Red5)", MACHINE_NOT_WORKING ) // 128Mbyte ROM, must be externally banked or different addressing scheme -// boots, same platform with scrambled opcodes as FC pocket -// palette issues in some games because they actually use the old VT style palette -// but no way to switch? -// some menu gfx broken, probably because this is a bad dump -CONS( 2015, dgun2573, 0, 0, nes_vt_fp_32mb, nes_vt, nes_vt_hh_state, empty_init, "dreamGEAR", "My Arcade Gamer V Portable Gaming System (DGUN-2573)", MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) CONS( 201?, denv150, 0, 0, nes_vt_cy_bigger, nes_vt, nes_vt_cy_lexibook_state, empty_init, "Denver", "Denver Game Console GMP-240C 150-in-1", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS ) @@ -3264,7 +2000,8 @@ CONS( 201?, techni4, 0, 0, nes_vt_pal_2mb, nes_vt, nes_vt_state, CONS( 200?, lpgm240, 0, 0, nes_vt_vh2009_8mb, nes_vt, nes_vt_swap_op_d5_d6_state, empty_init, "", "Let's Play! Game Machine 240 in 1", MACHINE_NOT_WORKING ) // mini 'retro-arcade' style cabinet // this has 'Shark' and 'Octopus' etc. like mc_dgear but uses scrambled bank registers -CONS( 200?, mc_sp69, 0, 0, nes_vt_4mb, nes_vt, nes_vt_sp69_state, empty_init, "", "Sports Game 69 in 1", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND) +// This was also often found in cart form with SunPlus / Famiclone hybrid systems to boost the game count, eg. the WiWi (ROM verified to match) +CONS( 200?, mc_sp69, 0, 0, nes_vt_4mb_sp69, nes_vt, nes_vt_sp69_state, empty_init, "", "Sports Game 69 in 1", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND) // this game was also sold by dreamGEAR and several others companies, each time with a different name and different case, although the dumped version was from ABL, and it hasn't been confirmed that the ROMs are identical for the other units // Super Ping Pong appears on the title screen, but not the box / product art which simply has "Ping Pong Plug & Play TV Game" on front/back/bottom/manual, and "Table Tennis Plug & Play TV Game" on left/right sides. Product code is PP1100 @@ -3272,13 +2009,13 @@ CONS( 200?, mc_sp69, 0, 0, nes_vt_4mb, nes_vt, nes_vt_sp69_state, empty_i CONS( 2006, ablping, 0, 0, nes_vt_2mb_ablping, nes_vt, nes_vt_ablping_state, empty_init, "Advance Bright Ltd", "Ping Pong / Table Tennis / Super Ping Pong (PP1100, ABL TV Game)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // Hummer systems, scrambled bank register -CONS( 200?, mc_sam60, 0, 0, nes_vt_2mb, nes_vt, nes_vt_hum_state, empty_init, "Hummer Technology Co., Ltd.", "Samuri (60 in 1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) -CONS( 200?, zdog, 0, 0, nes_vt_4mb, nes_vt, nes_vt_hum_state, empty_init, "Hummer Technology Co., Ltd.", "ZDog (44 in 1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) +CONS( 200?, mc_sam60, 0, 0, nes_vt_hummer_2mb, nes_vt, nes_vt_hum_state, empty_init, "Hummer Technology Co., Ltd.", "Samuri (60 in 1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) +CONS( 200?, zdog, 0, 0, nes_vt_hummer_4mb, nes_vt, nes_vt_hum_state, empty_init, "Hummer Technology Co., Ltd.", "ZDog (44 in 1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // very plain menus CONS( 200?, pjoyn50, 0, 0, nes_vt_4mb, nes_vt, nes_vt_state, empty_init, "", "PowerJoy Navigator 50 in 1", MACHINE_IMPERFECT_GRAPHICS ) -CONS( 200?, pjoys30, 0, 0, nes_vt_4mb, nes_vt, nes_vt_pjoy_state, empty_init, "", "PowerJoy Supermax 30 in 1", MACHINE_IMPERFECT_GRAPHICS ) -CONS( 200?, pjoys60, 0, 0, nes_vt_4mb, nes_vt, nes_vt_pjoy_state, empty_init, "", "PowerJoy Supermax 60 in 1", MACHINE_IMPERFECT_GRAPHICS ) +CONS( 200?, pjoys30, 0, 0, nes_vt_pjoy_4mb, nes_vt, nes_vt_pjoy_state, empty_init, "", "PowerJoy Supermax 30 in 1", MACHINE_IMPERFECT_GRAPHICS ) +CONS( 200?, pjoys60, 0, 0, nes_vt_pjoy_4mb, nes_vt, nes_vt_pjoy_state, empty_init, "", "PowerJoy Supermax 60 in 1", MACHINE_IMPERFECT_GRAPHICS ) // has a non-enhanced version of 'Octopus' as game 30 CONS( 200?, sarc110, 0, 0, nes_vt_4mb, nes_vt, nes_vt_state, empty_init, "", "Super Arcade 110 (set 1)", MACHINE_IMPERFECT_GRAPHICS ) CONS( 200?, sarc110a, sarc110, 0, nes_vt_4mb, nes_vt, nes_vt_state, empty_init, "", "Super Arcade 110 (set 2)", MACHINE_IMPERFECT_GRAPHICS ) @@ -3313,13 +2050,6 @@ CONS( 200?, mc_8x6ss, 0, 0, nes_vt_1mb, nes_vt, nes_vt_state, empty CONS( 2004, mc_dcat8, 0, 0, nes_vt_8mb, nes_vt, nes_vt_state, empty_init, "", "100 in 1 (D-CAT8 8bit Console, set 1) (v5.01.11-frd, BL 20041217)", MACHINE_IMPERFECT_GRAPHICS ) CONS( 2004, mc_dcat8a, mc_dcat8, 0, nes_vt_8mb, nes_vt, nes_vt_state, empty_init, "", "100 in 1 (D-CAT8 8bit Console, set 2)", MACHINE_IMPERFECT_GRAPHICS ) -// Runs well, minor GFX issues in intro -CONS( 2017, sy889, 0, 0, nes_vt_hh_8mb, nes_vt, nes_vt_hh_state, empty_init, "SY Corp", "SY-889 300 in 1 Handheld", MACHINE_IMPERFECT_GRAPHICS ) -CONS( 2016, sy888b, 0, 0, nes_vt_hh_4mb, nes_vt, nes_vt_hh_state, empty_init, "SY Corp", "SY-888B 288 in 1 Handheld", MACHINE_IMPERFECT_GRAPHICS ) - - -// Same hardware as SY-889 -CONS( 201?, mc_cb280, 0, 0, nes_vt_hh_4mb, nes_vt, nes_vt_hh_state, empty_init, "CoolBoy", "Coolboy RS-18 (280 in 1)", MACHINE_IMPERFECT_GRAPHICS ) // Runs well, only issues in SMB3 which crashes CONS( 2017, bittboy, 0, 0, nes_vt_bt_2x16mb, nes_vt, nes_vt_cy_state, empty_init, "BittBoy", "BittBoy Mini FC 300 in 1", MACHINE_IMPERFECT_GRAPHICS ) // has external banking (2x 16mbyte banks) @@ -3337,24 +2067,42 @@ CONS( 201?, mc_tv200, 0, 0, nes_vt_8mb, nes_vt, nes_vt_state, empty // probably another Thumbs Up product? cursor doesn't work unless nes_vt_hh machine is used? possibly newer than VT02 as it runs from an SPI ROM, might just not use enhanced features. Some minor game name changes to above (eg Smackdown just becomes Wrestling) CONS( 201?, unkra200, mc_tv200, 0, nes_vt_hh_8mb, nes_vt, nes_vt_hh_state, empty_init, "", "200 in 1 Retro Arcade", MACHINE_IMPERFECT_GRAPHICS ) -CONS( 2015, rminitv, 0, 0, nes_vt_fp_pal_32mb, nes_vt, nes_vt_hh_state, empty_init, "Orb Gaming", "Retro 'Mini TV' Console 300-in-1", MACHINE_IMPERFECT_GRAPHICS ) // single 32Mbyte bank! // available in a number of colours, with various brands, but likely all the same. // This was a red coloured pad, contains various unlicensed bootleg reskinned NES game eg Blob Buster is a hack of Dig Dug 2 and there are also hacks of Xevious, Donkey Kong Jr, Donkey Kong 3 and many others. CONS( 201?, ppgc200g, 0, 0, nes_vt_8mb, nes_vt, nes_vt_state, empty_init, "", "Plug & Play Game Controller with 200 Games (Supreme 200)", MACHINE_IMPERFECT_GRAPHICS ) -// New platform with scrambled opcodes, same as DGUN-2561. Runs fine with minor GFX and sound issues in menu -// Use DIP switch to select console or cartridge, as cartridge is fake and just toggles a GPIO -CONS( 2016, fcpocket, 0, 0, nes_vt_fp_4x16mb, nes_vt_fp, nes_vt_hh_state, empty_init, "", "FC Pocket 600 in 1", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // has external banking (2x 32mbyte banks) + // Probably VT09 or similar // Use DIP switch to select console or cartridge, as cartridge is fake and just toggles a ROM high address bit // (which can also be overriden by GPIO) CONS( 2017, fapocket, 0, 0, nes_vt_fa_4x16mb, nes_vt_fa, nes_vt_dg_fapocket_state, empty_init, "", "Family Pocket 638 in 1", MACHINE_IMPERFECT_GRAPHICS ) // has external banking (4x 16mbyte banks) -// Plays intro music but then crashes. same hardware as SY-88x but uses more features -CONS( 2016, mog_m320, 0, 0, nes_vt_hh_8mb, nes_vt, nes_vt_hh_state, empty_init, "MOGIS", "MOGIS M320 246 in 1 Handheld", MACHINE_NOT_WORKING ) CONS( 2017, otrail, 0, 0, nes_vt_dg_1mb, nes_vt, nes_vt_dg_state, empty_init, "Basic Fun", "The Oregon Trail", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS ) CONS( 2005, senwld, 0, 0, nes_vt_senwld_512kb, nes_vt, nes_vt_swap_op_d5_d6_state, empty_init, "Senario", "Win, Lose or Draw (Senario)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS ) // needs RAM in banked space, Alpha display emulating, Touchpad emulating etc. + + +// Runs well, minor GFX issues in intro +CONS( 2017, sy889, 0, 0, nes_vt_hh_8mb, nes_vt, nes_vt_hh_state, empty_init, "SY Corp", "SY-889 300 in 1 Handheld", MACHINE_IMPERFECT_GRAPHICS ) +CONS( 2016, sy888b, 0, 0, nes_vt_hh_4mb, nes_vt, nes_vt_hh_state, empty_init, "SY Corp", "SY-888B 288 in 1 Handheld", MACHINE_IMPERFECT_GRAPHICS ) + +// Same hardware as SY-889 +CONS( 201?, mc_cb280, 0, 0, nes_vt_hh_4mb, nes_vt, nes_vt_hh_state, empty_init, "CoolBoy", "Coolboy RS-18 (280 in 1)", MACHINE_IMPERFECT_GRAPHICS ) + +// Plays intro music but then crashes. same hardware as SY-88x but uses more features +CONS( 2016, mog_m320, 0, 0, nes_vt_hh_8mb, nes_vt, nes_vt_hh_state, empty_init, "MOGIS", "MOGIS M320 246 in 1 Handheld", MACHINE_NOT_WORKING ) + + +// similar menus to above, but with opcode scrambling +// palette issues in some games because they actually use the old VT style palette +// but no way to switch? +// some menu gfx broken, probably because this is a bad dump +CONS( 2015, dgun2573, 0, 0, nes_vt_fp_32mb, nes_vt, nes_vt_hh_state, empty_init, "dreamGEAR", "My Arcade Gamer V Portable Gaming System (DGUN-2573)", MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) +CONS( 2015, rminitv, 0, 0, nes_vt_fp_pal_32mb, nes_vt, nes_vt_hh_state, empty_init, "Orb Gaming", "Retro 'Mini TV' Console 300-in-1", MACHINE_IMPERFECT_GRAPHICS ) // single 32Mbyte bank! +// New platform with scrambled opcodes, same as DGUN-2561. Runs fine with minor GFX and sound issues in menu +// Use DIP switch to select console or cartridge, as cartridge is fake and just toggles a GPIO +CONS( 2016, fcpocket, 0, 0, nes_vt_fp_4x16mb, nes_vt_fp, nes_vt_hh_state, empty_init, "", "FC Pocket 600 in 1", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // has external banking (2x 32mbyte banks) + diff --git a/src/mame/machine/nes_vt_soc.cpp b/src/mame/machine/nes_vt_soc.cpp new file mode 100644 index 00000000000..c8ac9ade429 --- /dev/null +++ b/src/mame/machine/nes_vt_soc.cpp @@ -0,0 +1,1587 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +/*************************************************************************** + + The 'VT' series are SoC solutions that implement enhanced NES hardware + there are several generations of these chips each adding additional + functionality. + + This list is incomplete + + VT01 - plain famiclone? + VT02 - banking scheme to access 32MB, Dual APU with PCM support + VT03 - above + 4bpp sprite / bg modes, enhanced palette + + VT08 - ? + + VT09 - alt 4bpp modes? + + VT16 - ? + VT18 - ? + + VT33 (?) - used in FC Pocket, dgun2573 + Adds scrambled opcodes (XORed with 0xA1) and RGB444 palette mode, + and more advanced PCM modes (CPU and video working, sound NYI) + + VT368 (?) - used in DGUN2561, lxcmcy + Various enhancements not yet emulated. Different banking, possibly an ALU, + larger palette space + + VT36x (?) - used in SY889 + Uses SQI rather than parallel flash + Vaguely OneBus compatible but some registers different ($411C in particular) + Uses RGB format for palettes + Credit to NewRisingSun2 for much of the reverse engineering + same chipset used in Mogis M320, but uses more advanced feature set. + + (more) + + + + todo (VT03): + + APU refactoring to allow for mostly doubled up functionality + PCM channel + *more* + + todo (newer VTxx): + + new PCM audio in FC Pocket and DGUN-2573 + add support for VT368 (?) in DGUN-2561 and lxcmcy + add support for the VT369 (?) featurs used by the MOGIS M320 + +**************************************************************************/ + +#include "emu.h" +#include "nes_vt_soc.h" + +// TODO: identify what kind of SoCs each of these are (some are probably meant to be the same chip, just with subsets of the features added at the moment, especially the CY/BT/HH ones) +// also work out if some of these features (eg. opcode scrambling) should be done with external callbacks, sometimes the die was the same (VH2009) but encryption not always present (pin control or external feature?) + +DEFINE_DEVICE_TYPE(NES_VT_SOC, nes_vt_soc_device, "nes_vt_soc", "VTxx series System on a Chip (NTSC)") +DEFINE_DEVICE_TYPE(NES_VT_SOC_PAL, nes_vt_soc_pal_device, "nes_vt_soc_pal", "VTxx series System on a Chip (PAL)") + +DEFINE_DEVICE_TYPE(NES_VT_SOC_SCRAMBLE, nes_vt_soc_scramble_device, "nes_vt_soc_scram", "VTxx series System on a Chip (with simple Opcode scrambling)") + +DEFINE_DEVICE_TYPE(NES_VT_SOC_4KRAM, nes_vt_soc_4kram_device, "nes_vt_soc_4k", "VTxx series System on a Chip (with 4KByte RAM)") +DEFINE_DEVICE_TYPE(NES_VT_SOC_4KRAM_CY, nes_vt_soc_4kram_cy_device, "nes_vt_soc_4k_cy", "VTxx series System on a Chip (with 4KByte RAM) (CY)") +DEFINE_DEVICE_TYPE(NES_VT_SOC_4KRAM_BT, nes_vt_soc_4kram_bt_device, "nes_vt_soc_4k_bt", "VTxx series System on a Chip (with 4KByte RAM) (BT)") +DEFINE_DEVICE_TYPE(NES_VT_SOC_4KRAM_HH, nes_vt_soc_4kram_hh_device, "nes_vt_soc_4k_hh", "VTxx series System on a Chip (with 4KByte RAM) (HH)") + +DEFINE_DEVICE_TYPE(NES_VT_SOC_4KRAM_FP, nes_vt_soc_4kram_fp_device, "nes_vt_soc_4k_fp", "VTxx series System on a Chip (with 4KByte RAM) (FP) (NTSC)") +DEFINE_DEVICE_TYPE(NES_VT_SOC_4KRAM_FP_PAL, nes_vt_soc_4kram_fp_pal_device, "nes_vt_soc_4k_fp_pal", "VTxx series System on a Chip (with 4KByte RAM) (FP) (PAL)") + +DEFINE_DEVICE_TYPE(NES_VT_SOC_8KRAM_DG, nes_vt_soc_8kram_dg_device, "nes_vt_soc_8k_dg", "VTxx series System on a Chip (with 8KByte RAM) (DG)") +DEFINE_DEVICE_TYPE(NES_VT_SOC_8KRAM_FA, nes_vt_soc_8kram_fa_device, "nes_vt_soc_8k_dg", "VTxx series System on a Chip (with 8KByte RAM) (FA)") + +void nes_vt_soc_device::program_map(address_map &map) +{ +} + +nes_vt_soc_device::nes_vt_soc_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + device_memory_interface(mconfig, *this), + m_maincpu(*this, "maincpu"), + m_screen(*this, "screen"), + m_ppu(*this, "ppu"), + m_apu(*this, "apu"), + m_initial_e000_bank(0xff), + m_ntram(nullptr), + m_chrram(nullptr), + m_space_config("program", ENDIANNESS_LITTLE, 8, 25, 0, address_map_constructor(FUNC(nes_vt_soc_device::program_map), this)), + m_write_0_callback(*this), + m_read_0_callback(*this), + m_read_1_callback(*this), + m_extra_write_0_callback(*this), + m_extra_write_1_callback(*this), + m_extra_write_2_callback(*this), + m_extra_write_3_callback(*this), + m_extra_read_0_callback(*this), + m_extra_read_1_callback(*this), + m_extra_read_2_callback(*this), + m_extra_read_3_callback(*this) +{ + // 'no scramble' configuration + for (int i = 0; i < 6; i++) + m_2012_2017_descramble[i] = 2 + i; + + // 'no scramble' configuration + m_8000_scramble[0x0] = 0x6; + m_8000_scramble[0x1] = 0x7; + m_8000_scramble[0x2] = 0x2; + m_8000_scramble[0x3] = 0x3; + m_8000_scramble[0x4] = 0x4; + m_8000_scramble[0x5] = 0x5; + m_8000_scramble[0x6] = 0x7; + m_8000_scramble[0x7] = 0x8; + + // 'no scramble' configuration + m_410x_scramble[0x0] = 0x7; + m_410x_scramble[0x1] = 0x8; + + m_default_palette_mode = PAL_MODE_VT0x; + m_force_baddma = false; +} + +nes_vt_soc_device::nes_vt_soc_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_device(mconfig, NES_VT_SOC, tag, owner, clock) +{ +} + +nes_vt_soc_pal_device::nes_vt_soc_pal_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_device(mconfig, NES_VT_SOC_PAL, tag, owner, clock) +{ +} + + +nes_vt_soc_scramble_device::nes_vt_soc_scramble_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_device(mconfig, NES_VT_SOC_SCRAMBLE, tag, owner, clock) +{ +} + +nes_vt_soc_4kram_device::nes_vt_soc_4kram_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_4kram_device(mconfig, NES_VT_SOC_4KRAM, tag, owner, clock) +{ +} + +nes_vt_soc_4kram_device::nes_vt_soc_4kram_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_device(mconfig, type, tag, owner, clock), + m_upper_write_412c_callback(*this), + m_upper_read_412c_callback(*this), + m_upper_read_412d_callback(*this) +{ +} + +nes_vt_soc_4kram_cy_device::nes_vt_soc_4kram_cy_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_4kram_device(mconfig, NES_VT_SOC_4KRAM_CY, tag, owner, clock) +{ +} + +nes_vt_soc_4kram_bt_device::nes_vt_soc_4kram_bt_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_4kram_device(mconfig, NES_VT_SOC_4KRAM_BT, tag, owner, clock) +{ +} + + +nes_vt_soc_4kram_hh_device::nes_vt_soc_4kram_hh_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_4kram_device(mconfig, type, tag, owner, clock) +{ +} + +nes_vt_soc_4kram_hh_device::nes_vt_soc_4kram_hh_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_4kram_hh_device(mconfig, NES_VT_SOC_4KRAM_HH, tag, owner, clock) +{ +} + + +nes_vt_soc_4kram_fp_device::nes_vt_soc_4kram_fp_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_4kram_fp_device(mconfig, NES_VT_SOC_4KRAM_FP, tag, owner, clock) +{ +} + +nes_vt_soc_4kram_fp_device::nes_vt_soc_4kram_fp_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_4kram_hh_device(mconfig, type, tag, owner, clock) +{ +} + +nes_vt_soc_4kram_fp_pal_device::nes_vt_soc_4kram_fp_pal_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_4kram_fp_device(mconfig, NES_VT_SOC_4KRAM_FP_PAL, tag, owner, clock) +{ +} + +nes_vt_soc_8kram_dg_device::nes_vt_soc_8kram_dg_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_4kram_device(mconfig, type, tag, owner, clock) +{ +} + +nes_vt_soc_8kram_dg_device::nes_vt_soc_8kram_dg_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_8kram_dg_device(mconfig, NES_VT_SOC_8KRAM_DG, tag, owner, clock) +{ +} + +nes_vt_soc_8kram_fa_device::nes_vt_soc_8kram_fa_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) : + nes_vt_soc_8kram_dg_device(mconfig, NES_VT_SOC_8KRAM_FA, tag, owner, clock) +{ +} + +void nes_vt_soc_device::device_start() +{ + save_item(NAME(m_410x)); + + save_item(NAME(m_411c)); + save_item(NAME(m_411d)); + save_item(NAME(m_4242)); + + save_item(NAME(m_8000_addr_latch)); + + save_item(NAME(m_timer_irq_enabled)); + save_item(NAME(m_timer_running)); + save_item(NAME(m_timer_val)); + save_item(NAME(m_vdma_ctrl)); + + m_ntram = std::make_unique(0x2000); + save_pointer(NAME(m_ntram), 0x2000); + + m_chrram = std::make_unique(0x2000); + save_pointer(NAME(m_chrram), 0x2000); + + m_ppu->set_scanline_callback(*this, FUNC(nes_vt_soc_device::scanline_irq)); + m_ppu->set_hblank_callback(*this, FUNC(nes_vt_soc_device::hblank_irq)); + + //m_ppu->set_hblank_callback(*m_cartslot->m_cart, FUNC(device_nes_cart_interface::hblank_irq))); + //m_ppu->space(AS_PROGRAM).install_readwrite_handler(0, 0x1fff, read8_delegate(*m_cartslot->m_cart, FUNC(device_nes_cart_interface::chr_r)), write8_delegate(*m_cartslot->m_cart, FUNC(device_nes_cart_interface::chr_w))); + m_ppu->space(AS_PROGRAM).install_readwrite_handler(0x2000, 0x3eff, read8_delegate(*this, FUNC(nes_vt_soc_device::nt_r)), write8_delegate(*this, FUNC(nes_vt_soc_device::nt_w))); + m_ppu->space(AS_PROGRAM).install_readwrite_handler(0, 0x1fff, read8_delegate(*this, FUNC(nes_vt_soc_device::chr_r)), write8_delegate(*this, FUNC(nes_vt_soc_device::chr_w))); + + m_write_0_callback.resolve_safe(); + m_read_0_callback.resolve_safe(0xff); + m_read_1_callback.resolve_safe(0xff); + + m_extra_write_0_callback.resolve_safe(); + m_extra_write_1_callback.resolve_safe(); + m_extra_write_2_callback.resolve_safe(); + m_extra_write_3_callback.resolve_safe(); + + m_extra_read_0_callback.resolve_safe(0xff); + m_extra_read_1_callback.resolve_safe(0xff); + m_extra_read_2_callback.resolve_safe(0xff); + m_extra_read_3_callback.resolve_safe(0xff); +} + +void nes_vt_soc_device::device_reset() +{ + // what are the actual defaults? + m_410x[0x0] = 0x00; + m_410x[0x1] = 0x00; + m_410x[0x2] = 0x00; + m_410x[0x3] = 0x00; + m_410x[0x4] = 0x00; + m_410x[0x5] = 0x00; + m_410x[0x6] = 0x00; + m_410x[0x7] = 0x00; + m_410x[0x8] = 0x01; + m_410x[0x9] = 0x02; + m_410x[0xa] = 0x00; + m_410x[0xb] = 0x00; + m_411c = 0x00; + m_411d = 0x00; + m_4242 = 0x00; + + m_timer_irq_enabled = 0; + m_timer_running = 0; + m_timer_val = 0; + m_vdma_ctrl = 0; + + update_banks(); + + m_ppu->set_201x_descramble(m_2012_2017_descramble[0], m_2012_2017_descramble[1], m_2012_2017_descramble[2], m_2012_2017_descramble[3], m_2012_2017_descramble[4], m_2012_2017_descramble[5]); + m_ppu->set_palette_mode(m_default_palette_mode); + +} + +uint32_t nes_vt_soc_device::get_banks(uint8_t bnk) +{ + switch (m_410x[0xb] & 0x07) + { + case 0: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xC0) | (bnk & 0x3F)); // makes bank 0xff at 0xe000 map to 0x07e000 by default for vectors at 0x007fffx + case 1: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xE0) | (bnk & 0x1F)); + case 2: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xF0) | (bnk & 0x0F)); + case 3: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xF8) | (bnk & 0x07)); + case 4: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xFC) | (bnk & 0x03)); + case 5: return ((m_410x[0x0] & 0xF0) << 4) + ((m_410x[0xa] & 0xFE) | (bnk & 0x01)); + case 6: return ((m_410x[0x0] & 0xF0) << 4) + (m_410x[0xa]); + case 7: return ((m_410x[0x0] & 0xF0) << 4) + bnk; + } + + return 0; +} + +// 8000 needs to bank in 60000 ( bank 0x30 ) +void nes_vt_soc_device::update_banks() +{ + //uint32_t amod = m_ahigh >> 13; + + uint8_t bank; + + // 8000-9fff + if ((m_410x[0xb] & 0x40) != 0 || (m_410x[0x5] & 0x40) == 0) + { + if ((m_410x[0x5] & 0x40) == 0) + bank = m_410x[0x7]; + else + bank = m_410x[0x9]; + } + else + bank = 0xfe; + + m_bankaddr[0] = ((/*amod |*/ get_banks(bank)) ); + + // a000-bfff + bank = m_410x[0x8]; + m_bankaddr[1] = ((/*amod |*/ get_banks(bank)) ); + + // c000-dfff + if ((m_410x[0xb] & 0x40) != 0 || (m_410x[0x5] & 0x40) != 0) + { + if ((m_410x[0x5] & 0x40) == 0) + bank = m_410x[0x9]; + else + bank = m_410x[0x7]; + } + else + bank = 0xfe; + + m_bankaddr[2] = ((/*amod |*/ get_banks(bank)) ); + + // e000 - ffff + bank = m_initial_e000_bank; + m_bankaddr[3] = ((/*amod |*/ get_banks(bank)) ); +} + +uint16_t nes_vt_soc_device::decode_nt_addr(uint16_t addr) +{ + bool vert_mirror = !(m_410x[0x6] & 0x01); + int a11 = (addr >> 11) & 0x01; + int a10 = (addr >> 10) & 0x01; + uint16_t base = (addr & 0x3FF); + return ((vert_mirror ? a10 : a11) << 10) | base; +} + +WRITE8_MEMBER(nes_vt_soc_device::vt03_410x_w) +{ + scrambled_410x_w(offset, data); +} + +READ8_MEMBER(nes_vt_soc_device::vt03_410x_r) +{ + return m_410x[offset]; +} + + +// Source: https://wiki.nesdev.com/w/index.php/NES_2.0_submappers/Proposals#NES_2.0_Mapper_256 + +void nes_vt_soc_device::scrambled_410x_w(uint16_t offset, uint8_t data) +{ + switch (offset) + { + case 0x0: + m_410x[0x0] = data; + update_banks(); + break; + + case 0x1: + // latch timer value + m_410x[0x1] = data; + m_timer_running = 0; + break; + + case 0x2: + //logerror("vt03_4102_w %02x\n", data); + // load latched value and start counting + m_410x[0x2] = data; // value doesn't matter? + m_timer_val = m_410x[0x1]; + m_timer_running = 1; + break; + + case 0x3: + //logerror("vt03_4103_w %02x\n", data); + m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); + // disable timer irq + m_410x[0x3] = data; // value doesn't matter? + m_timer_irq_enabled = 0; + break; + + case 0x4: + //logerror("vt03_4104_w %02x\n", data); + // enable timer irq + m_410x[0x4] = data; // value doesn't matter? + m_timer_irq_enabled = 1; + break; + + case 0x5: + logerror("vt03_4105_w %02x\n", data); + m_410x[0x5] = data; + update_banks(); + break; + + case 0x6: + m_410x[0x6] = data; + break; + + case 0x7: + m_410x[m_410x_scramble[0]] = data; + update_banks(); + break; + + case 0x8: + m_410x[m_410x_scramble[1]] = data; + update_banks(); + break; + + case 0x9: + logerror("vt03_4109_w %02x\n", data); + m_410x[0x9] = data; + update_banks(); + break; + + case 0xa: + logerror("vt03_410aw %02x\n", data); + m_410x[0xa] = data; + update_banks(); + break; + + case 0xb: + /* + + D7 TSYNEN - Timer clock select 0:AD12, 1:HSYNC + D6 Prg Bank 0 Reg 2 enable / disable 0:Disable 1:Enable + D5 RS232 enable / disable 0:Disable 1:Enable + D4 Bus output control 0: normal 1: tristate + D3 6000-7fff and 8000-ffff control - 0 will not active XRWB, 1 will activate + D2-D0 - program bank 0 selector + + */ + + logerror("vt03_410b_w %02x\n", data); + m_410x[0xb] = data; + update_banks(); + break; + } +} + + + +READ8_MEMBER(nes_vt_soc_device::spr_r) +{ + if (m_4242 & 0x1 || m_411d & 0x04) + { + return m_chrram[offset]; + } + else + { + int realaddr = calculate_real_video_address(offset, 0, 1); + + address_space& spc = this->space(AS_PROGRAM); + return spc.read_byte(realaddr); + } +} + +READ8_MEMBER(nes_vt_soc_device::chr_r) +{ + if (m_4242 & 0x1 || m_411d & 0x04) + { + return m_chrram[offset]; + } + else + { + int realaddr = calculate_real_video_address(offset, 1, 0); + + address_space& spc = this->space(AS_PROGRAM); + return spc.read_byte(realaddr); + } +} + + +WRITE8_MEMBER(nes_vt_soc_device::chr_w) +{ + if (m_4242 & 0x1 || m_411d & 0x04) + { + logerror("vram write %04x %02x\n", offset, data); + m_chrram[offset] = data; + } +} + + + +void nes_vt_soc_device::scanline_irq(int scanline, int vblank, int blanked) +{ + video_irq(false, scanline, vblank, blanked); +} + +void nes_vt_soc_device::hblank_irq(int scanline, int vblank, int blanked) +{ + video_irq(true, scanline, vblank, blanked); +} + +void nes_vt_soc_device::video_irq(bool hblank, int scanline, int vblank, int blanked) +{ + //TSYNEN + if (((m_410x[0xb] >> 7) & 0x01) == hblank) + { + int irqstate = 0; + + //logerror("scanline_irq %d\n", scanline); + + if (m_timer_running && scanline < 0xe0) + { + m_timer_val--; + + if (m_timer_val < 0) + { + if (m_timer_irq_enabled && !blanked) + { + logerror("scanline_irq %d\n", scanline); + irqstate = 1; + } + } + } + + if (irqstate) + m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE); + //else + // m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); + } +} + +/* todo, handle custom VT nametable stuff here */ +READ8_MEMBER(nes_vt_soc_device::nt_r) +{ + return m_ntram[decode_nt_addr(offset)]; +} + +WRITE8_MEMBER(nes_vt_soc_device::nt_w) +{ + //logerror("nt wr %04x %02x", offset, data); + m_ntram[decode_nt_addr(offset)] = data; +} + + + + + + +int nes_vt_soc_device::calculate_real_video_address(int addr, int extended, int readtype) +{ + // might be a VT09 only feature (alt 4bpp mode?) + int alt_order = m_ppu->get_201x_reg(0x0) & 0x40; + + if (readtype == 0) + { + if (m_ppu->get_201x_reg(0x0) & 0x10) + { + extended = 1; + } + else + { + extended = 0; + } + } + else if (readtype == 1) + { + if (m_ppu->get_201x_reg(0x0) & 0x08) + { + extended = 1; + } + else + { + extended = 0; + } + } + + /* + Calculating TVA17 - TVA10 + + -------------------------------------------------------------------------------------------- + | COMR7 | AD[12:10] | TVA17 | TVA16 | TVA15 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | + | (4105, 0x80) | (2006) | | | | | | | | | + -------------------------------------------------------------------------------------------- + | 0/1/C/D | RV47 | RV46 | RV45 | RV44 | RV43 | RV42 | RV41 | AD10 | ** RV40 is never used + | 2/3/E/F | RV57 | RV56 | RV55 | RV54 | RV53 | RV52 | RV51 | AD10 | ** RV50 is never used + | 4/8 | RV07 | RV06 | RV05 | RV04 | RV03 | RV02 | RV01 | RV00 | + | 5/9 | RV17 | RV16 | RV15 | RV14 | RV13 | RV12 | RV11 | RV10 | + | 6/A | RV27 | RV26 | RV25 | RV24 | RV23 | RV22 | RV21 | RV20 | + | 7/B | RV37 | RV36 | RV35 | RV34 | RV33 | RV32 | RV31 | RV30 | + -------------------------------------------------------------------------------------------- + + m_r2012 = rv0x + m_r2013 = rv1x + m_r2014 = rv2x + m_r2015 = rv3x + m_r2016 = rv4x + m_r2017 = rv5x + + */ + int finaladdr = 0; + + int sel = (addr & 0x1c00) | ((m_410x[0x5] & 0x80) ? 0x2000 : 0x000); + + int vbank_tva17_tva10 = 0x00; + + switch ((sel >> 10) & 0xf) + { + case 0x0: + case 0x1: + case 0xc: + case 0xd: + vbank_tva17_tva10 = (m_ppu->get_201x_reg(0x6) & 0xfe) | ((addr & 0x0400) ? 1 : 0); + break; + + case 0x2: + case 0x3: + case 0xe: + case 0xf: + vbank_tva17_tva10 = (m_ppu->get_201x_reg(0x7) & 0xfe) | ((addr & 0x0400) ? 1 : 0); + break; + + case 0x4: + case 0x8: + vbank_tva17_tva10 = m_ppu->get_201x_reg(0x2); + break; + + case 0x5: + case 0x9: + vbank_tva17_tva10 = m_ppu->get_201x_reg(0x3); + break; + + case 0x6: + case 0xa: + vbank_tva17_tva10 = m_ppu->get_201x_reg(0x4); + break; + + case 0x7: + case 0xb: + vbank_tva17_tva10 = m_ppu->get_201x_reg(0x5); + break; + + } + + /* + Calculating VA17 - VA10 (requires TVA17-TVA10 to have been calculated) + + ------------------------------------------------------------------------------ + | VB0S[2:0] | VA[17:10] | + | 201a & 0x7 | VA17 | VA16 | VA15 | VA14 | VA13 | VA12 | VA11 | VA10 | + |----------------------------------------------------------------------------- + | 0x0 | TVA17 | TVA16 | TVA15 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | + | 0x1 | TV67 | TVA16 | TVA15 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | + | 0x2 | RV67 | RV66 | TVA15 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | + | 0x3 | INVALID ***************************************************** | + | 0x4 | RV67 | RV66 | RV65 | TVA14 | TVA13 | TVA12 | TVA11 | TVA10 | + | 0x5 | RV67 | RV66 | RV65 | RV64 | TVA13 | TVA12 | TVA11 | TVA10 | + | 0x6 | RV67 | RV66 | RV65 | RV64 | RV63 | TVA12 | TVA11 | TVA10 | + | 0x7 | INVALID ***************************************************** | + ------------------------------------------------------------------------------ + + RV67- RV63 = 0x201a & 0xf8 + + */ + + int va17_va10 = 0; + + int swit = m_ppu->get_201x_reg(0xa); + + switch (swit & 0x07) + { + case 0x0: va17_va10 = vbank_tva17_tva10; break; + case 0x1: va17_va10 = (vbank_tva17_tva10 & 0x7f) | (m_ppu->get_201x_reg(0xa) & 0x80); break; + case 0x2: va17_va10 = (vbank_tva17_tva10 & 0x3f) | (m_ppu->get_201x_reg(0xa) & 0xc0); break; + case 0x3: return -1; + case 0x4: va17_va10 = (vbank_tva17_tva10 & 0x1f) | (m_ppu->get_201x_reg(0xa) & 0xe0); break; + case 0x5: va17_va10 = (vbank_tva17_tva10 & 0x0f) | (m_ppu->get_201x_reg(0xa) & 0xf0); break; + case 0x6: va17_va10 = (vbank_tva17_tva10 & 0x07) | (m_ppu->get_201x_reg(0xa) & 0xf8); break; + case 0x7: return -1; + } + + int va34 = m_ppu->get_va34(); + + if (!extended) + { + int is4bpp = 0; + if (readtype == 0) is4bpp = m_ppu->get_201x_reg(0x0) & 0x02; + else if (readtype == 1) is4bpp = m_ppu->get_201x_reg(0x0) & 0x04; + + int va20_va18 = (m_ppu->get_201x_reg(0x8) & 0x70) >> 4; + + finaladdr = ((m_410x[0x0] & 0x0F) << 21) | (va20_va18 << 18) | (va17_va10 << 10) | (addr & 0x03ff); + + if (is4bpp) + { + if (!alt_order) + { + finaladdr = ((finaladdr & ~0xf) << 1) | (va34 << 4) | (finaladdr & 0xf); + } + else + { + finaladdr = (finaladdr << 1) | va34; + } + } + } + else + { + int eva2_eva0 = 0x00; + int is4bpp = 0; + + switch (readtype) + { + case 0: // background display + is4bpp = m_ppu->get_201x_reg(0x0) & 0x02; + + eva2_eva0 |= m_ppu->get_m_read_bg4_bg3(); + + if (m_ppu->get_201x_reg(0x1) & 0x02) + { + if (m_410x[0x6] & 0x1) eva2_eva0 |= 0x4; + } + else + { + if (m_ppu->get_201x_reg(0x8) & 0x08) eva2_eva0 |= 0x4; + } + break; + + case 1: // sprite display + is4bpp = m_ppu->get_201x_reg(0x0) & 0x04; // 16 colors or 16-pixel wide (both adjust the read) + + eva2_eva0 |= m_ppu->get_speva2_speva0(); + + break; + + case 2: // CPU R/W access + // todo + break; + } + + finaladdr = ((m_410x[0x0] & 0x0f) << 21) | (va17_va10 << 13) | (eva2_eva0 << 10) | (addr & 0x03ff); + + if (is4bpp) + { + if (!alt_order) + { + finaladdr = ((finaladdr & ~0xf) << 1) | (va34 << 4) | (finaladdr & 0xf); + } + else + { + finaladdr = (finaladdr << 1) | va34; + } + + } + } + return /*m_ahigh |*/ finaladdr; +} + +/* + nes_vt_soc_device::vt03_8000_mapper_w notes + + used for MMC3/other mapper compatibility + some consoles have scrambled registers for crude copy protection + + is this always there with VT based games? it maps where mappers would be on a NES cartridge + but then seems to be able to alter internal state of extended PPU registers, which is awkward +*/ + +void nes_vt_soc_device::scrambled_8000_w(address_space& space, uint16_t offset, uint8_t data) +{ + offset &= 0x7fff; + + uint16_t addr = m_real_access_address; // we need the actual write address, not the translated one, to keep bittboy happy + if ((m_411d & 0x01) && (m_411d & 0x03)) + { + //CNROM compat + logerror("%s: vtxx_cnrom_8000_w real address: (%04x) translated address: (%04x) %02x\n", machine().describe_context(), addr, offset + 0x8000, data); + m_ppu->set_201x_reg(0x6, data * 8); + m_ppu->set_201x_reg(0x7, data * 8 + 2); + m_ppu->set_201x_reg(0x2, data * 8 + 4); + m_ppu->set_201x_reg(0x3, data * 8 + 5); + m_ppu->set_201x_reg(0x4, data * 8 + 6); + m_ppu->set_201x_reg(0x5, data * 8 + 7); + + } + else if (m_411d & 0x01) + { + //MMC1 compat, TODO + logerror("%s: vtxx_mmc1_8000_w real address: (%04x) translated address: (%04x) %02x\n", machine().describe_context(), addr, offset + 0x8000, data); + + } + else if (m_411d & 0x02) + { + //UNROM compat + logerror("%s: vtxx_unrom_8000_w real address: (%04x) translated address: (%04x) %02x\n", machine().describe_context(), addr, offset + 0x8000, data); + + m_410x[0x7] = ((data & 0x0F) << 1); + m_410x[0x8] = ((data & 0x0F) << 1) + 1; + update_banks(); + } + else + { + //logerror("%s: vtxx_mmc3_8000_w real address: (%04x) translated address: (%04x) %02x\n", machine().describe_context(), addr, offset+0x8000, data ); + + //MMC3 compat + if ((addr < 0xA000) && !(addr & 0x01)) + { + logerror("%s: scrambled_8000_w real address: (%04x) translated address: (%04x) %02x (banking)\n", machine().describe_context(), addr, offset + 0x8000, data); + // Bank select + m_8000_addr_latch = data & 0x07; + // Bank config + m_410x[0x05] = data & ~(1 << 5); + update_banks(); + } + else if ((addr < 0xA000) && (addr & 0x01)) + { + logerror("%s: scrambled_8000_w real address: (%04x) translated address: (%04x) %02x (other scrambled stuff)\n", machine().describe_context(), addr, offset + 0x8000, data); + + switch (m_410x[0x05] & 0x07) + { + case 0x00: + m_ppu->set_201x_reg(m_8000_scramble[0], data); + break; + + case 0x01: + m_ppu->set_201x_reg(m_8000_scramble[1], data); + break; + + case 0x02: // hand? + m_ppu->set_201x_reg(m_8000_scramble[2], data); + break; + + case 0x03: // dog? + m_ppu->set_201x_reg(m_8000_scramble[3], data); + break; + + case 0x04: // ball thrown + m_ppu->set_201x_reg(m_8000_scramble[4], data); + break; + + case 0x05: // ball thrown + m_ppu->set_201x_reg(m_8000_scramble[5], data); + break; + case 0x06: + m_410x[m_8000_scramble[6]] = data; + //m_410x[0x9] = data; + update_banks(); + break; + + case 0x07: + m_410x[m_8000_scramble[7]] = data; + update_banks(); + break; + } + } + else if ((addr >= 0xA000) && (addr < 0xC000) && !(addr & 0x01)) + { + // Mirroring + m_410x[0x6] &= 0xFE; + m_410x[0x6] |= data & 0x01; + } + else if ((addr >= 0xA000) && (addr < 0xC000) && (addr & 0x01)) + { + // PRG RAM control, ignore + } + else if ((addr >= 0xC000) && (addr < 0xE000) && !(addr & 0x01)) + { + // IRQ latch + vt03_410x_w(space, 1, data); + } + else if ((addr >= 0xC000) && (addr < 0xE000) && (addr & 0x01)) + { + // IRQ reload + vt03_410x_w(space, 2, data); + } + else if ((addr >= 0xE000) && !(addr & 0x01)) + { + // IRQ disable + vt03_410x_w(space, 3, data); + } + else if ((addr >= 0xE000) && (addr & 0x01)) + { + // IRQ enable + vt03_410x_w(space, 4, data); + } + else + { + + } + } +} + +// MMC3 compatibility mode + +void nes_vt_soc_device::set_8000_scramble(uint8_t reg0, uint8_t reg1, uint8_t reg2, uint8_t reg3, uint8_t reg4, uint8_t reg5, uint8_t reg6, uint8_t reg7) +{ + m_8000_scramble[0] = reg0; // TODO: name the regs + m_8000_scramble[1] = reg1; + m_8000_scramble[2] = reg2; + m_8000_scramble[3] = reg3; + m_8000_scramble[4] = reg4; + m_8000_scramble[5] = reg5; + m_8000_scramble[6] = reg6; + m_8000_scramble[7] = reg7; +} + +void nes_vt_soc_device::set_410x_scramble(uint8_t reg0, uint8_t reg1) +{ + m_410x_scramble[0] = reg0; // TODO: name the regs + m_410x_scramble[1] = reg1; +} + +WRITE8_MEMBER(nes_vt_soc_device::vt03_8000_mapper_w) +{ + scrambled_8000_w(space, offset, data); + //logerror("%s: vt03_8000_mapper_w (%04x) %02x\n", machine().describe_context(), offset+0x8000, data ); +} + +/* APU plumbing, this is because we have a plain M6502 core in the VT03, otherwise this is handled in the core */ + +READ8_MEMBER(nes_vt_soc_device::psg1_4014_r) +{ + //return m_apu->read(0x14); + return 0x00; +} + +READ8_MEMBER(nes_vt_soc_device::psg1_4015_r) +{ + return m_apu->read(0x15); +} + +WRITE8_MEMBER(nes_vt_soc_device::psg1_4015_w) +{ + m_apu->write(0x15, data); +} + +WRITE8_MEMBER(nes_vt_soc_device::psg1_4017_w) +{ + m_apu->write(0x17, data); +} + +// early units (VT03?) have a DMA bug in NTSC mode +WRITE8_MEMBER(nes_vt_soc_device::vt_dma_w) +{ + if (!m_force_baddma) + do_dma(data, true); + else + do_dma(data, false); +} + + + +void nes_vt_soc_device::do_dma(uint8_t data, bool has_ntsc_bug) +{ + // only NTSC systems have 'broken' DMA which requires the DMA addresses to be shifted by 1, PAL systems work as expected + if (m_ppu->get_is_pal()) + has_ntsc_bug = false; + + uint8_t dma_mode = m_vdma_ctrl & 0x01; + uint8_t dma_len = (m_vdma_ctrl >> 1) & 0x07; + uint8_t src_nib_74 = (m_vdma_ctrl >> 4) & 0x0F; + + int length = 256; + switch (dma_len) + { + case 0x0: length = 256; break; + case 0x4: length = 16; break; + case 0x5: length = 32; break; + case 0x6: length = 64; break; + case 0x7: length = 128; break; + } + + uint16_t src_addr = (data << 8) | (src_nib_74 << 4); + logerror("vthh dma start ctrl=%02x addr=%04x\n", m_vdma_ctrl, src_addr); + + if (dma_mode == 1) + { + logerror("vdma dest %04x\n", m_ppu->get_vram_dest()); + } + + if (has_ntsc_bug && (dma_mode == 1) && ((m_ppu->get_vram_dest() & 0xFF00) == 0x3F00) && !(m_ppu->get_201x_reg(0x1) & 0x80)) + { + length -= 1; + src_addr += 1; + } + else if ((dma_mode == 1) && ((m_ppu->get_vram_dest() & 0xFF00) == 0x3F01) && !(m_ppu->get_201x_reg(0x1) & 0x80)) + { + // Legacy mode for DGUN-2573 compat + m_ppu->set_vram_dest(0x3F00); + m_ppu->set_palette_mode(PAL_MODE_VT0x); + } + + for (int i = 0; i < length; i++) + { + uint8_t spriteData = m_maincpu->space(AS_PROGRAM).read_byte(src_addr + i); + if (dma_mode) + { + m_maincpu->space(AS_PROGRAM).write_byte(0x2007, spriteData); + } + else + { + m_maincpu->space(AS_PROGRAM).write_byte(0x2004, spriteData); + } + //if(((src_addr + i) & 0xFF) == length && (i != 0)) break; + } + + // should last (length * 4 - 1) CPU cycles. + //((device_t*)m_maincpu)->execute().adjust_icount(-(length * 4 - 1)); +} + + +WRITE8_MEMBER(nes_vt_soc_device::vt03_4034_w) +{ + logerror("vt03_4034_w %02x\n", data); + m_vdma_ctrl = data; +} + +READ8_MEMBER(nes_vt_soc_device::in0_r) +{ + return m_read_0_callback(); +} + +READ8_MEMBER(nes_vt_soc_device::in1_r) +{ + return m_read_1_callback(); +} + +WRITE8_MEMBER(nes_vt_soc_device::in0_w) +{ + m_write_0_callback(offset, data); +} + +WRITE8_MEMBER(nes_vt_soc_device::extra_io_control_w) +{ + /* + 410d Extra I/O control + + 0x01 Extra I/O port 0 mode (1 = output, 0 = input) + 0x02 Extra I/O port 0 enable (1 = enable, 0 = disable) + 0x04 Extra I/O port 1 mode (1 = output, 0 = input) + 0x08 Extra I/O port 1 enable (1 = enable, 0 = disable) + 0x10 Extra I/O port 2 mode (1 = output, 0 = input) + 0x20 Extra I/O port 2 enable (1 = enable, 0 = disable) + 0x40 Extra I/O port 3 mode (1 = output, 0 = input) + 0x80 Extra I/O port 3 enable (1 = enable, 0 = disable) + */ + + logerror("%s: extra_io_control_w %02x\n", machine().describe_context(), data); +} + +READ8_MEMBER(nes_vt_soc_device::extrain_01_r) +{ + // TODO: check status of 410d port to make sure we only read from enabled ports + uint8_t in0 = 0x00, in1 = 0x00; + + in0 = m_extra_read_0_callback() & 0x0f; + in1 = m_extra_read_1_callback() & 0x0f; + + return in0 | (in1<<4); +} + +READ8_MEMBER(nes_vt_soc_device::extrain_23_r) +{ + // TODO: check status of 410d port to make sure we only read from enabled ports + uint8_t in2 = 0x00, in3 = 0x00; + + in2 = m_extra_read_2_callback() & 0x0f; + in3 = m_extra_read_3_callback() & 0x0f; + + return in2 | (in3<<4); +} + +WRITE8_MEMBER(nes_vt_soc_device::extraout_01_w) +{ + // TODO: use callbacks for this as output can be hooked up to anything + logerror("%s: extraout_01_w %02x\n", machine().describe_context(), data); +} + +WRITE8_MEMBER(nes_vt_soc_device::extraout_23_w) +{ + // TODO: use callbacks for this as output can be hooked up to anything + logerror("%s: extraout_23_w %02x\n", machine().describe_context(), data); +} + +READ8_MEMBER(nes_vt_soc_device::rs232flags_region_r) +{ + /* + 0x4119 RS232 Flags + Region + + 0x01 - RX bit 8 + 0x02 - RERFF (error status) + 0x04 - unused + 0x08 - XPORN (PAL = 1 NTSC = 0) + 0x10 - XF5OR6 (50hz = 1 60hz = 0) + 0x20 - RINGF (receive status) + 0x40 - TIFLAG (completed sending data status) + 0x80 - RIFLAG (completed receiving data status) + */ + uint8_t ret = 0x00; + + // Palette DMA is buggy on NTSC systems (at least for regular VT03) + // so the palette DMA writes will change based on the reading of these flags + + ret |= m_ppu->get_is_pal() ? 0x08 : 0x00; + ret |= m_ppu->get_is_50hz() ? 0x10 : 0x00; + + return ret; +} + + +READ8_MEMBER(nes_vt_soc_device::external_space_read) +{ + address_space& spc = this->space(AS_PROGRAM); + int bank = (offset & 0x6000) >> 13; + int address = (m_bankaddr[bank] * 0x2000) + (offset & 0x1fff); + m_real_access_address = offset + 0x8000; + return spc.read_byte(address); +} + +WRITE8_MEMBER(nes_vt_soc_device::external_space_write) +{ + address_space& spc = this->space(AS_PROGRAM); + int bank = (offset & 0x6000) >> 13; + int address = (m_bankaddr[bank] * 0x2000) + (offset&0x1fff); + m_real_access_address = offset + 0x8000; + spc.write_byte(address, data); +}; + +void nes_vt_soc_device::nes_vt_map(address_map &map) +{ + map(0x0000, 0x07ff).ram(); + + // ddrdismx relies on the mirroring + map(0x2000, 0x2007).mirror(0x00e0).rw(m_ppu, FUNC(ppu2c0x_device::read), FUNC(ppu2c0x_device::write)); // standard PPU registers + map(0x2010, 0x201f).mirror(0x00e0).rw(m_ppu, FUNC(ppu_vt03_device::read_extended), FUNC(ppu_vt03_device::write_extended)); // extra VT PPU registers + + map(0x4000, 0x4013).rw(m_apu, FUNC(nesapu_device::read), FUNC(nesapu_device::write)); + + + map(0x4014, 0x4014).r(FUNC(nes_vt_soc_device::psg1_4014_r)).w(FUNC(nes_vt_soc_device::vt_dma_w)); + map(0x4015, 0x4015).rw(FUNC(nes_vt_soc_device::psg1_4015_r), FUNC(nes_vt_soc_device::psg1_4015_w)); // PSG status / first control register + map(0x4016, 0x4016).rw(FUNC(nes_vt_soc_device::in0_r), FUNC(nes_vt_soc_device::in0_w)); + map(0x4017, 0x4017).r(FUNC(nes_vt_soc_device::in1_r)).w(FUNC(nes_vt_soc_device::psg1_4017_w)); + + map(0x4034, 0x4034).w(FUNC(nes_vt_soc_device::vt03_4034_w)); + + map(0x4100, 0x410b).r(FUNC(nes_vt_soc_device::vt03_410x_r)).w(FUNC(nes_vt_soc_device::vt03_410x_w)); + // 0x410c unused + map(0x410d, 0x410d).w(FUNC(nes_vt_soc_device::extra_io_control_w)); + map(0x410e, 0x410e).rw(FUNC(nes_vt_soc_device::extrain_01_r), FUNC(nes_vt_soc_device::extraout_01_w)); + map(0x410f, 0x410f).rw(FUNC(nes_vt_soc_device::extrain_23_r), FUNC(nes_vt_soc_device::extraout_23_w)); + // 0x4114 RS232 timer (low) + // 0x4115 RS232 timer (high) + // 0x4116 unused + // 0x4117 unused + // 0x4118 unused + map(0x4119, 0x4119).r(FUNC(nes_vt_soc_device::rs232flags_region_r)); + // 0x411a RS232 TX data + // 0x411b RS232 RX data + + + map(0x8000, 0xffff).rw(FUNC(nes_vt_soc_device::external_space_read), FUNC(nes_vt_soc_device::external_space_write)); + map(0x6000, 0x7fff).ram(); +} + + + +WRITE_LINE_MEMBER(nes_vt_soc_device::apu_irq) +{ + // TODO +// set_input_line(N2A03_APU_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); +} + +READ8_MEMBER(nes_vt_soc_device::apu_read_mem) +{ + // TODO + return 0x00;//mintf->program->read_byte(offset); +} + +uint32_t nes_vt_soc_device::screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect) +{ + return m_ppu->screen_update(screen, bitmap, cliprect); +} + + +device_memory_interface::space_config_vector nes_vt_soc_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_space_config) + }; +} + +void nes_vt_soc_device::do_pal_timings_and_ppu_replacement(machine_config& config) +{ + m_maincpu->set_clock(PALC_APU_CLOCK); + + PPU_VT03PAL(config.replace(), m_ppu, N2A03_PAL_XTAL); + m_ppu->set_cpu_tag(m_maincpu); + m_ppu->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); + m_ppu->read_bg().set(FUNC(nes_vt_soc_device::chr_r)); + m_ppu->read_sp().set(FUNC(nes_vt_soc_device::spr_r)); + m_ppu->set_screen(m_screen); + + m_screen->set_refresh_hz(50.0070); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC((113.66 / (PALC_APU_CLOCK.dvalue() / 1000000)) * + (ppu2c0x_device::VBLANK_LAST_SCANLINE_PAL - ppu2c0x_device::VBLANK_FIRST_SCANLINE_PALC + 1 + 2))); + m_screen->set_size(32 * 8, 312); + m_screen->set_visarea(0 * 8, 32 * 8 - 1, 0 * 8, 30 * 8 - 1); +} + + +void nes_vt_soc_device::device_add_mconfig(machine_config &config) +{ + M6502(config, m_maincpu, NTSC_APU_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_soc_device::nes_vt_map); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_refresh_hz(60.0988); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC((113.66/(NTSC_APU_CLOCK.dvalue()/1000000)) * + (ppu2c0x_device::VBLANK_LAST_SCANLINE_NTSC-ppu2c0x_device::VBLANK_FIRST_SCANLINE+1+2))); + m_screen->set_size(32*8, 262); + m_screen->set_visarea(0*8, 32*8-1, 0*8, 30*8-1); + m_screen->set_screen_update(FUNC(nes_vt_soc_device::screen_update)); + + PPU_VT03(config, m_ppu, N2A03_NTSC_XTAL); + m_ppu->set_cpu_tag(m_maincpu); + m_ppu->int_callback().set_inputline(m_maincpu, INPUT_LINE_NMI); + m_ppu->read_bg().set(FUNC(nes_vt_soc_device::chr_r)); + m_ppu->read_sp().set(FUNC(nes_vt_soc_device::spr_r)); + m_ppu->set_screen(m_screen); + + /* sound hardware */ + SPEAKER(config, "mono").front_center(); + + /* this should actually be a custom *almost* doubled up APU, however requires more thought + than just using 2 APUs as registers in the 2nd one affect the PCM channel mode but the + DMA control still comes from the 1st, but in the new mode, sound always outputs via the + 2nd. Probably need to split the APU into interface and sound gen logic. */ + NES_APU(config, m_apu, NTSC_APU_CLOCK); + m_apu->irq().set(FUNC(nes_vt_soc_device::apu_irq)); + m_apu->mem_read().set(FUNC(nes_vt_soc_device::apu_read_mem)); + m_apu->add_route(ALL_OUTPUTS, "mono", 0.50); +} + +void nes_vt_soc_pal_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_device::device_add_mconfig(config); + do_pal_timings_and_ppu_replacement(config); +} + + +/***********************************************************************************************************************************************************/ +/* 'Scramble' specifics */ +/***********************************************************************************************************************************************************/ + +void nes_vt_soc_scramble_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_device::device_add_mconfig(config); + + M6502_SWAP_OP_D5_D6(config.replace(), m_maincpu, NTSC_APU_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_soc_scramble_device::nes_vt_map); +} + +/***********************************************************************************************************************************************************/ +/* '4K' specifics */ +/***********************************************************************************************************************************************************/ + +void nes_vt_soc_4kram_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_device::device_add_mconfig(config); + m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_soc_4kram_device::nes_vt_map); +} + +void nes_vt_soc_4kram_device::device_start() +{ + nes_vt_soc_device::device_start(); + + m_upper_write_412c_callback.resolve_safe(); + m_upper_read_412c_callback.resolve_safe(0xff); + m_upper_read_412d_callback.resolve_safe(0xff); +} + +void nes_vt_soc_4kram_device::nes_vt_4k_ram_map(address_map &map) +{ + nes_vt_soc_device::nes_vt_map(map); + map(0x0800, 0x0fff).ram(); + +// map(0x412c, 0x412c).rw(FUNC(nes_vt_soc_4kram_device::vtfp_412c_r, FUNC(nes_vt_soc_4kram_device::vtfp_412c_extbank_w)); // GPIO +// map(0x412d, 0x412d).r(FUNC(nes_vt_soc_4kram_device::vtfp_412d_r)); // GPIO + +} + +/***********************************************************************************************************************************************************/ +/* 'CY' specifics (base = '4K') */ +/***********************************************************************************************************************************************************/ + +void nes_vt_soc_4kram_cy_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_device::device_add_mconfig(config); + m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_soc_4kram_cy_device::nes_vt_cy_map); +} + +void nes_vt_soc_4kram_cy_device::nes_vt_cy_map(address_map &map) +{ + nes_vt_4k_ram_map(map); + map(0x41b0, 0x41bf).r(FUNC(nes_vt_soc_4kram_cy_device::vt03_41bx_r)).w(FUNC(nes_vt_soc_4kram_cy_device::vt03_41bx_w)); + map(0x4130, 0x4136).r(FUNC(nes_vt_soc_4kram_cy_device::vt03_413x_r)).w(FUNC(nes_vt_soc_4kram_cy_device::vt03_413x_w)); + map(0x414f, 0x414f).r(FUNC(nes_vt_soc_4kram_cy_device::vt03_414f_r)); + map(0x415c, 0x415c).r(FUNC(nes_vt_soc_4kram_cy_device::vt03_415c_r)); + + map(0x48a0, 0x48af).r(FUNC(nes_vt_soc_4kram_cy_device::vt03_48ax_r)).w(FUNC(nes_vt_soc_4kram_cy_device::vt03_48ax_w)); +} + +void nes_vt_soc_4kram_cy_device::device_start() +{ + nes_vt_soc_device::device_start(); + save_item(NAME(m_413x)); +} + + +READ8_MEMBER(nes_vt_soc_4kram_cy_device::vt03_41bx_r) +{ + switch (offset) + { + case 0x07: + return 0x04; + default: + return 0x00; + } +} + +WRITE8_MEMBER(nes_vt_soc_4kram_cy_device::vt03_41bx_w) +{ + logerror("vt03_41bx_w %02x %02x\n", offset, data); +} + +READ8_MEMBER(nes_vt_soc_4kram_cy_device::vt03_413x_r) +{ + logerror("vt03_413x_r %02x\n", offset); + return m_413x[offset]; +} + +WRITE8_MEMBER(nes_vt_soc_4kram_cy_device::vt03_413x_w) +{ + logerror("vt03_413x_w %02x %02x\n", offset, data); + // VT168 style ALU ?? + m_413x[offset] = data; + if (offset == 0x5) + { + uint32_t res = uint32_t((m_413x[5] << 8) | m_413x[4]) * uint32_t((m_413x[1] << 8) | m_413x[0]); + m_413x[0] = res & 0xFF; + m_413x[1] = (res >> 8) & 0xFF; + m_413x[2] = (res >> 16) & 0xFF; + m_413x[3] = (res >> 24) & 0xFF; + m_413x[6] = 0x00; + + } + else if (offset == 0x6) + { + /*uint32_t res = uint32_t((m_413x[5] << 8) | m_413x[4]) * uint32_t((m_413x[1] << 8) | m_413x[0]); + m_413x[0] = res & 0xFF; + m_413x[1] = (res >> 8) & 0xFF; + m_413x[2] = (res >> 16) & 0xFF; + m_413x[3] = (res >> 24) & 0xFF;*/ + m_413x[6] = 0x00; + } +} + +READ8_MEMBER(nes_vt_soc_4kram_cy_device::vt03_414f_r) +{ + return 0xff; +} + +READ8_MEMBER(nes_vt_soc_4kram_cy_device::vt03_415c_r) +{ + return 0xff; +} + + +WRITE8_MEMBER(nes_vt_soc_4kram_cy_device::vt03_48ax_w) +{ + logerror("vt03_48ax_w %02x %02x\n", offset, data); +} + +READ8_MEMBER(nes_vt_soc_4kram_cy_device::vt03_48ax_r) +{ + switch (offset) + { + case 0x04: + return 0x01; + case 0x05: + return 0x01; + default: + return 0x00; + } +} + +/***********************************************************************************************************************************************************/ +/* 'BT' specifics (base = '4K') */ +/***********************************************************************************************************************************************************/ + +void nes_vt_soc_4kram_bt_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_device::device_add_mconfig(config); + m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_soc_4kram_bt_device::nes_vt_bt_map); +} + +void nes_vt_soc_4kram_bt_device::nes_vt_bt_map(address_map &map) +{ + nes_vt_4k_ram_map(map); + map(0x412c, 0x412c).w(FUNC(nes_vt_soc_4kram_bt_device::vt03_412c_extbank_w)); +} + +WRITE8_MEMBER(nes_vt_soc_4kram_bt_device::vt03_412c_extbank_w) +{ + m_upper_write_412c_callback(data); +} + + +/***********************************************************************************************************************************************************/ +/* 'HH' specifics (base = '4K') */ +/***********************************************************************************************************************************************************/ + +void nes_vt_soc_4kram_hh_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_device::device_add_mconfig(config); + m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_soc_4kram_hh_device::nes_vt_hh_map); +} + +WRITE8_MEMBER(nes_vt_soc_4kram_hh_device::vtfp_411d_w) +{ + // controls chram access and mapper emulation modes in later models + logerror("vtfp_411d_w %02x\n", data); + m_411d = data; + update_banks(); +} + +READ8_MEMBER(nes_vt_soc_4kram_hh_device::vthh_414a_r) +{ + return 0x80; +} + +void nes_vt_soc_4kram_hh_device::nes_vt_hh_map(address_map &map) +{ + nes_vt_soc_device::nes_vt_map(map); + + map(0x0000, 0x1fff).mask(0x0fff).ram(); + + map(0x414a, 0x414a).r(FUNC(nes_vt_soc_4kram_hh_device::vthh_414a_r)); + map(0x411d, 0x411d).w(FUNC(nes_vt_soc_4kram_hh_device::vtfp_411d_w)); +} + +/***********************************************************************************************************************************************************/ +/* 'FP' specifics (base = 'HH') */ // used by fcpocket, dgun2573, rminitv +/***********************************************************************************************************************************************************/ + +void nes_vt_soc_4kram_fp_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_device::device_add_mconfig(config); + + M6502_VTSCR(config.replace(), m_maincpu, NTSC_APU_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_soc_4kram_fp_device::nes_vt_fp_map); +} + + +READ8_MEMBER(nes_vt_soc_4kram_fp_device::vtfp_4119_r) +{ + // would be PAL/NTSC etc. in base system, maybe different here? + return 0x00; +} + +WRITE8_MEMBER(nes_vt_soc_4kram_fp_device::vtfp_411e_w) +{ + logerror("411e_w %02x\n", data); + if (data == 0x05) + dynamic_cast(*m_maincpu).set_next_scramble(true); + else if (data == 0x00) + dynamic_cast(*m_maincpu).set_next_scramble(false); +} + +WRITE8_MEMBER(nes_vt_soc_4kram_fp_device::vtfp_4a00_w) +{ + logerror("4a00_w %02x\n", data); + //if(data == 0x80) + // dynamic_cast(*m_maincpu).set_scramble(false); +} + + +WRITE8_MEMBER(nes_vt_soc_4kram_fp_device::vtfp_412c_extbank_w) +{ + m_upper_write_412c_callback(data); +} + +READ8_MEMBER(nes_vt_soc_4kram_fp_device::vtfp_412d_r) +{ + return m_upper_read_412d_callback(); +} + +WRITE8_MEMBER(nes_vt_soc_4kram_fp_device::vtfp_4242_w) +{ + logerror("vtfp_4242_w %02x\n", data); + m_4242 = data; +} + +void nes_vt_soc_4kram_fp_device::nes_vt_fp_map(address_map &map) +{ + nes_vt_soc_4kram_hh_device::nes_vt_hh_map(map); + + map(0x4119, 0x4119).r(FUNC(nes_vt_soc_4kram_fp_device::vtfp_4119_r)); + map(0x411e, 0x411e).w(FUNC(nes_vt_soc_4kram_fp_device::vtfp_411e_w)); // encryption toggle + + map(0x412c, 0x412c).w(FUNC(nes_vt_soc_4kram_fp_device::vtfp_412c_extbank_w)); // GPIO + map(0x412d, 0x412d).r(FUNC(nes_vt_soc_4kram_fp_device::vtfp_412d_r)); // GPIO + + map(0x4242, 0x4242).w(FUNC(nes_vt_soc_4kram_fp_device::vtfp_4242_w)); + + map(0x4a00, 0x4a00).w(FUNC(nes_vt_soc_4kram_fp_device::vtfp_4a00_w)); +} + +void nes_vt_soc_4kram_fp_pal_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_4kram_fp_device::device_add_mconfig(config); + do_pal_timings_and_ppu_replacement(config); +} + +/***********************************************************************************************************************************************************/ +/* 'DG' specifics (base = '4K') */ +/***********************************************************************************************************************************************************/ + +void nes_vt_soc_8kram_dg_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_device::device_add_mconfig(config); + m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_soc_8kram_dg_device::nes_vt_dg_map); +} + +WRITE8_MEMBER(nes_vt_soc_8kram_dg_device::vt03_411c_w) +{ + logerror("vt03_411c_w %02x\n", data); + m_411c = data; + update_banks(); +} + +void nes_vt_soc_8kram_dg_device::nes_vt_dg_map(address_map &map) +{ + nes_vt_soc_device::nes_vt_map(map); + + map(0x0000, 0x1fff).ram(); + map(0x411c, 0x411c).w(FUNC(nes_vt_soc_8kram_dg_device::vt03_411c_w)); +} + +/***********************************************************************************************************************************************************/ +/* 'FA' specifics (base = 'DG') */ // used by fapocket +/***********************************************************************************************************************************************************/ + +void nes_vt_soc_8kram_fa_device::device_add_mconfig(machine_config& config) +{ + nes_vt_soc_device::device_add_mconfig(config); + m_maincpu->set_addrmap(AS_PROGRAM, &nes_vt_soc_8kram_fa_device::nes_vt_fa_map); +} + +READ8_MEMBER(nes_vt_soc_8kram_fa_device::vtfa_412c_r) +{ + return m_upper_read_412c_callback(); +} + +WRITE8_MEMBER(nes_vt_soc_8kram_fa_device::vtfa_412c_extbank_w) +{ + m_upper_write_412c_callback(data); + +} + +WRITE8_MEMBER(nes_vt_soc_8kram_fa_device::vtfp_4242_w) +{ + logerror("vtfp_4242_w %02x\n", data); + m_4242 = data; +} + +void nes_vt_soc_8kram_fa_device::nes_vt_fa_map(address_map &map) +{ + nes_vt_soc_8kram_dg_device::nes_vt_dg_map(map); + + map(0x412c, 0x412c).r(FUNC(nes_vt_soc_8kram_fa_device::vtfa_412c_r)).w(FUNC(nes_vt_soc_8kram_fa_device::vtfa_412c_extbank_w)); + map(0x4242, 0x4242).w(FUNC(nes_vt_soc_8kram_fa_device::vtfp_4242_w)); +} + diff --git a/src/mame/machine/nes_vt_soc.h b/src/mame/machine/nes_vt_soc.h new file mode 100644 index 00000000000..0e9b57bdcf9 --- /dev/null +++ b/src/mame/machine/nes_vt_soc.h @@ -0,0 +1,343 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#ifndef MAME_MACHINE_NES_VT_H +#define MAME_MACHINE_NES_VT_H + +#pragma once + +#include "cpu/m6502/n2a03.h" +#include "machine/m6502_vtscr.h" +#include "machine/m6502_swap_op_d5_d6.h" +#include "video/ppu2c0x_vt.h" +#include "screen.h" +#include "speaker.h" + +class nes_vt_soc_device : public device_t, public device_memory_interface +{ +public: + nes_vt_soc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void program_map(address_map &map); + + DECLARE_WRITE8_MEMBER(vt03_8000_mapper_w); + + // 8-bit ports + auto write_0_callback() { return m_write_0_callback.bind(); } + auto read_0_callback() { return m_read_0_callback.bind(); } + auto read_1_callback() { return m_read_1_callback.bind(); } + + // 4-bit ports + auto extra_read_0_callback() { return m_extra_read_0_callback.bind(); } + auto extra_read_1_callback() { return m_extra_read_1_callback.bind(); } + auto extra_read_2_callback() { return m_extra_read_2_callback.bind(); } + auto extra_read_3_callback() { return m_extra_read_3_callback.bind(); } + + auto extra_write_0_callback() { return m_extra_write_0_callback.bind(); } + auto extra_write_1_callback() { return m_extra_write_1_callback.bind(); } + auto extra_write_2_callback() { return m_extra_write_2_callback.bind(); } + auto extra_write_3_callback() { return m_extra_write_3_callback.bind(); } + + void set_201x_descramble(uint8_t reg0, uint8_t reg1, uint8_t reg2, uint8_t reg3, uint8_t reg4, uint8_t reg5) + { + m_2012_2017_descramble[0] = reg0; // TOOD: name regs + m_2012_2017_descramble[1] = reg1; + m_2012_2017_descramble[2] = reg2; + m_2012_2017_descramble[3] = reg3; + m_2012_2017_descramble[4] = reg4; + m_2012_2017_descramble[5] = reg5; + }; + + void set_8000_scramble(uint8_t reg0, uint8_t reg1, uint8_t reg2, uint8_t reg3, uint8_t reg4, uint8_t reg5, uint8_t reg6, uint8_t reg7); + void set_410x_scramble(uint8_t reg0, uint8_t reg1); + void force_bad_dma() { m_force_baddma = true; }; + + void set_default_palette_mode(vtxx_pal_mode pmode) { m_default_palette_mode = pmode; } + +protected: + nes_vt_soc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; + virtual void device_reset() override; + + virtual space_config_vector memory_space_config() const override; + virtual void device_add_mconfig(machine_config &config) override; + + required_device m_maincpu; + required_device m_screen; + required_device m_ppu; + required_device m_apu; + + void nes_vt_map(address_map& map); + + uint32_t get_banks(uint8_t bnk); + void update_banks(); + uint16_t decode_nt_addr(uint16_t addr); + DECLARE_WRITE8_MEMBER(vt03_410x_w); + DECLARE_READ8_MEMBER(vt03_410x_r); + void scrambled_410x_w(uint16_t offset, uint8_t data); + DECLARE_READ8_MEMBER(spr_r); + DECLARE_READ8_MEMBER(chr_r); + DECLARE_WRITE8_MEMBER(chr_w); + void scanline_irq(int scanline, int vblank, int blanked); + void hblank_irq(int scanline, int vblank, int blanked); + void video_irq(bool hblank, int scanline, int vblank, int blanked); + DECLARE_READ8_MEMBER(nt_r); + DECLARE_WRITE8_MEMBER(nt_w); + int calculate_real_video_address(int addr, int extended, int readtype); + void scrambled_8000_w(address_space& space, uint16_t offset, uint8_t data); + DECLARE_READ8_MEMBER(psg1_4014_r); + DECLARE_READ8_MEMBER(psg1_4015_r); + DECLARE_WRITE8_MEMBER(psg1_4015_w); + DECLARE_WRITE8_MEMBER(psg1_4017_w); + DECLARE_WRITE8_MEMBER(vt_dma_w); + DECLARE_WRITE8_MEMBER(vt_fixed_dma_w); + void do_dma(uint8_t data, bool has_ntsc_bug); + DECLARE_WRITE8_MEMBER(vt03_4034_w); + + DECLARE_READ8_MEMBER(in0_r); + DECLARE_READ8_MEMBER(in1_r); + DECLARE_WRITE8_MEMBER(in0_w); + + DECLARE_WRITE8_MEMBER(extra_io_control_w); + DECLARE_READ8_MEMBER(extrain_01_r); + DECLARE_READ8_MEMBER(extrain_23_r); + DECLARE_WRITE8_MEMBER(extraout_01_w); + DECLARE_WRITE8_MEMBER(extraout_23_w); + DECLARE_READ8_MEMBER(rs232flags_region_r); + + uint32_t screen_update(screen_device& screen, bitmap_rgb32& bitmap, const rectangle& cliprect); + + uint8_t m_410x[0xc]; + + uint8_t m_vdma_ctrl; + int m_timer_irq_enabled; + int m_timer_running; + int m_timer_val; + + uint8_t m_8000_scramble[8]; + uint8_t m_410x_scramble[2]; + + uint8_t m_8000_addr_latch; + + uint8_t m_4242; + uint8_t m_411c; + uint8_t m_411d; + + uint8_t m_initial_e000_bank; + /* expansion nametable - todo, see if we can refactor NES code to be reusable without having to add full NES bus etc. */ + std::unique_ptr m_ntram; + std::unique_ptr m_chrram; + + DECLARE_WRITE_LINE_MEMBER(apu_irq); + DECLARE_READ8_MEMBER(apu_read_mem); + + DECLARE_READ8_MEMBER(external_space_read); + DECLARE_WRITE8_MEMBER(external_space_write); + + void do_pal_timings_and_ppu_replacement(machine_config& config); + +private: + + address_space_config m_space_config; + + int m_bankaddr[4]; + uint16_t m_real_access_address; + + devcb_write8 m_write_0_callback; + devcb_read8 m_read_0_callback; + devcb_read8 m_read_1_callback; + + devcb_write8 m_extra_write_0_callback; + devcb_write8 m_extra_write_1_callback; + devcb_write8 m_extra_write_2_callback; + devcb_write8 m_extra_write_3_callback; + + devcb_read8 m_extra_read_0_callback; + devcb_read8 m_extra_read_1_callback; + devcb_read8 m_extra_read_2_callback; + devcb_read8 m_extra_read_3_callback; + + uint8_t m_2012_2017_descramble[0x6]; // passed to PPU in reset + vtxx_pal_mode m_default_palette_mode; + bool m_force_baddma; +}; + +class nes_vt_soc_pal_device : public nes_vt_soc_device +{ +public: + nes_vt_soc_pal_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + +protected: + virtual void device_add_mconfig(machine_config& config) override; +}; + +class nes_vt_soc_scramble_device : public nes_vt_soc_device +{ +public: + nes_vt_soc_scramble_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + +protected: + virtual void device_add_mconfig(machine_config& config) override; +}; + +class nes_vt_soc_4kram_device : public nes_vt_soc_device +{ +public: + nes_vt_soc_4kram_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + + auto upper_read_412c_callback() { return m_upper_read_412c_callback.bind(); } + auto upper_read_412d_callback() { return m_upper_read_412d_callback.bind(); } + + auto upper_write_412c_callback() { return m_upper_write_412c_callback.bind(); } + + +protected: + nes_vt_soc_4kram_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock); + void device_start() override; + + virtual void device_add_mconfig(machine_config& config) override; + + void nes_vt_4k_ram_map(address_map& map); + + devcb_write8 m_upper_write_412c_callback; + + devcb_read8 m_upper_read_412c_callback; + devcb_read8 m_upper_read_412d_callback; +}; + +class nes_vt_soc_4kram_cy_device : public nes_vt_soc_4kram_device +{ +public: + nes_vt_soc_4kram_cy_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + +protected: + virtual void device_add_mconfig(machine_config& config) override; + void device_start() override; + + void nes_vt_cy_map(address_map& map); + + DECLARE_READ8_MEMBER(vt03_41bx_r); + DECLARE_WRITE8_MEMBER(vt03_41bx_w); + + DECLARE_READ8_MEMBER(vt03_413x_r); + DECLARE_WRITE8_MEMBER(vt03_413x_w); + + DECLARE_READ8_MEMBER(vt03_414f_r); + + DECLARE_READ8_MEMBER(vt03_415c_r); + + DECLARE_WRITE8_MEMBER(vt03_48ax_w); + DECLARE_READ8_MEMBER(vt03_48ax_r); + + uint8_t m_413x[8]; // CY only? +}; + +class nes_vt_soc_4kram_bt_device : public nes_vt_soc_4kram_device +{ +public: + nes_vt_soc_4kram_bt_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + +protected: + virtual void device_add_mconfig(machine_config& config) override; + + void nes_vt_bt_map(address_map& map); + + DECLARE_WRITE8_MEMBER(vt03_412c_extbank_w); +}; + +class nes_vt_soc_4kram_hh_device : public nes_vt_soc_4kram_device +{ +public: + nes_vt_soc_4kram_hh_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + +protected: + nes_vt_soc_4kram_hh_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock); + + virtual void device_add_mconfig(machine_config& config) override; + + void nes_vt_hh_map(address_map& map); + + DECLARE_READ8_MEMBER(vthh_414a_r); + DECLARE_WRITE8_MEMBER(vtfp_411d_w); + +}; + +class nes_vt_soc_4kram_fp_device : public nes_vt_soc_4kram_hh_device +{ +public: + nes_vt_soc_4kram_fp_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + +protected: + nes_vt_soc_4kram_fp_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock); + + virtual void device_add_mconfig(machine_config& config) override; + + void nes_vt_fp_map(address_map& map); + + DECLARE_READ8_MEMBER(vtfp_4119_r); + DECLARE_WRITE8_MEMBER(vtfp_411e_w); + DECLARE_WRITE8_MEMBER(vtfp_412c_extbank_w); + DECLARE_READ8_MEMBER(vtfp_412d_r); + DECLARE_WRITE8_MEMBER(vtfp_4242_w); + DECLARE_WRITE8_MEMBER(vtfp_4a00_w); +}; + +class nes_vt_soc_4kram_fp_pal_device : public nes_vt_soc_4kram_fp_device +{ +public: + nes_vt_soc_4kram_fp_pal_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + +protected: + virtual void device_add_mconfig(machine_config& config) override; +}; + + +class nes_vt_soc_8kram_dg_device : public nes_vt_soc_4kram_device +{ +public: + nes_vt_soc_8kram_dg_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + +protected: + nes_vt_soc_8kram_dg_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock); + + virtual void device_add_mconfig(machine_config& config) override; + + void nes_vt_dg_map(address_map& map); + + DECLARE_WRITE8_MEMBER(vt03_411c_w); +}; + +class nes_vt_soc_8kram_fa_device : public nes_vt_soc_8kram_dg_device +{ +public: + nes_vt_soc_8kram_fa_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); + +protected: + + virtual void device_add_mconfig(machine_config& config) override; + + void nes_vt_fa_map(address_map& map); + + DECLARE_READ8_MEMBER(vtfa_412c_r); + DECLARE_WRITE8_MEMBER(vtfa_412c_extbank_w); + DECLARE_WRITE8_MEMBER(vtfp_4242_w); +}; + + +DECLARE_DEVICE_TYPE(NES_VT_SOC, nes_vt_soc_device) +DECLARE_DEVICE_TYPE(NES_VT_SOC_PAL, nes_vt_soc_pal_device) + +DECLARE_DEVICE_TYPE(NES_VT_SOC_SCRAMBLE, nes_vt_soc_scramble_device) +DECLARE_DEVICE_TYPE(NES_VT_SOC_4KRAM, nes_vt_soc_4kram_device) +DECLARE_DEVICE_TYPE(NES_VT_SOC_4KRAM_CY, nes_vt_soc_4kram_cy_device) +DECLARE_DEVICE_TYPE(NES_VT_SOC_4KRAM_BT, nes_vt_soc_4kram_bt_device) +DECLARE_DEVICE_TYPE(NES_VT_SOC_4KRAM_HH, nes_vt_soc_4kram_hh_device) + +DECLARE_DEVICE_TYPE(NES_VT_SOC_4KRAM_FP, nes_vt_soc_4kram_fp_device) +DECLARE_DEVICE_TYPE(NES_VT_SOC_4KRAM_FP_PAL, nes_vt_soc_4kram_fp_pal_device) + +DECLARE_DEVICE_TYPE(NES_VT_SOC_8KRAM_DG, nes_vt_soc_8kram_dg_device) +DECLARE_DEVICE_TYPE(NES_VT_SOC_8KRAM_FA, nes_vt_soc_8kram_fa_device) + +#endif // MAME_MACHINE_NES_VT_H -- cgit v1.2.3