From 516143b170059dcb24fcb28714a7eae4cce5db1e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 12 Apr 2017 21:07:39 -0700 Subject: [PATCH] DS GX: Allow viewport to change in the middle of a frame --- CHANGES | 1 + include/mgba/internal/ds/gx.h | 10 +++++----- src/ds/gx.c | 8 ++++---- src/ds/gx/software.c | 12 ++++++------ 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CHANGES b/CHANGES index ceeefbbfd..bf32459d7 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,7 @@ Bugfixes: - DS Video: Fix affine transformations in video capture - DS GX: Fix bitmap textures when no palette is mapped (fixes mgba.io/i/628) - DS GX: Don't reset state between buffer swaps (fixes mgba.io/i/642) + - DS GX: Allow viewport to change in the middle of a frame Misc: - DS: Set boot complete bit in RAM on boot (fixes mgba.io/i/576, mgba.io/i/580, mgba.io/i/586) - DS Memory: Ensure DS9 I/O is 8-byte aligned diff --git a/include/mgba/internal/ds/gx.h b/include/mgba/internal/ds/gx.h index c3eff83cc..fc745a2f0 100644 --- a/include/mgba/internal/ds/gx.h +++ b/include/mgba/internal/ds/gx.h @@ -120,6 +120,11 @@ struct DSGXVertex { int32_t viewCoord[4]; int16_t vs; // 12.4 int16_t vt; // 12.4 + + int viewportX; + int viewportY; + int viewportWidth; + int viewportHeight; }; struct DSGXPolygon { @@ -143,11 +148,6 @@ struct DSGXRenderer { uint16_t* tex[4]; uint16_t* texPal[6]; - - int viewportX; - int viewportY; - int viewportWidth; - int viewportHeight; }; struct DSGXLight { diff --git a/src/ds/gx.c b/src/ds/gx.c index 4b5caf2c5..e30cd7c7f 100644 --- a/src/ds/gx.c +++ b/src/ds/gx.c @@ -1180,10 +1180,10 @@ static void _fifoRun(struct mTiming* timing, void* context, uint32_t cyclesLate) gx->viewportY2 = (uint8_t) entry.params[3]; gx->viewportWidth = gx->viewportX2 - gx->viewportX1 + 1; gx->viewportHeight = gx->viewportY2 - gx->viewportY1 + 1; - gx->renderer->viewportX = gx->viewportX1; - gx->renderer->viewportY = gx->viewportY1; - gx->renderer->viewportWidth = gx->viewportWidth; - gx->renderer->viewportHeight = gx->viewportHeight; + gx->currentVertex.viewportX = gx->viewportX1; + gx->currentVertex.viewportY = gx->viewportY1; + gx->currentVertex.viewportWidth = gx->viewportWidth; + gx->currentVertex.viewportHeight = gx->viewportHeight; break; case DS_GX_CMD_BOX_TEST: gxstat = DSRegGXSTATClearTestBusy(gxstat); diff --git a/src/ds/gx/software.c b/src/ds/gx/software.c index 653b3f3eb..d8cedf97b 100644 --- a/src/ds/gx/software.c +++ b/src/ds/gx/software.c @@ -487,8 +487,8 @@ static void _preparePoly(struct DSGXRenderer* renderer, struct DSGXVertex* verts v0w = 1; } - int32_t v0x = (v0->viewCoord[0] + v0w) * (int64_t) (renderer->viewportWidth << 12) / (v0w * 2) + (renderer->viewportX << 12); - int32_t v0y = (-v0->viewCoord[1] + v0w) * (int64_t) (renderer->viewportHeight << 12) / (v0w * 2) + (renderer->viewportY << 12); + int32_t v0x = (v0->viewCoord[0] + v0w) * (int64_t) (v0->viewportWidth << 12) / (v0w * 2) + (v0->viewportX << 12); + int32_t v0y = (-v0->viewCoord[1] + v0w) * (int64_t) (v0->viewportHeight << 12) / (v0w * 2) + (v0->viewportY << 12); if (poly->minY > v0y >> 12) { poly->minY = v0y >> 12; } @@ -504,8 +504,8 @@ static void _preparePoly(struct DSGXRenderer* renderer, struct DSGXVertex* verts if (!v1w) { v1w = 1; } - int32_t v1x = (v1->viewCoord[0] + v1w) * (int64_t) (renderer->viewportWidth << 12) / (v1w * 2) + (renderer->viewportX << 12); - int32_t v1y = (-v1->viewCoord[1] + v1w) * (int64_t) (renderer->viewportHeight << 12) / (v1w * 2) + (renderer->viewportY << 12); + int32_t v1x = (v1->viewCoord[0] + v1w) * (int64_t) (v1->viewportWidth << 12) / (v1w * 2) + (v1->viewportX << 12); + int32_t v1y = (-v1->viewCoord[1] + v1w) * (int64_t) (v1->viewportHeight << 12) / (v1w * 2) + (v1->viewportY << 12); if (poly->minY > v1y >> 12) { poly->minY = v1y >> 12; } @@ -563,8 +563,8 @@ static void _preparePoly(struct DSGXRenderer* renderer, struct DSGXVertex* verts if (!v1w) { v1w = 1; } - int32_t v1x = (v1->viewCoord[0] + v1w) * (int64_t) (renderer->viewportWidth << 12) / (v1w * 2) + (renderer->viewportX << 12); - int32_t v1y = (-v1->viewCoord[1] + v1w) * (int64_t) (renderer->viewportHeight << 12) / (v1w * 2) + (renderer->viewportY << 12); + int32_t v1x = (v1->viewCoord[0] + v1w) * (int64_t) (v1->viewportWidth << 12) / (v1w * 2) + (v1->viewportX << 12); + int32_t v1y = (-v1->viewCoord[1] + v1w) * (int64_t) (v1->viewportHeight << 12) / (v1w * 2) + (v1->viewportY << 12); if (poly->minY > v1y >> 12) { poly->minY = v1y >> 12;