From e06f85a328b7542a4b7d73fb512b68cb6402c848 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 22 Nov 2020 13:22:20 +1000 Subject: [PATCH] GPU: Fix VRAM palette changes not being detected in hw renderer Fixes wall texture animation in Mega Man Legends. --- src/core/gpu.h | 30 +++++++++++++++++++----------- src/core/gpu_hw.cpp | 9 ++++----- src/core/gpu_types.h | 38 +++++++++++++++----------------------- 3 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/core/gpu.h b/src/core/gpu.h index 459b2fbff..8921a42f8 100644 --- a/src/core/gpu.h +++ b/src/core/gpu.h @@ -358,30 +358,30 @@ protected: BitField dma_direction; BitField display_line_lsb; - bool IsMaskingEnabled() const + ALWAYS_INLINE bool IsMaskingEnabled() const { static constexpr u32 MASK = ((1 << 11) | (1 << 12)); return ((bits & MASK) != 0); } - bool SkipDrawingToActiveField() const + ALWAYS_INLINE bool SkipDrawingToActiveField() const { static constexpr u32 MASK = (1 << 19) | (1 << 22) | (1 << 10); static constexpr u32 ACTIVE = (1 << 19) | (1 << 22); return ((bits & MASK) == ACTIVE); } - bool InInterleaved480iMode() const + ALWAYS_INLINE bool InInterleaved480iMode() const { static constexpr u32 ACTIVE = (1 << 19) | (1 << 22); return ((bits & ACTIVE) == ACTIVE); } // During transfer/render operations, if ((dst_pixel & mask_and) == 0) { pixel = src_pixel | mask_or } - u16 GetMaskAND() const + ALWAYS_INLINE u16 GetMaskAND() const { // return check_mask_before_draw ? 0x8000 : 0x0000; return Truncate16((bits << 3) & 0x8000); } - u16 GetMaskOR() const + ALWAYS_INLINE u16 GetMaskOR() const { // return set_mask_while_drawing ? 0x8000 : 0x0000; return Truncate16((bits << 4) & 0x8000); @@ -409,13 +409,21 @@ protected: bool texture_page_changed; bool texture_window_changed; - bool IsTexturePageChanged() const { return texture_page_changed; } - void SetTexturePageChanged() { texture_page_changed = true; } - void ClearTexturePageChangedFlag() { texture_page_changed = false; } + /// Returns a rectangle comprising the texture palette area. + ALWAYS_INLINE_RELEASE Common::Rectangle GetTexturePaletteRectangle() const + { + static constexpr std::array palette_widths = {{16, 256, 0, 0}}; + return Common::Rectangle::FromExtents(texture_palette_x, texture_palette_y, + palette_widths[static_cast(mode_reg.texture_mode.GetValue())], 1); + } - bool IsTextureWindowChanged() const { return texture_window_changed; } - void SetTextureWindowChanged() { texture_window_changed = true; } - void ClearTextureWindowChangedFlag() { texture_window_changed = false; } + ALWAYS_INLINE bool IsTexturePageChanged() const { return texture_page_changed; } + ALWAYS_INLINE void SetTexturePageChanged() { texture_page_changed = true; } + ALWAYS_INLINE void ClearTexturePageChangedFlag() { texture_page_changed = false; } + + ALWAYS_INLINE bool IsTextureWindowChanged() const { return texture_window_changed; } + ALWAYS_INLINE void SetTextureWindowChanged() { texture_window_changed = true; } + ALWAYS_INLINE void ClearTextureWindowChangedFlag() { texture_window_changed = false; } } m_draw_mode = {}; Common::Rectangle m_drawing_area{0, 0, VRAM_WIDTH, VRAM_HEIGHT}; diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 63b007cf6..b14c09427 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -829,7 +829,7 @@ void GPU_HW::IncludeVRAMDityRectangle(const Common::Rectangle& rect) // shadow texture is updated if (!m_draw_mode.IsTexturePageChanged() && (m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(rect) || - (m_draw_mode.mode_reg.IsUsingPalette() && m_draw_mode.mode_reg.GetTexturePaletteRectangle().Intersects(rect)))) + (m_draw_mode.mode_reg.IsUsingPalette() && m_draw_mode.GetTexturePaletteRectangle().Intersects(rect)))) { m_draw_mode.SetTexturePageChanged(); } @@ -932,10 +932,9 @@ void GPU_HW::DispatchRenderCommand() if (m_draw_mode.IsTexturePageChanged()) { m_draw_mode.ClearTexturePageChangedFlag(); - if (m_vram_dirty_rect.Valid() && - (m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) || - (m_draw_mode.mode_reg.IsUsingPalette() && - m_draw_mode.mode_reg.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect)))) + if (m_vram_dirty_rect.Valid() && (m_draw_mode.mode_reg.GetTexturePageRectangle().Intersects(m_vram_dirty_rect) || + (m_draw_mode.mode_reg.IsUsingPalette() && + m_draw_mode.GetTexturePaletteRectangle().Intersects(m_vram_dirty_rect)))) { // Log_DevPrintf("Invalidating VRAM read cache due to drawing area overlap"); if (!IsFlushed()) diff --git a/src/core/gpu_types.h b/src/core/gpu_types.h index 4fd0472e7..4f713b1c9 100644 --- a/src/core/gpu_types.h +++ b/src/core/gpu_types.h @@ -93,15 +93,15 @@ union GPURenderCommand { switch (primitive) { - case GPUPrimitive::Polygon: - return shading_enable || (texture_enable && !raw_texture_enable); + case GPUPrimitive::Polygon: + return shading_enable || (texture_enable && !raw_texture_enable); - case GPUPrimitive::Line: - return true; + case GPUPrimitive::Line: + return true; - case GPUPrimitive::Rectangle: - default: - return false; + case GPUPrimitive::Rectangle: + default: + return false; } } }; @@ -175,24 +175,16 @@ union GPUDrawModeReg ALWAYS_INLINE u16 GetTexturePageBaseY() const { return ZeroExtend16(texture_page_y_base.GetValue()) * 256; } /// Returns true if the texture mode requires a palette. - bool IsUsingPalette() const { return (bits & (2 << 7)) == 0; } + ALWAYS_INLINE bool IsUsingPalette() const { return (bits & (2 << 7)) == 0; } /// Returns a rectangle comprising the texture page area. - Common::Rectangle GetTexturePageRectangle() const + ALWAYS_INLINE_RELEASE Common::Rectangle GetTexturePageRectangle() const { static constexpr std::array texture_page_widths = { - {TEXTURE_PAGE_WIDTH / 4, TEXTURE_PAGE_WIDTH / 2, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_WIDTH} }; + {TEXTURE_PAGE_WIDTH / 4, TEXTURE_PAGE_WIDTH / 2, TEXTURE_PAGE_WIDTH, TEXTURE_PAGE_WIDTH}}; return Common::Rectangle::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(), - texture_page_widths[static_cast(texture_mode.GetValue())], - TEXTURE_PAGE_HEIGHT); - } - - /// Returns a rectangle comprising the texture palette area. - Common::Rectangle GetTexturePaletteRectangle() const - { - static constexpr std::array palette_widths = { {16, 256, 0, 0} }; - return Common::Rectangle::FromExtents(GetTexturePageBaseX(), GetTexturePageBaseY(), - palette_widths[static_cast(texture_mode.GetValue())], 1); + texture_page_widths[static_cast(texture_mode.GetValue())], + TEXTURE_PAGE_HEIGHT); } }; @@ -218,14 +210,14 @@ struct GPUTextureWindow }; // 4x4 dither matrix. -static constexpr s32 DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = { {-4, +0, -3, +1}, // row 0 +static constexpr s32 DITHER_MATRIX[DITHER_MATRIX_SIZE][DITHER_MATRIX_SIZE] = {{-4, +0, -3, +1}, // row 0 {+2, -2, +3, -1}, // row 1 {-3, +1, -4, +0}, // row 2 - {+4, -1, +2, -2} }; // row 3 + {+4, -1, +2, -2}}; // row 3 #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4200) // warning C4200: nonstandard extension used: zero-sized array in struct/union +#pragma warning(disable : 4200) // warning C4200: nonstandard extension used: zero-sized array in struct/union #endif enum class GPUBackendCommandType : u8