all repos — mgba @ 2781a2a9f951b39ff89e47d0d13106918e1316c3

mGBA Game Boy Advance Emulator

GBA Video: Implement sprite mosaic on transformed sprites
Vicki Pfau vi@endrift.com
Tue, 21 May 2019 15:32:20 -0700
commit

2781a2a9f951b39ff89e47d0d13106918e1316c3

parent

6c1bc5548cf61da25f1fc70fe961fbbadff2b714

4 files changed, 46 insertions(+), 2 deletions(-)

jump to
M CHANGESCHANGES

@@ -27,6 +27,7 @@ - GBA: Fix RTC on non-standard sized ROMs (fixes mgba.io/i/1400)

- GBA Memory: Prevent writing to mirrored BG VRAM (fixes mgba.io/i/743) - GBA Video: Fix sprite mosaic clamping (fixes mgba.io/i/1008) - GB: Fix HALT when IE and IF unused bits are set (fixes mgba.io/i/1349) + - GBA Video: Implement mosaic on transformed sprites (fixes mgba.io/b/9) Other fixes: - Qt: More app metadata fixes - Qt: Fix load recent from archive (fixes mgba.io/i/1325)
M README.mdREADME.md

@@ -215,7 +215,6 @@

<a name="missing">[1]</a> Currently missing features are - OBJ window for modes 3, 4 and 5 ([Bug #5](http://mgba.io/b/5)) -- Mosaic for transformed OBJs ([Bug #9](http://mgba.io/b/9)) <a name="flashdetect">[2]</a> Flash memory size detection does not work in some cases. These can be configured at runtime, but filing a bug is recommended if such a case is encountered.
M README_DE.mdREADME_DE.md

@@ -215,7 +215,6 @@

<a name="missing">[1]</a> Zurzeit fehlende Features sind - OBJ-Fenster für die Modi 3, 4 und 5 ([Bug #5](http://mgba.io/b/5)) -- Mosaik-Effekt für umgewandelte OBJs ([Bug #9](http://mgba.io/b/9)) <a name="flashdetect">[2]</a> In manchen Fällen ist es nicht möglich, die Größe des Flash-Speichers automatisch zu ermitteln. Diese kann dann zur Laufzeit konfiguriert werden, es wird jedoch empfohlen, den Fehler zu melden.
M src/gba/renderers/software-obj.csrc/gba/renderers/software-obj.c

@@ -48,6 +48,31 @@ SPRITE_XBASE_ ## DEPTH(localX); \

SPRITE_DRAW_PIXEL_ ## DEPTH ## _ ## TYPE(localX); \ } +#define SPRITE_TRANSFORMED_MOSAIC_LOOP(DEPTH, TYPE) \ + unsigned tileData; \ + unsigned widthMask = ~(width - 1); \ + unsigned heightMask = ~(height - 1); \ + int localX = xAccum >> 8; \ + int localY = yAccum >> 8; \ + for (; outX < condition; ++outX, ++inX) { \ + renderer->spriteCyclesRemaining -= 2; \ + xAccum += mat.a; \ + yAccum += mat.c; \ + \ + if (outX % mosaicH == 0) { \ + localX = xAccum >> 8; \ + localY = yAccum >> 8; \ + } \ + \ + if (localX & widthMask || localY & heightMask) { \ + continue; \ + } \ + \ + SPRITE_YBASE_ ## DEPTH(localY); \ + SPRITE_XBASE_ ## DEPTH(localX); \ + SPRITE_DRAW_PIXEL_ ## DEPTH ## _ ## TYPE(localX); \ + } + #define SPRITE_XBASE_16(localX) unsigned xBase = (localX & ~0x7) * 4 + ((localX >> 1) & 2); #define SPRITE_YBASE_16(localY) unsigned yBase = (localY & ~0x7) * stride + (localY & 0x7) * 4;

@@ -173,6 +198,13 @@ int inX = outX - x;

if (end < condition) { condition = end; } + int mosaicH = 1; + if (GBAObjAttributesAIsMosaic(sprite->a)) { + mosaicH = GBAMosaicControlGetObjH(renderer->mosaic) + 1; + if (condition % mosaicH) { + condition += mosaicH - (condition % mosaicH); + } + } int xAccum = mat.a * (inX - 1 - (totalWidth >> 1)) + mat.b * (inY - (totalHeight >> 1)) + (width << 7); int yAccum = mat.c * (inX - 1 - (totalWidth >> 1)) + mat.d * (inY - (totalHeight >> 1)) + (height << 7);

@@ -223,6 +255,13 @@ if (!GBAObjAttributesAIs256Color(sprite->a)) {

palette = &palette[GBAObjAttributesCGetPalette(sprite->c) << 4]; if (flags & FLAG_OBJWIN) { SPRITE_TRANSFORMED_LOOP(16, OBJWIN); + } else if (mosaicH > 1) { + if (objwinSlowPath) { + objwinPalette = &objwinPalette[GBAObjAttributesCGetPalette(sprite->c) << 4]; + SPRITE_TRANSFORMED_MOSAIC_LOOP(16, NORMAL_OBJWIN); + } else { + SPRITE_TRANSFORMED_MOSAIC_LOOP(16, NORMAL); + } } else if (objwinSlowPath) { objwinPalette = &objwinPalette[GBAObjAttributesCGetPalette(sprite->c) << 4]; SPRITE_TRANSFORMED_LOOP(16, NORMAL_OBJWIN);

@@ -232,6 +271,12 @@ }

} else { if (flags & FLAG_OBJWIN) { SPRITE_TRANSFORMED_LOOP(256, OBJWIN); + } else if (mosaicH > 1) { + if (objwinSlowPath) { + SPRITE_TRANSFORMED_MOSAIC_LOOP(256, NORMAL_OBJWIN); + } else { + SPRITE_TRANSFORMED_MOSAIC_LOOP(256, NORMAL); + } } else if (objwinSlowPath) { SPRITE_TRANSFORMED_LOOP(256, NORMAL_OBJWIN); } else {