From 2e1e11f116cb2f87a9bc72c93d83badaf5d9a25d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 26 Nov 2022 12:03:21 -0800 Subject: [PATCH] PPGe: Respect 512 texture limit. If a message ends up rendering wider than 512 (which can happen because we use higher quality fonts than 1x), draw in tiles to avoid accessing texels outside 512. Fixes an issue in Sakura Taisen in the software renderer. --- Core/Util/PPGeDraw.cpp | 63 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index d7559c0fa1..9d0c6f832c 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -913,12 +913,20 @@ static void PPGeDrawTextImage(PPGeTextDrawerImage im, float x, float y, const PP return; } + // Sometimes our texture can be larger than 512 wide, which means we need to tile it. int bufw = ((im.entry.bmWidth + 31) / 32) * 32; - int wp2 = GetPow2(im.entry.bmWidth); + int tile1bmWidth = std::min(512, im.entry.bmWidth); + int tile2bmWidth = tile1bmWidth == 512 ? im.entry.bmWidth - 512 : 0; + bool hasTile2 = tile2bmWidth != 0; + + // Now figure the tile shift value. + int tile1wp2 = GetPow2(tile1bmWidth); + int tile2wp2 = hasTile2 ? GetPow2(tile2bmWidth) : 0; int hp2 = GetPow2(im.entry.bmHeight); + WriteCmd(GE_CMD_TEXADDR0, im.ptr & 0xFFFFF0); WriteCmd(GE_CMD_TEXBUFWIDTH0, bufw | ((im.ptr & 0xFF000000) >> 8)); - WriteCmd(GE_CMD_TEXSIZE0, wp2 | (hp2 << 8)); + WriteCmd(GE_CMD_TEXSIZE0, tile1wp2 | (hp2 << 8)); WriteCmd(GE_CMD_TEXFLUSH, 0); float w = im.entry.width * style.scale; @@ -934,21 +942,62 @@ static void PPGeDrawTextImage(PPGeTextDrawerImage im, float x, float y, const PP y -= h; BeginVertexData(); - float u1 = (float)im.entry.width / (1 << wp2); + float tile2x = 512 * style.scale; + float tile1w = hasTile2 ? 512.0f * style.scale : w; + float tile2w = hasTile2 ? w - tile1w : 0.0f; + float tile1u1 = hasTile2 ? 1.0f : (float)im.entry.width / (1 << tile1wp2); + float tile2u1 = hasTile2 ? (float)(im.entry.width - 512) / (1 << tile2wp2) : 0.0f; float v1 = (float)im.entry.height / (1 << hp2); if (style.hasShadow) { // Draw more shadows for a blurrier shadow. + u32 shadowColor = alphaMul(style.shadowColor, 0.35f); for (float dy = 0.0f; dy <= 2.0f; dy += 1.0f) { for (float dx = 0.0f; dx <= 1.0f; dx += 0.5f) { if (dx == 0.0f && dy == 0.0f) continue; - Vertex(x + dx, y + dy, 0, 0, 1 << wp2, 1 << hp2, alphaMul(style.shadowColor, 0.35f)); - Vertex(x + dx + w, y + dy + h, u1, v1, 1 << wp2, 1 << hp2, alphaMul(style.shadowColor, 0.35f)); + + Vertex(x + dx, y + dy, 0, 0, 1 << tile1wp2, 1 << hp2, shadowColor); + Vertex(x + dx + tile1w, y + dy + h, tile1u1, v1, 1 << tile1wp2, 1 << hp2, shadowColor); } } + + // Did we need another tile? + if (hasTile2) { + // Flush to change to tile2. + EndVertexDataAndDraw(GE_PRIM_RECTANGLES); + BeginVertexData(); + WriteCmd(GE_CMD_TEXADDR0, (im.ptr & 0xFFFFF0) + 256); + WriteCmd(GE_CMD_TEXSIZE0, tile2wp2 | (hp2 << 8)); + + for (float dy = 0.0f; dy <= 2.0f; dy += 1.0f) { + for (float dx = 0.0f; dx <= 1.0f; dx += 0.5f) { + if (dx == 0.0f && dy == 0.0f) + continue; + + Vertex(x + tile2x + dx, y + dy, 0, 0, 1 << tile2wp2, 1 << hp2, shadowColor); + Vertex(x + tile2x + dx + tile2w, y + dy + h, tile2u1, v1, 1 << tile2wp2, 1 << hp2, shadowColor); + } + } + + // Return to tile1 for the text. + EndVertexDataAndDraw(GE_PRIM_RECTANGLES); + BeginVertexData(); + WriteCmd(GE_CMD_TEXADDR0, im.ptr & 0xFFFFF0); + WriteCmd(GE_CMD_TEXSIZE0, tile1wp2 | (hp2 << 8)); + } + } + + Vertex(x, y, 0, 0, 1 << tile1wp2, 1 << hp2, style.color); + Vertex(x + tile1w, y + h, tile1u1, v1, 1 << tile1wp2, 1 << hp2, style.color); + if (hasTile2) { + EndVertexDataAndDraw(GE_PRIM_RECTANGLES); + BeginVertexData(); + WriteCmd(GE_CMD_TEXADDR0, (im.ptr & 0xFFFFF0) + 256); + WriteCmd(GE_CMD_TEXSIZE0, tile2wp2 | (hp2 << 8)); + + Vertex(x + tile2x, y, 0, 0, 1 << tile2wp2, 1 << hp2, style.color); + Vertex(x + tile2x + tile2w, y + h, tile2u1, v1, 1 << tile2wp2, 1 << hp2, style.color); } - Vertex(x, y, 0, 0, 1 << wp2, 1 << hp2, style.color); - Vertex(x + w, y + h, u1, v1, 1 << wp2, 1 << hp2, style.color); EndVertexDataAndDraw(GE_PRIM_RECTANGLES); PPGeSetDefaultTexture();