///////////////////////////////////////////////////////////////////////////////
// GPU Sprites innerloops generator
+typedef struct spriteDriverArg {
+ const le16_t *CBA;
+ u32 u0, v0, u0_mask, v0_mask;
+ s32 y0, y1, li;
+} spriteDriverArg;
+
+typedef void (*PS)(le16_t *pPixel, u32 count, const u8 *pTxt,
+ const spriteDriverArg *arg);
template<int CF>
-static void gpuSpriteSpanFn(le16_t *pDst, u32 count, u8* pTxt, u32 u0)
+static void gpuSpriteDriverFn(le16_t *pPixel, u32 count, const u8 *pTxt_base,
+ const spriteDriverArg *arg)
{
// Blend func can save an operation if it knows uSrc MSB is unset.
// Untextured prims can always skip (source color always comes with MSB=0).
uint_fast16_t uSrc, uDst, srcMSB;
bool should_blend;
- u32 u0_mask = gpu_unai.TextureWindow[2];
+ u32 u0_mask = arg->u0_mask;
u8 r5, g5, b5;
if (CF_LIGHT) {
u0_mask <<= 1;
}
- const le16_t *CBA_; if (CF_TEXTMODE!=3) CBA_ = gpu_unai.CBA;
+ const le16_t *CBA_; if (CF_TEXTMODE!=3) CBA_ = arg->CBA;
+ const u32 v0_mask = arg->v0_mask;
+ s32 y0 = arg->y0, y1 = arg->y1, li = arg->li;
+ u32 u0_ = arg->u0, v0 = arg->v0;
- do
+ for (; y0 < y1; ++y0, pPixel += FRAME_WIDTH, ++v0)
{
+ if (y0 & li) continue;
+ const u8 *pTxt = pTxt_base + ((v0 & v0_mask) * 2048);
+ le16_t *pDst = pPixel;
+ u32 u0 = u0_;
+ u32 count1 = count;
+ do
+ {
if (CF_MASKCHECK || CF_BLEND) { uDst = le16_to_u16(*pDst); }
if (CF_MASKCHECK) if (uDst&0x8000) { goto endsprite; }
endsprite:
u0 += (CF_TEXTMODE==3) ? 2 : 1;
pDst++;
+ }
+ while (--count1);
}
- while (--count);
}
-static void SpriteNULL(le16_t *pDst, u32 count, u8* pTxt, u32 u0)
+static void SpriteNULL(le16_t *pPixel, u32 count, const u8 *pTxt_base,
+ const spriteDriverArg *arg)
{
#ifdef ENABLE_GPU_LOG_SUPPORT
fprintf(stdout,"SpriteNULL()\n");
///////////////////////////////////////////////////////////////////////////////
// Sprite innerloops driver
-typedef void (*PS)(le16_t *pDst, u32 count, u8* pTxt, u32 u0);
// Template instantiation helper macros
-#define TI(cf) gpuSpriteSpanFn<(cf)>
+#define TI(cf) gpuSpriteDriverFn<(cf)>
#define TN SpriteNULL
#define TIBLOCK(ub) \
TN, TN, TN, TN, TN, TN, TN, TN, \
TN, TN, TI((ub)|0x72), TI((ub)|0x73), TN, TN, TI((ub)|0x76), TI((ub)|0x77), \
TN, TN, TI((ub)|0x7a), TI((ub)|0x7b), TN, TN, TI((ub)|0x7e), TI((ub)|0x7f)
-const PS gpuSpriteSpanDrivers[256] = {
+const PS gpuSpriteDrivers[256] = {
TIBLOCK(0<<8), TIBLOCK(1<<8)
};
///////////////////////////////////////////////////////////////////////////////
// GPU internal sprite drawing functions
-void gpuDrawS(PtrUnion packet, const PS gpuSpriteSpanDriver, s32 *w_out, s32 *h_out)
+void gpuDrawS(PtrUnion packet, const PS gpuSpriteDriver, s32 *w_out, s32 *h_out)
{
s32 x0, x1, y0, y1;
u32 u0, v0;
le16_t *Pixel = &gpu_unai.vram[FRAME_OFFSET(x0, y0)];
const int li=gpu_unai.ilace_mask;
- const int pi=(ProgressiveInterlaceEnabled()?(gpu_unai.ilace_mask+1):0);
- const int pif=(ProgressiveInterlaceEnabled()?(gpu_unai.prog_ilace_flag?(gpu_unai.ilace_mask+1):0):1);
+ //const int pi=(ProgressiveInterlaceEnabled()?(gpu_unai.ilace_mask+1):0);
+ //const int pif=(ProgressiveInterlaceEnabled()?(gpu_unai.prog_ilace_flag?(gpu_unai.ilace_mask+1):0):1);
unsigned int tmode = gpu_unai.TEXT_MODE >> 5;
- const u32 v0_mask = gpu_unai.TextureWindow[3];
u8* pTxt_base = (u8*)gpu_unai.TBA;
// Texture is accessed byte-wise, so adjust idx if 16bpp
if (tmode == 3) u0 <<= 1;
- for (; y0<y1; ++y0) {
- u8* pTxt = pTxt_base + ((v0 & v0_mask) * 2048);
- if (!(y0&li) && (y0&pi)!=pif)
- gpuSpriteSpanDriver(Pixel, x1, pTxt, u0);
- Pixel += FRAME_WIDTH;
- v0++;
- }
+ spriteDriverArg arg;
+ arg.CBA = gpu_unai.CBA;
+ arg.u0 = u0;
+ arg.v0 = v0;
+ arg.u0_mask = gpu_unai.TextureWindow[2];
+ arg.v0_mask = gpu_unai.TextureWindow[3];
+ arg.y0 = y0;
+ arg.y1 = y1;
+ arg.li = li;
+ gpuSpriteDriver(Pixel, x1, pTxt_base, &arg);
}
#ifdef __arm__
// Strip lower 3 bits of each color and determine if lighting should be used:
if ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
driver_idx |= Lighting;
- PS driver = gpuSpriteSpanDrivers[driver_idx];
+ PS driver = gpuSpriteDrivers[driver_idx];
gpuDrawS(packet, driver, &w, &h);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(w, h));
} break;
// Strip lower 3 bits of each color and determine if lighting should be used:
if ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
driver_idx |= Lighting;
- PS driver = gpuSpriteSpanDrivers[driver_idx];
+ PS driver = gpuSpriteDrivers[driver_idx];
gpuDrawS(packet, driver, &w, &h);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(w, h));
} break;
// Strip lower 3 bits of each color and determine if lighting should be used:
if ((le32_raw(gpu_unai.PacketBuffer.U4[0]) & HTOLE32(0xF8F8F8)) != HTOLE32(0x808080))
driver_idx |= Lighting;
- PS driver = gpuSpriteSpanDrivers[driver_idx];
+ PS driver = gpuSpriteDrivers[driver_idx];
gpuDrawS(packet, driver, &w, &h);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(w, h));
} break;