Move mode 0 into macro-land so that much of the logic can be inlined

This commit is contained in:
Jeffrey Pfau 2014-01-25 14:47:21 -08:00
parent 0e379fed41
commit 408d39a297
1 changed files with 388 additions and 307 deletions

View File

@ -679,11 +679,12 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) {
renderer->bg[3].sy += renderer->bg[3].dmy; renderer->bg[3].sy += renderer->bg[3].dmy;
} }
static void _composite(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) { // We stash the priority on the top bits so we can do a one-operator comparison
// We stash the priority on the top bits so we can do a one-operator comparison // The lower the number, the higher the priority, and sprites take precendence over backgrounds
// The lower the number, the higher the priority, and sprites take precendence over backgrounds // We want to do special processing if the color pixel is target 1, however
// We want to do special processing if the color pixel is target 1, however
if (color >= current){ static inline void _compositeBlendObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) {
if (color >= current) {
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) { if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->blda, current, renderer->bldb, color); color = _mix(renderer->blda, current, renderer->bldb, color);
} else { } else {
@ -695,29 +696,71 @@ static void _composite(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixe
*pixel = color; *pixel = color;
} }
#define BACKGROUND_DRAW_PIXEL_16 \ static inline void _compositeBlendNoObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) {
// We stash the priority on the top bits so we can do a one-operator comparison
// The lower the number, the higher the priority, and sprites take precendence over backgrounds
// We want to do special processing if the color pixel is target 1, however
if (color >= current) {
if (current & FLAG_TARGET_1 && color & FLAG_TARGET_2) {
color = _mix(renderer->blda, current, renderer->bldb, color);
} else {
color = current & 0x00FFFFFF;
}
} else {
color = color & ~FLAG_TARGET_2;
}
*pixel = color;
}
static inline void _compositeNoBlendObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) {
(void) (renderer);
if (color < current) {
*pixel = color | (current & FLAG_OBJWIN);
}
}
static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixel, uint32_t color, uint32_t current) {
(void) (renderer);
if (color < current) {
*pixel = color;
}
}
#define COMPOSITE_16_OBJWIN(BLEND) \
if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) { \
unsigned color = (current & FLAG_OBJWIN) ? objwinPalette[paletteData | pixelData] : palette[pixelData]; \
_composite ## BLEND ## Objwin(renderer, pixel, color | flags, current); \
}
#define COMPOSITE_16_NO_OBJWIN(BLEND) \
_composite ## BLEND ## NoObjwin(renderer, pixel, palette[pixelData] | flags, current);
#define COMPOSITE_256_OBJWIN(BLEND) \
if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) { \
unsigned color = (current & FLAG_OBJWIN) ? objwinPalette[pixelData] : palette[pixelData]; \
_composite ## BLEND ## Objwin(renderer, pixel, color | flags, current); \
}
#define COMPOSITE_256_NO_OBJWIN(BLEND) \
COMPOSITE_16_NO_OBJWIN(BLEND)
#define COMPOSITE_16_NO_OBJWIN(BLEND) \
_composite ## BLEND ## NoObjwin(renderer, pixel, palette[pixelData] | flags, current);
#define BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN) \
pixelData = tileData & 0xF; \ pixelData = tileData & 0xF; \
current = *pixel; \ current = *pixel; \
if (pixelData && IS_WRITABLE(current)) { \ if (pixelData && IS_WRITABLE(current)) { \
if (!objwinSlowPath) { \ COMPOSITE_16_ ## OBJWIN (BLEND); \
_composite(renderer, pixel, palette[pixelData] | flags, current); \
} else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) { \
unsigned color = (current & FLAG_OBJWIN) ? objwinPalette[paletteData | pixelData] : palette[pixelData]; \
_composite(renderer, pixel, color | flags, current); \
} \
} \ } \
tileData >>= 4; tileData >>= 4;
#define BACKGROUND_DRAW_PIXEL_256 \ #define BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN) \
pixelData = tileData & 0xFF; \ pixelData = tileData & 0xFF; \
current = *pixel; \ current = *pixel; \
if (pixelData && IS_WRITABLE(current)) { \ if (pixelData && IS_WRITABLE(current)) { \
if (!objwinSlowPath) { \ COMPOSITE_256_ ## OBJWIN (BLEND); \
_composite(renderer, pixel, palette[pixelData] | flags, current); \
} else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) { \
color_t* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette; \
_composite(renderer, pixel, currentPalette[pixelData] | flags, current); \
} \
} \ } \
tileData >>= 8; tileData >>= 8;
@ -765,6 +808,303 @@ static void _composite(struct GBAVideoSoftwareRenderer* renderer, uint32_t* pixe
} \ } \
} }
#define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_16(BLEND, OBJWIN) \
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
palette = &mainPalette[paletteData]; \
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) >> 2) + localY; \
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
tileData >>= 4 * mod8; \
for (; outX < end; ++outX) { \
uint32_t* pixel = &renderer->row[outX]; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
} \
} else { \
for (outX = end - 1; outX >= renderer->start; --outX) { \
uint32_t* pixel = &renderer->row[outX]; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
} \
}
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_16(BLEND, OBJWIN) \
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) >> 2) + localY; \
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
palette = &mainPalette[paletteData]; \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
outX = renderer->end - mod8; \
if (outX < renderer->start) { \
tileData >>= 4 * (renderer->start - outX); \
outX = renderer->start; \
} \
for (; outX < renderer->end; ++outX) { \
uint32_t* pixel = &renderer->row[outX]; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
} \
} else { \
tileData >>= 4 * (0x8 - mod8); \
int end2 = renderer->end - 8; \
if (end2 < -1) { \
end2 = -1; \
} \
for (outX = renderer->end - 1; outX > end2; --outX) { \
uint32_t* pixel = &renderer->row[outX]; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
} \
}
#define DRAW_BACKGROUND_MODE_0_MOSAIC_16(BLEND, OBJWIN) \
for (; tileX < tileEnd; ++tileX) { \
BACKGROUND_TEXT_SELECT_CHARACTER; \
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) >> 2) + localY; \
tileData = carryData; \
for (x = 0; x < 8; ++x) { \
if (!mosaicWait) { \
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
palette = &mainPalette[paletteData]; \
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
tileData >>= x * 4; \
} else { \
tileData >>= (7 - x) * 4; \
} \
tileData &= 0xF; \
tileData |= tileData << 4; \
tileData |= tileData << 8; \
tileData |= tileData << 12; \
tileData |= tileData << 16; \
tileData |= tileData << 20; \
tileData |= tileData << 24; \
tileData |= tileData << 28; \
carryData = tileData; \
mosaicWait = mosaicH; \
} \
--mosaicWait; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
++pixel; \
} \
}
#define DRAW_BACKGROUND_MODE_0_TILES_16(BLEND, OBJWIN) \
for (; tileX < tileEnd; ++tileX) { \
BACKGROUND_TEXT_SELECT_CHARACTER; \
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4; \
palette = &mainPalette[paletteData]; \
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) >> 2) + localY; \
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
if (tileData) { \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
++pixel; \
} else { \
pixel += 7; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_16(BLEND, OBJWIN); \
pixel += 8; \
} \
} else { \
pixel += 8; \
} \
}
#define DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_256(BLEND, OBJWIN) \
/* TODO: hflip */ \
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) >> 2) + (localY << 1); \
int end2 = end - 4; \
int shift = inX & 0x3; \
if (end2 > 0) { \
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
tileData >>= 8 * shift; \
shift = 0; \
for (; outX < end2; ++outX) { \
uint32_t* pixel = &renderer->row[outX]; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
} \
} \
\
tileData = ((uint32_t*)renderer->d.vram)[charBase + 1]; \
tileData >>= 8 * shift; \
for (; outX < end; ++outX) { \
uint32_t* pixel = &renderer->row[outX]; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
}
#define DRAW_BACKGROUND_MODE_0_TILE_PREFIX_256(BLEND, OBJWIN) \
/* TODO: hflip */ \
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) >> 2) + (localY << 1); \
outX = renderer->end - 8 + end; \
int end2 = 4 - end; \
if (end2 > 0) { \
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
for (; outX < renderer->end - end2; ++outX) { \
uint32_t* pixel = &renderer->row[outX]; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
} \
++charBase; \
} \
\
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
for (; outX < renderer->end; ++outX) { \
uint32_t* pixel = &renderer->row[outX]; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
}
#define DRAW_BACKGROUND_MODE_0_TILES_256(BLEND, OBJWIN) \
for (; tileX < tileEnd; ++tileX) { \
BACKGROUND_TEXT_SELECT_CHARACTER; \
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) >> 2) + (localY << 1); \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
if (tileData) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
++pixel; \
} else { \
pixel += 4; \
} \
tileData = ((uint32_t*)renderer->d.vram)[charBase + 1]; \
if (tileData) { \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
++pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
++pixel; \
} else { \
pixel += 4; \
} \
} else { \
uint32_t tileData = ((uint32_t*)renderer->d.vram)[charBase + 1]; \
if (tileData) { \
pixel += 3; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
} \
pixel += 4; \
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
if (tileData) { \
pixel += 3; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
--pixel; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
} \
pixel += 4; \
} \
}
#define DRAW_BACKGROUND_MODE_0_MOSAIC_256(BLEND, OBJWIN) \
for (; tileX < tileEnd; ++tileX) { \
BACKGROUND_TEXT_SELECT_CHARACTER; \
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) >> 2) + (localY << 1); \
tileData = carryData; \
for (x = 0; x < 8; ++x) { \
if (!mosaicWait) { \
if (x >= 4) { \
tileData = ((uint32_t*)renderer->d.vram)[charBase + 1]; \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
tileData >>= (x - 4) * 8; \
} else { \
tileData >>= (7 - x) * 8; \
} \
} else { \
tileData = ((uint32_t*)renderer->d.vram)[charBase]; \
if (!GBA_TEXT_MAP_HFLIP(mapData)) { \
tileData >>= x * 8; \
} else { \
tileData >>= (3 - x) * 8; \
} \
} \
tileData &= 0xFF; \
carryData = tileData; \
mosaicWait = mosaicH; \
} \
tileData |= tileData << 8; \
--mosaicWait; \
BACKGROUND_DRAW_PIXEL_256(BLEND, OBJWIN); \
++pixel; \
} \
}
#define DRAW_BACKGROUND_MODE_0(BPP, BLEND, OBJWIN) \
if (inX & 0x7) { \
int mod8 = inX & 0x7; \
BACKGROUND_TEXT_SELECT_CHARACTER; \
\
int end = outX + 0x8 - mod8; \
if (end > renderer->end) { \
/* TODO: ensure tiles are properly aligned from this*/ \
end = renderer->end; \
} \
DRAW_BACKGROUND_MODE_0_TILE_SUFFIX_ ## BPP (BLEND, OBJWIN) \
} \
if (inX & 0x7 || (renderer->end - renderer->start) & 0x7) { \
tileX = tileEnd; \
int pixelData, paletteData; \
int mod8 = (inX + renderer->end - renderer->start) & 0x7; \
BACKGROUND_TEXT_SELECT_CHARACTER; \
\
int end = 0x8 - mod8; \
DRAW_BACKGROUND_MODE_0_TILE_PREFIX_ ## BPP (BLEND, OBJWIN) \
\
tileX = (inX & 0x7) != 0; \
outX = renderer->start + tileX * 8 - (inX & 0x7); \
} \
\
uint32_t* pixel = &renderer->row[outX]; \
if (background->mosaic) { \
int mosaicH = renderer->mosaic.bgH + 1; \
int x; \
int mosaicWait = outX % mosaicH; \
int carryData = 0; \
DRAW_BACKGROUND_MODE_0_MOSAIC_ ## BPP (BLEND, OBJWIN) \
return; \
} \
\
DRAW_BACKGROUND_MODE_0_TILES_ ## BPP (BLEND, OBJWIN)
static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y) { static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y) {
int inX = renderer->start + background->x; int inX = renderer->start + background->x;
if (background->mosaic) { if (background->mosaic) {
@ -810,291 +1150,32 @@ static void _drawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, stru
int tileX = 0; int tileX = 0;
int tileEnd = (renderer->end - renderer->start + (inX & 0x7)) >> 3; int tileEnd = (renderer->end - renderer->start + (inX & 0x7)) >> 3;
if (inX & 0x7) { if (!objwinSlowPath) {
int mod8 = inX & 0x7; if (!(flags & FLAG_TARGET_2)) {
BACKGROUND_TEXT_SELECT_CHARACTER; if (!background->multipalette) {
DRAW_BACKGROUND_MODE_0(16, NoBlend, NO_OBJWIN);
int end = outX + 0x8 - mod8;
if (end > renderer->end) {
// TODO: ensure tiles are properly aligned from this
end = renderer->end;
}
if (!background->multipalette) {
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4;
palette = &mainPalette[paletteData];
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) >> 2) + localY;
tileData = ((uint32_t*)renderer->d.vram)[charBase];
if (!GBA_TEXT_MAP_HFLIP(mapData)) {
tileData >>= 4 * mod8;
for (; outX < end; ++outX) {
uint32_t* pixel = &renderer->row[outX];
BACKGROUND_DRAW_PIXEL_16;
}
} else { } else {
for (outX = end - 1; outX >= renderer->start; --outX) { DRAW_BACKGROUND_MODE_0(256, NoBlend, NO_OBJWIN);
uint32_t* pixel = &renderer->row[outX];
BACKGROUND_DRAW_PIXEL_16;
}
} }
} else { } else {
// TODO: hflip if (!background->multipalette) {
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) >> 2) + (localY << 1); DRAW_BACKGROUND_MODE_0(16, Blend, NO_OBJWIN);
int end2 = end - 4;
int shift = inX & 0x3;
if (end2 > 0) {
tileData = ((uint32_t*)renderer->d.vram)[charBase];
tileData >>= 8 * shift;
shift = 0;
for (; outX < end2; ++outX) {
uint32_t* pixel = &renderer->row[outX];
BACKGROUND_DRAW_PIXEL_256;
}
}
tileData = ((uint32_t*)renderer->d.vram)[charBase + 1];
tileData >>= 8 * shift;
for (; outX < end; ++outX) {
uint32_t* pixel = &renderer->row[outX];
BACKGROUND_DRAW_PIXEL_256;
}
}
}
if (inX & 0x7 || (renderer->end - renderer->start) & 0x7) {
tileX = tileEnd;
int pixelData, paletteData;
int mod8 = (inX + renderer->end - renderer->start) & 0x7;
BACKGROUND_TEXT_SELECT_CHARACTER;
int end = 0x8 - mod8;
if (!background->multipalette) {
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) >> 2) + localY;
tileData = ((uint32_t*)renderer->d.vram)[charBase];
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4;
palette = &mainPalette[paletteData];
if (!GBA_TEXT_MAP_HFLIP(mapData)) {
outX = renderer->end - mod8;
if (outX < renderer->start) {
tileData >>= 4 * (renderer->start - outX);
outX = renderer->start;
}
for (; outX < renderer->end; ++outX) {
uint32_t* pixel = &renderer->row[outX];
BACKGROUND_DRAW_PIXEL_16;
}
} else { } else {
tileData >>= 4 * (0x8 - mod8); DRAW_BACKGROUND_MODE_0(256, Blend, NO_OBJWIN);
int end2 = renderer->end - 8;
if (end2 < -1) {
end2 = -1;
}
for (outX = renderer->end - 1; outX > end2; --outX) {
uint32_t* pixel = &renderer->row[outX];
BACKGROUND_DRAW_PIXEL_16;
}
}
} else {
// TODO: hflip
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) >> 2) + (localY << 1);
outX = renderer->end - 8 + end;
int end2 = 4 - end;
if (end2 > 0) {
tileData = ((uint32_t*)renderer->d.vram)[charBase];
for (; outX < renderer->end - end2; ++outX) {
uint32_t* pixel = &renderer->row[outX];
BACKGROUND_DRAW_PIXEL_256;
}
++charBase;
}
tileData = ((uint32_t*)renderer->d.vram)[charBase];
for (; outX < renderer->end; ++outX) {
uint32_t* pixel = &renderer->row[outX];
BACKGROUND_DRAW_PIXEL_256;
}
}
tileX = (inX & 0x7) != 0;
outX = renderer->start + tileX * 8 - (inX & 0x7);
}
uint32_t* pixel = &renderer->row[outX];
if (background->mosaic) {
int mosaicH = renderer->mosaic.bgH + 1;
int x;
int mosaicWait = outX % mosaicH;
int carryData = 0;
if (!background->multipalette) {
for (; tileX < tileEnd; ++tileX) {
BACKGROUND_TEXT_SELECT_CHARACTER;
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) >> 2) + localY;
tileData = carryData;
for (x = 0; x < 8; ++x) {
if (!mosaicWait) {
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4;
palette = &mainPalette[paletteData];
tileData = ((uint32_t*)renderer->d.vram)[charBase];
if (!GBA_TEXT_MAP_HFLIP(mapData)) {
tileData >>= x * 4;
} else {
tileData >>= (7 - x) * 4;
}
tileData &= 0xF;
tileData |= tileData << 4;
tileData |= tileData << 8;
tileData |= tileData << 12;
tileData |= tileData << 16;
tileData |= tileData << 20;
tileData |= tileData << 24;
tileData |= tileData << 28;
carryData = tileData;
mosaicWait = mosaicH;
}
--mosaicWait;
BACKGROUND_DRAW_PIXEL_16;
++pixel;
}
}
} else {
for (; tileX < tileEnd; ++tileX) {
BACKGROUND_TEXT_SELECT_CHARACTER;
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) >> 2) + (localY << 1);
tileData = carryData;
for (x = 0; x < 8; ++x) {
if (!mosaicWait) {
if (x >= 4) {
tileData = ((uint32_t*)renderer->d.vram)[charBase + 1];
if (!GBA_TEXT_MAP_HFLIP(mapData)) {
tileData >>= (x - 4) * 8;
} else {
tileData >>= (7 - x) * 8;
}
} else {
tileData = ((uint32_t*)renderer->d.vram)[charBase];
if (!GBA_TEXT_MAP_HFLIP(mapData)) {
tileData >>= x * 8;
} else {
tileData >>= (3 - x) * 8;
}
}
tileData &= 0xFF;
carryData = tileData;
mosaicWait = mosaicH;
}
tileData |= tileData << 8;
--mosaicWait;
BACKGROUND_DRAW_PIXEL_256;
++pixel;
}
}
}
return;
}
if (!background->multipalette) {
for (; tileX < tileEnd; ++tileX) {
BACKGROUND_TEXT_SELECT_CHARACTER;
paletteData = GBA_TEXT_MAP_PALETTE(mapData) << 4;
palette = &mainPalette[paletteData];
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 5)) >> 2) + localY;
tileData = ((uint32_t*)renderer->d.vram)[charBase];
if (tileData) {
if (!GBA_TEXT_MAP_HFLIP(mapData)) {
BACKGROUND_DRAW_PIXEL_16;
++pixel;
BACKGROUND_DRAW_PIXEL_16;
++pixel;
BACKGROUND_DRAW_PIXEL_16;
++pixel;
BACKGROUND_DRAW_PIXEL_16;
++pixel;
BACKGROUND_DRAW_PIXEL_16;
++pixel;
BACKGROUND_DRAW_PIXEL_16;
++pixel;
BACKGROUND_DRAW_PIXEL_16;
++pixel;
BACKGROUND_DRAW_PIXEL_16;
++pixel;
} else {
pixel += 7;
BACKGROUND_DRAW_PIXEL_16;
--pixel;
BACKGROUND_DRAW_PIXEL_16;
--pixel;
BACKGROUND_DRAW_PIXEL_16;
--pixel;
BACKGROUND_DRAW_PIXEL_16;
--pixel;
BACKGROUND_DRAW_PIXEL_16;
--pixel;
BACKGROUND_DRAW_PIXEL_16;
--pixel;
BACKGROUND_DRAW_PIXEL_16;
--pixel;
BACKGROUND_DRAW_PIXEL_16;
pixel += 8;
}
} else {
pixel += 8;
} }
} }
} else { } else {
for (; tileX < tileEnd; ++tileX) { if (!(flags & FLAG_TARGET_2)) {
BACKGROUND_TEXT_SELECT_CHARACTER; if (!background->multipalette) {
charBase = ((background->charBase + (GBA_TEXT_MAP_TILE(mapData) << 6)) >> 2) + (localY << 1); DRAW_BACKGROUND_MODE_0(16, NoBlend, OBJWIN);
if (!GBA_TEXT_MAP_HFLIP(mapData)) {
tileData = ((uint32_t*)renderer->d.vram)[charBase];
if (tileData) {
BACKGROUND_DRAW_PIXEL_256;
++pixel;
BACKGROUND_DRAW_PIXEL_256;
++pixel;
BACKGROUND_DRAW_PIXEL_256;
++pixel;
BACKGROUND_DRAW_PIXEL_256;
++pixel;
} else {
pixel += 4;
}
tileData = ((uint32_t*)renderer->d.vram)[charBase + 1];
if (tileData) {
BACKGROUND_DRAW_PIXEL_256;
++pixel;
BACKGROUND_DRAW_PIXEL_256;
++pixel;
BACKGROUND_DRAW_PIXEL_256;
++pixel;
BACKGROUND_DRAW_PIXEL_256;
++pixel;
} else {
pixel += 4;
}
} else { } else {
uint32_t tileData = ((uint32_t*)renderer->d.vram)[charBase + 1]; DRAW_BACKGROUND_MODE_0(256, NoBlend, OBJWIN);
if (tileData) { }
pixel += 3; } else {
BACKGROUND_DRAW_PIXEL_256; if (!background->multipalette) {
--pixel; DRAW_BACKGROUND_MODE_0(16, Blend, OBJWIN);
BACKGROUND_DRAW_PIXEL_256; } else {
--pixel; DRAW_BACKGROUND_MODE_0(256, Blend, OBJWIN);
BACKGROUND_DRAW_PIXEL_256;
--pixel;
BACKGROUND_DRAW_PIXEL_256;
}
pixel += 4;
tileData = ((uint32_t*)renderer->d.vram)[charBase];
if (tileData) {
pixel += 3;
BACKGROUND_DRAW_PIXEL_256;
--pixel;
BACKGROUND_DRAW_PIXEL_256;
--pixel;
BACKGROUND_DRAW_PIXEL_256;
--pixel;
BACKGROUND_DRAW_PIXEL_256;
}
pixel += 4;
} }
} }
} }
@ -1159,10 +1240,10 @@ static void _drawBackgroundMode2(struct GBAVideoSoftwareRenderer* renderer, stru
uint32_t current = *pixel; uint32_t current = *pixel;
if (tileData && IS_WRITABLE(current)) { if (tileData && IS_WRITABLE(current)) {
if (!objwinSlowPath) { if (!objwinSlowPath) {
_composite(renderer, pixel, palette[tileData] | flags, current); _compositeBlendNoObjwin(renderer, pixel, palette[tileData] | flags, current);
} else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) { } else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) {
color_t* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette; color_t* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette;
_composite(renderer, pixel, currentPalette[tileData] | flags, current); _compositeBlendObjwin(renderer, pixel, currentPalette[tileData] | flags, current);
} }
} }
} }
@ -1191,11 +1272,11 @@ static void _drawBackgroundMode3(struct GBAVideoSoftwareRenderer* renderer, stru
uint32_t current = *pixel; uint32_t current = *pixel;
if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) { if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) {
if (!variant) { if (!variant) {
_composite(renderer, pixel, color | flags, current); _compositeBlendObjwin(renderer, pixel, color | flags, current);
} else if (renderer->blendEffect == BLEND_BRIGHTEN) { } else if (renderer->blendEffect == BLEND_BRIGHTEN) {
_composite(renderer, pixel, _brighten(color, renderer->bldy) | flags, current); _compositeBlendObjwin(renderer, pixel, _brighten(color, renderer->bldy) | flags, current);
} else if (renderer->blendEffect == BLEND_DARKEN) { } else if (renderer->blendEffect == BLEND_DARKEN) {
_composite(renderer, pixel, _darken(color, renderer->bldy) | flags, current); _compositeBlendObjwin(renderer, pixel, _darken(color, renderer->bldy) | flags, current);
} }
} }
} }
@ -1220,10 +1301,10 @@ static void _drawBackgroundMode4(struct GBAVideoSoftwareRenderer* renderer, stru
uint32_t current = *pixel; uint32_t current = *pixel;
if (color && IS_WRITABLE(current)) { if (color && IS_WRITABLE(current)) {
if (!objwinSlowPath) { if (!objwinSlowPath) {
_composite(renderer, pixel, palette[color] | flags, current); _compositeBlendNoObjwin(renderer, pixel, palette[color] | flags, current);
} else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) { } else if (objwinForceEnable || !(current & FLAG_OBJWIN) == objwinOnly) {
color_t* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette; color_t* currentPalette = (current & FLAG_OBJWIN) ? objwinPalette : palette;
_composite(renderer, pixel, currentPalette[color] | flags, current); _compositeBlendObjwin(renderer, pixel, currentPalette[color] | flags, current);
} }
} }
} }
@ -1255,11 +1336,11 @@ static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, stru
uint32_t current = *pixel; uint32_t current = *pixel;
if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) { if (!objwinSlowPath || !(current & FLAG_OBJWIN) != objwinOnly) {
if (!variant) { if (!variant) {
_composite(renderer, pixel, color | flags, current); _compositeBlendObjwin(renderer, pixel, color | flags, current);
} else if (renderer->blendEffect == BLEND_BRIGHTEN) { } else if (renderer->blendEffect == BLEND_BRIGHTEN) {
_composite(renderer, pixel, _brighten(color, renderer->bldy) | flags, current); _compositeBlendObjwin(renderer, pixel, _brighten(color, renderer->bldy) | flags, current);
} else if (renderer->blendEffect == BLEND_DARKEN) { } else if (renderer->blendEffect == BLEND_DARKEN) {
_composite(renderer, pixel, _darken(color, renderer->bldy) | flags, current); _compositeBlendObjwin(renderer, pixel, _darken(color, renderer->bldy) | flags, current);
} }
} }
} }
@ -1460,7 +1541,7 @@ static void _postprocessSprite(struct GBAVideoSoftwareRenderer* renderer, unsign
uint32_t color = renderer->spriteLayer[x] & ~FLAG_OBJWIN; uint32_t color = renderer->spriteLayer[x] & ~FLAG_OBJWIN;
uint32_t current = *pixel; uint32_t current = *pixel;
if ((color & FLAG_UNWRITTEN) != FLAG_UNWRITTEN && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority) { if ((color & FLAG_UNWRITTEN) != FLAG_UNWRITTEN && (color & FLAG_PRIORITY) >> OFFSET_PRIORITY == priority) {
_composite(renderer, pixel, color | flags, current); _compositeBlendObjwin(renderer, pixel, color | flags, current);
} }
} }
} }