summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/nes_vt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/nes_vt.cpp')
-rw-r--r--src/mame/drivers/nes_vt.cpp748
1 files changed, 625 insertions, 123 deletions
diff --git a/src/mame/drivers/nes_vt.cpp b/src/mame/drivers/nes_vt.cpp
index 6642fea66ed..0ba760e8472 100644
--- a/src/mame/drivers/nes_vt.cpp
+++ b/src/mame/drivers/nes_vt.cpp
@@ -20,13 +20,22 @@
VT16 - ?
VT18 - ?
-
- VT3x - 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
-
+
+ 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, lexcyber
+ 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)
VT1682 - NOT compatible with NES, different video system, sound CPU (4x
@@ -35,15 +44,14 @@
todo (VT03):
- Super Mario Bros 3 crashes after title screen, some kind of memory map issue
- possibly with MMC3 emulation mode
-
APU refactoring to allow for mostly doubled up functionality + PCM channel
*more*
todo (newer VTxx):
- everything
+ new PCM audio in FC Pocket and DGUN-2573
+ add support for VT368 (?) in DGUN-2561 and lexcyber
+ add support for the VT369 (?) featurs used by the MOGIS M320
todo (general)
@@ -65,16 +73,25 @@
#include "cpu/m6502/n2a03.h"
#include "machine/bankdev.h"
#include "video/ppu2c0x_vt.h"
-#include "cpu/m6502/m6502.h"
+#include "machine/m6502_vtscr.h"
#include "screen.h"
#include "speaker.h"
+enum class vt_scramble_mode {
+ NO_SCRAMBLE = 0,
+ WAIXING = 1,
+ PJOY = 2,
+ HUMMER = 3,
+ SP69 = 4
+};
+
class nes_vt_state : public nes_base_state
{
public:
nes_vt_state(const machine_config &mconfig, device_type type, const char *tag)
: nes_base_state(mconfig, type, tag)
, m_ntram(nullptr)
+ , m_chrram(nullptr)
, m_ppu(*this, "ppu")
, m_apu(*this, "apu")
, m_prg(*this, "prg")
@@ -83,6 +100,8 @@ public:
, m_prgbank2(*this, "prg_bank2")
, m_prgbank3(*this, "prg_bank3")
, m_prgrom(*this, "mainrom")
+ , m_csel(*this, "CARTSEL")
+
{ }
/* APU handling */
@@ -102,7 +121,19 @@ public:
/* VT03 extension handling */
DECLARE_WRITE8_MEMBER(vt03_410x_w);
+ DECLARE_READ8_MEMBER(vt03_410x_r);
+
+ DECLARE_WRITE8_MEMBER(vt03_410x_pjoy_w);
+ DECLARE_WRITE8_MEMBER(vt03_410x_hum_w);
+ DECLARE_WRITE8_MEMBER(vt03_410x_sp69_w);
+
DECLARE_WRITE8_MEMBER(vt03_8000_w);
+ DECLARE_WRITE8_MEMBER(vt03_8000_pjoy_w);
+ DECLARE_WRITE8_MEMBER(vt03_8000_hum_w);
+ DECLARE_WRITE8_MEMBER(vt03_8000_sp69_w);
+
+ void scrambled_410x_w(uint16_t offset, uint8_t data, vt_scramble_mode scram);
+ void scrambled_8000_w(address_space &space, uint16_t offset, uint8_t data, vt_scramble_mode scram);
DECLARE_WRITE8_MEMBER(vt03_4034_w);
DECLARE_WRITE8_MEMBER(vt03_41bx_w);
@@ -112,23 +143,52 @@ public:
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_READ8_MEMBER(vthh_414a_r);
+ DECLARE_WRITE8_MEMBER(vtfp_411e_w);
+ DECLARE_WRITE8_MEMBER(vtfp_4a00_w);
+ DECLARE_WRITE8_MEMBER(vtfp_412c_w);
+ DECLARE_WRITE8_MEMBER(vtfa_412c_w);
+ DECLARE_READ8_MEMBER(vtfp_412d_r);
+ DECLARE_WRITE8_MEMBER(vtfp_411d_w);
+ DECLARE_WRITE8_MEMBER(vtfp_4242_w);
+ DECLARE_READ8_MEMBER(vtfp_4119_r);
+
+ DECLARE_READ8_MEMBER(vtfa_412c_r);
/* OneBus read callbacks for getting sprite and tile data during rendering*/
DECLARE_READ8_MEMBER(spr_r);
DECLARE_READ8_MEMBER(chr_r);
+ DECLARE_WRITE8_MEMBER(chr_w);
+
void nes_vt(machine_config &config);
+
+ void nes_vt_hum(machine_config &config);
+ void nes_vt_pjoy(machine_config &config);
+ void nes_vt_sp69(machine_config &config);
+
+
void nes_vt_xx(machine_config &config);
void nes_vt_hh(machine_config &config);
void nes_vt_cy(machine_config &config);
void nes_vt_dg(machine_config &config);
void nes_vt_bt(machine_config &config);
void nes_vt_vg(machine_config &config);
+ void nes_vt_fp(machine_config &config);
+ void nes_vt_fa(machine_config &config);
private:
/* expansion nametable - todo, see if we can refactor NES code to be reusable without having to add full NES bus etc. */
std::unique_ptr<uint8_t[]> m_ntram;
+ std::unique_ptr<uint8_t[]> m_chrram;
+
DECLARE_READ8_MEMBER(nt_r);
DECLARE_WRITE8_MEMBER(nt_w);
@@ -137,8 +197,10 @@ private:
void video_irq(bool hblank, int scanline, int vblank, int blanked);
uint8_t m_410x[0xc];
- uint8_t m_411c;
- uint8_t m_412c;
+ uint8_t m_413x[8];
+
+ uint8_t m_411c, m_411d, m_4242;
+ uint32_t m_ahigh;
uint8_t m_vdma_ctrl;
int m_timer_irq_enabled;
@@ -167,6 +229,7 @@ private:
required_memory_bank m_prgbank3;
required_region_ptr<uint8_t> m_prgrom;
+ optional_ioport m_csel;
uint16_t decode_nt_addr(uint16_t addr);
void do_dma(uint8_t data, bool broken);
};
@@ -191,7 +254,7 @@ uint32_t nes_vt_state::get_banks(uint8_t bnk)
// 8000 needs to bank in 60000 ( bank 0x30 )
void nes_vt_state::update_banks()
{
- uint32_t amod = (m_412c & 0x04) ? 0x800 : 0x0;
+ uint32_t amod = m_ahigh >> 13;
uint8_t bank;
@@ -240,6 +303,38 @@ uint16_t nes_vt_state::decode_nt_addr(uint16_t addr) {
WRITE8_MEMBER(nes_vt_state::vt03_410x_w)
{
+ scrambled_410x_w(offset, data, vt_scramble_mode::NO_SCRAMBLE);
+}
+
+READ8_MEMBER(nes_vt_state::vt03_410x_r)
+{
+ return m_410x[offset];
+}
+
+WRITE8_MEMBER(nes_vt_state::vt03_410x_hum_w)
+{
+ scrambled_410x_w(offset, data, vt_scramble_mode::HUMMER);
+}
+WRITE8_MEMBER(nes_vt_state::vt03_410x_pjoy_w)
+{
+ scrambled_410x_w(offset, data, vt_scramble_mode::PJOY);
+}
+WRITE8_MEMBER(nes_vt_state::vt03_410x_sp69_w)
+{
+ scrambled_410x_w(offset, data, vt_scramble_mode::SP69);
+}
+// Source: https://wiki.nesdev.com/w/index.php/NES_2.0_submappers/Proposals#NES_2.0_Mapper_256
+
+static const uint16_t descram_4107_4108[5][2] = {
+ {0x7, 0x8},
+ {0x7, 0x8},
+ {0x8, 0x7},
+ {0x7, 0x8},
+ {0x7, 0x8},
+};
+
+void nes_vt_state::scrambled_410x_w(uint16_t offset, uint8_t data, vt_scramble_mode scram)
+{
switch (offset)
{
case 0x0:
@@ -254,6 +349,7 @@ WRITE8_MEMBER(nes_vt_state::vt03_410x_w)
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];
@@ -261,12 +357,15 @@ WRITE8_MEMBER(nes_vt_state::vt03_410x_w)
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;
@@ -283,12 +382,12 @@ WRITE8_MEMBER(nes_vt_state::vt03_410x_w)
break;
case 0x7:
- m_410x[0x7] = data;
+ m_410x[descram_4107_4108[(int)scram][0]] = data;
update_banks();
break;
case 0x8:
- m_410x[0x8] = data;
+ m_410x[descram_4107_4108[(int)scram][1]] = data;
update_banks();
break;
@@ -338,10 +437,58 @@ WRITE8_MEMBER(nes_vt_state::vt03_411c_w)
WRITE8_MEMBER(nes_vt_state::vt03_412c_w)
{
logerror("vt03_412c_w %02x\n", data);
- m_412c = data;
+ m_ahigh = (data & 0x04) ? (1 << 24) : 0x0;
update_banks();
}
+WRITE8_MEMBER(nes_vt_state::vtfp_412c_w)
+{
+ logerror("vtfp_412c_w %02x\n", data);
+ m_ahigh = (data & 0x01) ? (1 << 25) : 0x0;
+ update_banks();
+}
+
+WRITE8_MEMBER(nes_vt_state::vtfp_4242_w)
+{
+ logerror("vtfp_4242_w %02x\n", data);
+ m_4242 = data;
+}
+
+
+WRITE8_MEMBER(nes_vt_state::vtfp_411d_w)
+{
+ logerror("vtfp_411d_w %02x\n", data);
+ m_411d = data;
+ update_banks();
+}
+
+WRITE8_MEMBER(nes_vt_state::vtfa_412c_w)
+{
+ logerror("vtfp_412c_w %02x\n", data);
+ m_ahigh = 0;
+ m_ahigh |= (data & 0x01) ? (1 << 25) : 0x0;
+ m_ahigh |= (data & 0x02) ? (1 << 24) : 0x0;
+
+ //m_ahigh |= (m_csel->read() == 0x01) ? (1 << 25) : 0x0;
+ update_banks();
+}
+
+READ8_MEMBER(nes_vt_state::vtfa_412c_r)
+{
+ return m_csel->read();
+}
+
+READ8_MEMBER(nes_vt_state::vtfp_412d_r)
+{
+ return m_csel->read();
+}
+
+READ8_MEMBER(nes_vt_state::vtfp_4119_r)
+{
+ return 0x00;
+}
+
+
READ8_MEMBER(nes_vt_state::vt03_41bx_r)
{
switch(offset) {
@@ -369,6 +516,52 @@ READ8_MEMBER(nes_vt_state::vt03_48ax_r)
}
}
+WRITE8_MEMBER(nes_vt_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_state::vt03_413x_r)
+{
+ logerror("vt03_413x_r %02x\n", offset);
+ return m_413x[offset];
+}
+
+READ8_MEMBER(nes_vt_state::vt03_414f_r)
+{
+ return 0xff;
+}
+
+READ8_MEMBER(nes_vt_state::vt03_415c_r)
+{
+ return 0xff;
+}
+
+READ8_MEMBER(nes_vt_state::vthh_414a_r)
+{
+ return 0x80;
+}
+
uint32_t nes_vt_state::screen_update_vt(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
@@ -379,16 +572,50 @@ uint32_t nes_vt_state::screen_update_vt(screen_device &screen, bitmap_ind16 &bit
READ8_MEMBER(nes_vt_state::spr_r)
{
- int realaddr = calculate_real_video_address(offset, 0, 1);
- return m_prgrom[realaddr & (m_romsize-1)];
+ if(m_4242 & 0x1 || m_411d & 0x04) {
+ return m_chrram[offset];
+ } else {
+ int realaddr = calculate_real_video_address(offset, 0, 1);
+ return m_prgrom[realaddr & (m_romsize-1)];
+ }
}
READ8_MEMBER(nes_vt_state::chr_r)
{
- int realaddr = calculate_real_video_address(offset, 1, 0);
- return m_prgrom[realaddr & (m_romsize-1)];
+ if(m_4242 & 0x1 || m_411d & 0x04) {
+ return m_chrram[offset];
+ } else {
+ int realaddr = calculate_real_video_address(offset, 1, 0);
+ return m_prgrom[realaddr & (m_romsize-1)];
+ }
+}
+
+
+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;
+ }
+ /*int realaddr = calculate_real_video_address(offset, 1, 0);
+ return m_prgrom[realaddr & (m_romsize-1)];*/
}
+WRITE8_MEMBER(nes_vt_state::vtfp_411e_w) {
+ logerror("411e_w %02x\n", data);
+ if(data == 0x05)
+ dynamic_cast<m6502_vtscr&>(*m_maincpu).set_next_scramble(true);
+ else if(data == 0x00)
+ dynamic_cast<m6502_vtscr&>(*m_maincpu).set_next_scramble(false);
+}
+
+WRITE8_MEMBER(nes_vt_state::vtfp_4a00_w) {
+ logerror("4a00_w %02x\n", data);
+ //if(data == 0x80)
+ // dynamic_cast<m6502_vtscr&>(*m_maincpu).set_scramble(false);
+}
+
+
PALETTE_INIT_MEMBER(nes_vt_state, nesvt)
{
m_ppu->init_palette(palette, 0);
@@ -418,7 +645,7 @@ void nes_vt_state::video_irq(bool hblank, int scanline, int vblank, int blanked)
if (m_timer_val < 0)
{
- if (m_timer_irq_enabled)
+ if (m_timer_irq_enabled && !blanked)
{
logerror("scanline_irq %d\n", scanline);
irqstate = 1;
@@ -428,8 +655,8 @@ void nes_vt_state::video_irq(bool hblank, int scanline, int vblank, int blanked)
if (irqstate)
m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE);
- else
- m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
+ //else
+ // m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE);
}
}
@@ -442,6 +669,7 @@ READ8_MEMBER(nes_vt_state::nt_r)
WRITE8_MEMBER(nes_vt_state::nt_w)
{
+ //logerror("nt wr %04x %02x", offset, data);
m_ntram[decode_nt_addr(offset)] = data;
}
@@ -458,6 +686,8 @@ void nes_vt_state::machine_start()
m_prgbank3->configure_entries(0, m_numbanks, &m_prgrom[0x00000], 0x2000);
save_item(NAME(m_410x));
+ save_item(NAME(m_413x));
+
save_item(NAME(m_8000_addr_latch));
save_item(NAME(m_timer_irq_enabled));
@@ -467,12 +697,18 @@ void nes_vt_state::machine_start()
m_ntram = std::make_unique<uint8_t[]>(0x2000);
save_pointer(NAME(m_ntram.get()), 0x2000);
+ m_chrram = std::make_unique<uint8_t[]>(0x2000);
+ save_pointer(NAME(m_chrram.get()), 0x2000);
+
m_ppu->set_scanline_callback(ppu2c0x_device::scanline_delegate(FUNC(nes_vt_state::scanline_irq),this));
m_ppu->set_hblank_callback(ppu2c0x_device::scanline_delegate(FUNC(nes_vt_state::hblank_irq),this));
// m_ppu->set_hblank_callback(ppu2c0x_device::hblank_delegate(FUNC(device_nes_cart_interface::hblank_irq),m_cartslot->m_cart));
// m_ppu->space(AS_PROGRAM).install_readwrite_handler(0, 0x1fff, read8_delegate(FUNC(device_nes_cart_interface::chr_r),m_cartslot->m_cart), write8_delegate(FUNC(device_nes_cart_interface::chr_w),m_cartslot->m_cart));
m_ppu->space(AS_PROGRAM).install_readwrite_handler(0x2000, 0x3eff, read8_delegate(FUNC(nes_vt_state::nt_r),this), write8_delegate(FUNC(nes_vt_state::nt_w),this));
+ m_ppu->space(AS_PROGRAM).install_readwrite_handler(0, 0x1fff, read8_delegate(FUNC(nes_vt_state::chr_r),this), write8_delegate(FUNC(nes_vt_state::chr_w),this));
+
+
}
void nes_vt_state::machine_reset()
@@ -491,7 +727,10 @@ void nes_vt_state::machine_reset()
m_410x[0xa] = 0x00;
m_410x[0xb] = 0x00;
m_411c = 0x00;
- m_412c = 0x00;
+ m_411d = 0x00;
+ m_4242 = 0x00;
+
+ m_ahigh = (m_csel->read() == 0x01) ? (1 << 25) : 0x0;
m_timer_irq_enabled = 0;
m_timer_running = 0;
m_timer_val = 0;
@@ -705,96 +944,144 @@ int nes_vt_state::calculate_real_video_address(int addr, int extended, int readt
}
}
- uint32_t amod = (m_412c & 0x04) ? (1 << 24) : 0x0;
- return amod | finaladdr;
+ return m_ahigh | finaladdr;
}
/*
nes_vt_state::vt03_8000_w notes
- this is used by
- VT03dogA.bin
- at least, but even in EmuVT the sprite graphics there are corrupt
- so I'm not sure if it's just an incomplete demo, or there is more to this
+ used for MMC3/other mapper compatibility
+ some consoles have scrambled registers for crude copy protection
*/
-// MMC3 compatibility mode
-WRITE8_MEMBER(nes_vt_state::vt03_8000_w)
+static const uint8_t descram_8000_mmc3[5][8] = {
+ {0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x7, 0x8},
+ {0x5, 0x4, 0x3, 0x2, 0x7, 0x6, 0x7, 0x8},
+ {0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x8, 0x7},
+ {0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x7, 0x8},
+ {0x6, 0x7, 0x2, 0x3, 0x4, 0x5, 0x7, 0x8},
+};
+
+void nes_vt_state::scrambled_8000_w(address_space &space, uint16_t offset, uint8_t data, vt_scramble_mode scram)
{
- //logerror("%s: vt03_8000_w (%04x) %02x\n", machine().describe_context(), offset+0x8000, data );
uint16_t addr = offset + 0x8000;
- if((addr < 0xA000) && !(addr & 0x01)) {
- // Bank select
- m_8000_addr_latch = data & 0x07;
- // Bank config
- m_410x[0x05] &= 0x3F;
- m_410x[0x05] |= (data & 0xC0);
+ if((m_411d & 0x01) && (m_411d & 0x03)) {
+ //CNROM compat
+ logerror("vtxx_cnrom_8000_w (%04x) %02x\n", 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("vtxx_mmc1_8000_w (%04x) %02x\n", offset+0x8000, data );
+
+ } else if(m_411d & 0x02) {
+ //UNROM compat
+ logerror("vtxx_unrom_8000_w (%04x) %02x\n", offset+0x8000, data );
+
+ m_410x[0x7] = ((data & 0x0F) << 1);
+ m_410x[0x8] = ((data & 0x0F) << 1) + 1;
update_banks();
- } else if((addr < 0xA000) && (addr & 0x01)) {
- switch(m_8000_addr_latch) {
- case 0x00:
- m_ppu->set_201x_reg(0x6, data);
- break;
-
- case 0x01:
- m_ppu->set_201x_reg(0x7, data);
- break;
-
- case 0x02: // hand?
- m_ppu->set_201x_reg(0x2, data);
- break;
-
- case 0x03: // dog?
- m_ppu->set_201x_reg(0x3, data);
- break;
-
- case 0x04: // ball thrown
- m_ppu->set_201x_reg(0x4, data);
- break;
-
- case 0x05: // ball thrown
- m_ppu->set_201x_reg(0x5, data);
- break;
- case 0x06:
- m_410x[0x7] = data;
- //m_410x[0x9] = data;
- update_banks();
- break;
-
- case 0x07:
- m_410x[0x8] = 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 {
+ //logerror("vtxx_mmc3_8000_w (%04x) %02x\n", offset+0x8000, data );
+
+ //MMC3 compat
+ if((addr < 0xA000) && !(addr & 0x01)) {
+ // Bank select
+ m_8000_addr_latch = data & 0x07;
+ // Bank config
+ m_410x[0x05] = data & ~(1 << 5);
+ update_banks();
+ } else if((addr < 0xA000) && (addr & 0x01)) {
+ switch(m_410x[0x05] & 0x07) {
+ case 0x00:
+ m_ppu->set_201x_reg(descram_8000_mmc3[(int)scram][0], data);
+ break;
+
+ case 0x01:
+ m_ppu->set_201x_reg(descram_8000_mmc3[(int)scram][1], data);
+ break;
+
+ case 0x02: // hand?
+ m_ppu->set_201x_reg(descram_8000_mmc3[(int)scram][2], data);
+ break;
+
+ case 0x03: // dog?
+ m_ppu->set_201x_reg(descram_8000_mmc3[(int)scram][3], data);
+ break;
+
+ case 0x04: // ball thrown
+ m_ppu->set_201x_reg(descram_8000_mmc3[(int)scram][4], data);
+ break;
+
+ case 0x05: // ball thrown
+ m_ppu->set_201x_reg(descram_8000_mmc3[(int)scram][5], data);
+ break;
+ case 0x06:
+ m_410x[descram_8000_mmc3[(int)scram][6]] = data;
+ //m_410x[0x9] = data;
+ update_banks();
+ break;
+
+ case 0x07:
+ m_410x[descram_8000_mmc3[(int)scram][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
+WRITE8_MEMBER(nes_vt_state::vt03_8000_w)
+{
+ scrambled_8000_w(space, offset, data, vt_scramble_mode::NO_SCRAMBLE);
+ //logerror("%s: vt03_8000_w (%04x) %02x\n", machine().describe_context(), offset+0x8000, data );
+}
+WRITE8_MEMBER(nes_vt_state::vt03_8000_hum_w)
+{
+ scrambled_8000_w(space, offset, data, vt_scramble_mode::HUMMER);
+}
+WRITE8_MEMBER(nes_vt_state::vt03_8000_pjoy_w)
+{
+ scrambled_8000_w(space, offset, data, vt_scramble_mode::PJOY);
+}
+
+WRITE8_MEMBER(nes_vt_state::vt03_8000_sp69_w)
+{
+ scrambled_8000_w(space, offset, data, vt_scramble_mode::SP69);
}
/* 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(space, 0x14);
+ //return m_apu->read(space, 0x14);
+ return 0x00;
}
READ8_MEMBER(nes_vt_state::psg1_4015_r)
@@ -837,10 +1124,18 @@ void nes_vt_state::do_dma(uint8_t data, bool broken)
}
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(broken && (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);
+ ppu_vt03_device::set_palette_mode(*m_ppu, PAL_MODE_VT0x);
}
for (int i = 0; i < length; i++)
{
@@ -850,7 +1145,7 @@ void nes_vt_state::do_dma(uint8_t data, bool broken)
} else {
m_maincpu->space(AS_PROGRAM).write_byte(0x2004, spriteData);
}
- if(((src_addr + i) & 0xFF) == length) break;
+ //if(((src_addr + i) & 0xFF) == length && (i != 0)) break;
}
// should last (length * 4 - 1) CPU cycles.
@@ -860,11 +1155,12 @@ void nes_vt_state::do_dma(uint8_t data, bool broken)
WRITE8_MEMBER(nes_vt_state::vt03_4034_w)
{
+ logerror("vt03_4034_w %02x\n", data);
m_vdma_ctrl = data;
}
static ADDRESS_MAP_START( nes_vt_map, AS_PROGRAM, 8, nes_vt_state )
- AM_RANGE(0x0000, 0x1fff) AM_MASK(0x07FF) AM_RAM
+ AM_RANGE(0x0000, 0x07ff) AM_RAM
AM_RANGE(0x2000, 0x3fff) AM_MASK(0x001F) AM_DEVREADWRITE("ppu", ppu2c0x_device, read, write) /* PPU registers */
AM_RANGE(0x4000, 0x4013) AM_DEVREADWRITE("apu", nesapu_device, read, write)
@@ -875,23 +1171,48 @@ static ADDRESS_MAP_START( nes_vt_map, AS_PROGRAM, 8, nes_vt_state )
AM_RANGE(0x4034, 0x4034) AM_WRITE(vt03_4034_w)
- AM_RANGE(0x4100, 0x410b) AM_WRITE(vt03_410x_w)
+ AM_RANGE(0x4100, 0x410b) AM_READ(vt03_410x_r) AM_WRITE(vt03_410x_w)
AM_RANGE(0x8000, 0xffff) AM_DEVICE("prg", address_map_bank_device, amap8)
AM_RANGE(0x8000, 0xffff) AM_WRITE(vt03_8000_w)
AM_RANGE(0x6000, 0x7fff) AM_RAM
ADDRESS_MAP_END
+
/* Some later VT models have more RAM */
static ADDRESS_MAP_START( nes_vt_xx_map, AS_PROGRAM, 8, nes_vt_state )
AM_IMPORT_FROM(nes_vt_map)
AM_RANGE(0x0800, 0x0fff) AM_RAM
ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( nes_vt_hum_map, AS_PROGRAM, 8, nes_vt_state )
+AM_IMPORT_FROM(nes_vt_map)
+AM_RANGE(0x4100, 0x410b) AM_WRITE(vt03_410x_hum_w)
+AM_RANGE(0x8000, 0xffff) AM_WRITE(vt03_8000_hum_w)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( nes_vt_pjoy_map, AS_PROGRAM, 8, nes_vt_state )
+AM_IMPORT_FROM(nes_vt_map)
+AM_RANGE(0x4100, 0x410b) AM_WRITE(vt03_410x_pjoy_w)
+AM_RANGE(0x8000, 0xffff) AM_WRITE(vt03_8000_pjoy_w)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( nes_vt_sp69_map, AS_PROGRAM, 8, nes_vt_state )
+AM_IMPORT_FROM(nes_vt_map)
+AM_RANGE(0x4100, 0x410b) AM_WRITE(vt03_410x_sp69_w)
+AM_RANGE(0x8000, 0xffff) AM_WRITE(vt03_8000_sp69_w)
+ADDRESS_MAP_END
+
+
static ADDRESS_MAP_START( nes_vt_cy_map, AS_PROGRAM, 8, nes_vt_state )
AM_IMPORT_FROM(nes_vt_xx_map)
AM_RANGE(0x41b0, 0x41bf) AM_READ(vt03_41bx_r) AM_WRITE(vt03_41bx_w)
AM_RANGE(0x48a0, 0x48af) AM_READ(vt03_48ax_r) AM_WRITE(vt03_48ax_w)
+ AM_RANGE(0x4130, 0x4136) AM_READ(vt03_413x_r) AM_WRITE(vt03_413x_w)
+ AM_RANGE(0x414F, 0x414F) AM_READ(vt03_414f_r)
+ AM_RANGE(0x415C, 0x415C ) AM_READ(vt03_415c_r)
+
ADDRESS_MAP_END
static ADDRESS_MAP_START( nes_vt_bt_map, AS_PROGRAM, 8, nes_vt_state )
@@ -909,13 +1230,17 @@ static ADDRESS_MAP_START( nes_vt_hh_map, AS_PROGRAM, 8, nes_vt_state )
AM_RANGE(0x4016, 0x4016) AM_READWRITE(nes_in0_r, nes_in0_w)
AM_RANGE(0x4017, 0x4017) AM_READ(nes_in1_r) AM_WRITE(psg1_4017_w)
- AM_RANGE(0x4100, 0x410b) AM_WRITE(vt03_410x_w)
+ AM_RANGE(0x4100, 0x410b) AM_READ(vt03_410x_r) AM_WRITE(vt03_410x_w)
AM_RANGE(0x8000, 0xffff) AM_DEVICE("prg", address_map_bank_device, amap8)
AM_RANGE(0x8000, 0xffff) AM_WRITE(vt03_8000_w)
AM_RANGE(0x4034, 0x4034) AM_WRITE(vt03_4034_w)
AM_RANGE(0x4014, 0x4014) AM_READ(psg1_4014_r) AM_WRITE(vt_hh_sprite_dma_w)
+
+ AM_RANGE(0x414A, 0x414A) AM_READ(vthh_414a_r)
+ AM_RANGE(0x411d, 0x411d) AM_WRITE(vtfp_411d_w)
+
AM_RANGE(0x6000, 0x7fff) AM_RAM
ADDRESS_MAP_END
@@ -928,7 +1253,7 @@ static ADDRESS_MAP_START( nes_vt_dg_map, AS_PROGRAM, 8, nes_vt_state )
AM_RANGE(0x4016, 0x4016) AM_READWRITE(nes_in0_r, nes_in0_w)
AM_RANGE(0x4017, 0x4017) AM_READ(nes_in1_r) AM_WRITE(psg1_4017_w)
- AM_RANGE(0x4100, 0x410b) AM_WRITE(vt03_410x_w)
+ AM_RANGE(0x4100, 0x410b) AM_READ(vt03_410x_r) AM_WRITE(vt03_410x_w)
AM_RANGE(0x411c, 0x411c) AM_WRITE(vt03_411c_w)
@@ -940,6 +1265,26 @@ static ADDRESS_MAP_START( nes_vt_dg_map, AS_PROGRAM, 8, nes_vt_state )
AM_RANGE(0x6000, 0x7fff) AM_RAM
ADDRESS_MAP_END
+static ADDRESS_MAP_START( nes_vt_fp_map, AS_PROGRAM, 8, nes_vt_state )
+ AM_IMPORT_FROM(nes_vt_hh_map)
+ AM_RANGE(0x411e, 0x411e) AM_WRITE(vtfp_411e_w)
+ AM_RANGE(0x4a00, 0x4a00) AM_WRITE(vtfp_4a00_w)
+ AM_RANGE(0x412c, 0x412c) AM_WRITE(vtfp_412c_w)
+ AM_RANGE(0x412d, 0x412d) AM_READ(vtfp_412d_r)
+ AM_RANGE(0x4242, 0x4242) AM_WRITE(vtfp_4242_w)
+ AM_RANGE(0x4119, 0x4119) AM_READ(vtfp_4119_r)
+
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( nes_vt_fa_map, AS_PROGRAM, 8, nes_vt_state )
+
+ AM_IMPORT_FROM(nes_vt_dg_map)
+
+ AM_RANGE(0x412c, 0x412c) AM_READ(vtfa_412c_r) AM_WRITE(vtfa_412c_w)
+ AM_RANGE(0x4242, 0x4242) AM_WRITE(vtfp_4242_w)
+
+ADDRESS_MAP_END
+
static ADDRESS_MAP_START( prg_map, AS_PROGRAM, 8, nes_vt_state )
AM_RANGE(0x0000, 0x1fff) AM_ROMBANK("prg_bank0")
AM_RANGE(0x2000, 0x3fff) AM_ROMBANK("prg_bank1")
@@ -993,9 +1338,17 @@ static GFXDECODE_START( vt03_helper )
GFXDECODE_END
+static const uint8_t descram_ppu_2012_2017[5][6] = {
+ {0x2, 0x3, 0x4, 0x5, 0x6, 0x7},
+ {0x3, 0x2, 0x7, 0x6, 0x5, 0x4},
+ {0x2, 0x3, 0x4, 0x5, 0x6, 0x7},
+ {0x7, 0x6, 0x5, 0x4, 0x2, 0x3},
+ {0x4, 0x7, 0x2, 0x6, 0x5, 0x3},
+};
+
MACHINE_CONFIG_START(nes_vt_state::nes_vt)
/* basic machine hardware */
- MCFG_CPU_ADD("maincpu", M6502, NTSC_APU_CLOCK) // selectable speed?
+ MCFG_CPU_ADD("maincpu", M6502_VTSCR, NTSC_APU_CLOCK) // selectable speed?
MCFG_CPU_PROGRAM_MAP(nes_vt_map)
MCFG_SCREEN_ADD("screen", RASTER)
@@ -1043,6 +1396,32 @@ MACHINE_CONFIG_START(nes_vt_state::nes_vt)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MACHINE_CONFIG_END
+MACHINE_CONFIG_DERIVED(nes_vt_state::nes_vt_hum, nes_vt)
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(nes_vt_hum_map)
+
+ MCFG_PPU_VT03_MODIFY("ppu")
+ MCFG_PPU_VT03_SET_DESCRAMBLE(descram_ppu_2012_2017[3]);
+MACHINE_CONFIG_END
+
+MACHINE_CONFIG_DERIVED(nes_vt_state::nes_vt_pjoy, nes_vt)
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(nes_vt_pjoy_map)
+
+ MCFG_PPU_VT03_MODIFY("ppu")
+ MCFG_PPU_VT03_SET_DESCRAMBLE(descram_ppu_2012_2017[2]);
+MACHINE_CONFIG_END
+
+
+MACHINE_CONFIG_DERIVED(nes_vt_state::nes_vt_sp69, nes_vt)
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(nes_vt_sp69_map)
+
+ MCFG_PPU_VT03_MODIFY("ppu")
+ MCFG_PPU_VT03_SET_DESCRAMBLE(descram_ppu_2012_2017[4]);
+MACHINE_CONFIG_END
+
+
MACHINE_CONFIG_DERIVED(nes_vt_state::nes_vt_xx, nes_vt)
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(nes_vt_xx_map)
@@ -1095,8 +1474,37 @@ MACHINE_CONFIG_DERIVED(nes_vt_state::nes_vt_hh, nes_vt_xx)
MACHINE_CONFIG_END
static INPUT_PORTS_START( nes_vt )
+PORT_START("CARTSEL")
INPUT_PORTS_END
+MACHINE_CONFIG_DERIVED(nes_vt_state::nes_vt_fp, nes_vt_xx)
+MCFG_CPU_MODIFY("maincpu")
+MCFG_CPU_PROGRAM_MAP(nes_vt_fp_map)
+
+MCFG_PPU_VT03_MODIFY("ppu")
+MCFG_PPU_VT03_SET_PAL_MODE(PAL_MODE_NEW_RGB12);
+MACHINE_CONFIG_END
+
+MACHINE_CONFIG_DERIVED(nes_vt_state::nes_vt_fa, nes_vt_xx)
+MCFG_CPU_MODIFY("maincpu")
+MCFG_CPU_PROGRAM_MAP(nes_vt_fa_map)
+
+MACHINE_CONFIG_END
+
+
+static INPUT_PORTS_START( nes_vt_fp )
+ PORT_START("CARTSEL")
+ PORT_DIPNAME( 0x06, 0x00, "Cartridge Select" ) PORT_CODE(KEYCODE_3) PORT_TOGGLE
+ PORT_DIPSETTING( 0x00, "472-in-1" )
+ PORT_DIPSETTING( 0x06, "128-in-1" )
+MACHINE_CONFIG_END
+
+static INPUT_PORTS_START( nes_vt_fa )
+ PORT_START("CARTSEL")
+ PORT_DIPNAME( 0x01, 0x00, "Cartridge Select" ) PORT_CODE(KEYCODE_3) PORT_TOGGLE
+ PORT_DIPSETTING( 0x00, "508-in-1" )
+ PORT_DIPSETTING( 0x01, "130-in-1" )
+MACHINE_CONFIG_END
ROM_START( vdogdeme )
@@ -1273,6 +1681,11 @@ ROM_START( sy889 )
ROM_REGION( 0x800000, "mainrom", 0 )
ROM_LOAD( "sy889_w25q64.bin", 0x00000, 0x800000, CRC(fcdaa6fc) SHA1(0493747facf2172b8af22010851668bb18cbb3e4) )
ROM_END
+
+ROM_START( sy888b )
+ ROM_REGION( 0x400000, "mainrom", 0 )
+ ROM_LOAD( "sy888b_f25q32.bin", 0x00000, 0x400000, CRC(a8298c33) SHA1(7112dd13d5fb5f9f9d496816758defd22773ec6e) )
+ROM_END
#if 0
ROM_START( mc_15kin1 )
ROM_REGION( 0x200000, "mainrom", 0 )
@@ -1291,7 +1704,7 @@ ROM_END
#endif
ROM_START( dgun2573 )
ROM_REGION( 0x2000000, "mainrom", 0 )
- ROM_LOAD( "dgun2573.bin", 0x00000, 0x2000000, CRC(cde71a53) SHA1(d0d4c1965876291861781ecde46b1142b062f1f3) )
+ ROM_LOAD( "dgun2573.bin", 0x00000, 0x2000000, BAD_DUMP CRC(cde71a53) SHA1(d0d4c1965876291861781ecde46b1142b062f1f3) )
ROM_END
ROM_START( bittboy )
@@ -1299,6 +1712,61 @@ ROM_START( bittboy )
ROM_LOAD( "bittboy_flash_read_S29GL256N-TF-V2.bin", 0x00000, 0x2000000, CRC(24c802d7) SHA1(c1300ff799b93b9b53060b94d3985db4389c5d3a) )
ROM_END
+ROM_START( mc_89in1 )
+ ROM_REGION( 0x400000, "mainrom", 0 )
+ ROM_LOAD( "89in1.bin", 0x00000, 0x400000, CRC(b97f8ce5) SHA1(1a8e67f2b58a671ceec2b0ed18ec5954a71ae63a) )
+ROM_END
+
+ROM_START( mc_cb280 )
+ ROM_REGION( 0x400000, "mainrom", 0 )
+ ROM_LOAD( "w25q32.u5", 0x00000, 0x400000, CRC(c9541bdf) SHA1(f0ce46f18658ca5dbed881e5a80460e59820bbd0) )
+ROM_END
+
+ROM_START( mc_pg150 )
+ ROM_REGION( 0x2000000, "mainrom", 0 )
+ ROM_LOAD( "pocketgames150-in1.bin", 0x00000, 0x2000000, CRC(32f1176b) SHA1(2cfd9b61ebdfc328f020ae9bd5e5e2219321e828) )
+ROM_END
+
+ROM_START( mc_hh210 )
+ ROM_REGION( 0x1000000, "mainrom", 0 )
+ ROM_LOAD( "msp55lv128t.u4", 0x00000, 0x1000000, CRC(9ba520d4) SHA1(627f811b24314197e289a2ade668ff4115421bed) )
+ROM_END
+
+ROM_START( dvnimbus )
+ ROM_REGION( 0x1000000, "mainrom", 0 )
+ ROM_LOAD( "2012-7-4-V1.BIN", 0x00000, 0x1000000, CRC(a91d7aa6) SHA1(9421b70b281bb630752bc352c3715258044c0bbe) )
+ROM_END
+
+ROM_START( cbrs8 )
+ ROM_REGION( 0x1000000, "mainrom", 0 )
+ ROM_LOAD( "RS-8.bin", 0x00000, 0x1000000, BAD_DUMP CRC(10b2bed0) SHA1(0453a1e6769818ccf25dcf22b2c6198a5688a1d4) )
+ROM_END
+
+ROM_START( mc_tv200 )
+ ROM_REGION( 0x800000, "mainrom", 0 )
+ ROM_LOAD( "S29GL064N90.bin", 0x00000, 0x800000, CRC(ae1905d2) SHA1(11582055713ba937c1ad32c4ada8683eebc1c83c) )
+ROM_END
+
+ROM_START( fcpocket )
+ ROM_REGION( 0x8000000, "mainrom", 0 )
+ ROM_LOAD( "S29GL01GP.bin", 0x00000, 0x8000000, CRC(8703b18a) SHA1(07943443294e80ca93f83181c8bdbf950b87c52f) )
+ROM_END
+
+ROM_START( mog_m320 )
+ ROM_REGION( 0x800000, "mainrom", 0 )
+ ROM_LOAD( "W25Q64FV.bin", 0x00000, 0x800000, CRC(3c5e1b36) SHA1(4bcbf35ebf2b1714ccde5de758a89a6a39528f89) )
+ROM_END
+
+ROM_START( fapocket )
+ ROM_REGION( 0x4000000, "mainrom", 0 )
+ ROM_LOAD( "S29GL512N.bin", 0x00000, 0x4000000, CRC(37d0fb06) SHA1(0146a2fae32e23b65d4032c508f0d12cedd399c3) )
+ROM_END
+
+ROM_START( zdog )
+ ROM_REGION( 0x400000, "mainrom", 0 )
+ ROM_LOAD( "zdog.bin", 0x00000, 0x400000, CRC(5ed3485b) SHA1(5ab0e9370d4ed1535205deb0456878c4e400dd81) )
+ROM_END
+
// earlier version of vdogdemo
CONS( 200?, vdogdeme, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "VRT", "V-Dog (prototype, earlier)", MACHINE_NOT_WORKING )
@@ -1325,52 +1793,86 @@ CONS( 200?, vgpmini, 0, 0, nes_vt_vg, nes_vt, nes_vt_state, 0, "<unknown>",
// emulation
CONS( 200?, dgun2500, 0, 0, nes_vt_dg, nes_vt, nes_vt_state, 0, "dreamGEAR", "dreamGEAR Wireless Motion Control with 130 games (DGUN-2500)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND)
-// these are NOT VT03, but something newer but based around the same basic designs
-// (no visible tiles in ROM using standard decodes tho, might need moving out of here)
-// dgun2561 at least boots, but no visible gfx due to missing PPU features
-CONS( 2012, dgun2561, 0, 0, nes_vt_dg, nes_vt, nes_vt_state, 0, "dreamGEAR", "dreamGEAR My Arcade Portable Gaming System (DGUN-2561)", MACHINE_NOT_WORKING )
-CONS( 2015, dgun2573, 0, 0, nes_vt_hh, nes_vt, nes_vt_state, 0, "dreamGEAR", "dreamGEAR My Arcade Gamer V Portable Gaming System (DGUN-2573)", MACHINE_NOT_WORKING )
+// don't even get to menu. very enhanced chipset, VT368/9?
+CONS( 2012, dgun2561, 0, 0, nes_vt_cy, nes_vt, nes_vt_state, 0, "dreamGEAR", "dreamGEAR My Arcade Portable Gaming System (DGUN-2561)", MACHINE_NOT_WORKING )
CONS( 200?, lexcyber, 0, 0, nes_vt_cy, nes_vt, nes_vt_state, 0, "Lexibook", "Lexibook Compact Cyber Arcade", MACHINE_NOT_WORKING )
+// 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, nes_vt, nes_vt_state, 0, "dreamGEAR", "dreamGEAR My Arcade Gamer V Portable Gaming System (DGUN-2573)", MACHINE_WRONG_COLORS | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
+
// these are VT1682 based and have scrambled CPU opcodes. Will need VT1682 CPU and PPU
// to be emulated
// (no visible tiles in ROM using standard decodes tho, might need moving out of here)
CONS( 200?, ii8in1, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "Intec", "InterAct 8-in-1", MACHINE_NOT_WORKING )
CONS( 200?, ii32in1, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "Intec", "InterAct 32-in-1", MACHINE_NOT_WORKING )
-// this has 'Shark' and 'Octopus' etc. like mc_dgear but the graphics are entirely corrupt for any game using the extended modes, bad dump or different banking?
-CONS( 200?, mc_sp69, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "Sports Game 69 in 1", MACHINE_NOT_WORKING )
+// this has 'Shark' and 'Octopus' etc. like mc_dgear but uses scrambled bank registers
+CONS( 200?, mc_sp69, 0, 0, nes_vt_sp69, nes_vt, nes_vt_state, 0, "<unknown>", "Sports Game 69 in 1", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND)
-// doesn't boot
-CONS( 200?, mc_sam60, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "Hummer Technology Co., Ltd.", "Samuri (60 in 1)", MACHINE_NOT_WORKING )
+// Hummer systems, scrambled bank register
+CONS( 200?, mc_sam60, 0, 0, nes_vt_hum, nes_vt, nes_vt_state, 0, "Hummer Technology Co., Ltd.", "Samuri (60 in 1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
+CONS( 200?, zdog, 0, 0, nes_vt_hum, nes_vt, nes_vt_state, 0, "Hummer Technology Co., Ltd.", "ZDog (44 in 1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
// titles below don't seem to use the enhanced modes, so probably VT01 / VT02 or plain standalone famiclones?
// very plain menus
-CONS( 200?, pjoyn50, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "PowerJoy Navigator 50 in 1", MACHINE_NOT_WORKING )
-CONS( 200?, pjoys30, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "PowerJoy Supermax 30 in 1", MACHINE_NOT_WORKING )
-CONS( 200?, pjoys60, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "PowerJoy Supermax 60 in 1", MACHINE_NOT_WORKING )
+CONS( 200?, pjoyn50, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "PowerJoy Navigator 50 in 1", MACHINE_IMPERFECT_GRAPHICS )
+CONS( 200?, pjoys30, 0, 0, nes_vt_pjoy, nes_vt, nes_vt_state, 0, "<unknown>", "PowerJoy Supermax 30 in 1", MACHINE_IMPERFECT_GRAPHICS )
+CONS( 200?, pjoys60, 0, 0, nes_vt_pjoy, nes_vt, nes_vt_state, 0, "<unknown>", "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, nes_vt, nes_vt_state, 0, "<unknown>", "Super Arcade 110 (set 1)", MACHINE_NOT_WORKING )
-CONS( 200?, sarc110a, sarc110, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "Super Arcade 110 (set 2)", MACHINE_NOT_WORKING )
+CONS( 200?, sarc110, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "Super Arcade 110 (set 1)", MACHINE_IMPERFECT_GRAPHICS )
+CONS( 200?, sarc110a, sarc110, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "Super Arcade 110 (set 2)", MACHINE_IMPERFECT_GRAPHICS )
// both offer chinese or english menus
CONS( 200?, mc_110cb, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "CoolBoy", "110 in 1 CoolBaby (CoolBoy RS-1S)", MACHINE_IMPERFECT_GRAPHICS )
CONS( 200?, mc_138cb, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "CoolBoy", "138 in 1 CoolBaby (CoolBoy RS-5, PCB060-10009011V1.3)", MACHINE_IMPERFECT_GRAPHICS )
+// doesn't boot, bad dump
+CONS( 201?, cbrs8, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "CoolBoy", "CoolBoy RS-8 168 in 1", MACHINE_NOT_WORKING )
+
CONS( 200?, gprnrs1, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "Game Prince RS-1", MACHINE_IMPERFECT_GRAPHICS )
CONS( 200?, gprnrs16, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "Game Prince RS-16", MACHINE_IMPERFECT_GRAPHICS )
// unsorted, these were all in nes.xml listed as ONE BUS systems
CONS( 200?, mc_dg101, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "dreamGEAR", "dreamGEAR 101 in 1", MACHINE_IMPERFECT_GRAPHICS ) // dreamGear, but no enhanced games?
-CONS( 200?, mc_aa2, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "100 in 1 Arcade Action II (AT-103)", MACHINE_NOT_WORKING )
+CONS( 200?, mc_aa2, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "100 in 1 Arcade Action II (AT-103)", MACHINE_IMPERFECT_GRAPHICS )
CONS( 200?, mc_105te, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "2011 Super HiK 105 in 1 Turbo Edition", MACHINE_NOT_WORKING )
-CONS( 200?, mc_8x6cb, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "CoolBoy", "888888 in 1 (Coolboy AEF-390)", MACHINE_NOT_WORKING )
-CONS( 200?, mc_9x6ss, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "999999 in 1 (PXP2 Slim Station)", MACHINE_NOT_WORKING )
-CONS( 200?, mc_9x6sa, mc_9x6ss, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "999999 in 1 (8 bit Slim Station, NEWPXP-DVT22-A PCB)", MACHINE_NOT_WORKING )
+CONS( 200?, mc_8x6cb, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "CoolBoy", "888888 in 1 (Coolboy AEF-390)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
+CONS( 200?, mc_9x6ss, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "999999 in 1 (PXP2 Slim Station)", MACHINE_IMPERFECT_GRAPHICS )
+CONS( 200?, mc_9x6sa, mc_9x6ss, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "999999 in 1 (8 bit Slim Station, NEWPXP-DVT22-A PCB)", MACHINE_IMPERFECT_GRAPHICS )
CONS( 200?, mc_7x6ss, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "777777 in 1 (8 bit Slim Station, NEWPXP-DVT22-A PCB)", MACHINE_IMPERFECT_GRAPHICS )
CONS( 200?, mc_8x6ss, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "888888 in 1 (8 bit Slim Station, NEWPXP-DVT22-A PCB)", MACHINE_IMPERFECT_GRAPHICS )
CONS( 2004, mc_dcat8, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "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, nes_vt, nes_vt_state, 0, "<unknown>", "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, nes_vt, nes_vt_state, 0, "SY Corp", "SY-889 300 in 1 Handheld", MACHINE_NOT_WORKING )
+CONS( 2017, sy889, 0, 0, nes_vt_hh, nes_vt, nes_vt_state, 0, "SY Corp", "SY-889 300 in 1 Handheld", MACHINE_IMPERFECT_GRAPHICS )
+CONS( 2016, sy888b, 0, 0, nes_vt_hh, nes_vt, nes_vt_state, 0, "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, nes_vt, nes_vt_state, 0, "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, nes_vt, nes_vt_state, 0, "BittBoy", "BittBoy Mini FC 300 in 1", MACHINE_NOT_WORKING )
+CONS( 2017, bittboy, 0, 0, nes_vt_bt, nes_vt, nes_vt_state, 0, "BittBoy", "BittBoy Mini FC 300 in 1", MACHINE_IMPERFECT_GRAPHICS )
+// Runs well, all games seem to work
+CONS( 201?, mc_89in1, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "<unknown>", "89 in 1 Mini Game Console (060-92023011V1.0)", MACHINE_IMPERFECT_GRAPHICS )
+// Broken GFX, investigate
+CONS( 201?, mc_pg150, 0, 0, nes_vt_bt, nes_vt, nes_vt_state, 0, "<unknown>", "Pocket Games 150 in 1", MACHINE_NOT_WORKING )
+// No title screen, but press start and menu and games run fine. Makes odd
+// memory accesses which probably explain broken title screen
+CONS( 201?, mc_hh210, 0, 0, nes_vt_xx, nes_vt, nes_vt_state, 0, "<unknown>", "Handheld 210 in 1", MACHINE_NOT_WORKING )
+// First half of games don't work, probably bad dump
+CONS( 201?, dvnimbus, 0, 0, nes_vt_vg, nes_vt, nes_vt_state, 0, "<unknown>", "DVTech Nimbus 176 in 1", MACHINE_NOT_WORKING )
+// Works fine, VT02 based
+CONS( 201?, mc_tv200, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "Thumbs Up", "200 in 1 Retro TV Game", 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, nes_vt_fp, nes_vt_state, 0, "<unknown>", "FC Pocket 600 in 1", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
+// 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, nes_vt_fa, nes_vt_state, 0, "<unknown>", "Family Pocket 638 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, nes_vt, nes_vt_state, 0, "MOGIS", "MOGIS M320 246 in 1 Handheld", MACHINE_NOT_WORKING )