mirror of https://github.com/mgba-emu/mgba.git
GBA Video: Simplify sprite cycle counting (fixes #1279)
This commit is contained in:
parent
d61d9ef6a6
commit
031049cd06
1
CHANGES
1
CHANGES
|
@ -27,6 +27,7 @@ Emulation fixes:
|
||||||
- GBA Video: Fix disabling OBJWIN in GL renderer (fixes mgba.io/i/1759)
|
- GBA Video: Fix disabling OBJWIN in GL renderer (fixes mgba.io/i/1759)
|
||||||
- GBA Video: Add missing parts of 256-color mode 0 mosaic (fixes mgba.io/i/1701)
|
- GBA Video: Add missing parts of 256-color mode 0 mosaic (fixes mgba.io/i/1701)
|
||||||
- GBA Video: Fix double-size OBJ wrapping in GL renderer (fixes mgba.io/i/1712)
|
- GBA Video: Fix double-size OBJ wrapping in GL renderer (fixes mgba.io/i/1712)
|
||||||
|
- GBA Video: Simplify sprite cycle counting (fixes mgba.io/i/1279)
|
||||||
- SM83: Emulate HALT bug
|
- SM83: Emulate HALT bug
|
||||||
Other fixes:
|
Other fixes:
|
||||||
- 3DS: Fix framelimiter on newer citro3d (fixes mgba.io/i/1771)
|
- 3DS: Fix framelimiter on newer citro3d (fixes mgba.io/i/1771)
|
||||||
|
|
|
@ -16,6 +16,7 @@ struct GBAVideoRendererSprite {
|
||||||
struct GBAObj obj;
|
struct GBAObj obj;
|
||||||
int16_t y;
|
int16_t y;
|
||||||
int16_t endY;
|
int16_t endY;
|
||||||
|
int16_t cycles;
|
||||||
int8_t index;
|
int8_t index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,19 @@ int GBAVideoRendererCleanOAM(struct GBAObj* oam, struct GBAVideoRendererSprite*
|
||||||
LOAD_16LE(obj.b, 0, &oam[i].b);
|
LOAD_16LE(obj.b, 0, &oam[i].b);
|
||||||
LOAD_16LE(obj.c, 0, &oam[i].c);
|
LOAD_16LE(obj.c, 0, &oam[i].c);
|
||||||
if (GBAObjAttributesAIsTransformed(obj.a) || !GBAObjAttributesAIsDisable(obj.a)) {
|
if (GBAObjAttributesAIsTransformed(obj.a) || !GBAObjAttributesAIsDisable(obj.a)) {
|
||||||
|
int width = GBAVideoObjSizes[GBAObjAttributesAGetShape(obj.a) * 4 + GBAObjAttributesBGetSize(obj.b)][0];
|
||||||
int height = GBAVideoObjSizes[GBAObjAttributesAGetShape(obj.a) * 4 + GBAObjAttributesBGetSize(obj.b)][1];
|
int height = GBAVideoObjSizes[GBAObjAttributesAGetShape(obj.a) * 4 + GBAObjAttributesBGetSize(obj.b)][1];
|
||||||
|
int cycles = width;
|
||||||
if (GBAObjAttributesAIsTransformed(obj.a)) {
|
if (GBAObjAttributesAIsTransformed(obj.a)) {
|
||||||
height <<= GBAObjAttributesAGetDoubleSize(obj.a);
|
height <<= GBAObjAttributesAGetDoubleSize(obj.a);
|
||||||
|
width <<= GBAObjAttributesAGetDoubleSize(obj.a);
|
||||||
|
cycles = 10 + width * 2;
|
||||||
}
|
}
|
||||||
if (GBAObjAttributesAGetY(obj.a) < GBA_VIDEO_VERTICAL_PIXELS || GBAObjAttributesAGetY(obj.a) + height >= VIDEO_VERTICAL_TOTAL_PIXELS) {
|
if (GBAObjAttributesAGetY(obj.a) < GBA_VIDEO_VERTICAL_PIXELS || GBAObjAttributesAGetY(obj.a) + height >= VIDEO_VERTICAL_TOTAL_PIXELS) {
|
||||||
int y = GBAObjAttributesAGetY(obj.a) + offsetY;
|
int y = GBAObjAttributesAGetY(obj.a) + offsetY;
|
||||||
sprites[oamMax].y = y;
|
sprites[oamMax].y = y;
|
||||||
sprites[oamMax].endY = y + height;
|
sprites[oamMax].endY = y + height;
|
||||||
|
sprites[oamMax].cycles = cycles;
|
||||||
sprites[oamMax].obj = obj;
|
sprites[oamMax].obj = obj;
|
||||||
sprites[oamMax].index = i;
|
sprites[oamMax].index = i;
|
||||||
++oamMax;
|
++oamMax;
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
SPRITE_YBASE_ ## DEPTH(inY); \
|
SPRITE_YBASE_ ## DEPTH(inY); \
|
||||||
unsigned tileData; \
|
unsigned tileData; \
|
||||||
for (; outX < condition; ++outX, inX += xOffset) { \
|
for (; outX < condition; ++outX, inX += xOffset) { \
|
||||||
renderer->spriteCyclesRemaining -= 1; \
|
|
||||||
SPRITE_XBASE_ ## DEPTH(inX); \
|
SPRITE_XBASE_ ## DEPTH(inX); \
|
||||||
SPRITE_DRAW_PIXEL_ ## DEPTH ## _ ## TYPE(inX); \
|
SPRITE_DRAW_PIXEL_ ## DEPTH ## _ ## TYPE(inX); \
|
||||||
}
|
}
|
||||||
|
@ -33,7 +32,6 @@
|
||||||
unsigned widthMask = ~(width - 1); \
|
unsigned widthMask = ~(width - 1); \
|
||||||
unsigned heightMask = ~(height - 1); \
|
unsigned heightMask = ~(height - 1); \
|
||||||
for (; outX < condition; ++outX, ++inX) { \
|
for (; outX < condition; ++outX, ++inX) { \
|
||||||
renderer->spriteCyclesRemaining -= 2; \
|
|
||||||
xAccum += mat.a; \
|
xAccum += mat.a; \
|
||||||
yAccum += mat.c; \
|
yAccum += mat.c; \
|
||||||
int localX = xAccum >> 8; \
|
int localX = xAccum >> 8; \
|
||||||
|
@ -55,7 +53,6 @@
|
||||||
int localX = xAccum >> 8; \
|
int localX = xAccum >> 8; \
|
||||||
int localY = yAccum >> 8; \
|
int localY = yAccum >> 8; \
|
||||||
for (; outX < condition; ++outX, ++inX) { \
|
for (; outX < condition; ++outX, ++inX) { \
|
||||||
renderer->spriteCyclesRemaining -= 2; \
|
|
||||||
xAccum += mat.a; \
|
xAccum += mat.a; \
|
||||||
yAccum += mat.c; \
|
yAccum += mat.c; \
|
||||||
\
|
\
|
||||||
|
@ -272,7 +269,6 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
||||||
if (outX < start || outX >= condition) {
|
if (outX < start || outX >= condition) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
renderer->spriteCyclesRemaining -= 10;
|
|
||||||
|
|
||||||
if (!GBAObjAttributesAIs256Color(sprite->a)) {
|
if (!GBAObjAttributesAIs256Color(sprite->a)) {
|
||||||
palette = &palette[GBAObjAttributesCGetPalette(sprite->c) << 4];
|
palette = &palette[GBAObjAttributesCGetPalette(sprite->c) << 4];
|
||||||
|
@ -306,9 +302,6 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
||||||
SPRITE_TRANSFORMED_LOOP(256, NORMAL);
|
SPRITE_TRANSFORMED_LOOP(256, NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (end == GBA_VIDEO_HORIZONTAL_PIXELS && x + totalWidth > GBA_VIDEO_HORIZONTAL_PIXELS) {
|
|
||||||
renderer->spriteCyclesRemaining -= (x + totalWidth - GBA_VIDEO_HORIZONTAL_PIXELS) * 2;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
int outX = x >= start ? x : start;
|
int outX = x >= start ? x : start;
|
||||||
int condition = x + width;
|
int condition = x + width;
|
||||||
|
@ -366,9 +359,6 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
||||||
SPRITE_NORMAL_LOOP(256, NORMAL);
|
SPRITE_NORMAL_LOOP(256, NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (end == GBA_VIDEO_HORIZONTAL_PIXELS && x + width > GBA_VIDEO_HORIZONTAL_PIXELS) {
|
|
||||||
renderer->spriteCyclesRemaining -= x + width - GBA_VIDEO_HORIZONTAL_PIXELS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -845,12 +845,10 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (w = 0; w < renderer->nWindows; ++w) {
|
for (w = 0; w < renderer->nWindows; ++w) {
|
||||||
if (renderer->spriteCyclesRemaining <= 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
renderer->currentWindow = renderer->windows[w].control;
|
renderer->currentWindow = renderer->windows[w].control;
|
||||||
renderer->start = renderer->end;
|
renderer->start = renderer->end;
|
||||||
renderer->end = renderer->windows[w].endX;
|
renderer->end = renderer->windows[w].endX;
|
||||||
|
// TODO: partial sprite drawing
|
||||||
if (!GBAWindowControlIsObjEnable(renderer->currentWindow.packed) && !GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt)) {
|
if (!GBAWindowControlIsObjEnable(renderer->currentWindow.packed) && !GBARegisterDISPCNTIsObjwinEnable(renderer->dispcnt)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -858,6 +856,7 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
|
||||||
int drawn = GBAVideoSoftwareRendererPreprocessSprite(renderer, &sprite->obj, sprite->index, localY);
|
int drawn = GBAVideoSoftwareRendererPreprocessSprite(renderer, &sprite->obj, sprite->index, localY);
|
||||||
spriteLayers |= drawn << GBAObjAttributesCGetPriority(sprite->obj.c);
|
spriteLayers |= drawn << GBAObjAttributesCGetPriority(sprite->obj.c);
|
||||||
}
|
}
|
||||||
|
renderer->spriteCyclesRemaining -= sprite->cycles;
|
||||||
if (renderer->spriteCyclesRemaining <= 0) {
|
if (renderer->spriteCyclesRemaining <= 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue