summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/ppu2c0x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/ppu2c0x.cpp')
-rw-r--r--src/devices/video/ppu2c0x.cpp293
1 files changed, 120 insertions, 173 deletions
diff --git a/src/devices/video/ppu2c0x.cpp b/src/devices/video/ppu2c0x.cpp
index bad650cf0a6..c92af287081 100644
--- a/src/devices/video/ppu2c0x.cpp
+++ b/src/devices/video/ppu2c0x.cpp
@@ -30,37 +30,6 @@
#include "screen.h"
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-/* default monochromatic colortable */
-static const pen_t default_colortable_mono[] =
-{
- 0,1,2,3,
- 0,1,2,3,
- 0,1,2,3,
- 0,1,2,3,
- 0,1,2,3,
- 0,1,2,3,
- 0,1,2,3,
- 0,1,2,3,
-};
-
-/* default colortable */
-static const pen_t default_colortable[] =
-{
- 0,1,2,3,
- 0,5,6,7,
- 0,9,10,11,
- 0,13,14,15,
- 0,17,18,19,
- 0,21,22,23,
- 0,25,26,27,
- 0,29,30,31,
-};
-
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@@ -119,7 +88,6 @@ ppu2c0x_device::ppu2c0x_device(const machine_config& mconfig, device_type type,
device_t(mconfig, type, tag, owner, clock),
device_memory_interface(mconfig, *this),
device_video_interface(mconfig, *this),
- device_palette_interface(mconfig, *this),
m_space_config("videoram", ENDIANNESS_LITTLE, 8, 17, 0, internal_map),
m_cpu(*this, finder_base::DUMMY_TAG),
m_scanline(0), // reset the scanline count
@@ -234,7 +202,7 @@ ppu2c05_04_device::ppu2c05_04_device(const machine_config& mconfig, const char*
// device_start - device-specific startup
//-------------------------------------------------
-void ppu2c0x_device::device_start()
+void ppu2c0x_device::start_nopalram()
{
// bind our handler
m_int_callback.resolve_safe();
@@ -252,25 +220,8 @@ void ppu2c0x_device::device_start()
/* allocate a screen bitmap, videomem and spriteram, a dirtychar array and the monochromatic colortable */
m_bitmap = std::make_unique<bitmap_rgb32>(VISIBLE_SCREEN_WIDTH, VISIBLE_SCREEN_HEIGHT);
m_spriteram = make_unique_clear<uint8_t[]>(SPRITERAM_SIZE);
- m_colortable = std::make_unique<pen_t[]>(ARRAY_LENGTH(default_colortable));
- m_colortable_mono = std::make_unique<pen_t[]>(ARRAY_LENGTH(default_colortable_mono));
-
- m_palette_ram.resize(0x20);
- for (int i = 0; i < 0x20; i++)
- m_palette_ram[i] = 0x00;
-
- /* initialize the color tables */
- for (int i = 0; i < ARRAY_LENGTH(default_colortable_mono); i++)
- {
- /* monochromatic table */
- m_colortable_mono[i] = default_colortable_mono[i];
-
- /* color table */
- m_colortable[i] = default_colortable[i];
- }
-
- init_palette();
+ init_palette_tables();
// register for state saving
save_item(NAME(m_scanline));
@@ -289,15 +240,25 @@ void ppu2c0x_device::device_start()
save_item(NAME(m_scanlines_per_frame));
save_item(NAME(m_vblank_first_scanline));
save_item(NAME(m_regs));
- save_item(NAME(m_palette_ram));
save_item(NAME(m_draw_phase));
save_item(NAME(m_tilecount));
save_pointer(NAME(m_spriteram), SPRITERAM_SIZE);
- save_pointer(NAME(m_colortable), ARRAY_LENGTH(default_colortable));
- save_pointer(NAME(m_colortable_mono), ARRAY_LENGTH(default_colortable_mono));
+
save_item(NAME(*m_bitmap));
}
+void ppu2c0x_device::device_start()
+{
+ start_nopalram();
+
+ m_palette_ram.resize(0x20);
+
+ for (int i = 0; i < 0x20; i++)
+ m_palette_ram[i] = 0x00;
+
+ save_item(NAME(m_palette_ram));
+}
+
//**************************************************************************
// INLINE HELPERS
//**************************************************************************
@@ -332,12 +293,49 @@ inline void ppu2c0x_device::writebyte(offs_t address, uint8_t data)
*
*************************************/
-void ppu2c0x_device::init_palette()
+void ppu2c0x_device::apply_color_emphasis_and_clamp(bool is_pal_or_dendy, int color_emphasis, double& R, double& G, double& B)
{
- init_palette(false);
+ if (is_pal_or_dendy) // PAL machines swap the colour emphasis bits, this means the red/blue highlighting on rampart tally bar doesn't look as good
+ {
+ color_emphasis = bitswap<3>(color_emphasis, 2, 0, 1);
+ }
+
+ double r_mod = 0.0;
+ double g_mod = 0.0;
+ double b_mod = 0.0;
+
+ switch (color_emphasis)
+ {
+ case 0: r_mod = 1.0; g_mod = 1.0; b_mod = 1.0; break;
+ case 1: r_mod = 1.24; g_mod = .915; b_mod = .743; break;
+ case 2: r_mod = .794; g_mod = 1.09; b_mod = .882; break;
+ case 3: r_mod = .905; g_mod = 1.03; b_mod = 1.28; break;
+ case 4: r_mod = .741; g_mod = .987; b_mod = 1.0; break;
+ case 5: r_mod = 1.02; g_mod = .908; b_mod = .979; break;
+ case 6: r_mod = 1.02; g_mod = .98; b_mod = .653; break;
+ case 7: r_mod = .75; g_mod = .75; b_mod = .75; break;
+ }
+
+ R = R * r_mod;
+ G = G * g_mod;
+ B = B * b_mod;
+
+ /* 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;
}
-rgb_t ppu2c0x_device::nespal_to_RGB(int color_intensity, int color_num)
+rgb_t ppu2c0x_device::nespal_to_RGB(int color_intensity, int color_num, int color_emphasis, bool is_pal_or_dendy)
{
const double tint = 0.22; /* adjust to taste */
const double hue = 287.0;
@@ -390,25 +388,15 @@ rgb_t ppu2c0x_device::nespal_to_RGB(int color_intensity, int color_num)
double G = (y - (Kb * Ku * u + Kr * Kv * v) / (1 - Kb - Kr)) * 255.0;
double 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;
+ apply_color_emphasis_and_clamp(is_pal_or_dendy, color_emphasis, R, G, B);
return rgb_t(floor(R + .5), floor(G + .5), floor(B + .5));
}
-void ppu2c0x_device::init_palette(bool indirect)
+void ppu2c0x_device::init_palette_tables()
{
+ bool is_pal = m_scanlines_per_frame != NTSC_SCANLINES_PER_FRAME;
+
/* This routine builds a palette using a transformation from */
/* the YUV (Y, B-Y, R-Y) to the RGB color space */
@@ -421,45 +409,23 @@ void ppu2c0x_device::init_palette(bool indirect)
/* Loop through the emphasis modes (8 total) */
for (int color_emphasis = 0; color_emphasis < 8; color_emphasis++)
{
- /*
- double r_mod = 0.0;
- double g_mod = 0.0;
- double b_mod = 0.0;
-
- switch (color_emphasis)
- {
- case 0: r_mod = 1.0; g_mod = 1.0; b_mod = 1.0; break;
- case 1: r_mod = 1.24; g_mod = .915; b_mod = .743; break;
- case 2: r_mod = .794; g_mod = 1.09; b_mod = .882; break;
- case 3: r_mod = .905; g_mod = 1.03; b_mod = 1.28; break;
- case 4: r_mod = .741; g_mod = .987; b_mod = 1.0; break;
- case 5: r_mod = 1.02; g_mod = .908; b_mod = .979; break;
- case 6: r_mod = 1.02; g_mod = .98; b_mod = .653; break;
- case 7: r_mod = .75; g_mod = .75; b_mod = .75; break;
- }
- */
-
/* loop through the 4 intensities */
for (int color_intensity = 0; color_intensity < 4; color_intensity++)
{
/* loop through the 16 colors */
for (int color_num = 0; color_num < 16; color_num++)
{
- rgb_t col = nespal_to_RGB(color_intensity, color_num);
+ rgb_t col = nespal_to_RGB(color_intensity, color_num, color_emphasis, is_pal);
- /* Round, and set the value */
- if (indirect)
- set_indirect_color(entry++, col);
- else
- set_pen_color(entry++, col);
+ m_nespens[entry] = (uint32_t)col;
+ entry++;
+
}
}
}
-
- /* color tables are modified at run-time, and are initialized on 'ppu2c0x_reset' */
}
-void ppu2c0x_rgb_device::init_palette()
+void ppu2c0x_rgb_device::init_palette_tables()
{
/* Loop through the emphasis modes (8 total) */
int entry = 0;
@@ -471,27 +437,14 @@ void ppu2c0x_rgb_device::init_palette()
int G = ((color_emphasis & 2) ? 7 : m_palette_data[color_num * 3 + 1]);
int B = ((color_emphasis & 4) ? 7 : m_palette_data[color_num * 3 + 2]);
- set_pen_color(entry++, pal3bit(R), pal3bit(G), pal3bit(B));
+ m_nespens[entry] = (pal3bit(R)<<16) | (pal3bit(G)<<8) | pal3bit(B);
+
+ //set_pen_color(entry++, pal3bit(R), pal3bit(G), pal3bit(B));
+ entry++;
}
}
-
- /* color tables are modified at run-time, and are initialized on 'ppu2c0x_reset' */
}
-#if 0
-/* the charlayout we use for the chargen */
-static const gfx_layout ppu_charlayout =
-{
- 8, 8, /* 8*8 characters */
- 0,
- 2, /* 2 bits per pixel */
- { 8*8, 0 }, /* the two bitplanes are separated */
- { 0, 1, 2, 3, 4, 5, 6, 7 },
- { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
- 16*8 /* every char takes 16 consecutive bytes */
-};
-#endif
-
/*************************************
*
* PPU Initialization and Disposal
@@ -609,24 +562,34 @@ void ppu2c0x_device::shift_tile_plane_data(uint8_t& pix)
m_planebuf[1] = m_planebuf[1] << 1;
}
-void ppu2c0x_device::draw_tile_pixel(uint8_t pix, int color, pen_t back_pen, uint32_t*& dest, const pen_t* color_table)
+void ppu2c0x_device::draw_tile_pixel(uint8_t pix, int color, uint32_t back_pen, uint32_t*& dest)
{
- pen_t pen;
+ uint32_t usepen;
if (pix)
{
- const pen_t* paldata = &color_table[4 * color];
- pen = this->pen(paldata[pix]);
+ uint8_t pen = ((4 * color) + pix) & 0x1f;
+ uint16_t palval = m_palette_ram[pen];
+
+ if (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO)
+ palval &= 0x30;
+
+ // apply colour emphasis
+ palval |= ((m_regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS) << 1);
+
+ usepen = m_nespens[palval];
}
else
{
- pen = back_pen;
+ usepen = m_nespens[back_pen];
}
- *dest = pen;
+
+
+ *dest = usepen;
}
-void ppu2c0x_device::draw_tile(uint8_t* line_priority, int color_byte, int color_bits, int address, int start_x, pen_t back_pen, uint32_t*& dest, const pen_t* color_table)
+void ppu2c0x_device::draw_tile(uint8_t* line_priority, int color_byte, int color_bits, int address, int start_x, uint32_t back_pen, uint32_t*& dest)
{
int color = (((color_byte >> color_bits) & 0x03));
@@ -640,7 +603,7 @@ void ppu2c0x_device::draw_tile(uint8_t* line_priority, int color_byte, int color
if ((start_x + i) >= 0 && (start_x + i) < VISIBLE_SCREEN_WIDTH)
{
- draw_tile_pixel(pix, color, back_pen, dest, color_table);
+ draw_tile_pixel(pix, color, back_pen, dest);
// priority marking
if (pix)
@@ -659,23 +622,10 @@ void ppu2c0x_device::draw_background(uint8_t* line_priority)
{
bitmap_rgb32& bitmap = *m_bitmap;
- uint8_t color_mask;
- const pen_t* color_table;
-
- /* setup the color mask and colortable to use */
- if (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO)
- {
- color_mask = 0xf0;
- color_table = m_colortable_mono.get();
- }
- else
- {
- color_mask = 0xff;
- color_table = m_colortable.get();
- }
+ uint16_t palval = m_back_color;
/* cache the background pen */
- pen_t back_pen = pen(m_back_color & color_mask);
+ uint32_t back_pen = palval;
/* determine where in the nametable to start drawing from */
/* based on the current scanline and scroll regs */
@@ -730,7 +680,7 @@ void ppu2c0x_device::draw_background(uint8_t* line_priority)
// plus something that accounts for y
address += scroll_y_fine;
- draw_tile(line_priority, color_byte, color_bits, address, start_x, back_pen, dest, color_table);
+ draw_tile(line_priority, color_byte, color_bits, address, start_x, back_pen, dest);
start_x += 8;
@@ -751,25 +701,33 @@ void ppu2c0x_device::draw_background(uint8_t* line_priority)
dest = &bitmap.pix32(m_scanline);
for (int i = 0; i < 8; i++)
{
- *(dest++) = back_pen;
+ draw_back_pen(dest, back_pen);
+ dest++;
+
line_priority[i] ^= 0x02;
}
}
}
+void ppu2c0x_device::draw_back_pen(uint32_t* dst, int back_pen)
+{
+ *dst = m_nespens[back_pen];
+}
+
void ppu2c0x_device::draw_background_pen()
{
bitmap_rgb32& bitmap = *m_bitmap;
/* setup the color mask and colortable to use */
- uint8_t color_mask = (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO) ? 0xf0 : 0xff;
+ uint8_t color_mask = (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO) ? 0x30 : 0x3f;
+ uint16_t palval = m_back_color & color_mask;
/* cache the background pen */
- pen_t back_pen = pen(m_back_color & color_mask);
+ uint32_t back_pen = palval;
// Fill this scanline with the background pen.
for (int i = 0; i < bitmap.width(); i++)
- bitmap.pix32(m_scanline, i) = back_pen;
+ draw_back_pen(&bitmap.pix32(m_scanline, i), back_pen);
}
void ppu2c0x_device::read_sprite_plane_data(int address)
@@ -796,8 +754,16 @@ void ppu2c0x_device::make_sprite_pixel_data(uint8_t& pixel_data, int flipx)
void ppu2c0x_device::draw_sprite_pixel(int sprite_xpos, int color, int pixel, uint8_t pixel_data, bitmap_rgb32& bitmap)
{
- const pen_t* paldata = &m_colortable[4 * color];
- bitmap.pix32(m_scanline, sprite_xpos + pixel) = pen(paldata[pixel_data]);
+ uint16_t palval = m_palette_ram[((4 * color) | pixel_data) & 0x1f];
+
+ 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 = m_nespens[palval];
+ bitmap.pix32(m_scanline, sprite_xpos + pixel) = pix;
}
void ppu2c0x_device::read_extra_sprite_bits(int sprite_index)
@@ -1074,12 +1040,14 @@ void ppu2c0x_device::update_visible_enabled_scanline()
void ppu2c0x_device::update_visible_disabled_scanline()
{
bitmap_rgb32& bitmap = *m_bitmap;
- pen_t back_pen;
+ uint32_t back_pen;
/* setup the color mask and colortable to use */
- uint8_t color_mask = (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO) ? 0xf0 : 0xff;
+ uint8_t color_mask = (m_regs[PPU_CONTROL1] & PPU_CONTROL1_DISPLAY_MONO) ? 0x30 : 0x3f;
+
+ uint16_t palval = m_back_color & color_mask;
- back_pen = pen(m_back_color & color_mask);
+ back_pen = palval;
if (m_paletteram_in_ppuspace)
{
@@ -1092,13 +1060,13 @@ void ppu2c0x_device::update_visible_disabled_scanline()
// pen. Micro Machines makes use of this feature.
int pen_num = m_palette_ram[(m_videomem_addr & 0x03) ? (m_videomem_addr & 0x1f) : 0];
- back_pen = pen(pen_num);
+ back_pen = pen_num;
}
}
// Fill this scanline with the background pen.
for (int i = 0; i < bitmap.width(); i++)
- bitmap.pix32(m_scanline, i) = back_pen;
+ draw_back_pen(&bitmap.pix32(m_scanline, i), back_pen);
}
void ppu2c0x_device::update_visible_scanline()
@@ -1135,29 +1103,20 @@ void ppu2c0x_device::update_scanline()
void ppu2c0x_device::palette_write(offs_t offset, uint8_t data)
{
- int color_emphasis = (m_regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS) * 2;
-
// palette RAM is only 6 bits wide
data &= 0x3f;
- // transparent pens are mirrored!
if (offset & 0x3)
{
+ // regular pens, no mirroring
m_palette_ram[offset & 0x1f] = data;
- m_colortable[offset & 0x1f] = data + color_emphasis;
- m_colortable_mono[offset & 0x1f] = (data & 0xf0) + color_emphasis;
}
else
{
- int i;
+ // transparent pens are mirrored!
if (0 == (offset & 0xf))
{
m_back_color = data;
- for (i = 0; i < 32; i += 4)
- {
- m_colortable[i] = data + color_emphasis;
- m_colortable_mono[i] = (data & 0xf0) + color_emphasis;
- }
}
m_palette_ram[offset & 0xf] = m_palette_ram[(offset & 0xf) + 0x10] = data;
}
@@ -1279,18 +1238,6 @@ void ppu2c0x_device::write(offs_t offset, uint8_t data)
break;
case PPU_CONTROL1: /* 1 */
- /* if color intensity has changed, change all the color tables to reflect them */
- if ((data & PPU_CONTROL1_COLOR_EMPHASIS) != (m_regs[PPU_CONTROL1] & PPU_CONTROL1_COLOR_EMPHASIS))
- {
- int i;
- for (i = 0; i <= 0x1f; i++)
- {
- uint8_t oldColor = m_palette_ram[i];
-
- m_colortable[i] = oldColor + (data & PPU_CONTROL1_COLOR_EMPHASIS) * 2;
- }
- }
-
//logerror("control1 write: %02x (scanline: %d)\n", data, m_scanline);
m_regs[PPU_CONTROL1] = data;
break;