From 304abd860c8f13f39979bcf300b9a3eb4b6aec47 Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 7 Feb 2018 19:09:56 +0000 Subject: Several nes_vt Fixes and Improvements (#3178) * Add 89 in 1 mini console * Add mc_cb280, similar to sy889 * More VTxx ROMs * Add more nes_vt systems * Add SY888B * Add support for VTxx systems with scrambled instructions (FC Pocket, DGUN2573) * Add support for Family Pocket, and more FC Pocket games * Small fixes and reclassifications (nw) * Support for VTxx scrambled banking (thanks NewRisingSun for help) * New palette code from NewRisingSun, etc * Various VT03 fixes, several systems including ZDog now working * nes_vt comment/status updates (nw) * Refactor m6502_vtscr (nw) --- scripts/target/mame/mess.lua | 2 + src/devices/video/ppu2c0x.cpp | 3 + src/devices/video/ppu2c0x.h | 1 + src/devices/video/ppu2c0x_vt.cpp | 190 +++++----- src/devices/video/ppu2c0x_vt.h | 12 +- src/mame/drivers/nes_vt.cpp | 748 ++++++++++++++++++++++++++++++++------- src/mame/machine/m6502_vtscr.cpp | 97 +++++ src/mame/machine/m6502_vtscr.h | 58 +++ src/mame/mame.lst | 12 + 9 files changed, 905 insertions(+), 218 deletions(-) create mode 100644 src/mame/machine/m6502_vtscr.cpp create mode 100644 src/mame/machine/m6502_vtscr.h diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index ccd0b44fa27..6c8c86560ff 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -2542,6 +2542,8 @@ files { MAME_DIR .. "src/mame/audio/vboy.cpp", MAME_DIR .. "src/mame/audio/vboy.h", MAME_DIR .. "src/mame/drivers/gamecube.cpp", + MAME_DIR .. "src/mame/machine/m6502_vtscr.cpp", + MAME_DIR .. "src/mame/machine/m6502_vtscr.h", } createMESSProjects(_target, _subtarget, "nokia") diff --git a/src/devices/video/ppu2c0x.cpp b/src/devices/video/ppu2c0x.cpp index 86c265e9035..4370d9328d4 100644 --- a/src/devices/video/ppu2c0x.cpp +++ b/src/devices/video/ppu2c0x.cpp @@ -1329,6 +1329,9 @@ uint16_t ppu2c0x_device::get_vram_dest() { return m_videomem_addr; } +void ppu2c0x_device::set_vram_dest(uint16_t dest) { + m_videomem_addr = dest; +} /************************************* * diff --git a/src/devices/video/ppu2c0x.h b/src/devices/video/ppu2c0x.h index 11eff9624ce..38218e28628 100644 --- a/src/devices/video/ppu2c0x.h +++ b/src/devices/video/ppu2c0x.h @@ -159,6 +159,7 @@ public: dev.m_use_sprite_write_limitation = false; } uint16_t get_vram_dest(); + void set_vram_dest(uint16_t dest); protected: // registers definition diff --git a/src/devices/video/ppu2c0x_vt.cpp b/src/devices/video/ppu2c0x_vt.cpp index bfd18d3d68a..e396999a950 100644 --- a/src/devices/video/ppu2c0x_vt.cpp +++ b/src/devices/video/ppu2c0x_vt.cpp @@ -24,6 +24,8 @@ ppu_vt03_device::ppu_vt03_device(const machine_config &mconfig, const char *tag, m_read_bg(*this), m_read_sp(*this) { + for(int i = 0; i < 6; i++) + m_2012_2017_descramble[i] = 2 + i; } READ8_MEMBER(ppu_vt03_device::palette_read) @@ -40,90 +42,75 @@ READ8_MEMBER(ppu_vt03_device::palette_read) void ppu_vt03_device::set_new_pen(int i) { - if(m_pal_mode == PAL_MODE_NEW_RGB) { - uint16_t rgbval = (m_newpal[i&0x7f] & 0xff) | ((m_newpal[(i&0x7f)+0x80] & 0xff)<<8); - uint8_t blue = (rgbval & 0x001f) << 3; - uint8_t green = (rgbval & 0x3e0) >> 2; - uint8_t red = (rgbval & 0x7C00) >> 7; - m_palette->set_pen_color(i & 0x7f, rgb_t(red, green, blue)); + if((i < 0x20) && ((i & 0x3) == 0)) { + m_palette->set_pen_color(i & 0x7f, rgb_t(0, 0, 0)); } else { - // TODO: should this be tidied up? - uint16_t palval = (m_newpal[i&0x7f] & 0x3f) | ((m_newpal[(i&0x7f)+0x80] & 0x3f)<<6); - - uint8_t rhue = palval & 0x0F; - uint8_t rlum = (palval >> 4) & 0x0F; - uint8_t rsat = (palval >> 8) & 0x0F; - //See http://wiki.nesdev.com/w/index.php/VT03%2B_Enhanced_Palette#Inverted_extended_color_numbers - bool inverted = (rlum < ((rsat + 1) >> 1) || rlum > (15 - (rsat >>1))); - if(inverted && (m_pal_mode != PAL_MODE_NEW_VG)) { - rsat = 16 - rsat; - rlum = (rlum - 8) & 0x0F; - uint8_t hue_lut[16] = {0xD, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x0, 0xE, 0xF}; - rhue = hue_lut[rhue]; - } - - // Get base color - double hue = 287.0; - - double Kr = 0.2989; - double Kb = 0.1145; - double Ku = 2.029; - double Kv = 1.140; - - double sat; - double y, u, v; - double rad; - int R, G, B; - switch (rhue) - { - case 0: - sat = 0; rad = 0; - y = 1.0; - break; - - case 13: - sat = 0; rad = 0; - y = 0.77; - break; - - case 14: - case 15: - sat = 0; rad = 0; y = 0; - break; - - default: - sat = (m_pal_mode == PAL_MODE_NEW_VG) ? 0.5 : 0.7; - rad = M_PI * ((rhue * 30 + hue) / 180.0); - y = (m_pal_mode == PAL_MODE_NEW_VG) ? 0.4 : 0.9; - break; + if(m_pal_mode == PAL_MODE_NEW_RGB) { + uint16_t rgbval = (m_newpal[i&0x7f] & 0xff) | ((m_newpal[(i&0x7f)+0x80] & 0xff)<<8); + uint8_t blue = (rgbval & 0x001f) << 3; + uint8_t green = (rgbval & 0x3e0) >> 2; + uint8_t red = (rgbval & 0x7C00) >> 7; + m_palette->set_pen_color(i & 0x7f, rgb_t(red, green, blue)); + } else if(m_pal_mode == PAL_MODE_NEW_RGB12) { + uint16_t rgbval = (m_newpal[i&0x7f] & 0x3f) | ((m_newpal[(i&0x7f)+0x80] & 0x3f)<<6); + uint8_t red = (rgbval & 0x000f) << 4; + uint8_t green = (rgbval & 0x0f0); + uint8_t blue = (rgbval & 0xf00) >> 4; + m_palette->set_pen_color(i & 0x7f, rgb_t(red, green, blue)); + } else { + // Credit to NewRisingSun + uint16_t palval = (m_newpal[i&0x7f] & 0x3f) | ((m_newpal[(i&0x7f)+0x80] & 0x3f)<<6); + int nPhase = (palval >>0) &0xF; + int nLuma = (palval >>4) &0xF; + int nChroma = (palval >>8) &0xF; + float phaseOffset = -11.0; + //bool inverted = false; + if ((nLuma < (nChroma+1) >>1 || nLuma > 15 -(nChroma >>1)) && (m_pal_mode != PAL_MODE_NEW_VG)) { + //inverted = true; + // Strange color number wrap-around. Is this for protection reasons, or a bug of the original hardware? + // The VT03 data sheet advises programmers that 4 <= nLuma*2 +nChroma <= 0x1F, which does not correspond exactly to this condition. + static const unsigned char altPhases[16] = { 13, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 0, 14, 15}; + static const float altPhaseOffset[16] = { -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, 0, -5, -5, -5}; // Slight tweak in phase 6 for Z-Dog + phaseOffset += altPhaseOffset[nPhase]; // These "alternative" colors seem to be slightly shifted in addition to being wrapped-around, at least in EmuVT. + nPhase = altPhases[nPhase]; + nChroma = 16 -nChroma; + nLuma = (nLuma -8) &0xF; + } + float fLuma = (nLuma-4) /9.625; // Value determined from matching saturation =0 phases 1-12 + float fChroma = nChroma /18.975; // Value determined from matching phases 0 and 13 across all luminance and saturation levels + float fPhase = ((nPhase-2) *30.0 +phaseOffset) *M_PI /180.0; + if(m_pal_mode == PAL_MODE_NEW_VG) { + if(fPhase > 0 && fPhase < 13) { + fLuma /= 1.5; + fChroma /= 2; + } + } + float Y = fLuma; + float C = fChroma; + if (nPhase == 0 || nPhase >12) C =0.0;// Phases 0 and 13-15 are grays + if (nPhase == 0) Y += fChroma; // Phase 0 is the upper bound of the waveform + if (nPhase ==13) Y -= fChroma; // Phase 13 is the lower bound of the waveform + if (nPhase >=14) Y = 0.0; // Phases 14 and 15 always black + + float V = sin(fPhase) *C *1.05; // 1.05 needed to get closer to EmuVT palette's color levels in phases 1-12 + float U = cos(fPhase) *C *1.05; + float R = Y + 1.1400*V + 0.0000*U; + float G = Y - 0.5807*V - 0.3940*U; + float B = Y - 0.0000*V + 2.0290*U; + if (R <0.0) R =0.0; + if (R >1.0) R =1.0; + if (G <0.0) G =0.0; + if (G >1.0) G =1.0; + if (B <0.0) B =0.0; + if (B >1.0) B =1.0; + int RV = R *255.0; + int GV = G *255.0; + int BV = B *255.0; + + m_palette->set_pen_color(i & 0x7f, rgb_t(RV, GV ,BV)); } - - sat *= (rsat / 15.0); - y *= (rlum / 15.0); - u = sat * cos(rad); - v = sat * sin(rad); - - /* Transform to RGB */ - R = (y + Kv * v) * 255.0; - G = (y - (Kb * Ku * u + Kr * Kv * v) / (1 - Kb - Kr)) * 255.0; - B = (y + Ku * u) * 255.0; - - /* Clipping, in case of saturation */ - if (R < 0) - R = 0; - if (R > 255) - R = 255; - if (G < 0) - G = 0; - if (G > 255) - G = 255; - if (B < 0) - B = 0; - if (B > 255) - B = 255; - - m_palette->set_pen_color(i & 0x7f, rgb_t(R, G ,B)); } + } @@ -147,7 +134,13 @@ WRITE8_MEMBER(ppu_vt03_device::palette_write) READ8_MEMBER( ppu_vt03_device::read ) { - return ppu2c0x_device::read(space,offset); + if(offset <= 0xf) { + return ppu2c0x_device::read(space,offset); + } else if(offset <= 0x1f) { + return get_201x_reg(offset & 0x0f); + } else { + return 0; + } } void ppu_vt03_device::init_palette(palette_device &palette, int first_entry) @@ -187,15 +180,13 @@ void ppu_vt03_device::device_reset() m_read_sp.resolve_safe(0); for (int i = 0;i < 0xff;i++) m_newpal[i] = 0x0; - set_2010_reg(0x00); - set_2010_reg(0x80); - set_2010_reg(0x00); // todo: what are the actual defaults for these? for (int i = 0;i < 0x20;i++) set_201x_reg(i, 0x00); init_palette(*m_palette, 0); + m_read_bg4_bg3 = 0; m_va34 = 0; } @@ -233,6 +224,7 @@ void ppu_vt03_device::make_sprite_pixel_data(uint8_t &pixel_data, int flipx) ppu2c0x_device::make_sprite_pixel_data(pixel_data, flipx); int is4bpp = get_201x_reg(0x0) & 0x04; + int is16pix = get_201x_reg(0x0) & 0x01; if (is4bpp) { @@ -242,6 +234,12 @@ void ppu_vt03_device::make_sprite_pixel_data(uint8_t &pixel_data, int flipx) pixel_data |= (((m_extplanebuf[0] & 1) << 5) | ((m_extplanebuf[1] & 1) << 6)); m_extplanebuf[0] = m_extplanebuf[0] >> 1; m_extplanebuf[1] = m_extplanebuf[1] >> 1; + + if(is16pix) { + uint8_t pix0 = pixel_data & 0x03; + uint8_t pix1 = (pixel_data >> 5) & 0x03; + pixel_data = pix1 | (pix0 << 5); + } } else { @@ -268,7 +266,12 @@ void ppu_vt03_device::draw_sprite_pixel(int sprite_xpos, int color, int pixel, u /* this mode makes use of the extra planes to increase sprite width instead we probably need to split them out again and draw them at xpos+8 with a cliprect - not seen used yet */ - bitmap.pix16(m_scanline, sprite_xpos + pixel) = pixel_data + (machine().rand()&3); + if((pixel_data & 0x03) != 0) + bitmap.pix16(m_scanline, sprite_xpos + pixel) = (pixel_data & 0x03) + (4 * color); + if(((pixel_data >> 5) & 0x03) != 0) + bitmap.pix16(m_scanline, sprite_xpos + pixel + 8) = ((pixel_data >> 5) & 0x03) + (4 * color); + //ppu2c0x_device::draw_sprite_pixel(sprite_xpos, color, pixel, pixel_data & 0x03, bitmap); + //ppu2c0x_device::draw_sprite_pixel(sprite_xpos, color, pixel + 8, (pixel_data >> 5) & 0x03, bitmap); } } else @@ -345,7 +348,7 @@ void ppu_vt03_device::draw_tile_pixel(uint8_t pix, int color, uint16_t back_pen, } else { - pen = back_pen; // fixme backpen logic probably differs on vt03 due to extra colours + pen = 0; // fixme backpen logic probably differs on vt03 due to extra colours } *dest = pen; } @@ -409,31 +412,32 @@ WRITE8_MEMBER(ppu_vt03_device::write) break; case 0x11: + m_201x_regs[0x1] = data; break; case 0x12: - m_201x_regs[0x2] = data; + m_201x_regs[m_2012_2017_descramble[0]] = data; break; case 0x13: - m_201x_regs[0x3] = data; + m_201x_regs[m_2012_2017_descramble[1]] = data; break; case 0x14: - m_201x_regs[0x4] = data; + m_201x_regs[m_2012_2017_descramble[2]] = data; break; case 0x15: - m_201x_regs[0x5] = data; + m_201x_regs[m_2012_2017_descramble[3]] = data; break; case 0x16: - m_201x_regs[0x6] = data; + m_201x_regs[m_2012_2017_descramble[4]] = data; break; case 0x17: logerror("set reg 7 %02x\n", data); - m_201x_regs[0x7] = data; + m_201x_regs[m_2012_2017_descramble[5]] = data; break; case 0x18: diff --git a/src/devices/video/ppu2c0x_vt.h b/src/devices/video/ppu2c0x_vt.h index da9857aae38..aa62b29622c 100644 --- a/src/devices/video/ppu2c0x_vt.h +++ b/src/devices/video/ppu2c0x_vt.h @@ -30,10 +30,15 @@ #define MCFG_PPU_VT03_SET_PAL_MODE(pmode) \ ppu_vt03_device::set_palette_mode(*device, pmode); +#define MCFG_PPU_VT03_SET_DESCRAMBLE(dsc) \ + ppu_vt03_device::set_201x_descramble(*device, dsc); + + enum vtxx_pal_mode { PAL_MODE_VT0x, PAL_MODE_NEW_RGB, - PAL_MODE_NEW_VG + PAL_MODE_NEW_VG, + PAL_MODE_NEW_RGB12, }; class ppu_vt03_device : public ppu2c0x_device { @@ -44,6 +49,7 @@ public: template static devcb_base &set_read_sp_callback(device_t &device, Object &&cb) { return downcast(device).m_read_sp.set_callback(std::forward(cb)); } static void set_palette_mode(device_t &device, vtxx_pal_mode pmode) { downcast(device).m_pal_mode = pmode; } + static void set_201x_descramble(device_t &device, const uint8_t descramble[6]) { for (int i = 0; i < 6; i++) downcast(device).m_2012_2017_descramble[i] = descramble[i]; } virtual DECLARE_READ8_MEMBER(read) override; virtual DECLARE_WRITE8_MEMBER(write) override; @@ -86,7 +92,9 @@ private: palette_device *m_palette; uint8_t m_201x_regs[0x20]; - + + uint8_t m_2012_2017_descramble[0x6]; + vtxx_pal_mode m_pal_mode = PAL_MODE_VT0x; void set_2010_reg(uint8_t data); 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 m_ntram; + std::unique_ptr 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 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; @@ -239,6 +302,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) { @@ -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(*m_maincpu).set_next_scramble(true); + else if(data == 0x00) + dynamic_cast(*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(*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(0x2000); save_pointer(NAME(m_ntram.get()), 0x2000); + m_chrram = std::make_unique(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, "", // 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, "", "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, "", "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, "", "PowerJoy Navigator 50 in 1", MACHINE_NOT_WORKING ) -CONS( 200?, pjoys30, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "", "PowerJoy Supermax 30 in 1", MACHINE_NOT_WORKING ) -CONS( 200?, pjoys60, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "", "PowerJoy Supermax 60 in 1", MACHINE_NOT_WORKING ) +CONS( 200?, pjoyn50, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "", "PowerJoy Navigator 50 in 1", MACHINE_IMPERFECT_GRAPHICS ) +CONS( 200?, pjoys30, 0, 0, nes_vt_pjoy, nes_vt, nes_vt_state, 0, "", "PowerJoy Supermax 30 in 1", MACHINE_IMPERFECT_GRAPHICS ) +CONS( 200?, pjoys60, 0, 0, nes_vt_pjoy, nes_vt, nes_vt_state, 0, "", "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, "", "Super Arcade 110 (set 1)", MACHINE_NOT_WORKING ) -CONS( 200?, sarc110a, sarc110, 0, nes_vt, nes_vt, nes_vt_state, 0, "", "Super Arcade 110 (set 2)", MACHINE_NOT_WORKING ) +CONS( 200?, sarc110, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "", "Super Arcade 110 (set 1)", MACHINE_IMPERFECT_GRAPHICS ) +CONS( 200?, sarc110a, sarc110, 0, nes_vt, nes_vt, nes_vt_state, 0, "", "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, "", "Game Prince RS-1", MACHINE_IMPERFECT_GRAPHICS ) CONS( 200?, gprnrs16, 0, 0, nes_vt, nes_vt, nes_vt_state, 0, "", "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, "", "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, "", "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, "", "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, "", "999999 in 1 (PXP2 Slim Station)", MACHINE_NOT_WORKING ) -CONS( 200?, mc_9x6sa, mc_9x6ss, 0, nes_vt, nes_vt, nes_vt_state, 0, "", "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, "", "999999 in 1 (PXP2 Slim Station)", MACHINE_IMPERFECT_GRAPHICS ) +CONS( 200?, mc_9x6sa, mc_9x6ss, 0, nes_vt, nes_vt, nes_vt_state, 0, "", "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, "", "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, "", "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, "", "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, "", "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, "", "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, "", "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, "", "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, "", "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, "", "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, "", "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 ) diff --git a/src/mame/machine/m6502_vtscr.cpp b/src/mame/machine/m6502_vtscr.cpp new file mode 100644 index 00000000000..e8f76bae096 --- /dev/null +++ b/src/mame/machine/m6502_vtscr.cpp @@ -0,0 +1,97 @@ +// license:BSD-3-Clause +// copyright-holders:David Shah +/*************************************************************************** + + m6502_vtscr.cpp + + 6502 with VRT VTxx instruction scrambling + + Scrambling in newer NES-based VTxx systems (FC pocket, etc) seems to be + enabled with a write of 5 to 0x411E, then is activated at the next jump? + When enabled, opcodes are to be XORed with 0xA1 + + Another form of scrambling is used in the VRT VT1682, this is not yet + implemented at all in MAME (it's used for the MiWi2 and InterAct consoles). + This is simpler, permanently activated and consists of swapping opcode bits + 7 and 2. + +***************************************************************************/ + +#include "emu.h" +#include "m6502_vtscr.h" + +DEFINE_DEVICE_TYPE(M6502_VTSCR, m6502_vtscr, "m6502_vtscr", "M6502 with VTxx scrambling") + +m6502_vtscr::m6502_vtscr(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + m6502_device(mconfig, M6502_VTSCR, tag, owner, clock) +{ +} + +void m6502_vtscr::device_start() +{ + mintf = std::make_unique(); + set_scramble(false); + init(); +} + +void m6502_vtscr::set_next_scramble(bool scr) +{ + downcast(*mintf).m_next_scramble = scr; +} + +void m6502_vtscr::set_scramble(bool scr) +{ + downcast(*mintf).m_next_scramble = scr; + downcast(*mintf).m_scramble_en = scr; +} + + +void m6502_vtscr::device_reset() +{ + set_scramble(false); + m6502_device::device_reset(); +} + +bool m6502_vtscr::mi_decrypt::toggle_scramble(uint8_t op) { + return (op == 0x4C) || (op == 0x00) || (op == 0x6C); +} + + +uint8_t m6502_vtscr::mi_decrypt::read_sync(uint16_t adr) +{ + uint8_t res = direct->read_byte(adr); + if(m_scramble_en) + { + res = descramble(res); + } + + if(toggle_scramble(res)) + { + m_scramble_en = m_next_scramble; + } + return res; +} + +uint8_t m6502_vtscr::mi_decrypt::descramble(uint8_t op) +{ + return op ^ 0xA1; +} + +util::disasm_interface *m6502_vtscr::create_disassembler() +{ + return new disassembler(downcast(mintf.get())); +} + +m6502_vtscr::disassembler::disassembler(mi_decrypt *mi) : mintf(mi) +{ +} + +u32 m6502_vtscr::disassembler::interface_flags() const +{ + return SPLIT_DECRYPTION; +} + +u8 m6502_vtscr::disassembler::decrypt8(u8 value, offs_t pc, bool opcode) const +{ + return opcode && mintf->m_scramble_en ? mintf->descramble(value) : value; +} diff --git a/src/mame/machine/m6502_vtscr.h b/src/mame/machine/m6502_vtscr.h new file mode 100644 index 00000000000..bb24cdb2719 --- /dev/null +++ b/src/mame/machine/m6502_vtscr.h @@ -0,0 +1,58 @@ +// license:BSD-3-Clause +// copyright-holders:David Shah +/*************************************************************************** + + m6502_vtscr.h + + 6502 with VRT VTxx instruction scrambling + +***************************************************************************/ + +#ifndef MAME_CPU_M6502_VTSCR_H +#define MAME_CPU_M6502_VTSCR_H + +#pragma once + +#include "cpu/m6502/m6502.h" +#include "cpu/m6502/m6502d.h" + +class m6502_vtscr : public m6502_device { +public: + m6502_vtscr(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + void set_next_scramble(bool scr); + void set_scramble(bool scr); + +protected: + class mi_decrypt : public mi_default_normal { + public: + + bool m_scramble_en = false; + bool m_next_scramble = false; + + virtual ~mi_decrypt() {} + virtual uint8_t read_sync(uint16_t adr) override; + + uint8_t descramble(uint8_t op); + bool toggle_scramble(uint8_t op); + + }; + + class disassembler : public m6502_disassembler { + public: + mi_decrypt *mintf; + + disassembler(mi_decrypt *m); + virtual ~disassembler() = default; + virtual u32 interface_flags() const override; + virtual u8 decrypt8(u8 value, offs_t pc, bool opcode) const override; + }; + + virtual void device_reset() override; + virtual void device_start() override; + virtual util::disasm_interface *create_disassembler() override; +}; + +DECLARE_DEVICE_TYPE(M6502_VTSCR, m6502_vtscr) + +#endif // MAME_CPU_M6502_VTSCR_H diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 1c63421d7bb..76f5ca6e9a3 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -29799,8 +29799,20 @@ gprnrs16 vgpocket vgpmini sy889 +sy888b dgun2573 bittboy +mc_89in1 +mc_cb280 +mc_pg150 +mc_hh210 +dvnimbus +cbrs8 +mc_tv200 +fcpocket +mog_m320 +fapocket +zdog @source:newbrain.cpp newbrain // -- cgit v1.2.3