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)
This commit is contained in:
David Shah 2018-02-07 19:09:56 +00:00 committed by Olivier Galibert
parent 86670b17ac
commit 304abd860c
9 changed files with 907 additions and 220 deletions

View File

@ -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")

View File

@ -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;
}
/*************************************
*

View File

@ -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

View File

@ -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];
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));
}
// 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;
}
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:

View File

@ -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 <class Object> static devcb_base &set_read_sp_callback(device_t &device, Object &&cb) { return downcast<ppu_vt03_device &>(device).m_read_sp.set_callback(std::forward<Object>(cb)); }
static void set_palette_mode(device_t &device, vtxx_pal_mode pmode) { downcast<ppu_vt03_device &>(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<ppu_vt03_device &>(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);

File diff suppressed because it is too large Load Diff

View File

@ -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<mi_decrypt>();
set_scramble(false);
init();
}
void m6502_vtscr::set_next_scramble(bool scr)
{
downcast<mi_decrypt &>(*mintf).m_next_scramble = scr;
}
void m6502_vtscr::set_scramble(bool scr)
{
downcast<mi_decrypt &>(*mintf).m_next_scramble = scr;
downcast<mi_decrypt &>(*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<mi_decrypt *>(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;
}

View File

@ -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

View File

@ -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 //