summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video
diff options
context:
space:
mode:
author cam900 <dbtlrchl@naver.com>2020-10-25 22:49:49 +0900
committer GitHub <noreply@github.com>2020-10-26 00:49:49 +1100
commit62d9564619d6a91e4be07a3833e627ec652a9bd0 (patch)
tree9ce80ad40bf0d6d4760ade37dd61aae9558c7908 /src/devices/video
parent16f71a3a8ee0e5969c984be3164a6f5171d77abe (diff)
snes_ppu.cpp: Use device_palette_interface for Palette handling (#7375)
Use device_palette_interface for palette, fixed CGRAM size and direct color behavior
Diffstat (limited to 'src/devices/video')
-rw-r--r--src/devices/video/snes_ppu.cpp94
-rw-r--r--src/devices/video/snes_ppu.h11
2 files changed, 60 insertions, 45 deletions
diff --git a/src/devices/video/snes_ppu.cpp b/src/devices/video/snes_ppu.cpp
index e0b4eb544b1..1a8083195f3 100644
--- a/src/devices/video/snes_ppu.cpp
+++ b/src/devices/video/snes_ppu.cpp
@@ -83,9 +83,8 @@
#define SNES_CLIP_ALWAYS 3
#define SNES_VRAM_SIZE 0x10000 /* 64kb of video ram */
-#define SNES_CGRAM_SIZE 0x202 /* 256 16-bit colours + 1 tacked on 16-bit colour for fixed colour */
+#define SNES_CGRAM_SIZE 0x200 /* 256 16-bit colours */
#define SNES_OAM_SIZE 0x440 /* 1088 bytes of Object Attribute Memory */
-#define FIXED_COLOUR 256 /* Position in cgram for fixed colour */
/* Definitions for PPU Memory-Mapped registers */
@@ -193,6 +192,7 @@ DEFINE_DEVICE_TYPE(SNES_PPU, snes_ppu_device, "snes_ppu", "SNES PPU")
snes_ppu_device::snes_ppu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SNES_PPU, tag, owner, clock)
, device_video_interface(mconfig, *this)
+ , device_palette_interface(mconfig, *this)
, m_openbus_cb(*this)
, m_options(*this, ":OPTIONS")
, m_debug1(*this, ":DEBUG1")
@@ -227,11 +227,29 @@ void snes_ppu_device::device_start()
uint8_t ar = (uint8_t)(luma * r + 0.5);
uint8_t ag = (uint8_t)(luma * g + 0.5);
uint8_t ab = (uint8_t)(luma * b + 0.5);
- m_light_table[l][r << 10 | g << 5 | b << 0] = ar << 10 | ag << 5 | ab << 0;
+ m_light_table[l][r << 0 | g << 5 | b << 10] = ar << 0 | ag << 5 | ab << 10;
}
}
}
}
+ // initialize direct colours
+ for (int rgb = 0; rgb < 32*32*32; rgb++)
+ {
+ set_indirect_color(rgb, pal555(rgb, 0, 5, 10));
+ }
+ for (uint8_t group = 0; group < 8; group++)
+ {
+ for (int c = 0; c < 256; c++)
+ {
+ //palette = -------- BBGGGRRR
+ //group = -------- -----bgr
+ //output = 0BBb00GG Gg0RRRr0
+ const u16 direct = (c << 7 & 0x6000) + (group << 10 & 0x1000)
+ + (c << 4 & 0x0380) + (group << 5 & 0x0040)
+ + (c << 2 & 0x001c) + (group << 1 & 0x0002);
+ set_pen_indirect(DIRECT_COLOUR + c + (group * 256), direct);
+ }
+ }
for (int i = 0; i < ARRAY_LENGTH(m_scanlines); i++)
{
@@ -393,6 +411,10 @@ void snes_ppu_device::device_reset()
/* Init Palette RAM */
memset((uint8_t *)m_cgram.get(), 0, SNES_CGRAM_SIZE);
+ for (int i = 0; i < 256; i++)
+ set_pen_indirect(i, m_cgram[i]);
+
+ set_pen_indirect(FIXED_COLOUR, 0);
// other initializations to 0
memset(m_regs, 0, sizeof(m_regs));
@@ -729,11 +751,11 @@ void snes_ppu_device::update_line( uint16_t curline, uint8_t layer_idx, uint8_t
mosaic_priority = tile_priority;
if (direct_color_mode)
{
- mosaic_color = direct_color(palette_number, mosaic_palette);
+ mosaic_color = direct_color(mosaic_palette, palette_number);
}
else
{
- mosaic_color = m_cgram[(palette_index + mosaic_palette) % FIXED_COLOUR];
+ mosaic_color = pen_indirect((palette_index + mosaic_palette) & 0xff);
}
}
if (!mosaic_palette) continue;
@@ -827,11 +849,11 @@ void snes_ppu_device::update_line_mode7( uint16_t curline, uint8_t layer_idx )
mosaic_priority = priority;
if (m_direct_color && layer_idx == SNES_BG1)
{
- mosaic_color = direct_color(0, palette);
+ mosaic_color = direct_color(palette, 0);
}
else
{
- mosaic_color = m_cgram[palette];
+ mosaic_color = pen_indirect(palette);
}
}
if (!mosaic_palette) continue;
@@ -999,8 +1021,8 @@ void snes_ppu_device::update_objects( uint16_t curline )
{
if (!pribuf[x]) continue;
int blend = (palbuf[x] < 192) ? 1 : 0;
- if (m_layer[SNES_OAM].main_bg_enabled && window_above[x] == 0) plot_above(x, SNES_OAM, pribuf[x], m_cgram[palbuf[x]], blend);
- if (m_layer[SNES_OAM].sub_bg_enabled && window_below[x] == 0) plot_below(x, SNES_OAM, pribuf[x], m_cgram[palbuf[x]], blend);
+ if (m_layer[SNES_OAM].main_bg_enabled && window_above[x] == 0) plot_above(x, SNES_OAM, pribuf[x], pen_indirect(palbuf[x]), blend);
+ if (m_layer[SNES_OAM].sub_bg_enabled && window_below[x] == 0) plot_below(x, SNES_OAM, pribuf[x], pen_indirect(palbuf[x]), blend);
}
}
@@ -1287,8 +1309,8 @@ void snes_ppu_device::refresh_scanline( bitmap_rgb32 &bitmap, uint16_t curline )
#endif
const bool hires = m_mode == 5 || m_mode == 6 || m_pseudo_hires;
- uint16_t above_color = m_cgram[0];
- uint16_t below_color = hires ? m_cgram[0] : m_cgram[FIXED_COLOUR];
+ uint16_t above_color = pen_indirect(0);
+ uint16_t below_color = hires ? pen_indirect(0) : pen_indirect(FIXED_COLOUR);
for (int x = 0; x < SNES_SCR_WIDTH; x++)
{
above->buffer[x] = above_color;
@@ -1319,45 +1341,30 @@ void snes_ppu_device::refresh_scanline( bitmap_rgb32 &bitmap, uint16_t curline )
if (!hires)
{
const uint16_t c = luma[pixel(x, above, below, window_above, window_below)];
- const int r = (c & 0x1f);
- const int g = (c & 0x3e0) >> 5;
- const int b = (c & 0x7c00) >> 10;
- bitmap.pix(0, x * 2 + 0) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
- bitmap.pix(0, x * 2 + 1) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b));
+ bitmap.pix(0, x * 2 + 0) = indirect_color(c & 0x7fff);
+ bitmap.pix(0, x * 2 + 1) = indirect_color(c & 0x7fff);
}
else if (!blurring)
{
const uint16_t c0 = luma[pixel(x, below, above, window_above, window_below)];
const uint16_t c1 = luma[pixel(x, above, below, window_above, window_below)];
- const int r0 = (c0 & 0x1f);
- const int r1 = (c1 & 0x1f);
- const int g0 = (c0 & 0x3e0) >> 5;
- const int g1 = (c1 & 0x3e0) >> 5;
- const int b0 = (c0 & 0x7c00) >> 10;
- const int b1 = (c1 & 0x7c00) >> 10;
-
- bitmap.pix(0, x * 2 + 0) = rgb_t(pal5bit(r0), pal5bit(g0), pal5bit(b0));
- bitmap.pix(0, x * 2 + 1) = rgb_t(pal5bit(r1), pal5bit(g1), pal5bit(b1));
+
+ bitmap.pix(0, x * 2 + 0) = indirect_color(c0 & 0x7fff);
+ bitmap.pix(0, x * 2 + 1) = indirect_color(c1 & 0x7fff);
}
else
{
uint16_t curr = luma[pixel(x, below, above, window_above, window_below)];
uint16_t c0 = (prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
- const int r0 = (c0 & 0x1f);
- const int g0 = (c0 & 0x3e0) >> 5;
- const int b0 = (c0 & 0x7c00) >> 10;
- bitmap.pix(0, x * 2 + 0) = rgb_t(pal5bit(r0), pal5bit(g0), pal5bit(b0));
+ bitmap.pix(0, x * 2 + 0) = indirect_color(c0 & 0x7fff);
prev = curr;
curr = luma[pixel(x, above, below, window_above, window_below)];
uint16_t c1 = (prev + curr - ((prev ^ curr) & 0x0421)) >> 1;
- const int r1 = (c1 & 0x1f);
- const int g1 = (c1 & 0x3e0) >> 5;
- const int b1 = (c1 & 0x7c00) >> 10;
- bitmap.pix(0, x * 2 + 1) = rgb_t(pal5bit(r1), pal5bit(g1), pal5bit(b1));
+ bitmap.pix(0, x * 2 + 1) = indirect_color(c1 & 0x7fff);
prev = curr;
}
@@ -1372,7 +1379,7 @@ uint16_t snes_ppu_device::pixel(uint16_t x, SNES_SCANLINE *above, SNES_SCANLINE
if (!window_above[x]) above->buffer[x] = 0;
if (!window_below[x]) return above->buffer[x];
if (!m_layer[above->layer[x]].color_math || (above->layer[x] == SNES_OAM && above->blend_exception[x])) return above->buffer[x];
- if (!m_sub_add_mode) return blend(above->buffer[x], m_cgram[FIXED_COLOUR], BIT(m_color_modes, 0) != 0 && window_above[x] != 0);
+ if (!m_sub_add_mode) return blend(above->buffer[x], pen_indirect(FIXED_COLOUR), BIT(m_color_modes, 0) != 0 && window_above[x] != 0);
return blend(above->buffer[x], below->buffer[x], BIT(m_color_modes, 0) != 0 && window_above[x] != 0 && below->layer[x] != SNES_COLOR);
}
@@ -1723,6 +1730,7 @@ void snes_ppu_device::cgram_write(offs_t offset, uint8_t data)
data &= 0x7f;
((uint8_t *)m_cgram.get())[offset] = data;
+ set_pen_indirect(offset >> 1, m_cgram[offset >> 1] & 0x7fff);
}
uint16_t snes_ppu_device::direct_color(uint16_t palette, uint16_t group)
@@ -1730,9 +1738,7 @@ uint16_t snes_ppu_device::direct_color(uint16_t palette, uint16_t group)
//palette = -------- BBGGGRRR
//group = -------- -----bgr
//output = 0BBb00GG Gg0RRRr0
- return (palette << 7 & 0x6000) + (group << 10 & 0x1000)
- + (palette << 4 & 0x0380) + (group << 5 & 0x0040)
- + (palette << 2 & 0x001c) + (group << 1 & 0x0002);
+ return pen_indirect(DIRECT_COLOUR + palette + (group * 256));
}
void snes_ppu_device::set_current_vert(uint16_t value)
@@ -1984,7 +1990,7 @@ uint8_t snes_ppu_device::read(uint32_t offset, uint8_t wrio_bit7)
m_ppu2_open_bus |= cgram_read(m_cgram_address) & 0x7f;
}
- m_cgram_address = (m_cgram_address + 1) % (SNES_CGRAM_SIZE - 2);
+ m_cgram_address = (m_cgram_address + 1) & (SNES_CGRAM_SIZE - 1);
return m_ppu2_open_bus;
case OPHCT: /* Horizontal counter data by ext/soft latch */
if (m_read_ophct)
@@ -2244,7 +2250,7 @@ void snes_ppu_device::write(uint32_t offset, uint8_t data)
break;
case CGDATA: /* Data for colour RAM */
cgram_write(m_cgram_address, data);
- m_cgram_address = (m_cgram_address + 1) % (SNES_CGRAM_SIZE - 2);
+ m_cgram_address = (m_cgram_address + 1) & (SNES_CGRAM_SIZE - 1);
break;
case W12SEL: /* Window mask settings for BG1-2 */
if (data != PPU_REG(W12SEL))
@@ -2374,13 +2380,13 @@ void snes_ppu_device::write(uint32_t offset, uint8_t data)
break;
case COLDATA: /* Fixed colour data for fixed colour addition/subtraction */
{
- /* Store it in the extra space we made in the CGRAM. It doesn't really go there, but it's as good a place as any. */
+ /* Store it in the extra space we made in the palette entry. */
uint8_t r, g, b;
/* Get existing value. */
- r = m_cgram[FIXED_COLOUR] & 0x1f;
- g = (m_cgram[FIXED_COLOUR] & 0x3e0) >> 5;
- b = (m_cgram[FIXED_COLOUR] & 0x7c00) >> 10;
+ r = pen_indirect(FIXED_COLOUR) & 0x1f;
+ g = (pen_indirect(FIXED_COLOUR) & 0x3e0) >> 5;
+ b = (pen_indirect(FIXED_COLOUR) & 0x7c00) >> 10;
/* Set new value */
if (data & 0x20)
r = data & 0x1f;
@@ -2388,7 +2394,7 @@ void snes_ppu_device::write(uint32_t offset, uint8_t data)
g = data & 0x1f;
if (data & 0x80)
b = data & 0x1f;
- m_cgram[FIXED_COLOUR] = (r | (g << 5) | (b << 10));
+ set_pen_indirect(FIXED_COLOUR, r | (g << 5) | (b << 10));
} break;
case SETINI: /* Screen mode/video select */
m_interlace = (data & 0x01) ? 2 : 1;
diff --git a/src/devices/video/snes_ppu.h b/src/devices/video/snes_ppu.h
index 77c13b4dfca..f6ae1b09fa4 100644
--- a/src/devices/video/snes_ppu.h
+++ b/src/devices/video/snes_ppu.h
@@ -37,7 +37,8 @@
// ======================> snes_ppu_device
class snes_ppu_device : public device_t,
- public device_video_interface
+ public device_video_interface,
+ public device_palette_interface
{
public:
// construction/destruction
@@ -312,7 +313,15 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
+ // device_palette_interface overrides
+ // 256 word CG RAM data (0x000-0x0ff), 8 group of direct colours (0x100-0x8ff), Fixed color (0x900)
+ virtual uint32_t palette_entries() const override { return 0x100 + (0x100 * 8) + 1; }
+ virtual uint32_t palette_indirect_entries() const override { return 32 * 32 * 32; } // 15 bit BGR
+
private:
+ static constexpr uint16_t DIRECT_COLOUR = 0x100; // Position in palette entry for direct colour
+ static constexpr uint16_t FIXED_COLOUR = 0x100 + (0x100 * 8); // Position in palette entry for fixed colour
+
devcb_read16 m_openbus_cb;
optional_ioport m_options;
optional_ioport m_debug1;