diff options
Diffstat (limited to 'src/devices/video/ppu2c0x_vt.cpp')
-rw-r--r-- | src/devices/video/ppu2c0x_vt.cpp | 366 |
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; } |