snes_ppu.cpp: Use device_palette_interface for Palette handling (#7375)

Use device_palette_interface for palette, fixed CGRAM size and direct color behavior
This commit is contained in:
cam900 2020-10-25 22:49:49 +09:00 committed by GitHub
parent 16f71a3a8e
commit 62d9564619
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 44 deletions

View File

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

View File

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