summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/ppu2c0x_vt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/ppu2c0x_vt.cpp')
-rw-r--r--src/devices/video/ppu2c0x_vt.cpp366
1 files changed, 227 insertions, 139 deletions
diff --git a/src/devices/video/ppu2c0x_vt.cpp b/src/devices/video/ppu2c0x_vt.cpp
index 04da1b8740b..2b8b9b6e3dd 100644
--- a/src/devices/video/ppu2c0x_vt.cpp
+++ b/src/devices/video/ppu2c0x_vt.cpp
@@ -47,14 +47,10 @@ ppu_vt03pal_device::ppu_vt03pal_device(const machine_config& mconfig, const char
uint8_t ppu_vt03_device::palette_read(offs_t offset)
{
- if (m_201x_regs[0] & 0x80)
- {
- return m_newpal[offset];
- }
- else
- {
+ if (offset < 0x20)
return ppu2c0x_device::palette_read(offset);
- }
+ else
+ return m_palette_ram[offset];
}
void ppu_vt03_device::set_201x_descramble(uint8_t reg0, uint8_t reg1, uint8_t reg2, uint8_t reg3, uint8_t reg4, uint8_t reg5)
@@ -67,110 +63,17 @@ void ppu_vt03_device::set_201x_descramble(uint8_t reg0, uint8_t reg1, uint8_t re
m_2012_2017_descramble[5] = reg5;
}
-void ppu_vt03_device::set_new_pen(int i)
-{
- if ((i < 0x20) && ((i & 0x3) == 0))
- {
- set_pen_color(i & 0x7f, rgb_t(0, 0, 0));
- }
- else
- {
- 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;
- 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;
- 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;
-
- set_pen_color(i & 0x7f, rgb_t(RV, GV, BV));
- }
- }
-}
-
void ppu_vt03_device::palette_write(offs_t offset, uint8_t data)
{
- //logerror("pal write %d %02x\n", offset, data);
- // why is the check pal_mask = (m_pal_mode == PAL_MODE_NEW_VG) ? 0x08 : 0x80 in set_2010_reg and 0x04 : 0x80 here?
- uint8_t pal_mask = (m_pal_mode == PAL_MODE_NEW_VG) ? 0x04 : 0x80;
-
- if (m_201x_regs[0] & pal_mask)
+ if (offset < 0x20)
{
- m_newpal[offset & 0xff] = data;
- set_new_pen(offset);
+ ppu2c0x_device::palette_write(offset, data);
}
else
{
- //if(m_pal_mode == PAL_MODE_NEW_VG) // ddrdismx writes the palette before setting the register but doesn't use 'PAL_MODE_NEW_VG', Konami logo is missing if you don't allow writes to be stored for when we switch
- m_newpal[offset & 0xff] = data;
- ppu2c0x_device::palette_write(offset, data);
+ m_palette_ram[offset] = data;
}
}
@@ -235,20 +138,131 @@ uint8_t ppu_vt03_device::read_extended(offs_t offset)
}
-void ppu_vt03_device::init_palette()
+
+void ppu_vt03_device::init_vtxx_rgb555_palette_tables()
{
- // todo, work out the format of the 12 palette bits instead of just calling the main init
- ppu2c0x_device::init_palette(true);
+ int entry = 0;
+ for (int emp = 0; emp < 8; emp++)
+ {
+ for (int palval = 0; palval < 0x8000; palval++)
+ {
+ // uint16_t rgbval = (m_palette_ram[i & 0x7f] & 0xff) | ((m_palette_ram[(i & 0x7f) + 0x80] & 0xff) << 8);
+ uint8_t blue = (palval & 0x001f) << 3;
+ uint8_t green = (palval & 0x3e0) >> 2;
+ uint8_t red = (palval & 0x7C00) >> 7;
+
+ // TODO: apply emphasis values if they work in this mode
+ m_vtpens_rgb555[entry] = rgb_t(red, green, blue);
+ entry++;
+ }
+ }
+}
+
+void ppu_vt03_device::init_vtxx_rgb444_palette_tables()
+{
+ int entry = 0;
+ for (int emp = 0; emp < 8; emp++)
+ {
+ for (int palval = 0; palval < 0x1000; palval++)
+ {
+ //uint16_t rgbval = (m_palette_ram[i & 0x7f] & 0x3f) | ((m_palette_ram[(i & 0x7f) + 0x80] & 0x3f) << 6);
+ uint8_t red = (palval & 0x000f) << 4;
+ uint8_t green = (palval & 0x0f0);
+ uint8_t blue = (palval & 0xf00) >> 4;
+
+ // TODO: apply emphasis values if they work in this mode
+ m_vtpens_rgb444[entry] = rgb_t(red, green, blue);
+ entry++;
+ }
+ }
+}
+// what cases are palmode 1 anyway?
+void ppu_vt03_device::init_vt03_palette_tables(int palmode)
+{
+ // the 12-bit VT HSV format, Credit to NewRisingSun
+ int entry = 0;
+ for (int color_emphasis = 0; color_emphasis < 8; color_emphasis++)
+ {
+ for (int palval = 0; palval < 0x1000; palval++)
+ {
+ 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)) && (palmode != 1))
+ {
+ //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 (palmode == 1)
+ {
+ 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;
+
+ // does this really apply to the VT palette?
+ //bool is_pal = m_scanlines_per_frame != NTSC_SCANLINES_PER_FRAME;
+ //apply_color_emphasis_and_clamp(is_pal, color_emphasis, R, G, B);
+
+ m_vtpens[entry] = rgb_t(RV, GV, BV);
+ entry++;
+ }
+ }
}
void ppu_vt03_device::device_start()
{
- ppu2c0x_device::device_start();
+ start_nopalram();
+
+ m_palette_ram.resize(0x100);
- m_newpal = std::make_unique<uint8_t[]>(0x100);
- save_pointer(NAME(m_newpal), 0x100);
+ for (int i = 0; i < 0x100; i++)
+ m_palette_ram[i] = 0x00;
+ save_item(NAME(m_palette_ram));
save_item(NAME(m_201x_regs));
+
+ init_vt03_palette_tables(0);
+ init_vtxx_rgb555_palette_tables();
+ init_vtxx_rgb444_palette_tables();
}
uint8_t ppu_vt03_device::get_201x_reg(int reg)
@@ -270,16 +284,12 @@ void ppu_vt03_device::device_reset()
m_read_bg.resolve_safe(0);
m_read_sp.resolve_safe(0);
for (int i = 0; i < 0xff; i++)
- m_newpal[i] = 0x0;
+ m_palette_ram[i] = 0x0;
// todo: what are the actual defaults for these?
for (int i = 0; i < 0x20; i++)
set_201x_reg(i, 0x00);
- //m_201x_regs[0] = 0x86; // alt fix for ddrdismx would be to set the default palette mode here
-
- init_palette();
-
m_read_bg4_bg3 = 0;
m_va34 = 0;
}
@@ -353,7 +363,8 @@ void ppu_vt03_device::draw_sprite_pixel(int sprite_xpos, int color, int pixel, u
{
if (!is16pix)
{
- bitmap.pix32(m_scanline, sprite_xpos + pixel) = pen(pixel_data + (4 * color));
+ uint8_t pen = pixel_data + (4 * color);
+ draw_tile_pixel_inner(pen, &bitmap.pix(m_scanline, sprite_xpos + pixel));
}
else
{
@@ -361,9 +372,16 @@ void ppu_vt03_device::draw_sprite_pixel(int sprite_xpos, int color, int pixel, u
we probably need to split them out again and draw them at xpos+8 with a
cliprect - not seen used yet */
if ((pixel_data & 0x03) != 0)
- bitmap.pix32(m_scanline, sprite_xpos + pixel) = pen((pixel_data & 0x03) + (4 * color));
+ {
+ uint8_t pen = (pixel_data & 0x03) + (4 * color);
+ draw_tile_pixel_inner(pen, &bitmap.pix(m_scanline, sprite_xpos + pixel));
+ }
+
if (((pixel_data >> 5) & 0x03) != 0)
- bitmap.pix32(m_scanline, sprite_xpos + pixel + 8) = pen(((pixel_data >> 5) & 0x03) + (4 * color));
+ {
+ uint8_t pen = ((pixel_data >> 5) & 0x03) + (4 * color);
+ draw_tile_pixel_inner(pen, &bitmap.pix(m_scanline, sprite_xpos + pixel + 8));
+ }
//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);
}
@@ -414,13 +432,100 @@ void ppu_vt03_device::shift_tile_plane_data(uint8_t& pix)
}
}
-void ppu_vt03_device::draw_tile_pixel(uint8_t pix, int color, pen_t back_pen, uint32_t*& dest, const pen_t* color_table)
+
+void ppu_vt03_device::draw_back_pen(uint32_t* dst, int back_pen)
+{
+ if (m_201x_regs[0] & 0x80)
+ {
+ // is the back_pen always just pen 0 in VT modes? (using last data written to a transparent pen as per NES logic doesn't work as writes are split across 2 bytes)
+ draw_tile_pixel_inner(0, dst);
+ }
+ else
+ {
+ // in normal modes we still have the data from the palette writes as the 'backpen' so treat it as before
+ uint32_t pix;
+ pix = m_nespens[back_pen & 0x1ff];
+ *dst = pix;
+ }
+}
+
+
+void ppu_vt03_device::draw_tile_pixel_inner(uint8_t pen, uint32_t *dest)
+{
+ if (m_201x_regs[0] & 0x80)
+ {
+ if (m_pal_mode == PAL_MODE_NEW_RGB) // unknown newer VT mode
+ {
+ uint32_t palval;
+ palval = (m_palette_ram[pen & 0x7f] & 0xff) | ((m_palette_ram[(pen & 0x7f) + 0x80] & 0x7f) << 8);
+
+ // does grayscale mode exist here? (we haven't calculated any colours for it)
+ //if (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO)
+ // palval &= 0x30;
+
+ // apply colour emphasis (does it really exist here?) (we haven't calculated any colours for it, so ths has no effect)
+ palval |= ((m_regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS) << 10);
+
+ uint32_t pix;
+ pix = m_vtpens_rgb555[palval & 0x3ffff];
+ *dest = pix;
+ }
+ else if (m_pal_mode == PAL_MODE_NEW_RGB12) // unknown newer VT mode
+ {
+ uint32_t palval;
+ palval = (m_palette_ram[pen & 0x7f] & 0x3f) | ((m_palette_ram[(pen & 0x7f) + 0x80] & 0x3f) << 6);
+
+ // does grayscale mode exist here? (we haven't calculated any colours for it)
+ //if (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO)
+ // palval &= 0x30;
+
+ // apply colour emphasis (does it really exist here?) (we haven't calculated any colours for it, so ths has no effect)
+ palval |= ((m_regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS) << 7);
+
+ uint32_t pix;
+ pix = m_vtpens_rgb444[palval & 0x7fff];
+ *dest = pix;
+ }
+ else // VT03 mode
+ {
+ uint32_t palval;
+ palval = (m_palette_ram[pen & 0x7f] & 0x3f) | ((m_palette_ram[(pen & 0x7f) + 0x80] & 0x3f) << 6);
+
+ // does grayscale mode exist here? (we haven't calculated any colours for it)
+ //if (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO)
+ // palval &= 0x30;
+
+ // apply colour emphasis (does it really exist here?) (we calculate values for it when building the palette lookup)
+ palval |= ((m_regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS) << 7);
+
+ uint32_t pix;
+ pix = m_vtpens[palval & 0x7fff];
+ *dest = pix;
+ }
+ }
+ else // old colour compatible mode
+ {
+ uint16_t palval;
+ palval = (m_palette_ram[pen & 0x7f] & 0x3f);
+
+ if (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO)
+ palval &= 0x30;
+
+ // apply colour emphasis
+ palval |= ((m_regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS) << 1);
+
+ uint32_t pix;
+ pix = m_nespens[palval & 0x1ff];
+ *dest = pix;
+ }
+}
+void ppu_vt03_device::draw_tile_pixel(uint8_t pix, int color, uint32_t back_pen, uint32_t*& dest)
{
int is4bpp = get_201x_reg(0x0) & 0x02;
if (!is4bpp)
{
- ppu2c0x_device::draw_tile_pixel(pix, color, back_pen, dest, color_table);
+ ppu2c0x_device::draw_tile_pixel(pix, color, back_pen, dest);
}
else
{
@@ -442,9 +547,10 @@ void ppu_vt03_device::draw_tile_pixel(uint8_t pix, int color, pen_t back_pen, ui
}
else
{
- pen = 0; // fixme backpen logic probably differs on vt03 due to extra colours
+ pen = 0; // back_pen; // fixme backpen logic probably differs on vt03 due to extra colours
}
- *dest = this->pen(pen);
+
+ draw_tile_pixel_inner(pen, dest);
}
}
@@ -468,24 +574,6 @@ void ppu_vt03_device::set_2010_reg(uint8_t data)
2 : SP16EN
1 : BK16EN
0 : PIX16EN */
- uint8_t pal_mask = (m_pal_mode == PAL_MODE_NEW_VG) ? 0x08 : 0x80;
- if ((m_201x_regs[0x0] & pal_mask) != (data & pal_mask))
- {
- if (data & pal_mask)
- {
- for (int i = 0; i < 256; i++)
- {
- set_new_pen(i);
- }
- }
- else
- {
- for (int i = 0; i < 256; i++)
- {
- set_pen_indirect(i, i);
- }
- }
- }
m_201x_regs[0x0] = data;
}